diff --git a/desktop/core/src/desktop/js/apps/editor/EditorViewModel.js b/desktop/core/src/desktop/js/apps/editor/EditorViewModel.js index 9d0eb3de3e6..59aca1b3ea5 100644 --- a/desktop/core/src/desktop/js/apps/editor/EditorViewModel.js +++ b/desktop/core/src/desktop/js/apps/editor/EditorViewModel.js @@ -35,13 +35,11 @@ import changeURLParameter from 'utils/url/changeURLParameter'; import getParameter from 'utils/url/getParameter'; export default class EditorViewModel { - constructor(editorId, notebooks, options, CoordinatorEditorViewModel, RunningCoordinatorModel) { + constructor(options, CoordinatorEditorViewModel, RunningCoordinatorModel) { // eslint-disable-next-line no-restricted-syntax console.log('Editor v2 enabled.'); - this.editorId = editorId; this.snippetViewSettings = options.snippetViewSettings; - this.notebooks = notebooks; this.URLS = { editor: '/hue/editor', @@ -313,14 +311,13 @@ export default class EditorViewModel { } async init() { - if (this.editorId) { - await this.openNotebook(this.editorId); + const editorId = getParameter('editor'); + if (editorId) { + await this.openNotebook(editorId); } else if (getParameter('gist') !== '' || getParameter('type') !== '') { await this.newNotebook(getParameter('type')); } else if (getParameter('editor') !== '') { await this.openNotebook(getParameter('editor')); - } else if (this.notebooks.length > 0) { - this.loadNotebook(this.notebooks[0]); // Old way of loading json for /browse } else { await this.newNotebook(); } diff --git a/desktop/core/src/desktop/js/apps/editor/EditorViewModel.test.js b/desktop/core/src/desktop/js/apps/editor/EditorViewModel.test.js new file mode 100644 index 00000000000..5ee9120a450 --- /dev/null +++ b/desktop/core/src/desktop/js/apps/editor/EditorViewModel.test.js @@ -0,0 +1,30 @@ +// Licensed to Cloudera, Inc. under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. Cloudera, Inc. licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import EditorViewModel from './EditorViewModel'; +import changeURLParameter from 'utils/url/changeURLParameter'; + +describe('EditorViewModel.js', () => { + it('should load the document if opened with an ID in the "editor" url parameter', async () => { + changeURLParameter('editor', '123'); + const vm = new EditorViewModel({}); + const spy = jest.spyOn(vm, 'openNotebook').mockImplementation(() => Promise.resolve()); + + await vm.init(); + + expect(spy).toHaveBeenCalledWith('123'); + }); +}); diff --git a/desktop/core/src/desktop/js/apps/editor/app.js b/desktop/core/src/desktop/js/apps/editor/app.js index 13001901250..917c535c5e5 100644 --- a/desktop/core/src/desktop/js/apps/editor/app.js +++ b/desktop/core/src/desktop/js/apps/editor/app.js @@ -303,18 +303,12 @@ huePubSub.subscribe('app.dom.loaded', app => { if (window.EDITOR_ENABLE_QUERY_SCHEDULING) { viewModel = new EditorViewModel( - window.EDITOR_ID, - window.NOTEBOOKS_JSON, window.EDITOR_VIEW_MODEL_OPTIONS, window.CoordinatorEditorViewModel, window.RunningCoordinatorModel ); } else { - viewModel = new EditorViewModel( - window.EDITOR_ID, - window.NOTEBOOKS_JSON, - window.EDITOR_VIEW_MODEL_OPTIONS - ); + viewModel = new EditorViewModel(window.EDITOR_VIEW_MODEL_OPTIONS); } ko.applyBindings(viewModel, $(window.EDITOR_BINDABLE_ELEMENT)[0]); viewModel.init(); diff --git a/desktop/core/src/desktop/js/apps/notebook/NotebookViewModel.js b/desktop/core/src/desktop/js/apps/notebook/NotebookViewModel.js index 03a128fe77f..5c6ba054eb3 100644 --- a/desktop/core/src/desktop/js/apps/notebook/NotebookViewModel.js +++ b/desktop/core/src/desktop/js/apps/notebook/NotebookViewModel.js @@ -37,7 +37,7 @@ import getParameter from 'utils/url/getParameter'; import UUID from 'utils/string/UUID'; export default class NotebookViewModel { - constructor(editor_id, notebooks, options, CoordinatorEditorViewModel, RunningCoordinatorModel) { + constructor(options, CoordinatorEditorViewModel, RunningCoordinatorModel) { const self = this; self.URLS = { @@ -450,14 +450,13 @@ export default class NotebookViewModel { }; self.init = function () { - if (editor_id) { - self.openNotebook(editor_id); + const editorId = options?.editorId || getParameter('editor'); + if (editorId) { + self.openNotebook(editorId); } else if (getParameter('gist') !== '') { self.newNotebook(getParameter('type')); } else if (getParameter('editor') !== '') { self.openNotebook(getParameter('editor')); - } else if (notebooks.length > 0) { - self.loadNotebook(notebooks[0]); // Old way of loading json for /browse } else if (getParameter('type') !== '') { self.newNotebook(getParameter('type')); } else { diff --git a/desktop/core/src/desktop/js/apps/notebook/NotebookViewModel.test.js b/desktop/core/src/desktop/js/apps/notebook/NotebookViewModel.test.js new file mode 100644 index 00000000000..5791b4df1af --- /dev/null +++ b/desktop/core/src/desktop/js/apps/notebook/NotebookViewModel.test.js @@ -0,0 +1,39 @@ +// Licensed to Cloudera, Inc. under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. Cloudera, Inc. licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import NotebookViewModel from './NotebookViewModel'; +import changeURLParameter from 'utils/url/changeURLParameter'; + +describe('NotebookViewModel.js', () => { + it('should load the document if opened with an ID in the "editor" url parameter', async () => { + changeURLParameter('editor', '123'); + const vm = new NotebookViewModel({}); + const spy = jest.spyOn(vm, 'openNotebook').mockImplementation(() => Promise.resolve()); + + vm.init(); + + expect(spy).toHaveBeenCalledWith('123'); + }); + + it('should load the document if opened with an "editorId" option', async () => { + const vm = new NotebookViewModel({ editorId: '234' }); + const spy = jest.spyOn(vm, 'openNotebook').mockImplementation(() => Promise.resolve()); + + vm.init(); + + expect(spy).toHaveBeenCalledWith('234'); + }); +}); diff --git a/desktop/core/src/desktop/js/apps/notebook/app.js b/desktop/core/src/desktop/js/apps/notebook/app.js index 34d3e4c4f27..78d7377ca88 100644 --- a/desktop/core/src/desktop/js/apps/notebook/app.js +++ b/desktop/core/src/desktop/js/apps/notebook/app.js @@ -542,18 +542,12 @@ huePubSub.subscribe('app.dom.loaded', app => { if (window.EDITOR_ENABLE_QUERY_SCHEDULING) { viewModel = new NotebookViewModel( - window.EDITOR_ID, - window.NOTEBOOKS_JSON, window.EDITOR_VIEW_MODEL_OPTIONS, window.CoordinatorEditorViewModel, window.RunningCoordinatorModel ); } else { - viewModel = new NotebookViewModel( - window.EDITOR_ID, - window.NOTEBOOKS_JSON, - window.EDITOR_VIEW_MODEL_OPTIONS - ); + viewModel = new NotebookViewModel(window.EDITOR_VIEW_MODEL_OPTIONS); } ko.applyBindings(viewModel, $(window.EDITOR_BINDABLE_ELEMENT)[0]); viewModel.init(); diff --git a/desktop/core/src/desktop/js/ko/components/ko.historyPanel.js b/desktop/core/src/desktop/js/ko/components/ko.historyPanel.js index 9fc79798f94..c6538eceacc 100644 --- a/desktop/core/src/desktop/js/ko/components/ko.historyPanel.js +++ b/desktop/core/src/desktop/js/ko/components/ko.historyPanel.js @@ -169,7 +169,7 @@ class HistoryPanel { self.historyPanelVisible(false); }); - self.editorViewModel = new NotebookViewModel(null, '', { + self.editorViewModel = new NotebookViewModel({ user: window.LOGGED_USERNAME, userId: window.LOGGED_USER_ID, languages: [ diff --git a/desktop/libs/indexer/src/indexer/templates/importer.mako b/desktop/libs/indexer/src/indexer/templates/importer.mako index 8271880c030..dc7dc6c4a23 100644 --- a/desktop/libs/indexer/src/indexer/templates/importer.mako +++ b/desktop/libs/indexer/src/indexer/templates/importer.mako @@ -3030,7 +3030,8 @@ ${ commonheader(_("Importer"), "indexer", user, request, "60px") | n,unicode } self.jobId(resp.handle.id); $('#importerNotebook').html($('#importerNotebook-progress').html()); - self.editorVM = new window.NotebookViewModel(resp.history_uuid, '', { + self.editorVM = new window.NotebookViewModel({ + editorId: resp.history_uuid, user: '${ user.username }', userId: ${ user.id }, languages: [{name: "Java", type: "java"}, {name: "Hive SQL", type: "hive"}], // TODO reuse diff --git a/desktop/libs/indexer/src/indexer/templates/indexer.mako b/desktop/libs/indexer/src/indexer/templates/indexer.mako index e2fc4617282..221564be2a8 100644 --- a/desktop/libs/indexer/src/indexer/templates/indexer.mako +++ b/desktop/libs/indexer/src/indexer/templates/indexer.mako @@ -846,7 +846,8 @@ ${ commonheader(_("Solr Indexes"), "search", user, request, "60px") | n,unicode self.editorId(resp.history_id); self.jobId(resp.handle.id); $('#notebook').html($('#notebook-progress').html()); - self.editorVM = new window.NotebookViewModel(resp.history_uuid, '', { + self.editorVM = new window.NotebookViewModel({ + editorId: resp.history_uuid, user: '${ user.username }', userId: ${ user.id }, languages: [{name: "Java SQL", type: "java"}], diff --git a/desktop/libs/notebook/src/notebook/templates/editor2.mako b/desktop/libs/notebook/src/notebook/templates/editor2.mako index 053e82e794b..04c3dbcbab4 100644 --- a/desktop/libs/notebook/src/notebook/templates/editor2.mako +++ b/desktop/libs/notebook/src/notebook/templates/editor2.mako @@ -1290,10 +1290,6 @@ There is no bridge to KO for components using this integration. Example using in window.EDITOR_ENABLE_QUERY_SCHEDULING = '${ ENABLE_QUERY_SCHEDULING.get() }' === 'True'; - window.EDITOR_ID = ${ editor_id or 'null' }; - - window.NOTEBOOKS_JSON = ${ notebooks_json | n,unicode }; - window.SQL_ANALYZER_AUTO_UPLOAD_QUERIES = '${ OPTIMIZER.AUTO_UPLOAD_QUERIES.get() }' === 'True'; window.SQL_ANALYZER_AUTO_UPLOAD_DDL = '${ OPTIMIZER.AUTO_UPLOAD_DDL.get() }' === 'True'; diff --git a/desktop/libs/notebook/src/notebook/templates/editor_components.mako b/desktop/libs/notebook/src/notebook/templates/editor_components.mako index e3c1d556045..9e0c63d57f3 100644 --- a/desktop/libs/notebook/src/notebook/templates/editor_components.mako +++ b/desktop/libs/notebook/src/notebook/templates/editor_components.mako @@ -2266,10 +2266,6 @@ ${ sqlSyntaxDropdown.sqlSyntaxDropdown() } window.EDITOR_ENABLE_QUERY_SCHEDULING = '${ ENABLE_QUERY_SCHEDULING.get() }' === 'True'; - window.EDITOR_ID = ${ editor_id or 'null' }; - - window.NOTEBOOKS_JSON = ${ notebooks_json | n,unicode }; - window.SQL_ANALYZER_AUTO_UPLOAD_QUERIES = '${ OPTIMIZER.AUTO_UPLOAD_QUERIES.get() }' === 'True'; window.SQL_ANALYZER_AUTO_UPLOAD_DDL = '${ OPTIMIZER.AUTO_UPLOAD_DDL.get() }' === 'True'; diff --git a/desktop/libs/notebook/src/notebook/templates/editor_m.mako b/desktop/libs/notebook/src/notebook/templates/editor_m.mako index e8d4d092579..6f495c17aa4 100644 --- a/desktop/libs/notebook/src/notebook/templates/editor_m.mako +++ b/desktop/libs/notebook/src/notebook/templates/editor_m.mako @@ -173,6 +173,7 @@ ${ commonheader_m(editor_type, editor_type, user, request, "68px") | n,unicode } ace.config.set("basePath", "${ static('desktop/js/ace') }"); var VIEW_MODEL_OPTIONS = $.extend(${ options_json | n,unicode }, { + editorId: ${ editor_id or 'null' }, user: '${ user.username }', userId: ${ user.id }, assistAvailable: true, @@ -305,7 +306,7 @@ ${ commonheader_m(editor_type, editor_type, user, request, "68px") | n,unicode } } } - viewModel = new window.NotebookViewModel(${ editor_id or 'null' }, ${ notebooks_json | n,unicode }, VIEW_MODEL_OPTIONS); + viewModel = new window.NotebookViewModel(VIEW_MODEL_OPTIONS); ko.applyBindings(viewModel); viewModel.init(); }); diff --git a/desktop/libs/notebook/src/notebook/templates/notebooks.mako b/desktop/libs/notebook/src/notebook/templates/notebooks.mako deleted file mode 100644 index 0a8669e8bc1..00000000000 --- a/desktop/libs/notebook/src/notebook/templates/notebooks.mako +++ /dev/null @@ -1,302 +0,0 @@ -## Licensed to Cloudera, Inc. under one -## or more contributor license agreements. See the NOTICE file -## distributed with this work for additional information -## regarding copyright ownership. Cloudera, Inc. licenses this file -## to you under the Apache License, Version 2.0 (the -## "License"); you may not use this file except in compliance -## with the License. You may obtain a copy of the License at -## -## http://www.apache.org/licenses/LICENSE-2.0 -## -## Unless required by applicable law or agreed to in writing, software -## distributed under the License is distributed on an "AS IS" BASIS, -## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -## See the License for the specific language governing permissions and -## limitations under the License. - -<%! - import sys - from desktop.views import commonheader, commonfooter, commonimportexport, _ko - if sys.version_info[0] > 2: - from django.utils.translation import gettext as _ - else: - from django.utils.translation import ugettext as _ -%> -<%namespace name="actionbar" file="actionbar.mako" /> - -${ commonheader(_("Notebooks"), "spark", user, request, "60px") | n,unicode } - - - - - -
- -
-
- <%actionbar:render> - <%def name="search()"> - - - - <%def name="actions()"> - - - - <%def name="creation()"> - % if editor_type != 'notebook': - - % else: - - % endif - ${ _('Create') } - - - ${ _('Import') } - - - - - - - - - - - - - - - - - - - - - - - - -
${ _('Name') }${ _('Description') }${ _('Owner') }${ _('Last Modified') }
-
- -
- -
-
- - -
- -
- - - - -
- -${ commonimportexport(request) | n,unicode } - - - - - - -${ commonfooter(request, messages) | n,unicode } diff --git a/desktop/libs/notebook/src/notebook/urls.py b/desktop/libs/notebook/src/notebook/urls.py index 9015ba3d607..c651695fbed 100644 --- a/desktop/libs/notebook/src/notebook/urls.py +++ b/desktop/libs/notebook/src/notebook/urls.py @@ -30,7 +30,6 @@ re_path(r'^$', notebook_views.notebook, name='index'), re_path(r'^notebook/?$', notebook_views.notebook, name='notebook'), re_path(r'^notebook_embeddable/?$', notebook_views.notebook_embeddable, name='notebook_embeddable'), - re_path(r'^notebooks/?$', notebook_views.notebooks, name='notebooks'), re_path(r'^new/?$', notebook_views.new, name='new'), re_path(r'^download/?$', notebook_views.download, name='download'), re_path(r'^install_examples/?$', notebook_views.install_examples, name='install_examples'), diff --git a/desktop/libs/notebook/src/notebook/views.py b/desktop/libs/notebook/src/notebook/views.py index c8f48a4e404..c2a20e9689b 100644 --- a/desktop/libs/notebook/src/notebook/views.py +++ b/desktop/libs/notebook/src/notebook/views.py @@ -15,15 +15,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -from builtins import object import json import logging import sys from django.urls import reverse -from django.db.models import Q from django.shortcuts import redirect -from django.views.decorators.clickjacking import xframe_options_exempt from django.views.decorators.http import require_POST from beeswax.data_export import DOWNLOAD_COOKIE_AGE @@ -34,7 +31,6 @@ from desktop.lib.connectors.models import Connector from desktop.lib.django_util import render, JsonResponse from desktop.lib.exceptions_renderable import PopupException -from desktop.lib.json_utils import JSONEncoderForHTML from desktop.models import Document2, Document, FilesystemException, _get_gist_document from desktop.views import serve_403_error from metadata.conf import has_optimizer, has_catalog, has_workload_analytics @@ -51,39 +47,8 @@ else: from django.utils.translation import ugettext as _ - LOG = logging.getLogger() - -def notebooks(request): - editor_type = request.GET.get('type', 'notebook') - - if editor_type != 'notebook': - if USE_NEW_EDITOR.get(): - notebooks = [doc.to_dict() for doc in Document2.objects.documents( - user=request.user).search_documents(types=['query-%s' % editor_type])] - else: - notebooks = [ - d.content_object.to_dict() - for d in Document.objects.get_docs(request.user, Document2, qfilter=Q(extra__startswith='query')) - if not d.content_object.is_history and d.content_object.type == 'query-' + editor_type - ] - else: - if USE_NEW_EDITOR.get(): - notebooks = [doc.to_dict() for doc in Document2.objects.documents(user=request.user).search_documents(types=['notebook'])] - else: - notebooks = [ - d.content_object.to_dict() - for d in Document.objects.get_docs(request.user, Document2, qfilter=Q(extra='notebook')) - if not d.content_object.is_history - ] - - return render('notebooks.mako', request, { - 'notebooks_json': json.dumps(notebooks, cls=JSONEncoderForHTML), - 'editor_type': editor_type - }) - - @check_document_access_permission def notebook(request, is_embeddable=False): if not SHOW_NOTEBOOKS.get() or not request.user.has_hue_permission(action="access", app='notebook'): @@ -99,8 +64,6 @@ def notebook(request, is_embeddable=False): LOG.exception('Spark is not enabled') return render('notebook.mako', request, { - 'editor_id': notebook_id or None, - 'notebooks_json': '{}', 'is_embeddable': request.GET.get('is_embeddable', False), 'options_json': json.dumps({ 'languages': get_ordered_interpreters(request.user), @@ -148,8 +111,6 @@ def editor(request, is_mobile=False, is_embeddable=False): template = 'editor_m.mako' return render(template, request, { - 'editor_id': editor_id or None, - 'notebooks_json': '{}', 'is_embeddable': request.GET.get('is_embeddable', False), 'editor_type': editor_type, 'options_json': json.dumps({ @@ -208,7 +169,6 @@ def browse(request, database, table, partition_spec=None): compute=compute ) return render('editor2.mako' if ENABLE_HUE_5.get() else 'editor.mako', request, { - 'notebooks_json': json.dumps([editor.get_data()]), 'options_json': json.dumps({ 'languages': get_ordered_interpreters(request.user), 'mode': 'editor', @@ -295,7 +255,6 @@ def execute_and_watch(request): raise PopupException(_('Action %s is unknown') % action) return render('editor2.mako' if ENABLE_HUE_5.get() else 'editor.mako', request, { - 'notebooks_json': json.dumps([editor.get_data()]), 'options_json': json.dumps({ 'languages': [{"name": "%s SQL" % editor_type.title(), "type": editor_type}], 'mode': 'editor',