* for stat cats and stat cat entries in the IDL, make sure we have pcrud controller enabled and pcrud permissions set. Also set config_field for "entries" so that the AdminPage component can link them out to their own admin pages
* item and patron stat cat admin pages
* lp1857911 release notes
Leverages the BasicAdminPage component, with some tweaks.
Changes to the BasicAdminPage and AdminPage components all default to off, so should not affect existing interfaces:
* add an option to hide the Clear Filters action from subordinate admin pages (when you follow config fields)
* add an option to propagate recordLabel to the fmEditor component, and also use said label within the admin page
* add an option to propagate orgDefaultAllowed to the fmEditor component
For the stat cat and entry admin pages specifically, we leverage these to:
* hide Clear Filters so that we don't let the user get into a situation where they try to create a new stat cat entry but have a blank and unsettable stat cat field (because we mark that field as read-only in the fmEditor)
* default the Owner field for new stat cats and entries to the workstation library
* use Item and Patron instead of Asset and Actor in various labels (at least until we're ready to make that change wholesale in the IDL)
Signed-off-by: Jason Etheridge <jason@EquinoxOLI.org>
Signed-off-by: Jane Sandberg <js7389@princeton.edu>
</class>
<class id="asc" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="asset::stat_cat" oils_persist:tablename="asset.stat_cat" reporter:label="Asset Statistical Category">
<fields oils_persist:primary="id" oils_persist:sequence="asset.stat_cat_id_seq">
- <field reporter:label="Entries" name="entries" oils_persist:virtual="true" reporter:datatype="link"/>
+ <field reporter:label="Entries" name="entries" oils_persist:virtual="true" reporter:datatype="link" config_field="true"/>
<field reporter:label="Stat Cat ID" name="id" reporter:datatype="id" reporter:selector="name"/>
<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true"/>
<field reporter:label="OPAC Visible" name="opac_visible" reporter:datatype="bool"/>
</links>
<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
<actions>
+ <create permission="CREATE_COPY_STAT_CAT" context_field="owner"/>
<retrieve permission="STAFF_LOGIN" global_required="true"/>
- </actions>
+ <retrieve />
+ <update permission="UPDATE_COPY_STAT_CAT" context_field="owner"/>
+ <delete permission="DELETE_COPY_STAT_CAT" context_field="owner"/>
+ </actions>
</permacrud>
</class>
<class id="ac" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::card" oils_persist:tablename="actor.card" reporter:label="Library Card">
</class>
<class id="actsc" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::stat_cat" oils_persist:tablename="actor.stat_cat" reporter:label="User Statistical Category">
<fields oils_persist:primary="id" oils_persist:sequence="actor.stat_cat_id_seq">
- <field reporter:label="Entries" name="entries" oils_persist:virtual="true" reporter:datatype="link"/>
+ <field reporter:label="Entries" name="entries" oils_persist:virtual="true" reporter:datatype="link" config_field="true"/>
<field reporter:label="Default Entries" name="default_entries" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Stat Cat ID" name="id" reporter:datatype="id" reporter:selector="name"/>
<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true"/>
</actions>
</permacrud>
</class>
- <class id="actsce" controller="open-ils.cstore" oils_obj:fieldmapper="actor::stat_cat_entry" oils_persist:tablename="actor.stat_cat_entry" reporter:label="User Stat Cat Entry">
+ <class id="actsce" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::stat_cat_entry" oils_persist:tablename="actor.stat_cat_entry" reporter:label="User Stat Cat Entry">
<fields oils_persist:primary="id" oils_persist:sequence="actor.stat_cat_entry_id_seq">
<field reporter:label="Entry ID" name="id" reporter:datatype="id" />
<field reporter:label="Entry Owner" name="owner" reporter:datatype="link"/>
<link field="owner" reltype="has_a" key="id" map="" class="aou"/>
<link field="default_entries" reltype="has_many" key="stat_cat_entry" map="" class="actsced"/>
</links>
+ <permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
+ <actions>
+ <create permission="CREATE_PATRON_STAT_CAT_ENTRY">
+ <context link="stat_cat" field="owner"/>
+ </create>
+ <retrieve permission="STAFF_LOGIN" global_required="true"/>
+ <update permission="UPDATE_PATRON_STAT_CAT_ENTRY">
+ <context link="stat_cat" field="owner"/>
+ </update>
+ <delete permission="DELETE_PATRON_STAT_CAT_ENTRY">
+ <context link="stat_cat" field="owner"/>
+ </delete>
+ </actions>
+ </permacrud>
</class>
<class id="actsced" controller="open-ils.cstore" oils_obj:fieldmapper="actor::stat_cat_entry_default" oils_persist:tablename="actor.stat_cat_entry_default" reporter:label="User Stat Cat Default Entry">
<fields oils_persist:primary="id" oils_persist:sequence="actor.stat_cat_entry_default_id_seq">
</links>
<permacrud xmlns="http://open-ils.org/spec/opensrf/IDL/permacrud/v1">
<actions>
+ <create permission="CREATE_COPY_STAT_CAT_ENTRY">
+ <context link="stat_cat" field="owner"/>
+ </create>
<retrieve permission="STAFF_LOGIN" global_required="true"/>
+ <update permission="UPDATE_COPY_STAT_CAT_ENTRY">
+ <context link="stat_cat" field="owner"/>
+ </update>
+ <delete permission="DELETE_COPY_STAT_CAT_ENTRY">
+ <context link="stat_cat" field="owner"/>
+ </delete>
</actions>
</permacrud>
</class>
@Input() configLinkBasePath: string;
@Input() defaultNewRecord: IdlObject;
@Input() disableOrgFilter: boolean;
+ @Input() hideClearFilters: boolean;
@Input() fieldOrder: string;
@Input() idlClass: string;
@Input() persistKeyPfx: string;
@Input() readonlyFields: string;
@Input() enableUndelete: boolean;
+ @Input() recordLabel: string;
+ @Input() orgDefaultAllowed: string;
}
describe('Component: BasicAdminPage', () => {
@Component({
template: `
<ng-container *ngIf="idlClass">
- <eg-title i18n-prefix prefix="{{classLabel}} Administration">
+ <eg-title i18n-prefix prefix="{{recordLabel || classLabel}} Administration">
</eg-title>
- <eg-staff-banner bannerText="{{classLabel}} Configuration" i18n-bannerText>
+ <eg-staff-banner bannerText="{{recordLabel || classLabel}} Configuration" i18n-bannerText>
</eg-staff-banner>
<eg-admin-page persistKeyPfx="{{persistKeyPfx}}" idlClass="{{idlClass}}"
configLinkBasePath="{{configLinkBasePath}}"
fieldOrder="{{fieldOrder}}"
readonlyFields="{{readonlyFields}}"
+ recordLabel="{{recordLabel}}"
+ orgDefaultAllowed="{{orgDefaultAllowed}}"
+ [hideClearFilters]="hideClearFilters"
[defaultNewRecord]="defaultNewRecordIdl"
[enableUndelete]="enableUndelete"
[disableOrgFilter]="disableOrgFilter"></eg-admin-page>
persistKeyPfx: string;
fieldOrder = '';
readonlyFields = '';
+ recordLabel = '';
+ orgDefaultAllowed = '';
+ hideClearFilters: boolean;
defaultNewRecordIdl: IdlObject;
configLinkBasePath = '/staff/admin';
this.enableUndelete = data['enableUndelete'];
this.fieldOrder = data['fieldOrder'];
this.readonlyFields = data['readonlyFields'];
+ this.recordLabel = data['recordLabel'];
+ this.orgDefaultAllowed = data['orgDefaultAllowed'];
+ this.hideClearFilters = data['hideClearFilters'];
this.defaultNewRecord = data['defaultNewRecord'];
}
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"
+ routerLink="/staff/admin/local/actor/stat_cat"></eg-link-table-link>
<eg-link-table-link i18n-label label="Statistical Popularity Badges"
routerLink="/staff/admin/local/rating/badge"></eg-link-table-link>
<eg-link-table-link i18n-label label="Surveys"
loadChildren: () =>
import('./negative-balances/negative-balances.module').then(m => m.NegativeBalancesModule)
}, {
+ path: 'asset/stat_cat',
+ component: BasicAdminPageComponent,
+ data: [{
+ schema: 'asset',
+ table: 'stat_cat',
+ readonlyFields: 'id',
+ orgDefaultAllowed: 'owner',
+ recordLabel: $localize `Item Statistical Category`,
+ fieldOrder: 'name,owner,required,opac_visible,checkout_archive,sip_field,sip_format'}]
+}, {
+ path: 'asset/stat_cat_entry',
+ component: BasicAdminPageComponent,
+ data: [{
+ schema: 'asset',
+ table: 'stat_cat_entry',
+ readonlyFields: 'id,stat_cat',
+ orgDefaultAllowed: 'owner',
+ recordLabel: $localize `Item Statistical Category Entry`,
+ hideClearFilters: true,
+ fieldOrder: 'stat_cat,value,owner'}]
+}, {
+ path: 'actor/stat_cat',
+ component: BasicAdminPageComponent,
+ data: [{
+ schema: 'actor',
+ table: 'stat_cat',
+ readonlyFields: 'id',
+ orgDefaultAllowed: 'owner',
+ recordLabel: $localize `Patron Statistical Category`,
+ fieldOrder: 'name,owner,required,opac_visible,usr_summary,allow_freetext,checkout_archive,sip_field,sip_format'}]
+}, {
+ path: 'actor/stat_cat_entry',
+ component: BasicAdminPageComponent,
+ data: [{
+ schema: 'actor',
+ table: 'stat_cat_entry',
+ readonlyFields: 'id,stat_cat',
+ orgDefaultAllowed: 'owner',
+ recordLabel: $localize `Patron Statistical Category Entry`,
+ hideClearFilters: true,
+ fieldOrder: 'stat_cat,value,owner'}]
+}, {
path: ':schema/:table',
component: BasicAdminPageComponent
}
-<ng-template #successStrTmpl i18n>{{idlClassDef.label}} Update Succeeded</ng-template>
+<ng-template #successStrTmpl i18n>{{recordLabel || idlClassDef.label}} Update Succeeded</ng-template>
<eg-string #successString [template]="successStrTmpl"></eg-string>
-<ng-template #updateFailedStrTmpl i18n>Update of {{idlClassDef.label}} failed</ng-template>
+<ng-template #updateFailedStrTmpl i18n>Update of {{recordLabel || idlClassDef.label}} failed</ng-template>
<eg-string #updateFailedString [template]="updateFailedStrTmpl"></eg-string>
-<ng-template #deleteFailedStrTmpl i18n>Delete of {{idlClassDef.label}} failed or was not allowed</ng-template>
+<ng-template #deleteFailedStrTmpl i18n>Delete of {{recordLabel || idlClassDef.label}} failed or was not allowed</ng-template>
<eg-string #deleteFailedString [template]="deleteFailedStrTmpl"></eg-string>
-<ng-template #deleteSuccessStrTmpl i18n>{{idlClassDef.label}} Successfully Deleted</ng-template>
+<ng-template #deleteSuccessStrTmpl i18n>{{recordLabel || idlClassDef.label}} Successfully Deleted</ng-template>
<eg-string #deleteSuccessString [template]="deleteSuccessStrTmpl"></eg-string>
<ng-template #undeleteFailedStrTmpl i18n>Undelete of {{idlClassDef.label}} failed or was not allowed</ng-template>
<ng-template #undeleteSuccessStrTmpl i18n>{{idlClassDef.label}} Successfully undeleted</ng-template>
<eg-string #undeleteSuccessString [template]="undeleteSuccessStrTmpl"></eg-string>
-<ng-template #createStrTmpl i18n>{{idlClassDef.label}} Successfully Created</ng-template>
+<ng-template #createStrTmpl i18n>{{recordLabel || idlClassDef.label}} Successfully Created</ng-template>
<eg-string #createString [template]="createStrTmpl"></eg-string>
-<ng-template #createErrStrTmpl i18n>Failed to create new {{idlClassDef.label}}</ng-template>
+<ng-template #createErrStrTmpl i18n>Failed to create new {{recordLabel || idlClassDef.label}}</ng-template>
<eg-string #createErrString [template]="createErrStrTmpl"></eg-string>
<ng-container *ngIf="orgField || gridFilters">
<div class="flex-1"></div><!-- push right -->
<ng-container *ngIf="gridFilters">
<span i18n>Filters Applied: {{gridFilters | json}}</span>
- <a class="ps-2 fst-italic"
+ <a *ngIf="!hideClearFilters" class="ps-2 fst-italic"
[attr.href]="clearGridFiltersUrl()" i18n>Clear Filters</a>
</ng-container>
</div>
(onRowActivate)="showEditDialog($event)"
[filterable]="true" [stickyHeader]="true">
<eg-grid-toolbar-button [disabled]="!canCreate"
- label="New {{idlClassDef.label}}" i18n-label (onClick)="createNew()">
+ label="New {{recordLabel || idlClassDef.label}}" i18n-label (onClick)="createNew()">
</eg-grid-toolbar-button>
<eg-grid-toolbar-button [disabled]="translatableFields.length === 0"
label="Apply Translations" i18n-label (onClick)="translate()">
</eg-grid>
<eg-fm-record-editor #editDialog idlClass="{{idlClass}}"
+ [recordLabel]="recordLabel"
[fieldOptions]="fieldOptions"
[fieldOrder]="fieldOrder"
[defaultNewRecord]="defaultNewRecord"
[preloadLinkedValues]="true"
+ [orgDefaultAllowed]="orgDefaultAllowed"
[readonlyFields]="readonlyFields">
</eg-fm-record-editor>
// Optional comma-separated list of read-only fields
@Input() readonlyFields: string;
+ // Optional record label to use instead of the IDL label
+ @Input() recordLabel: string;
+
+ // optional flag to hide the Clear Filters action for gridFilters
+ @Input() hideClearFilters: boolean;
+
+ // optional list of org fields which are allowed a default if unset
+ @Input() orgDefaultAllowed: string;
+
// Optional template containing help/about text which will
// be added to the page, above the grid.
@Input() helpTemplate: TemplateRef<any>;
UPDATE_COPY permission the new UPDATE_COPY_BARCODE permission at the
same depth, though it's technically not needed.
* 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.