diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java index 52fd7405b25..3fb842d2de4 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java @@ -26,6 +26,7 @@ import com.google.common.base.Strings; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import org.apache.zeppelin.conf.ZeppelinConfiguration; @@ -60,7 +61,8 @@ public class NotebookServer extends WebSocketServlet implements NotebookSocketListener, JobListenerFactory, AngularObjectRegistryListener, RemoteInterpreterProcessListener { private static final Logger LOG = LoggerFactory.getLogger(NotebookServer.class); - Gson gson = new Gson(); + Gson gson = new GsonBuilder() + .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ").create(); final Map> noteSocketMap = new HashMap<>(); final Queue connectedSockets = new ConcurrentLinkedQueue<>(); diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java b/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java index 2af724f3f0a..e2f2d1fd9fe 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/integration/ZeppelinIT.java @@ -206,7 +206,7 @@ public void testSparkInterpreterDependencyLoading() throws Exception { MAX_BROWSER_TIMEOUT_SEC); String artifact = "org.apache.commons:commons-csv:1.1"; depArtifact.sendKeys(artifact); - driver.findElement(By.xpath("//div[contains(@class,'box')][contains(.,'spark')]//form//button[1]")).click(); + driver.findElement(By.xpath("//div[contains(@class,'box')][contains(.,'%spark')]//form//button[1]")).click(); driver.findElement(By.xpath("//div[@class='modal-dialog'][contains(.,'Do you want to update this interpreter and restart with new settings?')]" + "//div[@class='modal-footer']//button[contains(.,'OK')]")).click(); @@ -240,7 +240,7 @@ public void testSparkInterpreterDependencyLoading() throws Exception { WebElement testDepRemoveBtn = pollingWait(By.xpath("//tr[descendant::text()[contains(.,'" + artifact + "')]]/td[3]/div"), MAX_IMPLICIT_WAIT); testDepRemoveBtn.click(); - driver.findElement(By.xpath("//div[contains(@class,'box')][contains(.,'spark')]//form//button[1]")).click(); + driver.findElement(By.xpath("//div[contains(@class,'box')][contains(.,'%spark')]//form//button[1]")).click(); driver.findElement(By.xpath("//div[@class='modal-dialog'][contains(.,'Do you want to update this interpreter and restart with new settings?')]" + "//div[@class='modal-footer']//button[contains(.,'OK')]")).click(); } catch (Exception e) { diff --git a/zeppelin-web/.jshintrc b/zeppelin-web/.jshintrc index bdcd213761e..5cfaeddcaf2 100644 --- a/zeppelin-web/.jshintrc +++ b/zeppelin-web/.jshintrc @@ -32,6 +32,7 @@ "ace": false, "d3": false, "BootstrapDialog": false, - "Handsontable": false + "Handsontable": false, + "moment": false } } diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js index 15ceb61a6e4..110d8fa472b 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js @@ -971,18 +971,22 @@ angular.module('zeppelinWebApp') return ''; } var user = 'anonymous'; - var authInfo = pdata.authenticationInfo; - if (authInfo && authInfo.user) { + if (pdata.authenticationInfo !== null && !isEmpty(pdata.authenticationInfo.user)) { user = pdata.authenticationInfo.user; } - var dateUpdated = (pdata.dateUpdated === null) ? 'unknown' : pdata.dateUpdated; - var desc = 'Took ' + (timeMs/1000) + ' seconds. Last updated by ' + user + ' at time ' + dateUpdated + '.'; + var desc = 'Took ' + + moment.duration(moment(pdata.dateFinished).diff(moment(pdata.dateStarted))).humanize() + + '. Last updated by ' + user + ' at ' + moment(pdata.dateUpdated).format('MMMM DD YYYY, h:mm:ss A') + '.'; if ($scope.isResultOutdated()){ desc += ' (outdated)'; } return desc; }; + $scope.getElapsedTime = function() { + return 'Started ' + moment($scope.paragraph.dateStarted).fromNow() + '.'; + }; + $scope.isResultOutdated = function() { var pdata = $scope.paragraph; if (pdata.dateUpdated !==undefined && Date.parse(pdata.dateUpdated) > Date.parse(pdata.dateStarted)){ diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.css b/zeppelin-web/src/app/notebook/paragraph/paragraph.css index 213dac7e1ed..59cc28f7014 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.css +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.css @@ -82,11 +82,13 @@ table.dataTable.table-condensed .sorting_desc:after { border: 3px solid #DDDDDD; } -.paragraph .paragraphFooter { - height: 9px; +.paragraph .executionTime { + color: #999; + font-size: 10px; + font-family: 'Roboto', sans-serif; } -.paragraph .executionTime { +.paragraph .elapsedTime { color: #999; font-size: 10px; font-family: 'Roboto', sans-serif; diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.html b/zeppelin-web/src/app/notebook/paragraph/paragraph.html index 043b6e81739..0157c02727b 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.html +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.html @@ -68,5 +68,11 @@ id="{{paragraph.id}}_executionTime" class="executionTime" ng-bind-html="getExecutionTime()"> +
+
+
+
diff --git a/zeppelin-web/src/assets/styles/looknfeel/simple.css b/zeppelin-web/src/assets/styles/looknfeel/simple.css index 8373114a366..0078306185e 100644 --- a/zeppelin-web/src/assets/styles/looknfeel/simple.css +++ b/zeppelin-web/src/assets/styles/looknfeel/simple.css @@ -55,9 +55,14 @@ body { .paragraph .paragraphFooter { visibility: hidden; - height: 0; position: relative; - top : -13px; + top : -9px; + z-index: 99; +} + +.paragraph .paragraphFooterElapsed { + height: 0px; + float: right; z-index: 99; } @@ -67,6 +72,12 @@ body { margin-right: 5px; } +.paragraph .elapsedTime { + font-size: 8px; + text-align: right; + margin-right: 5px; +} + .paragraph:hover .paragraphFooter { visibility: visible; }