--- /dev/null
+<eg-title i18n-prefix prefix="Floating Group Administration"></eg-title>
+<eg-staff-banner bannerText="Floating Group Configuration4" i18n-bannerText>
+</eg-staff-banner>
+<!-- <eg-admin-page persistKeyPfx="server" idlClass="cfg"></eg-admin-page> -->
+<!-- <eg-staff-banner bannerText="Linked Group Members" i18n-bannerText>
+</eg-staff-banner>
+<eg-admin-page persistKeyPfx="server" idlClass="cfgm"></eg-admin-page> -->
+
+
+<!-- <ng-template #successStrTmpl i18n>{{idlClassDef.label}} Update Succeeded</ng-template>
+<eg-string #successString [template]="successStrTmpl"></eg-string>
+
+<ng-template #createStrTmpl i18n>{{idlClassDef.label}} Succeessfully Created</ng-template>
+<eg-string #createString [template]="createStrTmpl"></eg-string> -->
+
+<!-- <ng-container *ngIf="orgField">
+ <div class="d-flex">
+ <div>
+ <div class="input-group">
+ <div class="input-group-prepend">
+ <span class="input-group-text">{{orgFieldLabel}}</span>
+ </div>
+ <eg-org-select
+ [limitPerms]="viewPerms"
+ [initialOrg]="contextOrg"
+ (onChange)="orgOnChange($event)">
+ </eg-org-select>
+ </div>
+ </div>
+ <div class="pl-2">
+ <div class="form-check">
+ <input type="checkbox" (click)="grid.reload()"
+ [disabled]="disableAncestorSelector()"
+ [(ngModel)]="includeOrgAncestors"
+ class="form-check-input" id="include-ancestors">
+ <label class="form-check-label" for="include-ancestors" i18n>+ Ancestors</label>
+ </div>
+ <div class="form-check">
+ <input type="checkbox" (click)="grid.reload()"
+ [disabled]="disableDescendantSelector()"
+ [(ngModel)]="includeOrgDescendants"
+ class="form-check-input" id="include-descendants">
+ <label class="form-check-label" for="include-descendants" i18n>+ Descendants</label>
+ </div>
+ </div>
+ </div>
+ <hr/>
+</ng-container> -->
+
+<!-- idlObject and fieldName applied programmatically -->
+<!-- <eg-translate #translator></eg-translate> -->
+
+<eg-grid #grid idlClass="{{idlClass}}" [dataSource]="dataSource"
+ [sortable]="true" persistKey="{{persistKey}}">
+ <eg-grid-toolbar-button [disabled]="!canCreate"
+ label="New {{idlClassDef.label}}" i18n-label [action]="createNew">
+ </eg-grid-toolbar-button>
+ <!-- <eg-grid-toolbar-button [disabled]="translatableFields.length == 0"
+ label="Apply Translations" i18n-label [action]="translate">
+ </eg-grid-toolbar-button> -->
+ <eg-grid-toolbar-action label="Delete Selected" i18n-label [action]="deleteSelected">
+ </eg-grid-toolbar-action>
+ <eg-grid-toolbar-action label="Edit Selected" i18n-label [action]="editSelected">
+ </eg-grid-toolbar-action>
+</eg-grid>
+
+<!-- <eg-fm-record-editor #editDialog idlClass="{{idlClass}}">
+</eg-fm-record-editor> -->
--- /dev/null
+// import {Component} from '@angular/core';
+import {Component, Input, OnInit, TemplateRef, ViewChild} from '@angular/core';
+import { RouterModule, Routes, CanActivate, Router,
+ ActivatedRouteSnapshot,
+ RouterStateSnapshot,
+ CanActivateChild } from '@angular/router';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
+import {GridDataSource} from '@eg/share/grid/grid';
+import {GridComponent} from '@eg/share/grid/grid.component';
+import {TranslateComponent} from '@eg/staff/share/translate/translate.component';
+import {ToastService} from '@eg/share/toast/toast.service';
+import {Pager} from '@eg/share/util/pager';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {OrgService} from '@eg/core/org.service';
+import {PermService} from '@eg/core/perm.service';
+import {AuthService} from '@eg/core/auth.service';
+import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
+import {StringComponent} from '@eg/share/string/string.component';
+
+ @Component({
+ templateUrl: './floating-group.component.html'
+ })
+
+ export class FloatingGroupComponent {
+
+ @Input() idlClass: string = "cfg";
+
+ // Default sort field, used when no grid sorting is applied.
+ @Input() sortField: string;
+
+ // Data source may be provided by the caller. This gives the caller
+ // complete control over the contents of the grid. If no data source
+ // is provided, a generic one is create which is sufficient for data
+ // that requires no special handling, filtering, etc.
+ @Input() dataSource: GridDataSource;
+
+ // Size of create/edito dialog. Uses large by default.
+ @Input() dialogSize: 'sm' | 'lg' = 'lg';
+
+ // If an org unit field is specified, an org unit filter
+ // is added to the top of the page.
+ @Input() orgField: string;
+
+ // Disable the auto-matic org unit field filter
+ @Input() disableOrgFilter: boolean;
+
+ // Include objects linking to org units which are ancestors
+ // of the selected org unit.
+ @Input() includeOrgAncestors: boolean;
+
+ // Ditto includeOrgAncestors, but descendants.
+ @Input() includeOrgDescendants: boolean;
+
+ // Optional grid persist key. This is the part of the key
+ // following eg.grid.
+ @Input() persistKey: string;
+
+ // Optional path component to add to the generated grid persist key,
+ // formatted as (for example):
+ // 'eg.grid.admin.${persistKeyPfx}.config.billing_type'
+ @Input() persistKeyPfx: string = "server";
+
+ @ViewChild('grid') grid: GridComponent;
+ @ViewChild('editDialog') editDialog: FmRecordEditorComponent;
+ @ViewChild('successString') successString: StringComponent;
+ @ViewChild('createString') createString: StringComponent;
+ @ViewChild('translator') translator: TranslateComponent;
+
+ idlClassDef: any;
+ pkeyField: string;
+ createNew: () => void;
+ deleteSelected: (rows: IdlObject[]) => void;
+ editSelected: (rows: IdlObject[]) => void;
+
+ // True if any columns on the object support translations
+ translateRowIdx: number;
+ translateFieldIdx: number;
+ translatableFields: string[];
+ translate: () => void;
+
+ contextOrg: IdlObject;
+ orgFieldLabel: string;
+ viewPerms: string;
+ canCreate: boolean;
+
+ constructor(
+ private idl: IdlService,
+ private org: OrgService,
+ private auth: AuthService,
+ private pcrud: PcrudService,
+ private perm: PermService,
+ private toast: ToastService,
+ private router: Router
+ ) {
+ this.translatableFields = [];
+ }
+
+ applyOrgValues() {
+
+ if (this.disableOrgFilter) {
+ this.orgField = null;
+ return;
+ }
+
+ if (!this.orgField) {
+ // If no org unit field is specified, try to find one.
+ // If an object type has multiple org unit fields, the
+ // caller should specify one or disable org unit filter.
+ this.idlClassDef.fields.forEach(field => {
+ if (field['class'] === 'aou') {
+ this.orgField = field.name;
+ }
+ });
+ }
+
+ if (this.orgField) {
+ this.orgFieldLabel = this.idlClassDef.field_map[this.orgField].label;
+ this.contextOrg = this.org.root();
+ }
+ }
+
+ ngOnInit() {
+ console.log("ngOnInit running in fg component")
+ this.idlClassDef = this.idl.classes[this.idlClass];
+ this.pkeyField = this.idlClassDef.pkey || 'id';
+
+ // this.translatableFields =
+ // this.idlClassDef.fields.filter(f => f.i18n).map(f => f.name);
+
+ if (!this.persistKey) {
+ this.persistKey =
+ 'admin.' +
+ (this.persistKeyPfx ? this.persistKeyPfx + '.' : '') +
+ this.idlClassDef.table;
+ }
+
+ // Limit the view org selector to orgs where the user has
+ // permacrud-encoded view permissions.
+ const pc = this.idlClassDef.permacrud;
+ if (pc && pc.retrieve) {
+ this.viewPerms = pc.retrieve.perms;
+ }
+
+ this.checkCreatePerms();
+ this.applyOrgValues();
+
+ // If the caller provides not data source, create a generic one.
+ if (!this.dataSource) {
+ this.initDataSource();
+ }
+
+ // TODO: pass the row activate handler via the grid markup
+ // this.grid.onRowActivate.subscribe(
+ // (idlThing: IdlObject) => {
+ // console.log("grid.onrowactivate fg component")
+ // this.editDialog.mode = 'update';
+ // this.editDialog.recId = idlThing[this.pkeyField]();
+ // this.editDialog.open({size: this.dialogSize}).then(
+ // ok => {
+ // this.successString.current()
+ // .then(str => this.toast.success(str));
+ // this.grid.reload();
+ // },
+ // err => {}
+ // );
+ // }
+ // );
+
+ // this.createNew = () => {
+ // this.editDialog.mode = 'create';
+ // this.editDialog.open({size: this.dialogSize}).then(
+ // ok => {
+ // this.createString.current()
+ // .then(str => this.toast.success(str));
+ // this.grid.reload();
+ // },
+ // err => {}
+ // );
+ // };
+
+ this.deleteSelected = (floatingGroups: IdlObject[]) => {
+ floatingGroups.forEach(fg => fg.isdeleted(true));
+ this.pcrud.autoApply(floatingGroups).subscribe(
+ val => console.debug('deleted: ' + val),
+ err => {},
+ () => this.grid.reload()
+ );
+ };
+
+ this.editSelected = (floatingGroups: IdlObject[]) => {
+
+ // console.log(floatingGroups);
+ // console.log("route to this id:")
+ // console.log(floatingGroups[0].a[0]);
+ // console.log("route to this id:")
+ let idToEdit = floatingGroups[0].a[0];
+ console.log("you clicked edit. We are editing id=" + idToEdit);
+ this.router.navigate(["/staff/admin/server/config/floating_group/" + idToEdit]);
+ // Edit each IDL thing one at a time
+ // const editOneThing = (standingPenalty: IdlObject) => {
+ // if (!standingPenalty) { return; }
+
+ // this.showEditDialog(standingPenalty).then(
+ // () => editOneThing(standingPenaltyFields.shift()));
+ // };
+
+ // editOneThing(standingPenaltyFields.shift());
+ }
+ }
+
+ checkCreatePerms() {
+ this.canCreate = false;
+ const pc = this.idlClassDef.permacrud || {};
+ const perms = pc.create ? pc.create.perms : [];
+ if (perms.length === 0) { return; }
+
+ this.perm.hasWorkPermAt(perms, true).then(permMap => {
+ Object.keys(permMap).forEach(key => {
+ if (permMap[key].length > 0) {
+ this.canCreate = true;
+ }
+ });
+ });
+ }
+
+ orgOnChange(org: IdlObject) {
+ this.contextOrg = org;
+ this.grid.reload();
+ }
+
+ initDataSource() {
+ this.dataSource = new GridDataSource();
+
+ this.dataSource.getRows = (pager: Pager, sort: any[]) => {
+ const orderBy: any = {};
+
+ if (sort.length) {
+ // Sort specified from grid
+ orderBy[this.idlClass] = sort[0].name + ' ' + sort[0].dir;
+
+ } else if (this.sortField) {
+ // Default sort field
+ orderBy[this.idlClass] = this.sortField;
+ }
+
+ const searchOps = {
+ offset: pager.offset,
+ limit: pager.limit,
+ order_by: orderBy
+ };
+
+ if (this.contextOrg) {
+ // Filter rows by those linking to the context org and
+ // optionally ancestor and descendant org units.
+
+ let orgs = [this.contextOrg.id()];
+
+ if (this.includeOrgAncestors) {
+ orgs = this.org.ancestors(this.contextOrg, true);
+ }
+
+ if (this.includeOrgDescendants) {
+ // can result in duplicate workstation org IDs... meh
+ orgs = orgs.concat(
+ this.org.descendants(this.contextOrg, true));
+ }
+
+ const search = {};
+ search[this.orgField] = orgs;
+ return this.pcrud.search(this.idlClass, search, searchOps);
+ }
+
+ // No org filter -- fetch all rows
+ return this.pcrud.retrieveAll(this.idlClass, searchOps);
+ };
+ }
+
+ disableAncestorSelector(): boolean {
+ return this.contextOrg &&
+ this.contextOrg.id() === this.org.root().id();
+ }
+
+ disableDescendantSelector(): boolean {
+ return this.contextOrg && this.contextOrg.children().length === 0;
+ }
+
+
+
+
+
+ }
\ No newline at end of file