<field reporter:label="Name" name="name" reporter:datatype="text"/>
<field reporter:label="Renewal?" name="is_renewal" reporter:datatype="float"/>
<field reporter:label="Org Unit" name="org_unit" reporter:datatype="float"/>
- <field reporter:label="Copy Circ Lib" name="copy_circ_lib" reporter:datatype="float"/>
- <field reporter:label="Copy Owning Lib" name="copy_owning_lib" reporter:datatype="float"/>
+ <field reporter:label="Item Circ Library" name="copy_circ_lib" reporter:datatype="float"/>
+ <field reporter:label="Item Owning Library" name="copy_owning_lib" reporter:datatype="float"/>
<field reporter:label="User Home Lib" name="user_home_ou" reporter:datatype="float"/>
<field reporter:label="Permission Group" name="grp" reporter:datatype="float"/>
<field reporter:label="Circulation Modifier" name="circ_modifier" reporter:datatype="float"/>
- <field reporter:label="Copy Location" name="copy_location" reporter:datatype="float"/>
+ <field reporter:label="Shelving Location" name="copy_location" reporter:datatype="float"/>
<field reporter:label="MARC Type" name="marc_type" reporter:datatype="float"/>
<field reporter:label="MARC Form" name="marc_form" reporter:datatype="float"/>
<field reporter:label="MARC Bib Level" name="marc_bib_level" reporter:datatype="float"/>
<fields oils_persist:primary="id" oils_persist:sequence="config.circ_matrix_matchpoint_id_seq">
<field reporter:label="Matchpoint ID" name="id" reporter:datatype="id"/>
<field reporter:label="Renewal?" name="is_renewal" reporter:datatype="bool"/>
- <field reporter:label="Active?" name="active" reporter:datatype="bool"/>
- <field reporter:label="Org Unit" name="org_unit" reporter:datatype="org_unit" oils_obj:required="true"/>
- <field reporter:label="Copy Circ Lib" name="copy_circ_lib" reporter:datatype="org_unit"/>
- <field reporter:label="Copy Owning Lib" name="copy_owning_lib" reporter:datatype="org_unit"/>
+ <field reporter:label="Active?" name="active" reporter:datatype="bool" oils_obj:required="true"/>
+ <field reporter:label="Checkout Library" name="org_unit" reporter:datatype="org_unit" oils_obj:required="true"/>
+ <field reporter:label="Item Circ Library" name="copy_circ_lib" reporter:datatype="org_unit"/>
+ <field reporter:label="Item Owning Library" name="copy_owning_lib" reporter:datatype="org_unit"/>
<field reporter:label="User Home Lib" name="user_home_ou" reporter:datatype="org_unit"/>
<field reporter:label="Permission Group" name="grp" reporter:datatype="link" oils_obj:required="true"/>
<field reporter:label="Circulation Modifier" name="circ_modifier" oils_persist:primitive="string" reporter:datatype="link"/>
- <field reporter:label="Copy Location" name="copy_location" reporter:datatype="link"/>
+ <field reporter:label="Shelving Location" name="copy_location" reporter:datatype="link"/>
<field reporter:label="MARC Type" name="marc_type" oils_persist:primitive="string" reporter:datatype="link"/>
<field reporter:label="MARC Form" name="marc_form" oils_persist:primitive="string" reporter:datatype="link"/>
<field reporter:label="MARC Bib Level" name="marc_bib_level" oils_persist:primitive="string" reporter:datatype="link"/>
<field name="total_copy_hold_ratio" reporter:datatype="float" reporter:label="Minimum Total Copy/Hold Ratio"/>
<field name="available_copy_hold_ratio" reporter:datatype="float" reporter:label="Minimum Available Copy/Hold Ratio"/>
<field name="description" reporter:datatype="text" reporter:label="Description"/>
- <field name="renew_extends_due_date" reporter:datatype="bool" reporter:label="Early Renewal Extends Due Date"/>
+ <field name="renew_extends_due_date" reporter:datatype="bool" reporter:label="Early Renewal Extends Due Date" oils_obj:required="true"/>
<field name="renew_extend_min_interval" reporter:datatype="interval" reporter:label="Early Renewal Minimum Duration Interval"/>
</fields>
<links>
</actions>
</permacrud>
</class>
- <class id="cclsacpl" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::circ_limit_set_copy_loc_map" oils_persist:tablename="config.circ_limit_set_copy_loc_map" reporter:label="Circulation Limit Set Copy Location Map">
+ <class id="cclsacpl" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="config::circ_limit_set_copy_loc_map" oils_persist:tablename="config.circ_limit_set_copy_loc_map" reporter:label="Circulation Limit Set Shelving Location Map">
<fields oils_persist:primary="id" oils_persist:sequence="config.circ_limit_set_copy_loc_map_id_seq">
<field reporter:label="ID" name="id" reporter:datatype="id"/>
<field reporter:label="Limit Set" name="limit_set" reporter:datatype="link"/>
- <field reporter:label="Copy Location" name="copy_loc" reporter:datatype="link"/>
+ <field reporter:label="Shelving Location" name="copy_loc" reporter:datatype="link"/>
</fields>
<links>
<link field="limit_set" reltype="has_a" key="id" map="" class="ccls"/>
<field reporter:label="Patron Birth Year" name="usr_birth_year" reporter:datatype="int"/>
<field reporter:label="Call Number" name="copy_call_number" reporter:datatype="link"/>
<field reporter:label="Shelving Location" name="copy_location" reporter:datatype="link"/>
- <field reporter:label="Copy Owning Library" name="copy_owning_lib" reporter:datatype="link"/>
+ <field reporter:label="Item Owning Library" name="copy_owning_lib" reporter:datatype="link"/>
<field reporter:label="Copy Circulating Library" name="copy_circ_lib" reporter:datatype="link"/>
<field reporter:label="Bib Record" name="copy_bib_record" reporter:datatype="link"/>
<field reporter:label="Archived Patron Stat-Cat Entries" name="aaactsc_entries" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Patron Birth Year" name="usr_birth_year" reporter:datatype="int"/>
<field reporter:label="Call Number" name="copy_call_number" reporter:datatype="link"/>
<field reporter:label="Shelving Location" name="copy_location" reporter:datatype="link"/>
- <field reporter:label="Copy Owning Library" name="copy_owning_lib" reporter:datatype="link"/>
+ <field reporter:label="Item Owning Library" name="copy_owning_lib" reporter:datatype="link"/>
<field reporter:label="Copy Circulating Library" name="copy_circ_lib" reporter:datatype="link"/>
<field reporter:label="Bib Record" name="copy_bib_record" reporter:datatype="link"/>
<field reporter:label="Archived Patron Stat-Cat Entries" name="aaactsc_entries" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Name" name="name" reporter:datatype="text" oils_persist:i18n="true"/>
<field reporter:label="Is OPAC Visible?" name="opac_visible" reporter:datatype="bool"/>
<field reporter:label="Owning Org Unit" name="owning_lib" reporter:datatype="org_unit"/>
- <field reporter:label="Copy Location Orders" name="orders" oils_persist:virtual="true" reporter:datatype="link"/>
+ <field reporter:label="Shelving Location Orders" name="orders" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Copies" name="copies" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Label Prefix" name="label_prefix" reporter:datatype="text" oils_persist:i18n="true"/>
<field reporter:label="Label Suffix" name="label_suffix" reporter:datatype="text" oils_persist:i18n="true"/>
<field reporter:label="Owning Library" name="owner" reporter:datatype="org_unit" />
<field reporter:label="Position" name="pos" reporter:datatype="int"/>
<field reporter:label="Display Above Orgs" name="top" reporter:datatype="bool"/>
- <field reporter:label="Copy Location Mappings" name="location_maps" oils_persist:virtual="true" reporter:datatype="link"/>
+ <field reporter:label="Shelving Location Mappings" name="location_maps" oils_persist:virtual="true" reporter:datatype="link"/>
</fields>
<links>
<link field="owner" reltype="has_a" key="id" map="" class="aou"/>
<fields oils_persist:primary="id" oils_persist:sequence="asset.copy_location_group_map_id_seq">
<field reporter:label="ID" name="id" reporter:selector="name" reporter:datatype="id"/>
<field reporter:label="Group" name="lgroup" reporter:datatype="link"/>
- <field reporter:label="Copy Location" name="location" reporter:datatype="link"/>
+ <field reporter:label="Shelving Location" name="location" reporter:datatype="link"/>
</fields>
<links>
<link field="lgroup" reltype="has_a" key="id" map="" class="acplg"/>
<class id="aoupa" controller="open-ils.cstore open-ils.pcrud" oils_obj:fieldmapper="actor::org_unit_proximity_adjustment" oils_persist:tablename="actor.org_unit_proximity_adjustment" reporter:label="Org Unit Proximity Adjustment">
<fields oils_persist:primary="id" oils_persist:sequence="actor.org_unit_proximity_adjustment_id_seq">
<field name="id" reporter:label="ID" reporter:datatype="id" />
- <field name="item_circ_lib" reporter:label="Item Circ Lib" reporter:datatype="org_unit"/>
- <field name="item_owning_lib" reporter:label="Item Owning Lib" reporter:datatype="org_unit"/>
+ <field name="item_circ_lib" reporter:label="Item Circ Library" reporter:datatype="org_unit"/>
+ <field name="item_owning_lib" reporter:label="Item Owning Library" reporter:datatype="org_unit"/>
<field name="hold_pickup_lib" reporter:label="Hold Pickup Lib" reporter:datatype="org_unit"/>
<field name="hold_request_lib" reporter:label="Hold Request Lib" reporter:datatype="org_unit"/>
- <field name="copy_location" reporter:label="Copy Location" reporter:datatype="link"/>
+ <field name="copy_location" reporter:label="Shelving Location" reporter:datatype="link"/>
<field name="circ_mod" reporter:label="Circ Modifier" reporter:datatype="link"/>
<field name="pos" reporter:label="Position" reporter:datatype="int" oils_obj:required="true" />
<field name="absolute_adjustment" reporter:label="Absolute adjustment?" reporter:datatype="bool" />
<field reporter:label="Notes" name="notes" reporter:datatype="link" oils_persist:virtual="true"/>
<field reporter:label="Current Shelf Lib" name="current_shelf_lib" reporter:datatype="org_unit"/>
<field reporter:label="Acquisition Request" name="acq_request" reporter:datatype="link" />
- <field reporter:label="Copy Location Sort Order" name="copy_location_order_position" reporter:datatype="int" />
+ <field reporter:label="Shelving Location Sort Order" name="copy_location_order_position" reporter:datatype="int" />
<field reporter:label="User First Given Name" name="usr_first_given_name" reporter:datatype="text" />
<field reporter:label="User Second Given Name" name="usr_second_given_name" reporter:datatype="text" />
<field reporter:label="User Family Name" name="usr_family_name" reporter:datatype="text" />
<field reporter:label="Checkins" name="checkins" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Workstations" name="workstations" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Fund Allocation Percentages" name="fund_alloc_pcts" oils_persist:virtual="true" reporter:datatype="link"/>
- <field reporter:label="Copy Location Orders" name="copy_location_orders" oils_persist:virtual="true" reporter:datatype="link"/>
+ <field reporter:label="Shelving Location Orders" name="copy_location_orders" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Transit Copy Prev Destinations" name="atc_prev_dests" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Reservation Requests" name="resv_requests" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="Reservation Pickups" name="resv_pickups" oils_persist:virtual="true" reporter:datatype="link"/>
<field reporter:label="State" name="state" reporter:datatype="text"/>
<field reporter:label="Event" name="event" reporter:datatype="text" />
<field reporter:label="During Renewal" name="in_renew" reporter:datatype="bool" />
- <field reporter:label="Allow At Copy Circ Lib" name="at_circ" reporter:datatype="bool"/>
- <field reporter:label="Allow At Copy Owning Lib" name="at_owning" reporter:datatype="bool"/>
+ <field reporter:label="Allow At Item Circ Library" name="at_circ" reporter:datatype="bool"/>
+ <field reporter:label="Allow At Item Owning Library" name="at_owning" reporter:datatype="bool"/>
<field reporter:label="Invert allowed locations" name="invert_location" reporter:datatype="bool"/>
<field reporter:label="Next Statuses" name="next_status" reporter:datatype="text"/>
</fields>
<field reporter:label="Fund" name="fund" reporter:datatype="link" />
<field reporter:label="Fund Debit" name="fund_debit" reporter:datatype="link" />
<field reporter:label="Owning Library" name="owning_lib" reporter:datatype="org_unit" />
- <field reporter:label="Copy Location" name="location" reporter:datatype="link" />
+ <field reporter:label="Shelving Location" name="location" reporter:datatype="link" />
<field reporter:label="Circ Modifier" name="circ_modifier" reporter:datatype="link" />
<field reporter:label="Note" name="note" reporter:datatype="text" />
<field reporter:label="Collection Code" name="collection_code" reporter:datatype="text" />
--- /dev/null
+label {
+ margin-left: 8px;
+}
--- /dev/null
+<div *ngFor="let option of options; let i = index">
+ <input
+ type="radio"
+ [name]="name"
+ [value]="option.value"
+ [(ngModel)]="_value"
+ (change)="value = (i === 0)"
+ [checked]="_value === (i === 0)"
+ [required]="required"
+ [disabled]="disabled"
+ [id]="name + '-' + option.value"
+ />
+ <label [for]="name + '-' + option.value">{{ option.label }}</label>
+</div>
--- /dev/null
+import { Component, ChangeDetectorRef, forwardRef, OnInit, Input, Output } from '@angular/core';
+import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
+
+@Component({
+ selector: 'eg-bool-select',
+ templateUrl: './boolean-select.component.html',
+ styleUrls: ['./boolean-select.component.css'],
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => BooleanSelectComponent),
+ multi: true
+ }
+ ]
+})
+
+export class BooleanSelectComponent implements ControlValueAccessor {
+
+ @Input() label: string;
+ @Input() name: string;
+ @Input() options: Array<{ label: string; value: any }> = [
+ { label: $localize`Yes`, value: true },
+ { label: $localize`No`, value: false },
+ ];
+ private _value: boolean = false;
+ private _disabled: boolean = false;
+ private _required: boolean = false;
+
+ onChange: (value: boolean) => void = () => {};
+ onTouched: () => void = () => {};
+
+ get value(): boolean {
+ return this._value;
+ }
+
+ set value(value: boolean) {
+ this._value = value;
+ this.onChange(value);
+ this.onTouched();
+ }
+
+ writeValue(value: any): void {
+ this._value = value;
+ this.cdr.detectChanges();
+ }
+
+ registerOnChange(fn: (value: boolean) => void): void {
+ this.onChange = fn;
+ }
+
+ registerOnTouched(fn: () => void): void {
+ this.onTouched = fn;
+ }
+
+ get disabled(): boolean {
+ return this._disabled;
+ }
+
+ set disabled(value: boolean) {
+ this._disabled = value;
+ }
+
+ setDisabledState?(isDisabled: boolean): void {
+ this.disabled = isDisabled;
+ }
+
+ get required(): boolean {
+ return this._required;
+ }
+
+ set required(value: boolean) {
+ this._required = value;
+ }
+
+ setRequiredState?(isRequired: boolean): void {
+ this.required = isRequired;
+ }
+
+ constructor(public cdr: ChangeDetectorRef) {};
+
+ ngOnInit(): void {}
+
+}
import {ComboboxComponent, IdlClassTemplateDirective} from '@eg/share/combobox/combobox.component';
import {ComboboxEntryComponent} from '@eg/share/combobox/combobox-entry.component';
import {DateSelectComponent} from '@eg/share/date-select/date-select.component';
+import {BooleanSelectComponent} from '@eg/share/boolean-select/boolean-select.component';
import {OrgSelectComponent} from '@eg/share/org-select/org-select.component';
import {DateRangeSelectComponent} from '@eg/share/daterange-select/daterange-select.component';
import {DateTimeSelectComponent} from '@eg/share/datetime-select/datetime-select.component';
ComboboxComponent,
ComboboxEntryComponent,
DateSelectComponent,
+ BooleanSelectComponent,
OrgSelectComponent,
DateRangeSelectComponent,
DateTimeSelectComponent,
ComboboxComponent,
ComboboxEntryComponent,
DateSelectComponent,
+ BooleanSelectComponent,
OrgSelectComponent,
DateRangeSelectComponent,
DateTimeSelectComponent,
<span i18n>Dates must be in the correct order</span>
</div>
- <div class="form-group row" *ngFor="let field of fields">
+ <ng-container *ngFor="let field of fields">
+ <div class="form-group row">
<div class="col-lg-3">
<label for="{{idPrefix}}-{{field.name}}">{{field.label}}</label>
<eg-help-popover [placement]="'right'" *ngIf="field.helpText" helpText="{{field.helpTextValue}}"></eg-help-popover>
+ <ng-container *ngIf="isSafeToNull(field)">
+ <br />(<a (click)="setToNull(field)" href='javascript:;'><span i18n>Unset</span></a>)
+ </ng-container>
</div>
<div class="col-lg-9">
domId="{{idPrefix}}-{{field.name}}"
[limitPerms]="modePerms[mode]"
[readOnly]="field.readOnly"
+ [required]="field.isRequired()"
[applyDefault]="field.orgDefaultAllowed"
[applyOrgId]="record[field.name]()"
(onChange)="record[field.name]($event)">
</ng-container>
<ng-container *ngSwitchCase="'bool'">
- <input
- class="form-check-input"
- type="checkbox"
+ <eg-bool-select
name="{{field.name}}"
id="{{idPrefix}}-{{field.name}}"
[disabled]="field.readOnly"
+ [required]="field.isRequired()"
[ngModel]="record[field.name]()"
- (ngModelChange)="record[field.name]($event)"/>
+ (ngModelChange)="record[field.name]($event)">
+ </eg-bool-select>
+
</ng-container>
<ng-container *ngSwitchCase="'readonly-au'">
</a>
</div>
</div>
+ <ng-container *ngIf="field.append_template">
+ <ng-container
+ *ngTemplateOutlet="field.append_template; context:appendTemplateFieldContext(field)">
+ </ng-container>
+ </ng-container>
+ </ng-container>
</ng-container>
</form>
</div>
import {TranslateComponent} from '@eg/share/translate/translate.component';
import {FmRecordEditorActionComponent} from './fm-editor-action.component';
import {ConfirmDialogComponent} from '@eg/share/dialog/confirm.component';
+import {BooleanSelectComponent} from '@eg/share/boolean-select/boolean-select.component';
import {Directive, HostBinding} from '@angular/core';
import {AbstractControl, NG_VALIDATORS, ValidationErrors, Validator, Validators} from '@angular/forms';
// from the default set of form inputs.
customTemplate?: CustomFieldTemplate;
+ // Follow the normal field rendering with this custom template
+ appendTemplate?: CustomFieldTemplate;
+
// help text to display via a popover
helpText?: StringComponent;
if (field.datatype === 'bool') {
if (rec[field.name]() === true) {
rec[field.name]('t');
- // } else if (rec[field.name]() === false) {
- } else { // TODO: some bools can be NULL
+ } else if (rec[field.name]() === false) {
rec[field.name]('f');
+ } else {
+ rec[field.name](null);
}
} else if (field.datatype === 'org_unit') {
const org = rec[field.name]();
};
}
+ if (fieldOptions.appendTemplate) {
+ field.append_template = fieldOptions.appendTemplate.template;
+ field.append_context = fieldOptions.appendTemplate.context;
+ }
+
if (fieldOptions.customTemplate) {
field.template = fieldOptions.customTemplate.template;
field.context = fieldOptions.customTemplate.context;
}, fieldDef.context || {}
);
}
+ appendTemplateFieldContext(fieldDef: any): CustomFieldContext {
+ return Object.assign(
+ { record : this.record,
+ field: fieldDef // from this.fields
+ }, fieldDef.append_context || {}
+ );
+ }
save() {
const recToSave = this.idl.clone(this.record);
}
);
}
+
+ isSafeToNull(field) {
+ if (field.datatype == 'id') {
+ return false;
+ }
+ if (field.readOnly) {
+ return false;
+ }
+ if (field.isRequired()) {
+ return false;
+ }
+ return true;
+ }
+
+ setToNull(field) {
+ this.record[field.name](null);
+ }
}
// https://stackoverflow.com/a/57812865
<eg-string #successString i18n-text text="Circulation Policy Update Succeeded"></eg-string>
<eg-string #createString i18n-text text="Circulation Policy Creation Succeeded"></eg-string>
+<ng-container *ngIf="orgField || gridFilters">
+ <div class="row">
+ <div class="col-lg-6">
+ <ng-container *ngIf="orgField">
+ <eg-org-family-select
+ [limitPerms]="viewPerms"
+ [selectedOrgId]="contextOrg.id()"
+ [(ngModel)]="searchOrgs"
+ (ngModelChange)="grid.reload()">
+ </eg-org-family-select>
+ </ng-container>
+ </div>
+ <div class="col-lg-6 d-flex">
+ <div class="flex-1"></div><!-- push right -->
+ <ng-container *ngIf="gridFilters">
+ <span i18n>Filters Applied: {{gridFilters | json}}</span>
+ <a class="pl-2 font-italic"
+ [attr.href]="clearGridFiltersUrl()" i18n>Clear Filters</a>
+ </ng-container>
+ </div>
+ </div>
+ <hr/>
+</ng-container>
+
<eg-grid #grid idlClass="ccmm"
[dataSource]="dataSource"
[sortable]="true"
+ [filterable]="true"
+ persistKey="admin.config.circ_matrix_matchpoint"
(onRowActivate)="editSelected([$event])"
[showFields]='"is_renewal,active,org_unit,copy_circ_lib,copy_owning_lib,user_home_ou"'>
<eg-grid-toolbar-button
- label="New Circ Matrix Matchpoint" i18n-label (onClick)="createNew()">
+ label="New Circulation Policy" i18n-label (onClick)="createNew()">
</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)"
+ [disableOnRows]="notOneSelectedRow">
</eg-grid-toolbar-action>
</eg-grid>
</div>
<ng-template #active let-idPrefix="idPrefix" let-field="field" let-record="record">
- <div class="col-lg-9">
- <input
- class="form-check-input"
- type="checkbox"
- name="{{field.name}}"
- id="{{idPrefix}}-{{field.name}}"
- [disabled]="field.readOnly"
- [ngModel]="record[field.name]()"
- (ngModelChange)="record[field.name]($event)"/>
- </div>
- <div class="row" [ngStyle]="{
- width:'150%',
- backgroundColor:'black',
- marginLeft:'-43%',
- marginTop:'6%',
- marginBottom:'-1%',
- opacity:'90%',
- fontSize:'18px',
- textAlign:'center'}">
- <div [ngStyle]="{width:'100%', color:'white'}">Circulation Policies</div>
+ <div class="row">
+ <div class="col-lg-12">
+ <eg-staff-banner bannerText="Circulation Policy Matchpoints" i18n-bannerText>
+ </eg-staff-banner>
+ </div>
</div>
</ng-template>
<ng-template #item_age let-idPrefix="idPrefix" let-field="field" let-record="record">
- <div class="col-lg-9">
- <input
- class="form-control"
- id="{{idPrefix}}-{{field.name}}" name="{{field.name}}"
- type="text"
- placeholder="{{field.label}}..." i18n-placeholder
- [required]="field.isRequired()"
- [ngModel]="record[field.name]()"
- (ngModelChange)="record[field.name]($event)"/>
- </div>
- <div class="row" [ngStyle]="{
- width:'150%',
- backgroundColor:'black',
- marginLeft:'-43%',
- marginTop:'3%',
- marginBottom:'-1%',
- opacity:'90%',
- fontSize:'18px',
- textAlign:'center',
- paddingTop:'3.5%',
- paddingBottom:'5.5%',
- paddingLeft:'3.5%',
- paddingRight:'3.5%'}">
- <div [ngStyle]="{width:'100%', color:'white'}">Circulation Policy Effects</div>
+ <div class="row">
+ <div class="col-lg-12">
+ <eg-staff-banner bannerText="Circulation Policy Effects" i18n-bannerText>
+ </eg-staff-banner>
+ </div>
</div>
</ng-template>
fieldOrder="id,active,grp,org_unit,copy_circ_lib,copy_owning_lib,user_home_ou,is_renewal,juvenile_flag,circ_modifier,copy_location,marc_type,marc_form,marc_bib_level,marc_vr_format,ref_flag,usr_age_lower_bound,usr_age_upper_bound,item_age,circulate,duration_rule,renewals,hard_due_date,recurring_fine_rule,grace_period,max_fine_rule,available_copy_hold_ratio,total_copy_hold_ratio,script_test,description"
requiredFields="active,grp,org_unit"
(recordSaved)="configureLimitSets($event); clearLinkedCircLimitSets(); closeDialog()"
- [fieldOptions]="{active:{customTemplate:{template:active}}, item_age:{customTemplate:{template:item_age}}}">
+ [fieldOptions]="{active:{appendTemplate:{template:active}}, item_age:{appendTemplate:{template:item_age}}}">
</eg-fm-record-editor>
-</eg-circ-matrix-matchpoint-dialog>
\ No newline at end of file
+</eg-circ-matrix-matchpoint-dialog>
import {Component, OnInit, AfterViewInit, Input, ViewChild, ElementRef} from '@angular/core';
import {GridComponent} from '@eg/share/grid/grid.component';
import {GridDataSource, GridColumn, GridRowFlairEntry} from '@eg/share/grid/grid';
-import {IdlObject} from '@eg/core/idl.service';
+import {ActivatedRoute} from '@angular/router';
+import {Location} from '@angular/common';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
import {FmRecordEditorComponent} from '@eg/share/fm-editor/fm-editor.component';
import {LinkedCircLimitSetsComponent} from './linked-circ-limit-sets.component';
import {CircMatrixMatchpointDialogComponent} from './circ-matrix-matchpoint-dialog.component';
import {StringComponent} from '@eg/share/string/string.component';
import {PcrudService} from '@eg/core/pcrud.service';
import {ToastService} from '@eg/share/toast/toast.service';
+import {AuthService} from '@eg/core/auth.service';
+import {PermService} from '@eg/core/perm.service';
+import {OrgService} from '@eg/core/org.service';
+import {OrgFamily} from '@eg/share/org-family-select/org-family-select.component';
@Component({
templateUrl: './circ-matrix-matchpoint.component.html'
})
export class CircMatrixMatchpointComponent implements OnInit {
recId: number;
- gridDataSource: GridDataSource;
+ orgField = 'org_unit';
+ disableOrgFilter = false;
initDone = false;
- dataSource: GridDataSource = new GridDataSource();
+ dataSource: GridDataSource;
+ gridFilters: {[key: string]: string | number};
showLinkLimitSets = false;
usedSetLimitList = {};
linkedLimitSets = [];
marginTop: '25px',
marginLeft: '73%'
};
+ notOneSelectedRow: (rows: IdlObject[]) => boolean;
@ViewChild('limitSets', { static: false }) limitSets: ElementRef;
@ViewChild('circLimitSets', { static: true }) limitSetsComponent: LinkedCircLimitSetsComponent;
@Input() dialogSize: 'sm' | 'lg' = 'lg';
+ idlClassDef: any;
+ pkeyField: string;
+ contextOrg: IdlObject;
+ searchOrgs: OrgFamily;
+ orgFieldLabel: string;
+ viewPerms: string;
+ canCreate: boolean;
+
constructor(
+ private route: ActivatedRoute,
private pcrud: PcrudService,
- private toast: ToastService
- ) {
- this.gridDataSource = new GridDataSource();
- }
+ private toast: ToastService,
+ public idl: IdlService,
+ private org: OrgService,
+ public auth: AuthService,
+ private perm: PermService
+ ) {}
ngOnInit() {
this.initDone = true;
+ this.notOneSelectedRow = (rows: IdlObject[]) => (rows.length !== 1);
+ this.idlClassDef = this.idl.classes[this.idlClass];
+ this.pkeyField = this.idlClassDef.pkey || 'id';
+
+ // 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;
+ }
+
+ const contextOrg = this.route.snapshot.queryParamMap.get('contextOrg');
+ this.checkCreatePerms();
+ this.applyOrgValues(Number(contextOrg));
+
+ this.initDataSource();
+ }
+
+ applyOrgValues(orgId?: number) {
+
+ 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.get(orgId) || this.org.get(this.auth.user().ws_ou()) || this.org.root();
+ this.searchOrgs = {primaryOrgId: this.contextOrg.id()};
+ }
+ }
+
+ 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;
+ }
+ });
+ });
+ }
+
+ 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;
limit: pager.limit,
order_by: orderBy
};
- return this.pcrud.retrieveAll('ccmm', searchOps, {fleshSelectors: true});
+
+ if (!this.contextOrg && !this.gridFilters && !Object.keys(this.dataSource.filters).length) {
+ // No org filter -- fetch all rows
+ return this.pcrud.retrieveAll(
+ this.idlClass, searchOps, {fleshSelectors: true});
+ }
+
+ const search: any[] = new Array();
+ const orgFilter: any = {};
+
+ if (this.orgField && (this.searchOrgs || this.contextOrg)) {
+ orgFilter[this.orgField] =
+ this.searchOrgs.orgIds || [this.contextOrg.id()];
+ search.push(orgFilter);
+ }
+
+ Object.keys(this.dataSource.filters).forEach(key => {
+ Object.keys(this.dataSource.filters[key]).forEach(key2 => {
+ search.push(this.dataSource.filters[key][key2]);
+ });
+ });
+
+ // FIXME - do we want to remove this, which is used in several
+ // secondary admin pages, in favor of switching it to the built-in
+ // grid filtering?
+ if (this.gridFilters) {
+ // Lay the URL grid filters over our search object.
+ Object.keys(this.gridFilters).forEach(key => {
+ const urlProvidedFilters = {};
+ urlProvidedFilters[key] = this.gridFilters[key];
+ search.push(urlProvidedFilters);
+ });
+ }
+
+ return this.pcrud.search(
+ this.idlClass, search, searchOps, {fleshSelectors: true});
};
}
}
deleteLimitSets(limitSet) {
- return new Promise((resolve, reject) => {
+ return new Promise<void>((resolve, reject) => {
if (limitSet.isDeleted) {
if (limitSet.linkedLimitSet.id()) {
this.pcrud.remove(limitSet.linkedLimitSet).subscribe(res => {
]
})
-export class CircMatrixMathpointModule {
+export class CircMatrixMatchpointModule {
}
<eg-string #errorString i18n-text text="The Linked Set Name Already Exists on Another Matchpoint"></eg-string>
<div *ngIf="showLinkLimitSets">
- <div class="col-lg-15 bg-info d-flex justify-content-center"><h3 class="modal-title mt-3 mb-3" i18n>Linked Limit Sets</h3></div>
+ <div class="modal-header bg-info"><h4 class="modal-title" i18n>Linked Limit Sets</h4></div>
<ng-container *ngIf="getObjectKeys().length > 0">
<ng-container *ngFor="let key of getObjectKeys(); let i = index">
<div *ngIf="!linkedSetList[i].isDeleted" class="col-lg-15 d-flex justify-content-center">
(click)="addLinkedSet()"
i18n-title title="Add" i18n>Add
</button>
- <eg-help-popover [helpText]="'Go to Local Admin -> Circulation Limit Sets to Create a Link Limit Set'" ></eg-help-popover>
+ <eg-help-popover i18n-helpText helpText="'Go to Local Admin -> Circulation Limit Sets to Create a Link Limit Set'" ></eg-help-popover>
</div>
</div>
</div>
import('./negative-balances/negative-balances.module').then(m => m.NegativeBalancesModule)
}, {
path: 'config/circ_matrix_matchpoint',
- loadChildren: '@eg/staff/admin/local/circ_matrix_matchpoint/circ-matrix-matchpoint.module#CircMatrixMathpointModule'
+ loadChildren: () =>
+ import('./circ_matrix_matchpoint/circ-matrix-matchpoint.module').then(m => m.CircMatrixMatchpointModule)
}, {
path: ':schema/:table',
component: BasicAdminPageComponent
)
);
+INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
+VALUES (
+ 'eg.grid.admin.config.circ_matrix_matchpoint', 'gui', 'object',
+ oils_i18n_gettext(
+ 'eg.grid.admin.config.circ_matrix_matchpoint',
+ 'Grid Config: admin.config.circ_matrix_matchpoint',
+ '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.grid.admin.config.circ_matrix_matchpoint', 'gui', 'object',
+ oils_i18n_gettext(
+ 'eg.grid.admin.config.circ_matrix_matchpoint',
+ 'Grid Config: admin.config.circ_matrix_matchpoint',
+ 'cwst', 'label'
+ )
+);
+
+COMMIT;
* Prevent templates from applying or changing magical status in angular holdings editor (LP#1999401)
* Prevent directly editing the shelving location deleted field in the Shelving Locations Editor (LP#2002435)
* The "Strict Barcode" checkbox is now closer to the barcode input on the Check Out, Check In, and Renew Items pages (LP#1990968)
+* Angularized the Local Administration -> Circulation Policies interface.
+* Added an option to fmEditor for allowing one to unset a field (aka set to null)
+* Added some misc fmEditor tweaks/additions for developers
+* Replaced checkboxes for boolean fields in fmEditor with radio buttons
+* Changed instances of Copy Location to Shelving Location in the IDL, which wil be reflected in many interfaces.
+* Also, in the IDL, "Copy Circ Lib" and "Copy Owning Lib" become "Item Circ Library" and "Item Owning Library", respectively.
+* Org Unit becomes Checkout Library for the circ matrix. Checkout is more prevalent in the code than Check Out, but we should pick one.