From 7990636066e474d2ee4f4efbaa7fb22b849eada9 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Wed, 7 Jul 2021 20:07:47 +0300 Subject: [PATCH] show time to restore --- .../screens/trash/trash-screen.component.html | 86 +++++++++---------- .../screens/trash/trash-screen.component.ts | 60 ++++++++++--- .../src/app/modules/shared/pipes/date.pipe.ts | 62 +++++++++++++ .../src/app/modules/shared/shared.module.ts | 2 + apps/red-ui/src/assets/i18n/en.json | 8 ++ libs/red-ui-http/src/lib/model/dossier.ts | 2 + 6 files changed, 160 insertions(+), 60 deletions(-) create mode 100644 apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts diff --git a/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.html index 92a0e7c2e..e8f0dd7dc 100644 --- a/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.html @@ -1,7 +1,10 @@
- +
@@ -20,22 +23,20 @@ }} - - - + -
- -
+ + + + + + +
@@ -88,82 +89,75 @@
-
+
- {{ dw.dossierName }} + {{ entity.dossierName }}
- {{ getDossierTemplate(dw).name }} + {{ getDossierTemplate(entity.dossierTemplateId).name }}
-
- - {{ dw.files.length }} -
-
- - {{ dw.totalNumberOfPages }} -
- {{ dw.numberOfMembers }} + {{ entity.memberIds.length }}
- {{ dw.dossier.date | date: 'mediumDate' }} + {{ entity.date | date: 'mediumDate' }}
-
+
- {{ dw.dossier.dueDate | date: 'mediumDate' }} + {{ entity.dueDate | date: 'mediumDate' }}
- {{ dw.dossierDate | date: 'd MMM. yyyy' }} + {{ entity.softDeletedTime | date: 'd MMM. yyyy' }}
- {{ dw.dossier.date | date: 'd MMM. yyyy' }} + {{ getRestoreDate(entity.softDeletedTime) | date: 'timeFromNow' }}
diff --git a/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.ts index 5ef38b988..bbd15896b 100644 --- a/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/trash/trash-screen.component.ts @@ -1,42 +1,74 @@ import { Component, Injector, OnInit } from '@angular/core'; import { BaseListingComponent } from '@shared/base/base-listing.component'; -import { AdminDialogService } from '../../services/admin-dialog.service'; import { AppStateService } from '@state/app-state.service'; import { PermissionsService } from '@services/permissions.service'; -import { UserPreferenceService } from '@services/user-preference.service'; -import { DossierWrapper } from '@state/model/dossier.wrapper'; -import { DossierTemplateModel } from '@redaction/red-ui-http'; +import { Dossier, DossierControllerService, DossierTemplateModel } from '@redaction/red-ui-http'; +import { LoadingService } from '../../../../services/loading.service'; +import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service'; +import * as moment from 'moment'; +import { TranslateService } from '@ngx-translate/core'; @Component({ templateUrl: './trash-screen.component.html', styleUrls: ['./trash-screen.component.scss'] }) -export class TrashScreenComponent extends BaseListingComponent implements OnInit { +export class TrashScreenComponent extends BaseListingComponent implements OnInit { readonly itemSize = 85; + private readonly _deleteRetentionHours = this._appConfigService.getConfig( + AppConfigKey.DELETE_RETENTION_HOURS + ); - protected readonly _searchKey = 'name'; + protected readonly _searchKey = 'dossierName'; protected readonly _selectionKey = 'dossierId'; protected readonly _sortKey = 'dossier-listing'; constructor( - private readonly _dialogService: AdminDialogService, private readonly _appStateService: AppStateService, readonly permissionsService: PermissionsService, - protected readonly _injector: Injector + protected readonly _injector: Injector, + private readonly _dossierControllerService: DossierControllerService, + private readonly _loadingService: LoadingService, + private readonly _appConfigService: AppConfigService, + private readonly _translateService: TranslateService ) { super(_injector); } - ngOnInit(): void { - this.loadDossierTemplatesData(); + async ngOnInit(): Promise { + this._loadingService.start(); + await this.loadDossierTemplatesData(); + this._loadingService.stop(); } - loadDossierTemplatesData() { - this.allEntities = this._appStateService.allDossiers; + async loadDossierTemplatesData(): Promise { + this.allEntities = await this._dossierControllerService.getDeletedDossiers().toPromise(); + console.log(this.allEntities); this._executeSearchImmediately(); } - getDossierTemplate(dw: DossierWrapper): DossierTemplateModel { - return this._appStateService.getDossierTemplateById(dw.dossier.dossierTemplateId); + getDossierTemplate(dossierTemplateId: string): DossierTemplateModel { + return this._appStateService.getDossierTemplateById(dossierTemplateId); + } + + getRestoreDate(softDeletedTime: string) { + return moment(softDeletedTime).add(5, 'hours').format(); + } + + async restore(dossier: Dossier) { + this._loadingService.start(); + await this._dossierControllerService.restoreDossiers([dossier.dossierId]).toPromise(); + this.allEntities = this.allEntities.filter(e => e !== dossier); + this._loadingService.stop(); + } + + async hardDelete(dossier: Dossier) { + this._loadingService.start(); + await this._dossierControllerService.hardDeleteDossiers([dossier.dossierId]).toPromise(); + this.allEntities = this.allEntities.filter(e => e !== dossier); + this._loadingService.stop(); + } + + trackById(index: number, dossier: Dossier) { + return dossier.dossierId; } } diff --git a/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts b/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts new file mode 100644 index 000000000..4de9e5b87 --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts @@ -0,0 +1,62 @@ +import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core'; +import * as moment from 'moment'; +import { TranslateService } from '@ngx-translate/core'; +import { DatePipe as BaseDatePipe } from '@angular/common'; + +const HOURS_IN_A_DAY = 24; +const MINUTES_IN_AN_HOUR = 60; + +@Pipe({ + name: 'date' +}) +export class DatePipe extends BaseDatePipe implements PipeTransform { + constructor( + @Inject(LOCALE_ID) private readonly _locale: string, + private readonly _translateService: TranslateService + ) { + super(_locale); + } + + transform(value: null | undefined, format?: string, timezone?: string, locale?: string): null; + transform( + value: Date | string | number | null | undefined, + format?: string, + timezone?: string, + locale?: string + ): string | null; + transform(value: any, format?: string, timezone?: string, locale?: string): string { + if (format === 'timeFromNow') return this._getTimeFromNow(value); + return super.transform(value, format, timezone, locale); + } + + private _getTimeFromNow(item: string) { + const date = moment(item); + const now = new Date(Date.now()); + + const daysLeft = date.diff(now, 'days'); + const hoursFromNow = date.diff(now, 'hours'); + const hoursLeft = hoursFromNow - HOURS_IN_A_DAY * daysLeft; + const minutesFromNow = date.diff(now, 'minutes'); + const minutesLeft = minutesFromNow - HOURS_IN_A_DAY * MINUTES_IN_AN_HOUR * daysLeft; + + if (daysLeft === 0 && hoursLeft === 0 && minutesLeft > 0) + return this._translate('time.less-than-an-hour'); + + const hoursSuffix = this._translate(`time.hour${hoursLeft === 1 ? '' : 's'}`); + const hoursDisplay = `${hoursLeft} ${hoursSuffix}`; + + if (daysLeft === 0 && hoursLeft > 0) return hoursDisplay; + + const daysSuffix = this._translate(`time.day${daysLeft === 1 ? '' : 's'}`); + const daysDisplay = `${daysLeft} ${daysSuffix}`; + + if (daysLeft > 0 && hoursLeft > 0) return `${daysDisplay} ${hoursDisplay}`; + if (daysLeft > 0) return daysDisplay; + + return this._translate(`time.no-time-left`); + } + + private _translate(value: string, params?: { [key: string]: string }) { + return this._translateService.instant(value, params); + } +} diff --git a/apps/red-ui/src/app/modules/shared/shared.module.ts b/apps/red-ui/src/app/modules/shared/shared.module.ts index 4118cd4da..eca2e5034 100644 --- a/apps/red-ui/src/app/modules/shared/shared.module.ts +++ b/apps/red-ui/src/app/modules/shared/shared.module.ts @@ -38,6 +38,7 @@ import { PopupFilterComponent } from '@shared/components/filters/popup-filter/po import { AssignUserDropdownComponent } from './components/assign-user-dropdown/assign-user-dropdown.component'; import { InputWithActionComponent } from '@shared/components/input-with-action/input-with-action.component'; import { PageHeaderComponent } from './components/page-header/page-header.component'; +import { DatePipe } from '@shared/pipes/date.pipe'; const buttons = [ ChevronButtonComponent, @@ -75,6 +76,7 @@ const components = [ const utils = [ HumanizePipe, + DatePipe, SyncWidthDirective, HasScrollbarDirective, NavigateLastDossiersScreenDirective diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 25b455450..cfd4dc125 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -1404,5 +1404,13 @@ "text-placeholder": "Enter text" }, "title": "Watermark" + }, + "time": { + "no-time-left": "Time to restore already passed", + "less-than-an-hour": "< 1 hour", + "hour": "hour", + "hours": "hours", + "day": "day", + "days": "days" } } diff --git a/libs/red-ui-http/src/lib/model/dossier.ts b/libs/red-ui-http/src/lib/model/dossier.ts index f950fa242..66668b2e5 100644 --- a/libs/red-ui-http/src/lib/model/dossier.ts +++ b/libs/red-ui-http/src/lib/model/dossier.ts @@ -19,10 +19,12 @@ export interface Dossier { dossierTemplateId?: string; downloadFileTypes?: Array; dueDate?: string; + hardDeletedTime?: string; memberIds?: Array; ownerId?: string; reportTemplateIds?: Array; reportTypes?: Array; + softDeletedTime?: string; status?: Dossier.StatusEnum; watermarkEnabled?: boolean; }