diff --git a/.editorconfig b/.editorconfig index 7ac0fdd9b..49601a81f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,5 +14,9 @@ max_line_length = 140 max_line_length = off trim_trailing_whitespace = false +[*.ts] +ij_typescript_use_double_quotes = false +ij_typescript_enforce_trailing_comma = keep + [{*.json, .prettierrc, .eslintrc}] indent_size = 2 diff --git a/.eslintrc.json b/.eslintrc.json index 925cd52ff..567c024ba 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -184,6 +184,7 @@ "prefer-const": "error", "radix": "error", "curly": "error", + "quotes": ["error", "single"], "comma-dangle": [ "error", { diff --git a/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.html b/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.html index 5a41656d3..83dacdb5f 100644 --- a/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.html +++ b/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.html @@ -24,8 +24,8 @@ > - -
+ +
{{ download.filename }} diff --git a/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts b/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts index e30bb92fd..97d23d6be 100644 --- a/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts +++ b/apps/red-ui/src/app/components/downloads-list-screen/downloads-list-screen.component.ts @@ -1,22 +1,34 @@ -import { Component, forwardRef, Injector, OnInit } from '@angular/core'; +import { Component, forwardRef, Injector } from '@angular/core'; import { FileDownloadService } from '@upload-download/services/file-download.service'; -import { DownloadStatusWrapper } from '@upload-download/model/download-status.wrapper'; -import { DownloadControllerService } from '@redaction/red-ui-http'; -import { CircleButtonTypes, DefaultListingServices, ListingComponent, LoadingService, TableColumnConfig } from '@iqser/common-ui'; +import { DownloadStatus } from '@upload-download/model/download-status'; +import { + CircleButtonTypes, + DefaultListingServicesTmp, + EntitiesService, + ListingComponent, + LoadingService, + TableColumnConfig, +} from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { timer } from 'rxjs'; import { RouterHistoryService } from '@services/router-history.service'; @Component({ selector: 'redaction-downloads-list-screen', templateUrl: './downloads-list-screen.component.html', styleUrls: ['./downloads-list-screen.component.scss'], - providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => DownloadsListScreenComponent) }], + providers: [ + ...DefaultListingServicesTmp, + { provide: EntitiesService, useExisting: FileDownloadService }, + { + provide: ListingComponent, + useExisting: forwardRef(() => DownloadsListScreenComponent), + }, + ], }) -export class DownloadsListScreenComponent extends ListingComponent implements OnInit { +export class DownloadsListScreenComponent extends ListingComponent { readonly circleButtonTypes = CircleButtonTypes; readonly tableHeaderLabel = _('downloads-list.table-header.title'); - readonly tableColumnConfigs: TableColumnConfig[] = [ + readonly tableColumnConfigs: TableColumnConfig[] = [ { label: _('downloads-list.table-col-names.name'), width: '2fr' }, { label: _('downloads-list.table-col-names.size') }, { label: _('downloads-list.table-col-names.date') }, @@ -28,37 +40,27 @@ export class DownloadsListScreenComponent extends ListingComponent { - await this._loadData(); - }); - this._loadingService.stop(); - } - - downloadItem(download: DownloadStatusWrapper) { + downloadItem(download: DownloadStatus) { this._loadingService.loadWhile(this.fileDownloadService.performDownload(download)); } - deleteItems(downloads?: DownloadStatusWrapper[]) { + deleteItems(downloads?: DownloadStatus[]) { this._loadingService.loadWhile(this._deleteItems(downloads)); } - private async _deleteItems(downloads?: DownloadStatusWrapper[]) { + private async _deleteItems(downloads?: DownloadStatus[]) { const storageIds = (downloads || this.listingService.selected).map(d => d.storageId); - await this._downloadControllerService.deleteDownload({ storageIds }).toPromise(); + await this.fileDownloadService.delete({ storageIds }).toPromise(); this.listingService.setSelected([]); await this._loadData(); } private async _loadData() { - await this.fileDownloadService.getDownloadStatus().toPromise(); - this.entitiesService.setEntities(this.fileDownloadService.downloads); + await this.fileDownloadService.loadAll().toPromise(); } } diff --git a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts b/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts index 56e9cf409..c7d14e425 100644 --- a/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts +++ b/apps/red-ui/src/app/components/user-profile/user-profile-screen.component.ts @@ -4,7 +4,6 @@ import { ProfileModel, UserService } from '@services/user.service'; import { PermissionsService } from '@services/permissions.service'; import { LanguageService } from '@i18n/language.service'; import { TranslateService } from '@ngx-translate/core'; -import { UserControllerService } from '@redaction/red-ui-http'; import { ConfigService } from '@services/config.service'; import { DomSanitizer } from '@angular/platform-browser'; import { languagesTranslations } from '../../translations/languages-translations'; @@ -27,7 +26,6 @@ export class UserProfileScreenComponent implements OnInit { private readonly _formBuilder: FormBuilder, private readonly _userService: UserService, private readonly _configService: ConfigService, - private readonly _userControllerService: UserControllerService, private readonly _languageService: LanguageService, private readonly _domSanitizer: DomSanitizer, private readonly _translateService: TranslateService, @@ -82,14 +80,14 @@ export class UserProfileScreenComponent implements OnInit { const value = this.formGroup.value as ProfileModel; delete value.language; - await this._userControllerService + await this._userService .updateMyProfile({ ...value, }) .toPromise(); await this._userService.loadCurrentUser(); - await this._userService.loadAllUsers(); + await this._userService.loadAll().toPromise(); } this._initializeForm(); diff --git a/apps/red-ui/src/app/modules/admin/admin.module.ts b/apps/red-ui/src/app/modules/admin/admin.module.ts index 81c5b1ad1..a75a79525 100644 --- a/apps/red-ui/src/app/modules/admin/admin.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin.module.ts @@ -39,6 +39,8 @@ import { UserDetailsComponent } from './dialogs/add-edit-user-dialog/user-detail import { AddEditDossierAttributeDialogComponent } from './dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component'; import { DossierAttributesListingScreenComponent } from './screens/dossier-attributes-listing/dossier-attributes-listing-screen.component'; import { TrashScreenComponent } from './screens/trash/trash-screen.component'; +import { AuditService } from './services/audit.service'; +import { DigitalSignatureService } from './services/digital-signature.service'; const dialogs = [ AddEditDossierTemplateDialogComponent, @@ -88,7 +90,7 @@ const components = [ @NgModule({ declarations: [...components], - providers: [AdminDialogService], + providers: [AdminDialogService, AuditService, DigitalSignatureService], imports: [CommonModule, SharedModule, AdminRoutingModule, NgxChartsModule, ColorPickerModule, MonacoEditorModule], }) export class AdminModule {} diff --git a/apps/red-ui/src/app/modules/admin/components/dossier-template-actions/dossier-template-actions.component.ts b/apps/red-ui/src/app/modules/admin/components/dossier-template-actions/dossier-template-actions.component.ts index 3657c3083..1cd7a31d1 100644 --- a/apps/red-ui/src/app/modules/admin/components/dossier-template-actions/dossier-template-actions.component.ts +++ b/apps/red-ui/src/app/modules/admin/components/dossier-template-actions/dossier-template-actions.component.ts @@ -2,7 +2,6 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; 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 { CircleButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; import { UserService } from '@services/user.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -18,7 +17,7 @@ export class DossierTemplateActionsComponent implements OnInit { readonly currentUser = this._userService.currentUser; @Input() dossierTemplateId: string; - @Output() loadDossierTemplatesData = new EventEmitter(); + @Output() readonly loadDossierTemplatesData = new EventEmitter(); constructor( private readonly _router: Router, @@ -26,9 +25,8 @@ export class DossierTemplateActionsComponent implements OnInit { private readonly _userService: UserService, private readonly _loadingService: LoadingService, private readonly _appStateService: AppStateService, - private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _dialogService: AdminDialogService, - private readonly _dossierTemplateControllerService: DossierTemplateControllerService, + private readonly _dossierTemplatesService: DossierTemplatesService, ) {} get dossierTemplate() { @@ -41,7 +39,7 @@ export class DossierTemplateActionsComponent implements OnInit { openEditDossierTemplateDialog($event: any) { this._dialogService.openDialog('addEditDossierTemplate', $event, this.dossierTemplate, () => { - this.loadDossierTemplatesData?.emit(); + this.loadDossierTemplatesData.emit(); }); } @@ -49,8 +47,8 @@ export class DossierTemplateActionsComponent implements OnInit { this._dialogService.openDialog('confirm', $event, null, async () => { this._loadingService.start(); - await this._dossierTemplateControllerService - .deleteDossierTemplates([this.dossierTemplateId]) + await this._dossierTemplatesService + .delete([this.dossierTemplateId]) .toPromise() .catch(error => { if (error.status === 409) { @@ -60,12 +58,11 @@ export class DossierTemplateActionsComponent implements OnInit { } this._loadingService.stop(); }); - await this._dossierTemplateControllerService.deleteDossierTemplates([this.dossierTemplateId]).toPromise(); await this._dossierTemplatesService.loadAll().toPromise(); await this._appStateService.loadDictionaryData(); await this._router.navigate(['main', 'admin']); this._loadingService.stop(); - this.loadDossierTemplatesData?.emit(); + this.loadDossierTemplatesData.emit(); }); } } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component.ts index 8b1094dfd..31da50fd9 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component.ts @@ -65,7 +65,7 @@ export class AddEditDossierAttributeDialogComponent extends AutoUnsubscribe impl ...this.dossierAttributeForm.getRawValue(), }; - this._dossierAttributesService.addOrUpdateConfig(attribute).subscribe( + this._dossierAttributesService.createOrUpdate(attribute).subscribe( () => { this.dialogRef.close(true); }, diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.ts index 21bbab6e9..23f18bc1f 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component.ts @@ -4,13 +4,12 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import * as moment from 'moment'; import { Moment } from 'moment'; -import { DossierTemplateControllerService, DownloadFileType, IDossierTemplate } from '@redaction/red-ui-http'; +import { DownloadFileType, IDossierTemplate } from '@redaction/red-ui-http'; import { applyIntervalConstraints } from '@utils/date-inputs-utils'; import { downloadTypesTranslations } from '../../../../translations/download-types-translations'; import { DossierTemplatesService } from '../../../dossier/services/dossier-templates.service'; @Component({ - selector: 'redaction-add-edit-dossier-template-dialog', templateUrl: './add-edit-dossier-template-dialog.component.html', styleUrls: ['./add-edit-dossier-template-dialog.component.scss'], }) @@ -31,7 +30,6 @@ export class AddEditDossierTemplateDialogComponent { private readonly _appStateService: AppStateService, private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _formBuilder: FormBuilder, - private readonly _dossierTemplateController: DossierTemplateControllerService, public dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) readonly dossierTemplate: IDossierTemplate, ) { @@ -99,7 +97,7 @@ export class AddEditDossierTemplateDialogComponent { validFrom: this.hasValidFrom ? this.dossierTemplateForm.get('validFrom').value : null, validTo: this.hasValidTo ? this.dossierTemplateForm.get('validTo').value : null, }; - await this._dossierTemplateController.createOrUpdateDossierTemplate(dossierTemplate).toPromise(); + await this._dossierTemplatesService.createOrUpdate(dossierTemplate).toPromise(); await this._dossierTemplatesService.loadAll().toPromise(); await this._appStateService.loadDictionaryData(); this.dialogRef.close(true); diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.ts index a27419d23..0740d4ad1 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/reset-password/reset-password.component.ts @@ -1,6 +1,5 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { FormBuilder, Validators } from '@angular/forms'; -import { UserControllerService } from '@redaction/red-ui-http'; import { UserService } from '@services/user.service'; import { LoadingService } from '@iqser/common-ui'; import { User } from '@models/user'; @@ -19,14 +18,13 @@ export class ResetPasswordComponent { constructor( private readonly _formBuilder: FormBuilder, - private readonly _userControllerService: UserControllerService, private readonly _userService: UserService, private readonly _loadingService: LoadingService, ) {} async save() { this._loadingService.start(); - await this._userControllerService + await this._userService .resetPassword( { password: this.passwordForm.get('temporaryPassword').value, diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts index 8a779d360..899bae8de 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-user-dialog/user-details/user-details.component.ts @@ -1,11 +1,11 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { UserControllerService } from '@redaction/red-ui-http'; import { AdminDialogService } from '../../../services/admin-dialog.service'; import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; import { rolesTranslations } from '../../../../../translations/roles-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { User } from '@models/user'; +import { UserService } from '@services/user.service'; @Component({ selector: 'redaction-user-details', @@ -29,7 +29,7 @@ export class UserDetailsComponent implements OnInit { private readonly _toaster: Toaster, private readonly _dialogService: AdminDialogService, private readonly _loadingService: LoadingService, - private readonly _userControllerService: UserControllerService, + private readonly _userService: UserService, ) {} get changed(): boolean { @@ -102,8 +102,8 @@ export class UserDetailsComponent implements OnInit { const userData = { ...this.userForm.getRawValue(), roles: this.activeRoles }; if (!this.user) { - await this._userControllerService - .createUser(userData) + await this._userService + .create(userData) .toPromise() .then(() => { this.closeDialog.emit(true); @@ -117,7 +117,7 @@ export class UserDetailsComponent implements OnInit { this._loadingService.stop(); }); } else { - await this._userControllerService.updateProfile(userData, this.user.id).toPromise(); + await this._userService.updateProfile(userData, this.user.id).toPromise(); this.closeDialog.emit(true); } } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component.ts index 984effd5f..0d07e6cc4 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component.ts @@ -1,10 +1,10 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { UserControllerService } from '@redaction/red-ui-http'; -import { LoadingService } from '@iqser/common-ui'; +import { List, LoadingService } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { User } from '@models/user'; import { DossiersService } from '../../../dossier/services/dossiers.service'; +import { UserService } from '@services/user.service'; @Component({ selector: 'redaction-confirm-delete-users-dialog', @@ -20,11 +20,11 @@ export class ConfirmDeleteUsersDialogComponent { dossiersCount: number; constructor( - private readonly _dossiersService: DossiersService, + private readonly _userService: UserService, private readonly _loadingService: LoadingService, - private readonly _userControllerService: UserControllerService, + private readonly _dossiersService: DossiersService, + @Inject(MAT_DIALOG_DATA) readonly users: List, readonly dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) readonly users: User[], ) { this.dossiersCount = this._dossiersService.all.filter(dw => { for (const user of this.users) { @@ -43,7 +43,7 @@ export class ConfirmDeleteUsersDialogComponent { async deleteUser() { if (this.valid) { this._loadingService.start(); - await this._userControllerService.deleteUsers(this.users.map(u => u.id)).toPromise(); + await this._userService.delete(this.users.map(u => u.id)).toPromise(); this.dialogRef.close(true); } else { this.showToast = true; diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html index 75474415d..6166ee55d 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html @@ -53,8 +53,8 @@ - -
+ +
@@ -66,7 +66,7 @@ @@ -97,8 +97,8 @@
- -
+ +
{{ log.message }}
@@ -108,7 +108,7 @@
- +
diff --git a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts index 6214e0bb5..2377207de 100644 --- a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts @@ -1,6 +1,6 @@ import { Component, forwardRef, Injector, OnDestroy, OnInit } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; -import { AuditControllerService, AuditResponse, AuditSearchRequest, IAudit } from '@redaction/red-ui-http'; +import { AuditResponse, AuditSearchRequest, IAudit } from '@redaction/red-ui-http'; import { Moment } from 'moment'; import { applyIntervalConstraints } from '@utils/date-inputs-utils'; import { DefaultListingServices, ListingComponent, LoadingService, TableColumnConfig } from '@iqser/common-ui'; @@ -8,6 +8,7 @@ import { auditCategoriesTranslations } from '../../translations/audit-categories import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { UserService } from '@services/user.service'; import { Audit } from '@models/audit.model'; +import { AuditService } from '../../services/audit.service'; const PAGE_SIZE = 50; @@ -41,7 +42,7 @@ export class AuditScreenComponent extends ListingComponent implements OnD protected readonly _injector: Injector, private readonly _formBuilder: FormBuilder, private readonly _loadingService: LoadingService, - private readonly _auditControllerService: AuditControllerService, + private readonly _auditService: AuditService, ) { super(_injector); this.filterForm = this._formBuilder.group({ @@ -102,8 +103,8 @@ export class AuditScreenComponent extends ListingComponent implements OnD to, }; - promises.push(this._auditControllerService.getAuditCategories().toPromise()); - promises.push(this._auditControllerService.searchAuditLog(logsRequestBody).toPromise()); + promises.push(this._auditService.getCategories().toPromise()); + promises.push(this._auditService.searchAuditLog(logsRequestBody).toPromise()); const data = await Promise.all(promises); this.categories = data[0].map(c => c.category); diff --git a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html index 5ede13e02..1fb70d6d1 100644 --- a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html @@ -25,8 +25,8 @@
- -
+ +
diff --git a/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html index 558a8ffb3..305353c0b 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html @@ -77,8 +77,8 @@
- -
+ +
diff --git a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts index e9b27de0e..728224faa 100644 --- a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts @@ -1,11 +1,12 @@ import { Component, OnDestroy } from '@angular/core'; -import { DigitalSignature, DigitalSignatureControllerService } from '@redaction/red-ui-http'; +import { DigitalSignature } from '@redaction/red-ui-http'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { lastIndexOfEnd } from '@utils/functions'; import { AutoUnsubscribe, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { UserService } from '@services/user.service'; import { RouterHistoryService } from '@services/router-history.service'; +import { DigitalSignatureService } from '../../services/digital-signature.service'; @Component({ selector: 'redaction-digital-signature-screen', @@ -27,7 +28,7 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribe implements private readonly _userService: UserService, private readonly _loadingService: LoadingService, readonly routerHistoryService: RouterHistoryService, - private readonly _digitalSignatureControllerService: DigitalSignatureControllerService, + private readonly _digitalSignatureService: DigitalSignatureService, ) { super(); this.loadDigitalSignatureAndInitializeForm(); @@ -45,8 +46,8 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribe implements digitalSignature.password = digitalSignature.keySecret; const observable = this.digitalSignatureExists - ? this._digitalSignatureControllerService.updateDigitalSignature(digitalSignature) - : this._digitalSignatureControllerService.saveDigitalSignature(digitalSignature); + ? this._digitalSignatureService.update(digitalSignature) + : this._digitalSignatureService.save(digitalSignature); this.addSubscription = observable.subscribe( () => { @@ -64,7 +65,7 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribe implements } removeDigitalSignature() { - this.addSubscription = this._digitalSignatureControllerService.deleteDigitalSignature().subscribe( + this.addSubscription = this._digitalSignatureService.delete().subscribe( () => { this.loadDigitalSignatureAndInitializeForm(); this._toaster.success(_('digital-signature-screen.action.delete-success')); @@ -88,8 +89,8 @@ export class DigitalSignatureScreenComponent extends AutoUnsubscribe implements loadDigitalSignatureAndInitializeForm() { this._loadingService.start(); - this.addSubscription = this._digitalSignatureControllerService - .getDigitalSignature() + this.addSubscription = this._digitalSignatureService + .getSignature() .subscribe( digitalSignature => { this.digitalSignatureExists = true; diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.html index 6a2c78c77..c10ed9f52 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.html @@ -64,8 +64,8 @@
- -
+ +
{{ attribute.label }}
diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts index 4726578ba..6f760eff9 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-attributes-listing/dossier-attributes-listing-screen.component.ts @@ -1,7 +1,8 @@ import { Component, forwardRef, Injector, OnInit } from '@angular/core'; import { CircleButtonTypes, - DefaultListingServices, + DefaultListingServicesTmp, + EntitiesService, IconButtonTypes, ListingComponent, LoadingService, @@ -22,7 +23,8 @@ import { DossierTemplatesService } from '../../../dossier/services/dossier-templ templateUrl: './dossier-attributes-listing-screen.component.html', styleUrls: ['./dossier-attributes-listing-screen.component.scss'], providers: [ - ...DefaultListingServices, + ...DefaultListingServicesTmp, + { provide: EntitiesService, useExisting: DossierAttributesService }, { provide: ListingComponent, useExisting: forwardRef(() => DossierAttributesListingScreenComponent) }, ], }) @@ -59,7 +61,7 @@ export class DossierAttributesListingScreenComponent extends ListingComponent { this._loadingService.start(); const ids = dossierAttribute ? [dossierAttribute.id] : this.listingService.selected.map(item => item.id); - await this._dossierAttributesService.deleteConfigs(ids); + await this._dossierAttributesService.delete(ids).toPromise(); this.listingService.setSelected([]); await this._loadData(); }); @@ -68,18 +70,14 @@ export class DossierAttributesListingScreenComponent extends ListingComponent this._loadData(), + this._dialogService.openDialog('addEditDossierAttribute', $event, { dossierAttribute, dossierTemplateId }, async () => + this._loadData(), ); } private async _loadData() { this._loadingService.start(); - const attributes = await this._dossierAttributesService.getConfig(); - this.entitiesService.setEntities(attributes); + await this._dossierAttributesService.loadAll().toPromise(); this._loadingService.stop(); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.html index 84aba15e9..6dd34eda0 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.html @@ -38,7 +38,7 @@ @@ -61,8 +61,8 @@
- -
+ +
{{ dossierTemplate.name }} @@ -76,7 +76,7 @@
- +
diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.ts index 90609213e..8172592dd 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-template-listing/dossier-templates-listing-screen.component.ts @@ -13,7 +13,6 @@ import { TableColumnConfig, Toaster, } from '@iqser/common-ui'; -import { DossierTemplateControllerService } from '@redaction/red-ui-http'; import { UserService } from '@services/user.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { RouterHistoryService } from '@services/router-history.service'; @@ -42,22 +41,21 @@ export class DossierTemplatesListingScreenComponent extends ListingComponent { - this.loadDossierTemplatesData(); + this.loadDossierTemplateStats(); }); } - private async _deleteTemplates(templateIds = this.listingService.selected.map(d => d.dossierTemplateId)) { - await this._dossierTemplateControllerService - .deleteDossierTemplates(templateIds) - .toPromise() - .catch(error => { - if (error.status === 409) { - this._toaster.error(_('dossier-templates-listing.error.conflict')); - } else { - this._toaster.error(_('dossier-templates-listing.error.generic')); - } - }); - this.listingService.setSelected([]); - await this._dossierTemplatesService.loadAll().toPromise(); - await this._appStateService.loadDictionaryData(); - this.loadDossierTemplatesData(); - } - - private _loadDossierTemplateStats() { + loadDossierTemplateStats() { this.entitiesService.all.forEach(rs => { const dictionaries = this._appStateService.dictionaryData[rs.dossierTemplateId]; if (dictionaries) { @@ -107,4 +83,21 @@ export class DossierTemplatesListingScreenComponent extends ListingComponent d.dossierTemplateId)) { + await this._dossierTemplatesService + .delete(templateIds) + .toPromise() + .catch(error => { + if (error.status === 409) { + this._toaster.error(_('dossier-templates-listing.error.conflict')); + } else { + this._toaster.error(_('dossier-templates-listing.error.generic')); + } + }); + this.listingService.setSelected([]); + await this._dossierTemplatesService.loadAll().toPromise(); + await this._appStateService.loadDictionaryData(); + this.loadDossierTemplateStats(); + } } diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html index b8e64640f..3d61c2211 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html @@ -74,8 +74,8 @@
- -
+ +
{{ attribute.label }}
diff --git a/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.html index f4d327ede..06bc796ac 100644 --- a/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.html @@ -41,7 +41,7 @@ -
+
{{ entity.dossierName }} @@ -63,7 +63,7 @@
- +
diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html index 4a52d84ad..f78e18ef5 100644 --- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html @@ -65,10 +65,10 @@ > - -
+ +
- +
{{ user.email || '-' }}
diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts index 63bcb3642..bb1715711 100644 --- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts @@ -1,19 +1,18 @@ -import { Component, forwardRef, Injector, OnInit, QueryList, ViewChildren } from '@angular/core'; +import { Component, forwardRef, Injector, OnInit } from '@angular/core'; import { UserService } from '@services/user.service'; -import { UserControllerService } from '@redaction/red-ui-http'; import { AdminDialogService } from '../../services/admin-dialog.service'; import { TranslateService } from '@ngx-translate/core'; import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component'; import { TranslateChartService } from '@services/translate-chart.service'; import { CircleButtonTypes, - DefaultListingServices, + DefaultListingServicesTmp, + EntitiesService, IconButtonTypes, ListingComponent, LoadingService, TableColumnConfig, } from '@iqser/common-ui'; -import { InitialsAvatarComponent } from '@shared/components/initials-avatar/initials-avatar.component'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { rolesTranslations } from '../../../../translations/roles-translations'; @@ -23,7 +22,14 @@ import { User } from '@models/user'; @Component({ templateUrl: './user-listing-screen.component.html', styleUrls: ['./user-listing-screen.component.scss'], - providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => UserListingScreenComponent) }], + providers: [ + ...DefaultListingServicesTmp, + { provide: EntitiesService, useExisting: UserService }, + { + provide: ListingComponent, + useExisting: forwardRef(() => UserListingScreenComponent), + }, + ], }) export class UserListingScreenComponent extends ListingComponent implements OnInit { readonly translations = rolesTranslations; @@ -40,8 +46,6 @@ export class UserListingScreenComponent extends ListingComponent implement ]; collapsedDetails = false; chartData: DoughnutChartConfig[] = []; - @ViewChildren(InitialsAvatarComponent) - private readonly _avatars: QueryList; constructor( readonly userService: UserService, @@ -49,7 +53,6 @@ export class UserListingScreenComponent extends ListingComponent implement private readonly _loadingService: LoadingService, private readonly _dialogService: AdminDialogService, private readonly _translateService: TranslateService, - private readonly _userControllerService: UserControllerService, private readonly _translateChartService: TranslateChartService, ) { super(_injector); @@ -87,9 +90,8 @@ export class UserListingScreenComponent extends ListingComponent implement async toggleActive(user: User) { this._loadingService.start(); const requestBody = { ...user, roles: user.isActive ? [] : ['RED_USER'] }; - await this._userControllerService.updateProfile(requestBody, user.id).toPromise(); + await this.userService.updateProfile(requestBody, user.id).toPromise(); await this._loadData(); - this._avatars.find(item => item.userId === user.id).detectChanges(); } bulkDelete() { @@ -97,7 +99,7 @@ export class UserListingScreenComponent extends ListingComponent implement } private async _loadData() { - this.entitiesService.setEntities(await this.userService.loadAllUsers()); + await this.userService.loadAll().toPromise(); this._computeStats(); this._loadingService.stop(); } diff --git a/apps/red-ui/src/app/modules/admin/services/audit.service.ts b/apps/red-ui/src/app/modules/admin/services/audit.service.ts new file mode 100644 index 000000000..44f7b1d07 --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/services/audit.service.ts @@ -0,0 +1,20 @@ +import { Injectable, Injector } from '@angular/core'; +import { GenericService, RequiredParam, Validate } from '@iqser/common-ui'; +import { AuditResponse, AuditSearchRequest, CategoryModel, IAudit } from '@redaction/red-ui-http'; +import { Observable } from 'rxjs'; + +@Injectable() +export class AuditService extends GenericService { + constructor(protected readonly _injector: Injector) { + super(_injector, 'audit'); + } + + getCategories(): Observable { + return super.getAll(`${this._defaultModelPath}/categories`); + } + + @Validate() + searchAuditLog(@RequiredParam() body: AuditSearchRequest): Observable { + return this._post(body, `${this._defaultModelPath}/search`); + } +} diff --git a/apps/red-ui/src/app/modules/admin/services/digital-signature.service.ts b/apps/red-ui/src/app/modules/admin/services/digital-signature.service.ts new file mode 100644 index 000000000..d1e86db45 --- /dev/null +++ b/apps/red-ui/src/app/modules/admin/services/digital-signature.service.ts @@ -0,0 +1,29 @@ +import { Injectable, Injector } from '@angular/core'; +import { GenericService, RequiredParam, Validate } from '@iqser/common-ui'; +import { DigitalSignature, DigitalSignatureViewModel } from '@redaction/red-ui-http'; +import { Observable } from 'rxjs'; + +@Injectable() +export class DigitalSignatureService extends GenericService { + constructor(protected readonly _injector: Injector) { + super(_injector, 'digital-signature'); + } + + @Validate() + update(@RequiredParam() body: DigitalSignatureViewModel): Observable { + return this._put(body); + } + + @Validate() + save(@RequiredParam() body: DigitalSignature): Observable { + return this._post(body); + } + + delete(): Observable { + return super.delete({}); + } + + getSignature(): Observable { + return super.getAll(); + } +} diff --git a/apps/red-ui/src/app/modules/dossier/components/team-members-manager/team-members-manager.component.html b/apps/red-ui/src/app/modules/dossier/components/team-members-manager/team-members-manager.component.html index 6802347a2..c2fa279d7 100644 --- a/apps/red-ui/src/app/modules/dossier/components/team-members-manager/team-members-manager.component.html +++ b/apps/red-ui/src/app/modules/dossier/components/team-members-manager/team-members-manager.component.html @@ -36,8 +36,8 @@

 
     
-            
+            
             
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.ts index a437871bc..34a5bc68d 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.ts +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component.ts @@ -68,7 +68,7 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa dossierAttributeId: attr.id, value: this.currentAttrValue(attr), })); - await this._dossierAttributesService.setValues(this.dossier, dossierAttributeList); + await this._dossierAttributesService.setAttributes(this.dossier, dossierAttributeList).toPromise(); await this._loadAttributes(); this.updateDossier.emit(); this._loadingService.stop(); @@ -134,7 +134,7 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa } private async _loadAttributes() { - this.attributes = await this._dossierAttributesService.getValues(this.dossier); + this.attributes = await this._dossierAttributesService.getWithValues(this.dossier); this.customAttributes = this.attributes.filter(attr => !this.isImage(attr)); this.imageAttributes = this.attributes.filter(attr => this.isImage(attr)); } diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.html b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.html index af2998b79..08ab20e7f 100644 --- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.html +++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component.html @@ -34,8 +34,8 @@ > - -
+ +
{{ file.filename }}
diff --git a/apps/red-ui/src/app/modules/dossier/dossiers.module.ts b/apps/red-ui/src/app/modules/dossier/dossiers.module.ts index 6a0653da1..b6fd63572 100644 --- a/apps/red-ui/src/app/modules/dossier/dossiers.module.ts +++ b/apps/red-ui/src/app/modules/dossier/dossiers.module.ts @@ -26,7 +26,6 @@ import { AnnotationProcessingService } from './services/annotation-processing.se import { EditDossierDialogComponent } from './dialogs/edit-dossier-dialog/edit-dossier-dialog.component'; import { EditDossierGeneralInfoComponent } from './dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component'; import { EditDossierDownloadPackageComponent } from './dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component'; -import { UserPreferenceControllerService } from '@redaction/red-ui-http'; import { EditDossierDictionaryComponent } from './dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component'; import { EditDossierTeamMembersComponent } from './dialogs/edit-dossier-dialog/team-members/edit-dossier-team-members.component'; import { TeamMembersManagerComponent } from './components/team-members-manager/team-members-manager.component'; @@ -85,7 +84,6 @@ const services = [ PdfViewerDataService, AnnotationDrawService, AnnotationProcessingService, - UserPreferenceControllerService, ]; @NgModule({ diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html index 0444ba767..ee2d64bf2 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html @@ -15,7 +15,7 @@
- + { this.calculateChartConfig(); @@ -75,7 +75,7 @@ export class DossierDetailsComponent implements OnInit { } async assignOwner(user: User | string) { - this.owner = typeof user === 'string' ? this._userService.getRedUserById(user) : user; + this.owner = typeof user === 'string' ? this._userService.find(user) : user; const activeDossier = this.dossiersService.activeDossier; const dossierRequest: DossierRequest = { ...activeDossier, dossierId: activeDossier.dossierId, ownerId: this.owner.id }; await this.dossiersService.createOrUpdate(dossierRequest).toPromise(); diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/table-item/table-item.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/table-item/table-item.component.html index 0901befe5..ccb7f4a9a 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/table-item/table-item.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/table-item/table-item.component.html @@ -34,7 +34,7 @@
- +
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html index d8fddddee..32bc35237 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html @@ -121,8 +121,8 @@ > - -
+ +
@@ -131,7 +131,7 @@
- +
- -
+ +
{{ file.numberOfPages }}
- {{ file.excludedPagesCount }} + {{ file.excludedPages.length }}
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts index 5d631c526..d359af029 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts @@ -165,7 +165,7 @@ export class DossierOverviewScreenComponent extends ListingComponent imple .pipe(tap(index => (this._lastScrolledIndex = index))) .subscribe(); - this.dossierAttributes = await this._dossierAttributesService.getValues(this.currentDossier); + this.dossierAttributes = await this._dossierAttributesService.getWithValues(this.currentDossier); } catch (e) { console.log('Error from dossier overview screen: ', e); } finally { diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.html index 352e0354e..8bc85208b 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/table-item/table-item.component.html @@ -5,7 +5,7 @@
- +
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html index ef520987f..259a60597 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html @@ -42,7 +42,7 @@ @@ -83,7 +83,7 @@
- +
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts index b7f8b6f15..668d0829a 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts @@ -28,7 +28,7 @@ import { PermissionsService } from '@services/permissions.service'; import { timer } from 'rxjs'; import { UserPreferenceService } from '@services/user-preference.service'; import { UserService } from '@services/user.service'; -import { FileManagementControllerService, FileStatus, List, UserPreferenceControllerService } from '@redaction/red-ui-http'; +import { FileManagementControllerService, FileStatus, List } from '@redaction/red-ui-http'; import { PdfViewerDataService } from '../../services/pdf-viewer-data.service'; import { download } from '@utils/file-download-utils'; import { ViewMode } from '@models/file/view-mode'; @@ -88,7 +88,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni readonly permissionsService: PermissionsService, readonly userPreferenceService: UserPreferenceService, readonly userService: UserService, - private readonly _userPreferenceControllerService: UserPreferenceControllerService, private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _activatedRoute: ActivatedRoute, private readonly _dialogService: DossiersDialogService, diff --git a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html index 65076d3c2..e261dcdbb 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/search-screen/search-screen.component.html @@ -21,8 +21,8 @@
- -
+ +
this.all), ); } + + delete(body: List): Observable { + return super.delete(body, `${this._defaultModelPath}/delete`); + } + + @Validate() + createOrUpdate(@RequiredParam() body: IDossierTemplate) { + return this._post(body); + } } diff --git a/apps/red-ui/src/app/modules/shared/components/assign-user-dropdown/assign-user-dropdown.component.html b/apps/red-ui/src/app/modules/shared/components/assign-user-dropdown/assign-user-dropdown.component.html index 78afc5948..d4c0d2907 100644 --- a/apps/red-ui/src/app/modules/shared/components/assign-user-dropdown/assign-user-dropdown.component.html +++ b/apps/red-ui/src/app/modules/shared/components/assign-user-dropdown/assign-user-dropdown.component.html @@ -27,5 +27,5 @@
- + diff --git a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts index c03b703ce..96faf040d 100644 --- a/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/buttons/file-download-btn/file-download-btn.component.ts @@ -45,7 +45,10 @@ export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestr downloadFiles($event: MouseEvent) { $event.stopPropagation(); this.addSubscription = this._fileDownloadService - .downloadFiles(this.files, this.dossier) + .downloadFiles( + this.files.map(f => f.fileId), + this.dossier.dossierId, + ) .subscribe(() => this._toaster.info(_('download-status.queued'))); } } diff --git a/apps/red-ui/src/app/modules/shared/components/buttons/user-button/user-button.component.html b/apps/red-ui/src/app/modules/shared/components/buttons/user-button/user-button.component.html index 205781407..82028be44 100644 --- a/apps/red-ui/src/app/modules/shared/components/buttons/user-button/user-button.component.html +++ b/apps/red-ui/src/app/modules/shared/components/buttons/user-button/user-button.component.html @@ -1,5 +1,5 @@
diff --git a/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.html b/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.html index 0db9c6c2b..b2f2ed660 100644 --- a/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.html +++ b/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.html @@ -1,12 +1,12 @@ -
+
- {{ initials }} + {{ _user | name: { showInitials: true, defaultValue: ('initials-avatar.unassigned' | translate) } }}
- {{ displayName || ('initials-avatar.unassigned' | translate) }} + {{ userName }}
diff --git a/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts b/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts index fa46e8c97..efe4e086b 100644 --- a/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts @@ -1,8 +1,9 @@ -import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy } from '@angular/core'; +import { ChangeDetectionStrategy, Component, Input, OnChanges, OnDestroy } from '@angular/core'; import { UserService } from '@services/user.service'; -import { TranslateService } from '@ngx-translate/core'; import { AutoUnsubscribe } from '@iqser/common-ui'; import { User } from '@models/user'; +import { TranslateService } from '@ngx-translate/core'; +import { NamePipeOptions } from '@shared/pipes/name.pipe'; @Component({ selector: 'redaction-initials-avatar', @@ -11,39 +12,47 @@ import { User } from '@models/user'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class InitialsAvatarComponent extends AutoUnsubscribe implements OnChanges, OnDestroy { - @Input() userId: string; @Input() color = 'lightgray'; @Input() size: 'small' | 'large' = 'small'; @Input() withName = false; @Input() showYou = false; @Input() tooltipPosition: 'below' | 'above' = 'above'; - - displayName: string; - initials: string; colorClass: string; - user: User; - constructor( - private readonly _userService: UserService, - private readonly _translateService: TranslateService, - private readonly _changeDetectorRef: ChangeDetectorRef, - ) { + readonly namePipeOptions: NamePipeOptions = { + showYou: this.showYou, + defaultValue: this._translateService.instant('initials-avatar.unassigned'), + }; + + constructor(private readonly _userService: UserService, private readonly _translateService: TranslateService) { super(); - this.addSubscription = _userService.usersReloaded$.subscribe(() => { - this.detectChanges(); - }); + } + + _user: User; + + @Input() + set user(user: User | string) { + if (typeof user === 'string') { + this._user = this._userService.find(user); + } else { + this._user = user; + } } get hasBorder(): boolean { - return !!this.user && !this._isCurrentUser && this.user.isManager; + return !!this._user && !this.isCurrentUser && this._user.isManager; } get disabled(): boolean { - return this.user && !this.user.isActive; + return this._user && !this._user.isActive; + } + + get isCurrentUser(): boolean { + return this._userService.currentUser.id === this._user?.id; } private get _colorClass() { - if (this._isCurrentUser) { + if (this.isCurrentUser) { return 'primary-white'; } if (this.disabled) { @@ -56,44 +65,13 @@ export class InitialsAvatarComponent extends AutoUnsubscribe implements OnChange return `${this.color}-dark`; } - private get _isCurrentUser(): boolean { - return this._userService.currentUser.id === this.user?.id; - } - ngOnChanges(): void { - const isSystemUser = this.userId?.toLowerCase() === 'system'; + const isSystemUser = this._user?.id?.toLowerCase() === 'system'; if (isSystemUser) { - this.displayName = 'System'; - this.initials = 'SY'; this.colorClass = 'primary-white primary'; return; } - this.user = this._userService.getUserById(this.userId); - this.displayName = this._userService.getNameForId(this.userId); - - this.initials = this._getInitials(); this.colorClass = this._colorClass; - - if (this.showYou && this._isCurrentUser) { - this.displayName += ` (${this._translateService.instant('initials-avatar.you')})`; - } - } - - detectChanges(): void { - this.ngOnChanges(); - this._changeDetectorRef.detectChanges(); - } - - private _getInitials(): string { - if (!this.displayName) { - return '?'; - } - - return this.displayName - .split(' ') - .filter((value, idx) => idx < 2 && value !== ' ') - .map(str => str[0]) - .join(''); } } diff --git a/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.html b/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.html index 08e777a4a..61d9f63e8 100644 --- a/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.html +++ b/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.html @@ -6,7 +6,7 @@ [class.large-spacing]="largeSpacing" class="member" > - +
diff --git a/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts b/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts index 9b1da8a12..13da6ecb4 100644 --- a/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts +++ b/apps/red-ui/src/app/modules/shared/pipes/name.pipe.ts @@ -3,16 +3,61 @@ import { UserService } from '@services/user.service'; import { TranslateService } from '@ngx-translate/core'; import { User } from '@models/user'; +function getInitials(name: string) { + if (name.toLowerCase() === 'system') { + return 'SY'; + } + + const splittedName = name.split(' ').filter(value => value !== ' ' && value !== ''); + return splittedName + .filter((value, index) => index < 2) + .map(str => str[0]) + .join(''); +} + +function isSystemUser(user: User | string) { + const userId = typeof user === 'string' ? user : user.id; + return userId.toLowerCase() === 'system'; +} + +export interface NamePipeOptions { + showYou?: boolean; + showInitials?: boolean; + defaultValue?: string; +} + @Pipe({ name: 'name', }) export class NamePipe implements PipeTransform { + private readonly _defaultOptions: NamePipeOptions = { defaultValue: this._translateService.instant('unknown') }; + constructor(private readonly _userService: UserService, private readonly _translateService: TranslateService) {} - transform(value: User | string): string { - if (typeof value === 'string') { - return this._userService.getNameForId(value) || this._translateService.instant('unknown'); + transform(value?: User | string, options = this._defaultOptions): string { + let name; + if (!value || !isSystemUser(value)) { + name = this._getName(value) || options?.defaultValue; + } else { + name = 'System'; } - return value.name; + + if (options?.showYou && this._isCurrentUser(value)) { + name = `${name} (${this._translateService.instant('initials-avatar.you')})`; + } + + return options?.showInitials ? getInitials(name) : name; + } + + private _isCurrentUser(user: User | string): boolean { + const userId = typeof user === 'string' ? user : user.id; + return this._userService.currentUser.id === userId; + } + + private _getName(user: User | string): string | undefined { + if (!user) { + return undefined; + } + return typeof user === 'string' ? this._userService.getNameForId(user) : user.name; } } diff --git a/apps/red-ui/src/app/modules/shared/services/controller-wrappers/dossier-attributes.service.ts b/apps/red-ui/src/app/modules/shared/services/controller-wrappers/dossier-attributes.service.ts index b03e035d2..2ea94ca2a 100644 --- a/apps/red-ui/src/app/modules/shared/services/controller-wrappers/dossier-attributes.service.ts +++ b/apps/red-ui/src/app/modules/shared/services/controller-wrappers/dossier-attributes.service.ts @@ -1,50 +1,67 @@ -import { Injectable } from '@angular/core'; -import { DossierAttribute, DossierAttributes, DossierAttributesControllerService, IDossierAttributeConfig } from '@redaction/red-ui-http'; +import { Injectable, Injector } from '@angular/core'; +import { DossierAttribute, DossierAttributes, DossierAttributesConfig, IDossierAttributeConfig } from '@redaction/red-ui-http'; import { Dossier } from '@state/model/dossier'; import { DossierAttributeWithValue } from '@models/dossier-attributes.model'; import { Observable } from 'rxjs'; import { DossierAttributeConfig } from '@state/model/dossier-attribute-config'; import { DossierTemplatesService } from '../../../dossier/services/dossier-templates.service'; +import { EntitiesService, List, mapEach, RequiredParam, Validate } from '@iqser/common-ui'; +import { map, tap } from 'rxjs/operators'; @Injectable({ providedIn: 'root', }) -export class DossierAttributesService { - constructor( - private readonly _dossierAttributesControllerService: DossierAttributesControllerService, - private readonly _dossierTemplatesService: DossierTemplatesService, - ) {} +export class DossierAttributesService extends EntitiesService { + constructor(private readonly _dossierTemplatesService: DossierTemplatesService, protected readonly _injector: Injector) { + super(_injector, DossierAttributeConfig, 'dossier-attributes'); + } - async getValues(dossier: Dossier): Promise { - const attributes = await this._dossierAttributesControllerService.getDossierAttributes(dossier.id).toPromise(); - const attributesConfig = await this._dossierAttributesControllerService - .getDossierAttributesConfig(dossier.dossierTemplateId) - .toPromise(); + async getWithValues(dossier: Dossier): Promise { + const attributes = await this.getAttributes(dossier.id).toPromise(); + const attributesConfig = await this.getConfig(dossier.dossierTemplateId).toPromise(); - return attributesConfig.dossierAttributeConfigs.map(config => ({ + return attributesConfig.map(config => ({ ...config, - value: attributes.dossierAttributeList.find(attr => attr.dossierAttributeConfigId === config.id)?.value, + value: attributes.find(attr => attr.dossierAttributeConfigId === config.id)?.value, })); } - setValues(dossier: Dossier, dossierAttributeList: DossierAttribute[]): Promise { - return this._dossierAttributesControllerService.setDossierAttributes({ dossierAttributeList }, dossier.id).toPromise(); + @Validate() + setAttributes( + @RequiredParam() dossier: Dossier, + @RequiredParam() dossierAttributeList: List, + ): Observable { + return this._post({ dossierAttributeList }, `${this._defaultModelPath}/set/${dossier.id}`); } - deleteConfigs(ids: string[], dossierTemplateId = this._dossierTemplatesService.activeDossierTemplateId): Promise { - return this._dossierAttributesControllerService.deleteDossierAttributesConfig(ids, dossierTemplateId).toPromise(); + @Validate() + delete(@RequiredParam() ids: List, dossierTemplateId = this._dossierTemplatesService.activeDossierTemplateId): Observable { + return this._post(ids, `${this._defaultModelPath}/config/delete/${dossierTemplateId}`); } - async getConfig(dossierTemplateId = this._dossierTemplatesService.activeDossierTemplateId): Promise { - const config$ = this._dossierAttributesControllerService.getDossierAttributesConfig(dossierTemplateId); - const result = (await config$.toPromise())?.dossierAttributeConfigs || []; - return result.map(item => new DossierAttributeConfig(item)); + loadAll(dossierTemplateId = this._dossierTemplatesService.activeDossierTemplateId): Observable { + return this.getConfig(dossierTemplateId).pipe( + map(entities => entities ?? []), + mapEach(entity => new DossierAttributeConfig(entity)), + tap(entities => this.setEntities(entities)), + ); } - addOrUpdateConfig( - attribute: IDossierAttributeConfig, + @Validate() + createOrUpdate( + @RequiredParam() attributeConfig: IDossierAttributeConfig, dossierTemplateId = this._dossierTemplatesService.activeDossierTemplateId, ): Observable { - return this._dossierAttributesControllerService.addOrUpdateDossierAttributesConfig(attribute, dossierTemplateId); + return this._post(attributeConfig, `${this._defaultModelPath}/config/${dossierTemplateId}`); + } + + @Validate() + getConfig(@RequiredParam() dossierTemplateId: string): Observable> { + return this._getOne(['config', dossierTemplateId]).pipe(map(res => res.dossierAttributeConfigs)); + } + + @Validate() + getAttributes(@RequiredParam() dossierId: string): Observable> { + return this._getOne([dossierId]).pipe(map(res => res.dossierAttributeList)); } } diff --git a/apps/red-ui/src/app/modules/upload-download/model/download-status.ts b/apps/red-ui/src/app/modules/upload-download/model/download-status.ts new file mode 100644 index 000000000..7dec1bd37 --- /dev/null +++ b/apps/red-ui/src/app/modules/upload-download/model/download-status.ts @@ -0,0 +1,50 @@ +import { DownloadFileType, DownloadStatusType, IDownloadStatus, List } from '@redaction/red-ui-http'; +import { IListable } from '@iqser/common-ui'; + +export class DownloadStatus implements IDownloadStatus, IListable { + readonly creationDate?: string; + readonly dossierId?: string; + readonly downloadFileTypes?: List; + readonly fileIds?: List; + readonly fileSize?: number; + readonly filename?: string; + readonly lastDownload?: string; + readonly mimeType?: string; + readonly status?: DownloadStatusType; + readonly storageId?: string; + readonly userId?: string; + readonly size?: string; + inProgress: boolean; + + constructor(downloadStatus: IDownloadStatus) { + this.creationDate = downloadStatus.creationDate; + this.dossierId = downloadStatus.dossierId; + this.downloadFileTypes = downloadStatus.downloadFileTypes; + this.fileIds = downloadStatus.fileIds; + this.fileSize = downloadStatus.fileSize; + this.filename = downloadStatus.filename; + this.lastDownload = downloadStatus.lastDownload; + this.mimeType = downloadStatus.mimeType; + this.status = downloadStatus.status; + this.storageId = downloadStatus.storageId; + this.userId = downloadStatus.userId; + this.size = this._size; + } + + get id() { + return this.storageId; + } + + get searchKey(): string { + return this.storageId; + } + + get isReady() { + return this.status === 'READY'; + } + + private get _size() { + const i = this.fileSize === 0 ? 0 : Math.floor(Math.log(this.fileSize) / Math.log(1024)); + return (this.fileSize / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; + } +} diff --git a/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts b/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts deleted file mode 100644 index d81e5f778..000000000 --- a/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { DownloadStatus } from '@redaction/red-ui-http'; -import { IListable } from '@iqser/common-ui'; - -export class DownloadStatusWrapper implements IListable { - inProgress: boolean; - - constructor(private _downloadStatus: DownloadStatus) {} - - get id() { - return this.storageId; - } - - get searchKey(): string { - return this.storageId; - } - - get size() { - const i = this._downloadStatus.fileSize === 0 ? 0 : Math.floor(Math.log(this._downloadStatus.fileSize) / Math.log(1024)); - return (this._downloadStatus.fileSize / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; - } - - get creationDate() { - return this._downloadStatus.creationDate; - } - - get filename() { - return this._downloadStatus.filename; - } - - get lastDownload() { - return this._downloadStatus.lastDownload; - } - - get mimeType() { - return this._downloadStatus.mimeType; - } - - get dossierId() { - return this._downloadStatus.dossierId; - } - - get isReady() { - return this._downloadStatus.status === 'READY'; - } - - get status() { - return this._downloadStatus.status; - } - - get storageId() { - return this._downloadStatus.storageId; - } -} diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts index 91bb55e48..205ac900a 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts @@ -1,59 +1,57 @@ -import { ApplicationRef, Injectable } from '@angular/core'; -import { DownloadControllerService, FileManagementControllerService } from '@redaction/red-ui-http'; +import { Injectable, Injector } from '@angular/core'; +import { + DownloadResponse, + DownloadStatusResponse, + IDownloadStatus, + PrepareDownloadRequest, + RemoveDownloadRequest, +} from '@redaction/red-ui-http'; import { interval, Observable } from 'rxjs'; import { ConfigService } from '@services/config.service'; -import { TranslateService } from '@ngx-translate/core'; -import { Dossier } from '@state/model/dossier'; -import { File } from '@models/file/file'; -import { mergeMap, tap } from 'rxjs/operators'; -import { DownloadStatusWrapper } from '../model/download-status.wrapper'; -import { AppStateService } from '@state/app-state.service'; +import { map, mergeMap, tap } from 'rxjs/operators'; +import { DownloadStatus } from '../model/download-status'; import { KeycloakService } from 'keycloak-angular'; import { UserService } from '@services/user.service'; -import { List } from '@iqser/common-ui'; +import { EntitiesService, List, RequiredParam, Validate } from '@iqser/common-ui'; @Injectable() -export class FileDownloadService { - downloads: DownloadStatusWrapper[] = []; - - hasPendingDownloads; +export class FileDownloadService extends EntitiesService { + hasPendingDownloads = false; constructor( private readonly _userService: UserService, - private readonly _applicationRef: ApplicationRef, private readonly _keycloakService: KeycloakService, - private readonly _appStateService: AppStateService, - private readonly _translateService: TranslateService, private readonly _configService: ConfigService, - private readonly _downloadControllerService: DownloadControllerService, - private readonly _fileManagementControllerService: FileManagementControllerService, + protected readonly _injector: Injector, ) { + super(_injector, DownloadStatus, 'async/download'); interval(5000).subscribe(() => { if (_userService.currentUser.isUser) { - this.getDownloadStatus().subscribe(() => {}); + this.loadAll().subscribe(() => {}); } }); } - downloadFiles(files: List, dossier: Dossier): Observable { - return this._downloadControllerService - .prepareDownload({ - fileIds: files.map(f => f.fileId), - dossierId: dossier.id, - }) - .pipe(mergeMap(() => this.getDownloadStatus())); + downloadFiles(fileIds: List, dossierId: string): Observable { + return this.prepareDownload({ + fileIds, + dossierId, + }).pipe(mergeMap(() => this.loadAll())); } - getDownloadStatus() { - return this._downloadControllerService.getDownloadStatus().pipe( - tap(statusResponse => { - this.downloads = statusResponse.downloadStatus.map(d => new DownloadStatusWrapper(d)); - this.hasPendingDownloads = !!this.downloads.find(f => !f.lastDownload && f.isReady); - }), + loadAll(): Observable { + return this.getStatuses().pipe( + map(entities => entities.map(entity => new DownloadStatus(entity))), + tap(entities => this.setEntities(entities)), + tap(() => (this.hasPendingDownloads = !!this.all.find(f => !f.lastDownload && f.isReady))), ); } - async performDownload(status: DownloadStatusWrapper) { + getStatuses(): Observable { + return super._getOne(['status']).pipe(map(res => res.downloadStatus)); + } + + async performDownload(status: DownloadStatus) { const token = await this._keycloakService.getToken(); const anchor = document.createElement('a'); anchor.href = `${this._configService.values.API_URL}/async/download?access_token=${encodeURIComponent( @@ -66,4 +64,14 @@ export class FileDownloadService { anchor.click(); document.body.removeChild(anchor); } + + @Validate() + prepareDownload(@RequiredParam() body: PrepareDownloadRequest): Observable { + return this._post(body, `${this._defaultModelPath}/prepare`); + } + + @Validate() + delete(@RequiredParam() body: RemoveDownloadRequest): Observable { + return super._post(body, `${this._defaultModelPath}/delete`); + } } diff --git a/apps/red-ui/src/app/services/user-preference.service.ts b/apps/red-ui/src/app/services/user-preference.service.ts index 4dbeda9ea..4c918615f 100644 --- a/apps/red-ui/src/app/services/user-preference.service.ts +++ b/apps/red-ui/src/app/services/user-preference.service.ts @@ -1,15 +1,15 @@ -import { Injectable } from '@angular/core'; -import { UserPreferenceControllerService } from '@redaction/red-ui-http'; +import { Injectable, Injector } from '@angular/core'; +import { List } from '@redaction/red-ui-http'; +import { GenericService, RequiredParam, Validate } from '@iqser/common-ui'; -interface UserAttributes { - [p: string]: string[]; -} +type UserAttributes = Record; @Injectable({ providedIn: 'root', }) -export class UserPreferenceService { - constructor(private readonly _userPreferenceControllerService: UserPreferenceControllerService) { +export class UserPreferenceService extends GenericService { + constructor(protected readonly _injector: Injector) { + super(_injector, 'attributes'); this.reload(); } @@ -35,7 +35,7 @@ export class UserPreferenceService { async saveLastOpenedFileForDossier(dossierId: string, fileId: string): Promise { const key = `Dossier-Recent-${dossierId}`; this.userAttributes[key] = [fileId]; - await this._userPreferenceControllerService.savePreferences([fileId], key).toPromise(); + await this.savePreferences([fileId], key).toPromise(); } toggleDevFeatures(): void { @@ -44,11 +44,15 @@ export class UserPreferenceService { } reload(): void { - this._userPreferenceControllerService - .getAllUserAttributes() + this.getAll() .toPromise() .then(attributes => { this._userAttributes = attributes ?? {}; }); } + + @Validate() + savePreferences(@RequiredParam() body: List, @RequiredParam() key: string) { + return this._put(body, `${this._defaultModelPath}/${key}`); + } } diff --git a/apps/red-ui/src/app/services/user.service.ts b/apps/red-ui/src/app/services/user.service.ts index 608030d7f..fa84aec68 100644 --- a/apps/red-ui/src/app/services/user.service.ts +++ b/apps/red-ui/src/app/services/user.service.ts @@ -1,11 +1,13 @@ -import { Inject, Injectable } from '@angular/core'; +import { Inject, Injectable, Injector } from '@angular/core'; import { KeycloakService } from 'keycloak-angular'; import jwt_decode from 'jwt-decode'; -import { IUser, UserControllerService } from '@redaction/red-ui-http'; +import { CreateUserRequest, IUser, ResetPasswordRequest, UpdateMyProfileRequest, UpdateProfileRequest } from '@redaction/red-ui-http'; import { wipeCaches } from '@redaction/red-cache'; import { BASE_HREF } from '../tokens'; -import { Subject } from 'rxjs'; +import { Observable } from 'rxjs'; import { User } from '@models/user'; +import { EntitiesService, List, mapEach, QueryParam, RequiredParam, Validate } from '@iqser/common-ui'; +import { tap } from 'rxjs/operators'; export interface ProfileModel { username?: string; @@ -18,16 +20,14 @@ export interface ProfileModel { @Injectable({ providedIn: 'root', }) -export class UserService { - usersReloaded$ = new Subject(); - private _allUsers: User[]; - private _allRedUsers: User[]; - +export class UserService extends EntitiesService { constructor( + protected readonly _injector: Injector, @Inject(BASE_HREF) private readonly _baseHref: string, private readonly _keycloakService: KeycloakService, - private readonly _userControllerService: UserControllerService, - ) {} + ) { + super(_injector, User, 'user'); + } private _currentUser: User; @@ -36,11 +36,11 @@ export class UserService { } get managerUsers(): User[] { - return this._allRedUsers.filter(user => user.isManager); + return this.all.filter(user => user.isManager); } get eligibleUsers(): User[] { - return this._allRedUsers.filter(user => user.isUser || user.isManager); + return this.all.filter(user => user.isUser || user.isManager); } logout() { @@ -48,23 +48,13 @@ export class UserService { this._keycloakService.logout(window.location.origin + this._baseHref).then(); } - async loadUsersIfNecessary() { - if (!this._allRedUsers) { - await this.loadAllUsers(); - } - } + loadAll() { + const all$ = this._currentUser.isUserAdmin ? this.getUsers() : this.getUsers(true); - async loadAllUsers() { - let allUsers: IUser[]; - if (this._currentUser.isUserAdmin) { - allUsers = await this._userControllerService.getAllUsers().toPromise(); - } else { - allUsers = await this._userControllerService.getUsers().toPromise(); - } - this._allUsers = allUsers.map(user => new User(user, user.roles, user.userId)); - this._allRedUsers = this._allUsers.filter(user => user.hasAnyREDRoles); - this.usersReloaded$.next(); - return this._allUsers; + return all$.pipe( + mapEach(user => new User(user, user.roles, user.userId)), + tap(users => this.setEntities(users)), + ); } async loadCurrentUser() { @@ -74,16 +64,8 @@ export class UserService { this._currentUser = new User(await this._keycloakService.loadUserProfile(true), this._keycloakService.getUserRoles(true), userId); } - getRedUserById(id: string) { - return this._allRedUsers.find(u => u.id === id); - } - - getUserById(id: string) { - return this._allUsers ? this._allUsers.find(u => u.id === id) : this.getRedUserById(id); - } - getNameForId(userId: string): string | undefined { - return this.getUserById(userId)?.name; + return this.find(userId)?.name; } hasAnyRole(requiredRoles: string[], user = this._currentUser): boolean { @@ -99,4 +81,34 @@ export class UserService { return true; } + + getUsers(onlyRed = false, refreshCache = false): Observable { + const url = onlyRed ? `${this._defaultModelPath}/red` : this._defaultModelPath; + return super.getAll(url, [{ key: 'refreshCache', value: refreshCache }]); + } + + @Validate() + updateProfile(@RequiredParam() body: UpdateProfileRequest, @RequiredParam() userId: string) { + return this._post(body, `${this._defaultModelPath}/profile/${userId}`); + } + + @Validate() + updateMyProfile(@RequiredParam() body: UpdateMyProfileRequest) { + return this._post(body, `${this._defaultModelPath}/my-profile`); + } + + @Validate() + resetPassword(@RequiredParam() body: ResetPasswordRequest, @RequiredParam() userId: string) { + return this._post(body, `${this._defaultModelPath}/${userId}/reset-password`); + } + + @Validate() + create(@RequiredParam() body: CreateUserRequest) { + return this._post(body); + } + + delete(userIds: List) { + const queryParams = userIds.map(userId => ({ key: 'userId', value: userId })); + return super.delete(userIds, this._defaultModelPath, queryParams); + } } diff --git a/apps/red-ui/src/app/state/app-state.guard.ts b/apps/red-ui/src/app/state/app-state.guard.ts index 0a302acad..f2913b3bd 100644 --- a/apps/red-ui/src/app/state/app-state.guard.ts +++ b/apps/red-ui/src/app/state/app-state.guard.ts @@ -19,11 +19,11 @@ export class AppStateGuard implements CanActivate { async canActivate(route: ActivatedRouteSnapshot): Promise { if (this._userService.currentUser.isUserAdmin) { - await this._userService.loadUsersIfNecessary(); + await this._userService.loadAllIfEmpty(); } if (this._userService.currentUser.isUser || this._userService.currentUser.isAdmin) { - await this._userService.loadUsersIfNecessary(); + await this._userService.loadAllIfEmpty(); await this._dossierTemplatesService.loadAllIfEmpty(); await this._appStateService.loadDictionaryDataIfNecessary(); } diff --git a/libs/common-ui b/libs/common-ui index 4e84610f6..c715f73fd 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 4e84610f65c8993d9725af62188e3578e9a27e8b +Subproject commit c715f73fd3e0b4a70efb60995929877eaa2e8d11 diff --git a/libs/red-ui-http/src/lib/api.module.ts b/libs/red-ui-http/src/lib/api.module.ts index f7a22a5bb..5ff95bf33 100644 --- a/libs/red-ui-http/src/lib/api.module.ts +++ b/libs/red-ui-http/src/lib/api.module.ts @@ -1,12 +1,6 @@ import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core'; import { Configuration } from './configuration'; import { HttpClient } from '@angular/common/http'; - -import { AuditControllerService } from './api/auditController.service'; -import { DigitalSignatureControllerService } from './api/digitalSignatureController.service'; -import { DossierAttributesControllerService } from './api/dossierAttributesController.service'; -import { DossierTemplateControllerService } from './api/dossierTemplateController.service'; -import { DownloadControllerService } from './api/downloadController.service'; import { FileManagementControllerService } from './api/fileManagementController.service'; import { GeneralSettingsControllerService } from './api/generalSettingsController.service'; import { InfoControllerService } from './api/infoController.service'; @@ -19,8 +13,6 @@ import { ReportTemplateControllerService } from './api/reportTemplateController. import { RulesControllerService } from './api/rulesController.service'; import { SmtpConfigurationControllerService } from './api/smtpConfigurationController.service'; import { UploadControllerService } from './api/uploadController.service'; -import { UserControllerService } from './api/userController.service'; -import { UserPreferenceControllerService } from './api/userPreferenceController.service'; import { VersionsControllerService } from './api/versionsController.service'; import { ViewedPagesControllerService } from './api/viewedPagesController.service'; import { WatermarkControllerService } from './api/watermarkController.service'; @@ -33,11 +25,6 @@ import { StatusReportControllerService } from './api/statusReportController.serv declarations: [], exports: [], providers: [ - AuditControllerService, - DigitalSignatureControllerService, - DossierAttributesControllerService, - DossierTemplateControllerService, - DownloadControllerService, FileManagementControllerService, GeneralSettingsControllerService, InfoControllerService, @@ -50,8 +37,6 @@ import { StatusReportControllerService } from './api/statusReportController.serv RulesControllerService, SmtpConfigurationControllerService, UploadControllerService, - UserControllerService, - UserPreferenceControllerService, VersionsControllerService, ViewedPagesControllerService, WatermarkControllerService, @@ -67,7 +52,8 @@ export class ApiModule { } if (!http) { throw new Error( - 'You need to import the HttpClientModule in your AppModule! \n' + 'See also https://github.com/angular/angular/issues/20575', + 'You need to import the HttpClientModule in your AppModule! \n' + + 'See also https://github.com/angular/angular/issues/20575', ); } } diff --git a/libs/red-ui-http/src/lib/model/dossierAttributesConfig.ts b/libs/red-ui-http/src/lib/model/dossierAttributesConfig.ts index a3ef99543..b9cbe72b5 100644 --- a/libs/red-ui-http/src/lib/model/dossierAttributesConfig.ts +++ b/libs/red-ui-http/src/lib/model/dossierAttributesConfig.ts @@ -10,7 +10,8 @@ * Do not edit the class manually. */ import { IDossierAttributeConfig } from './dossierAttributeConfig'; +import { List } from '../red-types'; export interface DossierAttributesConfig { - dossierAttributeConfigs?: Array; + dossierAttributeConfigs: List; } diff --git a/libs/red-ui-http/src/lib/model/downloadResponse.ts b/libs/red-ui-http/src/lib/model/downloadResponse.ts index 89677868c..b875b7ac0 100644 --- a/libs/red-ui-http/src/lib/model/downloadResponse.ts +++ b/libs/red-ui-http/src/lib/model/downloadResponse.ts @@ -11,5 +11,5 @@ */ export interface DownloadResponse { - storageId?: string; + readonly storageId?: string; } diff --git a/libs/red-ui-http/src/lib/model/downloadStatus.ts b/libs/red-ui-http/src/lib/model/downloadStatus.ts index c84a2913a..583eaf860 100644 --- a/libs/red-ui-http/src/lib/model/downloadStatus.ts +++ b/libs/red-ui-http/src/lib/model/downloadStatus.ts @@ -9,35 +9,27 @@ * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ +import { DownloadFileType } from './dossier'; +import { List } from '../red-types'; -export interface DownloadStatus { - creationDate?: string; - dossierId?: string; - downloadFileTypes?: Array; - fileIds?: Array; - fileSize?: number; - filename?: string; - lastDownload?: string; - mimeType?: string; - status?: DownloadStatus.StatusEnum; - storageId?: string; - userId?: string; +export interface IDownloadStatus { + readonly creationDate?: string; + readonly dossierId?: string; + readonly downloadFileTypes?: List; + readonly fileIds?: List; + readonly fileSize?: number; + readonly filename?: string; + readonly lastDownload?: string; + readonly mimeType?: string; + readonly status?: DownloadStatusType; + readonly storageId?: string; + readonly userId?: string; } -export namespace DownloadStatus { - export type DownloadFileTypesEnum = 'ANNOTATED' | 'FLATTEN' | 'ORIGINAL' | 'PREVIEW' | 'REDACTED'; - export const DownloadFileTypesEnum = { - ANNOTATED: 'ANNOTATED' as DownloadFileTypesEnum, - FLATTEN: 'FLATTEN' as DownloadFileTypesEnum, - ORIGINAL: 'ORIGINAL' as DownloadFileTypesEnum, - PREVIEW: 'PREVIEW' as DownloadFileTypesEnum, - REDACTED: 'REDACTED' as DownloadFileTypesEnum, - }; - export type StatusEnum = 'FAILED' | 'GENERATING' | 'QUEUED' | 'READY'; - export const StatusEnum = { - FAILED: 'FAILED' as StatusEnum, - GENERATING: 'GENERATING' as StatusEnum, - QUEUED: 'QUEUED' as StatusEnum, - READY: 'READY' as StatusEnum, - }; -} +export const DownloadStatuses = { + FAILED: 'FAILED', + GENERATING: 'GENERATING', + QUEUED: 'QUEUED', + READY: 'READY', +} as const; +export type DownloadStatusType = keyof typeof DownloadStatuses; diff --git a/libs/red-ui-http/src/lib/model/downloadStatusResponse.ts b/libs/red-ui-http/src/lib/model/downloadStatusResponse.ts index 7945e9202..a35b3942d 100644 --- a/libs/red-ui-http/src/lib/model/downloadStatusResponse.ts +++ b/libs/red-ui-http/src/lib/model/downloadStatusResponse.ts @@ -9,8 +9,8 @@ * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ -import { DownloadStatus } from './downloadStatus'; +import { IDownloadStatus } from './downloadStatus'; export interface DownloadStatusResponse { - downloadStatus?: Array; + downloadStatus?: IDownloadStatus[]; } diff --git a/libs/red-ui-http/src/lib/model/prepareDownloadRequest.ts b/libs/red-ui-http/src/lib/model/prepareDownloadRequest.ts index f5e9b4f20..6fe625402 100644 --- a/libs/red-ui-http/src/lib/model/prepareDownloadRequest.ts +++ b/libs/red-ui-http/src/lib/model/prepareDownloadRequest.ts @@ -10,10 +10,12 @@ * Do not edit the class manually. */ +import { List } from '../red-types'; + /** * Object containing information on which file and report types should be included in the download. */ export interface PrepareDownloadRequest { - dossierId?: string; - fileIds?: Array; + readonly dossierId?: string; + readonly fileIds?: List; }