// Allow the selected entry ID to be passed via the template
// This does NOT not emit onChange events.
@Input() set selectedId(id: any) {
- if (id) {
- if (this.entrylist.length) {
- this.selected = this.entrylist.filter(e => e.id === id)[0];
- }
+ if (id === undefined) { return; }
- if (!this.selected) {
- // It's possible the selected ID lives in a set of entries
- // that are yet to be provided.
- this.startId = id;
- }
+ // clear on explicit null
+ if (id === null) { this.selected = null; }
+
+ if (this.entrylist.length) {
+ this.selected = this.entrylist.filter(e => e.id === id)[0];
+ }
+
+ if (!this.selected) {
+ // It's possible the selected ID lives in a set of entries
+ // that are yet to be provided.
+ this.startId = id;
}
}
if (idlInfo) {
col.idlFieldDef = idlInfo.idlField;
col.idlClass = idlInfo.idlClass.name;
+ if (!col.datatype) {
+ col.datatype = col.idlFieldDef.datatype;
+ }
if (!col.label) {
col.label = col.idlFieldDef.label || col.idlFieldDef.name;
- col.datatype = col.idlFieldDef.datatype;
}
}
}
import {HoldsModule} from '@eg/staff/share/holds/holds.module';
import {HoldingsModule} from '@eg/staff/share/holdings/holdings.module';
import {BookingModule} from '@eg/staff/share/booking/booking.module';
+import {PatronModule} from '@eg/staff/share/patron/patron.module';
import {CatalogComponent} from './catalog.component';
import {SearchFormComponent} from './search-form.component';
import {ResultsComponent} from './result/results.component';
HoldsModule,
HoldingsModule,
BookingModule,
+ PatronModule,
MarcEditModule
],
providers: [
+
+<eg-patron-search-dialog #patronSearch>
+</eg-patron-search-dialog>
+
<div class="row">
<div class="col-lg-4">
<h3 i18n>Place Hold
</h3>
</div>
<div class="col-lg-2 text-right">
- <button class="btn btn-outline-dark btn-sm" [disabled]="true">
+ <button class="btn btn-outline-dark btn-sm" (click)="searchPatrons()">
<span class="material-icons mat-icon-in-button align-middle"
i18n-title title="Search for Patron">search</span>
<span class="align-middle" i18n>Search for Patron</span>
import {HoldsService, HoldRequest,
HoldRequestTarget} from '@eg/staff/share/holds/holds.service';
import {ComboboxEntry} from '@eg/share/combobox/combobox.component';
+import {PatronSearchDialogComponent
+ } from '@eg/staff/share/patron/search-dialog.component';
class HoldContext {
holdMeta: HoldRequestTarget;
smsEnabled: boolean;
placeHoldsClicked: boolean;
+ @ViewChild('patronSearch', {static: false})
+ patronSearch: PatronSearchDialogComponent;
+
constructor(
private router: Router,
private route: ActivatedRoute,
)
);
}
+
+ searchPatrons() {
+ this.patronSearch.open({size: 'xl'}).toPromise().then(
+ patrons => {
+ if (!patrons || patrons.length === 0) { return; }
+
+ const user = patrons[0];
+
+ this.user = user;
+ this.userBarcode =
+ this.currentUserBarcode = user.card().barcode();
+ user.home_ou(this.org.get(user.home_ou()).id()); // de-flesh
+ this.applyUserSettings();
+ }
+ );
+ }
}
}
ngOnDestroy() {
- this.routeSub.unsubscribe();
- this.searchSub.unsubscribe();
- this.basketSub.unsubscribe();
+ if (this.routeSub) {
+ this.routeSub.unsubscribe();
+ this.searchSub.unsubscribe();
+ this.basketSub.unsubscribe();
+ }
}
// Apply the select-all checkbox when all visible records
import {GridModule} from '@eg/share/grid/grid.module';
import {PatronService} from './patron.service';
import {PatronSearchComponent} from './search.component';
+import {PatronSearchDialogComponent} from './search-dialog.component';
import {ProfileSelectComponent} from './profile-select.component';
@NgModule({
declarations: [
PatronSearchComponent,
+ PatronSearchDialogComponent,
ProfileSelectComponent
],
imports: [
],
exports: [
PatronSearchComponent,
+ PatronSearchDialogComponent,
ProfileSelectComponent
],
providers: [
this.cboxEntries.push(
{id: grp.id(), label: this.grpLabel(groups, grp)});
- groups.filter(g => g.parent() === grp.id())
+ groups
+ .filter(g => g.parent() === grp.id())
+ .sort((a, b) => {
+ if (a._display) {
+ return a._display.position() < b._display.position() ? -1 : 1;
+ } else {
+ return a.name() < b.name() ? -1 : 1;
+ }
+ })
.forEach(child => this.sortGroups(groups, child));
}
--- /dev/null
+<ng-template #dialogContent>
+ <div class="modal-header bg-info">
+ <h4 class="modal-title"><span i18n>Patron Search</span></h4>
+ <button type="button" class="close"
+ i18n-aria-label aria-label="Close" (click)="close()">
+ <span aria-hidden="true">×</span>
+ </button>
+ </div>
+ <div class="modal-body">
+ <eg-patron-search #searchForm (patronsSelected)="patronsSelected($event)">
+ </eg-patron-search>
+ </div>
+ <div class="modal-footer">
+ <ng-container>
+ <button type="button" class="btn btn-warning"
+ (click)="close()" i18n>Cancel</button>
+ <button type="button" class="btn btn-success"
+ [disabled]="searchForm ? searchForm.getSelected().length === 0 : true"
+ (click)="close(searchForm.getSelected())" i18n>Select</button>
+ </ng-container>
+ </div>
+</ng-template>
+
--- /dev/null
+import {Component, OnInit, Input, Output, ViewChild} from '@angular/core';
+import {IdlService, IdlObject} from '@eg/core/idl.service';
+import {NgbModal} from '@ng-bootstrap/ng-bootstrap';
+import {DialogComponent} from '@eg/share/dialog/dialog.component';
+import {PatronSearchComponent} from './search.component';
+
+/**
+ * Dialog container for patron search component
+ *
+ * <eg-patron-search-dialog (patronsSelected)="process($event)">
+ * </eg-patron-search-dialog>
+ */
+
+@Component({
+ selector: 'eg-patron-search-dialog',
+ templateUrl: 'search-dialog.component.html'
+})
+
+export class PatronSearchDialogComponent
+ extends DialogComponent implements OnInit {
+
+ @ViewChild('searchForm', {static: false})
+ searchForm: PatronSearchComponent;
+
+ constructor(private modal: NgbModal) { super(modal); }
+
+ ngOnInit() {}
+
+ // Fired when a row in the search grid is dbl-clicked / activated
+ patronsSelected(patrons: IdlObject[]) {
+ this.close(patrons);
+ }
+}
+
+
+
<eg-profile-select [useDisplayEntries]="true"
[(ngModel)]="search.profile">
</eg-profile-select>
- <!-- profile -->
</div>
<div class="col-lg-2">
+ <eg-org-select (onChange)="searchOrg = $event"
+ [applyOrgId]="searchOrg ? searchOrg.id() : null"
+ i18n-placeholder placeholder="Home Library">
+ </eg-org-select>
<!-- home org -->
</div>
<div class="col-lg-2">
export class PatronSearchComponent implements OnInit, AfterViewInit {
@ViewChild('searchGrid', {static: false}) searchGrid: GridComponent;
+
+ // Fired on dbl-click of a search result row.
@Output() patronsSelected: EventEmitter<any>;
search: any = {};
- searchOrg: number;
+ searchOrg: IdlObject;
expandForm: boolean;
dataSource: GridDataSource;
profileGroups: IdlObject[] = [];
}
ngOnInit() {
- this.searchOrg = this.org.root().id();
+ this.searchOrg = this.org.root();
this.store.getItemBatch([EXPAND_FORM, INCLUDE_INACTIVE])
.then(settings => {
this.expandForm = settings[EXPAND_FORM];
this.patronsSelected.emit([].concat(rows));
}
+ getSelected(): IdlObject[] {
+ return this.searchGrid ?
+ this.searchGrid.context.getSelectedRows() : [];
+ }
+
go() {
this.searchGrid.reload();
}
clear() {
- this.search = {};
- this.searchOrg = this.org.root().id();
- }
-
- homeOrgChange(orgId: number) {
- this.searchOrg = orgId;
+ this.search = {profile: null};
+ this.searchOrg = this.org.root();
}
getRows(pager: Pager, sort: any[]): Observable<any> {
pager.limit,
sorter,
null, // ?
- this.searchOrg,
+ this.searchOrg.id(),
DEFAULT_FLESH,
pager.offset
);