LP#1626157 more grid
authorBill Erickson <berickxx@gmail.com>
Tue, 8 May 2018 13:22:34 +0000 (09:22 -0400)
committerBill Erickson <berickxx@gmail.com>
Tue, 8 May 2018 13:22:34 +0000 (09:22 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/share/grid/grid-column-config.component.html
Open-ILS/src/eg2/src/app/share/grid/grid-column.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid.service.ts
Open-ILS/src/eg2/src/app/staff/admin/server/config/billing_type.component.html

index 3589461..7ce0cf0 100644 (file)
       <div class="col-lg-1 eg-grid-header-cell">Move Down</div>
       <div class="col-lg-1 eg-grid-header-cell">First Visible</div>
       <div class="col-lg-1 eg-grid-header-cell">Last Visible</div>
-      <div class="col-lg-1 eg-grid-header-cell" *ngIf="!disableMultiSort">Sort Priority</div>
+      <div class="col-lg-1 eg-grid-header-cell" 
+        *ngIf="columnSet.isMultiSortable">Sort Priority</div>
       <div class="col-lg-3 eg-grid-header-cell">
-        <button class="btn btn-info" ng-click="elevateVisible()">
+        <button class="btn btn-info" (click)="columnSet.moveVisibleToFront()">
           Visible Columns To Top
         </button>
       </div>
     </div>
-    <div class="row" *ngFor="let col of columnSet.columns"
-      [ngClass]="{visible : !col.visible}">
-      <div class="col-lg-1" (click)="col.hidden=!col.hidden">
-        <span *ngIf="!col.hidden" class="badge badge-success">&#x2713;</span>
-        <span *ngIf="col.hidden" class="badge badge-warning">&#x2717;</span>
+    <div class="row mt-1" *ngFor="let col of columnSet.columns"
+      [ngClass]="{visible : col.visible}">
+      <div class="col-lg-1" (click)="col.visible=!col.visible">
+        <span *ngIf="col.visible" class="badge badge-success">&#x2713;</span>
+        <span *ngIf="!col.visible" class="badge badge-warning">&#x2717;</span>
       </div>
-      <div class="col-lg-3" (click)="col.hidden=!col.hidden">{{col.label}}</div>
-    <!--
+      <div class="col-lg-3" (click)="col.visible=!col.visible">{{col.label}}</div>
       <div class="col-lg-1">
-        <a href title="[% l('Move column up') %]"
-          ng-click="modifyColumnPos(col, -1)">
-          <span class="glyphicon glyphicon-arrow-up"></span>
+        <a class="no-href" title="Move column up" i18n-title
+          (click)="columnSet.moveColumn(col, -1)">
+          <span class="material-icons">arrow_upward</span>
         </a>
       </div>
       <div class="col-lg-1">
-        <a href title="[% l('Move column down') %]"
-          ng-click="modifyColumnPos(col, 1)">
-          <span class="glyphicon glyphicon-arrow-down"></span>
+        <a class="no-href" title="Move column down" i18n-title
+          (click)="columnSet.moveColumn(col, 1)">
+          <span class="material-icons">arrow_downward</span>
         </a>
       </div>
       <div class="col-lg-1">
-        <a href title="[% l('Make first visible') %]"
-          ng-click="modifyColumnPos(col, -10000)">
-          <span class="glyphicon glyphicon-open"></span>
+        <a class="no-href" title="Make first visible" i18n-title
+          (click)="columnSet.moveColumn(col, -10000)">
+          <span class="material-icons">vertical_align_top</span>
         </a>
       </div>
       <div class="col-lg-1">
-        <a href title="[% l('Make last visible') %]"
-          ng-click="modifyColumnPos(col, 10000)">
-          <span class="glyphicon glyphicon-save"></span>
+        <a class="no-href" title="Make last visible" i18n-title
+          (click)="columnSet.moveColumn(col, 10000)">
+          <span class="material-icons">vertical_align_bottom</span>
         </a>
       </div>
-      <div class="col-lg-1" ng-if="!disableMultiSort">
-        <div ng-if="col.multisortable">
-          <input type='number' ng-model="col.sort"
-            title="[% l('Sort Priority / Direction') %]" style='width:2.3em'/>
+      <div class="col-lg-1" *ngIf="columnSet.isMultiSortable">
+        <div *ngIf="col.isMultiSortable">
+          <input type='number' [(ngModel)]="col.sort"
+            title="Sort Priority / Direction" i18n-title style='width:2.4em'/>
         </div>
       </div>
-    -->
 
     </div>
   </div>
index 2bade60..ad9e946 100644 (file)
@@ -14,7 +14,8 @@ export class EgGridColumnComponent implements OnInit {
     @Input() path: string;
     @Input() label: string;
     @Input() flex: number;
-    @Input() hidden: boolean = false;
+    @Input() visible: boolean;
+    @Input() hidden: boolean;
     @Input() cellTemplate: TemplateRef<any>;
     @Input() pkey: boolean;
 
index 01a2aa4..865ca90 100644 (file)
@@ -18,6 +18,8 @@ export class EgGridComponent implements OnInit {
 
     @Input() dataSource: EgGridDataSource;
     @Input() idlClass: string;
+    @Input() isMultiSortable: boolean;
+    @Input() persistKey: string;
 
     pager: Pager;
     columnSet: EgGridColumnSet;
@@ -28,19 +30,21 @@ export class EgGridComponent implements OnInit {
     constructor(private gridSvc: EgGridService) {
         this.pager = new Pager();
         this.selector = {};
-        this.pager.limit = 10; // TODO
+        this.pager.limit = 10; // TODO config
         this.onRowDblClick$ = new EventEmitter<any>();
         this.toolbarButtons = [];
     }
 
     ngOnInit() {
-        this.columnSet = this.gridSvc.initializeColumnSet(this.idlClass);
+        this.columnSet = new EgGridColumnSet(this.idlClass);
+        this.columnSet.isMultiSortable = this.isMultiSortable;
+        this.gridSvc.generateColumns(this.columnSet);
         this.dataSource.requestPage(this.pager);
     }
 
     reload() {
-        this.dataSource.data = [];
         this.pager.offset = 0;
+        this.dataSource.data = [];
         this.dataSource.requestPage(this.pager);
     }
 
index 6b10fc0..110ed2c 100644 (file)
@@ -48,18 +48,17 @@ export class EgGridService {
         return val+'';
     }
 
-    initializeColumnSet(idlClass?: string): EgGridColumnSet {
-        let columnSet = new EgGridColumnSet();
+    generateColumns(columnSet: EgGridColumnSet) {
 
         // generate columns for all non-virtual fields on the IDL class
-        if (idlClass) {
-            this.idl.classes[idlClass].fields.forEach(field => {
+        if (columnSet.idlClass) {
+            this.idl.classes[columnSet.idlClass].fields.forEach(field => {
                 if (field.virtual) return;
                 let col = new EgGridColumn();
                 col.name = field.name;
                 col.label = field.label || field.name;
                 col.idlFieldDef = field;
-                if (field.name == this.idl.classes[idlClass].pkey)
+                if (field.name == this.idl.classes[columnSet.idlClass].pkey)
                     col.isPkey = true;
                 columnSet.add(col);
             });
@@ -76,20 +75,26 @@ export class EgGridColumn {
     label: string;
     flex: number;
     hidden: boolean;
+    visible: boolean;
+    sort: number;
     idlClass: string;
     idlFieldDef: any;
     cellTemplate: TemplateRef<any>;
     isPkey: boolean;
     isDragTarget: boolean;
+    isMultiSortable: boolean;
 }
 
 
 export class EgGridColumnSet {
     columns: EgGridColumn[];
+    idlClass: string;
     pkeyColumn: EgGridColumn;
+    isMultiSortable: boolean;
 
-    constructor() {
+    constructor(idlClass?: string) {
         this.columns = [];
+        this.idlClass = idlClass;
     }
 
     add(col: EgGridColumn) {
@@ -98,11 +103,18 @@ export class EgGridColumnSet {
 
         if (col.isPkey) this.pkeyColumn = col;
 
+        col.visible = !col.hidden;
+
+        // If a column set is multisortable, all columns are multisortable
+        // by default. TODO: add isNotMultiSortable ?
+        if (col.isMultiSortable === undefined && this.isMultiSortable)
+            col.isMultiSortable = true;
+
         this.columns.push(col);
     }
 
     displayColumns(): EgGridColumn[] {
-        return this.columns.filter(c => !c.hidden);
+        return this.columns.filter(c => c.visible);
     }
 
     insertBefore(source: EgGridColumn, target: EgGridColumn) {
@@ -120,6 +132,44 @@ export class EgGridColumnSet {
         this.columns.splice(targetIdx, 0, source);
     }
 
+    // Move visible columns to the front of the list.
+    moveVisibleToFront() {
+        let newCols = this.displayColumns();
+        this.columns.forEach(col => { if (!col.visible) newCols.push(col) });
+        this.columns = newCols;
+    }
+
+    moveColumn(col: EgGridColumn, diff: number) {
+        var srcIdx, targetIdx;
+
+        this.columns.forEach((c, i) => {
+          if (c.name == col.name) srcIdx = i 
+        });
+
+        targetIdx = srcIdx + diff;
+        if (targetIdx < 0) {
+            targetIdx = 0;
+        } else if (targetIdx >= this.columns.length) {
+            // Target index follows the last visible column.
+            var lastVisible = 0;
+            this.columns.forEach((c, idx) => {
+                if (c.visible) lastVisible = idx;
+            });
+
+            // When moving a column (down) causes one or more
+            // visible columns to shuffle forward, our column
+            // moves into the slot of the last visible column.
+            // Otherwise, put it into the slot directly following 
+            // the last visible column.
+            targetIdx = srcIdx <= lastVisible ? lastVisible : lastVisible + 1;
+        }
+
+        // Splice column out of old position, insert at new position.
+        this.columns.splice(srcIdx, 1);
+        this.columns.splice(targetIdx, 0, col);
+    }
+
+
 }
 
 export class EgGridToolbarButton {
index 684883c..538bbc7 100644 (file)
@@ -1,7 +1,7 @@
 <eg-staff-banner bannerText="Billing Type Configuration" i18n-bannerText>
 </eg-staff-banner>
 
-<eg-grid #btGrid idlClass="cbt" [dataSource]="dataSource">
+<eg-grid #btGrid idlClass="cbt" [dataSource]="dataSource" [isMultiSortable]="true">
   <eg-grid-toolbar-button label="New Billing Type" i18n-label [action]="createBillingType">
   </eg-grid-toolbar-button>
 </eg-grid>