LPXXX Angular Volcopy
authorBill Erickson <berickxx@gmail.com>
Mon, 22 Jun 2020 20:42:36 +0000 (16:42 -0400)
committerBill Erickson <berickxx@gmail.com>
Mon, 22 Jun 2020 20:42:36 +0000 (16:42 -0400)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/eg2/src/app/staff/cat/volcopy/config.component.html
Open-ILS/src/eg2/src/app/staff/cat/volcopy/config.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.html
Open-ILS/src/eg2/src/app/staff/cat/volcopy/copy-attrs.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/vol-edit.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.service.ts
Open-ILS/src/sql/Pg/upgrade/XXXX.data.volcopy-settings.sql [new file with mode: 0644]

index 419d477..e32ac7c 100644 (file)
@@ -1,4 +1,4 @@
-<h3 i18n>Holdings Defaults</h3>
+<h3 class="mt-3" i18n>Holdings Defaults</h3>
 
 <div class="row">
   <div class="col-lg-6">
@@ -11,7 +11,7 @@
               <div class="form-check form-check-inline">
                 <input class="form-check-input" type="checkbox" 
                   id="hide-classification-column" 
-                  [(ngModel)]="volcopy.defaultValues.hide_classification_column">
+                  [(ngModel)]="volcopy.volCopyDefaults.hidden.classification">
                 <label class="form-check-label" for="hide-classification-column" i18n>
                   Hide Call Number Classification Column
                 </label>
@@ -21,7 +21,7 @@
               <div class="form-check form-check-inline">
                 <input class="form-check-input" type="checkbox" 
                   id="hide-prefix-column" 
-                  [(ngModel)]="volcopy.defaultValues.hide_prefix_column">
+                  [(ngModel)]="volcopy.volCopyDefaults.hidden.prefix">
                 <label class="form-check-label" for="hide-prefix-column" i18n>
                   Hide Call Number Prefix Column
                 </label>
@@ -31,7 +31,7 @@
               <div class="form-check form-check-inline">
                 <input class="form-check-input" type="checkbox" 
                   id="hide-suffix-column" 
-                  [(ngModel)]="volcopy.defaultValues.hide_suffix_column">
+                  [(ngModel)]="volcopy.volCopyDefaults.hidden.suffix">
                 <label class="form-check-label" for="hide-suffix-column" i18n>
                   Hide Call Number Suffix Column
                 </label>
@@ -56,9 +56,9 @@
                 <div class="col-lg-8">
                   <eg-combobox
                     domId="default-classification"
-                    [selectedId]="volcopy.defaultValues.classification || 1"
+                    [selectedId]="volcopy.volCopyDefaults.values.classification || 1"
                     [smallFormControl]="true"
-                    (onChange)="volcopy.defaultValues.classification = $entry ? $entry.id : null">
+                    (onChange)="volcopy.volCopyDefaults.values.classification = $entry ? $entry.id : null">
                     <eg-combobox-entry *ngFor="let cls of volcopy.volClasses"
                       [entryId]="cls.id()" [entryLabel]="cls.name()">
                     </eg-combobox-entry>
@@ -74,9 +74,9 @@
                 <div class="col-lg-8">
                   <eg-combobox
                     domId="default-prefix"
-                    [selectedId]="volcopy.defaultValues.prefix || -1"
+                    [selectedId]="volcopy.volCopyDefaults.values.prefix || -1"
                     [smallFormControl]="true"
-                    (onChange)="volcopy.defaultValues.prefix = $entry ? $entry.id : null">
+                    (onChange)="volcopy.volCopyDefaults.values.prefix = $entry ? $entry.id : null">
                     <eg-combobox-entry 
                       entryLabel="<None>" i18n-entryLabel [entryId]="-1">
                     </eg-combobox-entry>
@@ -95,9 +95,9 @@
                 <div class="col-lg-8">
                   <eg-combobox
                     domId="default-suffix"
-                    [selectedId]="volcopy.defaultValues.suffix || -1"
+                    [selectedId]="volcopy.volCopyDefaults.values.suffix || -1"
                     [smallFormControl]="true"
-                    (onChange)="volcopy.defaultValues.suffix = $entry ? $entry.id : null">
+                    (onChange)="volcopy.volCopyDefaults.values.suffix = $entry ? $entry.id : null">
                     <eg-combobox-entry 
                       entryLabel="<None>" i18n-entryLabel [entryId]="-1">
                     </eg-combobox-entry>
 
 <hr class="p-2"/>
 
-<h3 i18n>Item Attributes Defaults</h3>
-<span class="font-italic" i18n>Selected Attributes Will Be Visible</span>
+<h3 i18n>Hide Item Attributes</h3>
+<span class="font-italic" i18n>
+  Selected Attributes Will be <b>Hidden</b> from the Item Attributes Form.
+</span>
 
 <div class="row d-flex">
 
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-status-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.status">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.status">
             <label class="form-check-label" for="show-status-attr" i18n>
               Status
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-barcode-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.barcode">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.barcode">
             <label class="form-check-label" for="show-barcode-attr" i18n>
               Barcode
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-create_date-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.create_date">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.create_date">
             <label class="form-check-label" for="show-create_date-attr" i18n>
               Creation Date
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-active_date-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.active_date">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.active_date">
             <label class="form-check-label" for="show-active_date-attr" i18n>
               Activation Date
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-creator-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.creator">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.creator">
             <label class="form-check-label" for="show-creator-attr" i18n>
               Creator
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-edit_date-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.edit_date">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.edit_date">
             <label class="form-check-label" for="show-edit_date-attr" i18n>
               Last Edit Date
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-editor-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.editor">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.editor">
             <label class="form-check-label" for="show-editor-attr" i18n>
               Last Editor
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-location-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.location">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.location">
             <label class="form-check-label" for="show-location-attr" i18n>
               Location
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-circ_lib-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.circ_lib">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.circ_lib">
             <label class="form-check-label" for="show-circ_lib-attr" i18n>
               Circulating Library
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-owning_lib-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.owning_lib">
+              [(ngModel)]="volcopy.volCopyDefaults.owning_lib">
             <label class="form-check-label" for="show-owning_lib-attr" i18n>
               Owning Library
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-copy_number-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.copy_number">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.copy_number">
             <label class="form-check-label" for="show-copy_number-attr" i18n>
               Copy Number 
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-circulate-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.circulate">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.circulate">
             <label class="form-check-label" for="show-circulate-attr" i18n>
               Circulate
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-holdable-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.holdable">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.holdable">
             <label class="form-check-label" for="show-holdable-attr" i18n>
               Holdable
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-age_protect-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.age_protect">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.age_protect">
             <label class="form-check-label" for="show-age_protect-attr" i18n>
               Aged-Based Hold Protection
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-floating-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.floating">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.floating">
             <label class="form-check-label" for="show-floating-attr" i18n>
               Floating
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-loan_duration-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.loan_duration">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.loan_duration">
             <label class="form-check-label" for="show-loan_duration-attr" i18n>
               Loan Duration
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-fine_level-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.fine_level">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.fine_level">
             <label class="form-check-label" for="show-fine_level-attr" i18n>
               Fine Level
             </label>
           <div class="form-check form-check-inline">
             <input class="form-check-input" type="checkbox" 
               id="show-circ_as_type-attr" 
-              [(ngModel)]="volcopy.defaultValues.attributes.circ_as_type">
+              [(ngModel)]="volcopy.volCopyDefaults.hidden.circ_as_type">
             <label class="form-check-label" for="show-circ_as_type-attr" i18n>
               Circulate As Type
             </label>
index b21f546..f7fe312 100644 (file)
@@ -40,11 +40,14 @@ export class VolCopyConfigComponent implements OnInit, AfterViewInit {
     ) { }
 
     ngOnInit() {
-        console.log('DEFAULTS', this.volcopy.defaultValues);
+        console.log('DEFAULTS', this.volcopy.volCopyDefaults);
     }
 
     ngAfterViewInit() {
+    }
 
+    save() {
+        this.volcopy.saveDefaults();
     }
 }
 
index b99e852..d5016f9 100644 (file)
   <div class="flex-1 p-1">
     <div class="p-1"><h4 class="font-weight-bold" i18n>Identification</h4></div>
 
-    <div class="mb-1">
+    <div class="mb-1" *ngIf="displayAttr('status')">
       <eg-batch-item-attr label="Status" i18n-label [readOnly]="true"
         [labelCounts]="itemAttrCounts('status')">
       </eg-batch-item-attr>
     </div>
 
-    <div class="mb-1">
+    <div class="mb-1" *ngIf="displayAttr('barcode')">
       <eg-batch-item-attr label="Barcode" i18n-label
         [readOnly]="true" [emptyIsUnset]="true"
         [labelCounts]="itemAttrCounts('barcode')">
       </eg-batch-item-attr>
     </div>
 
-    <div class="mb-1">
+    <div class="mb-1" *ngIf="displayAttr('create_date')">
       <eg-batch-item-attr label="Creation Date" i18n-label [readOnly]="true"
         [labelCounts]="itemAttrCounts('create_date')">
       </eg-batch-item-attr>
     </div>
 
-    <div class="mb-1">
+    <div class="mb-1" *ngIf="displayAttr('active_date')">
       <eg-batch-item-attr label="Active Date" i18n-label [readOnly]="true"
         [labelCounts]="itemAttrCounts('active_date')">
       </eg-batch-item-attr>
     </div>
 
-    <div class="mb-1">
+    <div class="mb-1" *ngIf="displayAttr('creator')">
       <eg-batch-item-attr label="Creator" i18n-label [readOnly]="true"
         [labelCounts]="itemAttrCounts('creator')">
       </eg-batch-item-attr>
     </div>
 
-    <div class="mb-1">
+    <div class="mb-1" *ngIf="displayAttr('edit_date')">
       <eg-batch-item-attr label="Last Edit Date" i18n-label [readOnly]="true"
         [labelCounts]="itemAttrCounts('edit_date')">
       </eg-batch-item-attr>
     </div>
 
-    <div class="mb-1">
+    <div class="mb-1" *ngIf="displayAttr('editor')">
       <eg-batch-item-attr label="Last Editor" i18n-label [readOnly]="true"
         [labelCounts]="itemAttrCounts('editor')">
       </eg-batch-item-attr>
@@ -87,7 +87,7 @@
   <div class="flex-1 p-1">
     <div class="p-1"><h4 class="font-weight-bold" i18n>Location</h4></div>
 
-    <div>
+    <div *ngIf="displayAttr('location')">
       <ng-template #locationTemplate>
         <eg-item-location-select (valueChange)="values['location'] = $event"
           domId='location-input' [required]="true" permFilter="UPDATE_COPY">
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('circ_lib')">
       <ng-template #circLibTemplate>
         <eg-org-select 
           domId="circ-lib-input"
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('owning_lib', true)">
       <ng-template #owningLibTemplate>
         <eg-org-select 
           domId="owning-lib-input"
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('copy_number')">
       <ng-template #copyNumberTemplate>
         <input type="number" class="form-control"
           id="copy-number-input" [(ngModel)]="values['copy_number']"/>
   <div class="flex-1 p-1">
     <div class="p-1"><h4 class="font-weight-bold" i18n>Circulation</h4></div>
 
-    <div>
+    <div *ngIf="displayAttr('circulate')">
       <ng-template #circulateTemplate>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'circulate'}">
         </ng-container>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('holdable')">
       <ng-template #holdableTemplate>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'holdable'}">
         </ng-container>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('age_protect')">
       <ng-template #ageProtectTemplate>
         <select class="form-control" 
           id="age-protect-input" [(ngModel)]="values['age_protect']">
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('floating')">
       <ng-template #floatingTemplate>
         <select class="form-control" 
           id="floating-input" [(ngModel)]="values['floating']">
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('loan_duration')">
       <eg-string #loanDurationShort i18n-text text="Short"></eg-string>
       <eg-string #loanDurationNormal i18n-text text="Normal"></eg-string>
       <eg-string #loanDurationLong i18n-text text="Long"></eg-string>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('fine_level')">
       <eg-string #fineLevelLow i18n-text text="Low"></eg-string>
       <eg-string #fineLevelNormal i18n-text text="Normal"></eg-string>
       <eg-string #fineLevelHigh i18n-text text="High"></eg-string>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('circ_as_type')">
       <ng-template #circAsTypeTemplate>
         <select class="form-control" [(ngModel)]="values['circ_as_type']">
           <option [value]="null" i18n>&lt;Unset&gt;</option>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('circ_modifier')">
       <ng-template #circModifierTemplate>
         <select class="form-control" [(ngModel)]="values['circ_modifier']">
           <option [value]="null" i18n>&lt;Unset&gt;</option>
     </div>
     -->
 
-    <div class="border rounded m-1">
+    <div class="border rounded m-1" *ngIf="displayAttr('copy_notes', true)">
       <eg-copy-alerts-dialog #copyAlertsDialog></eg-copy-alerts-dialog>
       <div class="batch-header font-weight-bold p-2" i18n>Add Item Alerts</div>
       <div class="p-1">
       </div>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('deposit')">
       <ng-template #depositTemplate>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'deposit'}">
         </ng-container>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('deposit_amount')">
       <ng-template #depositAmountTemplate>
         <input type="number" class="form-control" 
           id="deposit-amount-input" [(ngModel)]="values['deposit_amount']"/>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('price')">
       <ng-template #priceTemplate>
         <input type="number" class="form-control" 
           id="price-input" [(ngModel)]="values['price']"/>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('opac_visible')">
       <ng-template #opacVisibleTemplate>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'opac_visible'}">
         </ng-container>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('ref')">
       <ng-template #refTemplate>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'ref'}">
         </ng-container>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('cost')">
       <ng-template #costTemplate>
         <input type="number" class="form-control" 
           id="cost-input" [(ngModel)]="values['cost']"/>
       </eg-batch-item-attr>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('mint_condition')">
       <eg-string #mintConditionYes i18n-text text="Good"></eg-string>
       <eg-string #mintConditionNo i18n-text text="Damaged"></eg-string>
 
   <div class="flex-1 p-1">
     <div class="p-1"><h4 class="font-weight-bold" i18n>Statistics</h4></div>
 
-    <div *ngFor="let cat of statCats(); let idx = index">
-      <ng-template #statCatTemplate>
-        <eg-combobox domId="stat-cat-input-{{idx}}"
-          (ngModelChange)="statCatValues[cat.id()] = $event ? $event.id : null"
-          [ngModel]="statCatValues[cat.id()]">
-          <eg-combobox-entry *ngFor="let entry of cat.entries()"
-            [entryId]="entry.id()" [entryLabel]="entry.value()">
-          </eg-combobox-entry>
-        </eg-combobox>
-      </ng-template>
-      <eg-batch-item-attr label="{{cat.name()}} ({{orgSn(cat.owner())}})" i18n-label
-        editInputDomId="stat-cat-input-{{idx}}"
-        [emptyIsUnset]="true"
-        [editTemplate]="statCatTemplate"
-        [labelCounts]="statCatCounts(cat.id())"
-        (changesSaved)="statCatChanged(cat.id())">
-      </eg-batch-item-attr>
-    </div>
-
+    <ng-container *ngIf="displayAttr('statcats', true)">
+      <div *ngFor="let cat of statCats(); let idx = index">
+        <ng-template #statCatTemplate>
+          <eg-combobox domId="stat-cat-input-{{idx}}"
+            (ngModelChange)="statCatValues[cat.id()] = $event ? $event.id : null"
+            [ngModel]="statCatValues[cat.id()]">
+            <eg-combobox-entry *ngFor="let entry of cat.entries()"
+              [entryId]="entry.id()" [entryLabel]="entry.value()">
+            </eg-combobox-entry>
+          </eg-combobox>
+        </ng-template>
+        <eg-batch-item-attr label="{{cat.name()}} ({{orgSn(cat.owner())}})" i18n-label
+          editInputDomId="stat-cat-input-{{idx}}"
+          [emptyIsUnset]="true"
+          [editTemplate]="statCatTemplate"
+          [labelCounts]="statCatCounts(cat.id())"
+          (changesSaved)="statCatChanged(cat.id())">
+        </eg-batch-item-attr>
+      </div>
+    </ng-container>
   </div>
 </div>
 
index 723638c..427f93c 100644 (file)
@@ -311,6 +311,10 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
             this.applyCopyValue(field, value);
         });
     }
+
+    displayAttr(field: string): boolean {
+        return this.volcopy.volCopyDefaults.hidden[field] !== true;
+    }
 }
 
 
index c5007f2..747b4bf 100644 (file)
@@ -491,8 +491,7 @@ export class VolEditComponent implements OnInit {
     }
 
     displayColumn(field: string): boolean {
-        const key = `hide_${field}_column`;
-        return this.volcopy.defaultValues[key] !== true;
+        return this.volcopy.volCopyDefaults.hidden[field] !== true;
     }
 }
 
index 4d884f0..8f15635 100644 (file)
@@ -114,7 +114,6 @@ export class VolCopyComponent implements OnInit {
         this.context.reset();
 
         this.volcopy.load()
-        .then(_ => console.log('VOLCOPYLOADED'))
         .then(_ => this.fetchHoldings(copyIds))
         .then(_ => this.volcopy.applyVolLabels(
             this.context.volNodes().map(n => n.target)))
index fad55a8..118c393 100644 (file)
@@ -15,12 +15,17 @@ import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.comp
 
 /* Managing volcopy data */
 
+interface VolCopyDefaults {
+    values: {[field: string]: any},
+    hidden: {[field: string]: boolean}
+}
+
 @Injectable()
 export class VolCopyService {
 
     autoId = -1;
 
-    defaultValues: any = null;
+    volCopyDefaults: VolCopyDefaults = null;
     copyStatuses: {[id: number]: IdlObject} = null;
 
     // Track this here so it can survive route changes.
@@ -166,17 +171,17 @@ export class VolCopyService {
     }
 
     fetchDefaults(): Promise<any> {
-        if (this.defaultValues) { return Promise.resolve(); }
+        if (this.volCopyDefaults) { return Promise.resolve(); }
 
-        return this.serverStore.getItem('cat.copy.defaults').then(
-            defaults => {
-                this.defaultValues = defaults || {};
+        return this.serverStore.getItem('cat.volcopy.defaults').then(
+            (defaults: VolCopyDefaults) => {
+                this.volCopyDefaults = defaults || {values: {}, hidden: {}};
             }
         ).then(_ => {
 
             // Default to location ID 1 (Stacks)
             return this.pcrud.retrieve('acpl', 1).toPromise()
-            .then(loc => this.defaultValues.location = loc);
+            .then(loc => this.volCopyDefaults.values.location = loc);
         });
     }
 
@@ -202,7 +207,7 @@ export class VolCopyService {
         return this.net.request(
             'open-ils.cat',
             'open-ils.cat.biblio.record.marc_cn.retrieve',
-            id, this.defaultValues.classification || null
+            id, this.volCopyDefaults.values.classification || null
         ).toPromise().then(res => {
             return Object.values(res)
                 .map(blob => Object.values(blob)[0]).sort();
@@ -218,8 +223,8 @@ export class VolCopyService {
         vol.record(recordId);
         vol.label(null);
         vol.owning_lib(Number(orgId));
-        vol.prefix(this.defaultValues.prefix || -1);
-        vol.suffix(this.defaultValues.suffix || -1);
+        vol.prefix(this.volCopyDefaults.values.prefix || -1);
+        vol.suffix(this.volCopyDefaults.values.suffix || -1);
 
         return vol;
     }
@@ -237,7 +242,7 @@ export class VolCopyService {
         copy.deposit_amount(0);
         copy.fine_level(2);     // Normal
         copy.loan_duration(2);  // Normal
-        copy.location(this.defaultValues.location);  // Stacks / fleshed
+        copy.location(this.volCopyDefaults.values.location);  // Stacks / fleshed
         copy.circulate('t');
         copy.holdable('t');
         copy.opac_visible('t');
@@ -270,12 +275,12 @@ export class VolCopyService {
 
         let promise = Promise.resolve(); // Serialization
 
-        if (this.defaultValues.classification) {
+        if (this.volCopyDefaults.values.classification) {
             // Workstation default classification overrides the
             // classification that might be used at the owning lib.
 
             vols.forEach(vol =>
-                vol.label_class(this.defaultValues.classification));
+                vol.label_class(this.volCopyDefaults.values.classification));
 
             return promise;
 
@@ -390,6 +395,24 @@ export class VolCopyService {
     }
 
 
+    saveDefaults(): Promise<any> {
+
+        // Scrub unnecessary content before storing.
+
+        Object.keys(this.volCopyDefaults.values).forEach(field => {
+            if (this.volCopyDefaults.values[field] === null) {
+                delete this.volCopyDefaults.values[field];
+            }
+        });
+
+        Object.keys(this.volCopyDefaults.hidden).forEach(field => {
+            if (this.volCopyDefaults.hidden[field] !== true) {
+                delete this.volCopyDefaults.hidden[field];
+            }
+        });
 
+        return this.serverStore.setItem(
+            'cat.volcopy.defaults', this.volCopyDefaults);
+    }
 }
 
diff --git a/Open-ILS/src/sql/Pg/upgrade/XXXX.data.volcopy-settings.sql b/Open-ILS/src/sql/Pg/upgrade/XXXX.data.volcopy-settings.sql
new file mode 100644 (file)
index 0000000..74396a1
--- /dev/null
@@ -0,0 +1,12 @@
+
+INSERT INTO config.workstation_setting_type (name, grp, datatype, label)
+VALUES (
+    'eg.cat.volcopy.defaults', 'cat', 'object',
+    oils_i18n_gettext(
+        'eg.cat.volcopy.defaults',
+        'Holdings Editor Default Values and Visibility',
+        'cwst', 'label'
+    )
+);
+
+