Browse Source

HUE-950 [core] Support Beeswax, Impala and Pig history

Romain Rigaux 12 years ago
parent
commit
97d0613a00

+ 2 - 2
apps/beeswax/src/beeswax/templates/execute.mako

@@ -579,9 +579,9 @@ ${layout.menubar(section='query')}
 
       $("#saveAsNameBtn").click(function () {
         $("<input>").attr("type", "hidden").attr("name", "saveform-name")
-                .attr("value", $("input[name=saveform-name]").data('value')).appendTo($("#advancedSettingsForm"));
+                .attr("value", $("input[name=saveform-name]").val()).appendTo($("#advancedSettingsForm"));
         $("<input>").attr("type", "hidden").attr("name", "saveform-desc")
-                .attr("value", $("input[name=saveform-desc]").data('value')).appendTo($("#advancedSettingsForm"));
+                .attr("value", $("input[name=saveform-desc]").val()).appendTo($("#advancedSettingsForm"));
         checkAndSubmit();
       });
 

+ 15 - 11
apps/beeswax/src/beeswax/views.py

@@ -111,15 +111,17 @@ def save_design(request, form, type, design, explicit_save):
   design.data = new_data
 
   design.save()
-  design.doc.update(name=design.name, description=design.desc)
 
-  Document.objects.link(design, owner=design.owner, name=design.name, extra=design.type)
+  LOG.info('Saved %s design "%s" (id %s) for %s' % (explicit_save and '' or 'auto ', design.name, design.id, design.owner))
 
-  LOG.info('Saved %s design "%s" (id %s) for %s' %
-           (explicit_save and '' or 'auto ', design.name, design.id, design.owner))
-  if explicit_save:
-    messages.info(request, _('Saved design "%(name)s"') % {'name': design.name})
-  # Design may now have a new/different id
+  if design.doc.exists():
+    design.doc.update(name=design.name, description=design.desc)
+  else:
+    Document.objects.link(design, owner=design.owner, extra=design.type, name=design.name, description=design.desc)
+    
+  if design.is_auto:
+    design.doc.get().add_to_history()
+    
   return design
 
 
@@ -400,8 +402,10 @@ def execute_query(request, design_id=None):
 
       if to_submit or to_save or to_saveas or to_explain:
         explicit_save = to_save or to_saveas
+        if explicit_save:
+          request.info(_('Query saved!'))
         design = save_design(request, form, query_type, design, explicit_save)
-        action = reverse(app_name + ':execute_query', kwargs=dict(design_id=design.id))
+        action = reverse(app_name + ':execute_query', kwargs={'design_id': design.id})
 
       if to_explain or to_submit:
         query_str = form.query.cleaned_data["query"]
@@ -438,7 +442,7 @@ def execute_query(request, design_id=None):
     'log': log,
     'autocomplete_base_url': reverse(get_app_name(request) + ':autocomplete', kwargs={}),
     'on_success_url': on_success_url,
-    'can_edit_name': design and not design.is_auto,
+    'can_edit_name': design.id and not design.is_auto,
   })
 
 
@@ -935,7 +939,7 @@ def authorized_get_history(request, query_history_id, owner_only=False, must_exi
       return None
 
   query_history.design.doc.get().can_read_or_exception(request.user)
-  
+
   return query_history
 
 
@@ -951,7 +955,7 @@ def safe_get_design(request, design_type, design_id=None):
     design = authorized_get_design(request, design_id)
 
   if design is None:
-    design = models.SavedQuery(owner=request.user, type=design_type)
+    design = SavedQuery(owner=request.user, type=design_type)
 
   return design
 

+ 4 - 4
apps/jobsub/src/jobsub/views.py

@@ -24,10 +24,6 @@ to the cluster.  A parameterized, submitted job design
 is a "job submission".  Submissions can be "watched".
 """
 
-try:
-  import json
-except ImportError:
-  import simplejson as json
 import logging
 import time as py_time
 
@@ -195,20 +191,24 @@ def save_design(request, design_id):
 def _save_design(design_id, data):
   sanitize_node_dict(data)
   workflow = _get_design(design_id)
+
   workflow.name = data['name']
   workflow.description = data.setdefault('description', '')
   workflow.is_shared = str(data.setdefault('is_shared', 'true')).lower() == "true"
   workflow.parameters = data.setdefault('parameters', '[]')
   node = workflow.start.get_child('to').get_full_node()
   node_id = node.id
+
   for key in data:
     if key in ('is_shared', 'capture_output', 'propagate_configuration'):
       setattr(node, key, str(data[key]).lower() == 'true')
     else:
       setattr(node, key, data[key])
+
   node.id = node_id
   node.pk = node_id
   node.save()
+
   workflow.save()
 
 

+ 3 - 2
apps/pig/src/pig/models.py

@@ -86,9 +86,11 @@ def create_or_update_script(id, name, script, user, parameters, resources, hadoo
   try:
     pig_script = PigScript.objects.get(id=id)
     pig_script.doc.get().can_read_or_exception(user)
-  except:
+  except PigScript.DoesNotExist:
     pig_script = PigScript.objects.create(owner=user, is_design=is_design)
     Doc.objects.link(pig_script, owner=pig_script.owner, name=name)
+    if not is_design:
+      pig_script.doc.get().add_to_history()
 
   pig_script.update_from_dict({
       'name': name,
@@ -104,7 +106,6 @@ def create_or_update_script(id, name, script, user, parameters, resources, hadoo
 def get_scripts(user, is_design=None):
   scripts = []  
   data = Doc.objects.available(PigScript, user)
-  print data
 
   if is_design is not None:
     data = [job for job in data if job.is_design]

+ 32 - 15
desktop/core/src/desktop/models.py

@@ -55,6 +55,13 @@ class Settings(models.Model):
 
 class DocumentTagManager(models.Manager):
 
+  def create_tag(self, owner, tag_name):
+    if tag_name in DocumentTag.RESERVED:
+      raise Exception(_("Can't add %s: it is a reserved tag.") % tag_name)
+    else:
+      tag, created = DocumentTag.objects.create(tag=tag_name, owner=owner)
+      return tag
+
   def get_default_tag(self, user):
     tag, created = DocumentTag.objects.get_or_create(owner=user, tag=DocumentTag.DEFAULT)
     return tag
@@ -63,15 +70,15 @@ class DocumentTagManager(models.Manager):
     tag, created = DocumentTag.objects.get_or_create(owner=user, tag=DocumentTag.TRASH)
     return tag
 
-  def create_tag(self, owner, tag_name):
-    tag = DocumentTag.objects.create(tag=tag_name, owner=owner)
+  def get_history_tag(self, user):
+    tag, created = DocumentTag.objects.get_or_create(owner=user, tag=DocumentTag.HISTORY)
     return tag
 
   def tag(self, owner, doc_id, tag_name='', tag_id=None):
     try:
       tag = DocumentTag.objects.get(id=tag_id, owner=owner)
-      if tag == DocumentTag.objects.get_trash_tag(owner):
-        raise Exception(_("Can't add trash tag. Please trash the document from instead."))
+      if tag.tag in DocumentTag.RESERVED:
+        raise Exception(_("Can't add %s: it is a reserved tag.") % tag)
     except DocumentTag.DoesNotExist:
       tag = DocumentTag.objects.create(tag=tag_name, owner=owner)
 
@@ -82,18 +89,17 @@ class DocumentTagManager(models.Manager):
   def untag(self, tag_id, owner, doc_id):
     tag = DocumentTag.objects.get(id=tag_id, owner=owner)
 
-    if tag == DocumentTag.get_trash_tag(owner):
-      raise Exception(_("Can't remove trash tag. Please restore the document from the trash instead."))
+    if tag.tag in DocumentTag.RESERVED:
+      raise Exception(_("Can't remove %s: it is a reserved tag.") % tag)
 
     doc = Document.objects.get_doc(doc_id, owner=owner)
     doc.remove(tag)
 
   def delete_tag(self, tag_id, owner):
     tag = DocumentTag.objects.get(id=tag_id, owner=owner)
-    default_tag = DocumentTag.objects.get_default_tag(user=owner)
 
-    if tag in (default_tag, DocumentTag.objects.get_trash_tag(owner)):
-      raise Exception(_("Can't remove default or trash tag. Please restore the document from the trash instead."))
+    if tag.tag in DocumentTag.RESERVED:
+      raise Exception(_("Can't remove %s: it is a reserved tag.") % tag)
     else:
       tag.delete()
 
@@ -104,23 +110,29 @@ class DocumentTagManager(models.Manager):
     doc = Document.objects.get_doc(doc_id, owner)
 
     for tag in doc.tags.all():
-      if tag.tag not in (DocumentTag.TRASH, DocumentTag.DEFAULT):
+      if tag.tag not in DocumentTag.RESERVED:
         doc.remove(tag)
 
     for tag_id in tag_ids:
       tag = DocumentTag.objects.get(id=tag_id, owner=owner)
-      if tag.tag != DocumentTag.TRASH:
+      if tag.tag not in DocumentTag.RESERVED:
         doc.add_tag(tag)
 
     return doc
 
 
 class DocumentTag(models.Model):
+  """
+  Reserved tags can't be manually removed by the user.
+  """
   owner = models.ForeignKey(auth_models.User, db_index=True)
   tag = models.SlugField()
 
-  DEFAULT = 'default'
-  TRASH = 'trash'
+  DEFAULT = 'default' # Always there
+  TRASH = 'trash' # There when the document is trashed
+  HISTORY = 'history' # There when the document is a submission history
+  
+  RESERVED = (DEFAULT, TRASH, HISTORY)
 
   objects = DocumentTagManager()
   unique_together = ('owner', 'tag')
@@ -154,9 +166,10 @@ class DocumentManager(models.Manager):
 
   def available_docs(self, model_class, user):
     ct = ContentType.objects.get_for_model(model_class)
-    tag = DocumentTag.objects.get_trash_tag(user=user)
+    trash = DocumentTag.objects.get_trash_tag(user=user)
+    history = DocumentTag.objects.get_history_tag(user=user)
 
-    return Document.objects.get_docs(user).filter(content_type=ct).exclude(tags__in=[tag]).order_by('-last_modified')
+    return Document.objects.get_docs(user).filter(content_type=ct).exclude(tags__in=[trash, history]).order_by('-last_modified')
 
   def available(self, model_class, user):
     docs = self.available_docs(model_class, user)
@@ -278,6 +291,10 @@ class Document(models.Model):
     tag = DocumentTag.objects.get_trash_tag(user=self.owner)
     self.tags.remove(tag)
 
+  def add_to_history(self):
+    tag = DocumentTag.objects.get_history_tag(user=self.owner)
+    self.tags.add(tag)
+
   def is_accessible(self, user):
     return user.is_superuser or self.owner == user or Document.objects.get_doc(self.id, user)
 

+ 6 - 5
desktop/core/src/desktop/templates/home.mako

@@ -118,8 +118,9 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
                 % endif
               </ul>
            </li>
-           <li class="viewTrash"><a href="javascript:void(0)"><i class="icon-trash"></i> ${_('View Trash')} <span id="trashCounter" class="badge pull-right">0</span></a></li>
-          <li class="nav-header tag-header">${_('Tags')} <div id="editTags" style="display: inline;cursor: pointer;margin-left: 6px"><i class="icon-edit"></i></div> </li>
+           <li class="viewTrash"><a href="javascript:void(0)"><i class="icon-trash"></i> ${_('Trash')} <span id="trashCounter" class="badge pull-right">0</span></a></li>
+           <li class="viewTrash"><a href="javascript:void(0)"><i class="icon-th-list"></i> ${_('History')} <span id="trashCounter" class="badge pull-right">0</span></a></li>
+          <li class="nav-header tag-header">${_('Tags')} <div id="editTags" style="display: inline;cursor: pointer;margin-left: 6px"><i class="icon-tags"></i></div> </li>
           % for tag in tags:
             %if tag.tag != "trash":
             <li class="toggleTag white" data-tag="${ tag.tag }"><div class="hueCheckbox pull-left"></div>${ tag.tag }</li>
@@ -147,7 +148,7 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
                 <th>${_('Tags')}</th>
                 <th>${_('Owner')}</th>
                 <th>${_('Last Modified')}</th>
-                <th>&nbsp;</th>
+                <th>${_('Sharing')}</th>
               </tr>
             </thead>
           </table>
@@ -212,7 +213,7 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
   </div>
   <div class="modal-body">
     <p>
-      <h4 id="documentShareNoShare" class="muted" style="margin-top:0px">${_('No shares yet.')}</h4>
+      <h4 id="documentShareNoShare" class="muted" style="margin-top:0px">${_('Not shared yet.')}</h4>
       <ul id="documentShareList" class="unstyled inline airy hide">
       </ul>
       <div class="clearfix"></div>
@@ -226,7 +227,7 @@ ${ commonheader(_('Welcome Home'), "home", user) | n,unicode }
   </div>
   <div class="modal-footer">
     <a href="#" data-dismiss="modal" class="btn">${_('Cancel')}</a>
-    <a id="saveDocumentShare" href="#" class="btn btn-primary disable-feedback">${_('Share it')}</a>
+    <a id="saveDocumentShare" href="#" class="btn btn-primary disable-feedback">${_('Update')}</a>
   </div>
 </div>
 

+ 1 - 1
desktop/core/src/desktop/views.py

@@ -333,7 +333,7 @@ def dump_config(request):
   if request.GET.get("private"):
     show_private = True
 
-  apps = sorted(appmanager.DESKTOP_MODULES, key=lambda app: app.menu_index)
+  apps = sorted(appmanager.DESKTOP_MODULES, key=lambda app: app.name)
   apps_names = [app.name for app in apps]
   top_level = sorted(GLOBAL_CONFIG.get().values(), key=lambda obj: apps_names.index(obj.config.key))