From bfb4d49108225f1ec9d337e595f8754707cab424 Mon Sep 17 00:00:00 2001 From: Bertrand Zuchuat Date: Mon, 23 Sep 2019 12:33:25 +0200 Subject: [PATCH] form options: item type and location * Adds custom widgets * Adds a new column "type" on item_type * Adds a new column "is_online" on location Co-Authored-by: Bertrand Zuchuat Co-Authored-by: Alicia Zangger --- data/item_types.json | 21 +++-- .../form_item_types/item_type-v0.0.1.json | 26 +++++- .../item_types/item_type-v0.0.1.json | 3 +- .../form_locations/location-v0.0.1.json | 34 +++++--- tests/data/data.json | 18 ++-- tests/ui/item_types/test_item_types_api.py | 2 +- ui/src/app/core/utils.ts | 5 ++ .../checkbox-is-online.component.html | 43 ++++++++++ .../checkbox-is-online.component.scss | 18 ++++ .../checkbox-is-online.component.spec.ts | 43 ++++++++++ .../checkbox-is-online.component.ts | 80 ++++++++++++++++++ ui/src/app/records/editor/editor.component.ts | 4 + .../select-item-type-type.component.html | 72 ++++++++++++++++ .../select-item-type-type.component.scss | 18 ++++ .../select-item-type-type.component.spec.ts | 44 ++++++++++ .../select-item-type-type.component.ts | 84 +++++++++++++++++++ ui/src/app/records/records.module.ts | 10 ++- ui/src/app/records/records.service.ts | 16 +++- 18 files changed, 511 insertions(+), 30 deletions(-) create mode 100644 ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.html create mode 100644 ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.scss create mode 100644 ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.spec.ts create mode 100644 ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.ts create mode 100644 ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.html create mode 100644 ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.scss create mode 100644 ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.spec.ts create mode 100644 ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.ts diff --git a/data/item_types.json b/data/item_types.json index 8454ed67e6..a58182cc11 100644 --- a/data/item_types.json +++ b/data/item_types.json @@ -6,7 +6,8 @@ "description": "Standard checkout.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/1" - } + }, + "type": "standard" }, { "pid": "2", @@ -15,7 +16,8 @@ "description": "Short checkout.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/1" - } + }, + "type": "standard" }, { "pid": "3", @@ -24,7 +26,8 @@ "description": "On-site consultation.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/1" - } + }, + "type": "standard" }, { "pid": "4", @@ -33,7 +36,8 @@ "description": "No checkout.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/1" - } + }, + "type": "standard" }, { "pid": "5", @@ -42,7 +46,8 @@ "description": "Standard checkout for adults only (16+).", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/1" - } + }, + "type": "standard" }, { "pid": "6", @@ -51,7 +56,8 @@ "description": "Short checkout for adults only (16+).", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/1" - } + }, + "type": "standard" }, { "pid": "7", @@ -60,7 +66,8 @@ "description": "Standard checkout.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/2" - } + }, + "type": "standard" }, { "pid": "8", diff --git a/rero_ils/modules/item_types/jsonschemas/form_item_types/item_type-v0.0.1.json b/rero_ils/modules/item_types/jsonschemas/form_item_types/item_type-v0.0.1.json index 6b78dc6760..bae249e92b 100644 --- a/rero_ils/modules/item_types/jsonschemas/form_item_types/item_type-v0.0.1.json +++ b/rero_ils/modules/item_types/jsonschemas/form_item_types/item_type-v0.0.1.json @@ -31,5 +31,29 @@ "key": "description" } ] + }, + { + "type": "fieldset", + "items": [ + { + "key": "type", + "type": "select-item-type-type", + "required": true, + "validationMessage": { + "alreadyTakenMessage": "There is already an online type for your organisation" + }, + "titleMap": [ + { + "value": "standard", + "name": "Standard" + }, + { + "value": "online", + "name": "Online" + } + ], + "default": "standard" + } + ] } -] \ No newline at end of file +] diff --git a/rero_ils/modules/item_types/jsonschemas/item_types/item_type-v0.0.1.json b/rero_ils/modules/item_types/jsonschemas/item_types/item_type-v0.0.1.json index f74d24d754..2b6163701c 100644 --- a/rero_ils/modules/item_types/jsonschemas/item_types/item_type-v0.0.1.json +++ b/rero_ils/modules/item_types/jsonschemas/item_types/item_type-v0.0.1.json @@ -8,7 +8,8 @@ "$schema", "pid", "name", - "organisation" + "organisation", + "type" ], "properties": { "$schema": { diff --git a/rero_ils/modules/locations/jsonschemas/form_locations/location-v0.0.1.json b/rero_ils/modules/locations/jsonschemas/form_locations/location-v0.0.1.json index 450963c248..f7a867f573 100644 --- a/rero_ils/modules/locations/jsonschemas/form_locations/location-v0.0.1.json +++ b/rero_ils/modules/locations/jsonschemas/form_locations/location-v0.0.1.json @@ -6,8 +6,7 @@ "title": "Library", "key": "library.$ref", "type": "select", - "remoteRecordType": "libraries", - "readonly": true + "remoteRecordType": "libraries" } ] }, @@ -33,15 +32,30 @@ ] }, { - "key": "is_pickup", - "type": "checkbox" - }, - { - "key": "is_online", - "type": "checkbox" + "type": "fieldset", + "items": [ + { + "key": "is_pickup", + "type": "checkbox" + }, + { + "key": "pickup_name", + "condition": "model.is_pickup" + } + ] }, { - "key": "pickup_name", - "condition": "model.is_pickup" + "type": "fieldset", + "items": [ + { + "key": "is_online", + "notitle": true, + "type": "checkbox-is-online", + "label": "Is Online", + "validationMessage": { + "alreadyTakenMessage": "The \"online\" type must be unique per library" + } + } + ] } ] diff --git a/tests/data/data.json b/tests/data/data.json index 67aea35947..6b694f951c 100644 --- a/tests/data/data.json +++ b/tests/data/data.json @@ -657,7 +657,8 @@ "description": "Standard checkout.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/org1" - } + }, + "type": "standard" }, "itty2": { "$schema": "https://ils.rero.ch/schema/item_types/item_type-v0.0.1.json", @@ -666,7 +667,8 @@ "description": "On-site consultation.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/org1" - } + }, + "type": "standard" }, "itty3": { "$schema": "https://ils.rero.ch/schema/item_types/item_type-v0.0.1.json", @@ -675,7 +677,8 @@ "description": "Specific rules.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/org1" - } + }, + "type": "standard" }, "itty4": { "$schema": "https://ils.rero.ch/schema/item_types/item_type-v0.0.1.json", @@ -684,7 +687,8 @@ "description": "Regular checkout.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/org2" - } + }, + "type": "standard" }, "itty5": { "$schema": "https://ils.rero.ch/schema/item_types/item_type-v0.0.1.json", @@ -693,7 +697,8 @@ "description": "Internal consultation.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/org2" - } + }, + "type": "standard" }, "itty6": { "$schema": "https://ils.rero.ch/schema/item_types/item_type-v0.0.1.json", @@ -702,7 +707,8 @@ "description": "Particular rules.", "organisation": { "$ref": "https://ils.rero.ch/api/organisations/org2" - } + }, + "type": "standard" }, "itty7": { "$schema": "https://ils.rero.ch/schema/item_types/item_type-v0.0.1.json", diff --git a/tests/ui/item_types/test_item_types_api.py b/tests/ui/item_types/test_item_types_api.py index a3ff770729..62b65ef7a2 100644 --- a/tests/ui/item_types/test_item_types_api.py +++ b/tests/ui/item_types/test_item_types_api.py @@ -34,7 +34,7 @@ def test_item_type_create(db, item_type_data_tmp, org_martigny, with pytest.raises(RecordValidationError): itty = ItemType.create(item_type_data_tmp, delete_pid=True) - del item_type_data_tmp['type'] + item_type_data_tmp['type'] = 'standard' itty = ItemType.create(item_type_data_tmp, delete_pid=True) assert itty == item_type_data_tmp diff --git a/ui/src/app/core/utils.ts b/ui/src/app/core/utils.ts index a36cc4251f..7e50ad801e 100644 --- a/ui/src/app/core/utils.ts +++ b/ui/src/app/core/utils.ts @@ -32,3 +32,8 @@ export function cleanDictKeys(data: any) { export function _(str: string) { return str; } + +export function extractIdOnRef(ref: string) { + const rx = /.*\/?(.+)$/ig; + return rx.exec(ref)[1]; +} diff --git a/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.html b/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.html new file mode 100644 index 0000000000..90afeb2e09 --- /dev/null +++ b/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.html @@ -0,0 +1,43 @@ + + diff --git a/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.scss b/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.scss new file mode 100644 index 0000000000..6d4fb55cab --- /dev/null +++ b/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.scss @@ -0,0 +1,18 @@ +/* + + RERO ILS + Copyright (C) 2019 RERO + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + */ diff --git a/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.spec.ts b/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.spec.ts new file mode 100644 index 0000000000..0a38f36aaa --- /dev/null +++ b/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.spec.ts @@ -0,0 +1,43 @@ +/* + +RERO ILS +Copyright (C) 2019 RERO + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CheckboxIsOnlineComponent } from './checkbox-is-online.component'; + +describe('CheckboxIsOnlineComponent', () => { + let component: CheckboxIsOnlineComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ CheckboxIsOnlineComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CheckboxIsOnlineComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.ts b/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.ts new file mode 100644 index 0000000000..db480cdebd --- /dev/null +++ b/ui/src/app/records/editor/checkbox-is-online/checkbox-is-online.component.ts @@ -0,0 +1,80 @@ +/* + +RERO ILS +Copyright (C) 2019 RERO + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ + +import { Component, OnInit, Input } from '@angular/core'; +import { AbstractControl } from '@angular/forms'; +import { JsonSchemaFormService } from 'angular6-json-schema-form'; +import { of } from 'rxjs'; +import { RecordsService } from '@app/records/records.service'; + +@Component({ + selector: 'app-checkbox-is-online', + templateUrl: './checkbox-is-online.component.html', + styleUrls: ['./checkbox-is-online.component.scss'] +}) +export class CheckboxIsOnlineComponent implements OnInit { + formControl: AbstractControl; + controlName: string; + controlValue: any; + controlDisabled = false; + boundControl = false; + options: any; + trueValue: any = true; + falseValue: any = false; + @Input() layoutNode: any; + @Input() layoutIndex: number[]; + @Input() dataIndex: number[]; + + constructor( + private jsf: JsonSchemaFormService, + private recordsService: RecordsService + ) { } + + ngOnInit() { + this.options = this.layoutNode.options || {}; + this.jsf.initializeControl(this); + if (this.controlValue === null || this.controlValue === undefined) { + this.controlValue = this.options.title; + } + this.formControl.setAsyncValidators([ + this.validUniqueIsOnlineLocationValidator.bind(this) + ]); + } + + updateValue(event) { + event.preventDefault(); + this.jsf.updateValue(this, event.target.checked ? this.trueValue : this.falseValue); + } + + get isChecked() { + return this.jsf.getFormControlValue(this) === this.trueValue; + } + + validUniqueIsOnlineLocationValidator(control: AbstractControl) { + if (this.isChecked) { + const values = control.root.value; + return this.recordsService.uniqueIsOnlineLocationValidator( + values.library.$ref, + values.pid + ); + } else { + return of(); + } + } +} diff --git a/ui/src/app/records/editor/editor.component.ts b/ui/src/app/records/editor/editor.component.ts index 139ec7dfb4..69204b69d9 100644 --- a/ui/src/app/records/editor/editor.component.ts +++ b/ui/src/app/records/editor/editor.component.ts @@ -39,6 +39,8 @@ import { AddReferenceComponent } from './add-reference/add-reference.component'; import { UserService } from '../../user.service'; import { MainFieldsManagerComponent } from './main-fields-manager/main-fields-manager.component'; import { SubmitComponent } from './submit/submit.component'; +import { SelectItemTypeTypeComponent } from './select-item-type-type/select-item-type-type.component'; +import { CheckboxIsOnlineComponent } from './checkbox-is-online/checkbox-is-online.component'; // import { Bootstrap4Framework } from 'angular6-json-schema-form'; // import { Framework } from 'angular6-json-schema-form'; @@ -92,6 +94,8 @@ export class EditorComponent implements OnInit { this.widgetLibrary.registerWidget('$ref', AddReferenceComponent); this.widgetLibrary.registerWidget('main-fields-manager', MainFieldsManagerComponent); this.widgetLibrary.registerWidget('submit', SubmitComponent); + this.widgetLibrary.registerWidget('select-item-type-type', SelectItemTypeTypeComponent); + this.widgetLibrary.registerWidget('checkbox-is-online', CheckboxIsOnlineComponent); this.currentLocale = translateService.currentLang; this.userService.userSettings.subscribe(settings => this.userSettings = settings); diff --git a/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.html b/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.html new file mode 100644 index 0000000000..eb3a7e47d4 --- /dev/null +++ b/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.html @@ -0,0 +1,72 @@ + +
+ + + +
diff --git a/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.scss b/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.scss new file mode 100644 index 0000000000..6d4fb55cab --- /dev/null +++ b/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.scss @@ -0,0 +1,18 @@ +/* + + RERO ILS + Copyright (C) 2019 RERO + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, version 3 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + */ diff --git a/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.spec.ts b/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.spec.ts new file mode 100644 index 0000000000..ecdc1389c9 --- /dev/null +++ b/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.spec.ts @@ -0,0 +1,44 @@ +/* + +RERO ILS +Copyright (C) 2019 RERO + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ + +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SelectItemTypeTypeComponent } from './select-item-type-type.component'; + +describe('SelectItemTypeTypeComponent', () => { + let component: SelectItemTypeTypeComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ SelectItemTypeTypeComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(SelectItemTypeTypeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.ts b/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.ts new file mode 100644 index 0000000000..46c541dddc --- /dev/null +++ b/ui/src/app/records/editor/select-item-type-type/select-item-type-type.component.ts @@ -0,0 +1,84 @@ +/* + +RERO ILS +Copyright (C) 2019 RERO + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, version 3 of the License. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +*/ + +import { AbstractControl } from '@angular/forms'; +import { buildTitleMap, isArray } from 'angular6-json-schema-form'; +import { Component, Input, OnInit } from '@angular/core'; +import { JsonSchemaFormService } from 'angular6-json-schema-form'; +import { RecordsService } from '@app/records/records.service'; +import { _ } from '@app/circulation/main-request/main-request.component'; +import { of } from 'rxjs'; + +@Component({ + selector: 'app-select-item-type-type', + templateUrl: './select-item-type-type.component.html', + styleUrls: ['./select-item-type-type.component.scss'] +}) +export class SelectItemTypeTypeComponent implements OnInit { + formControl: AbstractControl; + controlName: string; + controlValue: any; + controlDisabled = false; + boundControl = false; + options: any; + selectList: any[] = []; + isArray = isArray; + @Input() layoutNode: any; + @Input() layoutIndex: number[]; + @Input() dataIndex: number[]; + + constructor( + private jsf: JsonSchemaFormService, + private recordsService: RecordsService + ) { } + + ngOnInit() { + this.options = this.layoutNode.options || {}; + this.selectList = buildTitleMap( + this.options.titleMap || this.options.enumNames, + this.options.enum, !!this.options.required, !!this.options.flatList + ); + this.jsf.initializeControl(this); + if (this.options.default) { + this.formControl.setValue(this.options.default); + } + this.formControl.setAsyncValidators([ + this.typeValidator.bind(this) + ]); + } + + updateValue(event) { + this.jsf.updateValue(this, event.target.value); + } + + typeValidator(control: AbstractControl) { + const pid = control.root.value.pid; + const type = control.value; + if (type === 'online') { + return this.recordsService.valueAlreadyExists( + 'item_types', + 'type', + control.value, + pid + ); + } else { + return of(); + } + } +} diff --git a/ui/src/app/records/records.module.ts b/ui/src/app/records/records.module.ts index 7e327fbff1..18af9fe088 100644 --- a/ui/src/app/records/records.module.ts +++ b/ui/src/app/records/records.module.ts @@ -76,6 +76,8 @@ import { Bootstrap4FrameworkComponent } from './editor/bootstrap4-framework/boot import { AddReferenceComponent } from './editor/add-reference/add-reference.component'; import { MainFieldsManagerComponent } from './editor/main-fields-manager/main-fields-manager.component'; import { SubmitComponent } from './editor/submit/submit.component'; +import { SelectItemTypeTypeComponent } from './editor/select-item-type-type/select-item-type-type.component'; +import { CheckboxIsOnlineComponent } from './editor/checkbox-is-online/checkbox-is-online.component'; @NgModule({ declarations: [ @@ -114,7 +116,9 @@ import { SubmitComponent } from './editor/submit/submit.component'; Bootstrap4FrameworkComponent, AddReferenceComponent, MainFieldsManagerComponent, - SubmitComponent + SubmitComponent, + SelectItemTypeTypeComponent, + CheckboxIsOnlineComponent ], imports: [ CommonModule, @@ -150,7 +154,9 @@ import { SubmitComponent } from './editor/submit/submit.component'; Bootstrap4FrameworkComponent, AddReferenceComponent, MainFieldsManagerComponent, - SubmitComponent + SubmitComponent, + SelectItemTypeTypeComponent, + CheckboxIsOnlineComponent ], providers: [ LibraryExceptionFormService, diff --git a/ui/src/app/records/records.service.ts b/ui/src/app/records/records.service.ts index d0dbdde9a8..2d5a5fc94a 100644 --- a/ui/src/app/records/records.service.ts +++ b/ui/src/app/records/records.service.ts @@ -24,7 +24,7 @@ import { of, Subject } from 'rxjs'; import { TranslateService } from '@ngx-translate/core'; import { I18nPluralPipe, NgLocaleLocalization } from '@angular/common'; -import { DialogService, _ } from '@app/core'; +import { DialogService, _, extractIdOnRef } from '@app/core'; @Injectable({ providedIn: 'root' @@ -171,7 +171,7 @@ export class RecordsService { return this.http.put(url, record); } - valueAlreadyExists(record_type, field, value, excludePid) { + valueAlreadyExists(record_type, field, value, excludePid = null) { let url = `/api/${record_type}/?size=0&q=${field}:"${value}"`; if (excludePid) { url += ` NOT pid:${excludePid}`; @@ -183,6 +183,18 @@ export class RecordsService { ); } + uniqueIsOnlineLocationValidator(libraryRef: any, excludePid = null) { + const libraryPid = extractIdOnRef(libraryRef); + let url = `/api/locations/?size=0&q=library.pid:${libraryPid} AND is_online:true`; + if (excludePid) { + url += ` NOT pid:${excludePid}`; + } + return this.http.get(url).pipe( + map(res => res.hits.total), + map(total => total ? { alreadyTakenMessage: '' } : null), + debounceTime(1000) + ); + } deleteRecord(pid, recordType) { const success = new Subject();