diff --git a/apps/red-ui/src/app/modules/app-config/app-config.service.ts b/apps/red-ui/src/app/modules/app-config/app-config.service.ts index b0689d802..cf68cbd88 100644 --- a/apps/red-ui/src/app/modules/app-config/app-config.service.ts +++ b/apps/red-ui/src/app/modules/app-config/app-config.service.ts @@ -17,6 +17,7 @@ export enum AppConfigKey { ADMIN_CONTACT_URL = 'ADMIN_CONTACT_URL', AUTO_READ_TIME = 'AUTO_READ_TIME', MAX_FILE_SIZE_MB = 'MAX_FILE_SIZE_MB', + RECENT_PERIOD_IN_HOURS = 'RECENT_PERIOD_IN_HOURS', DELETE_RETENTION_HOURS = 'DELETE_RETENTION_HOURS', APP_NAME = 'APP_NAME', diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.scss b/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.scss index 7ccd36056..d101f19d8 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.scss +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.scss @@ -4,10 +4,6 @@ .content-container { position: relative; - .header-item { - justify-content: space-between; - } - cdk-virtual-scroll-viewport { ::ng-deep.cdk-virtual-scroll-content-wrapper { grid-template-columns: 2fr 1fr 1fr auto 11px; diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.ts index b0763931a..18987c562 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-listing-screen/dossier-listing-screen.component.ts @@ -24,8 +24,7 @@ import { dossierMemberChecker, dossierStatusChecker, dossierTemplateChecker, - processFilters, - quickFiltersChecker + processFilters } from '@shared/components/filters/popup-filter/utils/filter-utils'; import { QuickFiltersComponent } from '../../../shared/components/filters/quick-filters/quick-filters.component'; @@ -124,7 +123,8 @@ export class DossierListingScreenComponent { values: this.dossierTemplateFilters, checker: dossierTemplateChecker }, { values: this.quickFilters, - checker: quickFiltersChecker(this.quickFilters) + checker: (dw: DossierWrapper) => + this.quickFilters.reduce((acc, f) => acc || (f.checked && f.checker(dw)), false) } ]; } diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html index 3133e2b44..794c14beb 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview-screen/dossier-overview-screen.component.html @@ -106,6 +106,11 @@ (reload)="bulkActionPerformed()" [selectedFileIds]="selectedEntitiesIds" > + +
f.required && f.checked); + } + + get checkedNotRequiredFilters() { + return this.quickFilters.filter(f => !f.required && f.checked); + } + protected get _filterComponents(): (PopupFilterComponent | QuickFiltersComponent)[] { return [ this._statusFilterComponent, this._peopleFilterComponent, - this._needsWorkFilterComponent + this._needsWorkFilterComponent, + this._quickFiltersComponent ]; } @@ -118,6 +135,16 @@ export class DossierOverviewScreenComponent checker: annotationFilterChecker, matchAll: true, checkerArgs: this.permissionsService + }, + { + values: this.quickFilters, + checker: (file: FileStatusWrapper) => + this.checkedRequiredFilters.reduce((acc, f) => acc && f.checker(file), true) && + (this.checkedNotRequiredFilters.length === 0 || + this.checkedNotRequiredFilters.reduce( + (acc, f) => acc || f.checker(file), + false + )) } ]; } @@ -287,6 +314,11 @@ export class DossierOverviewScreenComponent this.collapsedDetails = !this.collapsedDetails; } + recentlyModifiedChecker = (file: FileStatusWrapper) => + moment(file.lastUpdated) + .add(this._appConfigService.getConfig('RECENT_PERIOD_IN_HOURS'), 'hours') + .isAfter(moment()); + protected _preFilter() { this.detailsContainerFilters = { needsWorkFilters: this.needsWorkFilters.map(f => ({ ...f })), @@ -378,5 +410,41 @@ export class DossierOverviewScreenComponent (a, b) => RedactionFilterSorter[a.key] - RedactionFilterSorter[b.key] ); this.needsWorkFilters = processFilters(this.needsWorkFilters, needsWorkFilters); + + this._computeQuickFilters(); + } + + private _computeQuickFilters() { + if (this.allEntities.filter(this.recentlyModifiedChecker).length > 0) { + this.quickFilters = [ + { + key: this.user.id, + label: 'dossier-overview.quick-filters.recent', + required: true, + checker: this.recentlyModifiedChecker + } + ]; + } else { + this.quickFilters = []; + } + + this.quickFilters = [ + ...this.quickFilters, + { + key: this.user.id, + label: 'dossier-overview.quick-filters.assigned-to-me', + checker: (file: FileStatusWrapper) => file.currentReviewer === this.user.id + }, + { + key: this.user.id, + label: 'dossier-overview.quick-filters.unassigned', + checker: (file: FileStatusWrapper) => !file.currentReviewer + }, + { + key: this.user.id, + label: 'dossier-overview.quick-filters.assigned-to-others', + checker: (file: FileStatusWrapper) => file.currentReviewer !== this.user.id + } + ]; } } diff --git a/apps/red-ui/src/app/modules/shared/components/filters/popup-filter/model/filter.model.ts b/apps/red-ui/src/app/modules/shared/components/filters/popup-filter/model/filter.model.ts index 4f65e85cd..16686cf98 100644 --- a/apps/red-ui/src/app/modules/shared/components/filters/popup-filter/model/filter.model.ts +++ b/apps/red-ui/src/app/modules/shared/components/filters/popup-filter/model/filter.model.ts @@ -9,4 +9,5 @@ export interface FilterModel { matches?: number; filters?: FilterModel[]; checker?: (obj?) => boolean; + required?: boolean; } diff --git a/apps/red-ui/src/app/modules/shared/components/filters/popup-filter/utils/filter-utils.ts b/apps/red-ui/src/app/modules/shared/components/filters/popup-filter/utils/filter-utils.ts index 40679fd19..1eb819636 100644 --- a/apps/red-ui/src/app/modules/shared/components/filters/popup-filter/utils/filter-utils.ts +++ b/apps/red-ui/src/app/modules/shared/components/filters/popup-filter/utils/filter-utils.ts @@ -175,9 +175,6 @@ export const addedDateChecker = (dw: DossierWrapper, filter: FilterModel) => export const dossierApproverChecker = (dw: DossierWrapper, filter: FilterModel) => dw.approverIds.includes(filter.key); -export const quickFiltersChecker = (quickFilters: FilterModel[]) => (dw: DossierWrapper) => - quickFilters.reduce((acc, filter) => acc || (filter.checked && filter.checker(dw)), false); - export function getFilteredEntities( entities: any[], filters: { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] diff --git a/apps/red-ui/src/app/modules/shared/components/filters/quick-filters/quick-filters.component.scss b/apps/red-ui/src/app/modules/shared/components/filters/quick-filters/quick-filters.component.scss index 5347cf580..b6eec662a 100644 --- a/apps/red-ui/src/app/modules/shared/components/filters/quick-filters/quick-filters.component.scss +++ b/apps/red-ui/src/app/modules/shared/components/filters/quick-filters/quick-filters.component.scss @@ -2,6 +2,8 @@ :host { display: flex; + flex: 1; + justify-content: flex-end; } .quick-filter { diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index c9c9c08ef..49ce0c5cf 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -10,6 +10,7 @@ "LICENSE_START": "01-01-2021", "LICENSE_END": "31-12-2021", "LICENSE_PAGE_COUNT": 1000000, + "RECENT_PERIOD_IN_HOURS": 24, "MAX_FILE_SIZE_MB": 100, "DELETE_RETENTION_HOURS": 96 } diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 31fbcdad3..a1f474edf 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -333,6 +333,12 @@ "reanalyse-dossier": { "success": "Files scheduled for reanalysis.", "error": "Failed to schedule files for reanalysis. Please try again." + }, + "quick-filters": { + "recent": "Recent", + "assigned-to-me": "Assigned to me", + "unassigned": "Unassigned", + "assigned-to-others": "Assigned to others" } }, "file-preview": { diff --git a/docker/red-ui/docker-entrypoint.sh b/docker/red-ui/docker-entrypoint.sh index 7d1f4cae9..ac66ed5d3 100755 --- a/docker/red-ui/docker-entrypoint.sh +++ b/docker/red-ui/docker-entrypoint.sh @@ -10,6 +10,7 @@ ADMIN_CONTACT_URL="${ADMIN_CONTACT_URL:-}" AUTO_READ_TIME="${AUTO_READ_TIME:-1.5}" MAX_FILE_SIZE_MB="${MAX_FILE_SIZE_MB:-50}" DELETE_RETENTION_HOURS="${DELETE_RETENTION_HOURS:-96}" +RECENT_PERIOD_IN_HOURS="${RECENT_PERIOD_IN_HOURS:-24}" BACKEND_APP_VERSION="${BACKEND_APP_VERSION:-4.7.0}" @@ -35,6 +36,7 @@ echo '{ "APP_NAME":"'"$APP_NAME"'", "AUTO_READ_TIME":'"$AUTO_READ_TIME"', "MAX_FILE_SIZE_MB":"'"$MAX_FILE_SIZE_MB"'", + "RECENT_PERIOD_IN_HOURS":"'"RECENT_PERIOD_IN_HOURS"'", "DELETE_RETENTION_HOURS":"'"$DELETE_RETENTION_HOURS"'", "API_URL":"'"$API_URL"'" }' > /usr/share/nginx/html/ui/assets/config/config.json