mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
[ZEPPELIN-2106] providing paragraph config in create
note/paragraph call * Allow to describe graph, colWidth, showTitle or full paragraph config directly in the Create Paragraph and Create Note endpoint. * Updated doc.
This commit is contained in:
parent
fb4c778b9e
commit
76af44ab6c
4 changed files with 194 additions and 30 deletions
|
|
@ -111,7 +111,28 @@ Notebooks REST API supports the following operations: List, Create, Get, Delete,
|
|||
},
|
||||
{
|
||||
"title": "paragraph title2",
|
||||
"text": "paragraph text2"
|
||||
"text": "paragraph text2",
|
||||
"showTitle": true,
|
||||
"colWidth": 9.0,
|
||||
"graph": {
|
||||
"mode": "pieChart"
|
||||
}
|
||||
}
|
||||
{
|
||||
"title": "paragraph title3",
|
||||
"text": "paragraph text3",
|
||||
"config": {
|
||||
"title": true,
|
||||
"colWidth": 6.0,
|
||||
"results": [
|
||||
{
|
||||
"graph": {
|
||||
"mode": "scatterChart",
|
||||
"optionOpen": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}</pre></td>
|
||||
|
|
@ -598,6 +619,39 @@ Notebooks REST API supports the following operations: List, Create, Get, Delete,
|
|||
"title": "Paragraph insert revised",
|
||||
"text": "%spark\nprintln(\"Paragraph insert revised\")",
|
||||
"index": 0
|
||||
}</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> sample JSON input (providing graph,showTitle and colWidth information) </td>
|
||||
<td><pre>
|
||||
{
|
||||
"title": "paragraph title2",
|
||||
"text": "paragraph text2",
|
||||
"showTitle": true,
|
||||
"colWidth": 9.0,
|
||||
"graph": {
|
||||
"mode": "pieChart"
|
||||
}
|
||||
}</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> sample JSON input (providing paragraph config) </td>
|
||||
<td><pre>
|
||||
{
|
||||
"title": "paragraph title3",
|
||||
"text": "paragraph text3",
|
||||
"config": {
|
||||
"title": true,
|
||||
"colWidth": 6.0,
|
||||
"results": [
|
||||
{
|
||||
"graph": {
|
||||
"mode": "scatterChart",
|
||||
"optionOpen": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}</pre></td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
|
|
|||
|
|
@ -18,11 +18,7 @@
|
|||
package org.apache.zeppelin.rest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
|
|
@ -337,16 +333,16 @@ public class NotebookRestApi {
|
|||
@Path("/")
|
||||
@ZeppelinApi
|
||||
public Response createNote(String message) throws IOException {
|
||||
String user = SecurityUtils.getPrincipal();
|
||||
LOG.info("Create new note by JSON {}", message);
|
||||
NewNoteRequest request = gson.fromJson(message, NewNoteRequest.class);
|
||||
AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal());
|
||||
AuthenticationInfo subject = new AuthenticationInfo(user);
|
||||
Note note = notebook.createNote(subject);
|
||||
List<NewParagraphRequest> initialParagraphs = request.getParagraphs();
|
||||
if (initialParagraphs != null) {
|
||||
for (NewParagraphRequest paragraphRequest : initialParagraphs) {
|
||||
Paragraph p = note.addParagraph(subject);
|
||||
p.setTitle(paragraphRequest.getTitle());
|
||||
p.setText(paragraphRequest.getText());
|
||||
initParagraph(p, paragraphRequest, user);
|
||||
}
|
||||
}
|
||||
note.addParagraph(subject); // add one paragraph to the last
|
||||
|
|
@ -425,6 +421,7 @@ public class NotebookRestApi {
|
|||
@ZeppelinApi
|
||||
public Response insertParagraph(@PathParam("noteId") String noteId, String message)
|
||||
throws IOException {
|
||||
String user = SecurityUtils.getPrincipal();
|
||||
LOG.info("insert paragraph {} {}", noteId, message);
|
||||
|
||||
Note note = notebook.getNote(noteId);
|
||||
|
|
@ -432,7 +429,7 @@ public class NotebookRestApi {
|
|||
checkIfUserCanWrite(noteId, "Insufficient privileges you cannot add paragraph to this note");
|
||||
|
||||
NewParagraphRequest request = gson.fromJson(message, NewParagraphRequest.class);
|
||||
AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal());
|
||||
AuthenticationInfo subject = new AuthenticationInfo(user);
|
||||
Paragraph p;
|
||||
Double indexDouble = request.getIndex();
|
||||
if (indexDouble == null) {
|
||||
|
|
@ -440,9 +437,7 @@ public class NotebookRestApi {
|
|||
} else {
|
||||
p = note.insertParagraph(indexDouble.intValue(), subject);
|
||||
}
|
||||
p.setTitle(request.getTitle());
|
||||
p.setText(request.getText());
|
||||
|
||||
initParagraph(p, request, user);
|
||||
note.persist(subject);
|
||||
notebookServer.broadcastNote(note);
|
||||
return new JsonResponse<>(Status.OK, "", p.getId()).build();
|
||||
|
|
@ -486,17 +481,7 @@ public class NotebookRestApi {
|
|||
checkIfParagraphIsNotNull(p);
|
||||
|
||||
Map<String, Object> newConfig = gson.fromJson(message, HashMap.class);
|
||||
if (newConfig == null || newConfig.isEmpty()) {
|
||||
LOG.warn("{} is trying to update paragraph {} of note {} with empty config",
|
||||
user, paragraphId, noteId);
|
||||
throw new BadRequestException("paragraph config cannot be empty");
|
||||
}
|
||||
Map<String, Object> origConfig = p.getConfig();
|
||||
for (String key : newConfig.keySet()) {
|
||||
origConfig.put(key, newConfig.get(key));
|
||||
}
|
||||
|
||||
p.setConfig(origConfig);
|
||||
configureParagraph(p, newConfig, user);
|
||||
AuthenticationInfo subject = new AuthenticationInfo(user);
|
||||
note.persist(subject);
|
||||
|
||||
|
|
@ -963,4 +948,62 @@ public class NotebookRestApi {
|
|||
}
|
||||
}
|
||||
|
||||
private void initParagraph(Paragraph p, NewParagraphRequest request, String user)
|
||||
throws IOException {
|
||||
LOG.info("Init Paragraph for user {}", user);
|
||||
checkIfParagraphIsNotNull(p);
|
||||
p.setTitle(request.getTitle());
|
||||
p.setText(request.getText());
|
||||
Map< String, Object > config = request.getConfig();
|
||||
if ( config != null){
|
||||
Vector< String > ignoredFields = new Vector<>();
|
||||
if ( request.getGraph() != null)
|
||||
ignoredFields.add("graph");
|
||||
if ( request.getColWidth() != null)
|
||||
ignoredFields.add("colWidth");
|
||||
if ( request.getShowTitle() != null)
|
||||
ignoredFields.add("showTitle");
|
||||
if ( ignoredFields.size() > 0 )
|
||||
LOG.warn("As config is provided, the following field(s) are ignored {}",
|
||||
ignoredFields.toString());
|
||||
}
|
||||
else {
|
||||
config = new HashMap<>();
|
||||
Map graph = request.getGraph();
|
||||
if (graph != null) {
|
||||
List<Object> results = new ArrayList<>();
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("graph", graph);
|
||||
results.add(result);
|
||||
config.put("results", results);
|
||||
}
|
||||
Double colWidth = request.getColWidth();
|
||||
if (colWidth != null) {
|
||||
config.put("colWidth", colWidth);
|
||||
}
|
||||
Boolean showTitle = request.getShowTitle();
|
||||
if (showTitle != null) {
|
||||
config.put("title", showTitle);
|
||||
}
|
||||
}
|
||||
if ( !config.isEmpty()) {
|
||||
configureParagraph(p, config, user);
|
||||
}
|
||||
}
|
||||
|
||||
private void configureParagraph(Paragraph p, Map< String, Object> newConfig, String user)
|
||||
throws IOException {
|
||||
LOG.info("Configure Paragraph for user {}", user);
|
||||
if (newConfig == null || newConfig.isEmpty()) {
|
||||
LOG.warn("{} is trying to update paragraph {} of note {} with empty config",
|
||||
user, p.getId(), p.getNote().getId());
|
||||
throw new BadRequestException("paragraph config cannot be empty");
|
||||
}
|
||||
Map<String, Object> origConfig = p.getConfig();
|
||||
for (String key : newConfig.keySet()) {
|
||||
origConfig.put(key, newConfig.get(key));
|
||||
}
|
||||
p.setConfig(origConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,15 +17,24 @@
|
|||
|
||||
package org.apache.zeppelin.rest.message;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* NewParagraphRequest rest api request message
|
||||
*
|
||||
* index field will be ignored when it's used to provide initial paragraphs
|
||||
* visualization (optional) one of:
|
||||
* table,pieChart,multibarChart,stackedAreaChart,lineChart,scatterChart
|
||||
* colWidth (optional), e.g. 12.0
|
||||
*/
|
||||
public class NewParagraphRequest {
|
||||
String title;
|
||||
String text;
|
||||
Double index;
|
||||
HashMap< String, Object > graph;
|
||||
Boolean showTitle;
|
||||
Double colWidth;
|
||||
HashMap< String, Object > config;
|
||||
|
||||
public NewParagraphRequest() {
|
||||
|
||||
|
|
@ -42,4 +51,12 @@ public class NewParagraphRequest {
|
|||
public Double getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public HashMap< String, Object > getGraph() { return graph; }
|
||||
|
||||
public Boolean getShowTitle() { return showTitle; }
|
||||
|
||||
public Double getColWidth() { return colWidth; }
|
||||
|
||||
public HashMap< String, Object > getConfig() { return config; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -133,8 +133,14 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
String noteName = "test";
|
||||
String jsonRequest = "{\"name\":\"" + noteName + "\", \"paragraphs\": [" +
|
||||
"{\"title\": \"title1\", \"text\": \"text1\"}," +
|
||||
"{\"title\": \"title2\", \"text\": \"text2\"}" +
|
||||
"]}";
|
||||
"{\"title\": \"title2\", \"text\": \"text2\"}," +
|
||||
"{\"title\": \"titleConfig1\", \"text\": \"text3\", " +
|
||||
"\"graph\": {\"mode\": \"pieChart\"}, " +
|
||||
"\"colWidth\": 9.0, \"showTitle\": true}, " +
|
||||
"{\"title\": \"titleConfig2\", \"text\": \"text4\", " +
|
||||
"\"config\": {\"colWidth\": 9.0, \"title\": true, "+
|
||||
"\"results\": [{\"graph\": {\"mode\": \"pieChart\"}}] "+
|
||||
"}}]} ";
|
||||
PostMethod post = httpPost("/notebook/", jsonRequest);
|
||||
LOG.info("testNoteCreate \n" + post.getResponseBodyAsString());
|
||||
assertThat("test note create method:", post, isAllowed());
|
||||
|
|
@ -154,13 +160,20 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
expectedNoteName = "Note " + newNoteId;
|
||||
}
|
||||
assertEquals("compare note name", expectedNoteName, newNoteName);
|
||||
assertEquals("initial paragraph check failed", 3, newNote.getParagraphs().size());
|
||||
assertEquals("initial paragraph check failed", 5, newNote.getParagraphs().size());
|
||||
for (Paragraph p : newNote.getParagraphs()) {
|
||||
if (StringUtils.isEmpty(p.getText())) {
|
||||
continue;
|
||||
}
|
||||
assertTrue("paragraph title check failed", p.getTitle().startsWith("title"));
|
||||
assertTrue("paragraph text check failed", p.getText().startsWith("text"));
|
||||
if ( p.getTitle() == "titleConfig"){
|
||||
assertEquals("paragraph col width check failed", 9.0, p.getConfig().get("colWidth"));
|
||||
assertTrue("paragraph show title check failed", ((boolean) p.getConfig().get("title")));
|
||||
Map graph = ((List<Map>)p.getConfig().get("results")).get(0);
|
||||
String mode = graph.get("mode").toString();
|
||||
assertEquals("paragraph graph mode check failed", "pieChart", mode);
|
||||
}
|
||||
}
|
||||
// cleanup
|
||||
ZeppelinServer.notebook.removeNote(newNoteId, anonymous);
|
||||
|
|
@ -213,8 +226,8 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
|
||||
|
||||
@Test
|
||||
public void testexportNote() throws IOException {
|
||||
LOG.info("testexportNote");
|
||||
public void testExportNote() throws IOException {
|
||||
LOG.info("testExportNote");
|
||||
Note note = ZeppelinServer.notebook.createNote(anonymous);
|
||||
assertNotNull("can't create new note", note);
|
||||
note.setName("source note for export");
|
||||
|
|
@ -246,7 +259,7 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
public void testImportNotebook() throws IOException {
|
||||
Map<String, Object> resp;
|
||||
String noteName = "source note for import";
|
||||
LOG.info("testImortNote");
|
||||
LOG.info("testImportNote");
|
||||
// create test note
|
||||
Note note = ZeppelinServer.notebook.createNote(anonymous);
|
||||
assertNotNull("can't create new note", note);
|
||||
|
|
@ -620,6 +633,43 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
assertEquals("title2", paragraphAtIdx0.getTitle());
|
||||
assertEquals("text2", paragraphAtIdx0.getText());
|
||||
|
||||
//append paragraph providing config
|
||||
String jsonRequest3 = "{\"title\": \"title3\", \"text\": \"text3\", " +
|
||||
"\"graph\": {\"mode\": \"pieChart\"}, " +
|
||||
"\"colWidth\": 9.0, \"showTitle\": true}";
|
||||
PostMethod post3 = httpPost("/notebook/" + note.getId() + "/paragraph", jsonRequest3);
|
||||
LOG.info("testInsertParagraph response3\n" + post3.getResponseBodyAsString());
|
||||
assertThat("Test insert method:", post3, isAllowed());
|
||||
post3.releaseConnection();
|
||||
|
||||
Paragraph p = note.getLastParagraph();
|
||||
assertEquals("title3", p.getTitle());
|
||||
assertEquals("text3", p.getText());
|
||||
Map result = ((List<Map>)p.getConfig().get("results")).get(0);
|
||||
String mode = ((Map)result.get("graph")).get("mode").toString();
|
||||
assertEquals("pieChart", mode);
|
||||
assertEquals(9.0, p.getConfig().get("colWidth"));
|
||||
assertTrue(((boolean) p.getConfig().get("title")));
|
||||
|
||||
//append paragraph providing graph
|
||||
String jsonRequest4 = "{\"title\": \"title4\", \"text\": \"text4\", "+
|
||||
"\"config\": {\"colWidth\": 9.0, \"title\": true, "+
|
||||
"\"results\": [{\"graph\": {\"mode\": \"pieChart\"}}]}}";
|
||||
PostMethod post4 = httpPost("/notebook/" + note.getId() + "/paragraph", jsonRequest4);
|
||||
LOG.info("testInsertParagraph response4\n" + post4.getResponseBodyAsString());
|
||||
assertThat("Test insert method:", post4, isAllowed());
|
||||
post4.releaseConnection();
|
||||
|
||||
Paragraph p2 = note.getLastParagraph();
|
||||
assertEquals("title4", p2.getTitle());
|
||||
assertEquals("text4", p2.getText());
|
||||
Map result2 = ((List<Map>)p.getConfig().get("results")).get(0);
|
||||
String mode2 = ((Map)result.get("graph")).get("mode").toString();
|
||||
assertEquals("pieChart", mode2);
|
||||
assertEquals(9.0, p2.getConfig().get("colWidth"));
|
||||
assertTrue(((boolean) p2.getConfig().get("title")));
|
||||
|
||||
|
||||
ZeppelinServer.notebook.removeNote(note.getId(), anonymous);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue