{{ dossierStats.numberOfFiles }}
diff --git a/apps/red-ui/src/app/modules/shared/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component.scss b/apps/red-ui/src/app/modules/shared/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component.scss
new file mode 100644
index 000000000..e69de29bb
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component.ts b/apps/red-ui/src/app/modules/shared/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component.ts
similarity index 79%
rename from apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component.ts
rename to apps/red-ui/src/app/modules/shared/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component.ts
index 30a26f8b5..d4b86aa17 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component.ts
+++ b/apps/red-ui/src/app/modules/shared/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component.ts
@@ -1,7 +1,6 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
import { Dossier, DossierStats } from '@red/domain';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
-import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
import * as moment from 'moment';
@@ -17,11 +16,7 @@ export class DossiersListingDossierNameComponent {
@Input() dossier: Dossier;
@Input() dossierStats: DossierStats;
- constructor(
- private readonly _dossierTemplatesService: DossierTemplatesService,
- private readonly _dossierStatsService: DossierStatsService,
- private readonly _dossiersService: DossiersService,
- ) {}
+ constructor(private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _dossiersService: DossiersService) {}
get approachingDueDate(): boolean {
return this._dueDateDaysDiff >= 0 && this._dueDateDaysDiff <= DUE_DATE_WARN_DAYS;
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 939fd0eb7..a185ccf62 100644
--- a/apps/red-ui/src/app/modules/shared/shared.module.ts
+++ b/apps/red-ui/src/app/modules/shared/shared.module.ts
@@ -27,6 +27,8 @@ import { TeamMembersComponent } from './components/team-members/team-members.com
import { EditorComponent } from './components/editor/editor.component';
import { ExpandableFileActionsComponent } from './components/expandable-file-actions/expandable-file-actions.component';
import { ProcessingIndicatorComponent } from '@shared/components/processing-indicator/processing-indicator.component';
+import { DossierStatusComponent } from '@shared/components/dossier-status/dossier-status.component';
+import { DossiersListingDossierNameComponent } from '@shared/components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component';
const buttons = [FileDownloadBtnComponent, UserButtonComponent];
@@ -43,6 +45,8 @@ const components = [
TeamMembersComponent,
ExpandableFileActionsComponent,
ProcessingIndicatorComponent,
+ DossierStatusComponent,
+ DossiersListingDossierNameComponent,
...buttons,
];
diff --git a/apps/red-ui/src/app/services/breadcrumbs.service.ts b/apps/red-ui/src/app/services/breadcrumbs.service.ts
index a6a082738..a6491df9a 100644
--- a/apps/red-ui/src/app/services/breadcrumbs.service.ts
+++ b/apps/red-ui/src/app/services/breadcrumbs.service.ts
@@ -10,12 +10,18 @@ import { BreadcrumbTypes } from '@red/domain';
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
export type RouterLinkActiveOptions = { exact: boolean } | IsActiveMatchOptions;
+export type BreadcrumbDisplayType = 'text' | 'dropdown';
export interface Breadcrumb {
readonly name$: Observable;
- readonly routerLink?: string[];
- readonly routerLinkActiveOptions?: RouterLinkActiveOptions | undefined;
- readonly clamp?: boolean;
+ readonly type: BreadcrumbDisplayType;
+ readonly options: {
+ readonly routerLink?: string[];
+ readonly routerLinkActiveOptions?: RouterLinkActiveOptions | undefined;
+ readonly clamp?: boolean;
+ readonly options?: Breadcrumb[];
+ readonly activeOption?: Breadcrumb;
+ };
}
export type Breadcrumbs = List;
@@ -63,7 +69,8 @@ export class BreadcrumbsService {
for (const breadcrumb of route.data.breadcrumbs || []) {
switch (breadcrumb) {
case BreadcrumbTypes.main:
- this._addMainBreadcrumb();
+ case BreadcrumbTypes.archive:
+ this._addMainBreadcrumb(breadcrumb as 'main' | 'archive');
break;
case BreadcrumbTypes.dossier:
this._addDossierBreadcrumb(route);
@@ -75,11 +82,34 @@ export class BreadcrumbsService {
}
}
- private _addMainBreadcrumb(): void {
- this._append({
+ private _addMainBreadcrumb(type: 'main' | 'archive'): void {
+ const activeDossiers: Breadcrumb = {
name$: of(this._translateService.instant('top-bar.navigation-items.dossiers')),
- routerLink: ['/main', 'dossiers'],
- routerLinkActiveOptions: { exact: true },
+ type: 'text' as BreadcrumbDisplayType,
+ options: {
+ routerLink: ['/main', 'dossiers'],
+ routerLinkActiveOptions: { exact: true },
+ },
+ };
+
+ const archivedDossiers: Breadcrumb = {
+ name$: of(this._translateService.instant('top-bar.navigation-items.archived-dossiers')),
+ type: 'text' as BreadcrumbDisplayType,
+ options: {
+ routerLink: ['/main', 'archive'],
+ routerLinkActiveOptions: { exact: true },
+ },
+ };
+
+ const activeOption = type === 'main' ? activeDossiers : archivedDossiers;
+
+ this._append({
+ name$: activeOption.name$,
+ type: 'dropdown' as BreadcrumbDisplayType,
+ options: {
+ options: [activeDossiers, archivedDossiers],
+ activeOption,
+ },
});
}
@@ -87,9 +117,12 @@ export class BreadcrumbsService {
const dossierId = route.paramMap.get(DOSSIER_ID);
this._append({
name$: this._dossiersService.getEntityChanged$(dossierId).pipe(pluck('dossierName')),
- routerLink: ['/main', 'dossiers', dossierId],
- routerLinkActiveOptions: { exact: true },
- clamp: true,
+ type: 'text' as BreadcrumbDisplayType,
+ options: {
+ routerLink: ['/main', 'dossiers', dossierId],
+ routerLinkActiveOptions: { exact: true },
+ clamp: true,
+ },
});
}
@@ -98,8 +131,11 @@ export class BreadcrumbsService {
const fileId = route.paramMap.get(FILE_ID);
this._append({
name$: this._filesMapService.watch$(dossierId, fileId).pipe(pluck('filename')),
- routerLink: ['/main', 'dossiers', dossierId, 'file', fileId],
- clamp: true,
+ type: 'text' as BreadcrumbDisplayType,
+ options: {
+ routerLink: ['/main', 'dossiers', dossierId, 'file', fileId],
+ clamp: true,
+ },
});
}
}
diff --git a/apps/red-ui/src/app/services/entity-services/archived-dossiers.service.ts b/apps/red-ui/src/app/services/entity-services/archived-dossiers.service.ts
new file mode 100644
index 000000000..9721d69ab
--- /dev/null
+++ b/apps/red-ui/src/app/services/entity-services/archived-dossiers.service.ts
@@ -0,0 +1,53 @@
+import { Injectable, Injector } from '@angular/core';
+import { EntitiesService, mapEach, Toaster } from '@iqser/common-ui';
+import { Dossier, IDossier } from '@red/domain';
+import { catchError, mapTo, switchMap, tap } from 'rxjs/operators';
+import { Observable, of } from 'rxjs';
+import { DossierStateService } from '@services/entity-services/dossier-state.service';
+import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
+import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
+import { DossiersService } from '@services/entity-services/dossiers.service';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class ArchivedDossiersService extends EntitiesService {
+ constructor(
+ protected readonly _injector: Injector,
+ private readonly _toaster: Toaster,
+ private readonly _dossierStateService: DossierStateService,
+ private readonly _dossierStatsService: DossierStatsService,
+ private readonly _dossiersService: DossiersService,
+ ) {
+ super(_injector, Dossier, 'archived-dossiers');
+ }
+
+ loadAll(): Observable {
+ const dossierIds = (dossiers: Dossier[]) => dossiers.map(d => d.id);
+ return this.getAll().pipe(
+ mapEach(entity => new Dossier(entity)),
+ /* Load stats before updating entities */
+ switchMap(dossiers => this._dossierStatsService.getFor(dossierIds(dossiers)).pipe(mapTo(dossiers))),
+ switchMap(dossiers => this._dossierStateService.loadAllForAllTemplates().pipe(mapTo(dossiers))),
+ tap(dossiers => this.setEntities(dossiers)),
+ );
+ }
+
+ archive(dossiers: Dossier[]): Observable {
+ const showToast = () => {
+ this._toaster.error(_('dossier-listing.archive.archive-failed'), { params: dossiers });
+ return of({});
+ };
+ return this._post(
+ dossiers.map(d => d.id),
+ `${this._defaultModelPath}/archive`,
+ ).pipe(
+ tap(() => this.#removeDossiers(dossiers)),
+ catchError(showToast),
+ );
+ }
+
+ #removeDossiers(dossiers: Dossier[]): void {
+ this._dossiersService.setEntities(this._dossiersService.all.filter(dossier => !dossiers.find(d => dossier.id === d.id)));
+ }
+}
diff --git a/apps/red-ui/src/app/services/entity-services/dossiers.service.ts b/apps/red-ui/src/app/services/entity-services/dossiers.service.ts
index 669383561..2610d479f 100644
--- a/apps/red-ui/src/app/services/entity-services/dossiers.service.ts
+++ b/apps/red-ui/src/app/services/entity-services/dossiers.service.ts
@@ -118,20 +118,6 @@ export class DossiersService extends EntitiesService {
);
}
- archive(dossiers: Dossier[]): Observable {
- const showToast = () => {
- this._toaster.error(_('dossier-listing.archive.archive-failed'), { params: dossiers });
- return of({});
- };
- return this._post(
- dossiers.map(d => d.id),
- 'archived-dossiers/archive',
- ).pipe(
- tap(() => this.#removeDossiers(dossiers)),
- catchError(showToast),
- );
- }
-
@Validate()
restore(@RequiredParam() dossierIds: List): Promise {
return firstValueFrom(this._post(dossierIds, 'deleted-dossiers/restore').pipe(switchMap(() => this.loadAll())));
diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json
index a1b84ce97..ba47d3192 100644
--- a/apps/red-ui/src/assets/i18n/en.json
+++ b/apps/red-ui/src/assets/i18n/en.json
@@ -313,6 +313,23 @@
"suggestion-resize": "Suggested Resize"
},
"annotations": "Annotations",
+ "archived-dossiers-listing": {
+ "no-data": {
+ "title": "No archived dossiers."
+ },
+ "no-match": {
+ "title": "No archived dossiers match your current filters."
+ },
+ "table-col-names": {
+ "dossier-status": "Dossier Status",
+ "last-modified": "Last Modified",
+ "name": "Name",
+ "owner": "Owner"
+ },
+ "table-header": {
+ "title": "{length} Archived {length, plural, one{Dossier} other{Dossiers}}"
+ }
+ },
"assign-dossier-owner": {
"dialog": {
"approvers": "Approvers",
@@ -1722,6 +1739,7 @@
},
"top-bar": {
"navigation-items": {
+ "archived-dossiers": "Archived Dossiers",
"back": "Back",
"dossiers": "Active Dossiers",
"my-account": {
diff --git a/libs/red-domain/src/lib/dossiers/dossier.model.ts b/libs/red-domain/src/lib/dossiers/dossier.model.ts
index e2a79d550..b95caf827 100644
--- a/libs/red-domain/src/lib/dossiers/dossier.model.ts
+++ b/libs/red-domain/src/lib/dossiers/dossier.model.ts
@@ -22,6 +22,7 @@ export class Dossier implements IDossier, IListable {
readonly status: DossierStatus;
readonly watermarkEnabled: boolean;
readonly watermarkPreviewEnabled: boolean;
+ readonly archivedTime: string;
readonly hasReviewers: boolean;
constructor(dossier: IDossier) {
@@ -43,6 +44,7 @@ export class Dossier implements IDossier, IListable {
this.status = dossier.status;
this.watermarkEnabled = dossier.watermarkEnabled;
this.watermarkPreviewEnabled = dossier.watermarkPreviewEnabled;
+ this.archivedTime = dossier.archivedTime;
this.hasReviewers = !!this.memberIds && this.memberIds.length > 1;
}
diff --git a/libs/red-domain/src/lib/dossiers/dossier.ts b/libs/red-domain/src/lib/dossiers/dossier.ts
index 1ff219033..59689a5d9 100644
--- a/libs/red-domain/src/lib/dossiers/dossier.ts
+++ b/libs/red-domain/src/lib/dossiers/dossier.ts
@@ -21,4 +21,5 @@ export interface IDossier {
readonly status: DossierStatus;
readonly watermarkEnabled: boolean;
readonly watermarkPreviewEnabled: boolean;
+ readonly archivedTime: string;
}
diff --git a/libs/red-domain/src/lib/shared/breadcrumb-types.ts b/libs/red-domain/src/lib/shared/breadcrumb-types.ts
index 3366c25a2..74ed8ae69 100644
--- a/libs/red-domain/src/lib/shared/breadcrumb-types.ts
+++ b/libs/red-domain/src/lib/shared/breadcrumb-types.ts
@@ -1,7 +1,8 @@
-export type BreadcrumbType = 'main' | 'dossier' | 'file';
+export type BreadcrumbType = 'main' | 'dossier' | 'file' | 'archive';
export const BreadcrumbTypes = {
main: 'main' as BreadcrumbType,
dossier: 'dossier' as BreadcrumbType,
file: 'file' as BreadcrumbType,
+ archive: 'archive' as BreadcrumbType,
};