diff --git a/zeppelin-web/src/app/notebook/notebook.controller.js b/zeppelin-web/src/app/notebook/notebook.controller.js index d09a0b23b64..111d1c49feb 100644 --- a/zeppelin-web/src/app/notebook/notebook.controller.js +++ b/zeppelin-web/src/app/notebook/notebook.controller.js @@ -164,7 +164,7 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope, for (let i = 0; i < $scope.note.paragraphs.length; i++) { let paragraphId = $scope.note.paragraphs[i].id if (jQuery.contains(angular.element('#' + paragraphId + '_container')[0], clickEvent.target)) { - $scope.$broadcast('focusParagraph', paragraphId, 0, true) + $scope.$broadcast('focusParagraph', paragraphId, 0, null, true) break } } @@ -504,7 +504,7 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope, para.focus = true // we need `$timeout` since angular DOM might not be initialized - $timeout(() => { $scope.$broadcast('focusParagraph', para.id, 0, false) }) + $timeout(() => { $scope.$broadcast('focusParagraph', para.id, 0, null, false) }) } }) } @@ -1180,6 +1180,92 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope, ** $scope.$on functions below */ + $scope.$on('runAllAbove', function (event, paragraph, isNeedConfirm) { + let allParagraphs = $scope.note.paragraphs + let toRunParagraphs = [] + + for (let i = 0; allParagraphs[i] !== paragraph; i++) { + if (i === allParagraphs.length - 1) { return } // if paragraph not in array of all paragraphs + toRunParagraphs.push(allParagraphs[i]) + } + + const paragraphs = toRunParagraphs.map(p => { + return { + id: p.id, + title: p.title, + paragraph: p.text, + config: p.config, + params: p.settings.params + } + }) + + if (!isNeedConfirm) { + websocketMsgSrv.runAllParagraphs($scope.note.id, paragraphs) + } else { + BootstrapDialog.confirm({ + closable: true, + title: '', + message: 'Run all above?', + callback: function (result) { + if (result) { + websocketMsgSrv.runAllParagraphs($scope.note.id, paragraphs) + } + } + }) + } + + $scope.saveCursorPosition(paragraph) + }) + + $scope.$on('runAllBelowAndCurrent', function (event, paragraph, isNeedConfirm) { + let allParagraphs = $scope.note.paragraphs + let toRunParagraphs = [] + + for (let i = allParagraphs.length - 1; allParagraphs[i] !== paragraph; i--) { + if (i < 0) { return } // if paragraph not in array of all paragraphs + toRunParagraphs.push(allParagraphs[i]) + } + + toRunParagraphs.push(paragraph) + toRunParagraphs.reverse() + + const paragraphs = toRunParagraphs.map(p => { + return { + id: p.id, + title: p.title, + paragraph: p.text, + config: p.config, + params: p.settings.params + } + }) + + if (!isNeedConfirm) { + websocketMsgSrv.runAllParagraphs($scope.note.id, paragraphs) + } else { + BootstrapDialog.confirm({ + closable: true, + title: '', + message: 'Run current and all below?', + callback: function (result) { + if (result) { + websocketMsgSrv.runAllParagraphs($scope.note.id, paragraphs) + } + } + }) + } + + $scope.saveCursorPosition(paragraph) + }) + + $scope.saveCursorPosition = function (paragraph) { + let angParagEditor = angular + .element('#' + paragraph.id + '_paragraphColumn_main') + .scope().editor + let col = angParagEditor.selection.lead.column + let row = angParagEditor.selection.lead.row + $scope.$broadcast('focusParagraph', paragraph.id, row + 1, col) + } + $scope.$on('setConnectedStatus', function (event, param) { if (connectedOnce && param) { initNotebook() diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph-control.html b/zeppelin-web/src/app/notebook/paragraph/paragraph-control.html index d6599725cc0..0b4ca1e4d67 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph-control.html +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph-control.html @@ -140,6 +140,24 @@ Insert new +
  • + + + + Ctrl+Shift+Enter + Run all above + +
  • +
  • + + + + Ctrl+Shift+Enter + Run all below + +
  • Ctrl+Shift+C diff --git a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js index c5788416adf..d3ed3466e76 100644 --- a/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js +++ b/zeppelin-web/src/app/notebook/paragraph/paragraph.controller.js @@ -471,6 +471,43 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca $scope.runParagraph($scope.getEditorValue(), false, false) } + $scope.runAllToThis = function(paragraph) { + $scope.$emit('runAllAbove', paragraph, true) + } + + $scope.runAllFromThis = function(paragraph) { + $scope.$emit('runAllBelowAndCurrent', paragraph, true) + } + + $scope.runAllToOrFromThis = function (paragraph) { + BootstrapDialog.show({ + message: 'Run paragraphs:', + title: '', + buttons: [{ + label: 'Close', + action: function(dialog) { + dialog.close() + } + }, + { + label: 'Run all above', + cssClass: 'btn-primary', + action: function(dialog) { + $scope.$emit('runAllAbove', paragraph, false) + dialog.close() + } + }, + { + label: 'Run current and all below', + cssClass: 'btn-primary', + action: function(dialog) { + $scope.$emit('runAllBelowAndCurrent', paragraph, false) + dialog.close() + } + }] + }) + } + $scope.turnOnAutoRun = function (paragraph) { paragraph.config.runOnSelectionChange = !paragraph.config.runOnSelectionChange commitParagraph(paragraph) @@ -1446,8 +1483,10 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca // move focus to next paragraph // $timeout stops chaining effect of focus propogation $timeout(() => $scope.$emit('moveFocusToNextParagraph', paragraphId)) - } else if (keyEvent.shiftKey && keyCode === 13) { // Shift + Enter + } else if (!keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 13) { // Shift + Enter $scope.runParagraphFromShortcut($scope.getEditorValue()) + } else if (keyEvent.ctrlKey && keyEvent.shiftKey && keyCode === 13) { // Ctrl + Shift + Enter + $scope.runAllToOrFromThis($scope.paragraph) } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 67) { // Ctrl + Alt + c $scope.cancelParagraph($scope.paragraph) } else if (keyEvent.ctrlKey && keyEvent.altKey && keyCode === 68) { // Ctrl + Alt + d @@ -1500,7 +1539,10 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca } }) - $scope.$on('focusParagraph', function (event, paragraphId, cursorPos, mouseEvent) { + $scope.$on('focusParagraph', function (event, paragraphId, cursorPosRow, cursorPosCol, mouseEvent) { + if (cursorPosCol === null || cursorPosCol === undefined) { + cursorPosCol = 0 + } if ($scope.paragraph.id === paragraphId) { // focus editor if (!$scope.paragraph.config.editorHide) { @@ -1508,14 +1550,14 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca $scope.editor.focus() // move cursor to the first row (or the last row) let row - if (cursorPos >= 0) { - row = cursorPos - $scope.editor.gotoLine(row, 0) + if (cursorPosRow >= 0) { + row = cursorPosRow + $scope.editor.gotoLine(row, cursorPosCol) } else { row = $scope.editor.session.getLength() - $scope.editor.gotoLine(row, 0) + $scope.editor.gotoLine(row, cursorPosCol) } - $scope.scrollToCursor($scope.paragraph.id, 0) + $scope.scrollToCursor($scope.paragraph.id, cursorPosCol) } } handleFocus(true) diff --git a/zeppelin-web/src/app/notebook/shortcut.html b/zeppelin-web/src/app/notebook/shortcut.html index c4b4009ee11..9bc55973a53 100644 --- a/zeppelin-web/src/app/notebook/shortcut.html +++ b/zeppelin-web/src/app/notebook/shortcut.html @@ -37,6 +37,17 @@

    Keyboard shortcuts

    + + +
    Run all above/below paragraphs
    + + +
    + Ctrl + Shift + Enter +
    + + +
    Cancel