Skip to content

Commit

Permalink
request: allow cancellation when item is at desk
Browse files Browse the repository at this point in the history
* Updates 'cancel request' permissions to allow the cancellation of an
item 'at desk'.
* Adds a method to update the item detailed view after a cancel request.
* Adds a flash message to inform the user about the item status.
* Moves 'cancel' and 'update' logic from the item-transaction component (list item) to
the item-transactions (list) component for a better understanding and to clean the code.
* Closes rero/rero-ils#1293.

Co-Authored-by: Alicia Zangger <alicia.zangger@rero.ch>
  • Loading branch information
Alicia Zangger committed Nov 4, 2020
1 parent 8ffbf9a commit b606cac
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,8 @@ <h3 translate>Issue data</h3>
</section>

<!-- TRANSACTIONS -->
<admin-item-transactions [item]="record"></admin-item-transactions>
<admin-item-transactions
[item]="record"
(cancelRequestEvent)="updateItemStatus()"
></admin-item-transactions>
</ng-container>
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ export class ItemDetailViewComponent implements DetailRecord, OnInit, OnDestroy
* @param _recordService - RecordService
*/
constructor(
private _recordService: RecordService,
private _recordService: RecordService
) {}

ngOnInit() {
this._recordObs = this.record$.subscribe( record => {
this._recordObs = this.record$.subscribe(record => {
this.record = record;
this._recordService.getRecord('locations', record.metadata.location.pid, 1).subscribe(data => this.location = data);
});
Expand All @@ -67,4 +67,14 @@ export class ItemDetailViewComponent implements DetailRecord, OnInit, OnDestroy
isPublicNote(note: ItemNote): boolean {
return Item.PUBLIC_NOTE_TYPES.includes(note.type);
}

/**
* Update item status
*/
updateItemStatus() {
this._recordService.getRecord('items', this.record.metadata.pid).subscribe((item: any) => {
this.record.metadata.status = item.metadata.status;
this.record.metadata.available = item.metadata.available;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
</button>
<ul id="dropdown-animated" *dropdownMenu class="dropdown-menu" role="menu" aria-labelledby="dropdown-animated">
<li role="menuitem" *ngFor="let pickup of pickupLocations; let i = index">
<a class="dropdown-item" (click)="updateRequest(pickup.value)">{{ pickup.label }}</a>
<a class="dropdown-item" (click)="emitUpdatePickupLocation(pickup.value)">{{ pickup.label }}</a>
</li>
</ul>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@
*/
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { DialogService, RecordService } from '@rero/ng-core';
import { ToastrService } from 'ngx-toastr';
import { DialogService } from '@rero/ng-core';
import { LoanState } from 'projects/admin/src/app/class/items';
import { LoanService } from 'projects/admin/src/app/service/loan.service';
import { UserService } from 'projects/admin/src/app/service/user.service';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { ItemsService } from 'projects/admin/src/app/service/items.service';

Expand Down Expand Up @@ -80,7 +77,12 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {
/**
* Informs parent component to remove request when it is cancelled
*/
@Output() removeRequest = new EventEmitter<boolean>();
@Output() cancelRequestEvent = new EventEmitter<any>();

/**
* Informs parent component to update pickup location
*/
@Output() updatePickupLocationEvent = new EventEmitter<any>();

/**
* On init hook
Expand All @@ -105,17 +107,13 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {

/**
* constructor
* @param _loanService - LoanService
* @param _userService - User service
* @param _toastrService - ToastrService
* @param _translateService - TranslateService
* @param _dialogService: DialogService
* @param _itemService: ItemsService
*/
constructor(
private _loanService: LoanService,
private _userService: UserService,
private _toastrService: ToastrService,
private _translateService: TranslateService,
private _dialogService: DialogService,
private _itemService: ItemsService
Expand All @@ -140,8 +138,9 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {
canCancelRequest(): boolean {
// No permission API in backend
// Allowed when loan state is PENDING or ITEM_IN_TRANSIT_FOR_PICKUP according to actions.md
return this.transaction.metadata.state === LoanState.PENDING
|| this.transaction.metadata.state === LoanState.ITEM_IN_TRANSIT_FOR_PICKUP;
const itemStatus = [LoanState.PENDING, LoanState.ITEM_IN_TRANSIT_FOR_PICKUP, LoanState.ITEM_AT_DESK];
return itemStatus.some((element) => element === this.transaction.metadata.state);

}

/**
Expand All @@ -151,8 +150,8 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {
canUpdateRequestPickupLocation(): boolean {
// No permission API in backend
// Allowed when loan state is PENDING or ITEM_IN_TRANSIT_FOR_PICKUP according to actions.md
return this.transaction.metadata.state === LoanState.PENDING
|| this.transaction.metadata.state === LoanState.ITEM_IN_TRANSIT_FOR_PICKUP;
const itemStatus = [LoanState.PENDING, LoanState.ITEM_IN_TRANSIT_FOR_PICKUP];
return itemStatus.some((element) => element === this.transaction.metadata.state);
}

/**
Expand All @@ -172,43 +171,27 @@ export class ItemTransactionComponent implements OnInit, OnDestroy {

this._dialogService.show(config).subscribe((confirm: boolean) => {
if (confirm) {
this.cancelRequest();
this.emitCancelRequest();
}
});
}

/**
* Cancel request
* Inform parent to cancel the request
*/
cancelRequest() {
this._loanService
.cancelLoan(
this.itemPid,
this.transaction.metadata.pid,
this._currentUser.currentLibrary
)
.subscribe((itemData: any) => {
this.removeRequest.emit(true);
});
emitCancelRequest() {
this.cancelRequestEvent.emit(this.transaction);
}

/**
* Update pickup location
* @param pickupLocationPid - pickup location pid to change
*/
updateRequest(pickupLocationPid: string) {
this._loanService
.updateLoanPickupLocation(
this.transaction.metadata.pid,
pickupLocationPid
)
.subscribe((data: any) => {
this._toastrService.success(
this._translateService.instant('The pickup location has been changed.'),
this._translateService.instant('Request')
);
this.transaction.metadata = data;
});
* Inform parent to cancel the request
*/
emitUpdatePickupLocation(pickupLocationPid: string) {
const data = {
pickupLocationPid,
transaction: this.transaction
};
this.updatePickupLocationEvent.emit(data);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
type="loan_request"
[transaction]="request"
[itemPid]="item.metadata.pid"
(removeRequest)="deleteRequest(request)"
(cancelRequestEvent)="cancelRequest($event)"
(updatePickupLocationEvent)="updateRequestPickupLocation($event)"
></admin-item-transaction>
</div>
</ng-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, Input, OnInit } from '@angular/core';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { BsModalService } from 'ngx-bootstrap/modal';
import { ToastrService } from 'ngx-toastr';
import { LoanService } from 'projects/admin/src/app/service/loan.service';
import { forkJoin } from 'rxjs';
import { UserService } from 'projects/admin/src/app/service/user.service';
import { Observable } from 'rxjs';
import { first } from 'rxjs/operators';
import { ItemRequestComponent } from '../../document-detail-view/item-request/item-request.component';

Expand All @@ -31,26 +35,43 @@ export class ItemTransactionsComponent implements OnInit {
/** Item record */
@Input() item: any;

/**
* Informs parent component that a request has been cancelled
*/
@Output() cancelRequestEvent = new EventEmitter<any>();

/** Borrowed loan */
borrowedBy: Array<any> = [];

/** Requested loan(s) */
requestedBy: Array<any> = [];

/**
* Current user
*/
private _currentUser: any;

/**
* Constructor
* @param _loanService - LoanService
* @param _modalService - BsModalService
* @param _toastrService - ToastrService
* @param _translateService - TranslateService
* @param _userService - UserService
*/
constructor(
private _loanService: LoanService,
private _modalService: BsModalService
private _modalService: BsModalService,
private _toastrService: ToastrService,
private _translateService: TranslateService,
private _userService: UserService
) { }

/**
* On init hook
*/
ngOnInit() {
this._currentUser = this._userService.getCurrentUser();
const borrowedBy$ = this._loanService.borrowedBy$(this.item.metadata.pid);
const requestedBy$ = this._loanService.requestedBy$(this.item.metadata.pid);
forkJoin([borrowedBy$, requestedBy$]).subscribe(
Expand Down Expand Up @@ -80,4 +101,55 @@ export class ItemTransactionsComponent implements OnInit {
this._loanService.requestedBy$(this.item.metadata.pid).subscribe(data => this.requestedBy = data);
});
}

/**
* Cancel request
* @param transaction - request to cancel
*/
cancelRequest(transaction: any) {
this._loanService
.cancelLoan(
this.item.pid,
transaction.metadata.pid,
this._currentUser.currentLibrary
)
.subscribe((itemData: any) => {
const status = itemData.status;
this._toastrService.warning(
this._translateService.instant('The item is ' + status),
// this._translateService.instant('The item is {{ status }}', { status }),
this._translateService.instant('Request')
);
this.cancelRequestEvent.emit();
this.updateRequestList();
});
}

/**
* Update request pickup location
* @param pickupLocationPid - pickup location pid to change
*/
updateRequestPickupLocation(data: any) {
this._loanService
.updateLoanPickupLocation(
data.transaction.metadata.pid,
data.pickupLocationPid
)
.subscribe((response: any) => {
this._toastrService.success(
this._translateService.instant('The pickup location has been changed.'),
this._translateService.instant('Request')
);
this.updateRequestList();
});
}

/**
* Update request list
*/
updateRequestList() {
this._loanService.requestedBy$(this.item.metadata.pid).subscribe(requestedLoans =>
this.requestedBy = requestedLoans
);
}
}

0 comments on commit b606cac

Please sign in to comment.