Merge branch 'master' into VM/RED-6240
This commit is contained in:
commit
0eefb3efca
7
.eslintignore
Normal file
7
.eslintignore
Normal file
@ -0,0 +1,7 @@
|
||||
.angular
|
||||
.dev
|
||||
.husky
|
||||
dist
|
||||
coverage
|
||||
node_modules
|
||||
bamboo-specs
|
||||
@ -45,12 +45,14 @@
|
||||
"plugin:@angular-eslint/recommended",
|
||||
"plugin:@angular-eslint/recommended--extra",
|
||||
"plugin:@angular-eslint/template/process-inline-templates",
|
||||
"plugin:prettier/recommended"
|
||||
"plugin:prettier/recommended",
|
||||
"plugin:rxjs/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"rxjs/no-ignored-subscription": "error",
|
||||
"@angular-eslint/no-conflicting-lifecycle": "error",
|
||||
"@angular-eslint/no-host-metadata-property": "error",
|
||||
"@angular-eslint/no-input-rename": "error",
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
|
||||
/.angular
|
||||
/.dev
|
||||
/.husky
|
||||
/dist
|
||||
/coverage
|
||||
/node_modules
|
||||
|
||||
26
apps/red-ui/jest.config.ts
Normal file
26
apps/red-ui/jest.config.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import type { Config } from 'jest';
|
||||
import { defaults } from 'jest-config';
|
||||
|
||||
export default {
|
||||
...defaults,
|
||||
displayName: 'red-ui',
|
||||
preset: '../../jest.preset.js',
|
||||
setupFilesAfterEnv: ['jest-preset-angular/setup-jest.js', 'jest-extended/all'],
|
||||
coverageDirectory: '../../coverage/apps/angular-jest',
|
||||
transform: {
|
||||
'^.+\\.(ts|mjs|js|html)$': [
|
||||
'jest-preset-angular',
|
||||
{
|
||||
tsconfig: '../../tsconfig.spec.json',
|
||||
stringifyContentPathRegex: '\\.(html|svg)$',
|
||||
},
|
||||
],
|
||||
},
|
||||
testEnvironment: 'jest-environment-jsdom',
|
||||
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
|
||||
snapshotSerializers: [
|
||||
'jest-preset-angular/build/serializers/no-ng-attributes',
|
||||
'jest-preset-angular/build/serializers/ng-snapshot',
|
||||
'jest-preset-angular/build/serializers/html-comment',
|
||||
],
|
||||
} as Config;
|
||||
@ -146,6 +146,7 @@ const routes: IqserRoutes = [
|
||||
},
|
||||
{
|
||||
path: 'downloads',
|
||||
// TODO: transform into a lazy loaded module
|
||||
component: DownloadsListScreenComponent,
|
||||
canActivate: [CompositeRouteGuard, IqserPermissionsGuard],
|
||||
data: {
|
||||
@ -161,7 +162,7 @@ const routes: IqserRoutes = [
|
||||
loadChildren: () => import('./modules/search/search.module').then(m => m.SearchModule),
|
||||
canActivate: [CompositeRouteGuard, IqserPermissionsGuard],
|
||||
data: {
|
||||
routeGuards: [IqserAuthGuard, RedRoleGuard],
|
||||
routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard],
|
||||
permissions: {
|
||||
allow: [ROLES.search],
|
||||
redirectTo: '/auth-error',
|
||||
@ -224,7 +225,7 @@ const routes: IqserRoutes = [
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes, { scrollPositionRestoration: 'enabled' })],
|
||||
providers: [{ provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy }],
|
||||
providers: [{ provide: RouteReuseStrategy, useExisting: CustomRouteReuseStrategy }],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, Inject, Renderer2, ViewContainerRef } from '@angular/core';
|
||||
import { Component, Inject, OnDestroy, Renderer2, ViewContainerRef } from '@angular/core';
|
||||
import { RouterHistoryService } from '@services/router-history.service';
|
||||
import { REDDocumentViewer } from './modules/pdf-viewer/services/document-viewer.service';
|
||||
import { DossiersChangesService } from '@services/dossiers/dossier-changes.service';
|
||||
@ -7,6 +7,8 @@ import { UserPreferenceService } from '@users/user-preference.service';
|
||||
import { getConfig, IqserPermissionsService } from '@iqser/common-ui';
|
||||
import { ROLES } from '@users/roles';
|
||||
import { AppConfig } from '@red/domain';
|
||||
import { ActivatedRoute, ParamMap, Router } from '@angular/router';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
function loadCustomTheme() {
|
||||
const cssFileName = getConfig<AppConfig>().THEME;
|
||||
@ -27,24 +29,49 @@ function loadCustomTheme() {
|
||||
selector: 'redaction-root',
|
||||
templateUrl: './app.component.html',
|
||||
})
|
||||
export class AppComponent {
|
||||
export class AppComponent implements OnDestroy {
|
||||
readonly #subscription = new Subscription();
|
||||
|
||||
constructor(
|
||||
/** ViewContainerRef needs to be injected for the color picker to work */
|
||||
readonly viewContainerRef: ViewContainerRef,
|
||||
/** RouterHistoryService needs to be injected for last dossiers screen to be updated on first app load */
|
||||
private readonly _routerHistoryService: RouterHistoryService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
userPreferenceService: UserPreferenceService,
|
||||
readonly documentViewer: REDDocumentViewer,
|
||||
private readonly _dossierChangesService: DossiersChangesService,
|
||||
@Inject(DOCUMENT) private readonly _document: Document,
|
||||
private readonly _renderer: Renderer2,
|
||||
private readonly _permissionsService: IqserPermissionsService,
|
||||
dossierChangesService: DossiersChangesService,
|
||||
@Inject(DOCUMENT) document: Document,
|
||||
renderer: Renderer2,
|
||||
permissionsService: IqserPermissionsService,
|
||||
private readonly _router: Router,
|
||||
route: ActivatedRoute,
|
||||
) {
|
||||
this._renderer.addClass(this._document.body, _userPreferenceService.getTheme());
|
||||
renderer.addClass(document.body, userPreferenceService.getTheme());
|
||||
loadCustomTheme();
|
||||
// TODO: Find a better place to initialize dossiers refresh
|
||||
if (_permissionsService.has(ROLES.dossiers.read)) {
|
||||
_dossierChangesService.initializeRefresh();
|
||||
if (permissionsService.has(ROLES.dossiers.read)) {
|
||||
const refreshSub = dossierChangesService.initializeRefresh().subscribe();
|
||||
this.#subscription.add(refreshSub);
|
||||
}
|
||||
|
||||
const sub = route.queryParamMap.subscribe(queryParams => this.#navigate(queryParams));
|
||||
this.#subscription.add(sub);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.#subscription.unsubscribe();
|
||||
}
|
||||
|
||||
#navigate(queryParams: ParamMap) {
|
||||
if (queryParams.has('code') || queryParams.has('state') || queryParams.has('session_state')) {
|
||||
return this._router.navigate([], {
|
||||
queryParams: {
|
||||
state: null,
|
||||
session_state: null,
|
||||
code: null,
|
||||
},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core';
|
||||
import { AppComponent } from './app.component';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
|
||||
@ -9,18 +8,27 @@ import { MissingTranslationHandler } from '@ngx-translate/core';
|
||||
import {
|
||||
BASE_HREF,
|
||||
CachingModule,
|
||||
CircleButtonComponent,
|
||||
CommonUiModule,
|
||||
EmptyStateComponent,
|
||||
HiddenActionDirective,
|
||||
InputWithActionComponent,
|
||||
IqserAllowDirective,
|
||||
IqserDenyDirective,
|
||||
IqserHelpModeModule,
|
||||
IqserListingModule,
|
||||
IqserLoadingModule,
|
||||
IqserPermissionsModule,
|
||||
IqserPermissionsService,
|
||||
IqserSharedModule,
|
||||
IqserTranslateModule,
|
||||
IqserUsersModule,
|
||||
LanguageService,
|
||||
LogoComponent,
|
||||
MAX_RETRIES_ON_SERVER_ERROR,
|
||||
RoundCheckboxComponent,
|
||||
SERVER_ERROR_SKIP_PATHS,
|
||||
ServerErrorInterceptor,
|
||||
SkeletonComponent,
|
||||
StopPropagationDirective,
|
||||
ToastComponent,
|
||||
} from '@iqser/common-ui';
|
||||
import { ToastrModule } from 'ngx-toastr';
|
||||
@ -101,7 +109,6 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
existingUserService: UserService,
|
||||
existingRoleGuard: RedRoleGuard,
|
||||
}),
|
||||
IqserSharedModule,
|
||||
CachingModule.forRoot(UI_CACHES),
|
||||
IqserHelpModeModule.forRoot(links),
|
||||
PdfViewerModule,
|
||||
@ -114,7 +121,6 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
}),
|
||||
IqserTranslateModule.forRoot({ pathPrefix: config.BASE_TRANSLATIONS_DIRECTORY || '/assets/i18n/redact/' }),
|
||||
IqserLoadingModule.forRoot(),
|
||||
IqserPermissionsModule.forRoot(),
|
||||
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
|
||||
LoggerModule.forRoot(undefined, {
|
||||
ruleProvider: {
|
||||
@ -125,7 +131,7 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
provide: TOKEN_LOGGER_CONFIG,
|
||||
useValue: {
|
||||
level: environment.production ? NgxLoggerLevel.ERROR : NgxLoggerLevel.DEBUG,
|
||||
enableSourceMaps: true,
|
||||
enableSourceMaps: false,
|
||||
timestampFormat: 'mm:ss:SSS',
|
||||
disableFileDetails: true,
|
||||
features: {
|
||||
@ -138,7 +144,7 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
enabled: false,
|
||||
},
|
||||
PDF: {
|
||||
enabled: true,
|
||||
enabled: false,
|
||||
},
|
||||
FILE: {
|
||||
enabled: false,
|
||||
@ -153,6 +159,17 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
} as ILoggerConfig,
|
||||
},
|
||||
}),
|
||||
CircleButtonComponent,
|
||||
EmptyStateComponent,
|
||||
SkeletonComponent,
|
||||
LogoComponent,
|
||||
HiddenActionDirective,
|
||||
StopPropagationDirective,
|
||||
InputWithActionComponent,
|
||||
RoundCheckboxComponent,
|
||||
IqserAllowDirective,
|
||||
IqserDenyDirective,
|
||||
IqserListingModule,
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
@ -223,26 +240,7 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
class AppModule {
|
||||
constructor(private readonly _router: Router, private readonly _route: ActivatedRoute) {
|
||||
this._configureKeyCloakRouteHandling();
|
||||
}
|
||||
|
||||
private _configureKeyCloakRouteHandling() {
|
||||
this._route.queryParamMap.subscribe(queryParams => {
|
||||
if (queryParams.has('code') || queryParams.has('state') || queryParams.has('session_state')) {
|
||||
this._router.navigate([], {
|
||||
queryParams: {
|
||||
state: null,
|
||||
session_state: null,
|
||||
code: null,
|
||||
},
|
||||
queryParamsHandling: 'merge',
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
class AppModule {}
|
||||
|
||||
return AppModule;
|
||||
};
|
||||
|
||||
@ -11,9 +11,7 @@
|
||||
|
||||
<a [matTooltip]="'top-bar.navigation-items.back-to-dashboard' | translate" [routerLink]="['/']" class="logo">
|
||||
<div [iqserHelpMode]="'home'" class="actions">
|
||||
<iqser-hidden-action (action)="userPreferenceService.toggleDevFeatures()">
|
||||
<iqser-logo icon="red:logo"></iqser-logo>
|
||||
</iqser-hidden-action>
|
||||
<iqser-logo (iqserHiddenAction)="userPreferenceService.toggleDevFeatures()" icon="red:logo"></iqser-logo>
|
||||
<div class="app-name">{{ titleService.getTitle() }}</div>
|
||||
</div>
|
||||
</a>
|
||||
@ -29,7 +27,10 @@
|
||||
|
||||
<iqser-help-button *deny="roles.getRss" [iqserHelpMode]="'help_mode'" id="help-mode-button"></iqser-help-button>
|
||||
|
||||
<redaction-notifications [iqserHelpMode]="'open_notifications'"></redaction-notifications>
|
||||
<redaction-notifications
|
||||
*ngIf="currentUser.isUser || currentUser.isManager"
|
||||
[iqserHelpMode]="'open_notifications'"
|
||||
></redaction-notifications>
|
||||
</div>
|
||||
|
||||
<iqser-user-button [iqserHelpMode]="'open_usermenu'" [matMenuTriggerFor]="userMenu" id="userMenu"></iqser-user-button>
|
||||
|
||||
@ -5,11 +5,11 @@
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[bulkActions]="bulkActions"
|
||||
[headerHelpModeKey]="'my_downloads'"
|
||||
[itemSize]="80"
|
||||
[noDataText]="'downloads-list.no-data.title' | translate"
|
||||
[selectionEnabled]="true"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
[headerHelpModeKey]="'my_downloads'"
|
||||
noDataIcon="iqser:download"
|
||||
></iqser-table>
|
||||
</div>
|
||||
@ -26,6 +26,7 @@
|
||||
></iqser-circle-button>
|
||||
</ng-template>
|
||||
|
||||
<!--TODO: move to a separate component-->
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<div *ngIf="cast(entity) as download">
|
||||
<div class="cell">
|
||||
@ -42,7 +43,7 @@
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ download.creationDate | date: 'd MMM yyyy, hh:mm a' }}
|
||||
{{ download.creationDate | date : 'd MMM yyyy, hh:mm a' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -1,4 +1,9 @@
|
||||
<iqser-circle-button [matMenuTriggerFor]="menu" [showDot]="hasUnreadNotifications$ | async" icon="red:notification"></iqser-circle-button>
|
||||
<iqser-circle-button
|
||||
[matMenuTriggerFor]="menu"
|
||||
[showDot]="hasUnreadNotifications$ | async"
|
||||
buttonId="notification-button"
|
||||
icon="red:notification"
|
||||
></iqser-circle-button>
|
||||
|
||||
<mat-menu #menu="matMenu" backdropClass="notifications-backdrop" class="notifications-menu" xPosition="before">
|
||||
<ng-template matMenuContent>
|
||||
@ -13,17 +18,25 @@
|
||||
<div *ngFor="let group of groups; let first = first">
|
||||
<div class="all-caps-label flex-align-items-center">
|
||||
<div>{{ group.date }}</div>
|
||||
<div (click)="markRead($event)" *ngIf="(hasUnreadNotifications$ | async) && first" class="view-all">
|
||||
<div
|
||||
(click)="markRead()"
|
||||
*ngIf="(hasUnreadNotifications$ | async) && first"
|
||||
class="view-all"
|
||||
id="notifications-mark-all-as-read-btn"
|
||||
stopPropagation
|
||||
>
|
||||
{{ 'notifications.mark-all-as-read' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
(click)="markRead($event, [notification], true)"
|
||||
*ngFor="let notification of group.notifications"
|
||||
(click)="markRead([notification], true)"
|
||||
*ngFor="let notification of group.notifications; trackBy: trackBy"
|
||||
[class.unread]="!notification.readDate"
|
||||
[id]="'notifications-mark-as-read-' + notification.id + '-btn'"
|
||||
class="notification"
|
||||
mat-menu-item
|
||||
stopPropagation
|
||||
>
|
||||
<iqser-initials-avatar [user]="notification.userId"></iqser-initials-avatar>
|
||||
|
||||
@ -31,11 +44,14 @@
|
||||
<div [innerHTML]="notification.message"></div>
|
||||
<div class="small-label mt-2">{{ notification.creationDate | date : 'exactDate' }}</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
(click)="markRead($event, [notification], !notification.readDate)"
|
||||
(click)="markRead([notification], !notification.readDate)"
|
||||
[id]="'notifications-mark-' + notification.id"
|
||||
class="dot"
|
||||
matTooltip="{{ 'notifications.mark-as' | translate : { type: notification.readDate ? 'unread' : 'read' } }}"
|
||||
matTooltipPosition="before"
|
||||
stopPropagation
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -4,7 +4,7 @@ import { NotificationsService } from '@services/notifications.service';
|
||||
import { Notification } from '@red/domain';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { Observable } from 'rxjs';
|
||||
import { isToday, shareLast } from '@iqser/common-ui';
|
||||
import { isToday, shareLast, trackByFactory } from '@iqser/common-ui';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@ -29,6 +29,7 @@ function chronologically(first: string, second: string) {
|
||||
export class NotificationsComponent {
|
||||
readonly hasUnreadNotifications$: Observable<boolean>;
|
||||
readonly groupedNotifications$: Observable<NotificationsGroup[]>;
|
||||
readonly trackBy = trackByFactory();
|
||||
|
||||
constructor(
|
||||
private readonly _notificationsService: NotificationsService,
|
||||
@ -47,9 +48,7 @@ export class NotificationsComponent {
|
||||
);
|
||||
}
|
||||
|
||||
async markRead($event, notifications: Notification[] = this._notificationsService.all, isRead = true): Promise<void> {
|
||||
$event.stopPropagation();
|
||||
|
||||
async markRead(notifications: Notification[] = this._notificationsService.all, isRead = true): Promise<void> {
|
||||
if (!notifications.find(notification => !!notification.readDate !== isRead)) {
|
||||
// If no notification changes status after the request, abort
|
||||
return;
|
||||
@ -71,11 +70,10 @@ export class NotificationsComponent {
|
||||
return n.creationDate.split('T')[0];
|
||||
});
|
||||
|
||||
const grouped = [...groupedMap.entries()];
|
||||
const sorted = grouped.sort(([aDate], [bDate]) => chronologically(aDate, bDate));
|
||||
return sorted.map(([date, _notifications]) => ({
|
||||
const sortedGroups = [...groupedMap.entries()].sort(([aDate], [bDate]) => chronologically(aDate, bDate));
|
||||
return sortedGroups.map(([date, _notifications]) => ({
|
||||
date: isToday(date) ? todayTranslation : this._datePipe.transform(date, 'sophisticatedDate'),
|
||||
notifications: _notifications.sort((a, b) => chronologically(a.creationDate, b.creationDate)),
|
||||
notifications: [..._notifications].sort((a, b) => chronologically(a.creationDate, b.creationDate)),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { CanDeactivate } from '@angular/router';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { map, Observable } from 'rxjs';
|
||||
import { map } from 'rxjs';
|
||||
import { ConfirmationDialogService, ConfirmOptions } from '@iqser/common-ui';
|
||||
|
||||
export interface ComponentCanDeactivate {
|
||||
@ -15,23 +15,24 @@ export interface ComponentCanDeactivate {
|
||||
export class PendingChangesGuard implements CanDeactivate<ComponentCanDeactivate> {
|
||||
constructor(private _dialogService: ConfirmationDialogService) {}
|
||||
|
||||
canDeactivate(component: ComponentCanDeactivate): boolean | Observable<boolean> {
|
||||
if (component.changed) {
|
||||
component.isLeavingPage = true;
|
||||
|
||||
const dialogRef = this._dialogService.openDialog({ disableConfirm: component.valid === false });
|
||||
return dialogRef.afterClosed().pipe(
|
||||
map(result => {
|
||||
if (result === ConfirmOptions.CONFIRM) {
|
||||
component.save().then();
|
||||
} else {
|
||||
component.discard?.().then();
|
||||
}
|
||||
component.isLeavingPage = false;
|
||||
return !!result;
|
||||
}),
|
||||
);
|
||||
canDeactivate(component: ComponentCanDeactivate) {
|
||||
if (!component.changed) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
component.isLeavingPage = true;
|
||||
|
||||
const dialogRef = this._dialogService.open({ disableConfirm: component.valid === false });
|
||||
return dialogRef.afterClosed().pipe(
|
||||
map(result => {
|
||||
if (result === ConfirmOptions.CONFIRM) {
|
||||
component.save().then();
|
||||
} else {
|
||||
component.discard?.().then();
|
||||
}
|
||||
component.isLeavingPage = false;
|
||||
return !!result;
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import { firstValueFrom } from 'rxjs';
|
||||
import { DOSSIER_ID, DOSSIER_TEMPLATE_ID } from '@red/domain';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DossierFilesGuard implements CanActivate {
|
||||
@ -14,6 +15,7 @@ export class DossierFilesGuard implements CanActivate {
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
private readonly _dictionaryMapService: DossierDictionariesMapService,
|
||||
private readonly _router: Router,
|
||||
) {}
|
||||
|
||||
@ -41,8 +43,10 @@ export class DossierFilesGuard implements CanActivate {
|
||||
async loadDossierData(dossierId: string, dossierTemplateId: string) {
|
||||
const promises = [];
|
||||
|
||||
const dictionary$ = this._dictionaryService.loadDossierDictionary(dossierTemplateId, dossierId);
|
||||
promises.push(firstValueFrom(dictionary$));
|
||||
if (!this._dictionaryMapService.has(dossierId)) {
|
||||
const dictionary$ = this._dictionaryService.loadDossierDictionary(dossierTemplateId, dossierId);
|
||||
promises.push(firstValueFrom(dictionary$));
|
||||
}
|
||||
|
||||
if (!this._filesMapService.has(dossierId)) {
|
||||
promises.push(firstValueFrom(this._filesService.loadAll(dossierId)));
|
||||
|
||||
@ -6,13 +6,20 @@ import { AccountSideNavComponent } from './account-side-nav/account-side-nav.com
|
||||
import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component';
|
||||
import { NotificationPreferencesService } from './services/notification-preferences.service';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { IqserSharedModule } from '@iqser/common-ui';
|
||||
import { IqserHelpModeModule } from '@iqser/common-ui';
|
||||
import { IconButtonComponent, IqserHelpModeModule, SideNavComponent } from '@iqser/common-ui';
|
||||
import { PreferencesComponent } from './screens/preferences/preferences.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AccountSideNavComponent, BaseAccountScreenComponent, PreferencesComponent],
|
||||
imports: [CommonModule, SharedModule, AccountRoutingModule, TranslateModule, IqserSharedModule, IqserHelpModeModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
AccountRoutingModule,
|
||||
TranslateModule,
|
||||
IqserHelpModeModule,
|
||||
IconButtonComponent,
|
||||
SideNavComponent,
|
||||
],
|
||||
providers: [NotificationPreferencesService],
|
||||
})
|
||||
export class AccountModule {}
|
||||
|
||||
@ -5,11 +5,12 @@ import { SharedModule } from '@shared/shared.module';
|
||||
import { NotificationsScreenComponent } from './notifications-screen/notifications-screen.component';
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { IconButtonComponent } from '@iqser/common-ui';
|
||||
|
||||
const routes = [{ path: '', component: NotificationsScreenComponent, canDeactivate: [PendingChangesGuard] }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [NotificationsScreenComponent],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, TranslateModule],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, TranslateModule, IconButtonComponent],
|
||||
})
|
||||
export class NotificationsModule {}
|
||||
|
||||
@ -86,7 +86,7 @@ export class UserProfileScreenComponent extends BaseFormComponent implements OnI
|
||||
const value = this.form.getRawValue() as IProfile;
|
||||
|
||||
if (this.emailChanged) {
|
||||
const dialogRef = this._dialogService.openDialog('confirmPassword', null, null);
|
||||
const dialogRef = this._dialogService.openDialog('confirmPassword');
|
||||
const password = await firstValueFrom(dialogRef.afterClosed());
|
||||
if (!password) {
|
||||
return;
|
||||
|
||||
@ -7,12 +7,13 @@ import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ConfirmPasswordDialogComponent } from './confirm-password-dialog/confirm-password-dialog.component';
|
||||
import { UserProfileDialogService } from './services/user-profile-dialog.service';
|
||||
import { CircleButtonComponent, IconButtonComponent } from '@iqser/common-ui';
|
||||
|
||||
const routes = [{ path: '', component: UserProfileScreenComponent, canDeactivate: [PendingChangesGuard] }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [UserProfileScreenComponent, ConfirmPasswordDialogComponent],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, TranslateModule],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, TranslateModule, IconButtonComponent, CircleButtonComponent],
|
||||
providers: [UserProfileDialogService],
|
||||
})
|
||||
export class UserProfileModule {}
|
||||
|
||||
@ -3,13 +3,11 @@ import { CompositeRouteGuard, IqserAuthGuard, IqserPermissionsGuard, IqserRoutes
|
||||
import { RedRoleGuard } from '@users/red-role.guard';
|
||||
import { EntitiesListingScreenComponent } from './screens/entities-listing/entities-listing-screen.component';
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
import { FileAttributesListingScreenComponent } from './screens/file-attributes-listing/file-attributes-listing-screen.component';
|
||||
import { DefaultColorsScreenComponent } from './screens/default-colors/default-colors-screen.component';
|
||||
import { UserListingScreenComponent } from './screens/user-listing/user-listing-screen.component';
|
||||
import { DigitalSignatureScreenComponent } from './screens/digital-signature/digital-signature-screen.component';
|
||||
import { AuditScreenComponent } from './screens/audit/audit-screen.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { DossierAttributesListingScreenComponent } from './screens/dossier-attributes-listing/dossier-attributes-listing-screen.component';
|
||||
import { GeneralConfigScreenComponent } from './screens/general-config/general-config-screen.component';
|
||||
import { BaseAdminScreenComponent } from './base-admin-screen/base-admin-screen.component';
|
||||
import { BaseDossierTemplateScreenComponent } from './base-dossier-templates-screen/base-dossier-template-screen.component';
|
||||
@ -17,7 +15,6 @@ import { DossierTemplatesGuard } from '@guards/dossier-templates.guard';
|
||||
import { DOSSIER_TEMPLATE_ID, ENTITY_TYPE } from '@red/domain';
|
||||
import { DossierTemplateExistsGuard } from '@guards/dossier-template-exists.guard';
|
||||
import { EntityExistsGuard } from '@guards/entity-exists-guard.service';
|
||||
import { DossierStatesListingScreenComponent } from './screens/dossier-states-listing/dossier-states-listing-screen.component';
|
||||
import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component';
|
||||
import { PermissionsGuard } from '@guards/permissions-guard';
|
||||
import { ROLES } from '@users/roles';
|
||||
@ -65,7 +62,9 @@ const dossierTemplateIdRoutes: IqserRoutes = [
|
||||
},
|
||||
{
|
||||
path: 'file-attributes',
|
||||
component: FileAttributesListingScreenComponent,
|
||||
component: BaseDossierTemplateScreenComponent,
|
||||
loadChildren: () =>
|
||||
import('./screens/file-attributes-listing/file-attributes-listing.module').then(m => m.FileAttributesListingModule),
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [IqserAuthGuard, RedRoleGuard],
|
||||
@ -90,7 +89,9 @@ const dossierTemplateIdRoutes: IqserRoutes = [
|
||||
},
|
||||
{
|
||||
path: 'dossier-attributes',
|
||||
component: DossierAttributesListingScreenComponent,
|
||||
component: BaseDossierTemplateScreenComponent,
|
||||
loadChildren: () =>
|
||||
import('./screens/dossier-attributes-listing/dossier-attributes-listing.module').then(m => m.DossierAttributesListingModule),
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [IqserAuthGuard, RedRoleGuard],
|
||||
@ -98,7 +99,9 @@ const dossierTemplateIdRoutes: IqserRoutes = [
|
||||
},
|
||||
{
|
||||
path: 'dossier-states',
|
||||
component: DossierStatesListingScreenComponent,
|
||||
component: BaseDossierTemplateScreenComponent,
|
||||
loadChildren: () =>
|
||||
import('./screens/dossier-states-listing/dossier-states-listing.module').then(m => m.DossierStatesListingModule),
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [IqserAuthGuard, RedRoleGuard],
|
||||
|
||||
@ -6,10 +6,8 @@ import { AuditScreenComponent } from './screens/audit/audit-screen.component';
|
||||
import { DefaultColorsScreenComponent } from './screens/default-colors/default-colors-screen.component';
|
||||
import { EntitiesListingScreenComponent } from './screens/entities-listing/entities-listing-screen.component';
|
||||
import { DigitalSignatureScreenComponent } from './screens/digital-signature/digital-signature-screen.component';
|
||||
import { FileAttributesListingScreenComponent } from './screens/file-attributes-listing/file-attributes-listing-screen.component';
|
||||
import { UserListingScreenComponent } from './screens/user-listing/user-listing-screen.component';
|
||||
import { DossierTemplateBreadcrumbsComponent } from './components/dossier-template-breadcrumbs/dossier-template-breadcrumbs.component';
|
||||
import { AddEditFileAttributeDialogComponent } from './dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
|
||||
import { DossierTemplateBreadcrumbsComponent } from './shared/components/dossier-template-breadcrumbs/dossier-template-breadcrumbs.component';
|
||||
import { AddEditCloneDossierTemplateDialogComponent } from './dialogs/add-edit-dossier-template-dialog/add-edit-clone-dossier-template-dialog.component';
|
||||
import { AddEntityDialogComponent } from './dialogs/add-entity-dialog/add-entity-dialog.component';
|
||||
import { EditColorDialogComponent } from './dialogs/edit-color-dialog/edit-color-dialog.component';
|
||||
@ -18,12 +16,8 @@ import { GeneralConfigScreenComponent } from './screens/general-config/general-c
|
||||
import { SmtpAuthDialogComponent } from './dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
||||
import { AddEditUserDialogComponent } from './dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
||||
import { UsersStatsComponent } from './components/users-stats/users-stats.component';
|
||||
import { FileAttributesCsvImportDialogComponent } from './dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
|
||||
import { ActiveFieldsListingComponent } from './dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.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';
|
||||
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 { AuditService } from './services/audit.service';
|
||||
import { DigitalSignatureService } from './services/digital-signature.service';
|
||||
import { BaseAdminScreenComponent } from './base-admin-screen/base-admin-screen.component';
|
||||
@ -32,48 +26,43 @@ import { SmtpConfigService } from './services/smtp-config.service';
|
||||
import { UploadDictionaryDialogComponent } from './dialogs/upload-dictionary-dialog/upload-dictionary-dialog.component';
|
||||
import { GeneralConfigFormComponent } from './screens/general-config/general-config-form/general-config-form.component';
|
||||
import { SmtpFormComponent } from './screens/general-config/smtp-form/smtp-form.component';
|
||||
import { FileAttributesConfigurationsDialogComponent } from './dialogs/file-attributes-configurations-dialog/file-attributes-configurations-dialog.component';
|
||||
import { SharedAdminModule } from './shared/shared-admin.module';
|
||||
import { BaseDossierTemplateScreenComponent } from './base-dossier-templates-screen/base-dossier-template-screen.component';
|
||||
import { DossierStatesListingScreenComponent } from './screens/dossier-states-listing/dossier-states-listing-screen.component';
|
||||
import { AddEditDossierStateDialogComponent } from './dialogs/add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
|
||||
import { A11yModule } from '@angular/cdk/a11y';
|
||||
import { ConfirmDeleteDossierStateDialogComponent } from './dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component';
|
||||
import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component';
|
||||
import { AdminSideNavComponent } from './admin-side-nav/admin-side-nav.component';
|
||||
import { AdminSideNavComponent } from './shared/components/admin-side-nav/admin-side-nav.component';
|
||||
import { SystemPreferencesFormComponent } from './screens/general-config/system-preferences-form/system-preferences-form.component';
|
||||
import { ConfigureCertificateDialogComponent } from './dialogs/configure-digital-signature-dialog/configure-certificate-dialog.component';
|
||||
import { PkcsSignatureConfigurationComponent } from './dialogs/configure-digital-signature-dialog/form/pkcs-signature-configuration/pkcs-signature-configuration.component';
|
||||
import { KmsSignatureConfigurationComponent } from './dialogs/configure-digital-signature-dialog/form/kms-signature-configuration/kms-signature-configuration.component';
|
||||
import {
|
||||
ChevronButtonComponent,
|
||||
CircleButtonComponent,
|
||||
DetailsRadioComponent,
|
||||
EditableInputComponent,
|
||||
EmptyStateComponent,
|
||||
HasScrollbarDirective,
|
||||
HumanizePipe,
|
||||
IqserButtonsModule,
|
||||
IqserEmptyStatesModule,
|
||||
IconButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IqserAllowDirective,
|
||||
IqserDenyDirective,
|
||||
IqserHelpModeModule,
|
||||
IqserInputsModule,
|
||||
IqserListingModule,
|
||||
IqserPermissionsModule,
|
||||
IqserScrollbarModule,
|
||||
IqserSharedModule,
|
||||
IqserUploadFileModule,
|
||||
IqserUsersModule,
|
||||
RoundCheckboxComponent,
|
||||
} from '@iqser/common-ui';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { AuditInfoDialogComponent } from './dialogs/audit-info-dialog/audit-info-dialog.component';
|
||||
import { DossierTemplateActionsComponent } from './shared/components/dossier-template-actions/dossier-template-actions.component';
|
||||
|
||||
const dialogs = [
|
||||
AddEditCloneDossierTemplateDialogComponent,
|
||||
AddEntityDialogComponent,
|
||||
AddEditFileAttributeDialogComponent,
|
||||
EditColorDialogComponent,
|
||||
SmtpAuthDialogComponent,
|
||||
AddEditUserDialogComponent,
|
||||
FileAttributesConfigurationsDialogComponent,
|
||||
FileAttributesCsvImportDialogComponent,
|
||||
AddEditDossierAttributeDialogComponent,
|
||||
UploadDictionaryDialogComponent,
|
||||
AddEditDossierStateDialogComponent,
|
||||
ConfirmDeleteDossierStateDialogComponent,
|
||||
ConfigureCertificateDialogComponent,
|
||||
AuditInfoDialogComponent,
|
||||
];
|
||||
@ -83,18 +72,12 @@ const screens = [
|
||||
DefaultColorsScreenComponent,
|
||||
EntitiesListingScreenComponent,
|
||||
DigitalSignatureScreenComponent,
|
||||
FileAttributesListingScreenComponent,
|
||||
UserListingScreenComponent,
|
||||
GeneralConfigScreenComponent,
|
||||
DossierAttributesListingScreenComponent,
|
||||
DossierStatesListingScreenComponent,
|
||||
];
|
||||
|
||||
const components = [
|
||||
DossierTemplateBreadcrumbsComponent,
|
||||
UsersStatsComponent,
|
||||
AdminSideNavComponent,
|
||||
ActiveFieldsListingComponent,
|
||||
ResetPasswordComponent,
|
||||
UserDetailsComponent,
|
||||
BaseAdminScreenComponent,
|
||||
@ -117,20 +100,27 @@ const components = [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
AdminRoutingModule,
|
||||
SharedAdminModule,
|
||||
A11yModule,
|
||||
IqserUsersModule,
|
||||
TranslateModule,
|
||||
HumanizePipe,
|
||||
IqserButtonsModule,
|
||||
IqserListingModule,
|
||||
IqserScrollbarModule,
|
||||
IqserInputsModule,
|
||||
IqserUploadFileModule,
|
||||
IqserEmptyStatesModule,
|
||||
IqserSharedModule,
|
||||
IqserHelpModeModule,
|
||||
IqserPermissionsModule,
|
||||
AdminSideNavComponent,
|
||||
DossierTemplateActionsComponent,
|
||||
DossierTemplateBreadcrumbsComponent,
|
||||
IconButtonComponent,
|
||||
CircleButtonComponent,
|
||||
ChevronButtonComponent,
|
||||
EmptyStateComponent,
|
||||
HasScrollbarDirective,
|
||||
RoundCheckboxComponent,
|
||||
InputWithActionComponent,
|
||||
EditableInputComponent,
|
||||
DetailsRadioComponent,
|
||||
IqserAllowDirective,
|
||||
IqserDenyDirective,
|
||||
],
|
||||
})
|
||||
export class AdminModule {}
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
<iqser-circle-button
|
||||
[routerLink]="['../..']"
|
||||
[tooltip]="'common.close' | translate"
|
||||
buttonId="close-view-btn"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
|
||||
@ -17,8 +17,8 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
export class BaseEntityScreenComponent {
|
||||
readonly disabledItems$: Observable<string[]>;
|
||||
readonly canDeleteEntity$: Observable<boolean>;
|
||||
readonly #dossierTemplateId: string = getParam(DOSSIER_TEMPLATE_ID);
|
||||
readonly #entityType: string = getParam(ENTITY_TYPE);
|
||||
readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
|
||||
readonly #entityType = getParam(ENTITY_TYPE);
|
||||
|
||||
constructor(
|
||||
private readonly _router: Router,
|
||||
@ -37,7 +37,7 @@ export class BaseEntityScreenComponent {
|
||||
}
|
||||
|
||||
openDeleteDictionariesDialog() {
|
||||
this._dialogService.openDialog('confirm', null, null, async () => {
|
||||
this._dialogService.openDialog('confirm', null, async () => {
|
||||
this._loadingService.start();
|
||||
const dossierTemplate = this._dossierTemplatesService.find(this.#dossierTemplateId);
|
||||
await firstValueFrom(this._dictionaryService.deleteDictionaries([this.#entityType], this.#dossierTemplateId));
|
||||
|
||||
@ -103,7 +103,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
||||
}
|
||||
|
||||
delete() {
|
||||
this._dialogService.deleteUsers([this.user.id], null, () => this.closeDialog.emit(true));
|
||||
this._dialogService.deleteUsers([this.user.id], () => this.closeDialog.emit(true));
|
||||
}
|
||||
|
||||
setRolesRequirements(checked: boolean, role: string): void {
|
||||
|
||||
@ -27,8 +27,12 @@
|
||||
<form [formGroup]="form">
|
||||
<div class="iqser-input-group w-150 mr-20">
|
||||
<mat-form-field>
|
||||
<mat-select (selectionChange)="filterChange()" formControlName="category">
|
||||
<mat-option *ngFor="let category of categories" [value]="category">
|
||||
<mat-select (selectionChange)="filterChange()" formControlName="category" id="select-category">
|
||||
<mat-option
|
||||
*ngFor="let category of categories"
|
||||
[value]="category"
|
||||
[id]="'select-category-' + category.toLocaleLowerCase()"
|
||||
>
|
||||
{{ (translations[category] | translate) || category }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
@ -37,7 +41,7 @@
|
||||
|
||||
<div class="iqser-input-group w-150">
|
||||
<mat-form-field>
|
||||
<mat-select (selectionChange)="filterChange()" formControlName="userId">
|
||||
<mat-select (selectionChange)="filterChange()" formControlName="userId" id="select-users">
|
||||
<mat-select-trigger>
|
||||
<iqser-initials-avatar
|
||||
*ngIf="form.get('userId').value !== ALL_USERS"
|
||||
@ -48,7 +52,7 @@
|
||||
<div *ngIf="form.get('userId').value === ALL_USERS" [translate]="ALL_USERS"></div>
|
||||
</mat-select-trigger>
|
||||
|
||||
<mat-option *ngFor="let userId of userIds" [value]="userId">
|
||||
<mat-option *ngFor="let userId of userIds" [value]="userId" [id]="'select-user-' + userId">
|
||||
<iqser-initials-avatar *ngIf="userId !== ALL_USERS" [user]="userId" [withName]="true"></iqser-initials-avatar>
|
||||
|
||||
<div *ngIf="userId === ALL_USERS" [translate]="ALL_USERS"></div>
|
||||
@ -60,7 +64,13 @@
|
||||
<div class="separator">·</div>
|
||||
|
||||
<div class="iqser-input-group datepicker-wrapper mr-20">
|
||||
<input (dateChange)="filterChange()" [matDatepicker]="fromPicker" formControlName="from" placeholder="dd/mm/yy" />
|
||||
<input
|
||||
id="start-date-input"
|
||||
(dateChange)="filterChange()"
|
||||
[matDatepicker]="fromPicker"
|
||||
formControlName="from"
|
||||
placeholder="dd/mm/yy"
|
||||
/>
|
||||
<mat-datepicker-toggle [for]="fromPicker" matSuffix>
|
||||
<mat-icon matDatepickerToggleIcon svgIcon="red:calendar"></mat-icon>
|
||||
</mat-datepicker-toggle>
|
||||
@ -70,7 +80,13 @@
|
||||
<div class="mr-20" translate="audit-screen.to"></div>
|
||||
|
||||
<div class="iqser-input-group datepicker-wrapper">
|
||||
<input (dateChange)="filterChange()" [matDatepicker]="toPicker" formControlName="to" placeholder="dd/mm/yy" />
|
||||
<input
|
||||
id="end-date-input"
|
||||
(dateChange)="filterChange()"
|
||||
[matDatepicker]="toPicker"
|
||||
formControlName="to"
|
||||
placeholder="dd/mm/yy"
|
||||
/>
|
||||
<mat-datepicker-toggle [for]="toPicker" matSuffix>
|
||||
<mat-icon matDatepickerToggleIcon svgIcon="red:calendar"></mat-icon>
|
||||
</mat-datepicker-toggle>
|
||||
@ -99,7 +115,7 @@
|
||||
<div class="cell">
|
||||
<div class="action-buttons">
|
||||
<iqser-circle-button
|
||||
(action)="openAuditDetails($event, log)"
|
||||
(action)="openAuditDetails(log)"
|
||||
*ngIf="log.hasDetails"
|
||||
[tooltip]="'audit-screen.action.info' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
:host ::ng-deep iqser-table iqser-table-header .header-item {
|
||||
justify-content: space-between;
|
||||
:host ::ng-deep {
|
||||
iqser-table iqser-table-header .header-item {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.mat-mdc-form-field .mat-mdc-text-field-wrapper {
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
|
||||
@ -83,6 +83,10 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnI
|
||||
}
|
||||
}
|
||||
|
||||
openAuditDetails(log: Audit) {
|
||||
this._dialogService.openDialog('auditInfo', { auditEntry: log });
|
||||
}
|
||||
|
||||
private _getForm(): UntypedFormGroup {
|
||||
return this._formBuilder.group({
|
||||
category: [this.ALL_CATEGORIES],
|
||||
@ -136,8 +140,4 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnI
|
||||
}
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
openAuditDetails($event: MouseEvent, log: Audit) {
|
||||
this._dialogService.openDialog('auditInfo', $event, { auditEntry: log });
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
<div class="cell">
|
||||
<div class="action-buttons">
|
||||
<iqser-circle-button
|
||||
(action)="openEditColorDialog($event, entity)"
|
||||
(action)="openEditColorDialog(entity)"
|
||||
*allow="roles.colors.write; if: currentUser.isAdmin"
|
||||
[iqserHelpMode]="'default_colors'"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
|
||||
@ -53,7 +53,7 @@ export class DefaultColorsScreenComponent extends ListingComponent<ListItem> {
|
||||
);
|
||||
}
|
||||
|
||||
openEditColorDialog($event: MouseEvent, color: ListItem) {
|
||||
this._dialogService.openDialog('editColor', $event, { colorKey: color.key, dossierTemplateId: this.#dossierTemplateId });
|
||||
openEditColorDialog(color: ListItem) {
|
||||
this._dialogService.openDialog('editColor', { colorKey: color.key, dossierTemplateId: this.#dossierTemplateId });
|
||||
}
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ export class DigitalSignatureScreenComponent implements OnInit {
|
||||
}
|
||||
|
||||
openConfigureCertificate(): void {
|
||||
const dialogRef = this._dialogService.openDialog('configureCertificate', null, null);
|
||||
const dialogRef = this._dialogService.openDialog('configureCertificate');
|
||||
firstValueFrom(dialogRef.afterClosed()).then(async res => {
|
||||
if (res) {
|
||||
await this.loadDigitalSignature();
|
||||
|
||||
@ -29,6 +29,7 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<iqser-icon-button
|
||||
(action)="save()"
|
||||
@ -0,0 +1,5 @@
|
||||
@use 'common-mixins';
|
||||
|
||||
.dialog-header {
|
||||
@include common-mixins.line-clamp(1);
|
||||
}
|
||||
@ -1,20 +1,36 @@
|
||||
import { Component, HostListener, Inject, OnDestroy } from '@angular/core';
|
||||
import { UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { DossierAttributeConfigTypes, FileAttributeConfigTypes, IDossierAttributeConfig } from '@red/domain';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { BaseDialogComponent, IqserEventTarget } from '@iqser/common-ui';
|
||||
import { BaseDialogComponent, CircleButtonComponent, IconButtonComponent, IqserEventTarget } from '@iqser/common-ui';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { DossierAttributesService } from '@services/entity-services/dossier-attributes.service';
|
||||
import { dossierAttributeTypesTranslations } from '@translations/dossier-attribute-types-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
|
||||
export interface AddEditDossierAttributeDialogData {
|
||||
readonly dossierAttribute: IDossierAttributeConfig;
|
||||
dossierTemplateId: string;
|
||||
readonly dossierTemplateId: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: './add-edit-dossier-attribute-dialog.component.html',
|
||||
styleUrls: ['./add-edit-dossier-attribute-dialog.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
TranslateModule,
|
||||
ReactiveFormsModule,
|
||||
NgIf,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
NgForOf,
|
||||
IconButtonComponent,
|
||||
CircleButtonComponent,
|
||||
],
|
||||
})
|
||||
export class AddEditDossierAttributeDialogComponent extends BaseDialogComponent implements OnDestroy {
|
||||
readonly dossierAttribute = this.data.dossierAttribute;
|
||||
@ -31,7 +47,7 @@ export class AddEditDossierAttributeDialogComponent extends BaseDialogComponent
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: AddEditDossierAttributeDialogData,
|
||||
) {
|
||||
super(_dialogRef, !!data.dossierAttribute);
|
||||
this.form = this._getForm(this.dossierAttribute);
|
||||
this.form = this.#form;
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
}
|
||||
|
||||
@ -49,6 +65,20 @@ export class AddEditDossierAttributeDialogComponent extends BaseDialogComponent
|
||||
return false;
|
||||
}
|
||||
|
||||
get #form() {
|
||||
const dossierAttribute = this.data.dossierAttribute;
|
||||
return this._formBuilder.group({
|
||||
label: [dossierAttribute?.label, Validators.required],
|
||||
...(!!dossierAttribute && {
|
||||
placeholder: {
|
||||
value: dossierAttribute.placeholder,
|
||||
disabled: true,
|
||||
},
|
||||
}),
|
||||
type: [dossierAttribute?.type || FileAttributeConfigTypes.TEXT, Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
async save() {
|
||||
this._loadingService.start();
|
||||
|
||||
@ -77,17 +107,4 @@ export class AddEditDossierAttributeDialogComponent extends BaseDialogComponent
|
||||
await this.save();
|
||||
}
|
||||
}
|
||||
|
||||
private _getForm(dossierAttribute: IDossierAttributeConfig): UntypedFormGroup {
|
||||
return this._formBuilder.group({
|
||||
label: [dossierAttribute?.label, Validators.required],
|
||||
...(!!dossierAttribute && {
|
||||
placeholder: {
|
||||
value: dossierAttribute.placeholder,
|
||||
disabled: true,
|
||||
},
|
||||
}),
|
||||
type: [dossierAttribute?.type || FileAttributeConfigTypes.TEXT, Validators.required],
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,42 +1,19 @@
|
||||
<section>
|
||||
<div class="page-header">
|
||||
<redaction-dossier-template-breadcrumbs class="flex-1"></redaction-dossier-template-breadcrumbs>
|
||||
|
||||
<div class="actions flex-1">
|
||||
<redaction-dossier-template-actions></redaction-dossier-template-actions>
|
||||
|
||||
<iqser-circle-button
|
||||
[routerLink]="['../..']"
|
||||
[tooltip]="'common.close' | translate"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-inner">
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<redaction-admin-side-nav type="dossierTemplates"></redaction-admin-side-nav>
|
||||
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
(noDataAction)="openAddEditAttributeDialog(null)"
|
||||
[bulkActions]="bulkActions"
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="50"
|
||||
[noDataButtonLabel]="'dossier-attributes-listing.no-data.action' | translate"
|
||||
[noDataText]="'dossier-attributes-listing.no-data.title' | translate"
|
||||
[noMatchText]="'dossier-attributes-listing.no-match.title' | translate"
|
||||
[selectionEnabled]="canEditDossierAttributes"
|
||||
[showNoDataButton]="canEditDossierAttributes"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
(noDataAction)="openAddEditAttributeDialog()"
|
||||
[bulkActions]="bulkActions"
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="50"
|
||||
[noDataButtonLabel]="'dossier-attributes-listing.no-data.action' | translate"
|
||||
[noDataText]="'dossier-attributes-listing.no-data.title' | translate"
|
||||
[noMatchText]="'dossier-attributes-listing.no-match.title' | translate"
|
||||
[selectionEnabled]="canEditDossierAttributes"
|
||||
[showNoDataButton]="canEditDossierAttributes"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
@ -56,11 +33,11 @@
|
||||
></iqser-input-with-action>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="openAddEditAttributeDialog($event)"
|
||||
(action)="openAddEditAttributeDialog()"
|
||||
*ngIf="canEditDossierAttributes"
|
||||
[iqserHelpMode]="'create_new_dossier_attribute'"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
[label]="'dossier-attributes-listing.add-new' | translate"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
></iqser-icon-button>
|
||||
@ -73,6 +50,7 @@
|
||||
</ul>
|
||||
</ng-template>
|
||||
|
||||
<!--TODO: move to a separate component-->
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<div *ngIf="cast(entity) as attribute">
|
||||
<div [matTooltip]="attribute.label" class="cell" matTooltipPosition="above">
|
||||
@ -91,7 +69,7 @@
|
||||
<div *ngIf="canEditDossierAttributes" class="action-buttons">
|
||||
<div [iqserHelpMode]="'edit_delete_dossier_attributes'" [overlappingElements]="['USER_MENU']">
|
||||
<iqser-circle-button
|
||||
(action)="openAddEditAttributeDialog($event, attribute)"
|
||||
(action)="openAddEditAttributeDialog(attribute)"
|
||||
[tooltip]="'dossier-attributes-listing.action.edit' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
defaultDialogConfig,
|
||||
getCurrentUser,
|
||||
getParam,
|
||||
IconButtonTypes,
|
||||
@ -16,6 +17,11 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DOSSIER_TEMPLATE_ID, DossierAttributeConfig, IDossierAttributeConfig, User } from '@red/domain';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
AddEditDossierAttributeDialogComponent,
|
||||
AddEditDossierAttributeDialogData,
|
||||
} from './add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-attributes-listing-screen.component.html',
|
||||
@ -44,40 +50,45 @@ export class DossierAttributesListingScreenComponent extends ListingComponent<Do
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _dossierAttributesService: DossierAttributesService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this._loadData();
|
||||
await this.#loadData();
|
||||
}
|
||||
|
||||
async openConfirmDeleteAttributeDialog($event: MouseEvent, attributes: DossierAttributeConfig[] = this.listingService.selected) {
|
||||
await this._dialogService.deleteAttributes(
|
||||
attributes,
|
||||
this.#dossierTemplateId,
|
||||
this.impactedTemplatesRef,
|
||||
'dossier',
|
||||
$event,
|
||||
async () => {
|
||||
this._loadingService.start();
|
||||
const ids = attributes.map(a => a.id);
|
||||
await firstValueFrom(this._dossierAttributesService.delete(ids, this.#dossierTemplateId));
|
||||
await this._loadData();
|
||||
},
|
||||
);
|
||||
await this._dialogService.deleteAttributes(attributes, this.#dossierTemplateId, this.impactedTemplatesRef, 'dossier', async () => {
|
||||
this._loadingService.start();
|
||||
const ids = attributes.map(a => a.id);
|
||||
await firstValueFrom(this._dossierAttributesService.delete(ids, this.#dossierTemplateId));
|
||||
await this.#loadData();
|
||||
});
|
||||
}
|
||||
|
||||
openAddEditAttributeDialog($event: MouseEvent, dossierAttribute?: IDossierAttributeConfig) {
|
||||
async openAddEditAttributeDialog(dossierAttribute?: IDossierAttributeConfig) {
|
||||
const dossierTemplateId = this.#dossierTemplateId;
|
||||
|
||||
this._dialogService.openDialog('addEditDossierAttribute', $event, { dossierAttribute, dossierTemplateId }, async () =>
|
||||
this._loadData(),
|
||||
const ref = this._dialog.open<AddEditDossierAttributeDialogComponent, AddEditDossierAttributeDialogData, boolean>(
|
||||
AddEditDossierAttributeDialogComponent,
|
||||
{
|
||||
...defaultDialogConfig,
|
||||
autoFocus: true,
|
||||
data: { dossierAttribute, dossierTemplateId },
|
||||
},
|
||||
);
|
||||
|
||||
const result = await firstValueFrom(ref.afterClosed());
|
||||
|
||||
if (result) {
|
||||
await this.#loadData();
|
||||
}
|
||||
}
|
||||
|
||||
private async _loadData() {
|
||||
async #loadData() {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._dossierAttributesService.loadAll(this.#dossierTemplateId));
|
||||
this._loadingService.stop();
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { DossierAttributesListingScreenComponent } from './dossier-attributes-listing-screen.component';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import {
|
||||
CircleButtonComponent,
|
||||
IconButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IqserHelpModeModule,
|
||||
IqserListingModule,
|
||||
IqserRoutes,
|
||||
} from '@iqser/common-ui';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
|
||||
const routes: IqserRoutes = [
|
||||
{
|
||||
path: '',
|
||||
component: DossierAttributesListingScreenComponent,
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [DossierAttributesListingScreenComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(routes),
|
||||
TranslateModule,
|
||||
CircleButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IconButtonComponent,
|
||||
IqserHelpModeModule,
|
||||
MatTooltipModule,
|
||||
IqserListingModule,
|
||||
],
|
||||
})
|
||||
export class DossierAttributesListingModule {}
|
||||
@ -51,8 +51,7 @@
|
||||
[label]="'add-edit-dossier-state.save' | translate"
|
||||
[submit]="true"
|
||||
[type]="iconButtonTypes.primary"
|
||||
>
|
||||
</iqser-icon-button>
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -6,8 +6,8 @@ import { DossierStatesService } from '@services/entity-services/dossier-states.s
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
|
||||
interface DialogData {
|
||||
readonly dossierState: IDossierState;
|
||||
export interface AddEditDossierStateDialogData {
|
||||
readonly dossierState?: IDossierState;
|
||||
readonly dossierTemplateId: string;
|
||||
}
|
||||
|
||||
@ -25,7 +25,7 @@ export class AddEditDossierStateDialogComponent extends BaseDialogComponent {
|
||||
constructor(
|
||||
private readonly _dossierStatesService: DossierStatesService,
|
||||
protected readonly _dialogRef: MatDialogRef<AddEditDossierStateDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: DialogData,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: AddEditDossierStateDialogData,
|
||||
) {
|
||||
super(_dialogRef, !!data.dossierState);
|
||||
this.form = this.#getForm();
|
||||
@ -4,7 +4,7 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<div class="heading">{{ 'confirm-delete-dossier-state.warning' | translate : translateArgs }}</div>
|
||||
<div [innerHTML]="'confirm-delete-dossier-state.warning' | translate : translateArgs" class="heading"></div>
|
||||
|
||||
<form *ngIf="data.dossierCount !== 0 && data.otherStates.length > 0" [formGroup]="form" class="mt-16">
|
||||
<div class="iqser-input-group">
|
||||
@ -1,74 +1,66 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { DossierState } from '@red/domain';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { firstValueFrom, forkJoin } from 'rxjs';
|
||||
import { combineLatest, firstValueFrom } from 'rxjs';
|
||||
import { DossierStatesService } from '@services/entity-services/dossier-states.service';
|
||||
import { IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service';
|
||||
import { take } from 'rxjs/operators';
|
||||
|
||||
interface DialogData {
|
||||
export interface ConfirmDeleteDossierStateDialogData {
|
||||
readonly toBeDeletedState: DossierState;
|
||||
readonly otherStates: DossierState[];
|
||||
readonly dossierCount: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-confirm-delete-dossier-state-dialog',
|
||||
templateUrl: './confirm-delete-dossier-state-dialog.component.html',
|
||||
styleUrls: ['./confirm-delete-dossier-state-dialog.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ConfirmDeleteDossierStateDialogComponent {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly form: UntypedFormGroup;
|
||||
readonly form = this.#form;
|
||||
readonly translateArgs = {
|
||||
name: this.data.toBeDeletedState.name,
|
||||
count: this.data.dossierCount,
|
||||
};
|
||||
|
||||
constructor(
|
||||
private readonly _formBuilder: UntypedFormBuilder,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _dossierStatesService: DossierStatesService,
|
||||
private readonly _dialogRef: MatDialogRef<ConfirmDeleteDossierStateDialogComponent>,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _archivedDossiersService: ArchivedDossiersService,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: DialogData,
|
||||
) {
|
||||
this.form = this.#getForm();
|
||||
}
|
||||
|
||||
get translateArgs() {
|
||||
return {
|
||||
name: this.data.toBeDeletedState.name,
|
||||
count: this.data.dossierCount,
|
||||
};
|
||||
}
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: ConfirmDeleteDossierStateDialogData,
|
||||
) {}
|
||||
|
||||
get label(): string {
|
||||
return this.#replaceDossierStatusId ? _('confirm-delete-dossier-state.delete-replace') : _('confirm-delete-dossier-state.delete');
|
||||
}
|
||||
|
||||
get #replaceDossierStatusId(): string {
|
||||
return this.form.get('replace').value ? this.form.get('replaceDossierStatusId').value : undefined;
|
||||
return this.form.controls.replace.value ? this.form.controls.replaceDossierStatusId.value : undefined;
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._dossierStatesService.deleteState(this.data.toBeDeletedState, this.#replaceDossierStatusId));
|
||||
await firstValueFrom(
|
||||
forkJoin([this._activeDossiersService.loadAll().pipe(take(1)), this._archivedDossiersService.loadAll().pipe(take(1))]),
|
||||
);
|
||||
this._toaster.success(_('confirm-delete-dossier-state.success'));
|
||||
this._dialogRef.close();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
#getForm(): UntypedFormGroup {
|
||||
get #form() {
|
||||
return this._formBuilder.group({
|
||||
replace: [false],
|
||||
replaceDossierStatusId: [null],
|
||||
});
|
||||
}
|
||||
|
||||
async save() {
|
||||
this._loadingService.start();
|
||||
|
||||
await this._dossierStatesService.deleteState(this.data.toBeDeletedState, this.#replaceDossierStatusId);
|
||||
await firstValueFrom(combineLatest([this._activeDossiersService.loadAll(), this._archivedDossiersService.loadAll()]));
|
||||
|
||||
this._toaster.success(_('confirm-delete-dossier-state.success'));
|
||||
this._dialogRef.close();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
@ -1,101 +0,0 @@
|
||||
<section>
|
||||
<div class="page-header">
|
||||
<redaction-dossier-template-breadcrumbs class="flex-1"></redaction-dossier-template-breadcrumbs>
|
||||
|
||||
<div class="actions flex-1">
|
||||
<redaction-dossier-template-actions></redaction-dossier-template-actions>
|
||||
|
||||
<iqser-circle-button
|
||||
[routerLink]="['../..']"
|
||||
[tooltip]="'common.close' | translate"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-inner">
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<redaction-admin-side-nav type="dossierTemplates"></redaction-admin-side-nav>
|
||||
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="80"
|
||||
[noDataText]="'dossier-states-listing.no-data.title' | translate"
|
||||
[noMatchText]="'dossier-states-listing.no-match.title' | translate"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
|
||||
<div class="right-container">
|
||||
<redaction-donut-chart
|
||||
*ngIf="chartConfig$ | async as chartConfig"
|
||||
[config]="chartConfig"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitles]="['dossier-states-listing.chart.dossier-states' | translate: { count: chartConfig.length }]"
|
||||
[totalType]="'simpleLabel'"
|
||||
></redaction-donut-chart>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ng-template #headerTemplate>
|
||||
<div class="table-header-actions">
|
||||
<iqser-input-with-action
|
||||
[(value)]="searchService.searchValue"
|
||||
[placeholder]="'dossier-states-listing.search' | translate"
|
||||
></iqser-input-with-action>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="openAddEditStateDialog($event)"
|
||||
*ngIf="permissionsService.canPerformDossierStatesActions()"
|
||||
[iqserHelpMode]="'create_new_dossier_state'"
|
||||
[label]="'dossier-states-listing.add-new' | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<div *ngIf="cast(entity) as state">
|
||||
<div class="cell">
|
||||
<div class="flex-align-items-center">
|
||||
<div [style.background-color]="state.color" class="dossier-state-square"></div>
|
||||
<div [matTooltip]="state.name" class="state-name clamp-1" matTooltipPosition="above">{{ state.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell center">
|
||||
<span class="small-label">{{ state.rank }}</span>
|
||||
</div>
|
||||
|
||||
<div class="cell center">
|
||||
<span class="small-label">{{ state.dossierCount }}</span>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div *ngIf="permissionsService.canPerformDossierStatesActions()" class="action-buttons">
|
||||
<div [iqserHelpMode]="'edit_delete_dossier_state'">
|
||||
<iqser-circle-button
|
||||
(action)="openAddEditStateDialog($event, state)"
|
||||
[tooltip]="'dossier-states-listing.action.edit' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteStateDialog($event, state)"
|
||||
[tooltip]="'dossier-states-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
@ -0,0 +1,44 @@
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="80"
|
||||
[noDataText]="'dossier-states-listing.no-data.title' | translate"
|
||||
[noMatchText]="'dossier-states-listing.no-match.title' | translate"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
|
||||
<div class="right-container">
|
||||
<redaction-donut-chart
|
||||
*ngIf="chartConfig$ | async as chartConfig"
|
||||
[config]="chartConfig"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitles]="['dossier-states-listing.chart.dossier-states' | translate : { count: chartConfig.length }]"
|
||||
[totalType]="'simpleLabel'"
|
||||
></redaction-donut-chart>
|
||||
</div>
|
||||
|
||||
<ng-template #headerTemplate>
|
||||
<div class="table-header-actions">
|
||||
<iqser-input-with-action
|
||||
[(value)]="searchService.searchValue"
|
||||
[placeholder]="'dossier-states-listing.search' | translate"
|
||||
></iqser-input-with-action>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="openAddStateDialog()"
|
||||
*ngIf="permissionsService.canPerformDossierStatesActions()"
|
||||
[iqserHelpMode]="'create_new_dossier_state'"
|
||||
[label]="'dossier-states-listing.add-new' | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<redaction-dossier-states-table-item [state]="entity"></redaction-dossier-states-table-item>
|
||||
</ng-template>
|
||||
@ -0,0 +1,8 @@
|
||||
:host {
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
.right-container {
|
||||
padding: 50px 26px 0;
|
||||
width: 250px;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
defaultDialogConfig,
|
||||
getParam,
|
||||
IconButtonTypes,
|
||||
ListingComponent,
|
||||
@ -8,35 +8,37 @@ import {
|
||||
SortingOrders,
|
||||
TableColumnConfig,
|
||||
} from '@iqser/common-ui';
|
||||
import { DonutChartConfig, DossierState, IDossierState } from '@red/domain';
|
||||
import { type DonutChartConfig, DOSSIER_TEMPLATE_ID, type DossierState } from '@red/domain';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { DossierStatesService } from '@services/entity-services/dossier-states.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
AddEditDossierStateDialogComponent,
|
||||
AddEditDossierStateDialogData,
|
||||
} from '../add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-states-listing-screen.component.html',
|
||||
styleUrls: ['./dossier-states-listing-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: listingProvidersFactory(DossierStatesListingScreenComponent),
|
||||
})
|
||||
export class DossierStatesListingScreenComponent extends ListingComponent<DossierState> implements OnInit, OnDestroy {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly tableHeaderLabel = _('dossier-states-listing.table-header.title');
|
||||
readonly tableColumnConfigs: TableColumnConfig<DossierState>[] = [
|
||||
{ label: _('dossier-states-listing.table-col-names.name'), sortByKey: 'name', width: '3fr' },
|
||||
{ label: _('dossier-states-listing.table-col-names.rank'), sortByKey: 'rank', class: 'flex-center' },
|
||||
{ label: _('dossier-states-listing.table-col-names.dossiers-count'), class: 'flex-center' },
|
||||
];
|
||||
chartConfig$: Observable<DonutChartConfig[]>;
|
||||
readonly #dossierTemplateId = getParam('dossierTemplateId');
|
||||
readonly chartConfig$: Observable<DonutChartConfig[]>;
|
||||
readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
|
||||
|
||||
constructor(
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _dossierStatesMapService: DossierStatesMapService,
|
||||
private readonly _dossierStatesService: DossierStatesService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
@ -56,21 +58,13 @@ export class DossierStatesListingScreenComponent extends ListingComponent<Dossie
|
||||
await firstValueFrom(this._dossierStatesService.loadAllForTemplate(this.#dossierTemplateId));
|
||||
}
|
||||
|
||||
openAddEditStateDialog($event: MouseEvent, dossierState?: IDossierState) {
|
||||
const data = {
|
||||
dossierState,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
};
|
||||
this._dialogService.openDialog('addEditDossierState', $event, data);
|
||||
}
|
||||
|
||||
openConfirmDeleteStateDialog($event: MouseEvent, dossierState: DossierState) {
|
||||
const data = {
|
||||
toBeDeletedState: dossierState,
|
||||
otherStates: this.entitiesService.all.filter(state => state.id !== dossierState.id),
|
||||
dossierCount: dossierState.dossierCount,
|
||||
};
|
||||
this._dialogService.openDialog('deleteDossierState', $event, data);
|
||||
openAddStateDialog() {
|
||||
this._dialog.open<AddEditDossierStateDialogComponent, AddEditDossierStateDialogData>(AddEditDossierStateDialogComponent, {
|
||||
...defaultDialogConfig,
|
||||
data: {
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
#chartConfig(states: DossierState[]): DonutChartConfig[] {
|
||||
@ -0,0 +1,62 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { DossierStatesListingScreenComponent } from './dossier-states-listing-screen/dossier-states-listing-screen.component';
|
||||
import { DossierStatesTableItemComponent } from './dossier-states-table-item/dossier-states-table-item.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import {
|
||||
CircleButtonComponent,
|
||||
IconButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IqserHelpModeModule,
|
||||
IqserListingModule,
|
||||
} from '@iqser/common-ui';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { DonutChartComponent } from '@shared/components/donut-chart/donut-chart.component';
|
||||
import { AdminSideNavComponent } from '../../shared/components/admin-side-nav/admin-side-nav.component';
|
||||
import { DossierTemplateActionsComponent } from '../../shared/components/dossier-template-actions/dossier-template-actions.component';
|
||||
import { DossierTemplateBreadcrumbsComponent } from '../../shared/components/dossier-template-breadcrumbs/dossier-template-breadcrumbs.component';
|
||||
import { AddEditDossierStateDialogComponent } from './add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { ColorPickerModule } from 'ngx-color-picker';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { ConfirmDeleteDossierStateDialogComponent } from './confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component';
|
||||
import { MatLegacyCheckboxModule } from '@angular/material/legacy-checkbox';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
DossierStatesListingScreenComponent,
|
||||
DossierStatesTableItemComponent,
|
||||
AddEditDossierStateDialogComponent,
|
||||
ConfirmDeleteDossierStateDialogComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: DossierStatesListingScreenComponent,
|
||||
},
|
||||
]),
|
||||
MatDialogModule,
|
||||
CircleButtonComponent,
|
||||
IqserHelpModeModule,
|
||||
MatTooltipModule,
|
||||
IconButtonComponent,
|
||||
TranslateModule,
|
||||
IqserListingModule,
|
||||
DonutChartComponent,
|
||||
AdminSideNavComponent,
|
||||
DossierTemplateActionsComponent,
|
||||
InputWithActionComponent,
|
||||
DossierTemplateBreadcrumbsComponent,
|
||||
ReactiveFormsModule,
|
||||
ColorPickerModule,
|
||||
MatIconModule,
|
||||
MatLegacyCheckboxModule,
|
||||
MatSelectModule,
|
||||
],
|
||||
})
|
||||
export class DossierStatesListingModule {}
|
||||
@ -0,0 +1,34 @@
|
||||
<div class="cell">
|
||||
<div class="flex-align-items-center">
|
||||
<div [style.background-color]="state.color" class="dossier-state-square"></div>
|
||||
<div [matTooltip]="state.name" class="state-name clamp-1" matTooltipPosition="above">{{ state.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell center">
|
||||
<span class="small-label">{{ state.rank }}</span>
|
||||
</div>
|
||||
|
||||
<div class="cell center">
|
||||
<span class="small-label">{{ state.dossierCount }}</span>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div *ngIf="permissionsService.canPerformDossierStatesActions()" class="action-buttons">
|
||||
<div [iqserHelpMode]="'edit_delete_dossier_state'">
|
||||
<iqser-circle-button
|
||||
(action)="openEditStateDialog(state)"
|
||||
[tooltip]="'dossier-states-listing.action.edit' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteStateDialog(state)"
|
||||
[tooltip]="'dossier-states-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -12,11 +12,6 @@
|
||||
color: var(--iqser-text);
|
||||
}
|
||||
|
||||
.right-container {
|
||||
padding: 50px 26px 0;
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.action-buttons > div {
|
||||
display: flex;
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
import { Component, inject, Input } from '@angular/core';
|
||||
import { CircleButtonTypes, defaultDialogConfig, EntitiesService } from '@iqser/common-ui';
|
||||
import { DossierState, IDossierState } from '@red/domain';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import {
|
||||
AddEditDossierStateDialogComponent,
|
||||
AddEditDossierStateDialogData,
|
||||
} from '../add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
ConfirmDeleteDossierStateDialogComponent,
|
||||
ConfirmDeleteDossierStateDialogData,
|
||||
} from '../confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-states-table-item',
|
||||
templateUrl: './dossier-states-table-item.component.html',
|
||||
styleUrls: ['./dossier-states-table-item.component.scss'],
|
||||
})
|
||||
export class DossierStatesTableItemComponent {
|
||||
@Input() state: DossierState;
|
||||
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly permissionsService = inject(PermissionsService);
|
||||
readonly #dialog = inject(MatDialog);
|
||||
readonly #entitiesService = inject(EntitiesService);
|
||||
|
||||
openConfirmDeleteStateDialog(dossierState: DossierState) {
|
||||
const data: ConfirmDeleteDossierStateDialogData = {
|
||||
toBeDeletedState: dossierState,
|
||||
otherStates: this.#entitiesService.all.filter(s => s.id !== dossierState.id),
|
||||
dossierCount: dossierState.dossierCount,
|
||||
};
|
||||
|
||||
this.#dialog.open<ConfirmDeleteDossierStateDialogComponent, ConfirmDeleteDossierStateDialogData>(
|
||||
ConfirmDeleteDossierStateDialogComponent,
|
||||
{
|
||||
...defaultDialogConfig,
|
||||
data,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
openEditStateDialog(dossierState: IDossierState) {
|
||||
this.#dialog.open<AddEditDossierStateDialogComponent, AddEditDossierStateDialogData>(AddEditDossierStateDialogComponent, {
|
||||
...defaultDialogConfig,
|
||||
data: {
|
||||
dossierState,
|
||||
dossierTemplateId: dossierState.dossierTemplateId,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -18,21 +18,21 @@
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
buttonId="dossier-template-listing-bulk-delete-btn"
|
||||
(action)="openBulkDeleteTemplatesDialog($event)"
|
||||
(action)="openBulkDeleteTemplatesDialog()"
|
||||
*allow="roles.templates.write; if: currentUser.isAdmin && (listingService.areSomeSelected$ | async)"
|
||||
[icon]="'iqser:trash'"
|
||||
[tooltip]="'dossier-templates-listing.bulk.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
buttonId="dossier-template-listing-bulk-delete-btn"
|
||||
></iqser-circle-button>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #headerTemplate>
|
||||
<div class="table-header-actions">
|
||||
<iqser-input-with-action
|
||||
inputId="dossier-template-listing-search-input"
|
||||
[(value)]="searchService.searchValue"
|
||||
[placeholder]="'dossier-templates-listing.search' | translate"
|
||||
inputId="dossier-template-listing-search-input"
|
||||
></iqser-input-with-action>
|
||||
|
||||
<iqser-icon-button
|
||||
|
||||
@ -54,14 +54,14 @@ export class DossierTemplatesListingScreenComponent extends ListingComponent<Dos
|
||||
super();
|
||||
}
|
||||
|
||||
openBulkDeleteTemplatesDialog($event?: MouseEvent) {
|
||||
return this._dialogService.openDialog('confirm', $event, null, () => {
|
||||
openBulkDeleteTemplatesDialog() {
|
||||
return this._dialogService.openDialog('confirm', null, () => {
|
||||
this._loadingService.loadWhile(this._deleteTemplates());
|
||||
});
|
||||
}
|
||||
|
||||
openAddDossierTemplateDialog() {
|
||||
this._dialogService.openDialog('addEditCloneDossierTemplate', null, null);
|
||||
this._dialogService.openDialog('addEditCloneDossierTemplate');
|
||||
}
|
||||
|
||||
private async _deleteTemplates(templateIds = this.listingService.selected.map(d => d.dossierTemplateId)) {
|
||||
|
||||
@ -4,18 +4,20 @@ import { RouterModule } from '@angular/router';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { TableItemComponent } from './table-item/table-item.component';
|
||||
import { DossierTemplatesListingScreenComponent } from './dossier-templates-listing-screen/dossier-templates-listing-screen.component';
|
||||
import { SharedAdminModule } from '../../shared/shared-admin.module';
|
||||
import {
|
||||
IqserButtonsModule,
|
||||
CircleButtonComponent,
|
||||
IconButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IqserAllowDirective,
|
||||
IqserHelpModeModule,
|
||||
IqserInputsModule,
|
||||
IqserListingModule,
|
||||
IqserPermissionsModule,
|
||||
IqserRoutes,
|
||||
IqserUsersModule,
|
||||
} from '@iqser/common-ui';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { DossierTemplateActionsComponent } from '../../shared/components/dossier-template-actions/dossier-template-actions.component';
|
||||
|
||||
const routes = [{ path: '', component: DossierTemplatesListingScreenComponent }];
|
||||
const routes: IqserRoutes = [{ path: '', component: DossierTemplatesListingScreenComponent }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [TableItemComponent, DossierTemplatesListingScreenComponent],
|
||||
@ -23,14 +25,15 @@ const routes = [{ path: '', component: DossierTemplatesListingScreenComponent }]
|
||||
RouterModule.forChild(routes),
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
SharedAdminModule,
|
||||
IqserUsersModule,
|
||||
TranslateModule,
|
||||
IqserInputsModule,
|
||||
IqserButtonsModule,
|
||||
IqserListingModule,
|
||||
IqserHelpModeModule,
|
||||
IqserPermissionsModule,
|
||||
DossierTemplateActionsComponent,
|
||||
CircleButtonComponent,
|
||||
IconButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IqserAllowDirective,
|
||||
],
|
||||
})
|
||||
export class DossierTemplatesListingModule {}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
<div class="small-label stats-subtitle">
|
||||
<div *ngIf="stats$ | async as stats">
|
||||
<mat-icon svgIcon="red:dictionary"></mat-icon>
|
||||
{{ 'dossier-templates-listing.entities' | translate: { length: stats.numberOfDictionaries } }}
|
||||
{{ 'dossier-templates-listing.entities' | translate : { length: stats.numberOfDictionaries } }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -22,25 +22,25 @@
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ dossierTemplate.dateAdded | date: 'd MMM yyyy' }}
|
||||
{{ dossierTemplate.dateAdded | date : 'd MMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ dossierTemplate.dateModified | date: 'd MMM yyyy' }}
|
||||
{{ dossierTemplate.dateModified | date : 'd MMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ dossierTemplate.validFrom | date: 'd MMM yyyy' }}
|
||||
{{ dossierTemplate.validFrom | date : 'd MMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div class="small-label">
|
||||
{{ dossierTemplate.validTo | date: 'd MMM yyyy' }}
|
||||
{{ dossierTemplate.validTo | date : 'd MMM yyyy' }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
<div class="small-label">
|
||||
{{ translations[dossierTemplate.dossierTemplateStatus] | translate }}
|
||||
</div>
|
||||
|
||||
<redaction-dossier-template-actions
|
||||
[dossierTemplateId]="dossierTemplate.dossierTemplateId"
|
||||
class="actions-container"
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteEntitiesDialog($event)"
|
||||
(action)="openDeleteEntitiesDialog()"
|
||||
*ngIf="permissionsService.canDeleteEntities(listingService.selected)"
|
||||
[tooltip]="'entities-listing.bulk.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
@ -58,8 +58,8 @@
|
||||
(action)="openAddEntityDialog()"
|
||||
*ngIf="permissionsService.canEditEntities()"
|
||||
[iqserHelpMode]="'create_new_entity'"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
[label]="'entities-listing.add-new' | translate"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
></iqser-icon-button>
|
||||
@ -101,7 +101,7 @@
|
||||
<div class="action-buttons">
|
||||
<div [iqserHelpMode]="'edit_delete_entities'" [overlappingElements]="['USER_MENU']">
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteEntitiesDialog($event, [dict])"
|
||||
(action)="openDeleteEntitiesDialog([dict])"
|
||||
*ngIf="permissionsService.canDeleteEntities(dict)"
|
||||
[tooltip]="'entities-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
|
||||
@ -48,8 +48,8 @@ export class EntitiesListingScreenComponent extends ListingComponent<Dictionary>
|
||||
this.templateStats$ = this._dossierTemplateStatsService.watch$(this.#dossierTemplateId).pipe(tap(() => this._loadDictionaryData()));
|
||||
}
|
||||
|
||||
openDeleteEntitiesDialog($event?: MouseEvent, types = this.listingService.selected) {
|
||||
this._dialogService.openDialog('confirm', $event, null, async () => {
|
||||
openDeleteEntitiesDialog(types = this.listingService.selected) {
|
||||
this._dialogService.openDialog('confirm', null, async () => {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._dictionaryService.deleteDictionaries(
|
||||
@ -62,8 +62,8 @@ export class EntitiesListingScreenComponent extends ListingComponent<Dictionary>
|
||||
});
|
||||
}
|
||||
|
||||
openAddEntityDialog($event?: MouseEvent) {
|
||||
this._dialogService.openDialog('addEntity', $event, { dossierTemplateId: this.#dossierTemplateId });
|
||||
openAddEntityDialog() {
|
||||
this._dialogService.openDialog('addEntity', { dossierTemplateId: this.#dossierTemplateId });
|
||||
}
|
||||
|
||||
private _loadDictionaryData(): void {
|
||||
|
||||
@ -6,9 +6,8 @@ import { DictionaryScreenComponent } from './screens/dictionary/dictionary-scree
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
import { EntityInfoComponent } from './screens/entity-info/entity-info.component';
|
||||
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||
import { SharedAdminModule } from '../../shared/shared-admin.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { IqserHelpModeModule, IqserPermissionsModule, IqserScrollbarModule } from '@iqser/common-ui';
|
||||
import { HasScrollbarDirective, IconButtonComponent, IqserDenyDirective, IqserHelpModeModule } from '@iqser/common-ui';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'info', pathMatch: 'full' },
|
||||
@ -38,14 +37,14 @@ const routes: Routes = [
|
||||
declarations: [DictionaryScreenComponent, EntityInfoComponent],
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
SharedAdminModule,
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
MonacoEditorModule,
|
||||
TranslateModule,
|
||||
IqserScrollbarModule,
|
||||
IqserHelpModeModule,
|
||||
IqserPermissionsModule,
|
||||
IconButtonComponent,
|
||||
HasScrollbarDirective,
|
||||
IqserDenyDirective,
|
||||
],
|
||||
})
|
||||
export class EntitiesModule {}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
@use 'common-mixins';
|
||||
|
||||
.options-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@ -7,3 +9,7 @@
|
||||
margin-right: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
@include common-mixins.line-clamp(1);
|
||||
}
|
||||
@ -1,9 +1,16 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { Validators } from '@angular/forms';
|
||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { fileAttributeTypesTranslations } from '@translations/file-attribute-types-translations';
|
||||
import { BaseDialogComponent } from '@iqser/common-ui';
|
||||
import { BaseDialogComponent, CircleButtonComponent, IconButtonComponent } from '@iqser/common-ui';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { NgForOf } from '@angular/common';
|
||||
import { MatLegacySlideToggleModule } from '@angular/material/legacy-slide-toggle';
|
||||
import { MatLegacyCheckboxModule as MatCheckboxModule } from '@angular/material/legacy-checkbox';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
|
||||
export interface AddEditFileAttributeDialogData {
|
||||
readonly fileAttribute: IFileAttributeConfig;
|
||||
@ -15,6 +22,19 @@ export interface AddEditFileAttributeDialogData {
|
||||
@Component({
|
||||
templateUrl: './add-edit-file-attribute-dialog.component.html',
|
||||
styleUrls: ['./add-edit-file-attribute-dialog.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
NgForOf,
|
||||
MatLegacySlideToggleModule,
|
||||
MatCheckboxModule,
|
||||
MatTooltipModule,
|
||||
IconButtonComponent,
|
||||
CircleButtonComponent,
|
||||
],
|
||||
})
|
||||
export class AddEditFileAttributeDialogComponent extends BaseDialogComponent {
|
||||
readonly DISPLAYED_FILTERABLE_LIMIT = 3;
|
||||
@ -30,7 +50,7 @@ export class AddEditFileAttributeDialogComponent extends BaseDialogComponent {
|
||||
};
|
||||
|
||||
constructor(
|
||||
protected readonly _dialogRef: MatDialogRef<AddEditFileAttributeDialogComponent>,
|
||||
protected readonly _dialogRef: MatDialogRef<AddEditFileAttributeDialogComponent, IFileAttributeConfig>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: AddEditFileAttributeDialogData,
|
||||
) {
|
||||
super(_dialogRef, !!data.fileAttribute);
|
||||
@ -1,23 +1,37 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { ReactiveFormsModule, Validators } from '@angular/forms';
|
||||
import { FileAttributeEncodingTypes, IFileAttributesConfig } from '@red/domain';
|
||||
import { fileAttributeEncodingTypesTranslations } from '@translations/file-attribute-encoding-types-translations';
|
||||
import { BaseDialogComponent } from '@iqser/common-ui';
|
||||
import { BaseDialogComponent, CircleButtonComponent, IconButtonComponent } from '@iqser/common-ui';
|
||||
import { MatLegacySlideToggleModule } from '@angular/material/legacy-slide-toggle';
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
|
||||
@Component({
|
||||
templateUrl: './file-attributes-configurations-dialog.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
MatLegacySlideToggleModule,
|
||||
NgIf,
|
||||
TranslateModule,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
NgForOf,
|
||||
IconButtonComponent,
|
||||
CircleButtonComponent,
|
||||
],
|
||||
})
|
||||
export class FileAttributesConfigurationsDialogComponent extends BaseDialogComponent {
|
||||
readonly encodingTypeOptions = Object.keys(FileAttributeEncodingTypes);
|
||||
readonly translations = fileAttributeEncodingTypesTranslations;
|
||||
readonly #configuration = this._data.config;
|
||||
readonly #configuration = inject<IFileAttributesConfig>(MAT_DIALOG_DATA);
|
||||
|
||||
constructor(
|
||||
protected readonly _dialogRef: MatDialogRef<FileAttributesConfigurationsDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) private readonly _data: { config: IFileAttributesConfig; dossierTemplateId: string },
|
||||
) {
|
||||
constructor(protected readonly _dialogRef: MatDialogRef<FileAttributesConfigurationsDialogComponent, IFileAttributesConfig>) {
|
||||
super(_dialogRef, true);
|
||||
this.form = this.#getForm();
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
@ -39,7 +53,7 @@ export class FileAttributesConfigurationsDialogComponent extends BaseDialogCompo
|
||||
this._dialogRef.close(this.#getConfiguration());
|
||||
}
|
||||
|
||||
#getConfiguration() {
|
||||
#getConfiguration(): IFileAttributesConfig {
|
||||
const supportCsvMapping = this.form.get('supportCsvMapping').value;
|
||||
if (supportCsvMapping) {
|
||||
return {
|
||||
@ -56,7 +70,7 @@ export class FileAttributesConfigurationsDialogComponent extends BaseDialogCompo
|
||||
};
|
||||
}
|
||||
|
||||
#getForm(): UntypedFormGroup {
|
||||
#getForm() {
|
||||
return this._formBuilder.group({
|
||||
supportCsvMapping: [!!this.#configuration.filenameMappingColumnHeaderName],
|
||||
keyColumn: [this.#configuration.filenameMappingColumnHeaderName || '', [Validators.required]],
|
||||
@ -10,7 +10,7 @@ import { FileAttributeConfig, FileAttributeConfigTypes, FileAttributeEncodingTyp
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
import { fileAttributeEncodingTypesTranslations } from '@translations/file-attribute-encoding-types-translations';
|
||||
|
||||
interface IFileAttributesCSVImportData {
|
||||
export interface IFileAttributesCSVImportData {
|
||||
readonly csv: File;
|
||||
readonly dossierTemplateId: string;
|
||||
readonly existingConfiguration: IFileAttributesConfig;
|
||||
@ -43,7 +43,7 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<IFi
|
||||
constructor(
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _formBuilder: UntypedFormBuilder,
|
||||
readonly dialogRef: MatDialogRef<FileAttributesCsvImportDialogComponent>,
|
||||
readonly dialogRef: MatDialogRef<FileAttributesCsvImportDialogComponent, boolean>,
|
||||
private readonly _fileAttributesService: FileAttributesService,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: IFileAttributesCSVImportData,
|
||||
) {
|
||||
@ -0,0 +1,47 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FileAttributesCsvImportDialogComponent } from './file-attributes-csv-import-dialog.component';
|
||||
import { ActiveFieldsListingComponent } from './active-fields-listing/active-fields-listing.component';
|
||||
import {
|
||||
ChevronButtonComponent,
|
||||
CircleButtonComponent,
|
||||
EditableInputComponent,
|
||||
IconButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IqserListingModule,
|
||||
RoundCheckboxComponent,
|
||||
} from '@iqser/common-ui';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||
import { MatSelectModule } from '@angular/material/select';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { MatLegacySlideToggleModule } from '@angular/material/legacy-slide-toggle';
|
||||
|
||||
@NgModule({
|
||||
declarations: [FileAttributesCsvImportDialogComponent, ActiveFieldsListingComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
CircleButtonComponent,
|
||||
TranslateModule,
|
||||
MatDialogModule,
|
||||
IconButtonComponent,
|
||||
InputWithActionComponent,
|
||||
MatFormFieldModule,
|
||||
MatSelectModule,
|
||||
ReactiveFormsModule,
|
||||
MatAutocompleteModule,
|
||||
MatInputModule,
|
||||
IqserListingModule,
|
||||
MatMenuModule,
|
||||
ChevronButtonComponent,
|
||||
EditableInputComponent,
|
||||
FormsModule,
|
||||
MatLegacySlideToggleModule,
|
||||
RoundCheckboxComponent,
|
||||
],
|
||||
})
|
||||
export class FileAttributesCsvImportDialogModule {}
|
||||
@ -1,41 +1,18 @@
|
||||
<section>
|
||||
<div class="page-header">
|
||||
<redaction-dossier-template-breadcrumbs class="flex-1"></redaction-dossier-template-breadcrumbs>
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[bulkActions]="bulkActions"
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="80"
|
||||
[noDataText]="'file-attributes-listing.no-data.title' | translate"
|
||||
[noMatchText]="'file-attributes-listing.no-match.title' | translate"
|
||||
[selectionEnabled]="permissionsService.canEditGlobalFileAttributes()"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
|
||||
<div class="actions flex-1">
|
||||
<redaction-dossier-template-actions></redaction-dossier-template-actions>
|
||||
|
||||
<iqser-circle-button
|
||||
[routerLink]="['../..']"
|
||||
[tooltip]="'common.close' | translate"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-inner">
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<redaction-admin-side-nav type="dossierTemplates"></redaction-admin-side-nav>
|
||||
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[bulkActions]="bulkActions"
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="80"
|
||||
[noDataText]="'file-attributes-listing.no-data.title' | translate"
|
||||
[noMatchText]="'file-attributes-listing.no-match.title' | translate"
|
||||
[selectionEnabled]="permissionsService.canEditGlobalFileAttributes()"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
|
||||
<div class="right-container"></div>
|
||||
</div>
|
||||
</section>
|
||||
<div class="right-container"></div>
|
||||
|
||||
<ng-template #impactedTemplates let-data="data">
|
||||
<ul class="templates-container flex">
|
||||
@ -45,7 +22,7 @@
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteAttributeDialog($event)"
|
||||
(action)="openConfirmDeleteAttributeDialog()"
|
||||
*ngIf="permissionsService.canEditGlobalFileAttributes() && (listingService.areSomeSelected$ | async)"
|
||||
[tooltip]="'file-attributes-listing.bulk-actions.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
@ -53,6 +30,7 @@
|
||||
></iqser-circle-button>
|
||||
</ng-template>
|
||||
|
||||
<!--TODO: move to a separate component-->
|
||||
<ng-template #headerTemplate>
|
||||
<div class="table-header-actions">
|
||||
<iqser-input-with-action
|
||||
@ -73,7 +51,7 @@
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openConfigurationsDialog($event)"
|
||||
(action)="openConfigurationsDialog()"
|
||||
*allow="roles.fileAttributes.writeConfig; if: currentUser.isAdmin"
|
||||
[iqserHelpMode]="'upload_file_attribute'"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
@ -84,7 +62,7 @@
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="openAddEditAttributeDialog($event)"
|
||||
(action)="openAddEditAttributeDialog()"
|
||||
*ngIf="permissionsService.canEditGlobalFileAttributes()"
|
||||
[iqserHelpMode]="'create_new_file_attribute'"
|
||||
[label]="'file-attributes-listing.add-new' | translate"
|
||||
@ -95,6 +73,7 @@
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<!--TODO: move to a separate component-->
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<div *ngIf="cast(entity) as attribute">
|
||||
<div class="label cell">
|
||||
@ -134,13 +113,14 @@
|
||||
<div *ngIf="permissionsService.canEditGlobalFileAttributes()" class="action-buttons">
|
||||
<div [iqserHelpMode]="'edit_delete_file_attribute'" [overlappingElements]="['USER_MENU']">
|
||||
<iqser-circle-button
|
||||
(action)="openAddEditAttributeDialog($event, attribute)"
|
||||
(action)="openAddEditAttributeDialog(attribute)"
|
||||
[tooltip]="'file-attributes-listing.action.edit' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteAttributeDialog($event, [attribute])"
|
||||
(action)="openConfirmDeleteAttributeDialog([attribute])"
|
||||
[tooltip]="'file-attributes-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { Component, ElementRef, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
defaultDialogConfig,
|
||||
getCurrentUser,
|
||||
getParam,
|
||||
IconButtonTypes,
|
||||
largeDialogConfig,
|
||||
ListingComponent,
|
||||
listingProvidersFactory,
|
||||
LoadingService,
|
||||
@ -20,11 +22,20 @@ import { firstValueFrom } from 'rxjs';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ROLES } from '@users/roles';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
AddEditFileAttributeDialogComponent,
|
||||
AddEditFileAttributeDialogData,
|
||||
} from './add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
|
||||
import {
|
||||
FileAttributesCsvImportDialogComponent,
|
||||
IFileAttributesCSVImportData,
|
||||
} from './file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
|
||||
import { FileAttributesConfigurationsDialogComponent } from './file-attributes-configurations-dialog/file-attributes-configurations-dialog.component';
|
||||
|
||||
@Component({
|
||||
templateUrl: './file-attributes-listing-screen.component.html',
|
||||
styleUrls: ['./file-attributes-listing-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: listingProvidersFactory(FileAttributesListingScreenComponent),
|
||||
})
|
||||
export class FileAttributesListingScreenComponent extends ListingComponent<FileAttributeConfig> implements OnInit, OnDestroy {
|
||||
@ -58,6 +69,7 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _fileAttributesService: FileAttributesService,
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
) {
|
||||
@ -76,65 +88,74 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
|
||||
await this.#loadData();
|
||||
}
|
||||
|
||||
openAddEditAttributeDialog($event: MouseEvent, fileAttribute?: IFileAttributeConfig) {
|
||||
async openAddEditAttributeDialog(fileAttribute?: IFileAttributeConfig) {
|
||||
const data = {
|
||||
fileAttribute,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
numberOfDisplayedAttrs: this._numberOfDisplayedAttrs,
|
||||
numberOfFilterableAttrs: this._numberOfFilterableAttrs,
|
||||
};
|
||||
this._dialogService.openDialog('addEditFileAttribute', $event, data, (newValue: IFileAttributeConfig) => {
|
||||
this._loadingService.loadWhile(this.#createNewFileAttributeAndRefreshView(newValue));
|
||||
|
||||
const ref = this._dialog.open<AddEditFileAttributeDialogComponent, AddEditFileAttributeDialogData, IFileAttributeConfig>(
|
||||
AddEditFileAttributeDialogComponent,
|
||||
{
|
||||
...defaultDialogConfig,
|
||||
autoFocus: true,
|
||||
data,
|
||||
},
|
||||
);
|
||||
|
||||
const result = await firstValueFrom(ref.afterClosed());
|
||||
this._loadingService.loadWhile(this.#createNewFileAttributeAndRefreshView(result));
|
||||
}
|
||||
|
||||
async openConfirmDeleteAttributeDialog(attributes: FileAttributeConfig[] = this.listingService.selected): Promise<void> {
|
||||
await this._dialogService.deleteAttributes(attributes, this.#dossierTemplateId, this._impactedTemplatesRef, 'file', async () => {
|
||||
this._loadingService.start();
|
||||
const ids = attributes.map(a => a.id);
|
||||
await firstValueFrom(this._fileAttributesService.deleteFileAttributes(ids, this.#dossierTemplateId));
|
||||
await firstValueFrom(this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId));
|
||||
await this.#loadData();
|
||||
});
|
||||
}
|
||||
|
||||
async openConfirmDeleteAttributeDialog(
|
||||
$event: MouseEvent,
|
||||
attributes: FileAttributeConfig[] = this.listingService.selected,
|
||||
): Promise<void> {
|
||||
await this._dialogService.deleteAttributes(
|
||||
attributes,
|
||||
this.#dossierTemplateId,
|
||||
this._impactedTemplatesRef,
|
||||
'file',
|
||||
$event,
|
||||
async () => {
|
||||
this._loadingService.start();
|
||||
const ids = attributes.map(a => a.id);
|
||||
await firstValueFrom(this._fileAttributesService.deleteFileAttributes(ids, this.#dossierTemplateId));
|
||||
await firstValueFrom(this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId));
|
||||
await this.#loadData();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
importCSV(files: FileList | File[]) {
|
||||
async importCSV(files: FileList | File[]) {
|
||||
const csv = files[0];
|
||||
this._fileInput.nativeElement.value = null;
|
||||
|
||||
this._dialogService.openDialog(
|
||||
'importFileAttributes',
|
||||
null,
|
||||
const ref = this._dialog.open<FileAttributesCsvImportDialogComponent, IFileAttributesCSVImportData, boolean>(
|
||||
FileAttributesCsvImportDialogComponent,
|
||||
{
|
||||
csv,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
existingConfiguration: this.#existingConfiguration,
|
||||
...largeDialogConfig,
|
||||
disableClose: false,
|
||||
data: {
|
||||
csv,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
existingConfiguration: this.#existingConfiguration,
|
||||
},
|
||||
},
|
||||
async () => this.#loadData(),
|
||||
);
|
||||
|
||||
const result = await firstValueFrom(ref.afterClosed());
|
||||
if (result) {
|
||||
await this.#loadData();
|
||||
}
|
||||
}
|
||||
|
||||
openConfigurationsDialog($event: MouseEvent) {
|
||||
const ref = this._dialogService.openDialog('fileAttributesConfigurations', $event, {
|
||||
config: this.#existingConfiguration,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
});
|
||||
async openConfigurationsDialog() {
|
||||
const ref = this._dialog.open<FileAttributesConfigurationsDialogComponent, IFileAttributesConfig, IFileAttributesConfig>(
|
||||
FileAttributesConfigurationsDialogComponent,
|
||||
{
|
||||
...defaultDialogConfig,
|
||||
data: this.#existingConfiguration,
|
||||
},
|
||||
);
|
||||
|
||||
ref.afterClosed().subscribe(async (configuration: IFileAttributesConfig) => {
|
||||
if (configuration) {
|
||||
await this.#setConfigAndLoadData(configuration);
|
||||
}
|
||||
});
|
||||
const configuration = await firstValueFrom(ref.afterClosed());
|
||||
|
||||
if (configuration) {
|
||||
await this.#setConfigAndLoadData(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
async #setConfigAndLoadData(configuration: IFileAttributesConfig) {
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { FileAttributesListingScreenComponent } from './file-attributes-listing-screen.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import {
|
||||
CircleButtonComponent,
|
||||
IconButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IqserAllowDirective,
|
||||
IqserHelpModeModule,
|
||||
IqserListingModule,
|
||||
IqserRoutes,
|
||||
RoundCheckboxComponent,
|
||||
} from '@iqser/common-ui';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
|
||||
const routes: IqserRoutes = [
|
||||
{
|
||||
path: '',
|
||||
component: FileAttributesListingScreenComponent,
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [FileAttributesListingScreenComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(routes),
|
||||
IqserListingModule,
|
||||
TranslateModule,
|
||||
CircleButtonComponent,
|
||||
InputWithActionComponent,
|
||||
IqserHelpModeModule,
|
||||
IqserAllowDirective,
|
||||
IconButtonComponent,
|
||||
MatIconModule,
|
||||
MatTooltipModule,
|
||||
RoundCheckboxComponent,
|
||||
],
|
||||
})
|
||||
export class FileAttributesListingModule {}
|
||||
@ -42,7 +42,7 @@ export class SmtpFormComponent extends BaseFormComponent implements OnInit {
|
||||
}
|
||||
|
||||
openAuthConfigDialog(skipDisableOnCancel?: boolean) {
|
||||
this._dialogService.openDialog('smtpAuthConfig', null, this.form.getRawValue(), null, authConfig => {
|
||||
this._dialogService.openDialog('smtpAuthConfig', this.form.getRawValue(), null, authConfig => {
|
||||
if (authConfig) {
|
||||
this.form.patchValue(authConfig);
|
||||
} else if (!skipDisableOnCancel) {
|
||||
|
||||
@ -3,7 +3,7 @@ import { CommonModule } from '@angular/common';
|
||||
import { DossierTemplateInfoScreenComponent } from './info-screen/dossier-template-info-screen.component';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { IqserButtonsModule, IqserHelpModeModule, IqserScrollbarModule, IqserUsersModule } from '@iqser/common-ui';
|
||||
import { HasScrollbarDirective, IqserHelpModeModule, IqserUsersModule } from '@iqser/common-ui';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
const routes = [{ path: '', component: DossierTemplateInfoScreenComponent }];
|
||||
@ -16,9 +16,8 @@ const routes = [{ path: '', component: DossierTemplateInfoScreenComponent }];
|
||||
SharedModule,
|
||||
IqserUsersModule,
|
||||
TranslateModule,
|
||||
IqserButtonsModule,
|
||||
IqserScrollbarModule,
|
||||
IqserHelpModeModule,
|
||||
HasScrollbarDirective,
|
||||
],
|
||||
})
|
||||
export class DossierTemplateInfoModule {}
|
||||
|
||||
@ -48,8 +48,7 @@
|
||||
[label]="'add-edit-justification.actions.save' | translate"
|
||||
[submit]="true"
|
||||
[type]="iconButtonTypes.primary"
|
||||
>
|
||||
</iqser-icon-button>
|
||||
></iqser-icon-button>
|
||||
|
||||
<div (click)="close()" class="all-caps-label cancel" translate="add-edit-justification.actions.cancel"></div>
|
||||
</div>
|
||||
|
||||
@ -2,9 +2,9 @@ import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import {
|
||||
ConfirmationDialogComponent,
|
||||
ConfirmationDialogInput,
|
||||
DialogConfig,
|
||||
DialogService,
|
||||
IConfirmationDialogData,
|
||||
LoadingService,
|
||||
TitleColors,
|
||||
} from '@iqser/common-ui';
|
||||
@ -39,7 +39,7 @@ export class JustificationsDialogService extends DialogService<DialogType> {
|
||||
}
|
||||
|
||||
confirmDelete(justifications: Justification[], dossierTemplateId: string) {
|
||||
const data = new ConfirmationDialogInput({
|
||||
const data: IConfirmationDialogData = {
|
||||
title: _('confirmation-dialog.delete-justification.title'),
|
||||
titleColor: TitleColors.WARN,
|
||||
question: _('confirmation-dialog.delete-justification.question'),
|
||||
@ -47,8 +47,9 @@ export class JustificationsDialogService extends DialogService<DialogType> {
|
||||
count: justifications.length,
|
||||
justificationName: justifications[0].name,
|
||||
},
|
||||
});
|
||||
this.openDialog('confirm', null, data, async () => {
|
||||
};
|
||||
|
||||
this.openDialog('confirm', data, async () => {
|
||||
this._loadingService.start();
|
||||
const justificationIds = justifications.map(j => j.id);
|
||||
await firstValueFrom(this._justificationService.delete(justificationIds, dossierTemplateId));
|
||||
|
||||
@ -60,7 +60,7 @@ export class JustificationsScreenComponent extends ListingComponent<Justificatio
|
||||
}
|
||||
|
||||
openAddJustificationDialog(): void {
|
||||
this._dialogService.openDialog('addEditJustification', null, { justification: null, dossierTemplateId: this.#dossierTemplateId });
|
||||
this._dialogService.openDialog('addEditJustification', { justification: null, dossierTemplateId: this.#dossierTemplateId });
|
||||
}
|
||||
|
||||
openConfirmDeleteDialog() {
|
||||
|
||||
@ -7,13 +7,22 @@ import { TableItemComponent } from './table-item/table-item.component';
|
||||
import { JustificationsDialogService } from './justifications-dialog.service';
|
||||
import { AddEditJustificationDialogComponent } from './add-edit-justification-dialog/add-edit-justification-dialog.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { IqserButtonsModule, IqserListingModule } from '@iqser/common-ui';
|
||||
import { CircleButtonComponent, HasScrollbarDirective, IconButtonComponent, IqserListingModule } from '@iqser/common-ui';
|
||||
|
||||
const routes = [{ path: '', component: JustificationsScreenComponent }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [JustificationsScreenComponent, TableItemComponent, AddEditJustificationDialogComponent],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, TranslateModule, IqserButtonsModule, IqserListingModule],
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
TranslateModule,
|
||||
IqserListingModule,
|
||||
IconButtonComponent,
|
||||
CircleButtonComponent,
|
||||
HasScrollbarDirective,
|
||||
],
|
||||
providers: [JustificationsDialogService],
|
||||
})
|
||||
export class JustificationsModule {}
|
||||
|
||||
@ -18,7 +18,7 @@ export class TableItemComponent {
|
||||
constructor(private readonly _dialogService: JustificationsDialogService) {}
|
||||
|
||||
openEditJustificationDialog() {
|
||||
this._dialogService.openDialog('addEditJustification', null, {
|
||||
this._dialogService.openDialog('addEditJustification', {
|
||||
justification: this.justification,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
});
|
||||
|
||||
@ -61,9 +61,14 @@
|
||||
<div>{{ licenseService.totalLicensedNumberOfPages }}</div>
|
||||
</div>
|
||||
|
||||
<div class="section-title all-caps-label" translate="license-info-screen.usage-details"></div>
|
||||
|
||||
<div class="row">
|
||||
<div translate="license-info-screen.analyzed-pages"></div>
|
||||
<div>{{ licenseService.currentInfo.numberOfAnalyzedPages }}</div>
|
||||
<div translate="license-info-screen.current-analyzed"></div>
|
||||
<div>
|
||||
{{ licenseService.analyzedPagesInCurrentLicensingPeriod }}
|
||||
({{ analysisPercentageOfLicense$ | async | number : '1.0-2' }}%)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
@ -71,27 +76,26 @@
|
||||
<div>{{ licenseService.currentInfo.numberOfOcrPages }}</div>
|
||||
</div>
|
||||
|
||||
<div class="section-title all-caps-label" translate="license-info-screen.usage-details"></div>
|
||||
<div *ngIf="!!licenseService.unlicensedPages" class="row">
|
||||
<div translate="license-info-screen.unlicensed-analyzed"></div>
|
||||
<div>{{ licenseService.unlicensedPages }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div
|
||||
*ngIf="licenseService.totalInfo.startDate | date : 'longDate' as startDate"
|
||||
*ngIf="licenseService.annualInfo.startDate | date : 'longDate' as startDate"
|
||||
[innerHTML]="'license-info-screen.total-analyzed' | translate : { date: startDate }"
|
||||
></div>
|
||||
<div>{{ licenseService.totalInfo.numberOfAnalyzedPages }}</div>
|
||||
|
||||
<div>{{ licenseService.annualInfo.numberOfAnalyzedPages }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div translate="license-info-screen.current-analyzed"></div>
|
||||
<div>
|
||||
{{ licenseService.currentInfo.numberOfAnalyzedPages }}
|
||||
({{ analysisPercentageOfLicense$ | async | number : '1.0-2' }}%)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!!licenseService.unlicensedInfo" class="row">
|
||||
<div translate="license-info-screen.unlicensed-analyzed"></div>
|
||||
<div>{{ licenseService.unlicensedInfo.numberOfAnalyzedPages }}</div>
|
||||
<div
|
||||
*ngIf="licenseService.annualInfo.startDate | date : 'longDate' as startDate"
|
||||
[innerHTML]="'license-info-screen.total-ocr-analyzed' | translate : { date: startDate }"
|
||||
></div>
|
||||
<div>{{ licenseService.annualInfo.numberOfOcrPages }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -50,7 +50,7 @@ export class LicenseScreenComponent {
|
||||
|
||||
getAnalysisPercentageOfLicense() {
|
||||
const totalLicensedNumberOfPages = this.licenseService.totalLicensedNumberOfPages;
|
||||
const numberOfAnalyzedPages = this.licenseService.currentInfo.numberOfAnalyzedPages;
|
||||
const numberOfAnalyzedPages = this.licenseService.analyzedPagesInCurrentLicensingPeriod;
|
||||
return totalLicensedNumberOfPages > 0 ? (numberOfAnalyzedPages / totalLicensedNumberOfPages) * 100 : 100;
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,8 @@
|
||||
<div *ngFor="let permission of mappedPermissions" class="center cell">
|
||||
<mat-slide-toggle
|
||||
(toggleChange)="togglePermission(config.searchKey, permission)"
|
||||
[checked]="config.getValue(permission)"
|
||||
[disabled]="config.isDisabled(permission)"
|
||||
[checked]="config.isChecked(permission)"
|
||||
[iqserHelpMode]="'dossier_permissions'"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
color="primary"
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { DOSSIER_TEMPLATE_ID, IPlaceholdersResponse, IReportTemplate, User } from '@red/domain';
|
||||
import { download } from '@utils/file-download-utils';
|
||||
import { ConfirmationDialogInput, getCurrentUser, getParam, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { getCurrentUser, getParam, IConfirmationDialogData, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import {
|
||||
generalPlaceholdersDescriptionsTranslations,
|
||||
@ -67,7 +67,7 @@ export class ReportsScreenComponent implements OnInit {
|
||||
}
|
||||
|
||||
deleteTemplate(template: IReportTemplate) {
|
||||
this._dialogService.openDialog('confirm', null, null, () => {
|
||||
this._dialogService.openDialog('confirm', null, () => {
|
||||
this._loadingService.loadWhile(this._deleteTemplate(template));
|
||||
});
|
||||
}
|
||||
@ -80,7 +80,7 @@ export class ReportsScreenComponent implements OnInit {
|
||||
return;
|
||||
}
|
||||
|
||||
const data = new ConfirmationDialogInput({
|
||||
const data: IConfirmationDialogData = {
|
||||
title: _('confirmation-dialog.upload-report-template.title'),
|
||||
question: _('confirmation-dialog.upload-report-template.question'),
|
||||
confirmationText: _('confirmation-dialog.upload-report-template.confirmation-text'),
|
||||
@ -89,8 +89,9 @@ export class ReportsScreenComponent implements OnInit {
|
||||
translateParams: {
|
||||
fileName: file.name,
|
||||
},
|
||||
});
|
||||
this._dialogService.openDialog('confirm', null, data, null, async result => {
|
||||
};
|
||||
|
||||
this._dialogService.openDialog('confirm', data, null, async result => {
|
||||
if (result) {
|
||||
const multiFileReport = result > 1;
|
||||
if (
|
||||
@ -119,7 +120,7 @@ export class ReportsScreenComponent implements OnInit {
|
||||
}
|
||||
|
||||
private async _openOverwriteConfirmationDialog(file: File, multiFileReport: boolean): Promise<void> {
|
||||
const data = new ConfirmationDialogInput({
|
||||
const data: IConfirmationDialogData = {
|
||||
title: _('confirmation-dialog.report-template-same-name.title'),
|
||||
question: _('confirmation-dialog.report-template-same-name.question'),
|
||||
confirmationText: _('confirmation-dialog.report-template-same-name.confirmation-text'),
|
||||
@ -127,9 +128,9 @@ export class ReportsScreenComponent implements OnInit {
|
||||
translateParams: {
|
||||
fileName: file.name,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
this._dialogService.openDialog('confirm', null, data, null, async result => {
|
||||
this._dialogService.openDialog('confirm', data, null, async result => {
|
||||
if (result) {
|
||||
await this._uploadTemplateForm(file, multiFileReport);
|
||||
}
|
||||
|
||||
@ -1,24 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { ReportsScreenComponent } from './reports-screen/reports-screen.component';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { IqserButtonsModule, IqserHelpModeModule, IqserPermissionsModule, IqserScrollbarModule } from '@iqser/common-ui';
|
||||
import { CircleButtonComponent, HasScrollbarDirective, IqserAllowDirective, IqserHelpModeModule, IqserRoutes } from '@iqser/common-ui';
|
||||
|
||||
const routes = [{ path: '', component: ReportsScreenComponent }];
|
||||
const routes: IqserRoutes = [{ path: '', component: ReportsScreenComponent }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [ReportsScreenComponent],
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
TranslateModule,
|
||||
IqserButtonsModule,
|
||||
IqserScrollbarModule,
|
||||
IqserHelpModeModule,
|
||||
IqserPermissionsModule,
|
||||
CircleButtonComponent,
|
||||
HasScrollbarDirective,
|
||||
IqserAllowDirective,
|
||||
],
|
||||
})
|
||||
export class ReportsModule {}
|
||||
|
||||
@ -13,7 +13,6 @@ import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration;
|
||||
import IStandaloneEditorConstructionOptions = monaco.editor.IStandaloneEditorConstructionOptions;
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-rules-screen',
|
||||
templateUrl: './rules-screen.component.html',
|
||||
styleUrls: ['./rules-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { RulesScreenComponent } from './rules-screen/rules-screen.component';
|
||||
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { IqserButtonsModule } from '@iqser/common-ui';
|
||||
import { IconButtonComponent } from '@iqser/common-ui';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
const routes = [{ path: '', component: RulesScreenComponent, canDeactivate: [PendingChangesGuard] }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [RulesScreenComponent],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, MonacoEditorModule, TranslateModule, IqserButtonsModule],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, MonacoEditorModule, TranslateModule, IconButtonComponent, FormsModule],
|
||||
})
|
||||
export class RulesModule {}
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
<iqser-page-header
|
||||
searchInputId="user-management-search-input"
|
||||
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
|
||||
[buttonConfigs]="buttonConfigs"
|
||||
[hideResetButton]="true"
|
||||
@ -7,6 +6,7 @@
|
||||
[searchPlaceholder]="'user-listing.search' | translate"
|
||||
[searchPosition]="searchPositions.withActions"
|
||||
[showCloseButton]="true"
|
||||
searchInputId="user-management-search-input"
|
||||
></iqser-page-header>
|
||||
|
||||
<div class="content-inner">
|
||||
@ -28,7 +28,6 @@
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
buttonId="bulk-delete-users-btn"
|
||||
(action)="bulkDelete()"
|
||||
*ngIf="listingService.areSomeSelected$ | async"
|
||||
[disabled]="(canDeleteSelected$ | async) === false"
|
||||
@ -36,6 +35,7 @@
|
||||
(canDeleteSelected$ | async) ? ('user-listing.bulk.delete' | translate) : ('user-listing.bulk.delete-disabled' | translate)
|
||||
"
|
||||
[type]="circleButtonTypes.dark"
|
||||
buttonId="bulk-delete-users-btn"
|
||||
icon="iqser:trash"
|
||||
tooltipPosition="after"
|
||||
></iqser-circle-button>
|
||||
@ -53,10 +53,10 @@
|
||||
|
||||
<div class="center cell">
|
||||
<mat-slide-toggle
|
||||
[id]="'toggle-active-' + user.id"
|
||||
(toggleChange)="toggleActive(user)"
|
||||
[checked]="user.active"
|
||||
[disabled]="!canDeactivate(user)"
|
||||
[id]="'toggle-active-' + user.id"
|
||||
[iqserHelpMode]="'activate_deactivate_user'"
|
||||
color="primary"
|
||||
></mat-slide-toggle>
|
||||
@ -71,14 +71,14 @@
|
||||
<div class="action-buttons">
|
||||
<div *allow="roles.users.write" [iqserHelpMode]="'edit_delete_user'">
|
||||
<iqser-circle-button
|
||||
(action)="openAddEditUserDialog($event, user)"
|
||||
(action)="openAddEditUserDialog(user)"
|
||||
[tooltip]="'user-listing.action.edit' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openDeleteUsersDialog([user.id], $event)"
|
||||
(action)="openDeleteUsersDialog([user.id])"
|
||||
[disabled]="deleteDisabled(user)"
|
||||
[tooltip]="'user-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
|
||||
@ -92,14 +92,14 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
|
||||
await this.#loadData();
|
||||
}
|
||||
|
||||
openAddEditUserDialog(event?: MouseEvent, user?: User) {
|
||||
this._dialogService.openDialog('addEditUser', event, user, async () => {
|
||||
openAddEditUserDialog(user?: User) {
|
||||
this._dialogService.openDialog('addEditUser', user, async () => {
|
||||
await this.#loadData();
|
||||
});
|
||||
}
|
||||
|
||||
openDeleteUsersDialog(userIds: string[], $event?: MouseEvent) {
|
||||
this._dialogService.deleteUsers(userIds, $event, async () => {
|
||||
openDeleteUsersDialog(userIds: string[]) {
|
||||
this._dialogService.deleteUsers(userIds, async () => {
|
||||
await this.#loadData();
|
||||
});
|
||||
}
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
<div class="pagination noselect">
|
||||
<div (click)="changePage.emit(1)" class="page-button" id="portraitPage">
|
||||
<mat-icon class="chevron-icon" svgIcon="red:nav-prev"></mat-icon>
|
||||
Portrait
|
||||
</div>
|
||||
|
||||
<div class="separator">/</div>
|
||||
|
||||
<div (click)="changePage.emit(2)" class="page-button" id="landscapePage">
|
||||
Landscape
|
||||
<mat-icon class="chevron-icon" svgIcon="red:nav-next"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
@ -0,0 +1,42 @@
|
||||
.pagination {
|
||||
z-index: 1;
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
right: calc(50% - (var(--viewer-width) / 2));
|
||||
transform: translate(-50%);
|
||||
background: var(--iqser-background);
|
||||
color: var(--iqser-grey-7);
|
||||
border: 1px solid var(--iqser-grey-7);
|
||||
border-radius: 8px;
|
||||
padding: 6px 2px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
> div {
|
||||
height: 16px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.separator {
|
||||
padding-left: 2px;
|
||||
padding-right: 2px;
|
||||
}
|
||||
|
||||
.page-button {
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
display: inline-flex;
|
||||
|
||||
&:hover {
|
||||
color: var(--iqser-text);
|
||||
}
|
||||
}
|
||||
|
||||
.chevron-icon {
|
||||
height: 16px;
|
||||
transform: rotate(-90deg);
|
||||
padding-left: 4px;
|
||||
padding-right: 4px;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-paginator',
|
||||
templateUrl: './paginator.component.html',
|
||||
styleUrls: ['./paginator.component.scss'],
|
||||
})
|
||||
export class PaginatorComponent {
|
||||
@Output() readonly changePage = new EventEmitter<number>();
|
||||
}
|
||||
@ -1,7 +1,9 @@
|
||||
<div class="content-container">
|
||||
<div class="viewer" id="viewer"></div>
|
||||
<div #viewer class="viewer" id="viewer"></div>
|
||||
|
||||
<div *ngIf="changed && currentUser.isAdmin" class="changes-box">
|
||||
<redaction-paginator (changePage)="navigateTo($event)" *ngIf="loaded$ | async"></redaction-paginator>
|
||||
|
||||
<div *ngIf="!!instance && changed && currentUser.isAdmin" class="changes-box">
|
||||
<iqser-icon-button
|
||||
(action)="save()"
|
||||
[disabled]="!valid"
|
||||
@ -9,6 +11,7 @@
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:check"
|
||||
></iqser-icon-button>
|
||||
|
||||
<div (click)="revert()" [translate]="'watermark-screen.action.revert'" class="all-caps-label cancel"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
flex-direction: row !important;
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
--viewer-width: 380px;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
@ -12,6 +13,7 @@
|
||||
|
||||
.viewer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { Component, ElementRef, Inject, OnInit, ViewChild } from '@angular/core';
|
||||
import WebViewer, { WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
@ -18,14 +18,14 @@ import { DOSSIER_TEMPLATE_ID, type IWatermark, type User, WATERMARK_ID, Watermar
|
||||
import { stampPDFPage } from '@utils/page-stamper';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { WatermarkService } from '@services/entity-services/watermark.service';
|
||||
import { firstValueFrom, Observable, of } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { BehaviorSubject, firstValueFrom, Observable, of } from 'rxjs';
|
||||
import { LicenseService } from '@services/license.service';
|
||||
import { UserPreferenceService } from '@users/user-preference.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { WatermarksMapService } from '@services/entity-services/watermarks-map.service';
|
||||
import { ROLES } from '@users/roles';
|
||||
import { environment } from '@environments/environment';
|
||||
import { tap } from 'rxjs/operators';
|
||||
|
||||
export const DEFAULT_WATERMARK: Partial<IWatermark> = {
|
||||
text: 'Watermark',
|
||||
@ -51,10 +51,10 @@ interface WatermarkForm {
|
||||
templateUrl: './watermark-screen.component.html',
|
||||
styleUrls: ['./watermark-screen.component.scss'],
|
||||
})
|
||||
export class WatermarkScreenComponent {
|
||||
export class WatermarkScreenComponent implements OnInit {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly currentUser = getCurrentUser<User>();
|
||||
readonly form = this._getForm();
|
||||
readonly form = this.#form;
|
||||
readonly watermark$: Observable<Partial<IWatermark>>;
|
||||
readonly fontOptions = [
|
||||
{ value: 'times-new-roman', display: 'Times' },
|
||||
@ -62,10 +62,12 @@ export class WatermarkScreenComponent {
|
||||
{ value: 'courier', display: 'Courier' },
|
||||
];
|
||||
readonly orientationOptions = ['DIAGONAL', 'HORIZONTAL', 'VERTICAL'];
|
||||
instance: WebViewerInstance;
|
||||
readonly loaded$ = new BehaviorSubject(false);
|
||||
@ViewChild('viewer', { static: true }) private readonly _viewer: ElementRef<HTMLDivElement>;
|
||||
readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
|
||||
readonly #watermarkId = Number(getParam(WATERMARK_ID));
|
||||
private _instance: WebViewerInstance;
|
||||
private _watermark: Partial<IWatermark> = {};
|
||||
#watermark: Partial<IWatermark> = {};
|
||||
|
||||
constructor(
|
||||
private readonly _http: HttpClient,
|
||||
@ -78,17 +80,16 @@ export class WatermarkScreenComponent {
|
||||
private readonly _watermarkService: WatermarkService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _router: Router,
|
||||
private readonly _watermarksMapService: WatermarksMapService,
|
||||
watermarksMapService: WatermarksMapService,
|
||||
) {
|
||||
const obs$: Observable<Partial<IWatermark>> = this.#watermarkId
|
||||
? _watermarksMapService.watch$(this.#dossierTemplateId, this.#watermarkId)
|
||||
: of(DEFAULT_WATERMARK);
|
||||
this.watermark$ = obs$.pipe(tap(wm => this._initForm(wm)));
|
||||
const watermark$ = watermarksMapService.watch$(this.#dossierTemplateId, this.#watermarkId);
|
||||
const obs$: Observable<Partial<IWatermark>> = this.#watermarkId ? watermark$ : of(DEFAULT_WATERMARK);
|
||||
this.watermark$ = obs$.pipe(tap(watermark => this.#initForm(watermark)));
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
for (const key of Object.keys(this.form.getRawValue())) {
|
||||
if (this._watermark[key] !== this.form.get(key)?.value) {
|
||||
if (this.#watermark[key] !== this.form.get(key)?.value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -102,113 +103,7 @@ export class WatermarkScreenComponent {
|
||||
return this.form.valid;
|
||||
}
|
||||
|
||||
@Debounce()
|
||||
async configChanged() {
|
||||
await this._drawWatermark();
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
const watermark: IWatermark = {
|
||||
id: this._watermark.id,
|
||||
enabled: this._watermark.id ? this._watermark.enabled : true,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
...this.form.getRawValue(),
|
||||
};
|
||||
this._loadingService.start();
|
||||
try {
|
||||
const updatedWatermark = await this._watermarkService.saveWatermark(watermark);
|
||||
this._toaster.success(
|
||||
watermark.id ? _('watermark-screen.action.change-success') : _('watermark-screen.action.created-success'),
|
||||
);
|
||||
if (!watermark.id) {
|
||||
await this._router.navigate([`/main/admin/dossier-templates/${this.#dossierTemplateId}/watermarks/${updatedWatermark.id}`]);
|
||||
}
|
||||
} catch (error) {
|
||||
this._toaster.error(_('watermark-screen.action.error'));
|
||||
}
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async revert() {
|
||||
this.form.patchValue({ ...this._watermark });
|
||||
await this.configChanged();
|
||||
}
|
||||
|
||||
async setValue(type: 'fontType' | 'orientation' | 'hexColor', value: any) {
|
||||
if (!this.form.get(type).disabled) {
|
||||
this.form.get(type).setValue(value);
|
||||
await this.configChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async _initForm(watermark: Partial<IWatermark>) {
|
||||
this._watermark = { ...watermark, dossierTemplateId: this.#dossierTemplateId };
|
||||
this.form.patchValue({ ...watermark });
|
||||
await this._loadViewer();
|
||||
}
|
||||
|
||||
private async _loadViewer() {
|
||||
if (this._instance) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._instance = await WebViewer(
|
||||
{
|
||||
licenseKey: this._licenseService.activeLicenseKey,
|
||||
path: this._convertPath('/assets/wv-resources'),
|
||||
css: this._convertPath('/assets/pdftron/stylesheet.css'),
|
||||
fullAPI: true,
|
||||
isReadOnly: true,
|
||||
backendType: 'ems',
|
||||
},
|
||||
document.getElementById('viewer'),
|
||||
);
|
||||
|
||||
this._instance.UI.setTheme(this._userPreferenceService.getTheme());
|
||||
|
||||
this._instance.Core.documentViewer.addEventListener('documentLoaded', async () => {
|
||||
this._loadingService.stop();
|
||||
await this._drawWatermark();
|
||||
});
|
||||
|
||||
if (environment.production) {
|
||||
this._instance.Core.setCustomFontURL('https://' + window.location.host + this._convertPath('/assets/pdftron'));
|
||||
}
|
||||
|
||||
this._disableElements();
|
||||
|
||||
const request = this._http.get('/assets/pdftron/blank.pdf', {
|
||||
responseType: 'blob',
|
||||
});
|
||||
const blobData = await firstValueFrom(request);
|
||||
this._instance.UI.loadDocument(blobData, { filename: 'blank.pdf' });
|
||||
}
|
||||
|
||||
private _disableElements() {
|
||||
this._instance.UI.disableElements(['header', 'toolsHeader', 'pageNavOverlay', 'textPopup']);
|
||||
}
|
||||
|
||||
private async _drawWatermark() {
|
||||
const pdfNet = this._instance.Core.PDFNet;
|
||||
const document = await this._instance.Core.documentViewer.getDocument().getPDFDoc();
|
||||
|
||||
await stampPDFPage(
|
||||
document,
|
||||
pdfNet,
|
||||
this.form.controls.text.value || '',
|
||||
this.form.controls.fontSize.value,
|
||||
this.form.controls.fontType.value,
|
||||
this.form.controls.orientation.value,
|
||||
this.form.controls.opacity.value,
|
||||
this.form.controls.hexColor.value,
|
||||
[1],
|
||||
this._licenseService.activeLicenseKey,
|
||||
);
|
||||
this._instance.Core.documentViewer.refreshAll();
|
||||
this._instance.Core.documentViewer.updateView([0], 0);
|
||||
}
|
||||
|
||||
private _getForm() {
|
||||
get #form() {
|
||||
const form: FormGroup<AsControl<WatermarkForm>> = this._formBuilder.group({
|
||||
name: [null],
|
||||
text: [null],
|
||||
@ -225,4 +120,122 @@ export class WatermarkScreenComponent {
|
||||
|
||||
return form;
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
await this.#loadViewer();
|
||||
}
|
||||
|
||||
@Debounce()
|
||||
async configChanged() {
|
||||
await this.#drawWatermark();
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
const watermark: IWatermark = {
|
||||
id: this.#watermark.id,
|
||||
enabled: this.#watermark.id ? this.#watermark.enabled : true,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
...this.form.getRawValue(),
|
||||
};
|
||||
|
||||
this._loadingService.start();
|
||||
|
||||
try {
|
||||
const updatedWatermark = await this._watermarkService.saveWatermark(watermark);
|
||||
this._toaster.success(
|
||||
watermark.id ? _('watermark-screen.action.change-success') : _('watermark-screen.action.created-success'),
|
||||
);
|
||||
if (!watermark.id) {
|
||||
await this._router.navigate([`/main/admin/dossier-templates/${this.#dossierTemplateId}/watermarks/${updatedWatermark.id}`]);
|
||||
}
|
||||
} catch (error) {
|
||||
this._toaster.error(_('watermark-screen.action.error'));
|
||||
}
|
||||
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async revert() {
|
||||
this.form.patchValue({ ...this.#watermark });
|
||||
await this.configChanged();
|
||||
}
|
||||
|
||||
async setValue(type: 'fontType' | 'orientation' | 'hexColor', value: any) {
|
||||
if (!this.form.get(type).disabled) {
|
||||
this.form.get(type).setValue(value);
|
||||
await this.configChanged();
|
||||
}
|
||||
}
|
||||
|
||||
navigateTo($event: number) {
|
||||
this.instance.Core.documentViewer.displayPageLocation($event, 0, 0);
|
||||
}
|
||||
|
||||
async #initForm(watermark: Partial<IWatermark>) {
|
||||
this.#watermark = { ...watermark, dossierTemplateId: this.#dossierTemplateId };
|
||||
this.form.patchValue({ ...watermark });
|
||||
}
|
||||
|
||||
async #loadViewer() {
|
||||
this.instance = await WebViewer(
|
||||
{
|
||||
licenseKey: this._licenseService.activeLicenseKey,
|
||||
path: this._convertPath('/assets/wv-resources'),
|
||||
css: this._convertPath('/assets/pdftron/stylesheet.css'),
|
||||
fullAPI: true,
|
||||
isReadOnly: true,
|
||||
backendType: 'ems',
|
||||
},
|
||||
// use nativeElement instead of document.getElementById('viwer')
|
||||
// because WebViewer works better with this approach
|
||||
this._viewer.nativeElement,
|
||||
);
|
||||
|
||||
this.instance.UI.setTheme(this._userPreferenceService.getTheme());
|
||||
|
||||
this.instance.Core.documentViewer.addEventListener('documentLoaded', async () => {
|
||||
this.loaded$.next(true);
|
||||
this._loadingService.stop();
|
||||
await this.#drawWatermark();
|
||||
});
|
||||
|
||||
if (environment.production) {
|
||||
this.instance.Core.setCustomFontURL('https://' + window.location.host + this._convertPath('/assets/pdftron'));
|
||||
}
|
||||
|
||||
this.#disableElements();
|
||||
await this.#loadDocument();
|
||||
}
|
||||
|
||||
async #loadDocument() {
|
||||
const request = this._http.get('/assets/pdftron/blank.pdf', {
|
||||
responseType: 'blob',
|
||||
});
|
||||
const blobData = await firstValueFrom(request);
|
||||
this.instance.UI.loadDocument(blobData, { filename: 'blank.pdf' });
|
||||
}
|
||||
|
||||
#disableElements() {
|
||||
this.instance.UI.disableElements(['header', 'toolsHeader', 'pageNavOverlay', 'textPopup']);
|
||||
}
|
||||
|
||||
async #drawWatermark() {
|
||||
const pdfNet = this.instance.Core.PDFNet;
|
||||
const document = await this.instance.Core.documentViewer.getDocument().getPDFDoc();
|
||||
|
||||
await stampPDFPage(
|
||||
document,
|
||||
pdfNet,
|
||||
this.form.controls.text.value || '',
|
||||
this.form.controls.fontSize.value,
|
||||
this.form.controls.fontType.value,
|
||||
this.form.controls.orientation.value,
|
||||
this.form.controls.opacity.value,
|
||||
this.form.controls.hexColor.value,
|
||||
[1, 2],
|
||||
this._licenseService.activeLicenseKey,
|
||||
);
|
||||
this.instance.Core.documentViewer.refreshAll();
|
||||
this.instance.Core.documentViewer.updateView([0, 1], 0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,25 +1,32 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { WatermarkScreenComponent } from './watermark-screen/watermark-screen.component';
|
||||
import { WatermarksListingScreenComponent } from './watermarks-listing/watermarks-listing-screen.component';
|
||||
import {
|
||||
CircleButtonComponent,
|
||||
CompositeRouteGuard,
|
||||
HasScrollbarDirective,
|
||||
IconButtonComponent,
|
||||
IqserAllowDirective,
|
||||
IqserAuthGuard,
|
||||
IqserButtonsModule,
|
||||
IqserHelpModeModule,
|
||||
IqserListingModule,
|
||||
IqserPermissionsModule,
|
||||
IqserScrollbarModule,
|
||||
IqserRoutes,
|
||||
IqserUsersModule,
|
||||
} from '@iqser/common-ui';
|
||||
import { RedRoleGuard } from '@users/red-role.guard';
|
||||
import { WATERMARK_ID } from '@red/domain';
|
||||
import { WatermarkExistsGuard } from '@guards/watermark-exists.guard';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { PaginatorComponent } from './paginator/paginator.component';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatLegacySliderModule } from '@angular/material/legacy-slider';
|
||||
import { ColorPickerModule } from 'ngx-color-picker';
|
||||
import { MatLegacySlideToggleModule } from '@angular/material/legacy-slide-toggle';
|
||||
|
||||
const routes = [
|
||||
const routes: IqserRoutes = [
|
||||
{
|
||||
path: '',
|
||||
component: WatermarksListingScreenComponent,
|
||||
@ -47,18 +54,23 @@ const routes = [
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [WatermarkScreenComponent, WatermarksListingScreenComponent],
|
||||
declarations: [WatermarkScreenComponent, WatermarksListingScreenComponent, PaginatorComponent],
|
||||
imports: [
|
||||
RouterModule.forChild(routes),
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
IqserUsersModule,
|
||||
TranslateModule,
|
||||
IqserButtonsModule,
|
||||
IqserListingModule,
|
||||
IqserScrollbarModule,
|
||||
IqserHelpModeModule,
|
||||
IqserPermissionsModule,
|
||||
MatIconModule,
|
||||
IconButtonComponent,
|
||||
ReactiveFormsModule,
|
||||
MatLegacySliderModule,
|
||||
ColorPickerModule,
|
||||
MatLegacySlideToggleModule,
|
||||
CircleButtonComponent,
|
||||
HasScrollbarDirective,
|
||||
IqserAllowDirective,
|
||||
],
|
||||
})
|
||||
export class WatermarkModule {}
|
||||
|
||||
@ -14,8 +14,8 @@
|
||||
<iqser-icon-button
|
||||
*allow="roles.watermarks.write; if: currentUser.isAdmin"
|
||||
[iqserHelpMode]="'create_new_watermark'"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
[label]="'watermarks-listing.add-new' | translate"
|
||||
[overlappingElements]="['USER_MENU']"
|
||||
[routerLink]="getRouterLink()"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
@ -66,7 +66,7 @@
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteWatermarkDialog($event, entity)"
|
||||
(action)="openConfirmDeleteWatermarkDialog(entity)"
|
||||
*allow="roles.watermarks.write; if: currentUser.isAdmin"
|
||||
[tooltip]="'watermarks-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
ConfirmationDialogInput,
|
||||
getCurrentUser,
|
||||
getParam,
|
||||
IconButtonTypes,
|
||||
IConfirmationDialogData,
|
||||
IqserPermissionsService,
|
||||
ListingComponent,
|
||||
listingProvidersFactory,
|
||||
@ -51,13 +51,14 @@ export class WatermarksListingScreenComponent extends ListingComponent<Watermark
|
||||
this.entitiesService.setEntities(this._watermarksMapService.get(this.#dossierTemplateId));
|
||||
}
|
||||
|
||||
async openConfirmDeleteWatermarkDialog($event: MouseEvent, watermark: Watermark) {
|
||||
async openConfirmDeleteWatermarkDialog(watermark: Watermark) {
|
||||
const isUsed = await this._watermarkService.isWatermarkUsed(watermark.id);
|
||||
|
||||
const data = new ConfirmationDialogInput({
|
||||
const data: IConfirmationDialogData = {
|
||||
question: isUsed ? _('watermarks-listing.watermark-is-used') : null,
|
||||
});
|
||||
this._dialogService.openDialog('confirm', $event, data, async () => {
|
||||
};
|
||||
|
||||
this._dialogService.openDialog('confirm', data, async () => {
|
||||
await this._deleteWatermark(watermark);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,27 +1,20 @@
|
||||
import { Injectable, TemplateRef } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AddEditFileAttributeDialogComponent } from '../dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
|
||||
import { AddEntityDialogComponent } from '../dialogs/add-entity-dialog/add-entity-dialog.component';
|
||||
import { AddEditCloneDossierTemplateDialogComponent } from '../dialogs/add-edit-dossier-template-dialog/add-edit-clone-dossier-template-dialog.component';
|
||||
import { EditColorDialogComponent } from '../dialogs/edit-color-dialog/edit-color-dialog.component';
|
||||
import { SmtpAuthDialogComponent } from '../dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
||||
import { AddEditUserDialogComponent } from '../dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
||||
import { FileAttributesCsvImportDialogComponent } from '../dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
|
||||
import { AddEditDossierAttributeDialogComponent } from '../dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component';
|
||||
import {
|
||||
ConfirmationDialogComponent,
|
||||
ConfirmationDialogInput,
|
||||
ConfirmOptions,
|
||||
DialogConfig,
|
||||
DialogService,
|
||||
largeDialogConfig,
|
||||
IConfirmationDialogData,
|
||||
LoadingService,
|
||||
TitleColors,
|
||||
} from '@iqser/common-ui';
|
||||
import { UploadDictionaryDialogComponent } from '../dialogs/upload-dictionary-dialog/upload-dictionary-dialog.component';
|
||||
import { FileAttributesConfigurationsDialogComponent } from '../dialogs/file-attributes-configurations-dialog/file-attributes-configurations-dialog.component';
|
||||
import { AddEditDossierStateDialogComponent } from '../dialogs/add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
|
||||
import { ConfirmDeleteDossierStateDialogComponent } from '../dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { firstValueFrom, forkJoin } from 'rxjs';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
@ -35,17 +28,11 @@ type DialogType =
|
||||
| 'confirm'
|
||||
| 'addEntity'
|
||||
| 'editColor'
|
||||
| 'addEditFileAttribute'
|
||||
| 'importFileAttributes'
|
||||
| 'fileAttributesConfigurations'
|
||||
| 'addEditUser'
|
||||
| 'smtpAuthConfig'
|
||||
| 'addEditCloneDossierTemplate'
|
||||
| 'auditInfo'
|
||||
| 'addEditDossierAttribute'
|
||||
| 'uploadDictionary'
|
||||
| 'addEditDossierState'
|
||||
| 'deleteDossierState'
|
||||
| 'configureCertificate';
|
||||
|
||||
@Injectable()
|
||||
@ -63,17 +50,6 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
component: EditColorDialogComponent,
|
||||
dialogConfig: { autoFocus: true },
|
||||
},
|
||||
addEditFileAttribute: {
|
||||
component: AddEditFileAttributeDialogComponent,
|
||||
dialogConfig: { autoFocus: true },
|
||||
},
|
||||
fileAttributesConfigurations: {
|
||||
component: FileAttributesConfigurationsDialogComponent,
|
||||
},
|
||||
importFileAttributes: {
|
||||
component: FileAttributesCsvImportDialogComponent,
|
||||
dialogConfig: { ...largeDialogConfig, ...{ disableClose: false } },
|
||||
},
|
||||
addEditUser: {
|
||||
component: AddEditUserDialogComponent,
|
||||
dialogConfig: { autoFocus: true },
|
||||
@ -86,19 +62,9 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
component: AddEditCloneDossierTemplateDialogComponent,
|
||||
dialogConfig: { width: '900px', autoFocus: true },
|
||||
},
|
||||
addEditDossierAttribute: {
|
||||
component: AddEditDossierAttributeDialogComponent,
|
||||
dialogConfig: { autoFocus: true },
|
||||
},
|
||||
uploadDictionary: {
|
||||
component: UploadDictionaryDialogComponent,
|
||||
},
|
||||
addEditDossierState: {
|
||||
component: AddEditDossierStateDialogComponent,
|
||||
},
|
||||
deleteDossierState: {
|
||||
component: ConfirmDeleteDossierStateDialogComponent,
|
||||
},
|
||||
configureCertificate: {
|
||||
component: ConfigureCertificateDialogComponent,
|
||||
dialogConfig: { disableClose: false, maxHeight: '100vh' },
|
||||
@ -118,8 +84,8 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
super(_dialog);
|
||||
}
|
||||
|
||||
deleteUsers(userIds: string[], $event?: MouseEvent, cb?: () => Promise<void> | void): void {
|
||||
const data = new ConfirmationDialogInput({
|
||||
deleteUsers(userIds: string[], cb?: () => Promise<void> | void): void {
|
||||
const data: IConfirmationDialogData = {
|
||||
title: _('confirm-delete-users.title'),
|
||||
question: _('confirm-delete-users.warning'),
|
||||
confirmationText: _('confirm-delete-users.delete'),
|
||||
@ -131,9 +97,9 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
{ value: false, label: _('confirm-delete-users.impacted-documents') },
|
||||
],
|
||||
toastMessage: _('confirm-delete-users.toast-error'),
|
||||
});
|
||||
};
|
||||
|
||||
this.openDialog('confirm', $event, data, async result => {
|
||||
this.openDialog('confirm', data, async result => {
|
||||
if (result === ConfirmOptions.CONFIRM) {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._userService.delete(userIds));
|
||||
@ -148,7 +114,6 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
dossierTemplateId: string,
|
||||
impactedTemplatesRef: TemplateRef<unknown>,
|
||||
type: 'dossier' | 'file',
|
||||
$event: MouseEvent,
|
||||
cb: () => Promise<void> | void,
|
||||
): Promise<void> {
|
||||
this._loadingService.start();
|
||||
@ -160,7 +125,7 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
const uniqueTemplates = Array.from(templateIds).map(id => templates.find(t => t.templateId === id));
|
||||
this._loadingService.stop();
|
||||
|
||||
const data = new ConfirmationDialogInput({
|
||||
const data: IConfirmationDialogData = {
|
||||
title: _('confirm-delete-attribute.title'),
|
||||
question: _('confirm-delete-attribute.warning'),
|
||||
confirmationText: _('confirm-delete-attribute.delete'),
|
||||
@ -184,7 +149,8 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
],
|
||||
toastMessage: _('confirm-delete-attribute.toast-error'),
|
||||
translateParams: { reportsCount: uniqueTemplates.length, count: attributes.length, name: attributes[0].label },
|
||||
});
|
||||
};
|
||||
|
||||
if (templates.length) {
|
||||
data.checkboxes.push({
|
||||
value: false,
|
||||
@ -193,7 +159,8 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
extraContentData: { templates: uniqueTemplates },
|
||||
});
|
||||
}
|
||||
this.openDialog('confirm', $event, data, async () => {
|
||||
|
||||
this.openDialog('confirm', data, async () => {
|
||||
await cb();
|
||||
});
|
||||
}
|
||||
|
||||
@ -2,10 +2,12 @@ import { Component, HostBinding, Input, OnInit } from '@angular/core';
|
||||
import { UserPreferenceService } from '@users/user-preference.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { adminSideNavTranslations } from '@translations/admin-side-nav-translations';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ActivatedRoute, RouterLink, RouterLinkActive } from '@angular/router';
|
||||
import { AdminSideNavType, AdminSideNavTypes, ENTITY_TYPE, User } from '@red/domain';
|
||||
import { ROLES } from '@users/roles';
|
||||
import { getCurrentUser, IqserPermissionsService } from '@iqser/common-ui';
|
||||
import { getCurrentUser, IqserHelpModeModule, IqserPermissionsService, SideNavComponent } from '@iqser/common-ui';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
|
||||
interface NavItem {
|
||||
readonly label: string;
|
||||
@ -18,6 +20,8 @@ interface NavItem {
|
||||
selector: 'redaction-admin-side-nav [type]',
|
||||
templateUrl: './admin-side-nav.component.html',
|
||||
styleUrls: ['./admin-side-nav.component.scss'],
|
||||
standalone: true,
|
||||
imports: [TranslateModule, NgIf, IqserHelpModeModule, RouterLink, RouterLinkActive, NgForOf, SideNavComponent],
|
||||
})
|
||||
export class AdminSideNavComponent implements OnInit {
|
||||
@Input() type: AdminSideNavType;
|
||||
@ -1,27 +1,27 @@
|
||||
<div class="action-buttons" *ngIf="currentUser.isAdmin">
|
||||
<div *ngIf="currentUser.isAdmin" [id]="'actions-for-' + dossierTemplateId" class="action-buttons">
|
||||
<div [iqserHelpMode]="'edit_clone_delete_dossier_templates'" [overlappingElements]="['USER_MENU']">
|
||||
<iqser-circle-button
|
||||
[buttonId]="'delete-dossier-template-btn-' + dossierTemplateId"
|
||||
(action)="openDeleteDossierTemplateDialog($event)"
|
||||
(action)="openDeleteDossierTemplateDialog()"
|
||||
[buttonId]="'delete-dossier-template-btn'"
|
||||
[tooltip]="'dossier-templates-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
[buttonId]="'copy-dossier-template-btn-' + dossierTemplateId"
|
||||
(action)="openEditCloneDossierTemplateDialog($event, true)"
|
||||
(action)="openEditCloneDossierTemplateDialog(true)"
|
||||
[buttonId]="'copy-dossier-template-btn'"
|
||||
[tooltip]="'dossier-templates-listing.action.clone' | translate"
|
||||
icon="iqser:copy"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:copy"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
[buttonId]="'edit-dossier-template-btn-' + dossierTemplateId"
|
||||
(action)="openEditCloneDossierTemplateDialog($event)"
|
||||
(action)="openEditCloneDossierTemplateDialog()"
|
||||
[buttonId]="'edit-dossier-template-btn'"
|
||||
[tooltip]="'dossier-templates-listing.action.edit' | translate"
|
||||
icon="iqser:edit"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user