LPXXX Angular Permission group tree admin UI
authorBill Erickson <berickxx@gmail.com>
Mon, 8 Apr 2019 15:45:12 +0000 (11:45 -0400)
committerBill Erickson <berickxx@gmail.com>
Mon, 8 Apr 2019 15:45:12 +0000 (11:45 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/share/grid/grid.ts
Open-ILS/src/eg2/src/app/staff/admin/server/perm-group-tree.component.html
Open-ILS/src/eg2/src/app/staff/admin/server/perm-group-tree.component.ts

index 3743488..304a3d3 100644 (file)
@@ -574,8 +574,6 @@ export class GridContext {
                 const diff = sortDef.col.comparator(valueA, valueB);
                 if (diff === 0) { continue; }
 
-                console.log(valueA, valueB, diff);
-
                 return sortDef.dir === 'DESC' ? -diff : diff;
             }
 
index 257dded..31a3477 100644 (file)
@@ -29,7 +29,7 @@
     <h3 i18n class="mb-3">Selected Permission Group</h3>
     <ng-container *ngIf="!selected">
       <div class="alert alert-info font-italic" i18n>
-        Select an org unit type from the tree on the left.
+        Select a permission group from the tree on the left.
       </div>
     </ng-container>
     <div *ngIf="selected" class="common-form striped-even">
                 {{selected.callerData.name()}}
               </div>
             </div>
+            <div class="row">
+              <div class="col-lg-4">
+                <label i18n>Description: </label>
+              </div>
+              <div class="col-lg-8 font-weight-bold">
+                {{selected.callerData.description()}}
+              </div>
+            </div>
+            <div class="row">
+              <div class="col-lg-4">
+                <label i18n>User Expiration Interval: </label>
+              </div>
+              <div class="col-lg-8 font-weight-bold">
+                {{selected.callerData.perm_interval()}}
+              </div>
+            </div>
+            <div class="row">
+              <div class="col-lg-4">
+                <label i18n>Application Permission: </label>
+              </div>
+              <div class="col-lg-8 font-weight-bold">
+                {{selected.callerData.application_perm()}}
+              </div>
+            </div>
+            <div class="row">
+              <div class="col-lg-4">
+                <label i18n>Hold Priority: </label>
+              </div>
+              <div class="col-lg-8 font-weight-bold">
+                {{selected.callerData.hold_priority()}}
+              </div>
+            </div>
+            <div class="row">
+              <div class="col-lg-4">
+                <label i18n>User Group?: </label>
+              </div>
+              <div class="col-lg-8 font-weight-bold">
+                <!-- TODO: replace with <eg-bool/> when merged -->
+                {{selected.callerData.usergroup() == 't'}}
+              </div>
+            </div>
           </ng-template>
         </ngb-tab>
-        <ngb-tab title="Group Permission" i18n-title id="perm">
+        <ngb-tab title="Group Permissions" i18n-title id="perm">
           <ng-template ngbTabContent>
+            
+            <div class="row font-weight-bold">
+              <div class="col-lg-5" i18n>Permissions</div>
+              <div class="col-lg-2" i18n>Depth</div>
+              <div class="col-lg-3" i18n>Group</div>
+              <div class="col-lg-2" i18n>Grantable?</div>
+            </div>
+
+            <div class="row" *ngFor="let map of groupPermMaps()">
+              <div class="col-lg-5">{{map.perm().code()}}</div>
+              <div class="col-lg-2">{{map.depth()}}</div>
+              <div class="col-lg-3">{{map.grp().name()}}</div>
+              <div class="col-lg-2">
+                <ng-container *ngIf="permIsInherited(map); else nativeMap">
+                 <!-- TODO migrate to <eg-bool/> once merged-->
+                  {{map.grantable() == 't'}}
+                </ng-container>
+                <ng-template #nativeMap>
+                  <input type="checkbox"
+                    [ngModel]="map.grantable() == 't'"
+                    (ngModelChange)="map.grantable($event ? 't' : 'f')"/>
+                </ng-template>
+              </div>
+            </div>
           </ng-template>
         </ngb-tab>
       </ngb-tabset>
index cba1644..0c11ff9 100644 (file)
@@ -1,4 +1,5 @@
 import {Component, Input, ViewChild, OnInit} from '@angular/core';
+import {Observable, from} from 'rxjs';
 import {Tree, TreeNode} from '@eg/share/tree/tree';
 import {IdlService, IdlObject} from '@eg/core/idl.service';
 import {OrgService} from '@eg/core/org.service';
@@ -9,6 +10,7 @@ import {StringComponent} from '@eg/share/string/string.component';
 import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
 import {FmRecordEditorComponent, FmFieldOptions} from '@eg/share/fm-editor/fm-editor.component';
 import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {Pager} from '@eg/share/util/pager';
 
 @Component({
     templateUrl: './perm-group-tree.component.html'
@@ -18,7 +20,10 @@ export class PermGroupTreeComponent implements OnInit {
 
     tree: Tree;
     selected: TreeNode;
-    permissions: ComboboxEntry[];
+    permissions: IdlObject[];
+    permIdMap: {[id: number]: IdlObject};
+    permEntries: ComboboxEntry[];
+    permMaps: IdlObject[];
 
     @ViewChild('editDialog') editDialog: FmRecordEditorComponent;
     @ViewChild('editString') editString: StringComponent;
@@ -34,6 +39,9 @@ export class PermGroupTreeComponent implements OnInit {
         private toast: ToastService
     ) {
         this.permissions = [];
+        this.permEntries = [];
+        this.permMaps = [];
+        this.permIdMap = {};
     }
 
 
@@ -41,7 +49,19 @@ export class PermGroupTreeComponent implements OnInit {
         this.loadPgtTree();
     }
 
+    groupPermMaps(): IdlObject[] {
+        let maps = this.inheritedPermissions();
+        maps = maps.concat(
+            this.permMaps.filter(m => +m.grp().id() === +this.selected.id));
+
+        return maps.sort((m1, m2) =>
+            m1.perm().code() < m2.perm().code() ? -1 : 1);
+    }
+
+
+
     loadPgtTree() {
+
         this.pcrud.search('pgt', {parent: null},
             {flesh: -1, flesh_fields: {pgt: ['children']}}
         ).subscribe(pgtTree => this.ingestPgtTree(pgtTree));
@@ -51,20 +71,27 @@ export class PermGroupTreeComponent implements OnInit {
         // "pgt" is text instead of a link.  So the value it expects
         // is the code, not the ID.
         this.pcrud.retrieveAll('ppl', {order_by: {ppl: ['name']}})
-        .subscribe(perm =>
-            this.permissions.push({id: perm.code(), label: perm.code()}));
+        .subscribe(perm => {
+            this.permissions.push(perm);
+            this.permEntries.push({id: perm.code(), label: perm.code()})
+            this.permissions.forEach(perm => this.permIdMap[+perm.id()] = perm)
+        });
+
+        // Perm-group maps
+        this.pcrud.retrieveAll('pgpm', {}, {fleshSelectors: true})
+            .subscribe(map => this.permMaps.push(map));
     }
 
     fmEditorOptions(): {[fieldName: string]: FmFieldOptions} {
         return {
             application_perm: {
-                customValues: this.permissions
+                customValues: this.permEntries
             }
         };
     }
 
     // Translate the org unt type tree into a structure EgTree can use.
-    ingestPgtTree(pgtTree) {
+    ingestPgtTree(pgtTree: IdlObject) {
 
         const handleNode = (pgtNode: IdlObject): TreeNode => {
             if (!pgtNode) { return; }
@@ -86,19 +113,44 @@ export class PermGroupTreeComponent implements OnInit {
         this.tree = new Tree(rootNode);
     }
 
-    nodeClicked($event: any) {
-        this.selected = $event;
+    groupById(id: number): IdlObject {
+        return this.tree.findNode(id).callerData;
     }
 
-    postUpdate(message: StringComponent) {
-        // Modifying org unit types means refetching the org unit
-        // data normally fetched on page load, since it includes
-        // org unit type data.
-        this.org.fetchOrgs().then(
-            ok => {
-                message.current().then(str => this.toast.success(str));
+    permById(id: number): IdlObject {
+        return this.permIdMap[id];
+    }
+
+    // Returns true if the perm map belongs to an ancestore of the
+    // currently selected group.
+    permIsInherited(map: IdlObject): boolean {
+        let treeNode = this.tree.findNode(this.selected.callerData.parent());
+        while (treeNode) {
+            if (+map.grp().id() === +treeNode.id) {
+                return true;
             }
-        );
+            treeNode = this.tree.findNode(treeNode.callerData.parent());
+        }
+        return false;
+    }
+
+    // List of perm maps that owned by perm groups which are ancestors
+    // of the selected group
+    inheritedPermissions(): IdlObject[] {
+        let maps: IdlObject[] = [];
+
+        let treeNode = this.tree.findNode(this.selected.callerData.parent());
+        while (treeNode) {
+            maps = maps.concat(
+                this.permMaps.filter(map => +map.grp().id() === +treeNode.id));
+            treeNode = this.tree.findNode(treeNode.callerData.parent());
+        }
+
+        return maps;
+    }
+
+    nodeClicked($event: any) {
+        this.selected = $event;
     }
 
     edit() {
@@ -107,7 +159,7 @@ export class PermGroupTreeComponent implements OnInit {
 
         this.editDialog.open({size: 'lg'}).then(
             success => {
-                this.postUpdate(this.editString);
+                this.editString.current().then(str => this.toast.success(str));
             },
             rejected => {
                 if (rejected && rejected.dismissed) {
@@ -134,7 +186,7 @@ export class PermGroupTreeComponent implements OnInit {
                         // pcrud action/transaction completed.
                         this.tree.removeNode(this.selected);
                         this.selected = null;
-                        this.postUpdate(this.editString);
+                        this.editString.current().then(str => this.toast.success(str));
                     }
                 );
             },
@@ -162,7 +214,7 @@ export class PermGroupTreeComponent implements OnInit {
                     callerData: result
                 });
                 parentTreeNode.children.push(newNode);
-                this.postUpdate(this.createString);
+                this.createString.current().then(str => this.toast.success(str));
             },
 
             rejected => {