zeppelin-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From prabhjyotsi...@apache.org
Subject zeppelin git commit: [ZEPPELIN-2823] Notebook saved status is wrong if there was a network disconnect or a flaky network.
Date Mon, 14 Aug 2017 22:36:25 GMT
Repository: zeppelin
Updated Branches:
  refs/heads/master 71d130521 -> 340b326d4


[ZEPPELIN-2823] Notebook saved status is wrong if there was a network disconnect or a flaky
network.

### What is this PR for?
Notebook content doesn't get saved if there is a flaky network, and at times user's paragraph
content also gets lost in this process.

### What type of PR is it?
[Bug Fix]

### What is the Jira issue?
* [ZEPPELIN-2823](https://issues.apache.org/jira/browse/ZEPPELIN-2823)

### How should this be tested?
Steps to re-produce:
 - create a new notebook
 - in the first paragraph enter text, say "version1"
 - now disconnect the network (say by removing LAN cable)
 - update this paragraph again with text "version2"
 - reconnect network
 - now observe the on the WebSocket reconnect, the content of this paragraph will go back
to "version1"

### Screenshots (if appropriate)

Before
![before](https://user-images.githubusercontent.com/674497/28852738-5772029e-76e0-11e7-82ed-8c2a25d3ab47.gif)

After
![after](https://user-images.githubusercontent.com/674497/28852739-5774efcc-76e0-11e7-9e48-4bda935c4686.gif)

### Questions:
* Does the licenses files need an update? N/A
* Is there breaking changes for older versions? N/A
* Does this needs documentation? N/A

Author: Prabhjyot Singh <prabhjyotsingh@gmail.com>

Closes #2512 from prabhjyotsingh/ZEPPELIN-2823 and squashes the following commits:

5f693ab93 [Prabhjyot Singh] - replace _.forEach with .map - extract BootstrapDialog.show outside
of the for loop
db30f479b [Prabhjyot Singh] alter text to `Changes that you have made will not be saved`
947be70b4 [Prabhjyot Singh] check if noteId exists in session or take it from fromMessage
8b8c2f974 [Prabhjyot Singh] check for empty originalText
d2a835f77 [Prabhjyot Singh] wait for server confirmation before updating stats of notebook


Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/340b326d
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/340b326d
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/340b326d

Branch: refs/heads/master
Commit: 340b326d47f3e07b7d98c2760b41c10424bfbb30
Parents: 71d1305
Author: Prabhjyot Singh <prabhjyotsingh@gmail.com>
Authored: Thu Aug 10 15:24:17 2017 -0700
Committer: Prabhjyot Singh <prabhjyotsingh@gmail.com>
Committed: Mon Aug 14 15:36:16 2017 -0700

----------------------------------------------------------------------
 .../apache/zeppelin/socket/NotebookServer.java  |  3 +
 .../src/app/notebook/notebook.controller.js     | 60 ++++++++++++++++++--
 .../notebook/paragraph/paragraph.controller.js  | 36 ++++++++++--
 .../paragraph/result/result.controller.js       |  2 +-
 .../websocket/websocket-event.factory.js        |  2 +-
 .../websocket/websocket-message.service.js      |  5 +-
 6 files changed, 95 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/340b326d/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
----------------------------------------------------------------------
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 61bc536..3ddeec0 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
@@ -1186,6 +1186,9 @@ public class NotebookServer extends WebSocketServlet
     Map<String, Object> params = (Map<String, Object>) fromMessage.get("params");
     Map<String, Object> config = (Map<String, Object>) fromMessage.get("config");
     String noteId = getOpenNoteId(conn);
+    if (noteId == null) {
+      noteId = (String) fromMessage.get("noteId");
+    }
 
     if (!hasParagraphWriterPermission(conn, notebook, noteId,
         userAndRoles, fromMessage.principal, "write")) {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/340b326d/zeppelin-web/src/app/notebook/notebook.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/notebook/notebook.controller.js b/zeppelin-web/src/app/notebook/notebook.controller.js
index a51ad4f..4b8b23f 100644
--- a/zeppelin-web/src/app/notebook/notebook.controller.js
+++ b/zeppelin-web/src/app/notebook/notebook.controller.js
@@ -51,6 +51,7 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
   $scope.interpreterBindings = []
   $scope.isNoteDirty = null
   $scope.saveTimer = null
+  $scope.paragraphWarningDialog = {}
 
   let connectedOnce = false
   let isRevisionPath = function (path) {
@@ -396,11 +397,6 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
     }, 10000)
   }
 
-  angular.element(window).on('beforeunload', function (e) {
-    $scope.killSaveTimer()
-    $scope.saveNote()
-  })
-
   $scope.setLookAndFeel = function (looknfeel) {
     $scope.note.config.looknfeel = looknfeel
     if ($scope.revisionView === true) {
@@ -1277,6 +1273,60 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
     $scope.note.config.personalizedMode = isPersonalized
   })
 
+  $scope.$on('$routeChangeStart', function (event, next, current) {
+    if (!$scope.note || !$scope.note.paragraphs) {
+      return
+    }
+    if ($scope.note && $scope.note.paragraphs) {
+      $scope.note.paragraphs.map(par => {
+        if ($scope.allowLeave === true) {
+          return
+        }
+        let thisScope = angular.element(
+          '#' + par.id + '_paragraphColumn_main').scope()
+
+        if (thisScope.dirtyText === undefined ||
+          thisScope.originalText === undefined ||
+          thisScope.dirtyText === thisScope.originalText) {
+          return true
+        } else {
+          event.preventDefault()
+          $scope.showParagraphWarning(next)
+        }
+      })
+    }
+  })
+
+  $scope.showParagraphWarning = function (next) {
+    if ($scope.paragraphWarningDialog.opened !== true) {
+      $scope.paragraphWarningDialog = BootstrapDialog.show({
+        closable: false,
+        closeByBackdrop: false,
+        closeByKeyboard: false,
+        title: 'Do you want to leave this site?',
+        message: 'Changes that you have made will not be saved.',
+        buttons: [{
+          label: 'Stay',
+          action: function (dialog) {
+            dialog.close()
+          }
+        }, {
+          label: 'Leave',
+          action: function (dialog) {
+            dialog.close()
+            let locationToRedirect = next['$$route']['originalPath']
+            Object.keys(next.pathParams).map(key => {
+              locationToRedirect = locationToRedirect.replace(':' + key,
+                next.pathParams[key])
+            })
+            $scope.allowLeave = true
+            $location.path(locationToRedirect)
+          }
+        }]
+      })
+    }
+  }
+
   $scope.$on('$destroy', function () {
     angular.element(window).off('beforeunload')
     $scope.killSaveTimer()

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/340b326d/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js
index 141f7b3..b4c79dd 100644
--- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js
+++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js
@@ -382,14 +382,41 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams,
$loca
       paragraphText, $scope.paragraph.config, $scope.paragraph.settings.params)
   }
 
+  $scope.bindBeforeUnload = function () {
+    angular.element(window).off('beforeunload')
+
+    let confirmOnPageExit = function (e) {
+      // If we haven't been passed the event get the window.event
+      e = e || window.event
+      let message = 'Do you want to reload this site?'
+
+      // For IE6-8 and Firefox prior to version 4
+      if (e) {
+        e.returnValue = message
+      }
+      // For Chrome, Safari, IE8+ and Opera 12+
+      return message
+    }
+    angular.element(window).on('beforeunload', confirmOnPageExit)
+  }
+
+  $scope.unBindBeforeUnload = function () {
+    angular.element(window).off('beforeunload')
+  }
+
   $scope.saveParagraph = function (paragraph) {
     const dirtyText = paragraph.text
     if (dirtyText === undefined || dirtyText === $scope.originalText) {
       return
     }
-    commitParagraph(paragraph)
-    $scope.originalText = dirtyText
-    $scope.dirtyText = undefined
+
+    $scope.bindBeforeUnload()
+
+    commitParagraph(paragraph).then(function () {
+      $scope.originalText = dirtyText
+      $scope.dirtyText = undefined
+      $scope.unBindBeforeUnload()
+    })
   }
 
   $scope.toggleEnableDisable = function (paragraph) {
@@ -1092,7 +1119,8 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams,
$loca
       settings: {params},
     } = paragraph
 
-    websocketMsgSrv.commitParagraph(id, title, text, config, params)
+    return websocketMsgSrv.commitParagraph(id, title, text, config, params,
+      $route.current.pathParams.noteId)
   }
 
   /** Utility function */

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/340b326d/zeppelin-web/src/app/notebook/paragraph/result/result.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/notebook/paragraph/result/result.controller.js b/zeppelin-web/src/app/notebook/paragraph/result/result.controller.js
index df9ebe9..be71d9c 100644
--- a/zeppelin-web/src/app/notebook/paragraph/result/result.controller.js
+++ b/zeppelin-web/src/app/notebook/paragraph/result/result.controller.js
@@ -645,7 +645,7 @@ function ResultCtrl ($scope, $rootScope, $route, $window, $routeParams,
$locatio
       }, newParagraphConfig.results[resultIndex], paragraph, resultIndex)
       renderResult($scope.type, true)
     } else {
-      websocketMsgSrv.commitParagraph(paragraph.id, title, text, newParagraphConfig, params)
+      return websocketMsgSrv.commitParagraph(paragraph.id, title, text, newParagraphConfig,
params)
     }
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/340b326d/zeppelin-web/src/components/websocket/websocket-event.factory.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/websocket/websocket-event.factory.js b/zeppelin-web/src/components/websocket/websocket-event.factory.js
index db058bb..10cfd9c 100644
--- a/zeppelin-web/src/components/websocket/websocket-event.factory.js
+++ b/zeppelin-web/src/components/websocket/websocket-event.factory.js
@@ -42,7 +42,7 @@ function WebsocketEventFactory ($rootScope, $websocket, $location, baseUrlSrv)
{
       data.roles = ''
     }
     console.log('Send >> %o, %o, %o, %o, %o', data.op, data.principal, data.ticket,
data.roles, data)
-    websocketCalls.ws.send(JSON.stringify(data))
+    return websocketCalls.ws.send(JSON.stringify(data))
   }
 
   websocketCalls.isConnected = function () {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/340b326d/zeppelin-web/src/components/websocket/websocket-message.service.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/components/websocket/websocket-message.service.js b/zeppelin-web/src/components/websocket/websocket-message.service.js
index 0dc02c3..cafc61b 100644
--- a/zeppelin-web/src/components/websocket/websocket-message.service.js
+++ b/zeppelin-web/src/components/websocket/websocket-message.service.js
@@ -233,11 +233,12 @@ function WebsocketMessageService ($rootScope, websocketEvents) {
       })
     },
 
-    commitParagraph: function (paragraphId, paragraphTitle, paragraphData, paragraphConfig,
paragraphParams) {
-      websocketEvents.sendNewEvent({
+    commitParagraph: function (paragraphId, paragraphTitle, paragraphData, paragraphConfig,
paragraphParams, noteId) {
+      return websocketEvents.sendNewEvent({
         op: 'COMMIT_PARAGRAPH',
         data: {
           id: paragraphId,
+          noteId: noteId,
           title: paragraphTitle,
           paragraph: paragraphData,
           config: paragraphConfig,


Mime
View raw message