[Zeppelin-635] AngularJS utilities functions and Hide/Show ParagraphId feature#678
[Zeppelin-635] AngularJS utilities functions and Hide/Show ParagraphId feature#678doanduyhai wants to merge 10 commits into
Conversation
|
CI build is green |
…aragraph scope, then note scope and then global scope, in this order
701cbfa to
bf3f894
Compare
bf3f894 to
80e1c27
Compare
|
@doanduyhai Thanks for great work.
This is the first time exposing Zeppelin provided javascript function to user. How about we make them little bit different from other functions defined in the scope. For example instead of collect all exposed function into I this way, both user/developer can explicitly recognize which is exposed function to user. What do you think?
Once angularObject is created (binded), no matter who (front-end / back-end) creates, every change of binded scope variable automatically pushed to server. And this function give user access to any scope of AngularObjectRegistry of any Interpreter process. to So user's javascript code only able to access current paragraph or notebook scope of AngularObject in the current interpreter process.
And do you mind making separate PR for change regarding dynamic form? |
|
Thanks @Leemoonsoo for you initial remarks.
I think I did not define clearly the objectives of this PR so let me explain it again: Functional requirements: As a Zeppelin user, I would like to design an HTML form which:
%sql
SELECT * FROM table WHERE name = ${name}Current Zeppelin dynamic forms can be enhanced to support points 2. and 5. but I think it's very hard (unless we redesign it from scratch) to support all other points. And I want to have a very flexible form system so I need to design my HTML form in another paragraph with %angular That's the main reason I want to be able to override dynamic forms system if a variable is already present in the AngularObjectRegistry (whether it was bound by a zeppelin context or by an AngularJS function client-side, it doesn't matter). Currently to achieve the same goal, you need to use the
Totally agree, I would propose to split this PR in smaller ones like:
+1 Good idea
+1. I will rename to
There are serious reasons for the current design. Right now, the current scope of the AngularObjectRegistry are, in descending order:
If we want to bind an angular object to a particular paragraph, the noteId is not necessary because we always choose the id from the current note (and it is not possible to change it to enforce note scope isolation). However, because of point 1. above, we need to provide also the interpreter group (so the interpreter name) of the paragraph otherwise we won't be able to retrieve the AngularObjectRegistry at the server-side. The below piece of code does this job: final InterpreterGroup interpreterGroup = findGroupForInterpreter(noteId, note.getNoteReplLoader().getInterpreterSettings(), interpreterName);
final AngularObjectRegistry registry = interpreterGroup.getAngularObjectRegistry();That explain why in the |
|
I just reviewed the code (didn't try the PR yet). For the show paragraphID, since it is an utility, maybe we could only show that ID as the top line of the settings drop down. That way we wouldn't need to toggle it nor to hide it depending on the view (report view) and we could copy paste it (hopefully). +1 for the |
+1 |
|
Just a few update. I don't forget this PR. I'll spit it into 3 smallers PR:
|
What is this PR for?
This is a PR to add utilities functions for the AngularJS system and a new Hide/Show Paragraph Id feature.
1) AngularJS Utility Functions
runParagraph('paragraphId'): run a paragraph given its idrunParagraphs(['paragraphId1', 'paragraphId2']): run a list of paragraphs given their idpushToServer('varName', value, parameters): push a variable varName with its value to the server/interpreter angular object repository using current noteId and provided interpreter(s) (and optionally paragraph id(s)). parameters is a map with the following properties:Ex:
Remarks:
removeFromServer('varName', parameters): remove the variable varName from server/interpreter angular object repository using current noteId.Ex:
Remarks:
2) Hide/Show Paragraph Id
This feature is necessary for the above AngularJS functions to work. One can always retrieve the current paragraph Id using the code
But it is far from being user-friendly. Therefore, now you can show or hide paragraph Id using a toggle. This is placed at the same place as Show/Hide line numbers.
The paragraph id is displayed at the top left corner, above the Title.
I'm completely open to any suggestion with regard to the location of the display
3) Technical Impl
First I have added a new Thrift method angularRegistryPush(). This method is used to push the current angular object registry from the Zeppelin server to the remote interpreter. According to @Leemoonsoo, when a note is loaded from the JSON file, the interpreter may not be initialized yet so we need to store all the angular variables in the local registry. As soon as the remote interpreter is started, we can call the angularRegistryPush() method to push the local registry to the remote interpreter
A new public constructor has been added to the
AngularObjectclass. The reason is because when we push the wholeMap<String, Map<String, AngularObject>>registry to the remote interpreter using angularRegistryPush(), the registry is serialized using Gson. At the remote interpreter side, the payload is deserialized back into aMap<String, Map<String, AngularObject>>. If a class do not have a public constructor then Gson will use someUnsafetricks to create it (see here). Consequently, theprivate transient List<AngularObjectWatcher> watchers = new LinkedList<AngularObjectWatcher>();property will NOT be initialized and will throwNullPointerExceptionlater when the code access thewatchersThe
runParagraph()andrunParagraphs()Angular functions are injected into the isolated scope created for each paragraph so that people can access them. Currently I'm using the following trick to retrieve the paragraph details for a given paragraphId:It's not the cleanest way. Ideally, we should inject into the isolated scope the
note.paragraphsarray from the Note scope but I'm not sure if it is recommended to leak such information into an isolated scope. Any idea/suggestion is welcomedNew message operations
ANGULAR_OBJECT_CLIENT_UPDATEandANGULAR_OBJECT_CLIENT_REMOVEhave been added to supportpushToServer()andremoveFromServer()Angular functions. The core functionalities are implemented inNotebookServer.angularObjectClientUpdate()andNotebookServer.angularObjectClientDelete(). I also add 8 unit tests for those 2 methods. Similar torunParagraph(), thepushToServer()andremoveFromServer()AngularJS functions are injected into the isolated scope to be available for end users.The
ZeppelinContext.getAngularObject()private method has been updated. Right now it look for variable using only the note scope. I change the code so that now, we look for a variable using:Last but not least, I have changed the current behavior of dynamic form. In the method
Paragraph.jobRun(), when we encounter a variable definition block ( ${var = ...} ) while parsing, we first look into the angular object registry using (noteId, paragraphId) scope, then (noteId) scope. If we find a matching variable we'll use it and we do not create any form input for the paragraph. At worst, we can just remove the last commit, it is independent from the other features.@Leemoonsoo @jongyoul @bzz @felixcheung @corneadoug I really need your remarks/comments for the above 6 technical points. Thanks
What type of PR is it?
[Feature]
Todos
Is there a relevant Jira issue?
ZEPPELIN-635
How should this be tested?
Clone this pull request locally with:
See below 12 screenshots for all possible test scenarios
Screenshots (if appropriate)
Hide/Show ParagraphId

Run Single Paragraph

Run Multiple Paragraphs

Push To Server Scenario 1: single interpreter, note scope

Push To Server Scenario 2: multiple interpreters, note scope

Push To Server Scenario 3: single interpreter, single paragraph

Push To Server Scenario 4: single interpreter, multiples paragraphs

Push To Server Scenario 5: single interpreter, multiples paragraphs AND note scope

Push To Server Scenario 6: single interpreter, multiples paragraphs AND run paragraphs

Push To Server Scenario 7: multiple interpreters, multiples paragraphs, overriding dynamic forms

Remove From Server Scenario 1: single interpreter, single paragraph

Remove From Server Scenario 2: single interpreter, note scope

Questions: