Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

general: implement new service record permission #157

Merged
merged 1 commit into from
Feb 18, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
 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/>.
-->

<ng-container *ngIf="item && permissions">
<div class="col-sm-4">
<a [routerLink]="['/records', 'items', 'detail', item.metadata.pid]">
{{ item.metadata.barcode }}
@@ -28,17 +28,17 @@
</div>
<div class="col-sm-4 text-right">
<ng-container *ngIf="isAvailableActions; else noactions">
<button *ngIf="!item.permissions.cannot_update" type="button" class="btn btn-primary btn-sm"
<button *ngIf="permissions.update.can" type="button" class="btn btn-primary btn-sm"
[routerLink]="['/records', 'items', 'edit', item.metadata.pid]">
<i class="fa fa-pencil"></i> {{ 'Edit' | translate }}
</button>

<button *ngIf="!item.permissions.cannot_delete; else notDelete" type="button" class="btn btn-primary btn-sm ml-1"
<button *ngIf="permissions.delete.can; else notDelete" type="button" class="btn btn-primary btn-sm ml-1"
(click)="delete(item.metadata.pid)">
<i class="fa fa-trash"></i> {{ 'Delete' | translate }}
</button>
<ng-template #notDelete>
<button type="button" class="btn btn-dark btn-sm ml-1" (click)="showDeleteMessage(item)">
<button type="button" class="btn btn-dark btn-sm ml-1" (click)="showDeleteMessage()">
<i class="fa fa-trash"></i> {{ 'Delete' | translate }}
</button>
</ng-template>
@@ -47,3 +47,4 @@
&nbsp;
</ng-template>
</div>
</ng-container>
Original file line number Diff line number Diff line change
@@ -15,17 +15,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Component, EventEmitter, Input, Output, OnInit } from '@angular/core';
import { RecordUiService } from '@rero/ng-core';
import { RecordPermissionMessageService } from 'projects/admin/src/app/service/record-permission-message.service';
import { UserService } from 'projects/admin/src/app/service/user.service';
import { UserService } from '../../../../service/user.service';
import { RecordPermissionService, RecordPermission } from '../../../../service/record-permission.service';

@Component({
selector: 'admin-holding-item',
templateUrl: './holding-item.component.html',
styles: []
templateUrl: './holding-item.component.html'
})
export class HoldingItemComponent {
export class HoldingItemComponent implements OnInit {

/** Holding record */
@Input() holding: any;
@@ -36,29 +35,41 @@ export class HoldingItemComponent {
/** Event for delete Item */
@Output() deleteItem = new EventEmitter();

/** Availables action */
/** Item permissions */
permissions: RecordPermission;

/** Availables actions */
get isAvailableActions() {
return this.userService.getCurrentUser().currentLibrary
return this._userService.getCurrentUser().currentLibrary
= this.holding.metadata.library.pid;
}

/**
* Constructor
* @param recordUiService - RecordUiService
* @param _recordUiService - RecordUiService
* @param _userService - UserService
* @param recordPermissionMessage - RecordPermissionMessageService
*/
constructor(
private recordUiService: RecordUiService,
private recordPermissionMessage: RecordPermissionMessageService,
private userService: UserService
private _recordUiService: RecordUiService,
private _userService: UserService,
private _recordPermissionService: RecordPermissionService
) { }

/**
* Init
*/
ngOnInit() {
this._recordPermissionService.getPermission('items', this.item.metadata.pid)
.subscribe(permissions => this.permissions = permissions);
}

/**
* Delete item
* @param itemPid - Item pid
*/
delete(itemPid: string) {
this.recordUiService.deleteRecord('items', itemPid).subscribe((success: any) => {
this._recordUiService.deleteRecord('items', itemPid).subscribe((success: any) => {
if (success) {
this.deleteItem.emit(itemPid);
}
@@ -69,8 +80,10 @@ export class HoldingItemComponent {
* Display message if the record cannot be deleted
* @param item - Item record
*/
public showDeleteMessage(item: object) {
const message = this.recordPermissionMessage.generateMessage(item);
this.recordUiService.showDeleteMessage(message);
public showDeleteMessage() {
const message = this._recordPermissionService.generateDeleteMessage(
this.permissions.delete.reasons
);
this._recordUiService.showDeleteMessage(message);
}
}
Original file line number Diff line number Diff line change
@@ -41,7 +41,10 @@ <h1>{{ record.metadata.name }}</h1>
<!-- ACTIVE BUDGET -->
<dt class="col-sm-3 offset-sm-2 offset-md-0 label-title">Active budget</dt>
<dd class="col-sm-7 col-md-8 mb-0">
<admin-budget-select [organisation]="record"></admin-budget-select>
<admin-budget-select *ngIf="isSystemLibrarian; else librarian" [organisation]="record"></admin-budget-select>
<ng-template #librarian>
{{ record.metadata.current_budget_pid | getRecord: 'budgets' : 'field' : 'name' | async }}
</ng-template>
</dd>
</dl>
</ng-container>
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@
import { Component } from '@angular/core';
import { DetailRecord } from '@rero/ng-core/lib/record/detail/view/detail-record';
import { Observable } from 'rxjs';
import { UserService } from '../../../service/user.service';

@Component({
selector: 'admin-organisation-detail-view',
@@ -33,4 +34,11 @@ export class OrganisationDetailViewComponent implements DetailRecord {
* Type
*/
type: string;

get isSystemLibrarian() {
return this._userService.hasRole('system_librarian');

}

constructor(private _userService: UserService) {}
}
Original file line number Diff line number Diff line change
@@ -29,6 +29,9 @@ export class AcquisitionOrderLinesRoute extends BaseRoute implements RouteInterf
/** Route name */
readonly name = 'acq_order_lines';

/** Record type */
readonly recordType = 'acq_order_lines';

/**
* Get Configuration
* @return Object
@@ -48,9 +51,9 @@ export class AcquisitionOrderLinesRoute extends BaseRoute implements RouteInterf
key: this.name,
label: 'Order lines',
detailComponent: AcquisitionOrderLineDetailViewComponent,
canAdd: () => this._routeToolService.canAddSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canAdd: () => this._routeToolService.canSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preCreateRecord: (data: any) => {
data.acq_order = {
$ref: this._routeToolService.apiService.getRefEndpoint(
7 changes: 5 additions & 2 deletions projects/admin/src/app/routes/acquisition-orders-route.ts
Original file line number Diff line number Diff line change
@@ -27,6 +27,9 @@ export class AcquisitionOrdersRoute extends BaseRoute implements RouteInterface
/** Route name */
readonly name = 'acq_orders';

/** Record type */
readonly recordType = 'acq_orders';

/**
* Get Configuration
* @return Object
@@ -48,8 +51,8 @@ export class AcquisitionOrdersRoute extends BaseRoute implements RouteInterface
label: 'Orders',
component: AcquisitionOrderBriefViewComponent,
detailComponent: AcquisitionOrderDetailViewComponent,
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preCreateRecord: (data: any) => {
const user = this._routeToolService.userService.getCurrentUser();
data.order_date = formatDate(
7 changes: 5 additions & 2 deletions projects/admin/src/app/routes/budgets-route.ts
Original file line number Diff line number Diff line change
@@ -24,6 +24,9 @@ export class BudgetsRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'budgets';

/** Record type */
readonly recordType = 'budgets';

/**
* Get Configuration
* @return Object
@@ -45,8 +48,8 @@ export class BudgetsRoute extends BaseRoute implements RouteInterface {
label: 'Budgets',
component: BudgetsBriefViewComponent,
detailComponent: BudgetDetailViewComponent,
canAdd: () => this._routeToolService.canAddSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canAdd: () => this._routeToolService.canSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: () => this._routeToolService.canNot(),
preCreateRecord: (data: any) => {
const user = this._routeToolService.userService.getCurrentUser();
9 changes: 6 additions & 3 deletions projects/admin/src/app/routes/circulation-policies-route.ts
Original file line number Diff line number Diff line change
@@ -25,6 +25,9 @@ export class CirculationPoliciesRoute extends BaseRoute implements RouteInterfac
/** Route name */
readonly name = 'circ_policies';

/** Record type */
readonly recordType = 'circ_policies';

/**
* Get Configuration
* @return Object
@@ -46,9 +49,9 @@ export class CirculationPoliciesRoute extends BaseRoute implements RouteInterfac
label: 'Circulation policies',
component: CircPoliciesBriefViewComponent,
detailComponent: CircPolicyDetailViewComponent,
canAdd: () => this._routeToolService.canAddSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record)
canAdd: () => this._routeToolService.canSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType)
}
]
}
7 changes: 5 additions & 2 deletions projects/admin/src/app/routes/documents-route.ts
Original file line number Diff line number Diff line change
@@ -25,6 +25,9 @@ export class DocumentsRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'documents';

/** Record type */
readonly recordType = 'documents';

/**
* Get Configuration
* @return Object
@@ -48,8 +51,8 @@ export class DocumentsRoute extends BaseRoute implements RouteInterface {
editorLongMode: true,
component: DocumentsBriefViewComponent,
detailComponent: DocumentDetailViewComponent,
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preprocessRecordEditor: (record: any) => {
return this.removeKey(record, '_text');
},
9 changes: 6 additions & 3 deletions projects/admin/src/app/routes/item-types-route.ts
Original file line number Diff line number Diff line change
@@ -24,6 +24,9 @@ export class ItemTypesRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'item_types';

/** Record type */
readonly recordType = 'item_types';

/**
* Get Configuration
* @return Object
@@ -45,9 +48,9 @@ export class ItemTypesRoute extends BaseRoute implements RouteInterface {
label: 'Item types',
component: ItemTypesBriefViewComponent,
detailComponent: ItemTypeDetailViewComponent,
canAdd: () => this._routeToolService.canAddSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canAdd: () => this._routeToolService.canSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preCreateRecord: (data: any) => {
const user = this._routeToolService.userService.getCurrentUser();
data.organisation = {
7 changes: 5 additions & 2 deletions projects/admin/src/app/routes/items-route.ts
Original file line number Diff line number Diff line change
@@ -28,6 +28,9 @@ export class ItemsRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'items';

/** Record type */
readonly recordType = 'items';

/**
* Get Configuration
* @return Object
@@ -48,8 +51,8 @@ export class ItemsRoute extends BaseRoute implements RouteInterface {
label: 'Items',
detailComponent: ItemDetailViewComponent,
canRead: (record: any) => this.canReadItem(record),
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preCreateRecord: (data: any) => {
data.document = {
$ref: this._routeToolService.apiService.getRefEndpoint(
9 changes: 6 additions & 3 deletions projects/admin/src/app/routes/libraries-route.ts
Original file line number Diff line number Diff line change
@@ -25,6 +25,9 @@ export class LibrariesRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'libraries';

/** Record type */
readonly recordType = 'libraries';

/**
* Get Configuration
* @return Object
@@ -46,9 +49,9 @@ export class LibrariesRoute extends BaseRoute implements RouteInterface {
label: 'Libraries',
component: LibrariesBriefViewComponent,
detailComponent: LibraryDetailViewComponent,
canAdd: () => this._routeToolService.canAddSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canAdd: () => this._routeToolService.canSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preCreateRecord: (data: any) => {
const user = this._routeToolService.userService.getCurrentUser();
data.organisation = {
9 changes: 6 additions & 3 deletions projects/admin/src/app/routes/locations-route.ts
Original file line number Diff line number Diff line change
@@ -23,6 +23,9 @@ export class LocationsRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'locations';

/** Record type */
readonly recordType = 'libraries';

/**
* Get Configuration
* @return Object
@@ -42,9 +45,9 @@ export class LocationsRoute extends BaseRoute implements RouteInterface {
key: this.name,
label: 'Locations',
detailComponent: LocationDetailViewComponent,
canAdd: () => this._routeToolService.canAddSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canAdd: () => this._routeToolService.canSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preCreateRecord: (record: any) => {
record.library = {
$ref: this._routeToolService.apiService.getRefEndpoint(
9 changes: 6 additions & 3 deletions projects/admin/src/app/routes/patron-types-route.ts
Original file line number Diff line number Diff line change
@@ -24,6 +24,9 @@ export class PatronTypesRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'patron_types';

/** Record type */
readonly recordType = 'patron_types';

/**
* Get Configuration
* @return Object
@@ -45,9 +48,9 @@ export class PatronTypesRoute extends BaseRoute implements RouteInterface {
label: 'Patron types',
component: PatronTypesBriefViewComponent,
detailComponent: PatronTypesDetailViewComponent,
canAdd: () => this._routeToolService.canAddSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canAdd: () => this._routeToolService.canSystemLibrarian(),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preCreateRecord: (data: any) => {
const user = this._routeToolService.userService.getCurrentUser();
data.organisation = {
7 changes: 5 additions & 2 deletions projects/admin/src/app/routes/patrons-route.ts
Original file line number Diff line number Diff line change
@@ -24,6 +24,9 @@ export class PatronsRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'patrons';

/** Record type */
readonly recordType = 'patrons';

/**
* Get Configuration
* @return Object
@@ -45,8 +48,8 @@ export class PatronsRoute extends BaseRoute implements RouteInterface {
label: 'Patrons',
component: PatronsBriefViewComponent,
detailComponent: PatronDetailViewComponent,
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
aggregationsExpand: ['roles']
}
]
2 changes: 0 additions & 2 deletions projects/admin/src/app/routes/persons-route.ts
Original file line number Diff line number Diff line change
@@ -44,8 +44,6 @@ export class PersonsRoute extends BaseRoute implements RouteInterface {
label: 'Persons',
component: PersonsBriefViewComponent,
detailComponent: PersonDetailViewComponent,
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
aggregationsExpand: ['sources']
}
]
120 changes: 85 additions & 35 deletions projects/admin/src/app/routes/route-tool.service.ts
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@ import { RecordPermissionMessageService } from '../service/record-permission-mes
import { of, Observable, Subscriber } from 'rxjs';
import { ActionStatus, ApiService, RecordService } from '@rero/ng-core';
import { UserService } from '../service/user.service';
import { RecordPermission, RecordPermissionService } from '../service/record-permission.service';


@Injectable({
@@ -71,76 +72,124 @@ export class RouteToolService {
* @param _apiService - ApiService
* @param _activatedRoute - ActivatedRoute
* @param _recordService - RecordService
* @param _recordPermissionService - RecordPermissionService
*/
constructor(
private _translateService: TranslateService,
private _recordPermissionService: RecordPermissionMessageService,
private _recordPermissionMessageService: RecordPermissionMessageService,
private _userService: UserService,
private _apiService: ApiService,
private _activatedRoute: ActivatedRoute,
private _recordService: RecordService
private _recordService: RecordService,
private _recordPermissionService: RecordPermissionService
) { }

/**
* Can not to disabled action
* Enabled action
* @param message - string
* @return Observable
*/
canNot() {
return of({ can: false, message: '' });
can(message: string = ''): Observable<ActionStatus> {
return of({ can: true, message });
}

/**
* Can Add System Librarian
* Disabled action
* @param message - string
* @return Observable
*/
canAddSystemLibrarian() {
return of({
can: this._userService.hasRole('system_librarian'),
message: ''
});
canNot(message: string = ''): Observable<ActionStatus> {
return of({ can: false, message });
}

/**
* Access only for system librarian
* @param message - string
* @return Observable
*/
canSystemLibrarian(message: string = ''): Observable<ActionStatus> {
return of(
{ can: this._userService.hasRole('system_librarian'), message }
);
}

/**
* Can Add
* @param record - Object
* @return Observable
*/
canUpdate(record: any) {
if (record.permissions && record.permissions.cannot_update) {
return of({ can: false, message: '' });
canUpdate(record: any, recordType: string): Observable<ActionStatus> {
// TODO: Refactoring after all change in resource permission
if ('documents' === recordType) {
const obs = new Observable((observer: Subscriber<any>): void => {
this._recordPermissionService
.getPermission(recordType, record.metadata.pid)
.subscribe((permission: RecordPermission) => {
observer.next({ can: permission.update.can, message: '' });
});
});

return obs;
} else {
if (record.permissions && record.permissions.cannot_update) {
return this.canNot();
}

return this.can();
}
return of({ can: true, message: '' });
}

/**
* Can Delete
* @param record - Object
* @return Observable
*/
canDelete(record: any): Observable<ActionStatus> {
const obs = new Observable((observer: Subscriber<any>): void => {
if (
record.permissions &&
record.permissions.cannot_delete &&
record.permissions.cannot_delete.permission &&
record.permissions.cannot_delete.permission === 'permission denied'
) {
observer.next({ can: false, message: '' });
} else {
observer.next({
can: !this._recordPermissionService.generateMessage(record),
message: this._recordPermissionService.generateMessage(record)
canDelete(record: any, recordType: string): Observable<ActionStatus> {
// TODO: Refactoring after all change in resource permission
if ('documents' === recordType) {
const obs = new Observable((observer: Subscriber<any>): void => {
this._recordPermissionService
.getPermission(recordType, record.metadata.pid)
.subscribe((permission: RecordPermission) => {
if (permission.delete.can) {
observer.next({ can: permission.delete.can, message: '' });
} else {
observer.next({
can: permission.delete.can,
message: this._recordPermissionService.generateDeleteMessage(
permission.delete.reasons
)
});
}
});
this.translateService.onLangChange.subscribe(() => {
});

return obs;
} else {
const obs = new Observable((observer: Subscriber<any>): void => {
if (
record.permissions &&
record.permissions.cannot_delete &&
record.permissions.cannot_delete.permission &&
record.permissions.cannot_delete.permission === 'permission denied'
) {
observer.next({ can: false, message: '' });
} else {
observer.next({
can: !this._recordPermissionService.generateMessage(record),
message: this._recordPermissionService.generateMessage(record)
can: !this._recordPermissionMessageService.generateMessage(record),
message: this._recordPermissionMessageService.generateMessage(record)
});
});
}
});
this.translateService.onLangChange.subscribe(() => {
observer.next({
can: !this._recordPermissionMessageService.generateMessage(record),
message: this._recordPermissionMessageService.generateMessage(record)
});
});
}
});

return obs;
return obs;
}
}

/**
@@ -160,6 +209,7 @@ export class RouteToolService {
/**
* Aggregation filter
* @param aggregations - Object
* @return array
*/
private aggFilter(aggregations: object) {
const aggs = {};
7 changes: 5 additions & 2 deletions projects/admin/src/app/routes/vendors-route.ts
Original file line number Diff line number Diff line change
@@ -24,6 +24,9 @@ export class VendorsRoute extends BaseRoute implements RouteInterface {
/** Route name */
readonly name = 'vendors';

/** Record type */
readonly recordType = 'persons';

/**
* Get Configuration
* @return Object
@@ -45,8 +48,8 @@ export class VendorsRoute extends BaseRoute implements RouteInterface {
label: 'Vendors',
component: VendorBriefViewComponent,
detailComponent: VendorDetailViewComponent,
canUpdate: (record: any) => this._routeToolService.canUpdate(record),
canDelete: (record: any) => this._routeToolService.canDelete(record),
canUpdate: (record: any) => this._routeToolService.canUpdate(record, this.recordType),
canDelete: (record: any) => this._routeToolService.canDelete(record, this.recordType),
preCreateRecord: (data: any) => {
const user = this._routeToolService.userService.getCurrentUser();
data.organisation = {
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { I18nPluralPipe, NgLocaleLocalization } from '@angular/common';

// TODO: Delete this service after refactoring of resource permission
@Injectable({
providedIn: 'root'
})
35 changes: 35 additions & 0 deletions projects/admin/src/app/service/record-permission.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* RERO ILS UI
* Copyright (C) 2020 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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 { TestBed } from '@angular/core/testing';

import { RecordPermissionService } from './record-permission.service';
import { TranslateModule } from '@ngx-translate/core';
import { HttpClientTestingModule } from '@angular/common/http/testing';

describe('ResourcePermissionService', () => {
beforeEach(() => TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
TranslateModule.forRoot({})
]
}));

it('should be created', () => {
const service: RecordPermissionService = TestBed.get(RecordPermissionService);
expect(service).toBeTruthy();
});
});
198 changes: 198 additions & 0 deletions projects/admin/src/app/service/record-permission.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
* RERO ILS UI
* Copyright (C) 2020 RERO
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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 { I18nPluralPipe, NgLocaleLocalization } from '@angular/common';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Injectable({
providedIn: 'root'
})
export class RecordPermissionService {

/** http client options */
private _httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
};

/**
* Constructor
* @param _httpClient - HttpClient
* @param _translateService - TranslateService
*/
constructor(
private _httpClient: HttpClient,
private _translateService: TranslateService
) { }

/**
* Get Permission by ressource with pid
* @param resource - string
* @param pid - string
*/
getPermission(resource: string, pid: string) {
return this._httpClient.get<RecordPermission>(
`/api/permissions/${resource}/${pid}`,
this._httpOptions
);
}

/**
* Generate Delete messages
* @param reasons - Object
* @return string
*/
generateDeleteMessage(reasons: any) {
const translatePlural = new I18nPluralPipe(new NgLocaleLocalization(
this._translateService.currentLang
));
const messages = [];

// Links
if ('links' in reasons) {
const plurialdict = this.plurialLinksMessages();
Object.keys(reasons.links).forEach(link => {
let message = null;
if ((link in plurialdict)) {
message = translatePlural.transform(
reasons.links[link],
plurialdict[link],
this._translateService.currentLang
);
} else {
message = reasons.links[link][link] + ' ' + link;
}
messages.push('- ' + message);
});
}

// Others
if ('others' in reasons) {
const plurialdict = this.othersMessages();
Object.keys(reasons.others).forEach(other => {
if ((other in plurialdict)) {
messages.push('- ' + plurialdict[other]);
} else {
messages.push('- ' + other);
}
});
}

messages.unshift(
messages.length === 1 ?
this._translateService.instant('You cannot delete the record for the following reason:') :
this._translateService.instant('You cannot delete the record for the following reasons:')
);

return messages.join('\n');
}

/**
* Plurial links messages
* @return array
*/
private plurialLinksMessages() {
return {
acq_order_lines: {
'=1': this._translateService.instant('has 1 acquisition order line attached'),
other: this._translateService.instant('has # acquisition order lines attached')
},
acq_orders: {
'=1': this._translateService.instant('has 1 acquisition orders attached'),
other: this._translateService.instant('has # acquisition orders attached')
},
acq_accounts: {
'=1': this._translateService.instant('has 1 acquisition account attached'),
other: this._translateService.instant('has # acquisition accounts attached')
},
budgets: {
'=1': this._translateService.instant('has 1 budget attached'),
other: this._translateService.instant('has # budgets attached')
},
circ_policies: {
'=1': this._translateService.instant('has 1 circulation policy attached'),
other: this._translateService.instant('has # circulation policies attached')
},
documents: {
'=1': this._translateService.instant('has 1 document attached'),
other: this._translateService.instant('has # documents attached')
},
item_types: {
'=1': this._translateService.instant('has 1 item type attached'),
other: this._translateService.instant('has # item types attached')
},
items: {
'=1': this._translateService.instant('has 1 item attached'),
other: this._translateService.instant('has # items attached')
},
libraries: {
'=1': this._translateService.instant('has 1 library attached'),
other: this._translateService.instant('has # libraries attached')
},
loans: {
'=1': this._translateService.instant('has 1 loan attached'),
other: this._translateService.instant('has # loans attached')
},
locations: {
'=1': this._translateService.instant('has 1 location attached'),
other: this._translateService.instant('has # locations attached')
},
organisations: {
'=1': this._translateService.instant('has 1 organisation attached'),
other: this._translateService.instant('has # organisations attached')
},
patron_types: {
'=1': this._translateService.instant('has 1 patron type attached'),
other: this._translateService.instant('has # patron types attached')
},
patrons: {
'=1': this._translateService.instant('has 1 patron attached'),
other: this._translateService.instant('has # patrons attached')
}
};
}

/**
* Others messages
* @return array
*/
private othersMessages() {
return {
is_default: this._translateService.instant('The default record cannot be deleted'),
has_settings: this._translateService.instant('The record contains settings'),
harvested: this._translateService.instant('The record has been harvested')
};
}
}

/**
* Permission response structure
*/
export interface RecordPermission {
update: {
can: boolean,
};
delete: {
can: boolean,
reasons?: {
others?: any,
links?: any
}
};
}
Original file line number Diff line number Diff line change
@@ -68,9 +68,6 @@ export class RoutingInitService {
aggregationsOrder: this.aggregations(viewcode),
aggregationsExpand: ['document_type'],
aggregationsBucketSize: 10,
listHeaders: {
Accept: 'application/rero+json, application/json'
},
preFilters: {
view: `${viewcode}`
}