placeholder="{{field.label}}..."
i18n-placeholder
domId="{{idPrefix}}-{{field.name}}"
+ persistKey="{{field.persistKey}}"
[limitPerms]="modePerms[mode]"
[readOnly]="field.readOnly"
[applyDefault]="field.orgDefaultAllowed"
// from the default set of form inputs.
customTemplate?: CustomFieldTemplate;
+ // Use this persistKey if the field is an org field
+ persistKey?: StringComponent;
+
// help text to display via a popover
helpText?: StringComponent;
} else if (field.datatype === 'org_unit') {
field.orgDefaultAllowed =
this.orgDefaultAllowedList.includes(field.name);
+ if (fieldOptions.persistKey) {
+ field.persistKey = fieldOptions.persistKey;
+ }
}
if (fieldOptions.helpText) {
import {IdlObject} from '@eg/core/idl.service';
import {OrgService} from '@eg/core/org.service';
import {OrgSelectComponent} from '@eg/share/org-select/org-select.component';
+import {ServerStoreService} from '@eg/core/server-store.service';
export interface OrgFamily {
primaryOrgId: number;
@Input() domId: string;
+ @Input() persistKey: string;
+
@Output() onChange = new EventEmitter<any>();
@ViewChildren(OrgSelectComponent) orgSelects: QueryList<OrgSelectComponent>;
constructor(
private auth: AuthService,
- private org: OrgService
+ private org: OrgService,
+ private serverStore: ServerStoreService
) {
}
this.propagateChange(this.options);
this.onChange.emit(this.options);
+
+ if (this.persistKey) {
+ const key = `eg.orgfamilyselect.${this.persistKey}`;
+ this.serverStore.setItem(key, this.options);
+ }
};
+
+ this.loadPersistedValues();
+ }
+
+ private loadPersistedValues() {
+ if (!this.persistKey) return;
+
+ const key = `eg.orgfamilyselect.${this.persistKey}`;
+
+ this.serverStore.getItem(key).then(persistedOptions => {
+ if (persistedOptions) {
+ this.writeValue(persistedOptions);
+ }
+ });
}
writeValue(value: OrgFamily) {
<eg-admin-page persistKeyPfx="{{persistKeyPfx}}" idlClass="{{idlClass}}"
configLinkBasePath="{{configLinkBasePath}}"
fieldOrder="{{fieldOrder}}"
+ [fieldOptions]="fieldOptions"
readonlyFields="{{readonlyFields}}"
recordLabel="{{recordLabel}}"
orgDefaultAllowed="{{orgDefaultAllowed}}"
+ orgFieldsDefaultingToContextOrg="{{orgFieldsDefaultingToContextOrg}}"
+ contextOrgSelectorPersistKey="{{contextOrgSelectorPersistKey}}"
[hideClearFilters]="hideClearFilters"
[defaultNewRecord]="defaultNewRecordIdl"
[enableUndelete]="enableUndelete"
+ [disableDelete]="disableDelete"
+ [deleteConfirmation]="deleteConfirmation"
+ [disableEdit]="disableEdit"
[disableOrgFilter]="disableOrgFilter"></eg-admin-page>
</ng-container>
`
classLabel: string;
persistKeyPfx: string;
fieldOrder = '';
+ fieldOptions = {};
+ contextOrgSelectorPersistKey = '';
readonlyFields = '';
recordLabel = '';
orgDefaultAllowed = '';
+ orgFieldsDefaultingToContextOrg = '';
hideClearFilters: boolean;
defaultNewRecordIdl: IdlObject;
configLinkBasePath = '/staff/admin';
disableOrgFilter: boolean;
enableUndelete: boolean;
+ disableDelete: boolean;
+ deleteConfirmation: string;
+ disableEdit: boolean;
private getParams$: Observable<ParamMap>;
private getRouteData$: Observable<any>;
}
this.disableOrgFilter = data['disableOrgFilter'];
this.enableUndelete = data['enableUndelete'];
+ this.disableDelete = data['disableDelete'];
+ this.deleteConfirmation = data['deleteConfirmation'];
+ this.disableEdit = data['disableEdit'];
this.fieldOrder = data['fieldOrder'];
+ this.fieldOptions = data['fieldOptions'];
+ this.contextOrgSelectorPersistKey = data['contextOrgSelectorPersistKey'];
this.readonlyFields = data['readonlyFields'];
this.recordLabel = data['recordLabel'];
this.orgDefaultAllowed = data['orgDefaultAllowed'];
+ this.orgFieldsDefaultingToContextOrg = data['orgFieldsDefaultingToContextOrg'];
this.hideClearFilters = data['hideClearFilters'];
this.defaultNewRecord = data['defaultNewRecord'];
}
routerLink="/staff/admin/local/config/ui_staff_portal_page_entry"></eg-link-table-link>
<eg-link-table-link i18n-label label="Standing Penalties"
routerLink="/staff/admin/local/config/standing_penalty"></eg-link-table-link>
- <eg-link-table-link i18n-label label="Statistical Categories Editor"
- url="/eg/staff/admin/local/asset/stat_cat_editor"></eg-link-table-link>
<eg-link-table-link i18n-label label="Item Statistical Categories Editor"
routerLink="/staff/admin/local/asset/stat_cat"></eg-link-table-link>
<eg-link-table-link i18n-label label="Patron Statistical Categories Editor"
table: 'stat_cat',
readonlyFields: 'id',
orgDefaultAllowed: 'owner',
+ orgFieldsDefaultingToContextOrg: 'owner',
+ fieldOptions: {owner: {persistKey: 'admin.stat_cat.owner' } },
+ contextOrgSelectorPersistKey: 'admin.item_stat_cat.main_org_selector',
recordLabel: $localize `Item Statistical Category`,
+ deleteConfirmation: $localize `Are you sure you wish to delete the selected statistical categories? This will also remove the affected stat cats from any item records using them.`,
fieldOrder: 'name,owner,required,opac_visible,checkout_archive,sip_field,sip_format'}]
}, {
path: 'asset/stat_cat_entry',
table: 'stat_cat_entry',
readonlyFields: 'id,stat_cat',
orgDefaultAllowed: 'owner',
+ orgFieldsDefaultingToContextOrg: 'owner',
+ fieldOptions: {owner: {persistKey: 'admin.stat_cat.owner' } },
+ contextOrgSelectorPersistKey: 'admin.item_stat_cat.main_org_selector',
+ disableEdit: true,
+ disableDelete: true,
recordLabel: $localize `Item Statistical Category Entry`,
hideClearFilters: true,
fieldOrder: 'stat_cat,value,owner'}]
table: 'stat_cat',
readonlyFields: 'id',
orgDefaultAllowed: 'owner',
+ orgFieldsDefaultingToContextOrg: 'owner',
+ fieldOptions: {owner: {persistKey: 'admin.stat_cat.owner' } },
+ contextOrgSelectorPersistKey: 'admin.patron_stat_cat.main_org_selector',
recordLabel: $localize `Patron Statistical Category`,
+ deleteConfirmation: $localize `Are you sure you wish to delete the selected statistical categories? This will also remove the affected stat cats from any patron records using them.`,
fieldOrder: 'name,owner,required,opac_visible,usr_summary,allow_freetext,checkout_archive,sip_field,sip_format'}]
}, {
path: 'actor/stat_cat_entry',
table: 'stat_cat_entry',
readonlyFields: 'id,stat_cat',
orgDefaultAllowed: 'owner',
+ orgFieldsDefaultingToContextOrg: 'owner',
+ fieldOptions: {owner: {persistKey: 'admin.stat_cat.owner' } },
+ contextOrgSelectorPersistKey: 'admin.patron_stat_cat.main_org_selector',
+ disableEdit: true,
+ disableDelete: true,
recordLabel: $localize `Patron Statistical Category Entry`,
hideClearFilters: true,
fieldOrder: 'stat_cat,value,owner'}]
<ng-template #createErrStrTmpl i18n>Failed to create new {{recordLabel || idlClassDef.label}}</ng-template>
<eg-string #createErrString [template]="createErrStrTmpl"></eg-string>
+<eg-confirm-dialog #deleteConfirmDialog
+ i18n-dialogTitle
+ dialogTitle="Delete Selected Rows"
+ [dialogBodyTemplate]="deleteConfirmMsg">
+</eg-confirm-dialog>
+<ng-template #deleteConfirmMsg>
+ <span *ngIf="!deleteConfirmation" i18n>Are you sure you want to delete the selected rows? This will also delete any data depending on the rows deleted.</span>
+ <span *ngIf="deleteConfirmation">{{deleteConfirmation}}</span>
+</ng-template>
+
<ng-container *ngIf="orgField || gridFilters">
<div class="row">
<div class="col-lg-6">
<ng-container *ngIf="orgField">
<eg-org-family-select
+ [persistKey]="contextOrgSelectorPersistKey"
[limitPerms]="viewPerms"
[selectedOrgId]="contextOrg.id()"
[(ngModel)]="searchOrgs"
- (ngModelChange)="grid.reload()">
+ (ngModelChange)="contextOrgChanged($event)">
</eg-org-family-select>
</ng-container>
</div>
<span i18n>Filters Applied: {{gridFilters | json}}</span>
<a *ngIf="!hideClearFilters" class="ps-2 fst-italic"
[attr.href]="clearGridFiltersUrl()" i18n>Clear Filters</a>
+
+ <button class="btn btn-info label-with-material-icon"
+ (click)="goBack()" [disabled]="hasNoHistory()">
+ <span class="material-icons">keyboard_backspace</span>
+ <span i18n>Return</span>
+ </button>
</ng-container>
</div>
</div>
<eg-grid-toolbar-button [disabled]="translatableFields.length === 0"
label="Apply Translations" i18n-label (onClick)="translate()">
</eg-grid-toolbar-button>
- <eg-grid-toolbar-action label="Edit Selected" i18n-label (onClick)="editSelected($event)">
+ <eg-grid-toolbar-action label="Edit Selected" i18n-label
+ (onClick)="editSelected($event)" *ngIf="!disableEdit">
</eg-grid-toolbar-action>
<eg-grid-toolbar-action label="Delete Selected" i18n-label (onClick)="deleteSelected($event)"
- [disableOnRows]="shouldDisableDelete">
+ [disableOnRows]="shouldDisableDelete" *ngIf="!disableDelete">
</eg-grid-toolbar-action>
<eg-grid-toolbar-action label="Undelete Selected" i18n-label (onClick)="undeleteSelected($event)"
[disableOnRows]="shouldDisableUndelete" *ngIf="enableUndelete">
import {GridComponent} from '@eg/share/grid/grid.component';
import {TranslateComponent} from '@eg/share/translate/translate.component';
import {ToastService} from '@eg/share/toast/toast.service';
+import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
import {Pager} from '@eg/share/util/pager';
import {PcrudService} from '@eg/core/pcrud.service';
import {OrgService} from '@eg/core/org.service';
// Give the grid an option to undelete any deleted rows
@Input() enableUndelete: boolean;
+ // Remove the ability to delete rows
+ @Input() disableDelete: boolean;
+
+ // Optional: Replace the default deletion confirmation text with this
+ @Input() deleteConfirmation: string;
+
+ // Remove the ability to edit rows
+ @Input() disableEdit: boolean;
+
// Include objects linking to org units which are ancestors
// of the selected org unit.
@Input() includeOrgAncestors: boolean;
// following eg.grid.
@Input() persistKey: string;
+ // If present, will be applied to the org selector for the grid
+ @Input() contextOrgSelectorPersistKey: string;
+
// Optional path component to add to the generated grid persist key,
// formatted as (for example):
// 'eg.grid.admin.${persistKeyPfx}.config.billing_type'
// optional list of org fields which are allowed a default if unset
@Input() orgDefaultAllowed: string;
+ // list of org fields to receive the context org as their default for new records
+ @Input() orgFieldsDefaultingToContextOrg: string;
+
// Optional template containing help/about text which will
// be added to the page, above the grid.
@Input() helpTemplate: TemplateRef<any>;
@ViewChild('undeleteFailedString', { static: true }) undeleteFailedString: StringComponent;
@ViewChild('undeleteSuccessString', { static: true }) undeleteSuccessString: StringComponent;
@ViewChild('translator', { static: true }) translator: TranslateComponent;
+ @ViewChild('deleteConfirmDialog', { static: true })
+ private deleteConfirmDialog: ConfirmDialogComponent;
idlClassDef: any;
pkeyField: string;
}
}
+ contextOrgChanged(orgEvent: any) {
+ this.grid.reload();
+ this.setDefaultNewRecordOrgFieldDefaults( orgEvent['primaryOrgId'] );
+ }
+
ngOnInit() {
this.idlClassDef = this.idl.classes[this.idlClass];
this.checkCreatePerms();
this.applyOrgValues(Number(contextOrg));
+ this.setDefaultNewRecordOrgFieldDefaults( Number(contextOrg) );
+
// If the caller provides not data source, create a generic one.
if (!this.dataSource) {
this.initDataSource();
}
+
+ console.log('admin this',this);
+ }
+
+ setDefaultNewRecordOrgFieldDefaults(contextOrg: number) {
+ // however we get a defaultNewRecord, we may want to default some org fields to the context org
+ if (this.orgFieldsDefaultingToContextOrg) {
+ if (!this.defaultNewRecord) {
+ this.defaultNewRecord = this.idl.create(this.idlClass);
+ }
+ this.orgFieldsDefaultingToContextOrg.split(/,/).forEach( field => {
+ if (this.defaultNewRecord[field] && this.pkeyField !== field) {
+ if (contextOrg) {
+ // since this can change often, we'll just blow away anything that might have come in a different way
+ this.defaultNewRecord[field]( contextOrg );
+ }
+ }
+ });
+ }
}
checkCreatePerms() {
}
showEditDialog(idlThing: IdlObject): Promise<any> {
+ if (this.disableEdit) {
+ return;
+ }
this.editDialog.mode = 'update';
this.editDialog.recordId = idlThing[this.pkeyField]();
return new Promise((resolve, reject) => {
}
deleteSelected(idlThings: IdlObject[]) {
- idlThings.forEach(idlThing => idlThing.isdeleted(true));
- this.pcrud.autoApply(idlThings).subscribe(
- val => {
- this.deleteSuccessString.current()
- .then(str => this.toast.success(str));
- },
- err => {
- this.deleteFailedString.current()
- .then(str => this.toast.danger(str));
- },
- () => this.grid.reload()
- );
+ this.deleteConfirmDialog.open().subscribe(confirmed => {
+ if ( confirmed ) {
+ idlThings.forEach(idlThing => idlThing.isdeleted(true));
+ this.pcrud.autoApply(idlThings).subscribe(
+ val => {
+ this.deleteSuccessString.current()
+ .then(str => this.toast.success(str));
+ },
+ err => {
+ this.deleteFailedString.current()
+ .then(str => this.toast.danger(str));
+ },
+ () => this.grid.reload()
+ );
+ }
+ });
}
shouldDisableDelete(rows: IdlObject[]): boolean {
const url = this.configLinkBasePath + '/' + parts[0] + '/' + parts[1];
return this.ngLocation.prepareExternalUrl(url);
}
+
+ hasNoHistory(): boolean {
+ return history.length === 0;
+ }
+
+ goBack() {
+ history.back();
+ }
+
}
export interface TemplateField {
'Grid Config: admin.config.idl_field_doc',
'cwst', 'label'
)
+), (
+ 'eg.orgselect.admin.stat_cat.owner', 'gui', 'integer',
+ oils_i18n_gettext(
+ 'eg.orgselect.admin.stat_cat.owner',
+ 'Default org unit for stat cat and stat cat entry editors',
+ 'cwst', 'label'
+ )
+), (
+ 'eg.orgfamilyselect.admin.item_stat_cat.main_org_selector', 'gui', 'integer',
+ oils_i18n_gettext(
+ 'eg.orgfamilyselect.admin.item_stat_cat.main_org_selector',
+ 'Default org unit for the main org select in the item stat cat and stat cat entry admin interfaces.',
+ 'cwst', 'label'
+ )
+), (
+ 'eg.orgfamilyselect.admin.patron_stat_cat.main_org_selector', 'gui', 'integer',
+ oils_i18n_gettext(
+ 'eg.orgfamilyselect.admin.patron_stat_cat.main_org_selector',
+ 'Default org unit for the main org select in the patron stat cat and stat cat entry admin interfaces.',
+ 'cwst', 'label'
+ )
);
--- /dev/null
+
+BEGIN;
+
+--SELECT evergreen.upgrade_deps_block_check('XXXX', :eg_version);
+
+INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
+VALUES
+ (
+ 'eg.orgselect.admin.stat_cat.owner', 'gui', 'integer',
+ oils_i18n_gettext(
+ 'eg.orgselect.admin.stat_cat.owner',
+ 'Default org unit for stat cat and stat cat entry editors',
+ 'cwst', 'label'
+ )
+ ), (
+ 'eg.orgfamilyselect.admin.item_stat_cat.main_org_selector', 'gui', 'integer',
+ oils_i18n_gettext(
+ 'eg.orgfamilyselect.admin.item_stat_cat.main_org_selector',
+ 'Default org unit for the main org select in the item stat cat and stat cat entry admin interfaces.',
+ 'cwst', 'label'
+ )
+ ), (
+ 'eg.orgfamilyselect.admin.patron_stat_cat.main_org_selector', 'gui', 'integer',
+ oils_i18n_gettext(
+ 'eg.orgfamilyselect.admin.patron_stat_cat.main_org_selector',
+ 'Default org unit for the main org select in the patron stat cat and stat cat entry admin interfaces.',
+ 'cwst', 'label'
+ )
+ );
+
+COMMIT;
* Patron and staff login forms now include a button to reveal the password input. (LP#1977554)
* Adds new Local Administration entries for Item Statistical Categories Editor and Patron Statistical Categories Editor, which are angularized interfaces.
* Tweaks eg-grids to underline hyperlinks within cells. This potentially affects multiple interfaces.
+* eg-org-family-select now supports persistKey