<button class="dropdown-item"
(click)="applyAction('email')" i18n>Email Title Details</button>
<button class="dropdown-item"
- (click)="applyAction('bucket')" i18n>Add Basket to Bucket</button>
+ (click)="applyAction('bucket')" i18n>Add to Bucket</button>
<button class="dropdown-item"
- (click)="applyAction('export_marc')" i18n>Export Records</button>
+ (click)="applyAction('export_marc')" i18n>Export All Basket Records</button>
<button class="dropdown-item"
(click)="applyAction('clear')" i18n>Clear Basket</button>
</div>
import {PrintService} from '@eg/share/print/print.service';
import {BucketDialogComponent
} from '@eg/staff/share/buckets/bucket-dialog.component';
+import {BasketSelectionService} from './basket-selection.service';
@Component({
selector: 'eg-catalog-basket-actions',
private net: NetService,
private auth: AuthService,
private printer: PrintService,
- private basket: BasketService
+ private basket: BasketService,
+ private basketSelect: BasketSelectionService
) {
this.basketAction = '';
}
break;
case 'hold':
- this.basket.getRecordIds().then(ids => {
+ this.basketSelect.getRecordIds().then(ids => {
this.router.navigate(['/staff/catalog/hold/T'],
{queryParams: {target: ids}});
});
break;
case 'print':
- this.basket.getRecordIds().then(ids => {
+ this.basketSelect.getRecordIds().then(ids => {
this.net.request(
'open-ils.search',
'open-ils.search.biblio.record.print', ids
break;
case 'email':
- this.basket.getRecordIds().then(ids => {
+ this.basketSelect.getRecordIds().then(ids => {
this.net.request(
'open-ils.search',
'open-ils.search.biblio.record.email',
break;
case 'bucket':
- this.basket.getRecordIds().then(ids => {
+ this.basketSelect.getRecordIds().then(ids => {
this.addToBucketDialog.bucketClass = 'biblio';
this.addToBucketDialog.itemIds = ids;
this.addToBucketDialog.open({size: 'lg'});
--- /dev/null
+import {Injectable, EventEmitter} from '@angular/core';
+import {BasketService} from '@eg/share/catalog/basket.service';
+import {Observable} from 'rxjs';
+
+/*
+ * Provides a way to select / deselect items in the basket view,
+ * with the same API as the basket service, without affecting the
+ * contents of the basket.
+ */
+
+@Injectable()
+export class BasketSelectionService {
+
+ idList: number[];
+
+ constructor(private basket: BasketService) {
+ this.idList = [];
+ }
+
+ init(): Promise<any> {
+ return this.basket.getRecordIds().then(ids => this.setRecordIds(ids));
+ }
+
+ hasRecordId(id: number): boolean {
+ return this.idList.indexOf(Number(id)) > -1;
+ }
+
+ recordCount(): number {
+ return this.idList.length;
+ }
+
+ getRecordIds(): Promise<number[]> {
+ return Promise.resolve(this.idList);
+ }
+
+ setRecordIds(ids: number[]): Promise<number[]> {
+ this.idList = ids;
+ return Promise.resolve(this.idList);
+ }
+
+ addRecordIds(ids: number[]): Promise<number[]> {
+ ids = ids.filter(id => !this.hasRecordId(id)); // avoid dupes
+
+ if (ids.length === 0) {
+ return Promise.resolve(this.idList);
+ }
+ return this.setRecordIds(
+ this.idList.concat(ids.map(id => Number(id))));
+ }
+
+ removeRecordIds(ids: number[]): Promise<number[]> {
+
+ if (this.idList.length === 0) {
+ return Promise.resolve(this.idList);
+ }
+
+ const wantedIds = this.idList.filter(
+ id => ids.indexOf(Number(id)) < 0);
+
+ return this.setRecordIds(wantedIds); // OK if empty
+ }
+
+ removeAllRecordIds(): Promise<number[]> {
+ return this.setRecordIds([]);
+ }
+}
+
+
import {SearchTemplatesComponent} from './search-templates.component';
import {MarcEditModule} from '@eg/staff/share/marc-edit/marc-edit.module';
import {PreferencesComponent} from './prefs.component';
+import {BasketSelectionService} from './basket-selection.service';
@NgModule({
declarations: [
MarcEditModule
],
providers: [
- StaffCatalogService
+ StaffCatalogService,
+ BasketSelectionService
]
})
import {StaffCatalogService} from '../catalog.service';
import {BasketService} from '@eg/share/catalog/basket.service';
import {CourseService} from '@eg/staff/share/course.service';
+import {BasketSelectionService} from '../basket-selection.service';
@Component({
selector: 'eg-catalog-result-record',
hasCourse = false;
courses: any[] = [];
+ recordSelector: BasketService | BasketSelectionService;
+
constructor(
private router: Router,
private org: OrgService,
private catUrl: CatalogUrlService,
private staffCat: StaffCatalogService,
private basket: BasketService,
- private course: CourseService
+ private course: CourseService,
+ private basketSelect: BasketSelectionService
) {}
ngOnInit() {
this.basketSub = this.basket.onChange.subscribe(() => {
this.isRecordSelected = this.basket.hasRecordId(this.summary.id);
});
+
+ if (this.searchContext.showBasket) {
+ this.recordSelector = this.basketSelect;
+ } else {
+ this.recordSelector = this.basket;
+ }
}
ngOnDestroy() {
toggleBasketEntry() {
if (this.isRecordSelected) {
- return this.basket.addRecordIds([this.summary.id]);
+ return this.recordSelector.addRecordIds([this.summary.id]);
} else {
- return this.basket.removeRecordIds([this.summary.id]);
+ return this.recordSelector.removeRecordIds([this.summary.id]);
}
}
}
<!-- header, pager, and list of records -->
<div id="staff-catalog-results-container" *ngIf="searchHasResults()">
<div class="row">
- <div class="col-lg-2" *ngIf="!searchContext.basket">
+ <div class="col-lg-2" *ngIf="!searchContext.showBasket">
<ng-container *ngIf="searchContext.termSearch.browseEntry">
<h3 i18n>Results for browse "{{searchContext.termSearch.browseEntry.value()}}"</h3>
</ng-container>
<h3 i18n>Search Results ({{searchContext.result.count}})</h3>
</ng-container>
</div>
- <div class="col-lg-2" *ngIf="searchContext.basket">
+ <div class="col-lg-2" *ngIf="searchContext.showBasket">
<h3 i18n>Basket View</h3>
</div>
<div class="col-lg-2">
- <label class="checkbox" *ngIf="!searchContext.basket">
+ <label class="checkbox" *ngIf="!searchContext.showBasket">
<input type='checkbox' [(ngModel)]="allRecsSelected"
(change)="toggleAllRecsSelected()"/>
<span class="pl-1" i18n>Select {{searchContext.pager.rowNumber(0)}} -
</div>
<div>
<div class="row mt-2">
- <div class="col-lg-2" *ngIf="!searchContext.basket">
+ <div class="col-lg-2" *ngIf="!searchContext.showBasket">
<eg-catalog-result-facets></eg-catalog-result-facets>
</div>
<div
- [ngClass]="{'col-lg-10': !searchContext.basket, 'col-lg-12': searchContext.basket}">
+ [ngClass]="{'col-lg-10': !searchContext.showBasket, 'col-lg-12': searchContext.showBasket}">
<div *ngFor="let summary of searchContext.result.records; let idx = index">
<div *ngIf="summary">
<eg-catalog-result-record [summary]="summary" [index]="idx">
import {StaffCatalogService} from '../catalog.service';
import {IdlObject} from '@eg/core/idl.service';
import {BasketService} from '@eg/share/catalog/basket.service';
+import {BasketSelectionService} from '../basket-selection.service';
@Component({
selector: 'eg-catalog-results',
routeSub: Subscription;
basketSub: Subscription;
+ recordSelector: BasketService | BasketSelectionService;
+
constructor(
private route: ActivatedRoute,
private pcrud: PcrudService,
private bib: BibRecordService,
private catUrl: CatalogUrlService,
private staffCat: StaffCatalogService,
- private basket: BasketService
+ private basket: BasketService,
+ private basketSelect: BasketSelectionService
) {}
ngOnInit() {
// Watch for basket changes applied by other components.
this.basketSub = this.basket.onChange.subscribe(
() => this.applyRecordSelection());
+
+ if (this.searchContext.showBasket) {
+ this.recordSelector = this.basketSelect;
+ this.basketSelect.init();
+ } else {
+ this.recordSelector = this.basket;
+ }
}
ngOnDestroy() {
const ids = this.searchContext.currentResultIds();
let allChecked = true;
ids.forEach(id => {
- if (!this.basket.hasRecordId(id)) {
+ if (!this.recordSelector.hasRecordId(id)) {
allChecked = false;
}
});
const ids = this.searchContext.currentResultIds();
if (this.allRecsSelected) {
- this.basket.addRecordIds(ids);
+ this.recordSelector.addRecordIds(ids);
} else {
- this.basket.removeRecordIds(ids);
+ this.recordSelector.removeRecordIds(ids);
}
}
}