Browse Source

HUE-1054 [jobsub] Polishing jobsub application

- Edit pathway is not broken... users should be able to go back and forth.
- Fix clone by sharing underlying workflow
- 'Requires some SMTP...' message should be for email action not 'Shell'
- when select a design, 'edit' button should be disabled
- Added a home button to top of editor
- 'FS' --> 'Fs'
- no i18n of 'Fs', 'Email', ... all the action names
- Allow viewing of designs owned by other user
- fix js escaping by removing escaping from title
Abraham Elmahrek 12 years ago
parent
commit
b97c8c7

+ 33 - 21
apps/jobsub/src/jobsub/templates/designs.mako

@@ -45,10 +45,12 @@ ${ commonheader(_('Job Designer'), "jobsub", user, "60px") | n,unicode }
 
   <%actionbar:render>
     <%def name="actions()">
+      <button id="home" class="btn" title="${_('Home')}"><i class="icon-share"></i> ${_('Home')}</button>
+      &nbsp;
       <button id="submit-design" class="btn" title="${_('Submit')}" data-bind="enable: selectedDesignObjects().length == 1"><i class="icon-play"></i> ${_('Submit')}</button>
-      <button id="edit-design" class="btn" title="${_('Edit')}" data-bind="enable: selectedDesignObjects().length == 1"><i class="icon-pencil"></i> ${_('Edit')}</button>
+      <button id="edit-design" class="btn" title="${_('Edit')}" data-bind="enable: selectedDesignObjects().length == 1 && window.location.hash.substring(0,12) != '#edit-design'"><i class="icon-pencil"></i> ${_('Edit')}</button>
       <button id="delete-designs" class="btn" title="${_('Delete')}" data-bind="enable: selectedDesignObjects().length > 0"><i class="icon-trash"></i> ${_('Delete')}</button>
-      <button id="clone-designs" class="btn" title="${_('Clone')}" data-bind="click: cloneDesigns, enable: selectedDesignObjects().length > 0"><i class="icon-share"></i> ${_('Clone')}</button>
+      <button id="clone-designs" class="btn" title="${_('Clone')}" data-bind="enable: selectedDesignObjects().length > 0"><i class="icon-share"></i> ${_('Clone')}</button>
     </%def>
 
     <%def name="creation()">
@@ -59,37 +61,37 @@ ${ commonheader(_('Job Designer'), "jobsub", user, "60px") | n,unicode }
           </a>
           <ul class="dropdown-menu" style="top: auto">
             <li>
-              <a href="#new-design/mapreduce" class="new-node-link" title="${_('Create MapReduce Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('MapReduce')}</a>
+              <a href="#new-design/mapreduce" class="new-node-link" title="${_('Create MapReduce Design')}" rel="tooltip"><i class="icon-plus-sign"></i> MapReduce</a>
             </li>
             <li>
-              <a href="#new-design/java" class="new-node-link" title="${_('Create Java Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('Java')}</a>
+              <a href="#new-design/java" class="new-node-link" title="${_('Create Java Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Java</a>
             </li>
             <li>
-              <a href="#new-design/streaming" class="new-node-link" title="${_('Create Streaming Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('Streaming')}</a>
+              <a href="#new-design/streaming" class="new-node-link" title="${_('Create Streaming Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Streaming</a>
             </li>
             <li>
-              <a href="#new-design/hive" class="new-node-link" title="${_('Create Hive Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('Hive')}</a>
+              <a href="#new-design/hive" class="new-node-link" title="${_('Create Hive Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Hive</a>
             </li>
             <li>
-              <a href="#new-design/pig" class="new-node-link" title="${_('Create Pig Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('Pig')}</a>
+              <a href="#new-design/pig" class="new-node-link" title="${_('Create Pig Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Pig</a>
             </li>
             <li>
-              <a href="#new-design/sqoop" class="new-node-link" title="${_('Create Sqoop Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('Sqoop')}</a>
+              <a href="#new-design/sqoop" class="new-node-link" title="${_('Create Sqoop Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Sqoop</a>
             </li>
             <li>
-              <a href="#new-design/fs" class="new-node-link" title="${_('Create FS Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('FS')}</a>
+              <a href="#new-design/fs" class="new-node-link" title="${_('Create Fs Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Fs</a>
             </li>
             <li>
-              <a href="#new-design/ssh" class="new-node-link" title="${_('Create SSH Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('SSH')}</a>
+              <a href="#new-design/ssh" class="new-node-link" title="${_('Create Ssh Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Ssh</a>
             </li>
             <li>
-              <a href="#new-design/shell" class="new-node-link" title="${_('Create Shell Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('Shell')}</a>
+              <a href="#new-design/shell" class="new-node-link" title="${_('Create Shell Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Shell</a>
             </li>
             <li>
-              <a href="#new-design/email" class="new-node-link" title="${_('Create Email Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('Email')}</a>
+              <a href="#new-design/email" class="new-node-link" title="${_('Create Email Design')}" rel="tooltip"><i class="icon-plus-sign"></i> Email</a>
             </li>
             <li>
-              <a href="#new-design/distcp" class="new-node-link" title="${_('Create DistCP Design')}" rel="tooltip"><i class="icon-plus-sign"></i> ${_('DistCP')}</a>
+              <a href="#new-design/distcp" class="new-node-link" title="${_('Create DistCp Design')}" rel="tooltip"><i class="icon-plus-sign"></i> DistCp</a>
             </li>
           </ul>
         </div>
@@ -228,7 +230,8 @@ $(document).ready(function() {
   // This global context may need to be updated.
   var global_action_context = {
     alert: "${_('You can parameterize the values, using')} <code>$myVar</code> ${_('or')} <code>${"${"}myVar}</code>. ${_('When the design is submitted, you will be prompted for the actual value of ')}<code>myVar</code>.",
-    shell_alert: "${_('Requires some SMTP server configuration to be present (in oozie-site.xml).')}",
+    paths_alert: "${_('All the paths are relative to the deployment directory. They can be absolute but this is not recommended.')}",
+    smtp_alert: "${_('Requires some SMTP server configuration to be present (in oozie-site.xml).')}",
     ssh_alert: "${_('The ssh server requires passwordless login.')}",
     save: {
       name: "${_('Save')}",
@@ -643,14 +646,17 @@ $(document).ready(function() {
         return;
       }
 
-      if (!designObject.design().editable()) {
-        routie('list-designs');
-        $.jHueNotify.error("${ _('Design is not editable. It is owned by user ') }" + designObject.design().owner() + '.');
-        return;
-      }
-
       // Show section only after we've finished the edit design process.
       $(document).one('edit.design', function() {
+        if (designObject.design().editable()) {
+          $('#design input').removeAttr('disabled');
+          $('#design textarea').removeAttr('disabled');
+          $('#design button').removeAttr('disabled');
+        } else {
+          $('#design input').attr('disabled', 'disabled');
+          $('#design textarea').attr('disabled', 'disabled');
+          $('#design button').attr('disabled', 'disabled');
+        }
         showSection('design');
       });
 
@@ -679,11 +685,17 @@ $(document).ready(function() {
     );
   });
   $('#edit-design').click(function() {
-    window.location = '#edit-design/' + designs.selectedIndex();
+    routie('edit-design/' + designs.selectedIndex());
   });
   $('#delete-designs').click(function() {
     $('#deleteWf').modal('show');
   });
+  $('#clone-designs').click(function() {
+    designs.cloneDesigns();
+  });
+  $('#home').click(function() {
+    routie('list-designs');
+  })
 });
 </script>
 

+ 10 - 7
apps/jobsub/src/jobsub/views.py

@@ -55,6 +55,7 @@ from jobsub.management.commands import jobsub_setup
 
 LOG = logging.getLogger(__name__)
 
+SKIP_ESCAPE = ('name', 'owner')
 
 def list_designs(request):
   '''
@@ -76,8 +77,9 @@ def list_designs(request):
   for design in data:
       ko_design = {
           'id': design.id,
-          'owner': escapejs(design.owner.username),
-          'name': escapejs(design.name),
+          'owner': design.owner.username,
+          # Design name is validated by workflow and node forms.
+          'name': design.name,
           'description': escapejs(design.description),
           'node_type': design.start.get_child('to').node_type,
           'last_modified': py_time.mktime(design.last_modified.timetuple()),
@@ -91,8 +93,7 @@ def list_designs(request):
     return render("designs.mako", request, {
       'currentuser': request.user,
       'owner': owner,
-      'name': name,
-      'designs': json.dumps(designs)
+      'name': name
     })
 
 def _get_design(design_id):
@@ -130,14 +131,14 @@ def delete_design(request, design_id):
 
 def get_design(request, design_id):
   workflow = _get_design(design_id)
-  _check_permission(request, workflow.owner.username, _("Access denied: edit design %(id)s.") % {'id': design_id})
   node = workflow.start.get_child('to')
   node_dict = model_to_dict(node)
   node_dict['id'] = design_id
   for key in node_dict:
     if key not in JSON_FIELDS:
-      node_dict[key] = escapejs(node_dict[key])
-  node_dict['editable'] = True
+      if key not in SKIP_ESCAPE:
+        node_dict[key] = escapejs(node_dict[key])
+  node_dict['editable'] = workflow.owner.id == request.user.id
   return render_json(node_dict);
 
 
@@ -185,6 +186,8 @@ def new_design(request, node_type):
     raise StructuredException(code="INVALID_REQUEST_ERROR", message=_('Error saving design'), data={'errors': form.errors}, error_code=400)
 
   workflow.managed = False
+  # Every one should be able to execute and clone a design.
+  workflow.is_shared = True
   workflow.save()
   Workflow.objects.initialize(workflow, request.fs)
   action = form.save(commit=False)

+ 8 - 2
apps/jobsub/static/js/jobsub.ko.js

@@ -80,6 +80,10 @@ var Design = (function($, ko, NodeFields) {
         });
       }
 
+      if (!('editable' in self)) {
+        self.editable = ko.observable(false);
+      }
+
       $(document).trigger('initialize.design', [options, self]);
     },
     request: function(url, options) {
@@ -311,6 +315,8 @@ var Designs = (function($, ko, NodeModelChooser) {
       // Reversing the order of the next two statements may cause KO to break.
       self.temporary().template(node_type);
       self.temporary().design(design);
+      // Do not do any thing with any other design.
+      self.deselectAll();
       $(document).trigger('new.design', [design]);
     },
     saveDesign: function(data, event) {
@@ -338,13 +344,13 @@ var Designs = (function($, ko, NodeModelChooser) {
             design.initialize({model: data});
             self.temporary().design(design);
             self.temporary().template(self.selectedDesignObject().template());
-            $(document).trigger('edit.design', [design, data]);
+            $(document).trigger('edit.design', [design]);
           });
           design.load();
         } else {
           self.temporary().design(design);
           self.temporary().template(self.selectedDesignObject().template());
-          $(document).trigger('edit.design', [design, data]);
+          $(document).trigger('edit.design', [design]);
         }
       }
     },

+ 1 - 0
apps/jobsub/static/templates/actions/email.html

@@ -26,6 +26,7 @@
 
       <div class="control-group">
         <p class="alert alert-info">{{ alert }}</p>
+        <p class="alert alert-info">{{ smtp_alert }}</p>
       </div>
 
       <div class="control-group" rel="popover" data-original-title="{{ to.name }}" data-content="{{ to.popover }}" data-bind="attr: {'class': ( errors.to().length > 0 ) ? 'control-group error' : 'control-group'}">

+ 1 - 1
apps/jobsub/static/templates/actions/shell.html

@@ -26,7 +26,7 @@
 
       <div class="control-group">
         <p class="alert alert-info">{{ alert }}</p>
-        <p class="alert alert-warn">{{ shell_alert }}</p>
+        <p class="alert alert-info">{{ paths_alert }}</p>
       </div>
 
       <div class="control-group" rel="popover" data-original-title="{{ command.name }}" data-content="{{ command.popover }}" data-bind="attr: {'class': ( errors.command().length > 0 ) ? 'control-group error' : 'control-group'}">