Xikui Wang has uploaded a new change for review.
https://asterix-gerrit.ics.uci.edu/1574
Change subject: Pretty JSON output
......................................................................
Pretty JSON output
1. Added Pretty JSON output query option.
2. Tweaked front end JS to rerender the JSON result. (Take the HTML
element and rerender it with json-viewer plugin).
3. Added jquery.json-viewer library (MIT License) to front end, with
several customization: a) Several compatibility bug fix (semi-colon,
comment); b) expand logo change.
Change-Id: Ieec8489c0a055b01e754bba5f9827a7c1f175567
---
M
asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java
M asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
A
asterixdb/asterix-app/src/main/resources/webui/static/css/jquery.json-viewer.css
A asterixdb/asterix-app/src/main/resources/webui/static/js/jquery.json-viewer.js
4 files changed, 209 insertions(+), 2 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/74/1574/1
diff --git
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java
index f401576..088d153 100644
---
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java
+++
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/ResultPrinter.java
@@ -87,7 +87,7 @@
// output by displayCSVHeader(), so skip it here
if (conf.is(SessionConfig.FORMAT_HTML)) {
conf.out().println("<h4>Results:</h4>");
- conf.out().println("<pre>");
+ conf.out().println("<pre class=\"result-content\">");
}
try {
diff --git a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
index 878b1cf..a83c636 100644
--- a/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
+++ b/asterixdb/asterix-app/src/main/resources/webui/querytemplate.html
@@ -35,8 +35,10 @@
<link href="/webui/static/css/style.css" rel="stylesheet"
type="text/css" />
+<script src="/webui/static/js/jquery.json-viewer.js"></script>
+<link href="/webui/static/css/jquery.json-viewer.css" type="text/css"
rel="stylesheet" />
-<script type="text/javascript">
+ <script type="text/javascript">
$(document).ready(function() {
var optionButtonSize = $('#checkboxes-on').width();
@@ -155,6 +157,28 @@
}
}
+ /* Handling Pretty JSON */
+ var resultFormat = $('#output-format option:checked').val();
+ var prettyJson = $('[name="pretty-json"]').is(':checked');
+ if ( prettyJson && (resultFormat == 'LOSSLESS_JSON' ||
resultFormat == 'CLEAN_JSON')) {
+ $('.result-content').each(
+ function(idx) {
+ var results = $(this).text().split('\n');
+ $(this).css('padding-left', '20px');
+ $(this).text('');
+ for (var iter1 = 0; iter1 < results.length - 1; iter1++) {
+ if (results[iter1].length < 1) {
+ continue;
+ }
+ var resultJSON = $.parseJSON(results[iter1]);
+ $(this).append($('<div/>').attr("id",
"json-record"+idx+"-"+iter1));
+
$('#json-record'+idx+"-"+iter1).jsonViewer(resultJSON);
+ }
+ }
+ );
+ }
+
+
var contentString = data.toString();
if (contentString.indexOf(durPattern) != -1) {
$('<div/>')
@@ -235,6 +259,7 @@
<option value="LOSSLESS_JSON">JSON (lossless)</option>
</select>
</label>
+ <label class="optlabel"><input type="checkbox"
name="pretty-json" value="true" /> Pretty JSON</label>
<label class="optlabel"><input type="checkbox"
name="wrapper-array" value="true" /> Wrap results in outer array</label>
<label class="checkbox optlabel"><input type="checkbox"
name="print-expr-tree" value="true" /> Print parsed expressions</label>
<label class="checkbox optlabel"><input type="checkbox"
name="print-rewritten-expr-tree" value="true" /> Print rewritten
expressions</label>
diff --git
a/asterixdb/asterix-app/src/main/resources/webui/static/css/jquery.json-viewer.css
b/asterixdb/asterix-app/src/main/resources/webui/static/css/jquery.json-viewer.css
new file mode 100644
index 0000000..d6143f9
--- /dev/null
+++
b/asterixdb/asterix-app/src/main/resources/webui/static/css/jquery.json-viewer.css
@@ -0,0 +1,45 @@
+/* Syntax highlighting for JSON objects */
+ul.json-dict, ol.json-array {
+ list-style-type: none;
+ margin: 0 0 0 1px;
+ border-left: 1px dotted #ccc;
+ padding-left: 2em;
+}
+.json-string {
+ color: #0B7500;
+}
+.json-literal {
+ color: #1A01CC;
+ font-weight: bold;
+}
+
+/* Toggle button */
+a.json-toggle {
+ position: relative;
+ color: inherit;
+ text-decoration: none;
+}
+a.json-toggle:focus {
+ outline: none;
+}
+a.json-toggle:before {
+ color: #aaa;
+ content: "\25BC"; /* down arrow */
+ position: absolute;
+ display: inline-block;
+ width: 1em;
+ left: -1em;
+}
+a.json-toggle.collapsed:before {
+ content: "\25B6"; /* left arrow */
+}
+
+/* Collapsable placeholder links */
+a.json-placeholder {
+ color: #aaa;
+ padding: 0 1em;
+ text-decoration: none;
+}
+a.json-placeholder:hover {
+ text-decoration: underline;
+}
diff --git
a/asterixdb/asterix-app/src/main/resources/webui/static/js/jquery.json-viewer.js
b/asterixdb/asterix-app/src/main/resources/webui/static/js/jquery.json-viewer.js
new file mode 100644
index 0000000..6ef9bdd
--- /dev/null
+++
b/asterixdb/asterix-app/src/main/resources/webui/static/js/jquery.json-viewer.js
@@ -0,0 +1,137 @@
+/**
+ * jQuery json-viewer
+ * @author: Alexandre Bodelot <[email protected]>
+ */
+(function($){
+
+ /**
+ * Check if arg is either an array with at least 1 element, or a dict with
at least 1 key
+ * @return boolean
+ */
+ function isCollapsable(arg) {
+ return arg instanceof Object && Object.keys(arg).length > 0;
+ }
+
+ /**
+ * Check if a string represents a valid url
+ * @return boolean
+ */
+ function isUrl(string) {
+ var regexp =
/^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/;
+ return regexp.test(string);
+ }
+
+ /**
+ * Transform a json object into html representation
+ * @return string
+ */
+ function json2html(json, options) {
+ var html = '';
+ if (typeof json === 'string') {
+ json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g,
'>');
+ if (isUrl(json))
+ html += '<a href="' + json + '" class="json-string">' + json + '</a>';
+ else
+ html += '<span class="json-string">"' + json + '"</span>';
+ }
+ else if (typeof json === 'number') {
+ html += '<span class="json-literal">' + json + '</span>';
+ }
+ else if (typeof json === 'boolean') {
+ html += '<span class="json-literal">' + json + '</span>';
+ }
+ else if (json === null) {
+ html += '<span class="json-literal">null</span>';
+ }
+ else if (json instanceof Array) {
+ if (json.length > 0) {
+ html += '[<ol class="json-array">';
+ for (var i = 0; i < json.length; ++i) {
+ html += '<li>';
+ if (isCollapsable(json[i])) {
+ html += '<a href class="json-toggle"></a>';
+ }
+ html += json2html(json[i], options);
+ if (i < json.length - 1) {
+ html += ',';
+ }
+ html += '</li>';
+ }
+ html += '</ol>]';
+ }
+ else {
+ html += '[]';
+ }
+ }
+ else if (typeof json === 'object') {
+ var key_count = Object.keys(json).length;
+ if (key_count > 0) {
+ html += '{<ul class="json-dict">';
+ for (var key in json) {
+ if (json.hasOwnProperty(key)) {
+ html += '<li>';
+ var keyRepr = options.withQuotes ?
+ '<span class="json-string">"' + key + '"</span>' : key;
+ if (isCollapsable(json[key])) {
+ html += '<a href class="json-toggle">' + keyRepr + '</a>';
+ }
+ else {
+ html += keyRepr;
+ }
+ html += ': ' + json2html(json[key], options);
+ if (--key_count > 0)
+ html += ',';
+ html += '</li>';
+ }
+ }
+ html += '</ul>}';
+ }
+ else {
+ html += '{}';
+ }
+ }
+ return html;
+ }
+
+ /**
+ * jQuery plugin method
+ * @param json: a javascript object
+ * @param options: an optional options hash
+ */
+ $.fn.jsonViewer = function(json, options) {
+ options = options || {};
+
+ return this.each(function() {
+
+ var html = json2html(json, options);
+ if (isCollapsable(json))
+ html = '<a href class="json-toggle"></a>' + html;
+
+ $(this).html(html);
+
+ $(this).off('click');
+ $(this).on('click', 'a.json-toggle', function() {
+ var target = $(this).toggleClass('collapsed').siblings('ul.json-dict,
ol.json-array');
+ target.toggle();
+ if (target.is(':visible')) {
+ target.siblings('.json-placeholder').remove();
+ }
+ else {
+ var count = target.children('li').length;
+ var placeholder = count + (count > 1 ? ' items' : ' item');
+ target.after('<a href class="json-placeholder">' + placeholder +
'</a>');
+ }
+ return false;
+ });
+
+ $(this).on('click', 'a.json-placeholder', function() {
+ $(this).siblings('a.json-toggle').click();
+ return false;
+ });
+
+ if (options.collapsed == true) {
+ $(this).find('a.json-toggle').click();
+ }
+ });
+ };
+})(jQuery);
--
To view, visit https://asterix-gerrit.ics.uci.edu/1574
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ieec8489c0a055b01e754bba5f9827a7c1f175567
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Xikui Wang <[email protected]>