diff --git a/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.html b/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.html index cdaa9c5a3..718341b24 100644 --- a/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.html +++ b/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.html @@ -16,247 +16,168 @@ --> - -

{{ patron.last_name }} {{ patron.first_name }}

- Date of birth - {{ patron.birth_date | dateTranslate:'mediumDate' }} - + + + +
+ + {{ patron.notes.length | i18nPlural: {'=1': 'Note', 'other': 'Notes'} }} + {{ patron.notes.length }} +
+
+
+
{{ note.type | translate }}
+
+
+
+
+ +
+ + {{ 'User informations' | translate }} +
+
+
+
Username
+
{{ patron.username }}
+
+
Keep history
+
+ +
+
{{ patron.roles | i18nPlural: {'=1': 'Role', 'other': 'Roles'} }}
+
+ + {{ role | translate }} + +
+
+ + +
+ + {{ 'Patron Information' | translate }} +
+
+
+
Barcode
+
+ {{ patron.patron.barcode | join: ', ' }} +
+
Type
+
{{ patron.patron.type.pid | getRecord: 'patron_types' : 'field' : 'name' | async }}
+
Account expiration
+
{{ patron.patron.expiration_date | dateTranslate:'mediumDate' }}
+ +
+
Affiliation libraries
+
    +
  • {{ library.pid | getRecord: 'libraries' : 'field' : 'name' | async }}
- -
- - -
-
Patron Information
- -
-
- Patron's barcodes or cards number -
-
- - {{ patron.patron.barcode | join: ', '}} - -
-
- -
-
- {{ patron.roles.length | i18nPlural: {'=1': 'Role', 'other': 'Roles'} }} -
-
- - {{ role | translate }}{{ last ? '' : ', ' }} - -
-
- -
-
- Type -
-
- {{ patron.patron.type.pid | getRecord: 'patron_types' : 'field' : 'name' | async }} -
-
- -
-
- Account expiration -
-
- {{ patron.patron.expiration_date | dateTranslate:'mediumDate' }} -
+ + +
Source
+
{{ patron.source }}
+
+ +
Local code
+
{{ patron.local_codes | join: ',' }}
+
+ +
+
Second address
+
+ {{ patron.second_address.street }}
+ {{ patron.second_address.postal_code }} {{ patron.second_address.city }}
+ {{ 'country_' + patron.second_address.country | translate }} +
+
-
-
- {{ 'Affiliation libraries' | translate }}: -
-
-
+ + + +
+ + {{ 'Librarian Information' | translate }} +
+
+
+
{{ patron.libraries.length | i18nPlural: {'=1': 'Library', 'other': 'Libraries'} }}
+
    +
  • {{ library.pid | getRecord: 'libraries' : 'field' : 'name' | async }} -
-
+ +
-
- +
+ diff --git a/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.scss b/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.scss new file mode 100644 index 000000000..773d85802 --- /dev/null +++ b/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.scss @@ -0,0 +1,50 @@ +/* + * RERO ILS UI + * Copyright (C) 2021 RERO + * Copyright (C) 2021 UCLouvain + * + * 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 . + */ + +@import '~bootstrap/scss/_functions'; +@import '~bootstrap/scss/_variables'; + +#contact-profile { + .profile-image { + width: 140px; + height: 140px; + border-radius: 70px; + background-color: $secondary; + text-align: center; + vertical-align: middle; + display: table-cell; + } + + .metadata { + text-transform: lowercase; + font-size: $small-font-size; + font-weight: $font-weight-bold; + color: $secondary; + &:before { + content: '('; + } + &:after { + content: ')'; + padding-right: map-get($spacers, 2); + } + } + + .btn-shore-more { + border-color: $card-border-color; + } +} diff --git a/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.ts b/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.ts index e5b40698f..0f094452e 100644 --- a/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.ts +++ b/projects/admin/src/app/record/detail-view/patron-detail-view/patron-detail-view.component.ts @@ -21,35 +21,74 @@ import { DetailRecord } from '@rero/ng-core/lib/record/detail/view/detail-record import { Observable, Subscription } from 'rxjs'; import { OperationLogsService } from '../../../service/operation-logs.service'; +interface PatronPhone { + value: string; + type?: string; + weight: number; +} + @Component({ selector: 'admin-patron-detail-view', - templateUrl: './patron-detail-view.component.html' + templateUrl: './patron-detail-view.component.html', + styleUrls: ['./patron-detail-view.component.scss'] }) export class PatronDetailViewComponent implements OnInit, DetailRecord, OnDestroy { + // COMPONENT ATTRIBUTES ===================================================== /** Data from patron we received */ record$: Observable; - /** Current displayed/used patron */ patron: any; - /** record type */ type: string; + /** Load operation logs on show */ + showOperationLogs = false; + /** collapsed sections */ + sectionCollapsed = { + user: false, + librarian: true, + patron: true, + notes: false + }; /** Subscription to (un)follow the record$ Observable */ private _subscription$ = new Subscription(); + /** mapping to define role badge color */ + private _rolesBadgeMappings = { + system_librarian: 'badge-danger', + librarian: 'badge-warning' + }; - /** Load operation logs on show */ - showOperationLogs = false; - - /** - * Is operation log enabled - * @return boolean - */ + // GETTER AND SETTER ======================================================== + /** Is operation log enabled */ get isEnabledOperationLog(): boolean { return this._operationLogsService.isLogVisible('patrons'); } + /** Get all phones related to the patron */ + get phones(): Array { + const data: Array = []; + if (this.patron.mobile_phone) { + data.push({value: this.patron.mobile_phone, type: 'Mobile', weight: 10}); + } + if (this.patron.home_phone) { + data.push({value: this.patron.home_phone, type: 'Home', weight: 7}); + } + if (this.patron.business_phone) { + data.push({value: this.patron.business_phone, type: 'Business', weight: 7}); + } + if (this.patron.other_phone) { + data.push({value: this.patron.other_phone, type: 'Other', weight: -1}); + } + return data.sort((a, b) => b.weight - a.weight); + } + + /** Check if the patron has the librarian role */ + get isLibrarian(): boolean { + return this.patron && this.patron.roles && this.patron.roles.includes('librarian'); + } + + // CONSTRUCTOR & HOOKS ====================================================== /** * Constructor. * @param _sanitizer - DomSanitizer, to render html. @@ -60,39 +99,39 @@ export class PatronDetailViewComponent implements OnInit, DetailRecord, OnDestro private _operationLogsService: OperationLogsService ) {} - /** - * Current patron initialization. - */ + /** OnInit hook */ ngOnInit() { - this._subscription$ = this.record$.subscribe(record => { - this.patron = record.metadata; - }); + this._subscription$ = this.record$.subscribe(record => this.patron = record.metadata); } - /** - * Unsubscribe observable when destroying the PatronDetailViewComponent - */ + /** OnDestroy hook */ ngOnDestroy() { this._subscription$.unsubscribe(); } + // COMPONENTS FUNCTIONS ===================================================== + /** - * Get the patron notes. - * - * It replace a new line to the corresponding html code. - * Allows to render html. + * Get the color badge to apply for a specific role + * @param role: the role to check. + * @return the bootstrap badge class to use for this role. */ - public get notes(): Array<{type: string, content: SafeHtml}> { - if (!this.patron.notes || this.patron.notes.length < 1) { - return []; + getRoleBadgeColor(role: string): string { + return (role in this._rolesBadgeMappings) + ? this._rolesBadgeMappings[role] + : 'badge-light'; + } + + /** Get the badge color to use for a note type + * @param noteType - the note type + */ + getNoteBadgeColor(noteType: string): string { + switch (noteType) { + case 'public_note': return 'badge-info'; + case 'staff_note': return 'badge-warning'; + default: return 'badge-secondary'; } - return this.patron.notes.map((note: any) => { - return { - type: note.type, - content: this._sanitizer.bypassSecurityTrustHtml( - note.content.replace('\n', '
')) - }; - }); } + } diff --git a/projects/admin/src/app/scss/styles.scss b/projects/admin/src/app/scss/styles.scss index 2e524238c..9b89be862 100644 --- a/projects/admin/src/app/scss/styles.scss +++ b/projects/admin/src/app/scss/styles.scss @@ -122,6 +122,29 @@ json-schema-form { vertical-align: top; } + +/* SHOW MORE BUTTON ====================================================== */ +.btn-shore-more { + border: $border-width solid $border-color; + border-radius: 2rem; + height: 30px; + width: 30px; + background-color: $white; + margin-right: map-get($spacers, 3); + + &.btn-expanded::before { + font-family: 'FontAwesome'; + font-weight: 100; + content: " \f0d7"; + } + + &.btn-collapsed::before { + font-family: 'FontAwesome'; + font-weight: 100; + content: " \f0da"; + } +} + // source: https://codepen.io/superjaberwocky/pen/AXdEWj .callout { border: 1px solid #eee;