浏览代码

HUE-6012 [metadata] Skeleton to port dropping tables into single page app

Romain Rigaux 8 年之前
父节点
当前提交
254283f

+ 9 - 5
apps/beeswax/src/beeswax/server/dbms.py

@@ -558,7 +558,7 @@ class HiveServer2Dbms(object):
     return self.execute_query(query, design)
     return self.execute_query(query, design)
 
 
 
 
-  def drop_tables(self, database, tables, design, skip_trash=False):
+  def drop_tables(self, database, tables, design, skip_trash=False, generate_ddl_only=False):
     hql = []
     hql = []
 
 
     for table in tables:
     for table in tables:
@@ -570,10 +570,14 @@ class HiveServer2Dbms(object):
         hql.append(drop_query)
         hql.append(drop_query)
 
 
     query = hql_query(';'.join(hql), database)
     query = hql_query(';'.join(hql), database)
-    design.data = query.dumps()
-    design.save()
-
-    return self.execute_query(query, design)
+    
+    if generate_ddl_only:
+      return query
+    else:   
+      design.data = query.dumps()
+      design.save()
+  
+      return self.execute_query(query, design)
 
 
 
 
   def drop_database(self, database):
   def drop_database(self, database):

+ 16 - 0
apps/metastore/src/metastore/static/metastore/js/metastore.ko.js

@@ -539,6 +539,22 @@ var MetastoreViewModel = (function () {
       })
       })
     };
     };
 
 
+    self.drop = function () {
+      $.post('/tables/drop/' + self.database.name, {
+    	table_selection: ko.mapping.toJSON([self.name]),
+    	skip_trash: 'off',
+    	is_embeddable: true
+      }, function(data) {
+        if (data && data.status == 0) {
+          self.navigatorStats().tags.push(self.addTagName());
+          self.addTagName('');
+          self.showAddTagName(false);
+        } else {
+          $(document).trigger("error", data.message);
+        }
+      });
+    };
+
     self.addTags = function () {
     self.addTags = function () {
       $.post('/metadata/api/navigator/add_tags', {
       $.post('/metadata/api/navigator/add_tags', {
         id: ko.mapping.toJSON(self.navigatorStats().identity),
         id: ko.mapping.toJSON(self.navigatorStats().identity),

+ 4 - 0
apps/metastore/src/metastore/templates/metastore.mako

@@ -557,6 +557,7 @@ ${ components.menubar() }
     % if has_write_access:
     % if has_write_access:
       % if is_embeddable:
       % if is_embeddable:
         <a class="inactive-action margin-left-10" data-bind="tooltip: { placement: 'bottom', delay: 750 }, click: function () { onePageViewModel.currentApp('importer') }" title="${_('Create a new database')}"><i class="fa fa-plus"></i></a>
         <a class="inactive-action margin-left-10" data-bind="tooltip: { placement: 'bottom', delay: 750 }, click: function () { onePageViewModel.currentApp('importer') }" title="${_('Create a new database')}"><i class="fa fa-plus"></i></a>
+        ## huePubSub.publish('open.app', {'app': 'importer', 'prefill': {'source_type: 'all', 'target_type': 'table'}, 'database': 'huedb'})
       % elif ENABLE_NEW_CREATE_TABLE.get():
       % elif ENABLE_NEW_CREATE_TABLE.get():
         <a class="inactive-action margin-left-10" data-bind="tooltip: { placement: 'bottom', delay: 750 }, attr: { 'href': '${ url('indexer:importer_prefill', source_type='manual', target_type='database') }' }" title="${_('Create a new database')}"><i class="fa fa-plus"></i></a>
         <a class="inactive-action margin-left-10" data-bind="tooltip: { placement: 'bottom', delay: 750 }, attr: { 'href': '${ url('indexer:importer_prefill', source_type='manual', target_type='database') }' }" title="${_('Create a new database')}"><i class="fa fa-plus"></i></a>
       % else:
       % else:
@@ -592,15 +593,18 @@ ${ components.menubar() }
       <a class="inactive-action" data-bind="tooltip: { placement: 'bottom', delay: 750 }, attr: { 'href': '/metastore/table/'+ database.name + '/' + name + '/read' }" title="${_('Browse Data')}"><i class="fa fa-play fa-fw"></i></a>
       <a class="inactive-action" data-bind="tooltip: { placement: 'bottom', delay: 750 }, attr: { 'href': '/metastore/table/'+ database.name + '/' + name + '/read' }" title="${_('Browse Data')}"><i class="fa fa-play fa-fw"></i></a>
     % endif
     % endif
     <a class="inactive-action" href="javascript:void(0)" data-bind="tooltip: { placement: 'bottom', delay: 750 }, click: function () { huePubSub.publish('assist.db.refresh', { sourceType: 'hive' }); }" title="${_('Refresh')}"><i class="pointer fa fa-refresh fa-fw" data-bind="css: { 'fa-spin blue' : $root.reloading }"></i></a>
     <a class="inactive-action" href="javascript:void(0)" data-bind="tooltip: { placement: 'bottom', delay: 750 }, click: function () { huePubSub.publish('assist.db.refresh', { sourceType: 'hive' }); }" title="${_('Refresh')}"><i class="pointer fa fa-refresh fa-fw" data-bind="css: { 'fa-spin blue' : $root.reloading }"></i></a>
+    % if user.is_superuser:
     <!-- ko if: $root.optimizerEnabled() && $root.database().table().optimizerStats() -->
     <!-- ko if: $root.optimizerEnabled() && $root.database().table().optimizerStats() -->
       <a class="inactive-action" title="${_('View in Optimizer')}" data-bind="tooltip: { placement: 'bottom', delay: 750 }, attr: { 'href': $root.optimizerUrl() + '#/table/' + $root.database().table().optimizerStats().eid }" target="_blank"><i class="fa fa-skyatlas fa-fw"></i></a>
       <a class="inactive-action" title="${_('View in Optimizer')}" data-bind="tooltip: { placement: 'bottom', delay: 750 }, attr: { 'href': $root.optimizerUrl() + '#/table/' + $root.database().table().optimizerStats().eid }" target="_blank"><i class="fa fa-skyatlas fa-fw"></i></a>
     <!-- /ko -->
     <!-- /ko -->
+    % endif
 ##     <a class="inactive-action margin-left-10" href="javascript: void(0);"><i class="fa fa-star"></i></a>
 ##     <a class="inactive-action margin-left-10" href="javascript: void(0);"><i class="fa fa-star"></i></a>
     % if has_write_access:
     % if has_write_access:
       <a class="inactive-action" href="#" data-bind="tooltip: { placement: 'bottom', delay: 750 }, click: showImportData, visible: tableDetails() && ! tableDetails().is_view" title="${_('Import Data')}"><i class="fa fa-upload fa-fw"></i></a>
       <a class="inactive-action" href="#" data-bind="tooltip: { placement: 'bottom', delay: 750 }, click: showImportData, visible: tableDetails() && ! tableDetails().is_view" title="${_('Import Data')}"><i class="fa fa-upload fa-fw"></i></a>
     % endif
     % endif
     % if has_write_access:
     % if has_write_access:
       <a class="inactive-action" href="#dropSingleTable" data-toggle="modal" data-bind="tooltip: { placement: 'bottom', delay: 750 }, attr: { 'title' : tableDetails() && tableDetails().is_view ? '${_('Drop View')}' : '${_('Drop Table')}' }"><i class="fa fa-times fa-fw"></i></a>
       <a class="inactive-action" href="#dropSingleTable" data-toggle="modal" data-bind="tooltip: { placement: 'bottom', delay: 750 }, attr: { 'title' : tableDetails() && tableDetails().is_view ? '${_('Drop View')}' : '${_('Drop Table')}' }"><i class="fa fa-times fa-fw"></i></a>
+      ## 
     % endif
     % endif
     <!-- ko if: tableDetails() -->
     <!-- ko if: tableDetails() -->
       <!-- ko if: tableDetails().partition_keys.length -->
       <!-- ko if: tableDetails().partition_keys.length -->

+ 27 - 13
apps/metastore/src/metastore/views.py

@@ -31,16 +31,18 @@ from desktop.lib.django_util import JsonResponse, render
 from desktop.lib.exceptions_renderable import PopupException
 from desktop.lib.exceptions_renderable import PopupException
 from desktop.models import Document2
 from desktop.models import Document2
 
 
-from metadata.conf import has_optimizer, has_navigator, get_optimizer_url, get_navigator_url
-
 from beeswax.design import hql_query
 from beeswax.design import hql_query
 from beeswax.models import SavedQuery
 from beeswax.models import SavedQuery
 from beeswax.server import dbms
 from beeswax.server import dbms
 from beeswax.server.dbms import get_query_server_config
 from beeswax.server.dbms import get_query_server_config
 from filebrowser.views import location_to_url
 from filebrowser.views import location_to_url
+from metadata.conf import has_optimizer, has_navigator, get_optimizer_url, get_navigator_url
+from notebook.connectors.base import Notebook
+from notebook.models import make_notebook
+
 from metastore.forms import LoadDataForm, DbForm
 from metastore.forms import LoadDataForm, DbForm
 from metastore.settings import DJANGO_APPS
 from metastore.settings import DJANGO_APPS
-from notebook.connectors.base import Notebook
+
 
 
 
 
 LOG = logging.getLogger(__name__)
 LOG = logging.getLogger(__name__)
@@ -371,16 +373,28 @@ def drop_table(request, database):
     tables = request.POST.getlist('table_selection')
     tables = request.POST.getlist('table_selection')
     tables_objects = [db.get_table(database, table) for table in tables]
     tables_objects = [db.get_table(database, table) for table in tables]
     skip_trash = request.POST.get('skip_trash') == 'on'
     skip_trash = request.POST.get('skip_trash') == 'on'
-    try:
-      # Can't be simpler without an important refactoring
-      design = SavedQuery.create_empty(app_name='beeswax', owner=request.user, data=hql_query('').dumps())
-      query_history = db.drop_tables(database, tables_objects, design, skip_trash=skip_trash)
-      url = reverse('beeswax:watch_query_history', kwargs={'query_history_id': query_history.id}) + '?on_success_url=' + reverse('metastore:show_tables', kwargs={'database': database})
-      return redirect(url)
-    except Exception, ex:
-      error_message, log = dbms.expand_exception(ex, db)
-      error = _("Failed to remove %(tables)s.  Error: %(error)s") % {'tables': ','.join(tables), 'error': error_message}
-      raise PopupException(error, title=_("Hive Error"), detail=log)
+    
+    if request.POST.get('is_embeddable'):
+      sql = db.drop_tables(database, tables_objects, design=None, skip_trash=skip_trash, generate_ddl_only=True)
+      return make_notebook(
+          name='Execute and watch',
+          editor_type='hive',
+          statement=sql.strip(),
+          status='ready',
+          database=database,
+          on_success_url=json.dumps({'app': 'metastore', 'path': 'table/%(database)s' % {'database': database}})
+      )
+    else:    
+      try:
+        # Can't be simpler without an important refactoring
+        design = SavedQuery.create_empty(app_name='beeswax', owner=request.user, data=hql_query('').dumps())
+        query_history = db.drop_tables(database, tables_objects, design, skip_trash=skip_trash)
+        url = reverse('beeswax:watch_query_history', kwargs={'query_history_id': query_history.id}) + '?on_success_url=' + reverse('metastore:show_tables', kwargs={'database': database})
+        return redirect(url)
+      except Exception, ex:
+        error_message, log = dbms.expand_exception(ex, db)
+        error = _("Failed to remove %(tables)s.  Error: %(error)s") % {'tables': ','.join(tables), 'error': error_message}
+        raise PopupException(error, title=_("Hive Error"), detail=log)
   else:
   else:
     title = _("Do you really want to delete the table(s)?")
     title = _("Do you really want to delete the table(s)?")
     return render('confirm.mako', request, {'url': request.path, 'title': title})
     return render('confirm.mako', request, {'url': request.path, 'title': title})

+ 6 - 1
desktop/core/src/desktop/templates/responsive.mako

@@ -1062,9 +1062,14 @@ ${ assist.assistPanel() }
             } else if (val == 'available') {
             } else if (val == 'available') {
               var snippet = notebook.snippets()[0];
               var snippet = notebook.snippets()[0];
               if (! snippet.result.handle().has_more_statements) {
               if (! snippet.result.handle().has_more_statements) {
+                // TODO: Show finish notification and clicking on it does onSuccessUrl
+                // or if still on initial spinner we redirect automatically to onSuccessUrl
                 if (notebook.onSuccessUrl()) {
                 if (notebook.onSuccessUrl()) {
                   // TODO: If we are in FB directory, also refresh FB dir
                   // TODO: If we are in FB directory, also refresh FB dir
-                  window.location.href = notebook.onSuccessUrl(); // TODO: Show finish notification or if still on initial spinner redirect automatically
+                  window.location.href = notebook.onSuccessUrl();
+                  // TODO: switch to something like params = ko.mapping.fromJSON(notebook.onSuccessUrl())
+                  // {'app': 'metastore', 'path': 'table/%(database)s' % {'database': database}}
+                  // huePubSub.publish('open.app', {'app': 'importer', 'prefill': {'source_type: 'all', 'target_type': 'table'}, 'database': 'huedb'})
                 }
                 }
               } else { // Perform last DROP statement execute
               } else { // Perform last DROP statement execute
                 snippet.execute();
                 snippet.execute();

+ 5 - 1
desktop/libs/indexer/src/indexer/api3.py

@@ -357,7 +357,11 @@ def _create_table_from_a_file(request, source, destination):
     }
     }
 
 
   editor_type = 'impala' if table_format == 'kudu' else 'hive'
   editor_type = 'impala' if table_format == 'kudu' else 'hive'
-  on_success_url = reverse('metastore:describe_table', kwargs={'database': database, 'table': table_name})
+  
+  if request.POST.get('is_embeddable'):
+    on_success_url = json.dumps({'app': 'metastore', 'path': 'table/%(database)s/%(table)s' % {'database': database, 'table': table_name}})
+  else:
+    on_success_url = reverse('metastore:describe_table', kwargs={'database': database, 'table': table_name})
 
 
   return make_notebook(name='Execute and watch', editor_type=editor_type, statement=sql.strip(), status='ready', database=database, on_success_url=on_success_url)
   return make_notebook(name='Execute and watch', editor_type=editor_type, statement=sql.strip(), status='ready', database=database, on_success_url=on_success_url)
 
 

+ 2 - 1
desktop/libs/indexer/src/indexer/templates/importer.mako

@@ -1680,7 +1680,8 @@ ${ assist.assistPanel() }
 % else:
 % else:
         $.post("${ url('indexer:importer_submit') }", {
         $.post("${ url('indexer:importer_submit') }", {
           "source": ko.mapping.toJSON(self.source),
           "source": ko.mapping.toJSON(self.source),
-          "destination": ko.mapping.toJSON(self.destination)
+          "destination": ko.mapping.toJSON(self.destination),
+          "is_embeddable": 'true'
         }, function (resp) {
         }, function (resp) {
           if (resp.history_uuid) {
           if (resp.history_uuid) {
             $.jHueNotify.info("${ _('Task ') }" + resp.history_uuid + "${_(' submitted.') }");
             $.jHueNotify.info("${ _('Task ') }" + resp.history_uuid + "${_(' submitted.') }");

+ 1 - 1
desktop/libs/notebook/src/notebook/static/notebook/js/notebook.ko.js

@@ -1410,7 +1410,7 @@ var EditorViewModel = (function() {
                 }
                 }
               }
               }
               if (! self.result.handle().has_more_statements && vm.successUrl()) {
               if (! self.result.handle().has_more_statements && vm.successUrl()) {
-                window.location.href = vm.successUrl();
+                window.location.href = vm.successUrl(); // Not used anymore in responsive 
               }
               }
             }
             }
             else if (self.status() == 'success') {
             else if (self.status() == 'success') {