web staff : grids
authorBill Erickson <berick@esilibrary.com>
Fri, 28 Mar 2014 20:56:10 +0000 (16:56 -0400)
committerBill Erickson <berick@esilibrary.com>
Fri, 28 Mar 2014 20:56:10 +0000 (16:56 -0400)
Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/templates/staff/css/style.css.tt2
Open-ILS/src/templates/staff/parts/t_autogrid.tt2
Open-ILS/src/templates/staff/t_base_js.tt2
Open-ILS/web/js/ui/default/staff/services/grid.js
Open-ILS/web/js/ui/default/staff/services/list.js

index 8ed9c70..16ddf28 100644 (file)
@@ -91,6 +91,11 @@ table.list tr.selected td {
  * Grid
  * ---------------------------------------------------------------------- */
 
+.eg-grid-primary-label {
+  font-weight: bold;
+  font-size: 120%;
+}
+
 /* odd/even row styling */
 .eg-grid-content-body > div:nth-child(odd):not(.eg-grid-row-selected) {
   background-color: rgb(248, 248, 248);
@@ -108,10 +113,8 @@ table.list tr.selected td {
 
 .eg-grid-action-row {
   border: none;
-  justify-content:flex-end; /* i.e. float right */
-
   /* margin should not have to be this large; something's up */
-  margin-bottom: 15px;
+  margin-bottom: 12px;
 }
 
 .eg-grid-header-row { 
index 29d73b2..6a0f57b 100644 (file)
@@ -4,6 +4,9 @@
   This sits above the grid and contains the column picker, etc.
 -->
 <div class="eg-grid-row eg-grid-action-row">
+  <div style="flex:1">
+    <div class="eg-grid-primary-label">{{gridLabel}}</div>
+  </div>
 
   <!-- column picker -->
   <div class="btn-group column-picker">
   </div>
 </div>
 
-<!--
-<br/>
--->
+<style>
+  /* MOVE ME */
+  .eg-grid-drag-handle {
+    width:2px; 
+    user-select: none; 
+    cursor: move;
+  }
+  .eg-grid-drag-handle:hover {
+    /*border:1px dashed #888;*/
+    color: red;
+  }
+
+</style>
 
 <div ng-show="list.items.length == 0" 
   class="alert alert-info">[% l('No Items To Display') %]</div>
   <!-- ================== -->
   <!-- Column headers row -->
   <div class="eg-grid-row eg-grid-header-row">
-    <div class="eg-grid-cell eg-grid-cell-stock">[% l('#') %]</div>
-    <div class="eg-grid-cell eg-grid-cell-stock">
-      <div><input type='checkbox' ng-click="list.toggleSelectAll()"/></div>
+    <div class="eg-grid-cell eg-grid-cell-stock" style="flex:{{indexFlex}}">
+      <div eg-drag-source eg-drag-dest column="+index">[% l('#') %]</div>
+    </div>
+    <div class="eg-grid-cell eg-grid-cell-stock" style="flex:{{selectorFlex}}">
+      <div eg-drag-source eg-drag-dest column="+selector">
+        <input type='checkbox' ng-click="list.toggleSelectAll()"/>
+      </div>
     </div>
     <div class="eg-grid-cell"
+        eg-drag-dest column="{{column.name}}"
         ng-repeat="column in list.allColumns"
         style="flex:{{column.flex}}"
         ng-show="list.displayColumns[column.name]">
-      <a href="javascript:;" ng-click="sortOn(column.name)">{{column.label}}</a>
-      <div style="height:100%;color:black">
-        foo
-        
-      </div>
+        <a eg-drag-source column="{{column.name}}" 
+          href='' ng-click="sortOn(column.name)">{{column.label}}</a>
     </div>
   </div>
 
   <!-- ============================= -->
   <!-- Inline grid configuration row -->
   <div class="eg-grid-row eg-grid-conf-row" ng-show="showGridConf">
-    <div class="eg-grid-cell eg-grid-cell-conf-header">
+    <div class="eg-grid-cell eg-grid-cell-conf-header" 
+        style="flex:{{indexFlex + selectorFlex}}">
       <div class="eg-grid-conf-cell-entry">[% l('Expand') %]</div>
       <div class="eg-grid-conf-cell-entry">[% l('Shrink') %]</div>
       <div class="eg-grid-conf-cell-entry">[% l('Sort') %]</div>
     <div class="eg-grid-row" 
         ng-repeat="item in list.items"
         ng-class="{'eg-grid-row-selected' : itemIsSelected(item)}">
-      <div class="eg-grid-cell eg-grid-cell-stock" 
+      <div class="eg-grid-cell eg-grid-cell-stock" style="flex:{{indexFlex}}"
         ng-click="handleRowClick($event, item)">
         {{$index + 1 + list.pageOffset}}
       </div>
-      <div class="eg-grid-cell eg-grid-cell-stock">
+      <div class="eg-grid-cell eg-grid-cell-stock" style="flex:{{selectorFlex}}">
         <!-- ng-click=handleRowClick here has unintended 
              consequences and is unnecessary, avoid it -->
         <div>
index 094baf0..3a5c80b 100644 (file)
@@ -39,3 +39,4 @@
 
 <!-- navbar driver -->
 <script src="[% ctx.media_prefix %]/js/ui/default/staff/navbar.js"></script>
+
index 5b32df0..118a0a6 100644 (file)
@@ -38,7 +38,10 @@ angular.module('egGridMod', ['egCoreMod', 'egListMod', 'egUiMod', 'ui.bootstrap'
             // grid configuration UI.  This is primarily used by
             // UIs where the data is ephemeral and can only be
             // single-display-column sorted.
-            disableSortPriority : '@'
+            disableSortPriority : '@',
+
+            // optional primary grid label
+            mainLabel : '@'
         },
 
         link : function(scope, element, attrs) {     
@@ -51,14 +54,18 @@ angular.module('egGridMod', ['egCoreMod', 'egListMod', 'egUiMod', 'ui.bootstrap'
         templateUrl : '/eg/staff/parts/t_autogrid', // TODO: avoid abs url
 
         controller : // TODO: reqs list
-            function($scope, $timeout, $modal, egIDL, egAuth, egNet, egList) { 
+            function($scope, $timeout, $modal, $document, $window, egIDL, egAuth, egNet, egList) { 
             var self = this;
 
-            // setup function, called at the end of the controller
+            // setup function. called at the end of the controller
             this.init = function() {
                 self.limit = 25; 
                 self.ofset = 0;
 
+                $scope.indexFlex = 1;
+                $scope.selectorFlex = 1;
+                $scope.gridLabel = $scope.mainLabel;
+
                 if (!$scope.query) {
                     console.error("egGrid requires a query");
                     return;
@@ -170,12 +177,16 @@ angular.module('egGridMod', ['egCoreMod', 'egListMod', 'egUiMod', 'ui.bootstrap'
              */
             this.compileAutoFields = function() {
                 if ($scope.list.allColumns.length) return;
+                var idlClass = egIDL.classes[$scope.idlClass];
 
-                $scope.idField = $scope.idField || 
-                    egIDL.classes[$scope.idlClass].pkey;
+                $scope.idField = $scope.idField || idlClass.pkey;
+
+                if (!$scope.gridLabel) {
+                    $scope.gridLabel = idlClass.label;
+                }
 
                 angular.forEach(
-                    egIDL.classes[$scope.idlClass].fields.sort(
+                    idlClass.fields.sort(
                         function(a, b) { return a.name < b.name ? -1 : 1 }),
                     function(field) {
                         if (field.virtual) return;
@@ -361,6 +372,27 @@ angular.module('egGridMod', ['egCoreMod', 'egListMod', 'egUiMod', 'ui.bootstrap'
                 ];
             }
 
+            this.onColumnDrag = function(col) {
+                // track which column we're dragging
+                self.dragColumn = col;
+            }
+
+            // if the target column does not match the source column,
+            // increase the size of the source column.
+            this.onColumnDragOver = function(target) {
+                if (angular.isUndefined(target)) return;
+                if (target == self.dragColumn) return;
+                if (self.dragColumn == '+index') {
+                    $scope.indexFlex += 1;
+                } else if (self.dragColumn == '+selector') {                             
+                    $scope.selectorFlex += 1;        
+                } else {
+                    var column = $scope.list.findColumn(self.dragColumn);
+                    $scope.modifyColumnFlex(column, 1);
+                }
+                $scope.$apply(); // needed
+            }
+
             this.init();
         }
     };
@@ -389,6 +421,41 @@ angular.module('egGridMod', ['egCoreMod', 'egListMod', 'egUiMod', 'ui.bootstrap'
     };
 })
 
+/** Simplified dnd directives for grid column controls.
+ *  Extract these out if the can be made generic enough
+ */
+
+.directive('egDragSource', function() {
+    return {
+        restrict : 'A',
+        require : '^egGrid',
+        link : function(scope, element, attrs, egGridCtrl) {
+            angular.element(element).attr('draggable', 'true');
+            element.bind('dragstart', function(e) {
+                var col = angular.element(e.target).attr('column');
+                egGridCtrl.onColumnDrag(col);
+            });
+        }
+    };
+})
+
+.directive('egDragDest', function() {
+    return {
+        restrict : 'A',
+        require : '^egGrid',
+        link : function(scope, element, attrs, egGridCtrl) {
+            element.bind('dragover', function(e) {
+                console.log('dragover');
+                e.stopPropagation();
+                e.preventDefault();
+                //e.dataTransfer.dropEffect = 'copy';
+                var col = angular.element(e.target).attr('column');
+                egGridCtrl.onColumnDragOver(col);
+            });
+        }
+    };
+})
+
 /**
  * Translates bare IDL object values into display values.
  * 1. Passes dates through the angular date filter
index d40f1d6..b3ce709 100644 (file)
@@ -50,6 +50,13 @@ angular.module('egListMod', ['egCoreMod'])
         // {index => true} map of selected rows
         this.selected = {};
 
+        this.findColumn = function(name) {
+            for (var i = 0; i < this.allColumns.length; i++) {
+                if (name == this.allColumns[i].name) 
+                    return this.allColumns[i];
+            }
+        }
+
         this.indexValue = function(item) {
             if (angular.isObject(item)) {
                 if (item !== null) {