Skip to content

Commit

Permalink
patron: a professional can change a user password
Browse files Browse the repository at this point in the history
* Adds missing license in some files.
* Fixes some spelling.
* Adds a button in the circulation patron profile to update the
  password.
* Adds a edit button in the circulation patron profile.
* Moves roles in the patron informations in the patron circulation
  profile and the patron detail view.

Co-Authored-by: Johnny Mariéthoz <Johnny.Mariethoz@rero.ch>
  • Loading branch information
jma committed Nov 4, 2020
1 parent c651807 commit 8ed6e06
Show file tree
Hide file tree
Showing 11 changed files with 396 additions and 49 deletions.
13 changes: 8 additions & 5 deletions projects/admin/src/app/circulation/circulation.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@ import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormlyModule } from '@ngx-formly/core';
import { RecordModule } from '@rero/ng-core';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { CollapseModule } from 'ngx-bootstrap/collapse';
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
import { SharedPipesModule } from '../shared/shared-pipes.module';
import { CheckinComponent } from './checkin/checkin.component';
import { CirculationRoutingModule } from './circulation-routing.module';
import { ItemComponent } from './item/item.component';
import { ItemsListComponent } from './items-list/items-list.component';
import { MainRequestComponent } from './main-request/main-request.component';
import { CardComponent } from './patron/card/card.component';
import { ChangePasswordFormComponent } from './patron/change-password-form/change-password-form.component';
import { HistoryItemComponent } from './patron/history/history-item/history-item.component';
import { HistoryComponent } from './patron/history/history.component';
import { LoanComponent } from './patron/loan/loan.component';
Expand All @@ -46,11 +47,11 @@ import {
} from './patron/patron-transactions/patron-transaction/overdue-transaction/overdue-transaction.component';
import { PatronTransactionComponent } from './patron/patron-transactions/patron-transaction/patron-transaction.component';
import { PatronTransactionsComponent } from './patron/patron-transactions/patron-transactions.component';
import { PendingItemComponent } from './patron/pending/pending-item/pending-item.component';
import { PendingComponent } from './patron/pending/pending.component';
import { PickupItemComponent } from './patron/pickup/pickup-item/pickup-item.component';
import { PickupComponent } from './patron/pickup/pickup.component';
import { ProfileComponent } from './patron/profile/profile.component';
import { PendingItemComponent } from './patron/pending/pending-item/pending-item.component';
import { PendingComponent } from './patron/pending/pending.component';
import { RequestedItemsListComponent } from './requested-items-list/requested-items-list.component';


Expand All @@ -77,7 +78,8 @@ import { RequestedItemsListComponent } from './requested-items-list/requested-it
DefaultTransactionComponent,
PatronTransactionEventFormComponent,
HistoryComponent,
HistoryItemComponent
HistoryItemComponent,
ChangePasswordFormComponent
],
imports: [
CommonModule,
Expand All @@ -91,7 +93,8 @@ import { RequestedItemsListComponent } from './requested-items-list/requested-it
SharedPipesModule
],
entryComponents: [
PatronTransactionEventFormComponent
PatronTransactionEventFormComponent,
ChangePasswordFormComponent
]
})
export class CirculationModule { }
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!--
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/>.
-->
<div *ngIf="form" class="modal show d-block" role="dialog">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" translate>Update Patron Password</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true" data-dismiss="modal" (click)="closeModal()">&times;</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="form" (ngSubmit)="submit(patron, model)">
<formly-form [form]="form" [fields]="formFields" [model]="model"></formly-form>
<div class="text-right">
<button id="change-password-submit-button" class="btn btn-primary" [disabled]="!form.valid" translate>Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* 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 { HttpClientTestingModule } from '@angular/common/http/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { BsModalRef } from 'ngx-bootstrap/modal';
import { CirculationModule } from '../../circulation.module';
import { ChangePasswordFormComponent } from './change-password-form.component';


describe('ChangePasswordFormComponent', () => {
let component: ChangePasswordFormComponent;
let fixture: ComponentFixture<ChangePasswordFormComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
HttpClientTestingModule,
CirculationModule
],
providers: [
BsModalRef
]
})
.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(ChangePasswordFormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* 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 { Component, OnInit } from '@angular/core';
import { FormGroup } from '@angular/forms';
import { FormlyFieldConfig } from '@ngx-formly/core';
import { TranslateService } from '@ngx-translate/core';
import { BsModalRef, BsModalService } from 'ngx-bootstrap/modal';
import { ToastrService } from 'ngx-toastr';
import { User } from '../../../class/user';
import { UserService } from '../../../service/user.service';

@Component({
selector: 'admin-change-password-form',
templateUrl: './change-password-form.component.html'
})
export class ChangePasswordFormComponent implements OnInit {

/** patron to change the password */
patron: User;

/** form */
form: FormGroup = new FormGroup({});

/** model */
model = {};

/** form fields */
formFields: FormlyFieldConfig[];

/**
* Constructor
* @param _modalService - BsModalService
* @param _bsModalRef - BsModalRef
* @param _translateService - TranslateService
* @param _toastr - ToastrService
* @param _userService - UserService
*/
constructor(
private _modalService: BsModalService,
private _bsModalRef: BsModalRef,
private _translateService: TranslateService,
private _toastr: ToastrService,
private _userService: UserService
) { }

/**
* Component initialization.
*/
ngOnInit() {
const initialState: any = this._modalService.config.initialState;
if (initialState.hasOwnProperty('patron')) {
this.closeModal();
}
this.patron = initialState.patron;
this._initForm();
}

/**
* Submit form
* @param model - Object
*/
submit(patron, model) {
this._userService.changePassword(patron.username, model.password).subscribe(
() => {
this._toastr.success(
this._translateService.instant('The patron password has been changed.'),
);
this.closeModal();
},
(resp) => {
console.log('Error: Update Patron Password', resp);
let error = this._translateService.instant('An error has occurred.');
if (resp.error && resp.error.message) {
error = `${error}: (${resp.error.message})`;
}
this._toastr.error(
error,
this._translateService.instant('Update Patron Password'),
{ disableTimeOut: true }
);
this.closeModal();
}
);
}

/**
* Initialize formly form.
*/
private _initForm() {
if (this.patron) {
this.formFields = [
{
key: 'password',
type: 'input',
focus: true,
templateOptions: {
type: 'password',
label: this._translateService.instant('New password'),
required: true,
// same as Invenio
minLength: 6,
maxLength: 128,
keydown: (field, event) => {
if (event.key === 'Enter') {
event.preventDefault();
}
}
}
}
];
}
}

/**
* Close modal dialog
* @param event - Event
*/
closeModal() {
this._bsModalRef.hide();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export class LoanComponent implements OnInit, OnDestroy {
/** Library PID of the logged user */
currentLibraryPid: string;

private _subcription = new Subscription();
/** Observable subscription */
private _subscription = new Subscription();

/**
* Constructor
Expand All @@ -77,7 +78,7 @@ export class LoanComponent implements OnInit, OnDestroy {
) {}

ngOnInit() {
this._subcription.add(this._patronService.currentPatron$.subscribe(patron => {
this._subscription.add(this._patronService.currentPatron$.subscribe(patron => {
this.patron = patron;
if (patron) {
this.isLoading = true;
Expand All @@ -101,7 +102,7 @@ export class LoanComponent implements OnInit, OnDestroy {
}

ngOnDestroy() {
this._subcription.unsubscribe();
this._subscription.unsubscribe();
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
<!--
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/>.
-->
<ng-container *ngIf="transactions">
<form [formGroup]="form" (ngSubmit)="onSubmitForm()">
<div class="modal-header">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
<!--
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/>.
-->
<section *ngIf="!isLoading; else loading" class="content">
<ng-container *ngIf="transactions.length > 0; else noTransaction">
<!-- HEADER ~~~~~~~~~~~~~~~~~~~~~~~~ -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
 along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<article *ngIf="currentPatron$ | async as patron">
<div *ngIf="canUpdate()" class="float-right">
<button [routerLink]="['/records','patrons','edit', patron.pid]" class="btn btn-sm btn-primary ml-1 ng-star-inserted" id="profile-edit-button" title="Edit"><i class="fa fa-pen mr-1"></i>{{ 'Edit' | translate }}</button>
</div>
<h3 class="mb-3">{{ patron.last_name }} {{ patron.first_name }}</h3>
<section class="m-2 p-2">
<!-- USERNAME -->
<dl class="row mb-0">
Expand Down Expand Up @@ -62,18 +66,7 @@
{{ patron.email }}
</dd>
</dl>
<!-- ROLES -->
<dl class="row mb-0">
<dt class="col-sm-3 offset-sm-2 offset-md-0">
<ng-container *ngIf="patron.roles.length === 1; else roles" translate>Role</ng-container>
<ng-template #roles translate>Roles</ng-template>:
</dt>
<dd class="col-sm-7 col-md-8 mb-0">
<ng-container *ngFor="let role of patron.roles; let last=last">
{{ role | translate }}{{ last ? '' : ', ' }}
</ng-container>
</dd>
</dl>
<button *ngIf="canUpdate()" class="btn btn-sm btn-outline-primary mt-2" id="profile-change-password-button" (click)="updatePatronPassword(patron)" title="Change Password">{{ 'Change Password' | translate }}</button>

</section>
<section class="m-2 p-2" *ngIf="patron.isLibrarian">
Expand All @@ -90,6 +83,18 @@ <h5 translate>Librarian Information</h5>
</section>
<section class="m-2 p-2" *ngIf="patron.patron">
<h5 translate>Patron Information</h5>
<!-- ROLES -->
<dl class="row mb-0">
<dt class="col-sm-3 offset-sm-2 offset-md-0">
<ng-container *ngIf="patron.roles.length === 1; else roles" translate>Role</ng-container>
<ng-template #roles translate>Roles</ng-template>:
</dt>
<dd class="col-sm-7 col-md-8 mb-0">
<ng-container *ngFor="let role of patron.roles; let last=last">
{{ role | translate }}{{ last ? '' : ', ' }}
</ng-container>
</dd>
</dl>
<!-- BARCODE -->
<dl class="row mb-0">
<dt class="col-sm-3 offset-sm-2 offset-md-0">
Expand Down
Loading

0 comments on commit 8ed6e06

Please sign in to comment.