From ec01b3f16e502c63807e1f3151476b04ede4f5b8 Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Thu, 3 Sep 2020 11:32:56 -0400 Subject: [PATCH] LP1879335 Retrieve linked bibs on demand Avoid populating any lists of all linked bib IDs for an authority record, since these lists can be very large. Instead, report the linked record count to the browse UI and teach the linked bibs UI to retrieve paged linked bib data on demand. Modifies the "abl" IDL class to be accessible via pcrud. Signed-off-by: Bill Erickson Signed-off-by: Galen Charlton --- Open-ILS/examples/fm_IDL.xml | 7 ++- .../app/staff/cat/authority/browse.service.ts | 2 +- .../staff/cat/authority/manage.component.html | 2 +- .../staff/cat/authority/manage.component.ts | 14 ++++++ .../share/bib-list/bib-list.component.ts | 48 +++++++++++-------- .../OpenILS/Application/Search/Authority.pm | 15 ++++-- 6 files changed, 62 insertions(+), 26 deletions(-) diff --git a/Open-ILS/examples/fm_IDL.xml b/Open-ILS/examples/fm_IDL.xml index 60e4bea34e..e5c945d1d4 100644 --- a/Open-ILS/examples/fm_IDL.xml +++ b/Open-ILS/examples/fm_IDL.xml @@ -2755,7 +2755,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - + @@ -2765,6 +2765,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + + + + + diff --git a/Open-ILS/src/eg2/src/app/staff/cat/authority/browse.service.ts b/Open-ILS/src/eg2/src/app/staff/cat/authority/browse.service.ts index 83701c1a25..848fb51dc0 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/authority/browse.service.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/authority/browse.service.ts @@ -68,7 +68,7 @@ export class BrowseService { return { authority: authMeta.authority, - link_count: authMeta.linked_bibs.length, + link_count: authMeta.linked_bib_count, heading: authMeta.heading, thesaurus: authMeta.thesaurus, thesaurus_code: authMeta.thesaurus_code, diff --git a/Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.html b/Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.html index 37bb7ecf02..c1951feda7 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.html +++ b/Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.html @@ -17,7 +17,7 @@
-
diff --git a/Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.ts b/Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.ts index 1234e76e0e..d4bd0ebcc8 100644 --- a/Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/cat/authority/manage.component.ts @@ -20,6 +20,7 @@ export class ManageAuthorityComponent implements OnInit { authId: number; authTab = 'bibs'; authMeta: any; + linkedBibIdSource: (pager: Pager, sort: any) => Promise; constructor( private router: Router, @@ -44,6 +45,19 @@ export class ManageAuthorityComponent implements OnInit { ).subscribe(meta => this.authMeta = meta); } }); + + this.linkedBibIdSource = (pager: Pager, sort: any) => { + return this.getLinkedBibIds(pager, sort); + }; + } + + getLinkedBibIds(pager: Pager, sort: any): Promise { + return this.pcrud.search('abl', + {authority: this.authId}, + {limit: pager.limit, offset: pager.offset}, + {atomic: true} + ).pipe(map(links => links.map(l => l.bib())) + ).toPromise(); } // Changing a tab in the UI means changing the route. diff --git a/Open-ILS/src/eg2/src/app/staff/share/bib-list/bib-list.component.ts b/Open-ILS/src/eg2/src/app/staff/share/bib-list/bib-list.component.ts index 19faff39b1..5cacc8e4ff 100644 --- a/Open-ILS/src/eg2/src/app/staff/share/bib-list/bib-list.component.ts +++ b/Open-ILS/src/eg2/src/app/staff/share/bib-list/bib-list.component.ts @@ -1,6 +1,6 @@ import {Component, Input, OnInit, ViewChild} from '@angular/core'; -import {Observable, empty} from 'rxjs'; -import {map, switchMap} from 'rxjs/operators'; +import {Observable, empty, from} from 'rxjs'; +import {map, tap, switchMap} from 'rxjs/operators'; import {IdlObject} from '@eg/core/idl.service'; import {Pager} from '@eg/share/util/pager'; import {NetService} from '@eg/core/net.service'; @@ -19,8 +19,10 @@ import {ComboboxEntry} from '@eg/share/combobox/combobox.component'; }) export class BibListComponent implements OnInit { - // Display bibs linked to this authority record. + // Static source of bib record IDs @Input() bibIds: number[]; + // Dynamic source of bib record IDs + @Input() bibIdSource: (pager: Pager, sort: any) => Promise; @Input() gridPersistKey: string; dataSource: GridDataSource; @@ -40,7 +42,7 @@ export class BibListComponent implements OnInit { this.dataSource.getRows = (pager: Pager, sort: any): Observable => { - if (this.bibIds) { + if (this.bibIds || this.bibIdSource) { return this.loadIds(pager, sort); } @@ -53,25 +55,33 @@ export class BibListComponent implements OnInit { } loadIds(pager: Pager, sort: any): Observable { - if (this.bibIds.length === 0) { + + let promise: Promise; + + if (this.bibIdSource) { + promise = this.bibIdSource(pager, sort); + + } else if (this.bibIds && this.bibIds.length > 0) { + promise = Promise.resolve( + this.bibIds.slice(pager.offset, pager.offset + pager.limit)); + + } else { return empty(); } - const orderBy: any = {rmsr: 'title'}; - if (sort.length) { - orderBy.rmsr = sort[0].name + ' ' + sort[0].dir; - } + return from(promise).pipe(switchMap(bibIds => { - return this.pcrud.search('rmsr', {id: this.bibIds}, { - order_by: orderBy, - limit: pager.limit, - offset: pager.offset, - flesh: 2, - flesh_fields: { - rmsr: ['biblio_record'], - bre: ['creator', 'editor'] - } - }); + if (bibIds.length === 0) { return empty(); } + + return this.pcrud.search('rmsr', {id: bibIds}, { + order_by: {rmsr: 'id'}, + flesh: 2, + flesh_fields: { + rmsr: ['biblio_record'], + bre: ['creator', 'editor'] + } + }); + })); } } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm index 57ec61dcb6..47c52b4257 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Authority.pm @@ -361,7 +361,7 @@ __PACKAGE__->register_method( thesaurus: short_code, thesaurus_code: code, control_set: control_set_object, - linked_bibs: [id1, id2, ...] + linked_bib_count: number } /, type => 'object' @@ -381,16 +381,23 @@ sub authority_main_entry { my $rec = $e->retrieve_authority_record_entry([ $auth_id, { flesh => 1, - flesh_fields => {are => [qw/control_set bib_links creator/]} + flesh_fields => {are => [qw/control_set creator/]} } ]) or return $e->event; my $response = { authority => $rec, - control_set => $rec->control_set, - linked_bibs => [ map {$_->bib} @{$rec->bib_links} ] + control_set => $rec->control_set }; + $response->{linked_bib_count} = $e->json_query({ + select => {abl => [ + {column => 'bib', transform => 'count', aggregate => 1} + ]}, + from => 'abl', + where => {authority => $auth_id} + })->[0]->{bib}; + # Extract the heading and thesaurus. # In theory this data has already been extracted in the DB, but # using authority.simple_heading results in data that varies -- 2.43.2