RED-3800 Audit Info Dialog

This commit is contained in:
Timo Bejan 2022-12-14 12:37:22 +02:00
parent 8fb0c84c64
commit f8fe1799f5
14 changed files with 148 additions and 2 deletions

View File

@ -46,6 +46,7 @@ import { ConfigureCertificateDialogComponent } from './dialogs/configure-digital
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 {
HumanizeCamelCasePipe,
HumanizePipe,
IqserButtonsModule,
IqserEmptyStatesModule,
@ -59,6 +60,8 @@ import {
IqserUsersModule,
} from '@iqser/common-ui';
import { TranslateModule } from '@ngx-translate/core';
import { OverlayModule } from '@angular/cdk/overlay';
import { AuditInfoDialog } from './dialogs/audit-info-dialog/audit-info-dialog.component';
const dialogs = [
AddEditCloneDossierTemplateDialogComponent,
@ -74,6 +77,7 @@ const dialogs = [
AddEditDossierStateDialogComponent,
ConfirmDeleteDossierStateDialogComponent,
ConfigureCertificateDialogComponent,
AuditInfoDialog,
];
const screens = [
@ -129,6 +133,8 @@ const components = [
IqserSharedModule,
IqserHelpModeModule,
IqserPermissionsModule,
OverlayModule,
HumanizeCamelCasePipe,
],
})
export class AdminModule {}

View File

@ -0,0 +1,17 @@
<section class="dialog">
<div [translate]="'audit-screen.audit-info-dialog.title'" class="dialog-header heading-l"></div>
<div class="dialog-content">
<div class="table output-data">
<div class="table-header">Key</div>
<div class="table-header">Value</div>
<ng-container *ngFor="let entry of data.auditEntry.details | keyvalue: originalOrder">
<div class="bold">{{ entry.key | humanize }}</div>
<div>{{ entry.value }}</div>
</ng-container>
</div>
</div>
<iqser-circle-button (action)="close()" class="dialog-close" icon="iqser:close"></iqser-circle-button>
</section>

View File

@ -0,0 +1,27 @@
.table {
display: grid;
grid-template-columns: repeat(2, 1fr);
> div {
padding: 8px 10px;
}
.bold {
font-weight: 600;
}
.value-content {
.value {
}
.actions {
}
}
.table-header {
margin: 10px 0;
border-bottom: 1px solid var(--iqser-separator);
background-color: var(--iqser-grey-2);
font-weight: 600;
}
}

View File

@ -0,0 +1,32 @@
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { BaseDialogComponent } from '@iqser/common-ui';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { IAudit } from '@red/domain';
import { DossierStatesService } from '@services/entity-services/dossier-states.service';
import { KeyValue } from '@angular/common';
interface DialogData {
readonly auditEntry: IAudit;
}
@Component({
selector: 'redaction-audit-info-dialog',
templateUrl: './audit-info-dialog.component.html',
styleUrls: ['./audit-info-dialog.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AuditInfoDialogComponent extends BaseDialogComponent {
readonly originalOrder = (a: KeyValue<string, string>, b: KeyValue<string, string>): number => 0;
constructor(
private readonly _dossierStatesService: DossierStatesService,
protected readonly _dialogRef: MatDialogRef<AuditInfoDialogComponent>,
@Inject(MAT_DIALOG_DATA) readonly data: DialogData,
) {
super(_dialogRef, false);
}
async save(): Promise<void> {
return;
}
}

View File

@ -11,6 +11,7 @@
[noDataText]="'audit-screen.no-data.title' | translate"
[tableColumnConfigs]="tableColumnConfigs"
[totalSize]="logs?.totalHits || 0"
[emptyColumnWidth]="'2fr'"
></iqser-table>
<ng-template #headerTemplate>
@ -94,5 +95,19 @@
</div>
<div class="cell">{{ (translations[log.category] | translate) || log.category | humanize }}</div>
<div class="cell">
<div class="action-buttons">
<iqser-circle-button
*ngIf="log.hasDetails"
(action)="openAuditDetails($event, log)"
cdkOverlayOrigin
#trigger="cdkOverlayOrigin"
[tooltip]="'audit-screen.action.info' | translate"
icon="red:info"
[type]="circleButtonTypes.dark"
></iqser-circle-button>
</div>
</div>
</div>
</ng-template>

View File

@ -17,3 +17,9 @@ form {
font-size: 16px;
opacity: 0.7;
}
.item-info {
background: var(--iqser-light);
border: 1px solid var(--iqser-grey-1);
padding: 20px;
}

View File

@ -2,6 +2,7 @@ import { Component, inject, OnDestroy, OnInit } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
import {
CircleButtonTypes,
getCurrentUser,
IqserPermissionsService,
ListingComponent,
@ -17,6 +18,7 @@ import { firstValueFrom } from 'rxjs';
import { Dayjs } from 'dayjs';
import { RouterHistoryService } from '@services/router-history.service';
import { ROLES } from '@users/roles';
import { AdminDialogService } from '../../services/admin-dialog.service';
const PAGE_SIZE = 50;
@ -26,6 +28,7 @@ const PAGE_SIZE = 50;
providers: listingProvidersFactory(AuditScreenComponent),
})
export class AuditScreenComponent extends ListingComponent<Audit> implements OnInit, OnDestroy {
readonly circleButtonTypes = CircleButtonTypes;
readonly ALL_CATEGORIES = 'allCategories';
readonly ALL_USERS = _('audit-screen.all-users');
readonly translations = auditCategoriesTranslations;
@ -38,6 +41,7 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnI
categories: string[] = [];
userIds: Set<string>;
logs: IAuditResponse;
readonly tableColumnConfigs: TableColumnConfig<Audit>[] = [
{ label: _('audit-screen.table-col-names.message') },
{ label: _('audit-screen.table-col-names.date') },
@ -52,6 +56,7 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnI
private readonly _formBuilder: UntypedFormBuilder,
private readonly _loadingService: LoadingService,
private readonly _auditService: AuditService,
private readonly _dialogService: AdminDialogService,
) {
super();
}
@ -130,4 +135,8 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnI
}
this._loadingService.stop();
}
openAuditDetails($event: MouseEvent, log: Audit) {
this._dialogService.openDialog('auditInfo', $event, { auditEntry: log });
}
}

View File

@ -29,6 +29,7 @@ import { UserService } from '@users/user.service';
import { IDossierAttributeConfig, IFileAttributeConfig, IReportTemplate } from '@red/domain';
import { ReportTemplateService } from '@services/report-template.service';
import { ConfigureCertificateDialogComponent } from '../dialogs/configure-digital-signature-dialog/configure-certificate-dialog.component';
import { AuditInfoDialog } from '../dialogs/audit-info-dialog/audit-info-dialog.component';
type DialogType =
| 'confirm'
@ -40,6 +41,7 @@ type DialogType =
| 'addEditUser'
| 'smtpAuthConfig'
| 'addEditCloneDossierTemplate'
| 'auditInfo'
| 'addEditDossierAttribute'
| 'uploadDictionary'
| 'addEditDossierState'
@ -101,6 +103,9 @@ export class AdminDialogService extends DialogService<DialogType> {
component: ConfigureCertificateDialogComponent,
dialogConfig: { disableClose: false, maxHeight: '100vh' },
},
auditInfo: {
component: AuditInfoDialog,
},
};
constructor(

View File

@ -402,7 +402,13 @@
},
"audit": "Aktivitätenprotokoll",
"audit-screen": {
"action": {
"info": "Info"
},
"all-users": "Alle Benutzer",
"audit-info-dialog": {
"title": "Audit Info"
},
"categories": {
"all-categories": "Alle Bereiche",
"audit": "Aktivitätenprotokoll",
@ -1961,6 +1967,7 @@
"save": "",
"undo": ""
},
"annotations": "",
"title": ""
},
"rules-screen": {

View File

@ -402,7 +402,13 @@
},
"audit": "Audit",
"audit-screen": {
"action": {
"info": "Info"
},
"all-users": "All Users",
"audit-info-dialog": {
"title": "Audit Info"
},
"categories": {
"all-categories": "All Categories",
"audit": "Audit",
@ -1961,6 +1967,7 @@
"save": "Save",
"undo": "Undo"
},
"annotations": "",
"title": "Structured Component Management"
},
"rules-screen": {

View File

@ -402,7 +402,13 @@
},
"audit": "Aktivitätenprotokoll",
"audit-screen": {
"action": {
"info": "Info"
},
"all-users": "Alle Benutzer",
"audit-info-dialog": {
"title": "Audit Info"
},
"categories": {
"all-categories": "Alle Bereiche",
"audit": "Aktivitätenprotokoll",
@ -1961,6 +1967,7 @@
"save": "",
"undo": ""
},
"annotations": "",
"title": ""
},
"rules-screen": {

View File

@ -402,7 +402,13 @@
},
"audit": "Audit",
"audit-screen": {
"action": {
"info": "Info"
},
"all-users": "All Users",
"audit-info-dialog": {
"title": "Audit Info"
},
"categories": {
"all-categories": "All Categories",
"audit": "Audit",

View File

@ -4,11 +4,12 @@ import { IAudit } from './audit';
export class Audit implements IAudit, IListable {
readonly recordId: string;
readonly category: string;
readonly details?: unknown;
readonly details?: { [key: string]: string };
readonly message: string;
readonly objectId?: string;
readonly recordDate: string;
readonly userId: string;
readonly hasDetails: boolean;
constructor(audit: IAudit) {
this.category = audit.category;
@ -18,6 +19,7 @@ export class Audit implements IAudit, IListable {
this.recordDate = audit.recordDate;
this.recordId = audit.recordId;
this.userId = audit.userId;
this.hasDetails = audit.details ? Object.keys(audit.details).length > 0 : false;
}
get id(): string {

View File

@ -1,6 +1,6 @@
export interface IAudit {
readonly category: string;
readonly details?: unknown;
readonly details?: { [key: string]: string };
readonly message: string;
readonly objectId?: string;
readonly recordDate: string;