소스 검색

HUE-2186 [search] Bulk copy collection templates

collections.ko.js: Fixed assignment of values to self.isLoading to use setter argument instead of assignment operator. (line 114)
admin_collections.mako: Removed list and replaced with table; Added Solr index as well as shared status columns; converted batch process links to buttons; removed trailing spaces
hue3.css: ported inline styles to style sheet
views.py: updated to include solr index and shared status with object sent to admin_collections.mako
search_controller.py (Romain): Updated copy and delete processes to handle multiple collections; removed trailing spaces
Paul McCaughtry 11 년 전
부모
커밋
b05e6d0

+ 6 - 7
apps/search/src/search/search_controller.py

@@ -54,32 +54,32 @@ class SearchController(object):
   def copy_collections(self, collection_ids):
     result = {'status': -1, 'message': ''}
     try:
-      for collection in Collection.objects.filter(id__in=collection_ids): 
+      for collection in Collection.objects.filter(id__in=collection_ids):
         copy = collection
         copy.label += _(' (Copy)')
         copy.id = copy.pk = None
-  
+
         facets = copy.facets
         facets.id = None
         facets.save()
         copy.facets = facets
-  
+
         result_ = copy.result
         result_.id = None
         result_.save()
         copy.result = result_
-  
+
         sorting = copy.sorting
         sorting.id = None
         sorting.save()
         copy.sorting = sorting
-  
+
         copy.save()
       result['status'] = 0
     except Exception, e:
       LOG.warn('Error copying collection: %s' % e)
       result['message'] = unicode(str(e), "utf8")
-      
+
     return result
 
   def is_collection(self, collection_name):
@@ -100,4 +100,3 @@ class SearchController(object):
     except:
       pass
     return indexes + SolrApi(SOLR_URL.get(), self.user).cores().keys()
-

+ 16 - 14
apps/search/src/search/templates/admin_collections.mako

@@ -35,7 +35,6 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
   <h4><a href="">${_('Dashboards')}</a></h4>
 </div>
 
-
 <div class="container-fluid">
   <div class="card">
     <%actionbar:render>
@@ -43,7 +42,11 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
         <input type="text" placeholder="${_('Filter dashboards...')}" class="input-xlarge search-query" id="filterInput" data-bind="visible: collections().length > 0 && !isLoading()">
         &nbsp;
         &nbsp;
-        <a data-bind="visible: collections().length > 0 && !isLoading()" class="btn" href="${ url('search:new_search') }" title="${ _('Create a new dashboard') }"><i class="fa fa-plus-circle"></i> ${ _('Dashboard') }</a>
+        <span>
+          <a class="btn" data-bind="click: $root.copyCollections, clickBubble: false"><i class="fa fa-files-o"></i> ${_('Copy')}</a> &nbsp;&nbsp;
+          <a class="btn" data-bind="click: $root.markManyForDeletion, clickBubble: false"><i class="fa fa-times"></i> ${_('Delete')}</a>
+        </span>
+        <a data-bind="visible: collections().length > 0 && !isLoading()" class="btn pull-right" href="${ url('search:new_search') }" title="${ _('Create a new dashboard') }"><i class="fa fa-plus-circle"></i> ${ _('Dashboard') }</a>
       </%def>
 
       <%def name="creation()">
@@ -61,7 +64,7 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
         </h1>
       </div>
     </div>
-    
+
     <div class="row-fluid" data-bind="visible: isLoading()">
       <div class="span10 offset1 center">
         <i class="fa fa-spinner fa-spin spinner"></i>
@@ -75,21 +78,19 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
             <th>
               <span data-bind="click: toggleSelectAll, css: {'fa-check': !ko.utils.arrayFilter(filteredCollections(), function(collection) {return !collection.selected()}).length}" class="hueCheckbox fa"></span>
             </th>
-            <th width="100%">
-              <span class="coll-heading">${_('Name')}</span>
-              <span class="pull-right collection-actions">
-                <a data-bind="click: $root.copyCollections, clickBubble: false"><i class="fa fa-files-o"></i> ${_('Copy')}</a> &nbsp;&nbsp;
-                <a data-bind="click: $root.markManyForDeletion, clickBubble: false"><i class="fa fa-times"></i> ${_('Delete')}</a>
-              </span>
-            </th>
+            <th>${ _('Name') }</th>
+            <th>${ _('Solr Index') }</th>
+            <th class="center">${ _('Shared') }</th>
           </tr>
         </thead>
         <tbody data-bind="foreach: filteredCollections">
-          <tr class="pointer">
+          <tr>
             <td data-bind="click: $root.toggleCollectionSelect.bind($root), clickBubble: false">
               <span data-bind="css: {'fa-check': $root.filteredCollections()[$index()].selected()}" class="hueCheckbox fa"></span>
             </td>
-            <td data-bind="text: label, click: $root.editCollection" title="${ _('Click to edit') }"></td>
+            <td><a data-bind="text: label, click: $root.editCollection" title="${ _('Click to edit') }" class="pointer"></a></td>
+            <td data-bind="text: name"></td>
+            <td class="center"><span data-bind="css: { 'fa fa-check': enabled }"></span></td>
           </tr>
         </tbody>
       </table>
@@ -122,7 +123,6 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
 
 <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/js/knockout.mapping-2.3.2.js" type="text/javascript" charset="utf-8"></script>
-
 <script src="/search/static/js/collections.ko.js" type="text/javascript" charset="utf-8"></script>
 
 <script>
@@ -130,10 +130,12 @@ ${ commonheader(_('Search'), "search", user, "29px") | n,unicode }
     labels: [],
     listCollectionsUrl: "${ url("search:admin_collections") }?format=json",
     deleteUrl: "${ url("search:admin_collection_delete") }",
-    copyUrl: "${ url("search:admin_collection_copy") }"
+    copyUrl: "${ url("search:admin_collection_copy") }",
+    indexerUrl: "/indexer/#edit/"
   }
 
   var viewModel = new SearchCollectionsModel(appProperties);
+
   ko.applyBindings(viewModel);
 
   $(document).ready(function () {

+ 1 - 0
apps/search/src/search/views.py

@@ -213,6 +213,7 @@ def admin_collections(request, is_redirect=False):
         'id': collection.id,
         'name': collection.name,
         'label': collection.label,
+        'enabled': collection.enabled,
         'isCoreOnly': collection.is_core_only,
         'absoluteUrl': collection.get_absolute_url()
       }

+ 23 - 10
apps/search/static/js/collections.ko.js

@@ -30,6 +30,7 @@ var Collection = function (coll) {
   self.id = ko.observable(coll.id);
   self.name = ko.observable(coll.name);
   self.label = ko.observable(coll.label);
+  self.enabled = ko.observable(coll.enabled);
   self.isCoreOnly = ko.observable(coll.isCoreOnly);
   self.absoluteUrl = ko.observable(coll.absoluteUrl);
   self.selected = ko.observable(false);
@@ -44,7 +45,14 @@ var Collection = function (coll) {
 }
 
 var SearchCollectionsModel = function (props) {
-  var self = this;
+  var cleanCollections,
+    self = this;
+
+  cleanCollections = function () {
+    self.isLoading(true);
+    self.collections.removeAll();
+    self.filteredCollections.removeAll();
+  };
 
   self.LABELS = props.labels;
 
@@ -53,6 +61,7 @@ var SearchCollectionsModel = function (props) {
   self.IMPORT_URL = props.importUrl;
   self.DELETE_URL = props.deleteUrl;
   self.COPY_URL = props.copyUrl;
+  self.INDEXER_URL = props.indexerUrl;
 
   self.isLoading = ko.observable(true);
   self.isLoadingImportables = ko.observable(false);
@@ -64,8 +73,6 @@ var SearchCollectionsModel = function (props) {
   self.importableCollections = ko.observableArray([]);
   self.importableCores = ko.observableArray([]);
 
-  self.collectionToDelete = null; // --> replace by self.selectedCollections()
-
   self.selectedCollections = ko.computed(function () {
     return ko.utils.arrayFilter(self.collections(), function (coll) {
       return coll.selected();
@@ -98,10 +105,14 @@ var SearchCollectionsModel = function (props) {
     }));
   };
 
+  self.viewIndex = function (collection) {
+    var idx = [self.INDEXER_URL, collection.label()].join('');
+    cleanCollections();
+    location.href = idx;
+  };
+
   self.editCollection = function (collection) {
-    self.isLoading(true);
-    self.collections.removeAll();
-    self.filteredCollections.removeAll();
+    cleanCollections();
     location.href = collection.absoluteUrl();
   };
 
@@ -111,9 +122,10 @@ var SearchCollectionsModel = function (props) {
   };
 
   self.deleteCollections = function () {
-    self.isLoading = true;
+    self.isLoading(true);
     $(document).trigger("deleting");
-    $.post(self.DELETE_URL, {
+    $.post(self.DELETE_URL,
+      {
         collections: ko.mapping.toJSON(self.selectedCollections())
       },
       function (data) {
@@ -125,8 +137,9 @@ var SearchCollectionsModel = function (props) {
 
   self.copyCollections = function (collections) {
     $(document).trigger("copying");
-    $.post(self.COPY_URL, {
-    	collections: ko.mapping.toJSON(self.selectedCollections())
+    $.post(self.COPY_URL,
+      {
+        collections: ko.mapping.toJSON(self.selectedCollections())
       }, function (data) {
         self.updateCollections();
       }, "json"

+ 1 - 1
desktop/core/static/css/hue3.css

@@ -1686,7 +1686,7 @@ border-bottom-left-radius: 0px;
 
 .coll-heading {
   position: relative;
-  top: 12px;
+  top: 10px;
 }
 
 .placeholder {