LP1803787 Grid toolbar actions menu component; cleanup
authorBill Erickson <berickxx@gmail.com>
Thu, 9 May 2019 15:50:19 +0000 (11:50 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 9 May 2019 16:15:31 +0000 (12:15 -0400)
Moves the guts of the grid toolbar actions menu (the buttons) to a
dedicated component that can be shared by both the actions drop-down
menu and the actions popover.  This adds support for honoring
disableOnRow for the popover actions. And avoids duplication.

Adds a sandbox example of using the toolbar action click event and
divider.

Some minor code cleanup/consistency changes.

Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/share/grid/grid-body.component.html
Open-ILS/src/eg2/src/app/share/grid/grid-body.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid-toolbar-action.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid-toolbar-actions-menu.component.html [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/grid/grid-toolbar-actions-menu.component.ts [new file with mode: 0644]
Open-ILS/src/eg2/src/app/share/grid/grid-toolbar.component.html
Open-ILS/src/eg2/src/app/share/grid/grid-toolbar.component.ts
Open-ILS/src/eg2/src/app/share/grid/grid.module.ts
Open-ILS/src/eg2/src/app/share/grid/grid.ts
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.html
Open-ILS/src/eg2/src/app/staff/sandbox/sandbox.component.ts

index 18a6a35..11cd884 100644 (file)
@@ -1,15 +1,7 @@
 <!-- uses dropdown menu CSS for easy stying, but it's not a dropdown -->
 <ng-template #contextMenu let-gridContext="gridContext">
-  <ng-container *ngFor="let action of gridContext.toolbarActions">
-    <ng-container *ngIf="action.separator">
-      <div class="dropdown-divider"></div>
-    </ng-container>
-    <ng-container *ngIf="!action.separator">
-      <a class="dropdown-item" (click)="performAction(action)">
-        <span class="ml-2">{{action.label}}</span>
-      </a>
-    </ng-container>
-  </ng-container>
+  <eg-grid-toolbar-actions-menu [gridContext]="gridContext">
+  </eg-grid-toolbar-actions-menu>
 </ng-template>
 
 <!--
index 8d96401..f5b2916 100644 (file)
@@ -90,10 +90,6 @@ export class GridBodyComponent implements OnInit {
         this.grid.onRowActivate.emit(row);
     }
 
-    performAction(action: GridToolbarAction) {
-        action.action(this.context.getSelectedRows());
-    }
-
     // Apply row selection, track the new menu if needed,
     // manually close any existing open menus, open selected menu.
     onRowContextClick($event, row: any, contextMenu: NgbPopover) {
index 6ebe6de..79368cd 100644 (file)
@@ -13,7 +13,7 @@ export class GridToolbarActionComponent implements OnInit {
     @Input() label: string;
 
     // Register to click events
-    @Output() onClick: EventEmitter<any []>;
+    @Output() actionClick: EventEmitter<any []>;
 
     // DEPRECATED: Pass a reference to a function that is called on click.
     @Input() action: (rows: any[]) => any;
@@ -27,10 +27,12 @@ export class GridToolbarActionComponent implements OnInit {
     @Input() disableOnRows: (rows: any[]) => boolean;
 
     // If true, render a separator bar only, no action link.
-    @Input() separator: boolean;
+    @Input() isSeparator: boolean;
 
     // get a reference to our container grid.
-    constructor(@Host() private grid: GridComponent) { }
+    constructor(@Host() private grid: GridComponent) {
+        this.actionClick = new EventEmitter<any []>();
+    }
 
     ngOnInit() {
 
@@ -42,14 +44,11 @@ export class GridToolbarActionComponent implements OnInit {
         const action = new GridToolbarAction();
         action.label = this.label;
         action.action = this.action;
+        action.actionClick = this.actionClick;
         action.group = this.group;
-        action.separator = this.separator;
+        action.isSeparator = this.isSeparator;
         action.disableOnRows = this.disableOnRows;
 
-        if (!this.separator) {
-            action.onClick = this.onClick = new EventEmitter<any []>();
-        }
-
         this.grid.context.toolbarActions.push(action);
     }
 }
diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid-toolbar-actions-menu.component.html b/Open-ILS/src/eg2/src/app/share/grid/grid-toolbar-actions-menu.component.html
new file mode 100644 (file)
index 0000000..383e287
--- /dev/null
@@ -0,0 +1,15 @@
+<button class="dropdown-item" 
+  [disabled]="shouldDisable(action)"
+  (click)="performAction(action)"
+  *ngFor="let action of gridContext.toolbarActions">
+  <ng-container *ngIf="action.isGroup">
+    <span class="font-weight-bold font-italic">{{action.label}}</span>
+  </ng-container>
+  <ng-container *ngIf="action.isSeparator">
+    <div class="dropdown-divider"></div>
+  </ng-container>
+  <ng-container *ngIf="!action.isGroup && !action.isSeparator">
+    <!-- grouped entries are left paddded for group indentation -->        
+    <span [ngClass]="{'ml-2': action.group}">{{action.label}}</span>
+  </ng-container>
+</button>
diff --git a/Open-ILS/src/eg2/src/app/share/grid/grid-toolbar-actions-menu.component.ts b/Open-ILS/src/eg2/src/app/share/grid/grid-toolbar-actions-menu.component.ts
new file mode 100644 (file)
index 0000000..322caba
--- /dev/null
@@ -0,0 +1,31 @@
+import {Component, Input, OnInit, Host} from '@angular/core';
+import {GridToolbarAction, GridContext} from '@eg/share/grid/grid';
+
+/** Models a list of toolbar action menu entries */
+
+@Component({
+  selector: 'eg-grid-toolbar-actions-menu',
+  templateUrl: 'grid-toolbar-actions-menu.component.html'
+})
+
+export class GridToolbarActionsMenuComponent {
+
+    @Input() gridContext: GridContext;
+
+    performAction(action: GridToolbarAction) {
+        if (action.isGroup || action.isSeparator) {
+            return; // These don't perform actions
+        }
+        const rows = this.gridContext.getSelectedRows();
+        action.actionClick.emit(rows);
+        if (action.action) { action.action(rows); }
+    }
+
+    shouldDisable(action: GridToolbarAction): boolean {
+        if (action.disableOnRows) {
+            return action.disableOnRows(this.gridContext.getSelectedRows());
+        }
+        return false;
+    }
+}
+
index d35bcaf..59db39e 100644 (file)
         class="material-icons mat-icon-in-button">playlist_add_check</span>
     </button>
     <div class="dropdown-menu" ngbDropdownMenu>
-      <button class="dropdown-item" 
-        [disabled]="shouldDisableAction(action)"
-        (click)="performAction(action)"
-        *ngFor="let action of gridContext.toolbarActions"
-        [disabled]="shouldDisableAction(action)">
-        <ng-container *ngIf="action.isGroup">
-          <span class="ml-2 font-weight-bold font-italic">{{action.label}}</span>
-        </ng-container>
-        <ng-container *ngIf="action.separator">
-          <div class="dropdown-divider"></div>
-        </ng-container>
-        <ng-container 
-          *ngIf="!action.group && !action.isGroup && !action.separator">
-          <span class="ml-2">{{action.label}}</span>
-        </ng-container>
-      </button>
+      <eg-grid-toolbar-actions-menu [gridContext]="gridContext">
+      </eg-grid-toolbar-actions-menu>
     </div>
   </div>
 
index a05aaa5..308fdd0 100644 (file)
@@ -77,28 +77,12 @@ export class GridToolbarComponent implements OnInit {
         );
     }
 
-    performAction(action: GridToolbarAction) {
-        if (action.isGroup || action.separator) {
-            return; // These don't perform actions
-        }
-        const rows = this.gridContext.getSelectedRows();
-        action.onClick.emit(rows);
-        if (action.action) { action.action(rows); }
-    }
-
     performButtonAction(button: GridToolbarButton) {
         const rows = this.gridContext.getSelectedRows();
         button.onClick.emit();
         if (button.action) { button.action(); }
     }
 
-    shouldDisableAction(action: GridToolbarAction) {
-        if (action.disableOnRows) {
-            return action.disableOnRows(this.gridContext.getSelectedRows());
-        }
-        return false;
-    }
-
     printHtml() {
         this.gridPrinter.printGrid();
     }
index 0773a7e..454dcfb 100644 (file)
@@ -9,6 +9,7 @@ import {GridToolbarComponent} from './grid-toolbar.component';
 import {GridToolbarButtonComponent} from './grid-toolbar-button.component';
 import {GridToolbarCheckboxComponent} from './grid-toolbar-checkbox.component';
 import {GridToolbarActionComponent} from './grid-toolbar-action.component';
+import {GridToolbarActionsMenuComponent} from './grid-toolbar-actions-menu.component';
 import {GridColumnConfigComponent} from './grid-column-config.component';
 import {GridColumnWidthComponent} from './grid-column-width.component';
 import {GridPrintComponent} from './grid-print.component';
@@ -26,6 +27,7 @@ import {GridPrintComponent} from './grid-print.component';
         GridToolbarButtonComponent,
         GridToolbarCheckboxComponent,
         GridToolbarActionComponent,
+        GridToolbarActionsMenuComponent,
         GridColumnConfigComponent,
         GridColumnWidthComponent,
         GridPrintComponent
index d1cc9c3..0821c9f 100644 (file)
@@ -931,11 +931,11 @@ export class GridContext {
 // Actions apply to specific rows
 export class GridToolbarAction {
     label: string;
-    onClick: EventEmitter<any []>;
+    actionClick: EventEmitter<any []>;
     action: (rows: any[]) => any; // DEPRECATED
     group: string;
     isGroup: boolean; // used for group placeholder entries
-    separator: boolean;
+    isSeparator: boolean;
     disableOnRows: (rows: any[]) => boolean;
 }
 
index 54cd87d..95c378a 100644 (file)
   <eg-grid-toolbar-action label="Action that needs a single row" i18n-label
     [action]="complimentEvergreen" [disableOnRows]="notOneSelectedRow">
   </eg-grid-toolbar-action>
+  <eg-grid-toolbar-action [isSeparator]="true">
+  </eg-grid-toolbar-action>
+  <eg-grid-toolbar-action label="Another Action" i18n-label
+    (actionClick)="complimentEvergreen2($event)">
+  </eg-grid-toolbar-action>
   <eg-grid-column name="test" [cellTemplate]="cellTmpl" 
     [cellContext]="btGridTestContext" [sortable]="false">
   </eg-grid-column>
index 543e3cb..f7de626 100644 (file)
@@ -136,6 +136,11 @@ export class SandboxComponent implements OnInit {
         });
     }
 
+    // Example of click handler for row action
+    complimentEvergreen2(rows: IdlObject[]) {
+        alert('I know, right?');
+    }
+
     openEditor() {
         this.fmRecordEditor.open({size: 'lg'}).then(
             ok => { console.debug(ok); },