Pull request #234: RED-684
Merge in RED/ui from RED-684 to master * commit '542f0a282d24bce28f1bcbf68609a35349da82ed': Reset password, refactored user listing dialogs Refactored admin dialog service
This commit is contained in:
commit
a9a6026f37
@ -34,6 +34,8 @@ import { ActiveFieldsListingComponent } from './dialogs/file-attributes-csv-impo
|
||||
import { AdminSideNavComponent } from './admin-side-nav/admin-side-nav.component';
|
||||
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||
import { ReportsScreenComponent } from './screens/reports/reports-screen.component';
|
||||
import { ResetPasswordComponent } from './dialogs/add-edit-user-dialog/reset-password/reset-password.component';
|
||||
import { UserDetailsComponent } from './dialogs/add-edit-user-dialog/user-details/user-details.component';
|
||||
|
||||
const dialogs = [
|
||||
AddEditDossierTemplateDialogComponent,
|
||||
@ -44,8 +46,7 @@ const dialogs = [
|
||||
SmtpAuthDialogComponent,
|
||||
AddEditUserDialogComponent,
|
||||
ConfirmDeleteUsersDialogComponent,
|
||||
FileAttributesCsvImportDialogComponent,
|
||||
AdminSideNavComponent
|
||||
FileAttributesCsvImportDialogComponent
|
||||
];
|
||||
|
||||
const screens = [
|
||||
@ -60,7 +61,8 @@ const screens = [
|
||||
LicenseInformationScreenComponent,
|
||||
UserListingScreenComponent,
|
||||
WatermarkScreenComponent,
|
||||
SmtpConfigScreenComponent
|
||||
SmtpConfigScreenComponent,
|
||||
ReportsScreenComponent
|
||||
];
|
||||
|
||||
const components = [
|
||||
@ -70,13 +72,16 @@ const components = [
|
||||
ComboSeriesVerticalComponent,
|
||||
UsersStatsComponent,
|
||||
ActiveFieldsListingComponent,
|
||||
AdminSideNavComponent,
|
||||
ResetPasswordComponent,
|
||||
UserDetailsComponent,
|
||||
|
||||
...dialogs,
|
||||
...screens
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components, ReportsScreenComponent],
|
||||
declarations: [...components],
|
||||
providers: [AdminDialogService],
|
||||
imports: [
|
||||
CommonModule,
|
||||
|
||||
@ -3,6 +3,8 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { DossierTemplateControllerService } from '@redaction/red-ui-http';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-template-actions',
|
||||
@ -16,6 +18,8 @@ export class DossierTemplateActionsComponent {
|
||||
constructor(
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossierTemplateControllerService: DossierTemplateControllerService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _router: Router,
|
||||
readonly permissionsService: PermissionsService
|
||||
) {
|
||||
@ -29,21 +33,22 @@ export class DossierTemplateActionsComponent {
|
||||
}
|
||||
|
||||
openEditDossierTemplateDialog($event: any) {
|
||||
$event.stopPropagation();
|
||||
this._dialogService.openAddEditDossierTemplateDialog(
|
||||
this._dialogService.openDialog(
|
||||
'addEditDossierTemplate',
|
||||
$event,
|
||||
this.dossierTemplate,
|
||||
async newDossierTemplate => {
|
||||
if (newDossierTemplate && this.loadDossierTemplatesData) {
|
||||
this.loadDossierTemplatesData.emit();
|
||||
}
|
||||
() => {
|
||||
this.loadDossierTemplatesData?.emit();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
openDeleteDossierTemplateDialog($event?: MouseEvent) {
|
||||
$event?.stopPropagation();
|
||||
|
||||
this._dialogService.openDeleteDossierTemplateDialog(this.dossierTemplate, async () => {
|
||||
this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
this._loadingService.start();
|
||||
await this._dossierTemplateControllerService
|
||||
.deleteDossierTemplates([this.dossierTemplateId])
|
||||
.toPromise();
|
||||
await this._appStateService.loadAllDossierTemplates();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
await this._router.navigate(['main', 'admin']);
|
||||
|
||||
@ -90,7 +90,7 @@ export class AddEditDictionaryDialogComponent {
|
||||
}
|
||||
|
||||
observable.subscribe(
|
||||
() => this._dialogRef.close(this.dictionary ? null : typeValue),
|
||||
() => this._dialogRef.close(true),
|
||||
error => {
|
||||
if (error.status === 409) {
|
||||
this._notifyError('add-edit-dictionary.error.dictionary-already-exists');
|
||||
|
||||
@ -1,72 +1,17 @@
|
||||
<section class="dialog">
|
||||
<div class="dialog-header heading-l">
|
||||
{{ (user ? 'add-edit-user.title.edit' : 'add-edit-user.title.new') | translate }}
|
||||
</div>
|
||||
<redaction-user-details
|
||||
(closeDialog)="dialogRef.close($event)"
|
||||
(toggleResetPassword)="toggleResetPassword()"
|
||||
*ngIf="!resettingPassword"
|
||||
[user]="user"
|
||||
></redaction-user-details>
|
||||
|
||||
<form (submit)="save()" [formGroup]="userForm">
|
||||
<div class="dialog-content">
|
||||
<div class="red-input-group required w-300">
|
||||
<label translate="add-edit-user.form.first-name"></label>
|
||||
<input formControlName="firstName" name="firstName" type="text" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required w-300">
|
||||
<label translate="add-edit-user.form.last-name"></label>
|
||||
<input formControlName="lastName" name="lastName" type="text" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required w-300">
|
||||
<label translate="add-edit-user.form.email"></label>
|
||||
<input formControlName="email" name="email" type="email" />
|
||||
</div>
|
||||
|
||||
<!-- <div class="red-input-group required w-300">-->
|
||||
<!-- <label translate="add-edit-user.form.password"></label>-->
|
||||
<!-- <input formControlName="password" name="password" type="password" />-->
|
||||
<!-- </div>-->
|
||||
|
||||
<div class="red-input-group">
|
||||
<label translate="add-edit-user.form.role"></label>
|
||||
<div class="roles-wrapper">
|
||||
<mat-checkbox
|
||||
*ngFor="let role of ROLES"
|
||||
[formControlName]="role"
|
||||
color="primary"
|
||||
>
|
||||
{{ 'roles.' + role | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button
|
||||
[disabled]="userForm.invalid || !changed"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
type="submit"
|
||||
>
|
||||
{{
|
||||
(user ? 'add-edit-user.actions.save-changes' : 'add-edit-user.actions.save')
|
||||
| translate
|
||||
}}
|
||||
</button>
|
||||
|
||||
<redaction-icon-button
|
||||
(action)="delete()"
|
||||
*ngIf="user"
|
||||
icon="red:trash"
|
||||
text="add-edit-user.actions.delete"
|
||||
type="show-bg"
|
||||
></redaction-icon-button>
|
||||
|
||||
<div
|
||||
class="all-caps-label cancel"
|
||||
mat-dialog-close
|
||||
translate="add-edit-user.actions.cancel"
|
||||
></div>
|
||||
</div>
|
||||
</form>
|
||||
<redaction-reset-password
|
||||
(close)="dialogRef.close($event)"
|
||||
(toggleResetPassword)="toggleResetPassword()"
|
||||
*ngIf="resettingPassword"
|
||||
[user]="user"
|
||||
></redaction-reset-password>
|
||||
|
||||
<redaction-circle-button
|
||||
class="dialog-close"
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
.roles-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-row-gap: 8px;
|
||||
margin-top: 8px;
|
||||
width: 300px;
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-add-edit-user-dialog',
|
||||
@ -10,91 +8,14 @@ import { UserService } from '@services/user.service';
|
||||
styleUrls: ['./add-edit-user-dialog.component.scss']
|
||||
})
|
||||
export class AddEditUserDialogComponent {
|
||||
userForm: FormGroup;
|
||||
readonly ROLES = ['RED_USER', 'RED_MANAGER', 'RED_USER_ADMIN', 'RED_ADMIN'];
|
||||
private readonly _ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
|
||||
resettingPassword = false;
|
||||
|
||||
constructor(
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _userService: UserService,
|
||||
public dialogRef: MatDialogRef<AddEditUserDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public user: User
|
||||
) {
|
||||
const rolesControls = this.ROLES.reduce(
|
||||
(prev, role) => ({
|
||||
...prev,
|
||||
[role]: [
|
||||
{
|
||||
value: this.user && this.user.roles.indexOf(role) !== -1,
|
||||
disabled:
|
||||
this.user &&
|
||||
Object.keys(this._ROLE_REQUIREMENTS).reduce(
|
||||
(value, key) =>
|
||||
value ||
|
||||
(role === this._ROLE_REQUIREMENTS[key] &&
|
||||
this.user.roles.indexOf(key) !== -1),
|
||||
false
|
||||
)
|
||||
}
|
||||
]
|
||||
}),
|
||||
{}
|
||||
);
|
||||
this.userForm = this._formBuilder.group({
|
||||
firstName: [this.user?.firstName, Validators.required],
|
||||
lastName: [this.user?.lastName, Validators.required],
|
||||
email: [
|
||||
{ value: this.user?.email, disabled: !!user },
|
||||
[Validators.required, Validators.email]
|
||||
],
|
||||
// password: [this.user?.password, Validators.required],
|
||||
...rolesControls
|
||||
});
|
||||
this._setRolesRequirements();
|
||||
}
|
||||
) {}
|
||||
|
||||
get changed(): boolean {
|
||||
if (!this.user) return true;
|
||||
|
||||
for (const key of Object.keys(this.userForm.getRawValue())) {
|
||||
if (this.user[key] !== this.userForm.get(key).value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
get activeRoles(): string[] {
|
||||
return this.ROLES.reduce((acc, role) => {
|
||||
if (this.userForm.get(role).value) {
|
||||
acc.push(role);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
async save() {
|
||||
this.dialogRef.close({
|
||||
action: this.user ? 'UPDATE' : 'CREATE',
|
||||
user: { ...this.userForm.getRawValue(), roles: this.activeRoles }
|
||||
});
|
||||
}
|
||||
|
||||
async delete() {
|
||||
this.dialogRef.close('DELETE');
|
||||
}
|
||||
|
||||
private _setRolesRequirements() {
|
||||
for (const key of Object.keys(this._ROLE_REQUIREMENTS)) {
|
||||
this.userForm.controls[key].valueChanges.subscribe(checked => {
|
||||
if (checked) {
|
||||
this.userForm.patchValue({ [this._ROLE_REQUIREMENTS[key]]: true });
|
||||
this.userForm.controls[this._ROLE_REQUIREMENTS[key]].disable();
|
||||
} else {
|
||||
this.userForm.controls[this._ROLE_REQUIREMENTS[key]].enable();
|
||||
}
|
||||
});
|
||||
}
|
||||
toggleResetPassword() {
|
||||
this.resettingPassword = !this.resettingPassword;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,26 @@
|
||||
<div
|
||||
[translateParams]="{ userName: userName }"
|
||||
[translate]="'reset-password-dialog.header'"
|
||||
class="dialog-header heading-l"
|
||||
></div>
|
||||
|
||||
<form (submit)="save()" [formGroup]="passwordForm">
|
||||
<div class="dialog-content">
|
||||
<div class="red-input-group required w-300">
|
||||
<label translate="reset-password-dialog.form.password"></label>
|
||||
<input formControlName="temporaryPassword" name="temporaryPassword" type="password" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button [disabled]="passwordForm.invalid" color="primary" mat-flat-button type="submit">
|
||||
{{ 'reset-password-dialog.actions.save' | translate }}
|
||||
</button>
|
||||
|
||||
<div
|
||||
(click)="toggleResetPassword.emit()"
|
||||
class="all-caps-label cancel"
|
||||
translate="reset-password-dialog.actions.cancel"
|
||||
></div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,46 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { UserService } from '../../../../../services/user.service';
|
||||
import { LoadingService } from '../../../../../services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-reset-password',
|
||||
templateUrl: './reset-password.component.html',
|
||||
styleUrls: ['./reset-password.component.scss']
|
||||
})
|
||||
export class ResetPasswordComponent {
|
||||
passwordForm: FormGroup;
|
||||
@Input() user: User;
|
||||
@Output() toggleResetPassword = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _userControllerService: UserControllerService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _loadingService: LoadingService
|
||||
) {
|
||||
this.passwordForm = this._formBuilder.group({
|
||||
temporaryPassword: [null, Validators.required]
|
||||
});
|
||||
}
|
||||
|
||||
get userName() {
|
||||
return this._userService.getNameForId(this.user.userId);
|
||||
}
|
||||
|
||||
async save() {
|
||||
this._loadingService.start();
|
||||
await this._userControllerService
|
||||
.resetPassword(
|
||||
{
|
||||
password: this.passwordForm.get('temporaryPassword').value,
|
||||
temporary: true
|
||||
},
|
||||
this.user.userId
|
||||
)
|
||||
.toPromise();
|
||||
this._loadingService.stop();
|
||||
this.toggleResetPassword.emit();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,66 @@
|
||||
<div class="dialog-header heading-l">
|
||||
{{ (user ? 'add-edit-user.title.edit' : 'add-edit-user.title.new') | translate }}
|
||||
</div>
|
||||
|
||||
<form (submit)="save()" [formGroup]="userForm">
|
||||
<div class="dialog-content">
|
||||
<div class="red-input-group required w-300">
|
||||
<label translate="add-edit-user.form.first-name"></label>
|
||||
<input formControlName="firstName" name="firstName" type="text" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required w-300">
|
||||
<label translate="add-edit-user.form.last-name"></label>
|
||||
<input formControlName="lastName" name="lastName" type="text" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required w-300">
|
||||
<label translate="add-edit-user.form.email"></label>
|
||||
<input formControlName="email" name="email" type="email" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group">
|
||||
<label translate="add-edit-user.form.role"></label>
|
||||
<div class="roles-wrapper">
|
||||
<mat-checkbox *ngFor="let role of ROLES" [formControlName]="role" color="primary">
|
||||
{{ 'roles.' + role | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
(click)="toggleResetPassword.emit()"
|
||||
*ngIf="!!user"
|
||||
class="mt-24 fit-content link-action"
|
||||
translate="add-edit-user.form.reset-password"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button
|
||||
[disabled]="userForm.invalid || !changed"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
type="submit"
|
||||
>
|
||||
{{
|
||||
(user ? 'add-edit-user.actions.save-changes' : 'add-edit-user.actions.save')
|
||||
| translate
|
||||
}}
|
||||
</button>
|
||||
|
||||
<redaction-icon-button
|
||||
(action)="delete()"
|
||||
*ngIf="user"
|
||||
icon="red:trash"
|
||||
text="add-edit-user.actions.delete"
|
||||
type="show-bg"
|
||||
></redaction-icon-button>
|
||||
|
||||
<div
|
||||
class="all-caps-label cancel"
|
||||
mat-dialog-close
|
||||
translate="add-edit-user.actions.cancel"
|
||||
></div>
|
||||
</div>
|
||||
</form>
|
||||
@ -0,0 +1,7 @@
|
||||
.roles-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
grid-row-gap: 8px;
|
||||
margin-top: 8px;
|
||||
width: 300px;
|
||||
}
|
||||
@ -0,0 +1,121 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { AdminDialogService } from '../../../services/admin-dialog.service';
|
||||
import { LoadingService } from '../../../../../services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-user-details',
|
||||
templateUrl: './user-details.component.html',
|
||||
styleUrls: ['./user-details.component.scss']
|
||||
})
|
||||
export class UserDetailsComponent implements OnInit {
|
||||
@Input() user: User;
|
||||
@Output() toggleResetPassword = new EventEmitter();
|
||||
@Output() closeDialog = new EventEmitter<any>();
|
||||
userForm: FormGroup;
|
||||
readonly ROLES = ['RED_USER', 'RED_MANAGER', 'RED_USER_ADMIN', 'RED_ADMIN'];
|
||||
private readonly _ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
|
||||
|
||||
constructor(
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _userControllerService: UserControllerService
|
||||
) {}
|
||||
|
||||
get changed(): boolean {
|
||||
if (!this.user) return true;
|
||||
|
||||
if (this.user.roles.length !== this.activeRoles.length) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(this.userForm.getRawValue())) {
|
||||
const keyValue = this.userForm.get(key).value;
|
||||
if (key.startsWith('RED_')) {
|
||||
if (this.user.roles.includes(key) !== keyValue) {
|
||||
return true;
|
||||
}
|
||||
} else if (this.user[key] !== keyValue) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
get activeRoles(): string[] {
|
||||
return this.ROLES.reduce((acc, role) => {
|
||||
if (this.userForm.get(role).value) {
|
||||
acc.push(role);
|
||||
}
|
||||
return acc;
|
||||
}, []);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
const rolesControls = this.ROLES.reduce(
|
||||
(prev, role) => ({
|
||||
...prev,
|
||||
[role]: [
|
||||
{
|
||||
value: this.user && this.user.roles.indexOf(role) !== -1,
|
||||
disabled:
|
||||
this.user &&
|
||||
Object.keys(this._ROLE_REQUIREMENTS).reduce(
|
||||
(value, key) =>
|
||||
value ||
|
||||
(role === this._ROLE_REQUIREMENTS[key] &&
|
||||
this.user.roles.indexOf(key) !== -1),
|
||||
false
|
||||
)
|
||||
}
|
||||
]
|
||||
}),
|
||||
{}
|
||||
);
|
||||
this.userForm = this._formBuilder.group({
|
||||
firstName: [this.user?.firstName, Validators.required],
|
||||
lastName: [this.user?.lastName, Validators.required],
|
||||
email: [
|
||||
{ value: this.user?.email, disabled: !!this.user },
|
||||
[Validators.required, Validators.email]
|
||||
],
|
||||
...rolesControls
|
||||
});
|
||||
this._setRolesRequirements();
|
||||
}
|
||||
|
||||
async save() {
|
||||
this._loadingService.start();
|
||||
const userData = { ...this.userForm.getRawValue(), roles: this.activeRoles };
|
||||
|
||||
if (!this.user) {
|
||||
await this._userControllerService.createUser(userData).toPromise();
|
||||
} else {
|
||||
await this._userControllerService.updateProfile(userData, this.user.userId).toPromise();
|
||||
}
|
||||
|
||||
this.closeDialog.emit(true);
|
||||
}
|
||||
|
||||
async delete() {
|
||||
this._dialogService.openDialog('deleteUsers', null, [this.user], async () => {
|
||||
this.closeDialog.emit(true);
|
||||
});
|
||||
}
|
||||
|
||||
private _setRolesRequirements() {
|
||||
for (const key of Object.keys(this._ROLE_REQUIREMENTS)) {
|
||||
this.userForm.controls[key].valueChanges.subscribe(checked => {
|
||||
if (checked) {
|
||||
this.userForm.patchValue({ [this._ROLE_REQUIREMENTS[key]]: true });
|
||||
this.userForm.controls[this._ROLE_REQUIREMENTS[key]].disable();
|
||||
} else {
|
||||
this.userForm.controls[this._ROLE_REQUIREMENTS[key]].enable();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FileAttributeConfig } from '@redaction/red-ui-http';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
@ -17,7 +16,6 @@ export class ConfirmDeleteFileAttributeDialogComponent {
|
||||
showToast = false;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
public dialogRef: MatDialogRef<ConfirmDeleteFileAttributeDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: FileAttributeConfig
|
||||
) {
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { User } from '@redaction/red-ui-http';
|
||||
import { User, UserControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-confirm-delete-users-dialog',
|
||||
@ -17,9 +18,11 @@ export class ConfirmDeleteUsersDialogComponent {
|
||||
dossiersCount: number;
|
||||
|
||||
constructor(
|
||||
@Inject(MAT_DIALOG_DATA) public users: User[],
|
||||
private readonly _appStateService: AppStateService,
|
||||
public dialogRef: MatDialogRef<ConfirmDeleteUsersDialogComponent>
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _userControllerService: UserControllerService,
|
||||
public dialogRef: MatDialogRef<ConfirmDeleteUsersDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public users: User[]
|
||||
) {
|
||||
this.dossiersCount = this._appStateService.allDossiers.filter(dw => {
|
||||
for (const user of this.users) {
|
||||
@ -41,6 +44,10 @@ export class ConfirmDeleteUsersDialogComponent {
|
||||
|
||||
async deleteUser() {
|
||||
if (this.valid) {
|
||||
this._loadingService.start();
|
||||
await this._userControllerService
|
||||
.deleteUsers(this.users.map(u => u.userId))
|
||||
.toPromise();
|
||||
this.dialogRef.close(true);
|
||||
} else {
|
||||
this.showToast = true;
|
||||
|
||||
@ -87,7 +87,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<redaction-full-page-loading-indicator
|
||||
[displayed]="!viewReady"
|
||||
></redaction-full-page-loading-indicator>
|
||||
|
||||
@ -1,21 +1,24 @@
|
||||
import { Component, Injector } from '@angular/core';
|
||||
import { Component, Injector, OnInit } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Colors, DictionaryControllerService } from '@redaction/red-ui-http';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-default-colors-screen',
|
||||
templateUrl: './default-colors-screen.component.html',
|
||||
styleUrls: ['./default-colors-screen.component.scss']
|
||||
})
|
||||
export class DefaultColorsScreenComponent extends BaseListingComponent<{
|
||||
key: string;
|
||||
value: string;
|
||||
}> {
|
||||
viewReady = false;
|
||||
export class DefaultColorsScreenComponent
|
||||
extends BaseListingComponent<{
|
||||
key: string;
|
||||
value: string;
|
||||
}>
|
||||
implements OnInit
|
||||
{
|
||||
protected readonly _sortKey = 'default-colors';
|
||||
private _colorsObj: Colors;
|
||||
|
||||
@ -24,35 +27,43 @@ export class DefaultColorsScreenComponent extends BaseListingComponent<{
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _dictionaryControllerService: DictionaryControllerService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
protected readonly _injector: Injector
|
||||
) {
|
||||
super(_injector);
|
||||
_appStateService.activateDossierTemplate(_activatedRoute.snapshot.params.dossierTemplateId);
|
||||
this._loadColors();
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this._loadColors();
|
||||
}
|
||||
|
||||
openEditColorDialog($event: any, color: { key: string; value: string }) {
|
||||
$event.stopPropagation();
|
||||
this._dialogService.openEditColorsDialog(
|
||||
this._colorsObj,
|
||||
color.key,
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
async () => this._loadColors()
|
||||
this._dialogService.openDialog(
|
||||
'editColor',
|
||||
$event,
|
||||
{
|
||||
colors: this._colorsObj,
|
||||
colorKey: color.key,
|
||||
dossierTemplateId: this._appStateService.activeDossierTemplateId
|
||||
},
|
||||
async () => {
|
||||
await this._loadColors();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private _loadColors() {
|
||||
this._dictionaryControllerService
|
||||
private async _loadColors() {
|
||||
this._loadingService.start();
|
||||
const data = await this._dictionaryControllerService
|
||||
.getColors(this._appStateService.activeDossierTemplateId)
|
||||
.toPromise()
|
||||
.then(data => {
|
||||
this._colorsObj = data;
|
||||
this.allEntities = Object.keys(data).map(key => ({
|
||||
key,
|
||||
value: data[key]
|
||||
}));
|
||||
this.viewReady = true;
|
||||
});
|
||||
.toPromise();
|
||||
this._colorsObj = data;
|
||||
this.allEntities = Object.keys(data).map(key => ({
|
||||
key,
|
||||
value: data[key]
|
||||
}));
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,12 +59,28 @@ export class DictionaryListingScreenComponent
|
||||
}
|
||||
|
||||
openDeleteDictionariesDialog($event?: MouseEvent, types = this.selectedEntitiesIds) {
|
||||
$event?.stopPropagation();
|
||||
this._dialogService.openDeleteDictionariesDialog(
|
||||
types,
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
this._loadingService.start();
|
||||
await this._dictionaryControllerService
|
||||
.deleteTypes(types, this._appStateService.activeDossierTemplateId)
|
||||
.toPromise();
|
||||
this.selectedEntitiesIds = [];
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadDictionaryData(false);
|
||||
this._calculateData();
|
||||
this._loadingService.stop();
|
||||
});
|
||||
}
|
||||
|
||||
openAddEditDictionaryDialog($event?: MouseEvent, dictionary?: TypeValueWrapper) {
|
||||
this._dialogService.openDialog(
|
||||
'addEditDictionary',
|
||||
$event,
|
||||
{
|
||||
dictionary,
|
||||
dossierTemplateId: this._appStateService.activeDossierTemplateId
|
||||
},
|
||||
async () => {
|
||||
this.selectedEntitiesIds = [];
|
||||
this._loadingService.start();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadDictionaryData(false);
|
||||
@ -74,23 +90,6 @@ export class DictionaryListingScreenComponent
|
||||
);
|
||||
}
|
||||
|
||||
openAddEditDictionaryDialog($event?: MouseEvent, dict?: TypeValueWrapper) {
|
||||
$event?.stopPropagation();
|
||||
this._dialogService.openAddEditDictionaryDialog(
|
||||
dict,
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
async newDictionary => {
|
||||
if (newDictionary) {
|
||||
this._loadingService.start();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadDictionaryData(false);
|
||||
this._calculateData();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private _loadDictionaryData(loadEntries = true): void {
|
||||
const appStateDictionaryData =
|
||||
this._appStateService.dictionaryData[this._appStateService.activeDossierTemplateId];
|
||||
|
||||
@ -10,6 +10,7 @@ import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component';
|
||||
import { DictionarySaveService } from '@shared/services/dictionary-save.service';
|
||||
import { TypeValueWrapper } from '../../../../models/file/type-value.wrapper';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dictionary-overview-screen',
|
||||
@ -32,7 +33,8 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _router: Router,
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _appStateService: AppStateService
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _loadingService: LoadingService
|
||||
) {
|
||||
super(_translateService);
|
||||
this._appStateService.activateDictionary(
|
||||
@ -54,12 +56,17 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple
|
||||
}
|
||||
|
||||
openEditDictionaryDialog($event: any) {
|
||||
$event.stopPropagation();
|
||||
this._dialogService.openAddEditDictionaryDialog(
|
||||
this.dictionary,
|
||||
this.dictionary.dossierTemplateId,
|
||||
this._dialogService.openDialog(
|
||||
'addEditDictionary',
|
||||
$event,
|
||||
{
|
||||
dictionary: this.dictionary,
|
||||
dossierTemplateId: this.dictionary.dossierTemplateId
|
||||
},
|
||||
async () => {
|
||||
this._loadingService.start();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -67,20 +74,19 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple
|
||||
openDeleteDictionaryDialog($event?: MouseEvent) {
|
||||
$event?.stopPropagation();
|
||||
|
||||
this._dialogService.openDeleteDictionariesDialog(
|
||||
[this.dictionary.type],
|
||||
this.dictionary.dossierTemplateId,
|
||||
async () => {
|
||||
await this._appStateService.loadDictionaryData();
|
||||
await this._router.navigate([
|
||||
'/main',
|
||||
'admin',
|
||||
'dossier-templates',
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
'dictionaries'
|
||||
]);
|
||||
}
|
||||
);
|
||||
this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
await this._dictionaryControllerService
|
||||
.deleteTypes([this.dictionary.type], this.dictionary.dossierTemplateId)
|
||||
.toPromise();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
await this._router.navigate([
|
||||
'/main',
|
||||
'admin',
|
||||
'dossier-templates',
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
'dictionaries'
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
download(): void {
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
}}
|
||||
</span>
|
||||
|
||||
<ng-container *ngIf="areSomeEntitiesSelected && !loading">
|
||||
<ng-container *ngIf="areSomeEntitiesSelected">
|
||||
<redaction-circle-button
|
||||
(action)="openDeleteTemplatesDialog($event)"
|
||||
*ngIf="permissionsService.isAdmin()"
|
||||
@ -44,8 +44,6 @@
|
||||
></redaction-circle-button>
|
||||
</ng-container>
|
||||
|
||||
<mat-spinner *ngIf="loading" diameter="15"></mat-spinner>
|
||||
|
||||
<div class="actions flex-1">
|
||||
<redaction-input-with-action
|
||||
[form]="searchForm"
|
||||
|
||||
@ -5,6 +5,8 @@ import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { DossierTemplateModelWrapper } from '../../../../models/file/dossier-template-model.wrapper';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
import { DossierTemplateControllerService } from '@redaction/red-ui-http';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-templates-listing-screen',
|
||||
@ -15,7 +17,6 @@ export class DossierTemplatesListingScreenComponent
|
||||
extends BaseListingComponent<DossierTemplateModelWrapper>
|
||||
implements OnInit
|
||||
{
|
||||
loading = false;
|
||||
protected readonly _searchKey = 'name';
|
||||
protected readonly _selectionKey = 'dossierTemplateId';
|
||||
protected readonly _sortKey = 'dossier-templates-listing';
|
||||
@ -23,9 +24,11 @@ export class DossierTemplatesListingScreenComponent
|
||||
constructor(
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossierTemplateControllerService: DossierTemplateControllerService,
|
||||
protected readonly _injector: Injector,
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly userPreferenceService: UserPreferenceService,
|
||||
protected readonly _injector: Injector
|
||||
readonly userPreferenceService: UserPreferenceService
|
||||
) {
|
||||
super(_injector);
|
||||
}
|
||||
@ -35,34 +38,38 @@ export class DossierTemplatesListingScreenComponent
|
||||
}
|
||||
|
||||
openDeleteTemplatesDialog($event?: MouseEvent) {
|
||||
$event?.stopPropagation();
|
||||
|
||||
this._dialogService.openBulkDeleteDossierTemplatesDialog(
|
||||
this.selectedEntitiesIds,
|
||||
async () => {
|
||||
this.selectedEntitiesIds = [];
|
||||
this.loading = true;
|
||||
await this._appStateService.loadAllDossierTemplates();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this.loadDossierTemplatesData();
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
return this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
this._loadingService.start();
|
||||
await this._dossierTemplateControllerService
|
||||
.deleteDossierTemplates(this.selectedEntitiesIds)
|
||||
.toPromise();
|
||||
this.selectedEntitiesIds = [];
|
||||
await this._appStateService.loadAllDossierTemplates();
|
||||
await this._appStateService.loadDictionaryData();
|
||||
this.loadDossierTemplatesData();
|
||||
});
|
||||
}
|
||||
|
||||
loadDossierTemplatesData() {
|
||||
this._loadingService.start();
|
||||
this._appStateService.reset();
|
||||
this.allEntities = this._appStateService.dossierTemplates;
|
||||
this._executeSearchImmediately();
|
||||
this._loadDossierTemplateStats();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
openAddDossierTemplateDialog() {
|
||||
this._dialogService.openAddEditDossierTemplateDialog(null, async newDossierTemplate => {
|
||||
if (newDossierTemplate) {
|
||||
this.loadDossierTemplatesData();
|
||||
this._dialogService.openDialog(
|
||||
'addEditDossierTemplate',
|
||||
null,
|
||||
null,
|
||||
async newDossierTemplate => {
|
||||
if (newDossierTemplate) {
|
||||
this.loadDossierTemplatesData();
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
private _loadDossierTemplateStats() {
|
||||
|
||||
@ -43,8 +43,6 @@
|
||||
>
|
||||
</redaction-circle-button>
|
||||
|
||||
<mat-spinner *ngIf="loading" diameter="15"></mat-spinner>
|
||||
|
||||
<div class="attributes-actions-container">
|
||||
<redaction-input-with-action
|
||||
[form]="searchForm"
|
||||
@ -204,7 +202,3 @@
|
||||
<div class="right-container"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<redaction-full-page-loading-indicator
|
||||
[displayed]="!viewReady"
|
||||
></redaction-full-page-loading-indicator>
|
||||
|
||||
@ -9,6 +9,7 @@ import { AppStateService } from '@state/app-state.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { BaseListingComponent } from '@shared/base/base-listing.component';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-attributes-listing-screen',
|
||||
@ -19,8 +20,6 @@ export class FileAttributesListingScreenComponent
|
||||
extends BaseListingComponent<FileAttributeConfig>
|
||||
implements OnInit
|
||||
{
|
||||
viewReady = false;
|
||||
loading = false;
|
||||
protected readonly _searchKey = 'label';
|
||||
protected readonly _selectionKey = 'id';
|
||||
protected readonly _sortKey = 'file-attributes-listing';
|
||||
@ -34,6 +33,7 @@ export class FileAttributesListingScreenComponent
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
protected readonly _injector: Injector
|
||||
) {
|
||||
super(_injector);
|
||||
@ -47,12 +47,12 @@ export class FileAttributesListingScreenComponent
|
||||
}
|
||||
|
||||
openAddEditAttributeDialog($event: MouseEvent, fileAttribute?: FileAttributeConfig) {
|
||||
$event.stopPropagation();
|
||||
this._dialogService.openAddEditFileAttributeDialog(
|
||||
fileAttribute,
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
async (newValue: FileAttributeConfig) => {
|
||||
this.loading = true;
|
||||
this._dialogService.openDialog(
|
||||
'addEditFileAttribute',
|
||||
$event,
|
||||
{ fileAttribute, dossierTemplateId: this._appStateService.activeDossierTemplateId },
|
||||
async newValue => {
|
||||
this._loadingService.start();
|
||||
await this._fileAttributesService
|
||||
.setFileAttributesConfiguration(
|
||||
newValue,
|
||||
@ -65,40 +65,39 @@ export class FileAttributesListingScreenComponent
|
||||
}
|
||||
|
||||
openConfirmDeleteAttributeDialog($event: MouseEvent, fileAttribute?: FileAttributeConfig) {
|
||||
$event.stopPropagation();
|
||||
this._dialogService.openConfirmDeleteFileAttributeDialog(
|
||||
fileAttribute,
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
async () => {
|
||||
this.loading = true;
|
||||
if (fileAttribute) {
|
||||
await this._fileAttributesService
|
||||
.deleteFileAttribute(
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
fileAttribute.id
|
||||
)
|
||||
.toPromise();
|
||||
} else {
|
||||
await this._fileAttributesService
|
||||
.deleteFileAttributes(
|
||||
this.selectedEntitiesIds,
|
||||
this._appStateService.activeDossierTemplateId
|
||||
)
|
||||
.toPromise();
|
||||
}
|
||||
await this._loadData();
|
||||
this._dialogService.openDialog('deleteFileAttribute', $event, fileAttribute, async () => {
|
||||
this._loadingService.start();
|
||||
if (fileAttribute) {
|
||||
await this._fileAttributesService
|
||||
.deleteFileAttribute(
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
fileAttribute.id
|
||||
)
|
||||
.toPromise();
|
||||
} else {
|
||||
await this._fileAttributesService
|
||||
.deleteFileAttributes(
|
||||
this.selectedEntitiesIds,
|
||||
this._appStateService.activeDossierTemplateId
|
||||
)
|
||||
.toPromise();
|
||||
}
|
||||
);
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
|
||||
importCSV(files: FileList | File[]) {
|
||||
const csvFile = files[0];
|
||||
const csv = files[0];
|
||||
this._fileInput.nativeElement.value = null;
|
||||
|
||||
this._dialogService.openImportFileAttributeCSVDialog(
|
||||
csvFile,
|
||||
this._appStateService.activeDossierTemplateId,
|
||||
this._existingConfiguration,
|
||||
this._dialogService.openDialog(
|
||||
'importFileAttributes',
|
||||
null,
|
||||
{
|
||||
csv,
|
||||
dossierTemplateId: this._appStateService.activeDossierTemplateId,
|
||||
existingConfiguration: this._existingConfiguration
|
||||
},
|
||||
async () => {
|
||||
await this._loadData();
|
||||
}
|
||||
@ -107,6 +106,7 @@ export class FileAttributesListingScreenComponent
|
||||
|
||||
private async _loadData() {
|
||||
try {
|
||||
this._loadingService.start();
|
||||
const response = await this._fileAttributesService
|
||||
.getFileAttributesConfiguration(this._appStateService.activeDossierTemplateId)
|
||||
.toPromise();
|
||||
@ -115,8 +115,7 @@ export class FileAttributesListingScreenComponent
|
||||
} catch (e) {
|
||||
} finally {
|
||||
this._executeSearchImmediately();
|
||||
this.viewReady = true;
|
||||
this.loading = false;
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,8 +79,4 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<redaction-full-page-loading-indicator
|
||||
[displayed]="!viewReady"
|
||||
></redaction-full-page-loading-indicator>
|
||||
|
||||
<input #fileInput (change)="uploadFile($event)" hidden type="file" />
|
||||
|
||||
@ -4,6 +4,7 @@ import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { ReportTemplate, ReportTemplateControllerService } from '@redaction/red-ui-http';
|
||||
import { download } from '../../../../utils/file-download-utils';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { LoadingService } from '../../../../services/loading.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-reports-screen',
|
||||
@ -11,7 +12,6 @@ import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
styleUrls: ['./reports-screen.component.scss']
|
||||
})
|
||||
export class ReportsScreenComponent implements OnInit {
|
||||
viewReady = false;
|
||||
placeholders: string[] = [
|
||||
'report',
|
||||
'predefined placeholder 1',
|
||||
@ -26,7 +26,8 @@ export class ReportsScreenComponent implements OnInit {
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _reportTemplateService: ReportTemplateControllerService,
|
||||
private readonly _dialogService: AdminDialogService
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _loadingService: LoadingService
|
||||
) {
|
||||
this._appStateService.activateDossierTemplate(
|
||||
_activatedRoute.snapshot.params.dossierTemplateId
|
||||
@ -39,11 +40,11 @@ export class ReportsScreenComponent implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
await this._loadReportTemplates();
|
||||
this.viewReady = true;
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async uploadFile($event) {
|
||||
this.viewReady = false;
|
||||
this._loadingService.start();
|
||||
const file = $event.target.files[0];
|
||||
|
||||
await this._reportTemplateService
|
||||
@ -52,7 +53,6 @@ export class ReportsScreenComponent implements OnInit {
|
||||
|
||||
this._fileInput.nativeElement.value = null;
|
||||
await this._loadReportTemplates();
|
||||
this.viewReady = true;
|
||||
}
|
||||
|
||||
async download(template: ReportTemplate) {
|
||||
@ -63,18 +63,20 @@ export class ReportsScreenComponent implements OnInit {
|
||||
}
|
||||
|
||||
deleteTemplate(template: ReportTemplate) {
|
||||
this._dialogService.openDeleteReportTemplateDialog(
|
||||
template.templateId,
|
||||
template.dossierTemplateId,
|
||||
async () => {
|
||||
await this._loadReportTemplates();
|
||||
}
|
||||
);
|
||||
this._dialogService.openDialog('confirm', null, null, async () => {
|
||||
this._loadingService.start();
|
||||
await this._reportTemplateService
|
||||
.deleteTemplate(template.dossierTemplateId, template.templateId)
|
||||
.toPromise();
|
||||
await this._loadReportTemplates();
|
||||
});
|
||||
}
|
||||
|
||||
private async _loadReportTemplates() {
|
||||
this._loadingService.start();
|
||||
this.availableTemplates = await this._reportTemplateService
|
||||
.getAvailableReportTemplates(this._appStateService.activeDossierTemplateId)
|
||||
.toPromise();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,8 +4,8 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import {
|
||||
GeneralConfigurationModel,
|
||||
SmtpConfigurationControllerService,
|
||||
GeneralSettingsControllerService,
|
||||
SmtpConfigurationControllerService,
|
||||
SMTPConfigurationModel
|
||||
} from '@redaction/red-ui-http';
|
||||
import { NotificationService, NotificationType } from '@services/notification.service';
|
||||
@ -103,13 +103,19 @@ export class SmtpConfigScreenComponent implements OnInit {
|
||||
}
|
||||
|
||||
openAuthConfigDialog(skipDisableOnCancel?: boolean) {
|
||||
this._dialogService.openSMTPAuthConfigDialog(this.configForm.getRawValue(), authConfig => {
|
||||
if (authConfig) {
|
||||
this.configForm.patchValue(authConfig);
|
||||
} else if (!skipDisableOnCancel) {
|
||||
this.configForm.patchValue({ auth: false }, { emitEvent: false });
|
||||
}
|
||||
});
|
||||
this._dialogService.openDialog(
|
||||
'smtpAuthConfig',
|
||||
null,
|
||||
this.configForm.getRawValue(),
|
||||
authConfig => {
|
||||
if (authConfig) {
|
||||
this.configForm.patchValue(authConfig);
|
||||
} else if (!skipDisableOnCancel) {
|
||||
this.configForm.patchValue({ auth: false }, { emitEvent: false });
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
async testConnection() {
|
||||
|
||||
@ -131,7 +131,7 @@
|
||||
type="dark-bg"
|
||||
></redaction-circle-button>
|
||||
<redaction-circle-button
|
||||
(action)="openDeleteUserDialog([user], $event)"
|
||||
(action)="openDeleteUsersDialog([user], $event)"
|
||||
[disabled]="user.userId === userService.userId"
|
||||
icon="red:trash"
|
||||
tooltip="user-listing.action.delete"
|
||||
|
||||
@ -25,7 +25,7 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly userService: UserService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _adminDialogService: AdminDialogService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _userControllerService: UserControllerService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
@ -43,31 +43,13 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
}
|
||||
|
||||
openAddEditUserDialog($event: MouseEvent, user?: User) {
|
||||
$event.stopPropagation();
|
||||
this._adminDialogService.openAddEditUserDialog(user, async result => {
|
||||
if (result === 'DELETE') {
|
||||
return this.openDeleteUserDialog([user]);
|
||||
}
|
||||
|
||||
this._loadingService.start();
|
||||
|
||||
if (result.action === 'CREATE') {
|
||||
await this._userControllerService.createUser(result.user).toPromise();
|
||||
} else if (result.action === 'UPDATE') {
|
||||
await this._userControllerService
|
||||
.updateProfile(result.user, user.userId)
|
||||
.toPromise();
|
||||
}
|
||||
|
||||
this._dialogService.openDialog('addEditUser', $event, user, async () => {
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
|
||||
openDeleteUserDialog(users: User[], $event?: MouseEvent) {
|
||||
$event?.stopPropagation();
|
||||
this._adminDialogService.openConfirmDeleteUsersDialog(users, async () => {
|
||||
this._loadingService.start();
|
||||
await this._userControllerService.deleteUsers(users.map(u => u.userId)).toPromise();
|
||||
openDeleteUsersDialog(users: User[], $event?: MouseEvent) {
|
||||
this._dialogService.openDialog('deleteUsers', $event, users, async () => {
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
@ -92,7 +74,7 @@ export class UserListingScreenComponent extends BaseListingComponent<User> imple
|
||||
}
|
||||
|
||||
async bulkDelete() {
|
||||
this.openDeleteUserDialog(this.allEntities.filter(u => this.isSelected(u)));
|
||||
this.openDeleteUsersDialog(this.allEntities.filter(u => this.isSelected(u)));
|
||||
}
|
||||
|
||||
trackById(index: number, user: User) {
|
||||
|
||||
@ -1,17 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
|
||||
import {
|
||||
Colors,
|
||||
DictionaryControllerService,
|
||||
DossierTemplateControllerService,
|
||||
DossierTemplateModel,
|
||||
FileAttributeConfig,
|
||||
FileAttributesConfig,
|
||||
ReportTemplateControllerService,
|
||||
SMTPConfigurationModel,
|
||||
TypeValue,
|
||||
User
|
||||
} from '@redaction/red-ui-http';
|
||||
import { AddEditFileAttributeDialogComponent } from '../dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
|
||||
import { AddEditDictionaryDialogComponent } from '../dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component';
|
||||
import { AddEditDossierTemplateDialogComponent } from '../dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component';
|
||||
@ -22,7 +10,19 @@ import { SmtpAuthDialogComponent } from '../dialogs/smtp-auth-dialog/smtp-auth-d
|
||||
import { AddEditUserDialogComponent } from '../dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
||||
import { ConfirmDeleteUsersDialogComponent } from '../dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
|
||||
import { FileAttributesCsvImportDialogComponent } from '../dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
|
||||
import { TypeValueWrapper } from '../../../models/file/type-value.wrapper';
|
||||
import { ComponentType } from '@angular/cdk/portal';
|
||||
|
||||
type DialogType =
|
||||
| 'confirm'
|
||||
| 'addEditDictionary'
|
||||
| 'editColor'
|
||||
| 'addEditFileAttribute'
|
||||
| 'deleteFileAttribute'
|
||||
| 'importFileAttributes'
|
||||
| 'addEditUser'
|
||||
| 'deleteUsers'
|
||||
| 'smtpAuthConfig'
|
||||
| 'addEditDossierTemplate';
|
||||
|
||||
const largeDialogConfig = {
|
||||
width: '90vw',
|
||||
@ -39,244 +39,74 @@ const dialogConfig = {
|
||||
|
||||
@Injectable()
|
||||
export class AdminDialogService {
|
||||
constructor(
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _dossierTemplateControllerService: DossierTemplateControllerService,
|
||||
private readonly _reportTemplateService: ReportTemplateControllerService,
|
||||
private readonly _dictionaryControllerService: DictionaryControllerService
|
||||
) {}
|
||||
private readonly _config: {
|
||||
[key in DialogType]: {
|
||||
component: ComponentType<any>;
|
||||
dialogConfig?: object;
|
||||
};
|
||||
} = {
|
||||
confirm: {
|
||||
component: ConfirmationDialogComponent
|
||||
},
|
||||
addEditDictionary: {
|
||||
component: AddEditDictionaryDialogComponent,
|
||||
dialogConfig: { autoFocus: true }
|
||||
},
|
||||
editColor: {
|
||||
component: EditColorDialogComponent,
|
||||
dialogConfig: { autoFocus: true }
|
||||
},
|
||||
addEditFileAttribute: {
|
||||
component: AddEditFileAttributeDialogComponent,
|
||||
dialogConfig: { autoFocus: true }
|
||||
},
|
||||
deleteFileAttribute: {
|
||||
component: ConfirmDeleteFileAttributeDialogComponent
|
||||
},
|
||||
importFileAttributes: {
|
||||
component: FileAttributesCsvImportDialogComponent,
|
||||
dialogConfig: largeDialogConfig
|
||||
},
|
||||
deleteUsers: {
|
||||
component: ConfirmDeleteUsersDialogComponent,
|
||||
dialogConfig: { autoFocus: true }
|
||||
},
|
||||
addEditUser: {
|
||||
component: AddEditUserDialogComponent,
|
||||
dialogConfig: { autoFocus: true }
|
||||
},
|
||||
smtpAuthConfig: {
|
||||
component: SmtpAuthDialogComponent,
|
||||
dialogConfig: { autoFocus: true }
|
||||
},
|
||||
addEditDossierTemplate: {
|
||||
component: AddEditDossierTemplateDialogComponent,
|
||||
dialogConfig: { width: '900px', autoFocus: true }
|
||||
}
|
||||
};
|
||||
|
||||
openDeleteDictionariesDialog(
|
||||
dictionaryTypes: string[],
|
||||
dossierTemplateId: string,
|
||||
cb?: () => void
|
||||
): MatDialogRef<ConfirmationDialogComponent> {
|
||||
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
|
||||
constructor(private readonly _dialog: MatDialog) {}
|
||||
|
||||
openDialog(
|
||||
type: DialogType,
|
||||
$event: MouseEvent,
|
||||
data: any,
|
||||
cb?: Function,
|
||||
checkForResult = true
|
||||
): MatDialogRef<any> {
|
||||
const config = this._config[type];
|
||||
|
||||
$event?.stopPropagation();
|
||||
const ref = this._dialog.open(config.component, {
|
||||
...dialogConfig,
|
||||
...(config.dialogConfig || {}),
|
||||
data
|
||||
});
|
||||
ref.afterClosed().subscribe(async result => {
|
||||
if (result) {
|
||||
await this._dictionaryControllerService
|
||||
.deleteTypes(dictionaryTypes, dossierTemplateId)
|
||||
.toPromise();
|
||||
if (cb) cb();
|
||||
if ((result || !checkForResult) && cb) {
|
||||
await cb(result);
|
||||
}
|
||||
});
|
||||
return ref;
|
||||
}
|
||||
|
||||
openDeleteReportTemplateDialog(
|
||||
templateId: string,
|
||||
dossierTemplateId: string,
|
||||
cb?: Function
|
||||
): MatDialogRef<ConfirmationDialogComponent> {
|
||||
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
|
||||
ref.afterClosed().subscribe(async result => {
|
||||
if (result) {
|
||||
await this._reportTemplateService
|
||||
.deleteTemplate(dossierTemplateId, templateId)
|
||||
.toPromise();
|
||||
if (cb) cb();
|
||||
}
|
||||
});
|
||||
return ref;
|
||||
}
|
||||
|
||||
openDeleteDossierTemplateDialog(
|
||||
dossierTemplate: DossierTemplateModel,
|
||||
cb?: () => void
|
||||
): MatDialogRef<ConfirmationDialogComponent> {
|
||||
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
|
||||
ref.afterClosed().subscribe(async result => {
|
||||
if (result) {
|
||||
if (cb) await cb();
|
||||
}
|
||||
});
|
||||
return ref;
|
||||
}
|
||||
|
||||
openBulkDeleteDossierTemplatesDialog(
|
||||
dossierTemplateIds: string[],
|
||||
cb?: Function
|
||||
): MatDialogRef<ConfirmationDialogComponent> {
|
||||
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
|
||||
ref.afterClosed().subscribe(async result => {
|
||||
if (result) {
|
||||
if (cb) await cb();
|
||||
}
|
||||
});
|
||||
return ref;
|
||||
}
|
||||
|
||||
openAddEditDictionaryDialog(
|
||||
dictionary: TypeValueWrapper,
|
||||
dossierTemplateId: string,
|
||||
cb?: (newDictionary: TypeValue | null) => void
|
||||
): MatDialogRef<AddEditDictionaryDialogComponent> {
|
||||
const ref = this._dialog.open(AddEditDictionaryDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: { dictionary, dossierTemplateId },
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe((newDictionary: TypeValue) => {
|
||||
if (newDictionary && cb) cb(newDictionary);
|
||||
else if (cb) cb(null);
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
openEditColorsDialog(
|
||||
colors: Colors,
|
||||
colorKey: string,
|
||||
dossierTemplateId: string,
|
||||
cb?: (result: boolean) => void
|
||||
): MatDialogRef<EditColorDialogComponent> {
|
||||
const ref = this._dialog.open(EditColorDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: { colors, colorKey, dossierTemplateId },
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe((result: boolean) => {
|
||||
if (result && cb) {
|
||||
cb(result);
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
openAddEditDossierTemplateDialog(
|
||||
dossierTemplate: DossierTemplateModel,
|
||||
cb?: Function
|
||||
): MatDialogRef<AddEditDossierTemplateDialogComponent> {
|
||||
const ref = this._dialog.open(AddEditDossierTemplateDialogComponent, {
|
||||
...dialogConfig,
|
||||
width: '900px',
|
||||
data: dossierTemplate,
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe(result => {
|
||||
if (result && cb) {
|
||||
cb(result);
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
openImportFileAttributeCSVDialog(
|
||||
csv: File,
|
||||
dossierTemplateId: string,
|
||||
existingConfiguration: FileAttributesConfig,
|
||||
cb?: Function
|
||||
): MatDialogRef<FileAttributesCsvImportDialogComponent> {
|
||||
const ref = this._dialog.open(FileAttributesCsvImportDialogComponent, {
|
||||
...largeDialogConfig,
|
||||
data: { csv, dossierTemplateId, existingConfiguration }
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe(result => {
|
||||
if (result && cb) {
|
||||
cb(result);
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
openAddEditFileAttributeDialog(
|
||||
fileAttribute: FileAttributeConfig,
|
||||
dossierTemplateId: string,
|
||||
cb?: Function
|
||||
): MatDialogRef<AddEditFileAttributeDialogComponent> {
|
||||
const ref = this._dialog.open(AddEditFileAttributeDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: { fileAttribute, dossierTemplateId },
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe(result => {
|
||||
if (result && cb) {
|
||||
cb(result);
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
openConfirmDeleteFileAttributeDialog(
|
||||
fileAttribute: FileAttributeConfig,
|
||||
dossierTemplateId: string,
|
||||
cb?: Function
|
||||
): MatDialogRef<ConfirmDeleteFileAttributeDialogComponent> {
|
||||
const ref = this._dialog.open(ConfirmDeleteFileAttributeDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: fileAttribute,
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe(result => {
|
||||
if (result && cb) {
|
||||
cb(result);
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
openSMTPAuthConfigDialog(
|
||||
smtpConfig: SMTPConfigurationModel,
|
||||
cb?: Function
|
||||
): MatDialogRef<SmtpAuthDialogComponent> {
|
||||
const ref = this._dialog.open(SmtpAuthDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: smtpConfig,
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe(result => {
|
||||
if (cb) {
|
||||
cb(result);
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
openAddEditUserDialog(user?: User, cb?: Function): MatDialogRef<AddEditUserDialogComponent> {
|
||||
const ref = this._dialog.open(AddEditUserDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: user,
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe(result => {
|
||||
if (result && cb) {
|
||||
cb(result);
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
openConfirmDeleteUsersDialog(
|
||||
users: User[],
|
||||
cb?: Function
|
||||
): MatDialogRef<ConfirmDeleteUsersDialogComponent> {
|
||||
const ref = this._dialog.open(ConfirmDeleteUsersDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: users,
|
||||
autoFocus: true
|
||||
});
|
||||
|
||||
ref.afterClosed().subscribe(result => {
|
||||
if (result && cb) {
|
||||
cb(result);
|
||||
}
|
||||
});
|
||||
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,7 +97,8 @@
|
||||
"email": "Email",
|
||||
"first-name": "First Name",
|
||||
"last-name": "Last Name",
|
||||
"role": "Role"
|
||||
"role": "Role",
|
||||
"reset-password": "Reset Password"
|
||||
},
|
||||
"title": {
|
||||
"edit": "Edit User",
|
||||
@ -338,6 +339,16 @@
|
||||
"formula": "Formula"
|
||||
}
|
||||
},
|
||||
"reset-password-dialog": {
|
||||
"header": "Set Temporary Password for {{userName}}",
|
||||
"form": {
|
||||
"password": "Temporary password"
|
||||
},
|
||||
"actions": {
|
||||
"save": "Save",
|
||||
"cancel": "Cancel"
|
||||
}
|
||||
},
|
||||
"comment": "Comment",
|
||||
"comments": {
|
||||
"add-comment": "Enter comment",
|
||||
|
||||
@ -364,3 +364,7 @@ section.settings {
|
||||
.d-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.cdk-overlay-container {
|
||||
z-index: 800;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user