--- /dev/null
+<eg-staff-banner bannerText="Local Admin Notifications/Action Triggers" i18n-bannerText>
+</eg-staff-banner>
+
+<ng-template #textAreaTemplate let-field="field" let-record="record">
+ <textarea class="form-control" name="{{field.name}}" [readonly]="field.readOnly"
+ [required]="field.isRequired()" [ngModel]="record[field.name]()"
+ (ngModelChange)="record[field.name]($event)" style="height: 600px;">
+ </textarea>
+</ng-template>
+<eg-fm-record-editor #eventDialog idlClass="atevdef"
+[fieldOptions]="{message_template:{customTemplate:{template:textAreaTemplate}},template:{customTemplate:{template:textAreaTemplate}}}"
+fieldOrder="owner,name,hook,active,delay,delay_field,group_field,reactor,validator,repeat_delay,id,cleanup_failure,granularity,max_delay,message_library_path,message_template,message_title,message_usr_path,opt_in_setting,usr_field,retention_interval,cleanup_success,template">
+</eg-fm-record-editor>
+<eg-fm-record-editor #hookDialog idlClass="ath"></eg-fm-record-editor>
+<eg-fm-record-editor #reactorDialog idlClass="atreact"></eg-fm-record-editor>
+<eg-fm-record-editor #validatorDialog idlClass="atval"></eg-fm-record-editor>
+
+<ngb-tabset #triggersTabs [activeId]="triggerTab" (tabChange)="onTabChange($event)"
+ class="mb-3">
+ <ngb-tab title="Event Definitions" i18n-title id="101">
+ <ng-template ngbTabContent>
+ <h4 class="mb-3 mt-3">Trigger Event Definitions</h4>
+ <eg-grid #eventsGrid idlClass="atevdef" [dataSource]="eventsDataSource"
+ showFields="owner,name,hook,active,delay,delay_field,group_field,reactor,validator,repeat_delay,granularity,retention_interval"
+ [stickyHeader]="true" [showLinkSelectors]="true" [sortable]="true"
+ (onRowActivate)="editSelected([$event])" [filterable]="true">
+ <eg-grid-toolbar-button label="New Event Definition" i18n-label
+ [action]="createNewEvent"></eg-grid-toolbar-button>
+ <eg-grid-toolbar-action label="Edit Selected" i18n-label
+ [action]="editSelected"></eg-grid-toolbar-action>
+ <eg-grid-toolbar-action label="Clone Selected" i18n-label
+ [action]="cloneSelected"></eg-grid-toolbar-action>
+ <eg-grid-toolbar-action label="Delete Selected" i18n-label
+ (onClick)="deleteSelected($event)"></eg-grid-toolbar-action>
+ <eg-grid-column i18n-label label="Owning Library" path="owner">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Name" path="name">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Hook" path="hook">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Enabled" path="active">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Processing Delay" path="delay" [filterable]="false">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Processing Delay Context Field" path="delay_field">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Processing Group Context Field" path="group_field">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Reactor" path="reactor">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Validator" path="validator">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Event Repeatability Delay" path="repeat_delay" [filterable]="false">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Granularity" path="granularity">
+ </eg-grid-column>
+ <eg-grid-column i18n-label label="Retention Interval" path="retention_interval" [filterable]="false">
+ </eg-grid-column>
+ </eg-grid>
+ </ng-template>
+ </ngb-tab>
+ <ngb-tab title="Hooks" i18n-title id="hooks">
+ <ng-template ngbTabContent>
+ <h4 class="mb-3 mt-3">Trigger Hooks</h4>
+ <eg-grid #hooksGrid idlClass="ath" [dataSource]="hooksDataSource"
+ (onRowActivate)="editSelected([$event])" [sortable]="true" [filterable]="true">
+ <eg-grid-toolbar-button label="New Hook" i18n-label [action]="createNewHook">
+ </eg-grid-toolbar-button>
+ <eg-grid-toolbar-action label="Edit Selected" i18n-label
+ [action]="editSelected"></eg-grid-toolbar-action>
+ <eg-grid-toolbar-action label="Delete Selected" i18n-label
+ (onClick)="deleteSelected($event)"></eg-grid-toolbar-action>
+ </eg-grid>
+ </ng-template>
+ </ngb-tab>
+ <ngb-tab title="Reactors" i18n-title id="reactors">
+ <ng-template ngbTabContent>
+ <h4 class="mb-3 mt-3">Trigger Reactors</h4>
+ <eg-grid #reactorsGrid idlClass="atreact" [dataSource]="reactorsDataSource"
+ (onRowActivate)="editSelected([$event])" [sortable]="true" [filterable]="true">
+ <eg-grid-toolbar-button label="New Reactor" i18n-label
+ [action]="createNewReactor"></eg-grid-toolbar-button>
+ <eg-grid-toolbar-action label="Edit Selected" i18n-label
+ [action]="editSelected"></eg-grid-toolbar-action>
+ <eg-grid-toolbar-action label="Delete Selected" i18n-label
+ (onClick)="deleteSelected($event)"></eg-grid-toolbar-action>
+ </eg-grid>
+ </ng-template>
+ </ngb-tab>
+ <ngb-tab title="Validators" i18n-title id="validators">
+ <ng-template ngbTabContent>
+ <h4 class="mb-3 mt-3">Trigger Validators</h4>
+ <eg-grid #validatorsGrid idlClass="atval" [dataSource]="validatorsDataSource"
+ (onRowActivate)="editSelected([$event])" [sortable]="true" [filterable]="true">
+ <eg-grid-toolbar-button label="New Validator" i18n-label
+ [action]="createNewValidator"></eg-grid-toolbar-button>
+ <eg-grid-toolbar-action label="Edit Selected" i18n-label
+ [action]="editSelected"></eg-grid-toolbar-action>
+ <eg-grid-toolbar-action label="Delete Selected" i18n-label
+ (onClick)="deleteSelected($event)"></eg-grid-toolbar-action>
+ </eg-grid>
+ </ng-template>
+ </ngb-tab>
+</ngb-tabset>
+
+<eg-string #createSuccessString i18n-text text="New entry Added"></eg-string>
+<eg-string #createErrString i18n-text text="Failed to create new entry"></eg-string>
+<eg-string #deleteFailedString i18n-text text="Delete of entry failed or was not allowed">
+</eg-string>
+<eg-string #deleteSuccessString i18n-text text="Delete of entry succeeded"></eg-string>
+<eg-string #updateFailedString i18n-text text="Update of entry failed or was not allowed">
+</eg-string>
+<eg-string #updateSuccessString i18n-text text="Update of entry succeeded"></eg-string>
+<eg-string #cloneFailedString i18n-text text="Clone of entry failed or was not allowed">
+</eg-string>
+<eg-string #cloneSuccessString i18n-text text="Clone of entry succeeded"></eg-string>
--- /dev/null
+import {Pager} from '@eg/share/util/pager';
+import {Component, OnInit, ViewChild} from '@angular/core';
+import {GridComponent} from '@eg/share/grid/grid.component';
+import {GridDataSource} from '@eg/share/grid/grid';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
+import {PcrudService} from '@eg/core/pcrud.service';
+import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
+import {StringComponent} from '@eg/share/string/string.component';
+import {ToastService} from '@eg/share/toast/toast.service';
+import {NgbTabChangeEvent} from '@ng-bootstrap/ng-bootstrap';
+
+@Component({
+ templateUrl: './triggers.component.html'
+})
+
+export class TriggersComponent implements OnInit {
+
+ eventsDataSource: GridDataSource = new GridDataSource();
+ hooksDataSource: GridDataSource = new GridDataSource();
+ reactorsDataSource: GridDataSource = new GridDataSource();
+ validatorsDataSource: GridDataSource = new GridDataSource();
+ triggerTab: string;
+ idlClass: string;
+
+ @ViewChild('eventDialog', {static: false}) eventDialog: FmRecordEditorComponent;
+ @ViewChild('hookDialog', {static: false}) hookDialog: FmRecordEditorComponent;
+ @ViewChild('reactorDialog', {static: false}) reactorDialog: FmRecordEditorComponent;
+ @ViewChild('validatorDialog', {static: false}) validatorDialog: FmRecordEditorComponent;
+
+ @ViewChild('eventsGrid', {static: false}) eventsGrid: GridComponent;
+ @ViewChild('hooksGrid', {static: false}) hooksGrid: GridComponent;
+ @ViewChild('reactorsGrid', {static: false}) reactorsGrid: GridComponent;
+ @ViewChild('validatorsGrid', {static: false}) validatorsGrid: GridComponent;
+
+ @ViewChild('updateSuccessString', {static: false}) updateSuccessString: StringComponent;
+ @ViewChild('updateFailedString', {static: false}) updateFailedString: StringComponent;
+ @ViewChild('cloneSuccessString', {static: false}) cloneSuccessString: StringComponent;
+ @ViewChild('cloneFailedString', {static: false}) cloneFailedString: StringComponent;
+ @ViewChild('deleteFailedString', {static: false}) deleteFailedString: StringComponent;
+ @ViewChild('deleteSuccessString', {static: false}) deleteSuccessString: StringComponent;
+ @ViewChild('createSuccessString', {static: false}) createSuccessString: StringComponent;
+ @ViewChild('createErrString', {static: false}) createErrString: StringComponent;
+
+ constructor(
+ private idl: IdlService,
+ private pcrud: PcrudService,
+ private toast: ToastService,
+ ) {
+ }
+
+ ngOnInit() {
+ this.eventsDataSource.getRows = (pager: Pager, sort: any[]) => {
+ const orderEventsBy: any = {atevdef: 'name'};
+ if (sort.length) {
+ orderEventsBy.atevdef = sort[0].name + ' ' + sort[0].dir;
+ }
+ return this.doSearch('atevdef', orderEventsBy, this.eventsDataSource, pager);
+ };
+
+ this.hooksDataSource.getRows = (pager: Pager, sort: any[]) => {
+ const orderHooksBy: any = {ath: 'key'};
+ if (sort.length) {
+ orderHooksBy.ath = sort[0].name + ' ' + sort[0].dir;
+ }
+ return this.doSearch('ath', orderHooksBy, this.hooksDataSource, pager);
+ };
+
+ this.reactorsDataSource.getRows = (pager: Pager, sort: any[]) => {
+ const orderReactorsBy: any = {atreact: 'module'};
+ if (sort.length) {
+ orderReactorsBy.atreact = sort[0].name + ' ' + sort[0].dir;
+ }
+ return this.doSearch('atreact', orderReactorsBy, this.reactorsDataSource, pager);
+ };
+
+ this.validatorsDataSource.getRows = (pager: Pager, sort: any[]) => {
+ const orderValidatorsBy: any = {atval: 'module'};
+ if (sort.length) {
+ orderValidatorsBy.atval = sort[0].name + ' ' + sort[0].dir;
+ }
+ return this.doSearch('atval', orderValidatorsBy, this.validatorsDataSource, pager);
+ };
+ }
+
+ doSearch(idlString: any, currentOrderBy: any, currentDataSource: any, pager: Pager) {
+ const base: Object = {};
+ base[this.idl.classes[idlString].pkey] = {'!=' : null};
+ const query: any = new Array();
+ query.push(base);
+ Object.keys(currentDataSource.filters).forEach(key => {
+ Object.keys(currentDataSource.filters[key]).forEach(key2 => {
+ query.push(currentDataSource.filters[key][key2]);
+ });
+ });
+ return this.pcrud.search(idlString,
+ query, {
+ offset: pager.offset,
+ limit: pager.limit,
+ order_by: currentOrderBy
+ });
+ }
+
+ onTabChange(event: NgbTabChangeEvent) {
+ this.triggerTab = event.nextId;
+ }
+
+ createNewEvent = () => {
+ this.createNewThing(this.eventDialog, this.eventsGrid);
+ }
+
+ createNewHook = () => {
+ this.createNewThing(this.hookDialog, this.hooksGrid);
+ }
+
+ createNewReactor = () => {
+ this.createNewThing(this.reactorDialog, this.reactorsGrid);
+ }
+
+ createNewValidator = () => {
+ this.createNewThing(this.validatorDialog, this.validatorsGrid);
+ }
+
+ createNewThing = (currentDialog: any, currentGrid: any) => {
+ currentDialog.mode = 'create';
+ currentDialog.recordId = null;
+ currentDialog.record = null;
+ currentDialog.open({size: 'lg'}).subscribe(
+ ok => {
+ this.createSuccessString.current()
+ .then(str => this.toast.success(str));
+ currentGrid.reload();
+ },
+ rejection => {
+ if (!rejection.dismissed) {
+ this.createErrString.current()
+ .then(str => this.toast.danger(str));
+ }
+ }
+ );
+ }
+
+ editSelected = (selectedRecords: IdlObject[]) => {
+ const editOneThing = (record: IdlObject) => {
+ if (!record) { return; }
+ this.showEditDialog(record).then(
+ () => editOneThing(selectedRecords.shift()));
+ };
+ editOneThing(selectedRecords.shift());
+ }
+
+ lookUpIdl (idl: string) {
+ let currentDialog;
+ let currentGrid;
+ switch (idl) {
+ case 'atevdef':
+ currentDialog = this.eventDialog;
+ currentGrid = this.eventsGrid;
+ break;
+ case 'ath':
+ currentDialog = this.hookDialog;
+ currentGrid = this.hooksGrid;
+ break;
+ case 'atreact':
+ currentDialog = this.reactorDialog;
+ currentGrid = this.reactorsGrid;
+ break;
+ case 'atval':
+ currentDialog = this.validatorDialog;
+ currentGrid = this.validatorsGrid;
+ break;
+ default:
+ console.debug('Unknown class name');
+ }
+ return {currentDialog: currentDialog, currentGrid: currentGrid};
+ }
+
+ showEditDialog = (selectedRecord: IdlObject): Promise<any> => {
+ const idl = selectedRecord.classname;
+ const lookupResults = this.lookUpIdl(idl);
+ const currentDialog = lookupResults.currentDialog;
+ const currentGrid = lookupResults.currentGrid;
+ currentDialog.mode = 'update';
+ const clone = this.idl.clone(selectedRecord);
+ currentDialog.record = clone;
+ return new Promise((resolve, reject) => {
+ currentDialog.open({size: 'lg'}).subscribe(
+ result => {
+ this.updateSuccessString.current()
+ .then(str => this.toast.success(str));
+ currentGrid.reload();
+ resolve(result);
+ },
+ error => {
+ this.updateFailedString.current()
+ .then(str => this.toast.danger(str));
+ reject(error);
+ }
+ );
+ });
+ }
+
+ deleteSelected = (idlThings: IdlObject[]) => {
+ const idl = idlThings[0].classname;
+ const currentGrid = this.lookUpIdl(idl).currentGrid;
+ idlThings.forEach(idlThing => idlThing.isdeleted(true));
+ this.pcrud.autoApply(idlThings).subscribe(
+ val => {
+ console.debug('deleted: ' + val);
+ this.deleteSuccessString.current()
+ .then(str => this.toast.success(str));
+ currentGrid.reload();
+ },
+ err => {
+ this.deleteFailedString.current()
+ .then(str => this.toast.danger(str));
+ }
+ );
+ }
+
+ cloneSelected = (idlThings: IdlObject[]) => {
+ const clone = this.idl.clone(idlThings[0]);
+ clone.id(null);
+ this.eventDialog.mode = 'create';
+ this.eventDialog.recordId = null;
+ this.eventDialog.record = clone;
+ this.eventDialog.open({size: 'lg'}).subscribe(
+ ok => {
+ this.cloneSuccessString.current()
+ .then(str => this.toast.success(str));
+ this.eventsGrid.reload();
+ },
+ rejection => {
+ if (!rejection.dismissed) {
+ this.cloneFailedString.current()
+ .then(str => this.toast.danger(str));
+ }
+ }
+ );
+ }
+}