<eg-staff-banner bannerText="{{classLabel}} Configuration" i18n-bannerText>
</eg-staff-banner>
<eg-admin-page persistKeyPfx="{{persistKeyPfx}}" idlClass="{{idlClass}}"
+ configLinkBasePath="{{configLinkBasePath}}"
readonlyFields="{{readonlyFields}}"
[disableOrgFilter]="disableOrgFilter"></eg-admin-page>
`
classLabel: string;
persistKeyPfx: string;
readonlyFields = '';
+ configLinkBasePath = '/staff/admin';
// Tell the admin page to disable and hide the automagic org unit filter
disableOrgFilter: boolean;
// ACQ is a special case, because unlike 'server', 'local',
// 'workstation', the schema ('acq') is the root of the path.
this.persistKeyPfx = '';
+ } else {
+ this.configLinkBasePath += '/' + this.persistKeyPfx;
}
// Pass the readonlyFields param if available
<ng-container *ngTemplateOutlet="helpTemplate"></ng-container>
</ng-container>
+<ng-template #configFieldLink let-row="row" let-col="col">
+ <a i18n-title title="Link To {{col.label}}"
+ [routerLink]="configFieldRouteLink(row, col)"
+ [queryParams]="configFieldRouteParams(row, col)">{{col.label}}</a>
+</ng-template>
+
<eg-grid #grid idlClass="{{idlClass}}" [dataSource]="dataSource" hideFields="{{hideGridFields}}"
[sortable]="true" persistKey="{{persistKey}}">
<eg-grid-toolbar-button [disabled]="!canCreate"
</eg-grid-toolbar-action>
<eg-grid-toolbar-action label="Delete Selected" i18n-label (onClick)="deleteSelected($event)">
</eg-grid-toolbar-action>
+ <ng-container *ngFor="let cf of configFields">
+ <eg-grid-column name="{{cf.name}}" [cellTemplate]="configFieldLink">
+ </eg-grid-column>
+ </ng-container>
</eg-grid>
<eg-fm-record-editor #editDialog idlClass="{{idlClass}}"
import {Component, Input, OnInit, TemplateRef, ViewChild} from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import {IdlService, IdlObject} from '@eg/core/idl.service';
-import {GridDataSource} from '@eg/share/grid/grid';
+import {GridDataSource, GridColumn} from '@eg/share/grid/grid';
import {GridComponent} from '@eg/share/grid/grid.component';
import {TranslateComponent} from '@eg/share/translate/translate.component';
import {ToastService} from '@eg/share/toast/toast.service';
// Override default values for fm-editor
@Input() defaultNewRecord: IdlObject;
+ // Used as the first part of the routerLink path when creating
+ // links to related tables via configField's.
+ @Input() configLinkBasePath: string;
@ViewChild('grid', { static: true }) grid: GridComponent;
@ViewChild('editDialog', { static: true }) editDialog: FmRecordEditorComponent;
idlClassDef: any;
pkeyField: string;
- configFields: string[];
+ configFields: any[]; // IDL field definitions
// True if any columns on the object support translations
translateRowIdx: number;
}
ngOnInit() {
+
this.idlClassDef = this.idl.classes[this.idlClass];
this.pkeyField = this.idlClassDef.pkey || 'id';
const search: any = {};
- search[this.orgField] = this.searchOrgs.orgIds || [this.contextOrg.id()];
+ if (this.orgField) {
+ search[this.orgField] =
+ this.searchOrgs.orgIds || [this.contextOrg.id()];
+ }
if (this.gridFilters) {
// Lay the URL grid filters over our search object.
this.translator.open({size: 'lg'});
}
+
+ // Construct a routerLink path for a configField.
+ configFieldRouteLink(row: any, col: GridColumn): string {
+ const cf = this.configFields.filter(field => field.name === col.name)[0];
+ const linkClass = this.idl.classes[cf['class']];
+ const pathParts = linkClass.table.split(/\./); // schema.tablename
+ return `${this.configLinkBasePath}/${pathParts[0]}/${pathParts[1]}`;
+ }
+
+ // Compiles a gridFilter value used when navigating to a linked
+ // class via configField. The filter ensures the linked page
+ // only shows rows which refer back to the object from which the
+ // link was clicked.
+ configFieldRouteParams(row: any, col: GridColumn): any {
+ const cf = this.configFields.filter(field => field.name === col.name)[0];
+ const linkClass = this.idl.classes[cf['class']];
+
+ // cf.key is the name of the field on the linked object that
+ // refers back to this object.
+
+ // The field definition on the linked class for the cf.key
+ // field has its own key, which refers to the name of the field on the
+ // on this object which provides the other end of the link between
+ // the two objects. This is typically the primary key field,
+ // but not necessarily.
+ const localField = linkClass.field_map[cf.key].key || this.pkeyField;
+
+ const filter: any = {};
+ filter[cf.key] = row[localField]();
+
+ return {gridFilters : JSON.stringify(filter)};
+ }
}