LPXXX Angular Volcopy
authorBill Erickson <berickxx@gmail.com>
Mon, 22 Jun 2020 19:34:14 +0000 (15:34 -0400)
committerBill Erickson <berickxx@gmail.com>
Thu, 25 Jun 2020 14:36:18 +0000 (10:36 -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.html
Open-ILS/src/eg2/src/app/staff/cat/volcopy/vol-edit.component.ts
Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.component.html
Open-ILS/src/eg2/src/app/staff/cat/volcopy/volcopy.service.ts
Open-ILS/src/eg2/src/app/staff/share/holdings/batch-item-attr.component.html
Open-ILS/src/eg2/src/app/staff/share/holdings/batch-item-attr.component.ts
Open-ILS/src/sql/Pg/upgrade/XXXX.data.volcopy-settings.sql [new file with mode: 0644]

index e69de29..93b264c 100644 (file)
@@ -0,0 +1,476 @@
+<div class="row d-flex">
+  <div class="flex-1"></div>
+  <button class="btn btn-outline-dark" (click)="save()" i18n>Save Defaults</button>
+</div>
+
+<h3 class="mt-3" i18n>Holdings Defaults</h3>
+
+<div class="row">
+  <div class="col-lg-6">
+    <div class="row">
+      <div class="col-lg-12">
+        <div class="card">
+          <div class="card-header" i18n>Holdings Display Defaults</div>
+          <ul class="list-group list-group-flush">
+            <li class="list-group-item">
+              <div class="form-check form-check-inline">
+                <input class="form-check-input" type="checkbox" 
+                  id="hide-classification-column" 
+                  [(ngModel)]="volcopy.defaults.hidden.classification">
+                <label class="form-check-label" for="hide-classification-column" i18n>
+                  Hide Call Number Classification Column
+                </label>
+              </div>
+            </li>
+            <li class="list-group-item">
+              <div class="form-check form-check-inline">
+                <input class="form-check-input" type="checkbox" 
+                  id="hide-prefix-column" 
+                  [(ngModel)]="volcopy.defaults.hidden.prefix">
+                <label class="form-check-label" for="hide-prefix-column" i18n>
+                  Hide Call Number Prefix Column
+                </label>
+              </div>
+            </li>
+            <li class="list-group-item">
+              <div class="form-check form-check-inline">
+                <input class="form-check-input" type="checkbox" 
+                  id="hide-suffix-column" 
+                  [(ngModel)]="volcopy.defaults.hidden.suffix">
+                <label class="form-check-label" for="hide-suffix-column" i18n>
+                  Hide Call Number Suffix Column
+                </label>
+              </div>
+            </li>
+          </ul>
+        </div>
+      </div>
+    </div>
+  </div>
+  <div class="col-lg-6">
+    <div class="row">
+      <div class="col-lg-12">
+        <div class="card">
+          <div class="card-header" i18n>Holdings Creation Defaults</div>
+          <ul class="list-group list-group-flush p-2">
+            <li class="list-group-item">
+              <div class="row">
+                <div class="col-lg-4" i18n>
+                  <label for="default-classification" i18n>Default Classification</label>
+                </div>
+                <div class="col-lg-8">
+                  <eg-combobox
+                    domId="default-classification"
+                    [selectedId]="volcopy.defaults.values.classification || 1"
+                    [smallFormControl]="true"
+                    (onChange)="volcopy.defaults.values.classification = $event ? $event.id : null">
+                    <eg-combobox-entry *ngFor="let cls of volcopy.volClasses"
+                      [entryId]="cls.id()" [entryLabel]="cls.name()">
+                    </eg-combobox-entry>
+                  </eg-combobox>
+                </div>
+              </div>
+            </li>
+            <li class="list-group-item">
+              <div class="row">
+                <div class="col-lg-4" i18n>
+                  <label for="default-prefix" i18n>Default Prefix</label>
+                </div>
+                <div class="col-lg-8">
+                  <eg-combobox
+                    domId="default-prefix"
+                    [smallFormControl]="true"
+                    [startId]="volcopy.defaults.values.prefix || -1"
+                    (onChange)="volcopy.defaults.values.prefix = $event ? $event.id : null">
+                    <eg-combobox-entry 
+                      entryLabel="<None>" i18n-entryLabel [entryId]="-1">
+                    </eg-combobox-entry>
+                    <eg-combobox-entry *ngFor="let pfx of volcopy.volPrefixes"
+                      [entryId]="pfx.id()" [entryLabel]="pfx.label()">
+                    </eg-combobox-entry>
+                  </eg-combobox>
+                </div>
+              </div>
+            </li>
+            <li class="list-group-item">
+              <div class="row">
+                <div class="col-lg-4" i18n>
+                  <label for="default-suffix" i18n>Default Suffix</label>
+                </div>
+                <div class="col-lg-8">
+                  <eg-combobox
+                    domId="default-suffix"
+                    [selectedId]="volcopy.defaults.values.suffix || -1"
+                    [smallFormControl]="true"
+                    (onChange)="volcopy.defaults.values.suffix = $event ? $event.id : null">
+                    <eg-combobox-entry 
+                      entryLabel="<None>" i18n-entryLabel [entryId]="-1">
+                    </eg-combobox-entry>
+                    <eg-combobox-entry *ngFor="let sfx of volcopy.volSuffixes"
+                      [entryId]="sfx.id()" [entryLabel]="sfx.label()">
+                    </eg-combobox-entry>
+                  </eg-combobox>
+                </div>
+              </div>
+            </li>
+          </ul>
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+
+<hr class="p-2"/>
+
+<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">
+
+  <!-- COLUMN 1 -->
+  <div class="flex-1 p-1">
+    <div class="card">
+      <div class="card-header" i18n>Identification</div>
+      <ul class="list-group list-group-flush">
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-status-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.status">
+            <label class="form-check-label" for="show-status-attr" i18n>
+              Status
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-barcode-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.barcode">
+            <label class="form-check-label" for="show-barcode-attr" i18n>
+              Barcode
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-create_date-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.create_date">
+            <label class="form-check-label" for="show-create_date-attr" i18n>
+              Creation Date
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-active_date-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.active_date">
+            <label class="form-check-label" for="show-active_date-attr" i18n>
+              Activation Date
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-creator-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.creator">
+            <label class="form-check-label" for="show-creator-attr" i18n>
+              Creator
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-edit_date-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.edit_date">
+            <label class="form-check-label" for="show-edit_date-attr" i18n>
+              Last Edit Date
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-editor-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.editor">
+            <label class="form-check-label" for="show-editor-attr" i18n>
+              Last Editor
+            </label>
+          </div>
+        </li>
+      </ul>
+    </div>
+  </div>
+
+  <!-- COLUMN 2 -->
+  <div class="flex-1 p-1">
+    <div class="card">
+      <div class="card-header" i18n>Location</div>
+      <ul class="list-group list-group-flush">
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-location-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.location">
+            <label class="form-check-label" for="show-location-attr" i18n>
+              Location
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-circ_lib-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.circ_lib">
+            <label class="form-check-label" for="show-circ_lib-attr" i18n>
+              Circulating Library
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-owning_lib-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.owning_lib">
+            <label class="form-check-label" for="show-owning_lib-attr" i18n>
+              Owning Library
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-copy_number-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.copy_number">
+            <label class="form-check-label" for="show-copy_number-attr" i18n>
+              Copy Number 
+            </label>
+          </div>
+        </li>
+      </ul>
+    </div>
+  </div>
+
+  <!-- COLUMN 3 -->
+
+  <div class="flex-1 p-1">
+    <div class="card">
+      <div class="card-header" i18n>Circulation</div>
+      <ul class="list-group list-group-flush">
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-circulate-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.circulate">
+            <label class="form-check-label" for="show-circulate-attr" i18n>
+              Circulate
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-holdable-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.holdable">
+            <label class="form-check-label" for="show-holdable-attr" i18n>
+              Holdable
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-age_protect-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.age_protect">
+            <label class="form-check-label" for="show-age_protect-attr" i18n>
+              Aged-Based Hold Protection
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-floating-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.floating">
+            <label class="form-check-label" for="show-floating-attr" i18n>
+              Floating
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-loan_duration-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.loan_duration">
+            <label class="form-check-label" for="show-loan_duration-attr" i18n>
+              Loan Duration
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-fine_level-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.fine_level">
+            <label class="form-check-label" for="show-fine_level-attr" i18n>
+              Fine Level
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-circ_as_type-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.circ_as_type">
+            <label class="form-check-label" for="show-circ_as_type-attr" i18n>
+              Circulate As Type
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-circ_modifier-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.circ_modifier">
+            <label class="form-check-label" for="show-circ_modifier-attr" i18n>
+              Circulation Modifier
+            </label>
+          </div>
+        </li>
+      </ul>
+    </div>
+  </div>
+
+  <!-- COLUMN 4 -->
+
+  <div class="flex-1 p-1">
+    <div class="card">
+      <div class="card-header" i18n>Miscellaneous</div>
+      <ul class="list-group list-group-flush">
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-copy_alerts-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.copy_alerts">
+            <label class="form-check-label" for="show-copy_alerts-attr" i18n>
+              Item Alerts
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-deposit-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.deposit">
+            <label class="form-check-label" for="show-deposit-attr" i18n>
+              Deposit
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-deposit_amount-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.deposit_amount">
+            <label class="form-check-label" for="show-deposit_amount-attr" i18n>
+              Deposit Amount
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-price-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.price">
+            <label class="form-check-label" for="show-price-attr" i18n>
+              Price
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-opac_visible-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.opac_visible">
+            <label class="form-check-label" for="show-opac_visible-attr" i18n>
+              OPAC Visible
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-ref-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.ref">
+            <label class="form-check-label" for="show-ref-attr" i18n>
+              Reference
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-cost-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.cost">
+            <label class="form-check-label" for="show-cost-attr" i18n>
+              Cost 
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-mint_condition-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.mint_condition">
+            <label class="form-check-label" for="show-mint_condition-attr" i18n>
+              Quality
+            </label>
+          </div>
+        </li>
+      </ul>
+    </div>
+  </div>
+
+  <!-- COLUMN 5 -->
+
+  <div class="flex-1 p-1">
+    <div class="card">
+      <div class="card-header" i18n>Statistics</div>
+      <ul class="list-group list-group-flush">
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-copy_tags-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.copy_tags">
+            <label class="form-check-label" for="show-copy_tags-attr" i18n>
+              Add Item Tags
+            </label>
+          </div>
+        </li>
+        <li class="list-group-item">
+          <div class="form-check form-check-inline">
+            <input class="form-check-input" type="checkbox" 
+              id="show-statcats-attr" 
+              [(ngModel)]="volcopy.defaults.hidden.statcats">
+            <label class="form-check-label" for="show-statcats-attr" i18n>
+              Statistical Categories
+            </label>
+          </div>
+        </li>
+      </ul>
+    </div>
+  </div>
+</div>
+
+<div class="row d-flex">
+  <div class="flex-1"></div>
+  <button class="btn btn-outline-dark" (click)="save()" i18n>Save Defaults</button>
+</div>
+
+
index 35c926b..5716f9e 100644 (file)
@@ -34,16 +34,20 @@ export class VolCopyConfigComponent implements OnInit, AfterViewInit {
         private auth: AuthService,
         private pcrud: PcrudService,
         private holdings: HoldingsService,
-        private volcopy: VolCopyService,
         private format: FormatService,
-        private store: StoreService
+        private store: StoreService,
+        public  volcopy: VolCopyService
     ) { }
 
     ngOnInit() {
+        console.log('DEFAULTS', this.volcopy.defaults);
     }
 
     ngAfterViewInit() {
+    }
 
+    save() {
+        this.volcopy.saveDefaults();
     }
 }
 
index 3086135..4ea94ab 100644 (file)
   </eg-combobox>
 </ng-template>
 
+<!-- this one is also repeated a lot -->
+<ng-template #batchAttr let-field="field" 
+  let-label="label" let-template="template" let-displayAs="displayAs">
+  <eg-batch-item-attr 
+    [name]="field" 
+    [label]="label || copyFieldLabel(field)"
+    [displayAs]="displayAs"
+    [editInputDomId]="field + '-input'"
+    [emptyIsUnset]="true"
+    [editTemplate]="template"
+    [labelCounts]="itemAttrCounts(field)"
+    (valueCleared)="applyCopyValue(field, null)"
+    (changesSaved)="applyCopyValue(field)">
+  </eg-batch-item-attr>
+</ng-template>
 
 <!-- Copy Templates -->
 <div class="row border rounded border-dark pt-2 pb-2 bg-faint">
   <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>
   <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-item-location-select>
       </ng-template>
-      <eg-batch-item-attr label="Location / Collection" i18n-label
-        editInputDomId="location-input"
-        [editTemplate]="locationTemplate"
-        [labelCounts]="itemAttrCounts('location')"
-        (changesSaved)="applyCopyValue('location')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'location',template:locationTemplate}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('circ_lib')">
       <ng-template #circLibTemplate>
         <eg-org-select 
-          domId="circ-lib-input"
+          domId="circ_lib-input"
           (onChange)="values['circ_lib'] = $event ? $event.id() : null"
           [limitPerms]="['UPDATE_COPY']">
         </eg-org-select>
       </ng-template>
-      <eg-batch-item-attr label="Circulating Library" i18n-label
-        editInputDomId="circ-lib-input"
-        [editTemplate]="circLibTemplate"
-        [labelCounts]="itemAttrCounts('circ_lib')"
-        (changesSaved)="circLibChanged()">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'circ_lib',template:circLibTemplate}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('owning_lib')">
       <ng-template #owningLibTemplate>
         <eg-org-select 
           domId="owning-lib-input"
           [limitPerms]="['UPDATE_COPY']">
         </eg-org-select>
       </ng-template>
-      <eg-batch-item-attr label="Owning Library" i18n-label
-        editInputDomId="owning-lib-input"
-        [editTemplate]="owningLibTemplate"
-        [labelCounts]="itemAttrCounts('owning_lib')"
-        (changesSaved)="owningLibChanged()">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'owning_lib',template:owningLibTemplate}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('copy_number')">
       <ng-template #copyNumberTemplate>
         <input type="number" class="form-control"
           id="copy-number-input" [(ngModel)]="values['copy_number']"/>
       </ng-template>
-      <eg-batch-item-attr label="Copy Number" i18n-label
-        editInputDomId="copy-number-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="copyNumberTemplate"
-        [labelCounts]="itemAttrCounts('copy_number')"
-        (changesSaved)="applyCopyValue('copy_number')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'copy_number',template:copyNumberTemplate}">
+      </ng-container>
     </div>
-
   </div>
 
   <!-- COLUMN 3 -->
   <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>
       </ng-template>
-      <eg-batch-item-attr label="Circulate" i18n-label
-        displayAs="bool"
-        editInputDomId="circulate-input"
-        [editTemplate]="circulateTemplate"
-        [labelCounts]="itemAttrCounts('circulate')"
-        (changesSaved)="applyCopyValue('circulate')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'circulate',template:circulateTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('holdable')">
       <ng-template #holdableTemplate>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'holdable'}">
         </ng-container>
       </ng-template>
-      <eg-batch-item-attr label="Holdable" i18n-label
-        displayAs="bool"
-        editInputDomId="holdable-input"
-        [editTemplate]="holdableTemplate"
-        [labelCounts]="itemAttrCounts('holdable')"
-        (changesSaved)="applyCopyValue('holdable')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'holdable',template:holdableTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('age_protect')">
       <ng-template #ageProtectTemplate>
-        <select class="form-control" 
-          id="age-protect-input" [(ngModel)]="values['age_protect']">
-          <option [value]="null" i18n>&lt;Unset&gt;</option>
-          <option *ngFor="let rule of ageProtectRules" 
-            value="{{rule.id()}}">{{rule.name()}}</option>
-        </select>
+        <eg-combobox domId="age_protect-input"
+          (ngModelChange)="values['age_protect'] = $event ? $event.id : null"
+          [ngModel]="values['age_protect']">
+          <eg-combobox-entry *ngFor="let rule of volcopy.ageProtectRules"
+            [entryId]="rule.id()" [entryLabel]="rule.name()">
+          </eg-combobox-entry>
+        </eg-combobox>
       </ng-template>
-      <eg-batch-item-attr label="Aged-Based Hold Protection" i18n-label
-        editInputDomId="age-protect-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="ageProtectTemplate"
-        [labelCounts]="itemAttrCounts('age_protect')"
-        (changesSaved)="applyCopyValue('age_protect')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'age_protect',template:ageProtectTemplate}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('floating')">
       <ng-template #floatingTemplate>
-        <select class="form-control" 
-          id="floating-input" [(ngModel)]="values['floating']">
-          <option [value]="null" i18n>&lt;Unset&gt;</option>
-          <option *ngFor="let grp of floatingGroups" 
-            value="{{grp.id()}}">{{grp.name()}}</option>
-        </select>
+        <eg-combobox domId="floating-input"
+          (ngModelChange)="values['floating'] = $event ? $event.id : null"
+          [ngModel]="values['floating']">
+          <eg-combobox-entry *ngFor="let grp of volcopy.floatingGroups"
+            [entryId]="grp.id()" [entryLabel]="grp.name()">
+          </eg-combobox-entry>
+        </eg-combobox>
       </ng-template>
-      <eg-batch-item-attr label="Floating" i18n-label
-        editInputDomId="floating-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="floatingTemplate"
-        [labelCounts]="itemAttrCounts('floating')"
-        (changesSaved)="applyCopyValue('floating')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'floating',template:floatingTemplate}">
+      </ng-container>
     </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>
           <option value="3" i18n>{{loanDurationLong.text}}</option>
         </select>
       </ng-template>
-      <eg-batch-item-attr label="Loan Duration" i18n-label
-        editInputDomId="loan-duration-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="loanDurationTemplate"
-        [labelCounts]="itemAttrCounts('loan_duration')"
-        (changesSaved)="applyCopyValue('loan_duration')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'loan_duration',template:loanDurationTemplate}">
+      </ng-container>
     </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>
           <option value="3" i18n>{{fineLevelHigh.text}}</option>
         </select>
       </ng-template>
-      <eg-batch-item-attr label="Fine Level" i18n-label
-        editInputDomId="fine-level-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="fineLevelTemplate"
-        [labelCounts]="itemAttrCounts('fine_level')"
-        (changesSaved)="applyCopyValue('fine_level')">
-      </eg-batch-item-attr>
-    </div>
-
-    <div>
-      <ng-template #ageProtectTemplate>
-        <select class="form-control" [(ngModel)]="values['age_protect']">
-          <option [value]="null" i18n>&lt;Unset&gt;</option>
-          <option *ngFor="let rule of ageProtectRules" 
-            value="{{rule.id()}}">{{rule.name()}}</option>
-        </select>
-      </ng-template>
-      <eg-batch-item-attr label="Aged-Based Hold Protection" i18n-label
-        [emptyIsUnset]="true"
-        [editTemplate]="ageProtectTemplate"
-        [labelCounts]="itemAttrCounts('age_protect')"
-        (changesSaved)="applyCopyValue('age_protect')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'fine_level',template:fineLevelTemplate}">
+      </ng-container>
     </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>
-          <option *ngFor="let map of itemTypeMaps"
-            value="{{map.code()}}">{{map.value()}}</option>
-        </select>
+        <eg-combobox domId="circ-as-type-input"
+          (ngModelChange)="values['circ_as_type'] = $event ? $event.id : null"
+          [ngModel]="values['circ_as_type']">
+          <eg-combobox-entry *ngFor="let map of volcopy.itemTypeMaps"
+            [entryId]="map.code()" [entryLabel]="map.value()">
+          </eg-combobox-entry>
+        </eg-combobox>
       </ng-template>
-      <eg-batch-item-attr label="Circulate as Type" i18n-label
-        [emptyIsUnset]="true"
-        [editTemplate]="circAsTypeTemplate"
-        [labelCounts]="itemAttrCounts('circ_as_type')"
-        (changesSaved)="applyCopyValue('circ_as_type')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'circ_as_type',template:circAsTypeTemplate}">
+      </ng-container>
     </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>
             value="{{mod.code()}}">{{mod.name()}}</option>
         </select>
       </ng-template>
-      <eg-batch-item-attr label="Circulion Modifier" i18n-label
-        [emptyIsUnset]="true"
-        [editTemplate]="circModifierTemplate"
-        [labelCounts]="itemAttrCounts('circ_modifier')"
-        (changesSaved)="applyCopyValue('circ_modifier')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'circ_modifier',template:circModifierTemplate}">
+      </ng-container>
     </div>
 
   </div>
     </div>
     -->
 
-    <div class="border rounded m-1">
+    <div class="border rounded m-1" *ngIf="displayAttr('copy_notes')">
       <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>
       </ng-template>
-      <eg-batch-item-attr label="Deposit" i18n-label
-        displayAs="bool"
-        editInputDomId="deposit-input"
-        [editTemplate]="depositTemplate"
-        [labelCounts]="itemAttrCounts('deposit')"
-        (changesSaved)="applyCopyValue('deposit')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'deposit',template:depositTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('deposit_amount')">
       <ng-template #depositAmountTemplate>
         <input type="number" class="form-control" 
           id="deposit-amount-input" [(ngModel)]="values['deposit_amount']"/>
       </ng-template>
-      <eg-batch-item-attr label="Deposit Amount" i18n-label
-        displayAs="currency"
-        editInputDomId="deposit-amount-input"
-        [editTemplate]="depositAmountTemplate"
-        [labelCounts]="itemAttrCounts('deposit_amount')"
-        (changesSaved)="applyCopyValue('deposit_amount')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'deposit_amount',template:depositAmountTemplate,displayAs:'currency'}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('price')">
       <ng-template #priceTemplate>
         <input type="number" class="form-control" 
           id="price-input" [(ngModel)]="values['price']"/>
       </ng-template>
-      <eg-batch-item-attr label="Price" i18n-label
-        displayAs="currency"
-        editInputDomId="price-input"
-        [editTemplate]="priceTemplate"
-        [labelCounts]="itemAttrCounts('price')"
-        (changesSaved)="applyCopyValue('price')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'price',template:priceTemplate,displayAs:'currency'}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('opac_visible')">
       <ng-template #opacVisibleTemplate>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'opac_visible'}">
         </ng-container>
       </ng-template>
-      <eg-batch-item-attr label="OPAC Visible" i18n-label
-        displayAs="bool"
-        editInputDomId="opac_visible-input"
-        [editTemplate]="opacVisibleTemplate"
-        [labelCounts]="itemAttrCounts('opac_visible')"
-        (changesSaved)="applyCopyValue('opac_visible')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'opac_visible',template:opacVisibleTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('ref')">
       <ng-template #refTemplate>
         <ng-container *ngTemplateOutlet="yesNoSelect;context:{field:'ref'}">
         </ng-container>
       </ng-template>
-      <eg-batch-item-attr label="Reference" i18n-label
-        displayAs="bool"
-        editInputDomId="ref-input"
-        [editTemplate]="refTemplate"
-        [labelCounts]="itemAttrCounts('ref')"
-        (changesSaved)="applyCopyValue('ref')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'ref',template:refTemplate,displayAs:'bool'}">
+      </ng-container>
     </div>
 
-    <div>
+    <div *ngIf="displayAttr('cost')">
       <ng-template #costTemplate>
         <input type="number" class="form-control" 
           id="cost-input" [(ngModel)]="values['cost']"/>
       </ng-template>
-      <eg-batch-item-attr label="Acquisition Cost" i18n-label
-        displayAs="currency"
-        editInputDomId="cost-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="costTemplate"
-        [labelCounts]="itemAttrCounts('cost')"
-        (changesSaved)="applyCopyValue('cost')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'cost',template:costTemplate,displayAs:'currency'}">
+      </ng-container>
     </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>
 
           <option value="f" i18n>{{mintConditionNo.text}}</option>
         </select>
       </ng-template>
-      <eg-batch-item-attr label="Quality" i18n-label
-        editInputDomId="mint-condition-input"
-        [emptyIsUnset]="true"
-        [editTemplate]="mintConditionTemplate"
-        [labelCounts]="itemAttrCounts('mint_condition')"
-        (changesSaved)="applyCopyValue('mint_condition')">
-      </eg-batch-item-attr>
+      <ng-container *ngTemplateOutlet="batchAttr;
+        context:{field:'mint_condition',template:mintConditionTemplate}">
+      </ng-container>
     </div>
 
   </div>
   <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 class="border rounded m-1" *ngIf="displayAttr('copy_tags')">
+      <!--
+      <eg-copy-tags-dialog #copyTagsDialog></eg-copy-tags-dialog>
+      -->
+      <div class="batch-header font-weight-bold p-2" i18n>Add Item Tags</div>
+      <div class="p-1">
+        <button class="btn btn-outline-dark" (click)="openCopyAlerts()" i18n>
+          Item Tags
+        </button>
+      </div>
     </div>
 
+    <ng-container *ngIf="displayAttr('statcats')">
+      <div *ngFor="let cat of statCats()">
+        <ng-template #statCatTemplate>
+          <eg-combobox domId="stat-cat-input-{{cat.id()}}"
+            (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
+          name="stat_cat_{{cat.id()}}" editInputDomId="stat-cat-input-{{cat.id()}}"
+          [emptyIsUnset]="true"
+          [editTemplate]="statCatTemplate"
+          [labelCounts]="statCatCounts(cat.id())"
+          (changesSaved)="statCatChanged(cat.id())">
+        </eg-batch-item-attr>
+      </div>
+    </ng-container>
   </div>
 </div>
 
index 723638c..44d2858 100644 (file)
@@ -1,4 +1,5 @@
-import {Component, Input, OnInit, AfterViewInit, ViewChild, Renderer2} from '@angular/core';
+import {Component, Input, OnInit, AfterViewInit, ViewChild,
+    QueryList, ViewChildren} from '@angular/core';
 import {Router, ActivatedRoute, ParamMap} from '@angular/router';
 import {tap} from 'rxjs/operators';
 import {IdlObject, IdlService} from '@eg/core/idl.service';
@@ -16,6 +17,7 @@ import {StringComponent} from '@eg/share/string/string.component';
 import {CopyAlertsDialogComponent
     } from '@eg/staff/share/holdings/copy-alerts-dialog.component';
 import {ComboboxComponent, ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {BatchItemAttrComponent} from '@eg/staff/share/holdings/batch-item-attr.component';
 
 @Component({
   selector: 'eg-copy-attrs',
@@ -66,10 +68,12 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
     @ViewChild('copyTemplateCbox', {static: false})
         copyTemplateCbox: ComboboxComponent;
 
+    @ViewChildren(BatchItemAttrComponent)
+        batchAttrs: QueryList<BatchItemAttrComponent>;
+
     constructor(
         private router: Router,
         private route: ActivatedRoute,
-        private renderer: Renderer2,
         private evt: EventService,
         private idl: IdlService,
         private org: OrgService,
@@ -77,9 +81,9 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
         private auth: AuthService,
         private pcrud: PcrudService,
         private holdings: HoldingsService,
-        private volcopy: VolCopyService,
         private format: FormatService,
-        private store: StoreService
+        private store: StoreService,
+        public  volcopy: VolCopyService
     ) { }
 
     ngOnInit() {
@@ -221,7 +225,13 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
     }
 
     applyCopyValue(field: string, value?: any) {
-        if (value === undefined) { value = this.values[field]; }
+        if (value === undefined) {
+            value = this.values[field];
+        } else {
+            this.values[field] = value;
+        }
+
+        // TODO: handle circ_lib, owning_lib changes specially
 
         console.debug('APPLYING', field, value);
 
@@ -233,18 +243,6 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
         });
     }
 
-    circLibChanged() {
-        // TODO other stuff happens here?
-        this.applyCopyValue('circ_lib');
-    }
-
-    owningLibChanged() {
-        // TODO
-        // copies.ischanged(true);
-        console.log('OWNING LIB ', this.values['owning_lib']);
-    }
-
-
     // Create or modify a stat cat entry for each copy that does not
     // already match the new value.
     statCatChanged(catId: number) {
@@ -311,6 +309,21 @@ export class CopyAttrsComponent implements OnInit, AfterViewInit {
             this.applyCopyValue(field, value);
         });
     }
+
+    saveTemplate() {
+        this.batchAttrs.forEach(comp => {
+            console.log(comp.editInputDomId);
+        });
+    }
+
+    displayAttr(field: string): boolean {
+        return this.volcopy.defaults.hidden[field] !== true;
+    }
+
+    copyFieldLabel(field: string): string {
+        const def = this.idl.classes.acp.field_map[field];
+        return def ? def.label : '';
+    }
 }
 
 
index 9edeb21..8d06132 100644 (file)
 <div class="row d-flex bg-faint mb-2 pb-1 pt-1 border border-dark rounded">
   <div class="p-1" [ngStyle]="{flex: flexAt(1)}"> </div>
   <div class="p-1" [ngStyle]="{flex: flexAt(2)}"> </div>
-  <div class="p-1" [ngStyle]="{flex: flexAt(3)}">
+  <div class="p-1" [ngStyle]="{flex: flexAt(3)}" *ngIf="displayColumn('classification')">
     <div><label class="font-weight-bold" i18n>Classification</label></div>
     <div>
       <eg-combobox [smallFormControl]="true" [(ngModel)]="batchVolClass">
-        <eg-combobox-entry *ngFor="let cls of volClasses"
+        <eg-combobox-entry *ngFor="let cls of volcopy.volClasses"
           [entryId]="cls.id()" [entryLabel]="cls.name()">
         </eg-combobox-entry>
       </eg-combobox>
     </div>
   </div>
-  <div class="p-1" [ngStyle]="{flex: flexAt(4)}">
+  <div class="p-1" [ngStyle]="{flex: flexAt(4)}" *ngIf="displayColumn('prefix')">
     <div><label class="font-weight-bold" i18n>Prefix</label></div>
     <div>
       <eg-combobox [smallFormControl]="true" [(ngModel)]="batchVolPrefix">
-        <eg-combobox-entry *ngFor="let pfx of volPrefixes"
+        <eg-combobox-entry *ngFor="let pfx of volcopy.volPrefixes"
           [entryId]="pfx.id()" [entryLabel]="pfx.label()">
         </eg-combobox-entry>
       </eg-combobox>
       </eg-combobox>
     </div>
   </div>
-  <div class="p-1" [ngStyle]="{flex: flexAt(6)}">
+  <div class="p-1" [ngStyle]="{flex: flexAt(6)}" *ngIf="displayColumn('suffix')">
     <div><label class="font-weight-bold" i18n>Suffix</label></div>
     <div>
       <eg-combobox [smallFormControl]="true" [(ngModel)]="batchVolSuffix">
-        <eg-combobox-entry *ngFor="let sfx of volSuffixes"
+        <eg-combobox-entry *ngFor="let sfx of volcopy.volSuffixes"
           [entryId]="sfx.id()" [entryLabel]="sfx.label()">
         </eg-combobox-entry>
       </eg-combobox>
   <div class="p-1" [ngStyle]="{flex: flexAt(2)}">
     <label class="font-weight-bold" i18n>Call Numbers</label>
   </div>
-  <div class="p-1" [ngStyle]="{flex: flexAt(3)}">
+  <div class="p-1" [ngStyle]="{flex: flexAt(3)}" *ngIf="displayColumn('classification')">
     <label class="font-weight-bold" i18n>Classification</label>
   </div>
-  <div class="p-1" [ngStyle]="{flex: flexAt(4)}">
+  <div class="p-1" [ngStyle]="{flex: flexAt(4)}" *ngIf="displayColumn('prefix')">
     <label class="font-weight-bold" i18n>Prefix</label>
   </div>
   <div class="p-1" [ngStyle]="{flex: flexAt(5)}">
     <label class="font-weight-bold" i18n>Call Number Label</label>
   </div>
-  <div class="p-1" [ngStyle]="{flex: flexAt(6)}">
+  <div class="p-1" [ngStyle]="{flex: flexAt(6)}" *ngIf="displayColumn('suffix')">
     <label class="font-weight-bold" i18n>Suffix</label>
   </div>
   <div class="p-1" [ngStyle]="{flex: flexAt(7)}">
               (ngModelChange)="volCountChanged(orgNode, $event)"/>
           </ng-container>
         </div>
-        <div class="p-1" [ngStyle]="{flex: flexAt(3)}">
+        <div class="p-1" [ngStyle]="{flex: flexAt(3)}" *ngIf="displayColumn('classification')">
           <ng-container *ngIf="copyIdx == 0">
             <eg-combobox
               [selectedId]="volNode.target.label_class()"
               [smallFormControl]="true"
               [required]="true"
               (onChange)="applyVolValue(volNode.target, 'label_class', $event ? $event.id : null)">
-              <eg-combobox-entry *ngFor="let cls of volClasses"
+              <eg-combobox-entry *ngFor="let cls of volcopy.volClasses"
                 [entryId]="cls.id()" [entryLabel]="cls.name()">
               </eg-combobox-entry>
             </eg-combobox>
           </ng-container>
         </div>
-        <div class="p-1" [ngStyle]="{flex: flexAt(4)}">
+        <div class="p-1" [ngStyle]="{flex: flexAt(4)}" *ngIf="displayColumn('prefix')">
           <ng-container *ngIf="copyIdx == 0">
             <eg-combobox
               [selectedId]="volNode.target.prefix()"
               <eg-combobox-entry
                 [entryId]="-1" entryLabel="<None>" i18n-entryLabel>
               </eg-combobox-entry>
-              <eg-combobox-entry *ngFor="let pfx of volPrefixes"
+              <eg-combobox-entry *ngFor="let pfx of volcopy.volPrefixes"
                 [entryId]="pfx.id()" [entryLabel]="pfx.label()">
               </eg-combobox-entry>
             </eg-combobox>
               (change)="applyVolValue(volNode.target, 'label', $event.target.value)">
           </ng-container>
         </div>
-        <div class="p-1" [ngStyle]="{flex: flexAt(6)}">
+        <div class="p-1" [ngStyle]="{flex: flexAt(6)}" *ngIf="displayColumn('suffix')">
           <ng-container *ngIf="copyIdx == 0">
             <eg-combobox
               [selectedId]="volNode.target.suffix()"
               <eg-combobox-entry
                 [entryId]="-1" entryLabel="<None>" i18n-entryLabel>
               </eg-combobox-entry>
-              <eg-combobox-entry *ngFor="let sfx of volSuffixes"
+              <eg-combobox-entry *ngFor="let sfx of volcopy.volSuffixes"
                 [entryId]="sfx.id()" [entryLabel]="sfx.label()">
               </eg-combobox-entry>
             </eg-combobox>
index 4dc6574..b6948a4 100644 (file)
@@ -30,9 +30,6 @@ export class VolEditComponent implements OnInit {
     flexSettings: {[column: number]: number} = {
         1: 1, 2: 1, 3: 2, 4: 1, 5: 2, 6: 1, 7: 1, 8: 2, 9: 1, 10: 1};
 
-    volClasses: IdlObject[] = null;
-    volPrefixes: IdlObject[] = null;
-    volSuffixes: IdlObject[] = null;
     bibParts: {[bibId: number]: IdlObject[]} = {};
 
     batchVolClass: ComboboxEntry;
@@ -64,7 +61,7 @@ export class VolEditComponent implements OnInit {
         private net: NetService,
         private auth: AuthService,
         private holdings: HoldingsService,
-        private volcopy: VolCopyService
+        public  volcopy: VolCopyService
     ) {}
 
     ngOnInit() {
@@ -76,24 +73,6 @@ export class VolEditComponent implements OnInit {
         .then(labels => this.recordVolLabels = labels)
         .then(_ => this.fetchBibParts())
         .then(_ => this.addStubCopies());
-
-        this.holdings.fetchCallNumberClasses().then(
-            classes => this.volClasses = classes);
-
-        const myOrgs = this.org.fullPath(this.auth.user().ws_ou(), true);
-
-        // The batch edit controls only include values for "here"
-        this.holdings.fetchCallNumberPrefixes().then(prefixes =>
-            this.volPrefixes = prefixes
-                .filter(sfx => sfx.id() !== -1)
-                .filter(pfx => myOrgs.includes(pfx.owning_lib()))
-        );
-
-        this.holdings.fetchCallNumberSuffixes().then(suffixes =>
-            this.volSuffixes = suffixes
-                .filter(sfx => sfx.id() !== -1)
-                .filter(sfx => myOrgs.includes(sfx.owning_lib()))
-        );
     }
 
 
@@ -510,5 +489,9 @@ export class VolEditComponent implements OnInit {
             }
         }
     }
+
+    displayColumn(field: string): boolean {
+        return this.volcopy.defaults.hidden[field] !== true;
+    }
 }
 
index 2c69778..996ebb7 100644 (file)
@@ -6,7 +6,7 @@
   </div>
 </div>
 
-<ng-container *ngIf="!sessionExpired">
+<ng-container *ngIf="!sessionExpired && !loading">
 
   <eg-bib-summary *ngIf="context.recordId" [recordId]="context.recordId"></eg-bib-summary>
 
index 07e009e..d9ce8a0 100644 (file)
@@ -15,12 +15,18 @@ 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;
+    defaults: VolCopyDefaults = null;
+    defaultLocation: IdlObject;
     copyStatuses: {[id: number]: IdlObject} = null;
 
     // Track this here so it can survive route changes.
@@ -32,6 +38,9 @@ export class VolCopyService {
     circModifiers: IdlObject[] = [];
     statCats: IdlObject[] = [];
     statCatEntryMap: {[id: number]: IdlObject} = {}; // entry id => entry
+    volClasses: IdlObject[] = null;
+    volPrefixes: IdlObject[] = null;
+    volSuffixes: IdlObject[] = null;
 
     templateNames: ComboboxEntry[] = [];
     templates: any = {};
@@ -52,14 +61,30 @@ export class VolCopyService {
     // Fetch the data that is always needed.
     load(): Promise<any> {
 
-        if (this.itemTypeMaps.length > 0) {
-            return Promise.resolve();
-        }
+        if (this.itemTypeMaps.length > 0) { return Promise.resolve(); }
+
+        const myOrgs = this.org.fullPath(this.auth.user().ws_ou(), true);
 
         return this.fetchDefaults()
         .then(_ => this.holdings.fetchCallNumberClasses())
-        .then(_ => this.holdings.fetchCallNumberPrefixes())
-        .then(_ => this.holdings.fetchCallNumberSuffixes())
+        .then(cls => this.volClasses = cls)
+
+        .then(_ => {
+            return this.holdings.fetchCallNumberPrefixes().then(prefixes =>
+                this.volPrefixes = prefixes
+                    .filter(sfx => sfx.id() !== -1)
+                    .filter(pfx => myOrgs.includes(pfx.owning_lib()))
+            );
+        })
+
+        .then(_ => {
+            return this.holdings.fetchCallNumberSuffixes().then(suffixes =>
+                this.volSuffixes = suffixes
+                    .filter(sfx => sfx.id() !== -1)
+                    .filter(sfx => myOrgs.includes(sfx.owning_lib()))
+            );
+        })
+
         .then(_ => this.fetchCopyStats())
         .then(_ => this.fetchTemplates())
         .then(_ => {
@@ -147,17 +172,23 @@ export class VolCopyService {
     }
 
     fetchDefaults(): Promise<any> {
-        if (this.defaultValues) { return Promise.resolve(); }
+        if (this.defaults) { return Promise.resolve(); }
 
-        return this.serverStore.getItem('cat.copy.defaults').then(
-            defaults => {
-                this.defaultValues = defaults || {};
+        return this.serverStore.getItem('eg.cat.volcopy.defaults').then(
+            (defaults: VolCopyDefaults) => {
+                this.defaults = defaults || {values: {}, hidden: {}};
             }
+
         ).then(_ => {
 
-            // Default to location ID 1 (Stacks)
-            return this.pcrud.retrieve('acpl', 1).toPromise()
-            .then(loc => this.defaultValues.location = loc);
+            // Use the first non-deleted copy location within org unit
+            // range as the default.  Typically "Stacks".
+
+            const myOrgs = this.org.fullPath(this.auth.user().ws_ou(), true);
+            return this.pcrud.search('acpl',
+                {deleted: 'f', owning_lib: myOrgs},
+                {order_by: {acpl: 'id'}, limit: 1}
+            ).toPromise().then(loc => this.defaultLocation = loc);
         });
     }
 
@@ -183,7 +214,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.defaults.values.classification || null
         ).toPromise().then(res => {
             return Object.values(res)
                 .map(blob => Object.values(blob)[0]).sort();
@@ -199,8 +230,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.defaults.values.prefix || -1);
+        vol.suffix(this.defaults.values.suffix || -1);
 
         return vol;
     }
@@ -218,7 +249,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.defaultLocation);  // Stacks / fleshed
         copy.circulate('t');
         copy.holdable('t');
         copy.opac_visible('t');
@@ -251,12 +282,12 @@ export class VolCopyService {
 
         let promise = Promise.resolve(); // Serialization
 
-        if (this.defaultValues.classification) {
+        if (this.defaults.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.defaults.values.classification));
 
             return promise;
 
@@ -371,6 +402,24 @@ export class VolCopyService {
     }
 
 
+    saveDefaults(): Promise<any> {
+
+        // Scrub unnecessary content before storing.
+
+        Object.keys(this.defaults.values).forEach(field => {
+            if (this.defaults.values[field] === null) {
+                delete this.defaults.values[field];
+            }
+        });
 
+        Object.keys(this.defaults.hidden).forEach(field => {
+            if (this.defaults.hidden[field] !== true) {
+                delete this.defaults.hidden[field];
+            }
+        });
+
+        return this.serverStore.setItem(
+            'eg.cat.volcopy.defaults', this.defaults);
+    }
 }
 
index e8f00a2..f364cd5 100644 (file)
@@ -36,6 +36,7 @@
     <div class="mt-1">
       <button class="btn btn-outline-dark" (click)="save()" i18n>Apply</button>
       <button class="btn btn-outline-dark ml-1" (click)="cancel()" i18n>Cancel</button>
+      <button class="btn btn-outline-dark ml-1" (click)="clear()" i18n>Clear</button>
     </div>
   </ng-container>
 </div>
index 408ebf9..a725454 100644 (file)
@@ -21,6 +21,10 @@ export class BatchItemAttrComponent {
     // Main display label, e.g. "Circulation Modifier"
     @Input() label: string;
 
+    // Optional.  Useful for exracting information (i.e. hasChanges)
+    // on a specific field from a set of batch attr components.
+    @Input() name: string;
+
     // Maps display labels to the number of items that have the label.
     // e.g. {"Stacks": 4, "Display": 12}
     @Input() labelCounts: {[label: string]: number} = {};
@@ -44,6 +48,7 @@ export class BatchItemAttrComponent {
 
     @Output() changesSaved: EventEmitter<void> = new EventEmitter<void>();
     @Output() changesCanceled: EventEmitter<void> = new EventEmitter<void>();
+    @Output() valueCleared: EventEmitter<void> = new EventEmitter<void>();
 
     // Is the editTtemplate visible?
     editing = false;
@@ -63,6 +68,13 @@ export class BatchItemAttrComponent {
         this.changesCanceled.emit();
     }
 
+    clear() {
+        this.hasChanged = true;
+        this.editing = false;
+        this.valueCleared.emit();
+    }
+
+
     toggleEditMode() {
         if (this.readOnly) { return; }
 
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'
+    )
+);
+
+