<eg-staff-banner bannerText="Manage Authority Records" i18n-bannerText>
</eg-staff-banner>
-<eg-grid #grid [dataSource]="dataSource">
- <eg-grid-column name="id" label="ID" i18n-label [index]="true"></eg-grid-column>
- <eg-grid-column name="link_count" label="Linked Bibs" i18n-label></eg-grid-column>
- <eg-grid-column name="heading" label="Heading" i18n-label></eg-grid-column>
- <eg-grid-column name="control_set" label="Control Set" i18n-label></eg-grid-column>
- <eg-grid-column name="thesaurus" label="Thesaurus" i18n-label></eg-grid-column>
+<div class="row form-inline mb-3">
+ <div class="col-lg-3">
+ <div class="input-group">
+ <div class="input-group-prepend">
+ <span class="input-group-text" id="search-term" i18n>Search Term</span>
+ </div>
+ <input type="text" class="form-control" placeholder="Search Term"
+ i18n-placeholder aria-describedby="search-term"
+ (keyup.enter)="search()" [(ngModel)]="searchTerm">
+ </div>
+ </div>
+ <div class="col-lg-5">
+ <div class="input-group">
+ <div class="input-group-prepend">
+ <span class="input-group-text" id="auth-axis" i18n>Authority Type</span>
+ </div>
+ <eg-combobox #axisCbox [(ngModel)]="authorityAxis"
+ [entries]="authorityAxes" (onChange)="search()">
+ </eg-combobox>
+ <button class="btn btn-outline-dark ml-2" (click)="search()" i18n>Submit</button>
+ </div>
+ </div>
+ <div class="col-lg-4 d-flex">
+ <div class="flex-1"></div><!-- push right -->
+ <div class="form-inline">
+ <button class="btn btn-outline-dark ml-2" (click)="search(-1)" i18n>Previous</button>
+ <label for='offset-input' class="form-control ml-2" i18n>Page</label>
+ <input class="form-control" type="number"
+ [(ngModel)]="searchOffset" id="offset-input" (change)="search()"/>
+ <button class="btn btn-outline-dark ml-2" (click)="search(1)" i18n>Next</button>
+ </div>
+ </div>
+</div>
+
+<eg-grid #grid [dataSource]="dataSource" [disablePaging]="true">
+ <eg-grid-column name="id" label="ID" path="authority.id" i18n-label
+ [index]="true" flex="1"></eg-grid-column>
+ <eg-grid-column name="link_count" label="Linked Bibs"
+ i18n-label flex="1"></eg-grid-column>
+ <eg-grid-column name="heading" label="Heading" i18n-label flex="3"></eg-grid-column>
+ <eg-grid-column name="control_set" path="authority.control_set.name"
+ label="Control Set" i18n-label flex="1"></eg-grid-column>
+ <eg-grid-column name="thesaurus" label="Thesaurus" i18n-label flex="1"></eg-grid-column>
+ <eg-grid-column name="thesaurus_code" label="Thesaurus Code"
+ i18n-label flex="1"></eg-grid-column>
+ <eg-grid-column name="creator" label="Creator" i18n-label
+ path="authority.creator.usrname" flex="1"></eg-grid-column>
+ <eg-grid-column name="create_date" label="Create Date" i18n-label
+ path="authority.create_date" flex="1" datatype="timestamp"></eg-grid-column>
+ <eg-grid-column name="edit_date" label="Edit Date" i18n-label
+ path="authority.edit_date" flex="1" datatype="timestamp"></eg-grid-column>
+ <eg-grid-column name="source" label="Source" i18n-label
+ path="authority.source" flex="1"></eg-grid-column>
+ <eg-grid-column name="owner" label="Owner" i18n-label
+ path="authority.owner" flex="1"></eg-grid-column>
+
+
</eg-grid>
+
import {Component, OnInit, ViewChild} from '@angular/core';
-import {Observable} from 'rxjs';
+import {Observable, empty} from 'rxjs';
import {map, 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';
import {PcrudService} from '@eg/core/pcrud.service';
+import {OrgService} from '@eg/core/org.service';
+import {GridComponent} from '@eg/share/grid/grid.component';
import {GridContext, GridDataSource} from '@eg/share/grid/grid';
import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
/* Find, merge, and edit authority records */
@Component({
- templateUrl: 'manage.component.html'
+ templateUrl: 'manage.component.html',
+ styles: [`#offset-input { width: 4em; }`]
})
export class ManageAuthorityComponent implements OnInit {
- authorityAxis: string;
+ // Grid paging is disabled in this UI to support browsing in
+ // both directions. Define our own paging trackers.
+ pageSize = 15;
+ searchOffset = 0;
+
+ searchTerm: string;
+ authorityAxis: ComboboxEntry;
authorityAxes: ComboboxEntry[];
dataSource: GridDataSource;
+ @ViewChild('grid', {static: false}) grid: GridComponent;
+
constructor(
private net: NetService,
+ private org: OrgService,
private pcrud: PcrudService
) {
}
ngOnInit() {
- // TODO fetch axes
+ this.pcrud.retrieveAll('aba', {}, {atomic: true})
+ .subscribe(axes => {
+ this.authorityAxes = axes
+ .map(axis => ({id: axis.code(), label: axis.name()}))
+ .sort((a1, a2) => a1.label < a2.label ? -1 : 1);
+ });
this.dataSource = new GridDataSource();
this.dataSource.getRows = (pager: Pager, sort: any): Observable<any> => {
- return this.loadAuthorities(pager, sort);
+ return this.loadAuthorities();
}
}
- loadAuthorities(pager: Pager, sort: any): Observable<any> {
+ loadAuthorities(): Observable<any> {
+
+ if (!this.searchTerm || !this.authorityAxis.id) {
+ return empty();
+ }
return this.net.request(
'open-ils.supercat',
'open-ils.supercat.authority.browse.by_axis',
- 'subject', 'g', pager.limit, pager.offset
+ this.authorityAxis.id, this.searchTerm,
+ this.pageSize, this.searchOffset
).pipe(switchMap(authIds => {
+
return this.net.request(
'open-ils.search',
'open-ils.search.authority.main_entry', authIds
);
})).pipe(map(authMeta => {
+
+ const oOrg = this.org.get(authMeta.authority.owner());
+
return {
- id: authMeta.authority_id,
+ authority: authMeta.authority,
link_count: authMeta.linked_bibs.length,
- heading: authMeta.heading.value(),
- control_set: authMeta.control_set.name(),
- thesaurus: authMeta.heading.thesaurus()
+ heading: authMeta.heading,
+ thesaurus: authMeta.thesaurus,
+ thesaurus_code: authMeta.thesaurus_code,
+ owner: oOrg ? oOrg.shortname() : ''
};
}));
}
+
+ search(offset?: number) {
+ if (offset) { this.searchOffset += offset; }
+
+ this.grid.reload();
+ }
}
use OpenILS::Utils::Fieldmapper;
use OpenILS::Application::AppUtils;
+use MARC::Record;
+use MARC::File::XML (BinaryEncoding => 'UTF-8');
+use MARC::Charset;
use XML::LibXML;
use XML::LibXSLT;
use OpenILS::Utils::CStoreEditor q/:funcs/;
return => {
desc => q/
Stream of authority metadata objects.
- { authority_id: $id,
- heading: $main_entry_heading, # fleshed atag
- control_set: $control_set,
- linked_bibs: [$id1, $id2, ...]
+ { authority: are_object,
+ heading: heading_text,
+ thesaurus: short_code,
+ thesaurus_code: code,
+ control_set: control_set_object,
+ linked_bibs: [id1, id2, ...]
}
/,
type => 'object'
my $rec = $e->retrieve_authority_record_entry([
$auth_id, {
flesh => 1,
- flesh_fields => {are => [qw/control_set bib_links/]}
+ flesh_fields => {are => [qw/control_set bib_links creator/]}
}
]) or return $e->event;
- my $main_entry = $e->json_query({
- select => {ash => [qw/id/]},
- from => {ash => 'acsaf'},
- where => {
- '+ash' => {record => $auth_id},
- '+acsaf' => {main_entry => undef}
- },
- limit => 1
- })->[0];
-
my $response = {
- authority_id => $auth_id,
+ authority => $rec,
control_set => $rec->control_set,
linked_bibs => [ map {$_->bib} @{$rec->bib_links} ]
};
- if ($main_entry) {
- $response->{heading} =
- $e->search_authority_simple_heading([
- {id => $main_entry->{id}},
- {flesh => 1, flesh_fields => {ash => [qw/atag/]}}
- ])->[0];
+ # Extract the heading and thesaurus.
+ # In theory this data has already been extracted in the DB,
+ # but my results vary quite a bit from the previous authority
+ # manage interface. I took the MARC parsing approach because
+ # it matches the logic (and results) of the previous UI.
+
+ my $marc = MARC::Record->new_from_xml($rec->marc);
+ my $heading_field = $marc->field('1..');
+ $response->{heading} = $heading_field->as_string if $heading_field;
+
+ my $field_008 = $marc->field('008');
+ if ($field_008) {
+ my $thes = substr($field_008->data, 11, 1);
+
+ if (defined $thes) {
+ $response->{thesaurus} = $thes;
+
+ if ($thes ne 'z') { # 'z' ('Other') maps to many entries
+ my $thesaurus =
+ $e->search_authority_thesaurus({short_code => $thes})->[0];
+
+ $response->{thesaurus_code} = $thesaurus->code if $thesaurus;
+ }
+ }
}
+ $rec->clear_marc;
$client->respond($response);
}