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 64ac343e5..e7e29e70e 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
@@ -39,7 +39,7 @@
@@ -106,6 +106,7 @@
implemen
private readonly _deleteRetentionHours = this._appConfigService.getConfig(AppConfigKey.DELETE_RETENTION_HOURS);
constructor(
- private readonly _appStateService: AppStateService,
- private readonly _statusControllerService: StatusControllerService,
readonly permissionsService: PermissionsService,
protected readonly _injector: Injector,
private readonly _dossiersService: DossiersService,
@@ -47,6 +47,19 @@ export class TrashScreenComponent extends BaseListingComponent implemen
this.screenStateService.setEntities(await this._dossiersService.getDeleted());
}
+ canRestore(softDeletedTime: string): boolean {
+ const date = moment(this.getRestoreDate(softDeletedTime));
+ 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;
+
+ return daysLeft >= 0 && hoursLeft >= 0 && minutesLeft > 0;
+ }
+
getRestoreDate(softDeletedTime: string): string {
return moment(softDeletedTime).add(this._deleteRetentionHours, 'hours').toISOString();
}
diff --git a/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts b/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts
index 4966a26d1..c091d8b73 100644
--- a/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts
+++ b/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts
@@ -5,7 +5,7 @@ import { SearchService } from '../services/search.service';
import { ScreenStateService } from '../services/screen-state.service';
import { combineLatest, Observable } from 'rxjs';
import { AutoUnsubscribeComponent } from './auto-unsubscribe.component';
-import { distinctUntilChanged, map } from 'rxjs/operators';
+import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
import { PermissionsService } from '@services/permissions.service';
import { FilterService } from '../services/filter.service';
@@ -14,14 +14,14 @@ export abstract class BaseListingComponent extends AutoUnsubscribeComponent i
@ViewChild(CdkVirtualScrollViewport)
readonly scrollViewport: CdkVirtualScrollViewport;
- readonly permissionsService: PermissionsService;
- readonly filterService: FilterService;
- readonly sortingService: SortingService;
- readonly searchService: SearchService;
- readonly screenStateService: ScreenStateService;
+ readonly permissionsService = this._injector.get(PermissionsService);
+ readonly filterService = this._injector.get(FilterService);
+ readonly sortingService = this._injector.get(SortingService);
+ readonly searchService = this._injector.get(SearchService);
+ readonly screenStateService = this._injector.get>(ScreenStateService);
- readonly sortedDisplayedEntities$: Observable;
- readonly noMatch$: Observable;
+ readonly sortedDisplayedEntities$ = this._sortedDisplayedEntities$;
+ readonly noMatch$ = this._noMatch$;
protected readonly _tableHeaderLabel: string;
/**
@@ -34,15 +34,7 @@ export abstract class BaseListingComponent extends AutoUnsubscribeComponent i
protected constructor(protected readonly _injector: Injector) {
super();
this.trackByPrimaryKey = this.trackByPrimaryKey.bind(this);
- this.permissionsService = this._injector.get(PermissionsService);
- this.filterService = this._injector.get(FilterService);
- this.sortingService = this._injector.get(SortingService);
- this.searchService = this._injector.get(SearchService);
- this.screenStateService = this._injector.get>(ScreenStateService);
setTimeout(() => this.setInitialConfig());
-
- this.sortedDisplayedEntities$ = this._sortedDisplayedEntities$;
- this.noMatch$ = this._noMatch$;
}
get tableHeaderLabel(): string {
@@ -58,7 +50,9 @@ export abstract class BaseListingComponent extends AutoUnsubscribeComponent i
}
private get _sortedDisplayedEntities$(): Observable {
- return this.screenStateService.displayedEntities$.pipe(map(entities => this.sortingService.defaultSort(entities)));
+ return this.sortingService.sortingOptionChanged$.pipe(
+ switchMap(() => this.screenStateService.displayedEntities$.pipe(map(entities => this.sortingService.defaultSort(entities))))
+ );
}
private get _noMatch$(): Observable {
@@ -71,7 +65,7 @@ export abstract class BaseListingComponent extends AutoUnsubscribeComponent i
setInitialConfig() {
this.sortingService.setSortingOption({
column: this._primaryKey,
- order: SortingOrders.ASC
+ order: SortingOrders.asc
});
this.searchService.setSearchKey(this._primaryKey);
}
diff --git a/apps/red-ui/src/app/services/sorting.service.ts b/apps/red-ui/src/app/services/sorting.service.ts
index 9f54c91a5..f78954f67 100644
--- a/apps/red-ui/src/app/services/sorting.service.ts
+++ b/apps/red-ui/src/app/services/sorting.service.ts
@@ -1,46 +1,40 @@
import { Injectable } from '@angular/core';
import { orderBy } from 'lodash';
+import { BehaviorSubject } from 'rxjs';
-export type SortingOrder = 'asc' | 'desc';
+export const SortingOrders = {
+ asc: 'asc',
+ desc: 'desc'
+} as const;
-export const enum SortingOrders {
- ASC = 'asc',
- DESC = 'desc'
-}
+export type SortingOrder = keyof typeof SortingOrders;
export interface SortingOption {
- order: SortingOrder;
- column: string;
+ readonly order: SortingOrder;
+ readonly column: string;
}
@Injectable({
providedIn: 'root'
})
export class SortingService {
- private _sortingOption: SortingOption;
+ private readonly _sortingOption$ = new BehaviorSubject(null);
+ readonly sortingOptionChanged$ = this._sortingOption$.asObservable();
get sortingOption(): SortingOption {
- return this._sortingOption;
- }
-
- private get _currentOrder(): SortingOrder {
- return this._sortingOption.order;
- }
-
- private set _currentOrder(value: SortingOrder) {
- this._sortingOption.order = value;
+ return this._sortingOption$.getValue();
}
setSortingOption(value: SortingOption): void {
- this._sortingOption = value;
+ this._sortingOption$.next(value);
}
- sort(values: T[], order = '', column: string = ''): T[] {
- if (!values || order === '' || !order) {
+ sort(values: T[], order?: string, column?: string): T[] {
+ if (!values || !order) {
return values;
} // no array
- if (!column || column === '') {
- if (order === SortingOrders.ASC) {
+ if (!column) {
+ if (order === SortingOrders.asc) {
return values.sort();
} else {
return values.sort().reverse();
@@ -57,10 +51,13 @@ export class SortingService {
}
toggleSort(column: string) {
- if (this._sortingOption.column === column) {
- this._currentOrder = this._currentOrder === SortingOrders.ASC ? SortingOrders.DESC : SortingOrders.ASC;
+ if (this.sortingOption.column === column) {
+ this._sortingOption$.next({
+ column,
+ order: this.sortingOption.order === SortingOrders.asc ? SortingOrders.desc : SortingOrders.asc
+ });
} else {
- this._sortingOption = { column, order: SortingOrders.ASC };
+ this._sortingOption$.next({ column, order: SortingOrders.asc });
}
}
}