From ac8fa0ff52a1cc9cb6563d3f147fe6feb5ec001a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 19 Mar 2021 22:00:36 +0200 Subject: [PATCH 01/11] File attributes listing --- apps/red-ui/src/app/app.module.ts | 10 ++ .../circle-button.component.html | 2 + .../circle-button.component.scss | 4 + .../circle-button/circle-button.component.ts | 1 + .../rule-set-actions.component.scss | 7 - .../rule-set-view-switch/tabs.component.html | 2 +- .../rule-set-view-switch/tabs.component.ts | 9 +- apps/red-ui/src/app/icons/icons.module.ts | 1 + .../dictionary-listing-screen.component.html | 6 +- .../dictionary-listing-screen.component.scss | 5 +- ...e-attributes-listing-screen.component.html | 127 ++++++++++++++++++ ...e-attributes-listing-screen.component.scss | 54 ++++++++ ...ile-attributes-listing-screen.component.ts | 112 +++++++++++++++ .../watermark-screen.component.html | 9 +- .../project-listing-actions.component.html | 2 +- apps/red-ui/src/app/utils/sorting.service.ts | 5 +- apps/red-ui/src/assets/i18n/en.json | 19 +++ .../src/assets/icons/general/read-only.svg | 19 +++ apps/red-ui/src/assets/styles/red-tables.scss | 4 + 19 files changed, 370 insertions(+), 28 deletions(-) create mode 100644 apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html create mode 100644 apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.scss create mode 100644 apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts create mode 100644 apps/red-ui/src/assets/icons/general/read-only.svg diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index ac4295fd6..d73af6f1f 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -118,6 +118,7 @@ import { MatProgressBarModule } from '@angular/material/progress-bar'; import { ForceRedactionDialogComponent } from './dialogs/force-redaction-dialog/force-redaction-dialog.component'; import { AuditScreenComponent } from './screens/admin/audit-screen/audit-screen.component'; import { PaginationComponent } from './components/pagination/pagination.component'; +import { FileAttributesListingScreenComponent } from './screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component'; import { SearchInputComponent } from './components/search-input/search-input.component'; export function HttpLoaderFactory(httpClient: HttpClient) { @@ -237,6 +238,14 @@ const routes = [ routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] } }, + { + path: 'file-attributes', + component: FileAttributesListingScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, { path: 'watermark', component: WatermarkScreenComponent, @@ -392,6 +401,7 @@ const matImports = [ ComboSeriesVerticalComponent, AuditScreenComponent, PaginationComponent, + FileAttributesListingScreenComponent, SearchInputComponent ], imports: [ diff --git a/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.html b/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.html index bdad4ece7..8dcc3efc8 100644 --- a/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.html +++ b/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.html @@ -7,7 +7,9 @@ [disabled]="disabled" [class.small]="small" [class.overlay]="showDot" + [class.dummy]="dummy" mat-icon-button + [disableRipple]="dummy" > diff --git a/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.scss b/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.scss index b2af7125f..5e1167f4b 100644 --- a/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.scss +++ b/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.scss @@ -36,4 +36,8 @@ button { background-color: $yellow-2; } } + + &.dummy { + cursor: default; + } } diff --git a/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.ts b/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.ts index 085885e2a..e8f899791 100644 --- a/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.ts +++ b/apps/red-ui/src/app/components/buttons/circle-button/circle-button.component.ts @@ -14,6 +14,7 @@ export class CircleButtonComponent implements OnInit { @Input() disabled = false; @Input() small = false; @Input() type: 'default' | 'primary' | 'warn' | 'dark-bg' = 'default'; + @Input() dummy = false; @Output() action = new EventEmitter(); constructor() {} diff --git a/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.scss b/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.scss index eeb99fae7..e69de29bb 100644 --- a/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.scss +++ b/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.scss @@ -1,7 +0,0 @@ -.action-buttons { - display: flex; - - redaction-circle-button:not(:last-child) { - margin-right: 2px; - } -} diff --git a/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.html b/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.html index 0ffea530a..c93576d79 100644 --- a/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.html +++ b/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.html @@ -1,7 +1,7 @@
diff --git a/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts b/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts index d73b195b5..5ddfe29e4 100644 --- a/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts +++ b/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts @@ -2,6 +2,7 @@ import { Component, Input, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { AppStateService } from '../../state/app-state.service'; import { UserPreferenceService } from '../../common/service/user-preference.service'; +import { PermissionsService } from '../../common/service/permissions.service'; @Component({ selector: 'redaction-tabs', @@ -9,17 +10,19 @@ import { UserPreferenceService } from '../../common/service/user-preference.serv styleUrls: ['./tabs.component.scss'] }) export class TabsComponent implements OnInit { - @Input() public screen: 'rules' | 'dictionaries' | 'watermark' | 'default-colors'; + @Input() public screen: 'rules' | 'dictionaries' | 'watermark' | 'default-colors' | 'file-attributes'; - public tabs: { screen: string; onlyDevMode?: boolean; label?: string }[] = [ + public tabs: { screen: string; onlyDevMode?: boolean; onlyAdmin?: boolean; label?: string }[] = [ { screen: 'dictionaries' }, { screen: 'rules', onlyDevMode: true, label: 'rule-editor' }, { screen: 'default-colors' }, - { screen: 'watermark' } + { screen: 'watermark' }, + { screen: 'file-attributes', onlyAdmin: true } ]; constructor( public readonly userPreferenceService: UserPreferenceService, + public readonly permissionsService: PermissionsService, private readonly _router: Router, private readonly _appStateService: AppStateService ) {} diff --git a/apps/red-ui/src/app/icons/icons.module.ts b/apps/red-ui/src/app/icons/icons.module.ts index 7a0945248..a4f14eae0 100644 --- a/apps/red-ui/src/app/icons/icons.module.ts +++ b/apps/red-ui/src/app/icons/icons.module.ts @@ -55,6 +55,7 @@ export class IconsModule { 'preview', 'radio-indeterminate', 'radio-selected', + 'read-only', 'ready-for-approval', 'refresh', 'report', diff --git a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.html b/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.html index 558ca32e0..695d1740e 100644 --- a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.html +++ b/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.html @@ -42,7 +42,7 @@ {{ 'dictionary-listing.table-header.title' | translate: { length: displayedDictionaries.length } }} -
+
-
+
{{ dict.rank }}
-
+
diff --git a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.scss b/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.scss index 7ea9ffd49..defb8b5e7 100644 --- a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.scss +++ b/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.scss @@ -4,7 +4,7 @@ .header-item { padding: 0 16px 0 10px; - .dictionary-actions-container { + .attributes-actions-container { display: flex; flex: 1; justify-content: flex-end; @@ -36,8 +36,7 @@ redaction-table-col-name::ng-deep { align-items: center; justify-content: flex-start; - &.analyzed, - &.rank { + &.center { justify-content: center; } diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html new file mode 100644 index 000000000..b56c31b1b --- /dev/null +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html @@ -0,0 +1,127 @@ +
+ + +
+
+
+
+
+ + +
+ + + {{ 'file-attributes-listing.table-header.title' | translate: { length: displayedAttributes.length } }} + + +
+ +
+ +
+
+
+ +
+
+ + + + + + + +
+ +
+
+ +
+ + + +
+
+
+ +
+ +
+ {{ attribute.name }} +
+
+ - + + +
+
+ +
+
+
+ + + + +
+
+
+
+
+
+ +
+
+
diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.scss b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.scss new file mode 100644 index 000000000..92f4a963f --- /dev/null +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.scss @@ -0,0 +1,54 @@ +.page-header .actions { + display: flex; + justify-content: flex-end; +} + +.header-item { + padding: 0 24px 0 10px; +} + +redaction-table-col-name::ng-deep { + > div { + padding-left: 10px !important; + } +} + +.left-container { + width: 100vw; + + .header-item { + .attributes-actions-container { + display: flex; + flex: 1; + justify-content: flex-end; + + > *:not(:last-child) { + margin-right: 16px; + } + } + } + + cdk-virtual-scroll-viewport { + ::ng-deep.cdk-virtual-scroll-content-wrapper { + grid-template-columns: auto 1fr 1fr 1fr 1fr 11px; + + .table-item { + > div:not(.scrollbar-placeholder) { + padding-left: 10px; + } + + > div { + &.center { + align-items: center; + } + } + } + } + + &.has-scrollbar:hover { + ::ng-deep.cdk-virtual-scroll-content-wrapper { + grid-template-columns: auto 1fr 1fr 1fr 1fr; + } + } + } +} diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts new file mode 100644 index 000000000..38e6d3856 --- /dev/null +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts @@ -0,0 +1,112 @@ +import { Component, OnInit } from '@angular/core'; +import { PermissionsService } from '../../../common/service/permissions.service'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { FileAttribute, FileAttributesControllerService } from '@redaction/red-ui-http'; +import { AppStateService } from '../../../state/app-state.service'; +import { ActivatedRoute } from '@angular/router'; +import { debounce } from '../../../utils/debounce'; +import { SortingOption, SortingService } from '../../../utils/sorting.service'; + +@Component({ + selector: 'redaction-file-attributes-listing-screen', + templateUrl: './file-attributes-listing-screen.component.html', + styleUrls: ['./file-attributes-listing-screen.component.scss'] +}) +export class FileAttributesListingScreenComponent implements OnInit { + public searchForm: FormGroup; + public attributes: FileAttribute[] = []; + public displayedAttributes: FileAttribute[] = []; + public selectedFileAttributeIds: string[] = []; + + constructor( + public readonly permissionsService: PermissionsService, + public readonly _sortingService: SortingService, + private readonly _formBuilder: FormBuilder, + private readonly _fileAttributesService: FileAttributesControllerService, + private readonly _appStateService: AppStateService, + private readonly _activatedRoute: ActivatedRoute + ) { + this._appStateService.activateRuleSet(_activatedRoute.snapshot.params.ruleSetId); + + this.searchForm = this._formBuilder.group({ + query: [''] + }); + + this.searchForm.valueChanges.subscribe((value) => this._executeSearch(value)); + } + + async ngOnInit() { + try { + const response = await this._fileAttributesService.getFileAttributesConfiguration(this._appStateService.activeRuleSetId).toPromise(); + this.attributes = response?.fileAttributes || []; + } catch (e) { + // TODO: Remove + this.attributes = [ + { + name: 'Atribut', + editable: true, + id: '1', + visible: true + }, + { + name: 'Alt atribut', + editable: false, + id: '2', + visible: true + } + ]; + } + this.displayedAttributes = [...this.attributes]; + } + + public get noData(): boolean { + return this.displayedAttributes.length === 0; + } + + public get sortingOption(): SortingOption { + return this._sortingService.getSortingOption('file-attributes-listing'); + } + + public toggleSort($event) { + this._sortingService.toggleSort('file-attributes-listing', $event); + } + + @debounce(200) + private _executeSearch(value: { query: string }) { + this.displayedAttributes = this.attributes.filter((attribute) => attribute.name.toLowerCase().includes(value.query.toLowerCase())); + } + + public openAddEditAttributeDialog($event: MouseEvent, attribute?: FileAttribute) { + $event.stopPropagation(); + } + + public toggleAttributeSelected($event: MouseEvent, attribute: FileAttribute) { + $event.stopPropagation(); + const idx = this.selectedFileAttributeIds.indexOf(attribute.id); + if (idx === -1) { + this.selectedFileAttributeIds.push(attribute.id); + } else { + this.selectedFileAttributeIds.splice(idx, 1); + } + } + + public toggleSelectAll() { + if (this.areSomeAttributesSelected) { + this.selectedFileAttributeIds = []; + } else { + this.selectedFileAttributeIds = this.displayedAttributes.map((a) => a.id); + } + } + + public get areAllAttributesSelected() { + return this.displayedAttributes.length !== 0 && this.selectedFileAttributeIds.length === this.displayedAttributes.length; + } + + public get areSomeAttributesSelected() { + return this.selectedFileAttributeIds.length > 0; + } + + public isAttributeSelected(attribute: FileAttribute) { + return this.selectedFileAttributeIds.indexOf(attribute.id) !== -1; + } +} diff --git a/apps/red-ui/src/app/screens/admin/watermark-screen/watermark-screen.component.html b/apps/red-ui/src/app/screens/admin/watermark-screen/watermark-screen.component.html index ea6c8c85b..d4c0ca1ff 100644 --- a/apps/red-ui/src/app/screens/admin/watermark-screen/watermark-screen.component.html +++ b/apps/red-ui/src/app/screens/admin/watermark-screen/watermark-screen.component.html @@ -5,14 +5,7 @@
- +
diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.html b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.html index 55303082c..8d93d75d7 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.html +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.html @@ -36,5 +36,5 @@ > - +
diff --git a/apps/red-ui/src/app/utils/sorting.service.ts b/apps/red-ui/src/app/utils/sorting.service.ts index 45ffa97a8..b73629bdb 100644 --- a/apps/red-ui/src/app/utils/sorting.service.ts +++ b/apps/red-ui/src/app/utils/sorting.service.ts @@ -5,7 +5,7 @@ export class SortingOption { column: string; } -type Screen = 'project-listing' | 'project-overview' | 'dictionary-listing' | 'rule-sets-listing' | 'default-colors'; +type Screen = 'project-listing' | 'project-overview' | 'dictionary-listing' | 'rule-sets-listing' | 'default-colors' | 'file-attributes-listing'; @Injectable({ providedIn: 'root' @@ -16,7 +16,8 @@ export class SortingService { 'project-overview': { column: 'filename', order: 'asc' }, 'dictionary-listing': { column: 'label', order: 'asc' }, 'rule-sets-listing': { column: 'name', order: 'asc' }, - 'default-colors': { column: 'key', order: 'asc' } + 'default-colors': { column: 'key', order: 'asc' }, + 'file-attributes-listing': { column: 'name', order: 'asc' } }; constructor() {} diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 2f2404fe9..16d75e479 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -694,6 +694,24 @@ "modified-on": "Modified on" } }, + "file-attributes-listing": { + "search": "Search by attribute name...", + "add-new": "New Attribute", + "table-header": { + "title": "{{length}} file attributes" + }, + "table-col-names": { + "name": "Name", + "created-by": "Created by", + "permissions": "Permissions" + }, + "no-data": "No file attributes.", + "read-only": "Read-only", + "action": { + "edit": "Edit attribute", + "delete": "Delete attribute" + } + }, "user-listing": { "table-header": { "title": "{{length}} users" @@ -748,6 +766,7 @@ }, "rule-editor": "Rule Editor", "watermark": "Watermark", + "file-attributes": "File Attributes", "pending-changes-guard": "WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.", "reset-filters": "Reset Filters", "overwrite-files-dialog": { diff --git a/apps/red-ui/src/assets/icons/general/read-only.svg b/apps/red-ui/src/assets/icons/general/read-only.svg new file mode 100644 index 000000000..ff827078c --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/read-only.svg @@ -0,0 +1,19 @@ + + + 9C81EE87-2992-4087-907E-26A83F796466 + + + + + + + + + + + + + + + + diff --git a/apps/red-ui/src/assets/styles/red-tables.scss b/apps/red-ui/src/assets/styles/red-tables.scss index c5f77f376..34da2ed36 100644 --- a/apps/red-ui/src/assets/styles/red-tables.scss +++ b/apps/red-ui/src/assets/styles/red-tables.scss @@ -80,6 +80,10 @@ cdk-virtual-scroll-viewport { width: 14px; } + redaction-circle-button:not(:last-child) { + margin-right: 2px; + } + &.active { display: flex; // compensate for scroll From d6a4dcae77cc4b486d326625052ce2a1c7750306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 19 Mar 2021 22:05:40 +0200 Subject: [PATCH 02/11] Extract routing to module --- apps/red-ui/src/app/app-routing.module.ts | 212 ++++++++++++++++++++++ apps/red-ui/src/app/app.module.ts | 190 +------------------ 2 files changed, 215 insertions(+), 187 deletions(-) create mode 100644 apps/red-ui/src/app/app-routing.module.ts diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts new file mode 100644 index 000000000..bf29d8918 --- /dev/null +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -0,0 +1,212 @@ +import { AuthErrorComponent } from './screens/auth-error/auth-error.component'; +import { AuthGuard } from './auth/auth.guard'; +import { PdfViewerScreenComponent } from './screens/pdf-viewer-screen/pdf-viewer-screen.component'; +import { CompositeRouteGuard } from './utils/composite-route.guard'; +import { RedRoleGuard } from './auth/red-role.guard'; +import { HtmlDebugScreenComponent } from './screens/html-debug-screen/html-debug-screen.component'; +import { BaseScreenComponent } from './screens/base-screen/base-screen.component'; +import { ProjectListingScreenComponent } from './screens/project-listing-screen/project-listing-screen.component'; +import { AppStateGuard } from './state/app-state.guard'; +import { ProjectOverviewScreenComponent } from './screens/project-overview-screen/project-overview-screen.component'; +import { FilePreviewScreenComponent } from './screens/file/file-preview-screen/file-preview-screen.component'; +import { DownloadsListScreenComponent } from './screens/downloads-list-screen/downloads-list-screen.component'; +import { RuleSetsListingScreenComponent } from './screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component'; +import { DictionaryListingScreenComponent } from './screens/admin/dictionary-listing-screen/dictionary-listing-screen.component'; +import { DictionaryOverviewScreenComponent } from './screens/admin/dictionary-overview-screen/dictionary-overview-screen.component'; +import { PendingChangesGuard } from './utils/can-deactivate.guard'; +import { RulesScreenComponent } from './screens/admin/rules-screen/rules-screen.component'; +import { FileAttributesListingScreenComponent } from './screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component'; +import { WatermarkScreenComponent } from './screens/admin/watermark-screen/watermark-screen.component'; +import { DefaultColorsScreenComponent } from './screens/admin/default-colors-screen/default-colors-screen.component'; +import { UserListingScreenComponent } from './screens/admin/user-listing-screen/user-listing-screen.component'; +import { LicenseInformationScreenComponent } from './screens/admin/license-information-screen/license-information-screen.component'; +import { DigitalSignatureScreenComponent } from './screens/admin/digital-signature-screen/digital-signature-screen.component'; +import { AuditScreenComponent } from './screens/admin/audit-screen/audit-screen.component'; +import { RouterModule } from '@angular/router'; +import { NgModule } from '@angular/core'; + +const routes = [ + { + path: '', + redirectTo: 'ui/projects', + pathMatch: 'full' + }, + { + path: 'auth-error', + component: AuthErrorComponent, + canActivate: [AuthGuard] + }, + { + path: 'pdf-preview/:projectId/:fileId', + component: PdfViewerScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard] + } + }, + { + path: 'html-debug/:projectId/:fileId', + component: HtmlDebugScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard] + } + }, + + { + path: 'ui', + component: BaseScreenComponent, + children: [ + { + path: 'projects', + component: ProjectListingScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'projects/:projectId', + component: ProjectOverviewScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'projects/:projectId/file/:fileId', + component: FilePreviewScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'downloads', + component: DownloadsListScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'admin', + children: [ + { path: '', redirectTo: 'project-templates', pathMatch: 'full' }, + { + path: 'project-templates', + children: [ + { + path: '', + component: RuleSetsListingScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: ':ruleSetId', + children: [ + { + path: 'dictionaries', + children: [ + { + path: '', + component: DictionaryListingScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: ':type', + component: DictionaryOverviewScreenComponent, + canActivate: [CompositeRouteGuard], + canDeactivate: [PendingChangesGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + } + ] + }, + { + path: 'rules', + component: RulesScreenComponent, + canActivate: [CompositeRouteGuard], + canDeactivate: [PendingChangesGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'file-attributes', + component: FileAttributesListingScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'watermark', + component: WatermarkScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'default-colors', + component: DefaultColorsScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { path: '', redirectTo: 'dictionaries', pathMatch: 'full' } + ] + } + ] + }, + { + path: 'users', + component: UserListingScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'license-info', + component: LicenseInformationScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'digital-signature', + component: DigitalSignatureScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + }, + { + path: 'audit', + component: AuditScreenComponent, + canActivate: [CompositeRouteGuard], + data: { + routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] + } + } + ] + } + ] + } +]; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule {} diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index d73af6f1f..944c3e907 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -1,7 +1,7 @@ import { BrowserModule } from '@angular/platform-browser'; import { APP_INITIALIZER, NgModule } from '@angular/core'; import { AppComponent } from './app.component'; -import { ActivatedRoute, Router, RouterModule } from '@angular/router'; +import { ActivatedRoute, Router } from '@angular/router'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { HTTP_INTERCEPTORS, HttpClient, HttpClientModule } from '@angular/common/http'; @@ -43,15 +43,11 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { InitialsAvatarComponent } from './common/initials-avatar/initials-avatar.component'; import { StatusBarComponent } from './components/status-bar/status-bar.component'; import { LogoComponent } from './logo/logo.component'; -import { CompositeRouteGuard } from './utils/composite-route.guard'; -import { AppStateGuard } from './state/app-state.guard'; import { SimpleDoughnutChartComponent } from './components/simple-doughnut-chart/simple-doughnut-chart.component'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatSlideToggleModule } from '@angular/material/slide-toggle'; import { AnnotationIconComponent } from './components/annotation-icon/annotation-icon.component'; -import { AuthGuard } from './auth/auth.guard'; import { AuthErrorComponent } from './screens/auth-error/auth-error.component'; -import { RedRoleGuard } from './auth/red-role.guard'; import { MatListModule } from '@angular/material/list'; import { AssignOwnerDialogComponent } from './dialogs/assign-owner-dialog/assign-owner-dialog.component'; import { MatDatepickerModule } from '@angular/material/datepicker'; @@ -101,7 +97,6 @@ import { AddEditRuleSetDialogComponent } from './screens/admin/rule-sets-listing import { RuleSetActionsComponent } from './components/rule-set-actions/rule-set-actions.component'; import { TabsComponent } from './components/rule-set-view-switch/tabs.component'; import { MatSliderModule } from '@angular/material/slider'; -import { PendingChangesGuard } from './utils/can-deactivate.guard'; import { OverwriteFilesDialogComponent } from './dialogs/overwrite-files-dialog/overwrite-files-dialog.component'; import { KeycloakService } from 'keycloak-angular'; import { FileDownloadBtnComponent } from './components/buttons/file-download-btn/file-download-btn.component'; @@ -120,191 +115,12 @@ import { AuditScreenComponent } from './screens/admin/audit-screen/audit-screen. import { PaginationComponent } from './components/pagination/pagination.component'; import { FileAttributesListingScreenComponent } from './screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component'; import { SearchInputComponent } from './components/search-input/search-input.component'; +import { AppRoutingModule } from './app-routing.module'; export function HttpLoaderFactory(httpClient: HttpClient) { return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json'); } -const routes = [ - { - path: '', - redirectTo: 'ui/projects', - pathMatch: 'full' - }, - { - path: 'auth-error', - component: AuthErrorComponent, - canActivate: [AuthGuard] - }, - { - path: 'pdf-preview/:projectId/:fileId', - component: PdfViewerScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard] - } - }, - { - path: 'html-debug/:projectId/:fileId', - component: HtmlDebugScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard] - } - }, - - { - path: 'ui', - component: BaseScreenComponent, - children: [ - { - path: 'projects', - component: ProjectListingScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'projects/:projectId', - component: ProjectOverviewScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'projects/:projectId/file/:fileId', - component: FilePreviewScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'downloads', - component: DownloadsListScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'admin', - children: [ - { path: '', redirectTo: 'project-templates', pathMatch: 'full' }, - { - path: 'project-templates', - children: [ - { - path: '', - component: RuleSetsListingScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: ':ruleSetId', - children: [ - { - path: 'dictionaries', - children: [ - { - path: '', - component: DictionaryListingScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: ':type', - component: DictionaryOverviewScreenComponent, - canActivate: [CompositeRouteGuard], - canDeactivate: [PendingChangesGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - } - ] - }, - { - path: 'rules', - component: RulesScreenComponent, - canActivate: [CompositeRouteGuard], - canDeactivate: [PendingChangesGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'file-attributes', - component: FileAttributesListingScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'watermark', - component: WatermarkScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'default-colors', - component: DefaultColorsScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { path: '', redirectTo: 'dictionaries', pathMatch: 'full' } - ] - } - ] - }, - { - path: 'users', - component: UserListingScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'license-info', - component: LicenseInformationScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'digital-signature', - component: DigitalSignatureScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - }, - { - path: 'audit', - component: AuditScreenComponent, - canActivate: [CompositeRouteGuard], - data: { - routeGuards: [AuthGuard, RedRoleGuard, AppStateGuard] - } - } - ] - } - ] - } -]; - const matImports = [ MatDialogModule, MatNativeDateModule, @@ -421,7 +237,7 @@ const matImports = [ deps: [HttpClient] } }), - RouterModule.forRoot(routes), + AppRoutingModule, NgpSortModule, ...matImports, ToastrModule.forRoot({ From e3c2c5fe8712ffe0aab87924f739c70314ebac9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 19 Mar 2021 22:09:59 +0200 Subject: [PATCH 03/11] Move items outside of common directory --- apps/red-ui/src/app/app.module.ts | 8 ++++---- .../admin-page-header/admin-breadcrumbs.component.ts | 4 ++-- .../file-download-btn/file-download-btn.component.ts | 2 +- .../file-actions/file-actions.component.html | 0 .../file-actions/file-actions.component.scss | 0 .../file-actions/file-actions.component.ts | 2 +- .../filter/filter.component.html | 0 .../filter/filter.component.scss | 0 .../filter/filter.component.ts | 0 .../filter/model/filter.model.ts | 0 .../filter/utils/filter-utils.ts | 2 +- .../hidden-action/hidden-action.component.html | 0 .../hidden-action/hidden-action.component.scss | 0 .../hidden-action/hidden-action.component.ts | 0 .../initials-avatar/initials-avatar.component.html | 0 .../initials-avatar/initials-avatar.component.scss | 0 .../initials-avatar/initials-avatar.component.ts | 0 .../needs-work-badge/needs-work-badge.component.ts | 2 +- .../rule-set-actions/rule-set-actions.component.ts | 2 +- .../rule-set-view-switch/tabs.component.ts | 4 ++-- .../simple-doughnut-chart.component.ts | 2 +- .../team-members/team-members.component.ts | 2 +- .../components/type-filter/type-filter.component.ts | 2 +- .../force-redaction-dialog.component.ts | 2 +- .../manual-annotation-dialog.component.ts | 2 +- .../admin/audit-screen/audit-screen.component.ts | 2 +- .../default-colors-screen.component.ts | 2 +- .../dictionary-listing-screen.component.ts | 2 +- .../dictionary-overview-screen.component.ts | 2 +- .../digital-signature-screen.component.ts | 2 +- .../file-attributes-listing-screen.component.ts | 2 +- .../license-information-screen.component.ts | 2 +- .../rule-sets-listing-screen.component.ts | 2 +- .../admin/rules-screen/rules-screen.component.ts | 2 +- .../user-listing-screen.component.ts | 2 +- .../watermark-screen/watermark-screen.component.ts | 2 +- .../app/screens/base-screen/base-screen.component.ts | 4 ++-- .../annotation-actions.component.ts | 4 ++-- .../file-preview-screen.component.ts | 8 ++++---- .../app/screens/file/model/file-status.wrapper.ts | 2 +- .../file/page-indicator/page-indicator.component.ts | 2 +- .../screens/file/pdf-viewer/pdf-viewer.component.ts | 4 ++-- .../screens/file/service/annotation-draw.service.ts | 2 +- .../file/service/annotation-processing.service.ts | 6 +++--- .../app/screens/file/service/file-action.service.ts | 2 +- .../file/service/manual-annotation.service.ts | 2 +- .../screens/file/service/pdf-viewer-data.service.ts | 2 +- .../project-listing-actions.component.ts | 4 ++-- .../project-listing-details.component.ts | 2 +- .../project-listing-screen.component.ts | 12 ++++++------ .../bulk-actions/bulk-actions.component.ts | 2 +- .../project-details/project-details.component.ts | 6 +++--- .../project-overview-screen.component.ts | 12 ++++++------ .../src/app/upload-download/file-download.service.ts | 2 +- .../service => utils}/annotation-actions.service.ts | 10 +++++----- .../{common/service => utils}/permissions.service.ts | 8 ++++---- .../sorters/redaction-filter-sorter.ts | 0 .../app/{common => utils}/sorters/status-sorter.ts | 0 .../{common => utils}/sorters/super-type-sorter.ts | 0 .../service => utils}/user-preference.service.ts | 0 60 files changed, 77 insertions(+), 77 deletions(-) rename apps/red-ui/src/app/{common => components}/file-actions/file-actions.component.html (100%) rename apps/red-ui/src/app/{common => components}/file-actions/file-actions.component.scss (100%) rename apps/red-ui/src/app/{common => components}/file-actions/file-actions.component.ts (98%) rename apps/red-ui/src/app/{common => components}/filter/filter.component.html (100%) rename apps/red-ui/src/app/{common => components}/filter/filter.component.scss (100%) rename apps/red-ui/src/app/{common => components}/filter/filter.component.ts (100%) rename apps/red-ui/src/app/{common => components}/filter/model/filter.model.ts (100%) rename apps/red-ui/src/app/{common => components}/filter/utils/filter-utils.ts (98%) rename apps/red-ui/src/app/{common => components}/hidden-action/hidden-action.component.html (100%) rename apps/red-ui/src/app/{common => components}/hidden-action/hidden-action.component.scss (100%) rename apps/red-ui/src/app/{common => components}/hidden-action/hidden-action.component.ts (100%) rename apps/red-ui/src/app/{common => components}/initials-avatar/initials-avatar.component.html (100%) rename apps/red-ui/src/app/{common => components}/initials-avatar/initials-avatar.component.scss (100%) rename apps/red-ui/src/app/{common => components}/initials-avatar/initials-avatar.component.ts (100%) rename apps/red-ui/src/app/{common/service => utils}/annotation-actions.service.ts (96%) rename apps/red-ui/src/app/{common/service => utils}/permissions.service.ts (96%) rename apps/red-ui/src/app/{common => utils}/sorters/redaction-filter-sorter.ts (100%) rename apps/red-ui/src/app/{common => utils}/sorters/status-sorter.ts (100%) rename apps/red-ui/src/app/{common => utils}/sorters/super-type-sorter.ts (100%) rename apps/red-ui/src/app/{common/service => utils}/user-preference.service.ts (100%) diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 944c3e907..ccf7e55fe 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -40,7 +40,7 @@ import { AuthModule } from './auth/auth.module'; import { FileUploadDownloadModule } from './upload-download/file-upload-download.module'; import { FullPageLoadingIndicatorComponent } from './utils/full-page-loading-indicator/full-page-loading-indicator.component'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; -import { InitialsAvatarComponent } from './common/initials-avatar/initials-avatar.component'; +import { InitialsAvatarComponent } from './components/initials-avatar/initials-avatar.component'; import { StatusBarComponent } from './components/status-bar/status-bar.component'; import { LogoComponent } from './logo/logo.component'; import { SimpleDoughnutChartComponent } from './components/simple-doughnut-chart/simple-doughnut-chart.component'; @@ -57,7 +57,7 @@ import { HumanizePipe } from './utils/humanize.pipe'; import { CommentsComponent } from './components/comments/comments.component'; import { ManualAnnotationDialogComponent } from './dialogs/manual-redaction-dialog/manual-annotation-dialog.component'; import { ToastComponent } from './components/toast/toast.component'; -import { FilterComponent } from './common/filter/filter.component'; +import { FilterComponent } from './components/filter/filter.component'; import { TableColNameComponent } from './components/table-col-name/table-col-name.component'; import { ProjectDetailsComponent } from './screens/project-overview-screen/project-details/project-details.component'; import { PageIndicatorComponent } from './screens/file/page-indicator/page-indicator.component'; @@ -65,13 +65,13 @@ import { NeedsWorkBadgeComponent } from './components/needs-work-badge/needs-wor import { ProjectListingEmptyComponent } from './screens/empty-states/project-listing-empty/project-listing-empty.component'; import { AnnotationActionsComponent } from './screens/file/annotation-actions/annotation-actions.component'; import { ProjectListingDetailsComponent } from './screens/project-listing-screen/project-listing-details/project-listing-details.component'; -import { FileActionsComponent } from './common/file-actions/file-actions.component'; +import { FileActionsComponent } from './components/file-actions/file-actions.component'; import { TypeAnnotationIconComponent } from './components/type-annotation-icon/type-annotation-icon.component'; import { TypeFilterComponent } from './components/type-filter/type-filter.component'; import { DictionaryAnnotationIconComponent } from './components/dictionary-annotation-icon/dictionary-annotation-icon.component'; import { BulkActionsComponent } from './screens/project-overview-screen/bulk-actions/bulk-actions.component'; import { HttpCacheInterceptor } from '@redaction/red-cache'; -import { HiddenActionComponent } from './common/hidden-action/hidden-action.component'; +import { HiddenActionComponent } from './components/hidden-action/hidden-action.component'; import { IconButtonComponent } from './components/buttons/icon-button/icon-button.component'; import { UserButtonComponent } from './components/buttons/user-button/user-button.component'; import { CircleButtonComponent } from './components/buttons/circle-button/circle-button.component'; diff --git a/apps/red-ui/src/app/components/admin-page-header/admin-breadcrumbs.component.ts b/apps/red-ui/src/app/components/admin-page-header/admin-breadcrumbs.component.ts index c4318ebc3..d81a46fa9 100644 --- a/apps/red-ui/src/app/components/admin-page-header/admin-breadcrumbs.component.ts +++ b/apps/red-ui/src/app/components/admin-page-header/admin-breadcrumbs.component.ts @@ -1,7 +1,7 @@ import { Component, Input } from '@angular/core'; import { AppStateService } from '../../state/app-state.service'; -import { UserPreferenceService } from '../../common/service/user-preference.service'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { UserPreferenceService } from '../../utils/user-preference.service'; +import { PermissionsService } from '../../utils/permissions.service'; @Component({ selector: 'redaction-admin-breadcrumbs', diff --git a/apps/red-ui/src/app/components/buttons/file-download-btn/file-download-btn.component.ts b/apps/red-ui/src/app/components/buttons/file-download-btn/file-download-btn.component.ts index 1686b0f38..21b7edb01 100644 --- a/apps/red-ui/src/app/components/buttons/file-download-btn/file-download-btn.component.ts +++ b/apps/red-ui/src/app/components/buttons/file-download-btn/file-download-btn.component.ts @@ -1,5 +1,5 @@ import { Component, Input } from '@angular/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { ProjectWrapper } from '../../../state/model/project.wrapper'; import { FileStatusWrapper } from '../../../screens/file/model/file-status.wrapper'; import { FileDownloadService } from '../../../upload-download/file-download.service'; diff --git a/apps/red-ui/src/app/common/file-actions/file-actions.component.html b/apps/red-ui/src/app/components/file-actions/file-actions.component.html similarity index 100% rename from apps/red-ui/src/app/common/file-actions/file-actions.component.html rename to apps/red-ui/src/app/components/file-actions/file-actions.component.html diff --git a/apps/red-ui/src/app/common/file-actions/file-actions.component.scss b/apps/red-ui/src/app/components/file-actions/file-actions.component.scss similarity index 100% rename from apps/red-ui/src/app/common/file-actions/file-actions.component.scss rename to apps/red-ui/src/app/components/file-actions/file-actions.component.scss diff --git a/apps/red-ui/src/app/common/file-actions/file-actions.component.ts b/apps/red-ui/src/app/components/file-actions/file-actions.component.ts similarity index 98% rename from apps/red-ui/src/app/common/file-actions/file-actions.component.ts rename to apps/red-ui/src/app/components/file-actions/file-actions.component.ts index c8fb60ed6..4d663a7c2 100644 --- a/apps/red-ui/src/app/common/file-actions/file-actions.component.ts +++ b/apps/red-ui/src/app/components/file-actions/file-actions.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { PermissionsService } from '../service/permissions.service'; +import { PermissionsService } from '../../utils/permissions.service'; import { FileStatusWrapper } from '../../screens/file/model/file-status.wrapper'; import { DialogService } from '../../dialogs/dialog.service'; import { AppStateService } from '../../state/app-state.service'; diff --git a/apps/red-ui/src/app/common/filter/filter.component.html b/apps/red-ui/src/app/components/filter/filter.component.html similarity index 100% rename from apps/red-ui/src/app/common/filter/filter.component.html rename to apps/red-ui/src/app/components/filter/filter.component.html diff --git a/apps/red-ui/src/app/common/filter/filter.component.scss b/apps/red-ui/src/app/components/filter/filter.component.scss similarity index 100% rename from apps/red-ui/src/app/common/filter/filter.component.scss rename to apps/red-ui/src/app/components/filter/filter.component.scss diff --git a/apps/red-ui/src/app/common/filter/filter.component.ts b/apps/red-ui/src/app/components/filter/filter.component.ts similarity index 100% rename from apps/red-ui/src/app/common/filter/filter.component.ts rename to apps/red-ui/src/app/components/filter/filter.component.ts diff --git a/apps/red-ui/src/app/common/filter/model/filter.model.ts b/apps/red-ui/src/app/components/filter/model/filter.model.ts similarity index 100% rename from apps/red-ui/src/app/common/filter/model/filter.model.ts rename to apps/red-ui/src/app/components/filter/model/filter.model.ts diff --git a/apps/red-ui/src/app/common/filter/utils/filter-utils.ts b/apps/red-ui/src/app/components/filter/utils/filter-utils.ts similarity index 98% rename from apps/red-ui/src/app/common/filter/utils/filter-utils.ts rename to apps/red-ui/src/app/components/filter/utils/filter-utils.ts index 4b5458596..4941d5baa 100644 --- a/apps/red-ui/src/app/common/filter/utils/filter-utils.ts +++ b/apps/red-ui/src/app/components/filter/utils/filter-utils.ts @@ -1,7 +1,7 @@ import { FilterModel } from '../model/filter.model'; import { FileStatusWrapper } from '../../../screens/file/model/file-status.wrapper'; import { ProjectWrapper } from '../../../state/model/project.wrapper'; -import { PermissionsService } from '../../service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; export function processFilters(oldFilters: FilterModel[], newFilters: FilterModel[]) { copySettings(oldFilters, newFilters); diff --git a/apps/red-ui/src/app/common/hidden-action/hidden-action.component.html b/apps/red-ui/src/app/components/hidden-action/hidden-action.component.html similarity index 100% rename from apps/red-ui/src/app/common/hidden-action/hidden-action.component.html rename to apps/red-ui/src/app/components/hidden-action/hidden-action.component.html diff --git a/apps/red-ui/src/app/common/hidden-action/hidden-action.component.scss b/apps/red-ui/src/app/components/hidden-action/hidden-action.component.scss similarity index 100% rename from apps/red-ui/src/app/common/hidden-action/hidden-action.component.scss rename to apps/red-ui/src/app/components/hidden-action/hidden-action.component.scss diff --git a/apps/red-ui/src/app/common/hidden-action/hidden-action.component.ts b/apps/red-ui/src/app/components/hidden-action/hidden-action.component.ts similarity index 100% rename from apps/red-ui/src/app/common/hidden-action/hidden-action.component.ts rename to apps/red-ui/src/app/components/hidden-action/hidden-action.component.ts diff --git a/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.html b/apps/red-ui/src/app/components/initials-avatar/initials-avatar.component.html similarity index 100% rename from apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.html rename to apps/red-ui/src/app/components/initials-avatar/initials-avatar.component.html diff --git a/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.scss b/apps/red-ui/src/app/components/initials-avatar/initials-avatar.component.scss similarity index 100% rename from apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.scss rename to apps/red-ui/src/app/components/initials-avatar/initials-avatar.component.scss diff --git a/apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.ts b/apps/red-ui/src/app/components/initials-avatar/initials-avatar.component.ts similarity index 100% rename from apps/red-ui/src/app/common/initials-avatar/initials-avatar.component.ts rename to apps/red-ui/src/app/components/initials-avatar/initials-avatar.component.ts diff --git a/apps/red-ui/src/app/components/needs-work-badge/needs-work-badge.component.ts b/apps/red-ui/src/app/components/needs-work-badge/needs-work-badge.component.ts index 2334c9b48..65b5a007f 100644 --- a/apps/red-ui/src/app/components/needs-work-badge/needs-work-badge.component.ts +++ b/apps/red-ui/src/app/components/needs-work-badge/needs-work-badge.component.ts @@ -1,6 +1,6 @@ import { Component, Input, OnInit } from '@angular/core'; import { AppStateService } from '../../state/app-state.service'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { PermissionsService } from '../../utils/permissions.service'; import { FileStatusWrapper } from '../../screens/file/model/file-status.wrapper'; import { ProjectWrapper } from '../../state/model/project.wrapper'; diff --git a/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.ts b/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.ts index 902c3387a..5f6d4c15a 100644 --- a/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.ts +++ b/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { DialogService } from '../../dialogs/dialog.service'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { PermissionsService } from '../../utils/permissions.service'; import { AppStateService } from '../../state/app-state.service'; import { Router } from '@angular/router'; diff --git a/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts b/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts index 5ddfe29e4..a62a34b73 100644 --- a/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts +++ b/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts @@ -1,8 +1,8 @@ import { Component, Input, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { AppStateService } from '../../state/app-state.service'; -import { UserPreferenceService } from '../../common/service/user-preference.service'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { UserPreferenceService } from '../../utils/user-preference.service'; +import { PermissionsService } from '../../utils/permissions.service'; @Component({ selector: 'redaction-tabs', diff --git a/apps/red-ui/src/app/components/simple-doughnut-chart/simple-doughnut-chart.component.ts b/apps/red-ui/src/app/components/simple-doughnut-chart/simple-doughnut-chart.component.ts index 4705f8767..9828a12f8 100644 --- a/apps/red-ui/src/app/components/simple-doughnut-chart/simple-doughnut-chart.component.ts +++ b/apps/red-ui/src/app/components/simple-doughnut-chart/simple-doughnut-chart.component.ts @@ -1,6 +1,6 @@ import { Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; import { Color } from '../../utils/types'; -import { FilterModel } from '../../common/filter/model/filter.model'; +import { FilterModel } from '../filter/model/filter.model'; export class DoughnutChartConfig { value: number; diff --git a/apps/red-ui/src/app/components/team-members/team-members.component.ts b/apps/red-ui/src/app/components/team-members/team-members.component.ts index f1f94c557..55e13d956 100644 --- a/apps/red-ui/src/app/components/team-members/team-members.component.ts +++ b/apps/red-ui/src/app/components/team-members/team-members.component.ts @@ -1,5 +1,5 @@ import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { PermissionsService } from '../../utils/permissions.service'; @Component({ selector: 'redaction-team-members', diff --git a/apps/red-ui/src/app/components/type-filter/type-filter.component.ts b/apps/red-ui/src/app/components/type-filter/type-filter.component.ts index ed7bbc11f..fe3702f18 100644 --- a/apps/red-ui/src/app/components/type-filter/type-filter.component.ts +++ b/apps/red-ui/src/app/components/type-filter/type-filter.component.ts @@ -1,5 +1,5 @@ import { Component, Input, OnInit } from '@angular/core'; -import { FilterModel } from '../../common/filter/model/filter.model'; +import { FilterModel } from '../filter/model/filter.model'; import { AppStateService } from '../../state/app-state.service'; import { DEFAULT_RUL_SET_UUID } from '../../utils/rule-set-default'; diff --git a/apps/red-ui/src/app/dialogs/force-redaction-dialog/force-redaction-dialog.component.ts b/apps/red-ui/src/app/dialogs/force-redaction-dialog/force-redaction-dialog.component.ts index f79ef8af3..fa4fd1e35 100644 --- a/apps/red-ui/src/app/dialogs/force-redaction-dialog/force-redaction-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/force-redaction-dialog/force-redaction-dialog.component.ts @@ -7,7 +7,7 @@ import { NotificationService } from '../../notification/notification.service'; import { TranslateService } from '@ngx-translate/core'; import { UserService } from '../../user/user.service'; import { ManualAnnotationService } from '../../screens/file/service/manual-annotation.service'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { PermissionsService } from '../../utils/permissions.service'; export interface LegalBasisOption { label?: string; diff --git a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts index 0e27b091c..38ce3848a 100644 --- a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts @@ -9,7 +9,7 @@ import { UserService } from '../../user/user.service'; import { ManualRedactionEntryWrapper } from '../../screens/file/model/manual-redaction-entry.wrapper'; import { ManualAnnotationService } from '../../screens/file/service/manual-annotation.service'; import { ManualAnnotationResponse } from '../../screens/file/model/manual-annotation-response'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { PermissionsService } from '../../utils/permissions.service'; export interface LegalBasisOption { label?: string; diff --git a/apps/red-ui/src/app/screens/admin/audit-screen/audit-screen.component.ts b/apps/red-ui/src/app/screens/admin/audit-screen/audit-screen.component.ts index 0d0dbfae7..7df53cc82 100644 --- a/apps/red-ui/src/app/screens/admin/audit-screen/audit-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/audit-screen/audit-screen.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { FormBuilder, FormGroup } from '@angular/forms'; import { AuditControllerService, AuditResponse, AuditSearchRequest } from '@redaction/red-ui-http'; import { TranslateService } from '@ngx-translate/core'; diff --git a/apps/red-ui/src/app/screens/admin/default-colors-screen/default-colors-screen.component.ts b/apps/red-ui/src/app/screens/admin/default-colors-screen/default-colors-screen.component.ts index eb686c824..7fdaf535b 100644 --- a/apps/red-ui/src/app/screens/admin/default-colors-screen/default-colors-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/default-colors-screen/default-colors-screen.component.ts @@ -3,7 +3,7 @@ import { AppStateService } from '../../../state/app-state.service'; import { Colors, DictionaryControllerService, TypeValue } from '@redaction/red-ui-http'; import { ActivatedRoute } from '@angular/router'; import { SortingOption, SortingService } from '../../../utils/sorting.service'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { DialogService } from '../../../dialogs/dialog.service'; @Component({ diff --git a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.ts index b511b141a..fd6b9f05a 100644 --- a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/dictionary-listing-screen.component.ts @@ -6,7 +6,7 @@ import { DialogService } from '../../../dialogs/dialog.service'; import { AppStateService } from '../../../state/app-state.service'; import { tap } from 'rxjs/operators'; import { forkJoin } from 'rxjs'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { FormBuilder, FormGroup } from '@angular/forms'; import { debounce } from '../../../utils/debounce'; import { ActivatedRoute } from '@angular/router'; diff --git a/apps/red-ui/src/app/screens/admin/dictionary-overview-screen/dictionary-overview-screen.component.ts b/apps/red-ui/src/app/screens/admin/dictionary-overview-screen/dictionary-overview-screen.component.ts index e36ab7b20..e150eb501 100644 --- a/apps/red-ui/src/app/screens/admin/dictionary-overview-screen/dictionary-overview-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/dictionary-overview-screen/dictionary-overview-screen.component.ts @@ -2,7 +2,7 @@ import { Component, ElementRef, ViewChild } from '@angular/core'; import { DictionaryControllerService, TypeValue } from '@redaction/red-ui-http'; import { DialogService } from '../../../dialogs/dialog.service'; import { AppStateService } from '../../../state/app-state.service'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { ActivatedRoute, Router } from '@angular/router'; import { AceEditorComponent } from 'ng2-ace-editor'; import { debounce } from '../../../utils/debounce'; diff --git a/apps/red-ui/src/app/screens/admin/digital-signature-screen/digital-signature-screen.component.ts b/apps/red-ui/src/app/screens/admin/digital-signature-screen/digital-signature-screen.component.ts index 327553587..bbeb6b39b 100644 --- a/apps/red-ui/src/app/screens/admin/digital-signature-screen/digital-signature-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/digital-signature-screen/digital-signature-screen.component.ts @@ -3,7 +3,7 @@ import { DigitalSignature, DigitalSignatureControllerService } from '@redaction/ import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { NotificationService, NotificationType } from '../../../notification/notification.service'; import { TranslateService } from '@ngx-translate/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { lastIndexOfEnd } from '../../../utils/functions'; @Component({ diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts index 38e6d3856..e3eecb7c6 100644 --- a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { FormBuilder, FormGroup } from '@angular/forms'; import { FileAttribute, FileAttributesControllerService } from '@redaction/red-ui-http'; import { AppStateService } from '../../../state/app-state.service'; diff --git a/apps/red-ui/src/app/screens/admin/license-information-screen/license-information-screen.component.ts b/apps/red-ui/src/app/screens/admin/license-information-screen/license-information-screen.component.ts index 263d57718..1e5081dba 100644 --- a/apps/red-ui/src/app/screens/admin/license-information-screen/license-information-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/license-information-screen/license-information-screen.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { LicenseReport, LicenseReportControllerService } from '@redaction/red-ui-http'; import { AppConfigService } from '../../../app-config/app-config.service'; import * as moment from 'moment'; diff --git a/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component.ts index 798199927..7c7b9d617 100644 --- a/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit } from '@angular/core'; import { SortingOption, SortingService } from '../../../utils/sorting.service'; import { DialogService } from '../../../dialogs/dialog.service'; import { AppStateService } from '../../../state/app-state.service'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { FormBuilder, FormGroup } from '@angular/forms'; import { debounce } from '../../../utils/debounce'; import { RuleSetModel } from '@redaction/red-ui-http'; diff --git a/apps/red-ui/src/app/screens/admin/rules-screen/rules-screen.component.ts b/apps/red-ui/src/app/screens/admin/rules-screen/rules-screen.component.ts index 33be7fbc2..21c30d8d9 100644 --- a/apps/red-ui/src/app/screens/admin/rules-screen/rules-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/rules-screen/rules-screen.component.ts @@ -1,5 +1,5 @@ import { Component, ElementRef, ViewChild } from '@angular/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { AceEditorComponent } from 'ng2-ace-editor'; import { RulesControllerService, RuleSetModel } from '@redaction/red-ui-http'; import { NotificationService, NotificationType } from '../../../notification/notification.service'; diff --git a/apps/red-ui/src/app/screens/admin/user-listing-screen/user-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/user-listing-screen/user-listing-screen.component.ts index 99d12a890..f987df0de 100644 --- a/apps/red-ui/src/app/screens/admin/user-listing-screen/user-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/user-listing-screen/user-listing-screen.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { UserService } from '../../../user/user.service'; import { User } from '@redaction/red-ui-http'; import { FormBuilder, FormGroup } from '@angular/forms'; diff --git a/apps/red-ui/src/app/screens/admin/watermark-screen/watermark-screen.component.ts b/apps/red-ui/src/app/screens/admin/watermark-screen/watermark-screen.component.ts index d0238e7f3..c6f6b89f6 100644 --- a/apps/red-ui/src/app/screens/admin/watermark-screen/watermark-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/watermark-screen/watermark-screen.component.ts @@ -1,5 +1,5 @@ import { ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import WebViewer, { WebViewerInstance } from '@pdftron/webviewer'; import { AppStateService } from '../../../state/app-state.service'; import { environment } from '../../../../environments/environment'; diff --git a/apps/red-ui/src/app/screens/base-screen/base-screen.component.ts b/apps/red-ui/src/app/screens/base-screen/base-screen.component.ts index 9f9e37fd8..e592b5e7f 100644 --- a/apps/red-ui/src/app/screens/base-screen/base-screen.component.ts +++ b/apps/red-ui/src/app/screens/base-screen/base-screen.component.ts @@ -2,8 +2,8 @@ import { Component } from '@angular/core'; import { UserService } from '../../user/user.service'; import { AppStateService } from '../../state/app-state.service'; import { LanguageService } from '../../i18n/language.service'; -import { PermissionsService } from '../../common/service/permissions.service'; -import { UserPreferenceService } from '../../common/service/user-preference.service'; +import { PermissionsService } from '../../utils/permissions.service'; +import { UserPreferenceService } from '../../utils/user-preference.service'; import { Router } from '@angular/router'; import { AppConfigService } from '../../app-config/app-config.service'; import { Title } from '@angular/platform-browser'; diff --git a/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.ts b/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.ts index a56185a0d..bb07606c9 100644 --- a/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.ts +++ b/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.ts @@ -1,9 +1,9 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { AnnotationWrapper } from '../model/annotation.wrapper'; import { AppStateService } from '../../../state/app-state.service'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { AnnotationPermissions } from '../model/annotation.permissions'; -import { AnnotationActionsService } from '../../../common/service/annotation-actions.service'; +import { AnnotationActionsService } from '../../../utils/annotation-actions.service'; import { Annotations, WebViewerInstance } from '@pdftron/webviewer'; @Component({ diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts index 54111d07d..31c9a8f79 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts @@ -15,15 +15,15 @@ import { AnnotationData, FileDataModel } from '../model/file-data.model'; import { FileActionService } from '../service/file-action.service'; import { AnnotationDrawService } from '../service/annotation-draw.service'; import { AnnotationProcessingService } from '../service/annotation-processing.service'; -import { FilterModel } from '../../../common/filter/model/filter.model'; +import { FilterModel } from '../../../components/filter/model/filter.model'; import { tap } from 'rxjs/operators'; import { NotificationService } from '../../../notification/notification.service'; import { TranslateService } from '@ngx-translate/core'; import { FileStatusWrapper } from '../model/file-status.wrapper'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { Subscription, timer } from 'rxjs'; -import { handleFilterDelta, processFilters } from '../../../common/filter/utils/filter-utils'; -import { UserPreferenceService } from '../../../common/service/user-preference.service'; +import { handleFilterDelta, processFilters } from '../../../components/filter/utils/filter-utils'; +import { UserPreferenceService } from '../../../utils/user-preference.service'; import { UserService } from '../../../user/user.service'; import { FormBuilder, FormGroup } from '@angular/forms'; import { FileManagementControllerService, StatusControllerService } from '@redaction/red-ui-http'; diff --git a/apps/red-ui/src/app/screens/file/model/file-status.wrapper.ts b/apps/red-ui/src/app/screens/file/model/file-status.wrapper.ts index 0c827b641..234879708 100644 --- a/apps/red-ui/src/app/screens/file/model/file-status.wrapper.ts +++ b/apps/red-ui/src/app/screens/file/model/file-status.wrapper.ts @@ -1,5 +1,5 @@ import { FileStatus } from '@redaction/red-ui-http'; -import { StatusSorter } from '../../../common/sorters/status-sorter'; +import { StatusSorter } from '../../../utils/sorters/status-sorter'; export class FileStatusWrapper { constructor(public fileStatus: FileStatus, public reviewerName: string) {} diff --git a/apps/red-ui/src/app/screens/file/page-indicator/page-indicator.component.ts b/apps/red-ui/src/app/screens/file/page-indicator/page-indicator.component.ts index 29d7fbe39..4045a09c1 100644 --- a/apps/red-ui/src/app/screens/file/page-indicator/page-indicator.component.ts +++ b/apps/red-ui/src/app/screens/file/page-indicator/page-indicator.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core'; import { ViewedPages, ViewedPagesControllerService } from '@redaction/red-ui-http'; import { AppStateService } from '../../../state/app-state.service'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { AppConfigKey, AppConfigService } from '../../../app-config/app-config.service'; import { Subscription } from 'rxjs'; diff --git a/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts index 1e23aa9ee..171014c2d 100644 --- a/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts @@ -24,8 +24,8 @@ import { FileStatusWrapper } from '../model/file-status.wrapper'; import { KeycloakService } from 'keycloak-angular'; import { environment } from '../../../../environments/environment'; import { AnnotationDrawService } from '../service/annotation-draw.service'; -import { AnnotationActionsService } from '../../../common/service/annotation-actions.service'; -import { UserPreferenceService } from '../../../common/service/user-preference.service'; +import { AnnotationActionsService } from '../../../utils/annotation-actions.service'; +import { UserPreferenceService } from '../../../utils/user-preference.service'; import { translateQuads } from '../../../utils/pdf-coordinates'; import Tool = Tools.Tool; diff --git a/apps/red-ui/src/app/screens/file/service/annotation-draw.service.ts b/apps/red-ui/src/app/screens/file/service/annotation-draw.service.ts index 64c39f020..b3d23f7c4 100644 --- a/apps/red-ui/src/app/screens/file/service/annotation-draw.service.ts +++ b/apps/red-ui/src/app/screens/file/service/annotation-draw.service.ts @@ -4,7 +4,7 @@ import { Rectangle, RedactionLogControllerService, SectionGrid, SectionRectangle import { hexToRgb } from '../../../utils/functions'; import { AppStateService } from '../../../state/app-state.service'; import { AnnotationWrapper } from '../model/annotation.wrapper'; -import { UserPreferenceService } from '../../../common/service/user-preference.service'; +import { UserPreferenceService } from '../../../utils/user-preference.service'; @Injectable({ providedIn: 'root' diff --git a/apps/red-ui/src/app/screens/file/service/annotation-processing.service.ts b/apps/red-ui/src/app/screens/file/service/annotation-processing.service.ts index f5943932f..379774b64 100644 --- a/apps/red-ui/src/app/screens/file/service/annotation-processing.service.ts +++ b/apps/red-ui/src/app/screens/file/service/annotation-processing.service.ts @@ -1,9 +1,9 @@ import { Injectable } from '@angular/core'; import { AppStateService } from '../../../state/app-state.service'; import { AnnotationWrapper } from '../model/annotation.wrapper'; -import { FilterModel } from '../../../common/filter/model/filter.model'; -import { handleCheckedValue } from '../../../common/filter/utils/filter-utils'; -import { SuperTypeSorter } from '../../../common/sorters/super-type-sorter'; +import { FilterModel } from '../../../components/filter/model/filter.model'; +import { handleCheckedValue } from '../../../components/filter/utils/filter-utils'; +import { SuperTypeSorter } from '../../../utils/sorters/super-type-sorter'; import { getFirstRelevantTextPart } from '../../../utils/functions'; @Injectable({ diff --git a/apps/red-ui/src/app/screens/file/service/file-action.service.ts b/apps/red-ui/src/app/screens/file/service/file-action.service.ts index 8b46665ca..bd2e063f3 100644 --- a/apps/red-ui/src/app/screens/file/service/file-action.service.ts +++ b/apps/red-ui/src/app/screens/file/service/file-action.service.ts @@ -4,7 +4,7 @@ import { AppStateService } from '../../../state/app-state.service'; import { UserService } from '../../../user/user.service'; import { FileStatus, ReanalysisControllerService, StatusControllerService } from '@redaction/red-ui-http'; import { FileStatusWrapper } from '../model/file-status.wrapper'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { isArray } from 'rxjs/internal-compatibility'; @Injectable({ diff --git a/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts b/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts index b8237d1b0..80c5a496e 100644 --- a/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts +++ b/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts @@ -6,7 +6,7 @@ import { NotificationService, NotificationType } from '../../../notification/not import { TranslateService } from '@ngx-translate/core'; import { tap } from 'rxjs/operators'; import { UserService } from '../../../user/user.service'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; @Injectable({ providedIn: 'root' diff --git a/apps/red-ui/src/app/screens/file/service/pdf-viewer-data.service.ts b/apps/red-ui/src/app/screens/file/service/pdf-viewer-data.service.ts index a97e95c0e..9d0378de4 100644 --- a/apps/red-ui/src/app/screens/file/service/pdf-viewer-data.service.ts +++ b/apps/red-ui/src/app/screens/file/service/pdf-viewer-data.service.ts @@ -10,7 +10,7 @@ import { import { FileType } from '../model/file-type'; import { FileDataModel } from '../model/file-data.model'; import { AppStateService } from '../../../state/app-state.service'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { FileStatusWrapper } from '../model/file-status.wrapper'; @Injectable({ diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.ts b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.ts index 5344a95b3..cb828511b 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.ts +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { ProjectWrapper } from '../../../state/model/project.wrapper'; -import { StatusSorter } from '../../../common/sorters/status-sorter'; +import { StatusSorter } from '../../../utils/sorters/status-sorter'; import { download } from '../../../utils/file-download-utils'; import { computerize } from '../../../utils/functions'; import { FileManagementControllerService } from '@redaction/red-ui-http'; diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.ts b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.ts index 5ee602320..ac3f1a42c 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.ts +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { DoughnutChartConfig } from '../../../components/simple-doughnut-chart/simple-doughnut-chart.component'; import { AppStateService } from '../../../state/app-state.service'; -import { FilterModel } from '../../../common/filter/model/filter.model'; +import { FilterModel } from '../../../components/filter/model/filter.model'; @Component({ selector: 'redaction-project-listing-details', diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts index d7736785c..f2ec6af0a 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-listing-screen/project-listing-screen.component.ts @@ -5,7 +5,7 @@ import { UserService } from '../../user/user.service'; import { DoughnutChartConfig } from '../../components/simple-doughnut-chart/simple-doughnut-chart.component'; import { groupBy, humanize } from '../../utils/functions'; import { DialogService } from '../../dialogs/dialog.service'; -import { FilterModel } from '../../common/filter/model/filter.model'; +import { FilterModel } from '../../components/filter/model/filter.model'; import { annotationFilterChecker, getFilteredEntities, @@ -13,20 +13,20 @@ import { projectMemberChecker, projectStatusChecker, ruleSetChecker -} from '../../common/filter/utils/filter-utils'; +} from '../../components/filter/utils/filter-utils'; import { TranslateService } from '@ngx-translate/core'; import { SortingOption, SortingService } from '../../utils/sorting.service'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { PermissionsService } from '../../utils/permissions.service'; import { ProjectWrapper } from '../../state/model/project.wrapper'; import { Subscription, timer } from 'rxjs'; import { tap } from 'rxjs/operators'; import { TranslateChartService } from '../../utils/translate-chart.service'; -import { RedactionFilterSorter } from '../../common/sorters/redaction-filter-sorter'; -import { StatusSorter } from '../../common/sorters/status-sorter'; +import { RedactionFilterSorter } from '../../utils/sorters/redaction-filter-sorter'; +import { StatusSorter } from '../../utils/sorters/status-sorter'; import { Router } from '@angular/router'; import { FormBuilder, FormGroup } from '@angular/forms'; import { debounce } from '../../utils/debounce'; -import { FilterComponent } from '../../common/filter/filter.component'; +import { FilterComponent } from '../../components/filter/filter.component'; @Component({ selector: 'redaction-project-listing-screen', diff --git a/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.ts index 52a25d881..158723fa5 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.ts @@ -3,7 +3,7 @@ import { AppStateService } from '../../../state/app-state.service'; import { UserService } from '../../../user/user.service'; import { FileManagementControllerService, ReanalysisControllerService } from '@redaction/red-ui-http'; import { DialogService } from '../../../dialogs/dialog.service'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { PermissionsService } from '../../../utils/permissions.service'; import { FileStatusWrapper } from '../../file/model/file-status.wrapper'; import { FileActionService } from '../../file/service/file-action.service'; import { Observable } from 'rxjs'; diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.ts index b8c6f55ec..ab6e1b065 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.ts @@ -4,10 +4,10 @@ import { groupBy } from '../../../utils/functions'; import { DoughnutChartConfig } from '../../../components/simple-doughnut-chart/simple-doughnut-chart.component'; import { DialogService } from '../../../dialogs/dialog.service'; import { Router } from '@angular/router'; -import { FilterModel } from '../../../common/filter/model/filter.model'; -import { PermissionsService } from '../../../common/service/permissions.service'; +import { FilterModel } from '../../../components/filter/model/filter.model'; +import { PermissionsService } from '../../../utils/permissions.service'; import { TranslateChartService } from '../../../utils/translate-chart.service'; -import { StatusSorter } from '../../../common/sorters/status-sorter'; +import { StatusSorter } from '../../../utils/sorters/status-sorter'; @Component({ selector: 'redaction-project-details', diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts index c30ec9fa2..f82de01c5 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts @@ -9,23 +9,23 @@ import { StatusOverlayService } from '../../upload-download/status-overlay.servi import { DialogService } from '../../dialogs/dialog.service'; import { TranslateService } from '@ngx-translate/core'; import { FileActionService } from '../file/service/file-action.service'; -import { FilterModel } from '../../common/filter/model/filter.model'; +import { FilterModel } from '../../components/filter/model/filter.model'; import * as moment from 'moment'; import { ProjectDetailsComponent } from './project-details/project-details.component'; import { FileStatusWrapper } from '../file/model/file-status.wrapper'; -import { annotationFilterChecker, getFilteredEntities, keyChecker, processFilters } from '../../common/filter/utils/filter-utils'; +import { annotationFilterChecker, getFilteredEntities, keyChecker, processFilters } from '../../components/filter/utils/filter-utils'; import { SortingOption, SortingService } from '../../utils/sorting.service'; -import { PermissionsService } from '../../common/service/permissions.service'; +import { PermissionsService } from '../../utils/permissions.service'; import { UserService } from '../../user/user.service'; import { FileManagementControllerService, FileStatus } from '@redaction/red-ui-http'; import { Subscription, timer } from 'rxjs'; import { tap } from 'rxjs/operators'; -import { RedactionFilterSorter } from '../../common/sorters/redaction-filter-sorter'; -import { StatusSorter } from '../../common/sorters/status-sorter'; +import { RedactionFilterSorter } from '../../utils/sorters/redaction-filter-sorter'; +import { StatusSorter } from '../../utils/sorters/status-sorter'; import { FormBuilder, FormGroup } from '@angular/forms'; import { debounce } from '../../utils/debounce'; import { convertFiles, handleFileDrop } from '../../utils/file-drop-utils'; -import { FilterComponent } from '../../common/filter/filter.component'; +import { FilterComponent } from '../../components/filter/filter.component'; @Component({ selector: 'redaction-project-overview-screen', diff --git a/apps/red-ui/src/app/upload-download/file-download.service.ts b/apps/red-ui/src/app/upload-download/file-download.service.ts index 70956f07f..6038577ad 100644 --- a/apps/red-ui/src/app/upload-download/file-download.service.ts +++ b/apps/red-ui/src/app/upload-download/file-download.service.ts @@ -9,7 +9,7 @@ import { FileStatusWrapper } from '../screens/file/model/file-status.wrapper'; import { mergeMap, tap } from 'rxjs/operators'; import { DownloadStatusWrapper } from './model/download-status.wrapper'; import { AppStateService } from '../state/app-state.service'; -import { PermissionsService } from '../common/service/permissions.service'; +import { PermissionsService } from '../utils/permissions.service'; import { KeycloakService } from 'keycloak-angular'; @Injectable({ diff --git a/apps/red-ui/src/app/common/service/annotation-actions.service.ts b/apps/red-ui/src/app/utils/annotation-actions.service.ts similarity index 96% rename from apps/red-ui/src/app/common/service/annotation-actions.service.ts rename to apps/red-ui/src/app/utils/annotation-actions.service.ts index 20a0f00a3..1abfc4eda 100644 --- a/apps/red-ui/src/app/common/service/annotation-actions.service.ts +++ b/apps/red-ui/src/app/utils/annotation-actions.service.ts @@ -1,13 +1,13 @@ import { EventEmitter, Injectable, NgZone } from '@angular/core'; import { PermissionsService } from './permissions.service'; -import { ManualAnnotationService } from '../../screens/file/service/manual-annotation.service'; -import { DialogService } from '../../dialogs/dialog.service'; -import { AnnotationWrapper } from '../../screens/file/model/annotation.wrapper'; +import { ManualAnnotationService } from '../screens/file/service/manual-annotation.service'; +import { DialogService } from '../dialogs/dialog.service'; +import { AnnotationWrapper } from '../screens/file/model/annotation.wrapper'; import { Observable } from 'rxjs'; import { TranslateService } from '@ngx-translate/core'; import { AddRedactionRequest } from '@redaction/red-ui-http'; -import { getFirstRelevantTextPart } from '../../utils/functions'; -import { AnnotationPermissions } from '../../screens/file/model/annotation.permissions'; +import { getFirstRelevantTextPart } from './functions'; +import { AnnotationPermissions } from '../screens/file/model/annotation.permissions'; @Injectable({ providedIn: 'root' diff --git a/apps/red-ui/src/app/common/service/permissions.service.ts b/apps/red-ui/src/app/utils/permissions.service.ts similarity index 96% rename from apps/red-ui/src/app/common/service/permissions.service.ts rename to apps/red-ui/src/app/utils/permissions.service.ts index e75007ba8..4bcc25cb9 100644 --- a/apps/red-ui/src/app/common/service/permissions.service.ts +++ b/apps/red-ui/src/app/utils/permissions.service.ts @@ -1,9 +1,9 @@ import { Injectable } from '@angular/core'; -import { AppStateService } from '../../state/app-state.service'; -import { UserService, UserWrapper } from '../../user/user.service'; -import { FileStatusWrapper } from '../../screens/file/model/file-status.wrapper'; +import { AppStateService } from '../state/app-state.service'; +import { UserService, UserWrapper } from '../user/user.service'; +import { FileStatusWrapper } from '../screens/file/model/file-status.wrapper'; import { User } from '@redaction/red-ui-http'; -import { ProjectWrapper } from '../../state/model/project.wrapper'; +import { ProjectWrapper } from '../state/model/project.wrapper'; @Injectable({ providedIn: 'root' diff --git a/apps/red-ui/src/app/common/sorters/redaction-filter-sorter.ts b/apps/red-ui/src/app/utils/sorters/redaction-filter-sorter.ts similarity index 100% rename from apps/red-ui/src/app/common/sorters/redaction-filter-sorter.ts rename to apps/red-ui/src/app/utils/sorters/redaction-filter-sorter.ts diff --git a/apps/red-ui/src/app/common/sorters/status-sorter.ts b/apps/red-ui/src/app/utils/sorters/status-sorter.ts similarity index 100% rename from apps/red-ui/src/app/common/sorters/status-sorter.ts rename to apps/red-ui/src/app/utils/sorters/status-sorter.ts diff --git a/apps/red-ui/src/app/common/sorters/super-type-sorter.ts b/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts similarity index 100% rename from apps/red-ui/src/app/common/sorters/super-type-sorter.ts rename to apps/red-ui/src/app/utils/sorters/super-type-sorter.ts diff --git a/apps/red-ui/src/app/common/service/user-preference.service.ts b/apps/red-ui/src/app/utils/user-preference.service.ts similarity index 100% rename from apps/red-ui/src/app/common/service/user-preference.service.ts rename to apps/red-ui/src/app/utils/user-preference.service.ts From 7073d4514ccc608237b02354f29364892fa668ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 19 Mar 2021 22:29:21 +0200 Subject: [PATCH 04/11] Quick fixes --- .../rule-set-actions/rule-set-actions.component.scss | 7 +++++++ .../app/components/rule-set-view-switch/tabs.component.ts | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.scss b/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.scss index e69de29bb..eeb99fae7 100644 --- a/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.scss +++ b/apps/red-ui/src/app/components/rule-set-actions/rule-set-actions.component.scss @@ -0,0 +1,7 @@ +.action-buttons { + display: flex; + + redaction-circle-button:not(:last-child) { + margin-right: 2px; + } +} diff --git a/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts b/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts index a62a34b73..93307b4c1 100644 --- a/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts +++ b/apps/red-ui/src/app/components/rule-set-view-switch/tabs.component.ts @@ -17,7 +17,7 @@ export class TabsComponent implements OnInit { { screen: 'rules', onlyDevMode: true, label: 'rule-editor' }, { screen: 'default-colors' }, { screen: 'watermark' }, - { screen: 'file-attributes', onlyAdmin: true } + { screen: 'file-attributes', onlyAdmin: true, onlyDevMode: true } ]; constructor( From 75e624881c7c9035a48efa9d47bcad38ea388c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 19 Mar 2021 22:38:25 +0200 Subject: [PATCH 05/11] Reorganize more files --- apps/red-ui/src/app/app.module.ts | 26 ++++++++++--------- ...ject-overview-bulk-actions.component.html} | 0 ...ject-overview-bulk-actions.component.scss} | 0 ...roject-overview-bulk-actions.component.ts} | 22 ++++++++-------- .../combo-chart/combo-chart.component.html | 0 .../combo-chart/combo-chart.component.scss | 0 .../combo-chart/combo-chart.component.ts | 0 .../combo-series-vertical.component.ts | 0 .../combo-chart/index.ts | 0 .../project-listing-empty.component.html | 8 +----- .../project-listing-empty.component.scss | 0 .../project-listing-empty.component.ts | 0 ...full-page-loading-indicator.component.html | 0 ...full-page-loading-indicator.component.scss | 0 .../full-page-loading-indicator.component.ts | 0 .../project-details.component.html | 0 .../project-details.component.scss | 2 +- .../project-details.component.ts | 16 ++++++------ .../project-listing-actions.component.html | 0 .../project-listing-actions.component.scss | 0 .../project-listing-actions.component.ts | 14 +++++----- .../project-listing-details.component.html | 0 .../project-listing-details.component.scss | 2 +- .../project-listing-details.component.ts | 6 ++--- .../add-edit-dictionary-dialog.component.html | 0 .../add-edit-dictionary-dialog.component.scss | 2 +- .../add-edit-dictionary-dialog.component.ts | 4 +-- ...-edit-file-attribute-dialog.component.html | 1 + ...-edit-file-attribute-dialog.component.scss | 0 ...dd-edit-file-attribute-dialog.component.ts | 12 +++++++++ .../add-edit-rule-set-dialog.component.html | 0 .../add-edit-rule-set-dialog.component.scss | 0 .../add-edit-rule-set-dialog.component.ts | 2 +- apps/red-ui/src/app/dialogs/dialog.service.ts | 6 ++--- .../edit-color-dialog.component.html | 0 .../edit-color-dialog.component.scss | 0 .../edit-color-dialog.component.ts | 2 +- .../project-overview-screen.component.html | 5 +++- .../project-overview-screen.component.ts | 2 +- 39 files changed, 72 insertions(+), 60 deletions(-) rename apps/red-ui/src/app/{screens/project-overview-screen/bulk-actions/bulk-actions.component.html => components/bulk-actions/project-overview-bulk-actions.component.html} (100%) rename apps/red-ui/src/app/{screens/project-overview-screen/bulk-actions/bulk-actions.component.scss => components/bulk-actions/project-overview-bulk-actions.component.scss} (100%) rename apps/red-ui/src/app/{screens/project-overview-screen/bulk-actions/bulk-actions.component.ts => components/bulk-actions/project-overview-bulk-actions.component.ts} (86%) rename apps/red-ui/src/app/{screens/admin/license-information-screen => components}/combo-chart/combo-chart.component.html (100%) rename apps/red-ui/src/app/{screens/admin/license-information-screen => components}/combo-chart/combo-chart.component.scss (100%) rename apps/red-ui/src/app/{screens/admin/license-information-screen => components}/combo-chart/combo-chart.component.ts (100%) rename apps/red-ui/src/app/{screens/admin/license-information-screen => components}/combo-chart/combo-series-vertical.component.ts (100%) rename apps/red-ui/src/app/{screens/admin/license-information-screen => components}/combo-chart/index.ts (100%) rename apps/red-ui/src/app/{screens => components}/empty-states/project-listing-empty/project-listing-empty.component.html (56%) rename apps/red-ui/src/app/{screens => components}/empty-states/project-listing-empty/project-listing-empty.component.scss (100%) rename apps/red-ui/src/app/{screens => components}/empty-states/project-listing-empty/project-listing-empty.component.ts (100%) rename apps/red-ui/src/app/{utils => components}/full-page-loading-indicator/full-page-loading-indicator.component.html (100%) rename apps/red-ui/src/app/{utils => components}/full-page-loading-indicator/full-page-loading-indicator.component.scss (100%) rename apps/red-ui/src/app/{utils => components}/full-page-loading-indicator/full-page-loading-indicator.component.ts (100%) rename apps/red-ui/src/app/{screens/project-overview-screen => components}/project-details/project-details.component.html (100%) rename apps/red-ui/src/app/{screens/project-overview-screen => components}/project-details/project-details.component.scss (94%) rename apps/red-ui/src/app/{screens/project-overview-screen => components}/project-details/project-details.component.ts (80%) rename apps/red-ui/src/app/{screens/project-listing-screen => components}/project-listing-actions/project-listing-actions.component.html (100%) rename apps/red-ui/src/app/{screens/project-listing-screen => components}/project-listing-actions/project-listing-actions.component.scss (100%) rename apps/red-ui/src/app/{screens/project-listing-screen => components}/project-listing-actions/project-listing-actions.component.ts (86%) rename apps/red-ui/src/app/{screens/project-listing-screen => components}/project-listing-details/project-listing-details.component.html (100%) rename apps/red-ui/src/app/{screens/project-listing-screen => components}/project-listing-details/project-listing-details.component.scss (92%) rename apps/red-ui/src/app/{screens/project-listing-screen => components}/project-listing-details/project-listing-details.component.ts (81%) rename apps/red-ui/src/app/{screens/admin/dictionary-listing-screen => dialogs}/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html (100%) rename apps/red-ui/src/app/{screens/admin/dictionary-listing-screen => dialogs}/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.scss (77%) rename apps/red-ui/src/app/{screens/admin/dictionary-listing-screen => dialogs}/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts (96%) create mode 100644 apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html create mode 100644 apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.scss create mode 100644 apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts rename apps/red-ui/src/app/{screens/admin/rule-sets-listing-screen => dialogs}/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.html (100%) rename apps/red-ui/src/app/{screens/admin/rule-sets-listing-screen => dialogs}/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.scss (100%) rename apps/red-ui/src/app/{screens/admin/rule-sets-listing-screen => dialogs}/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.ts (97%) rename apps/red-ui/src/app/{screens/admin/default-colors-screen => dialogs}/edit-color-dialog/edit-color-dialog.component.html (100%) rename apps/red-ui/src/app/{screens/admin/default-colors-screen => dialogs}/edit-color-dialog/edit-color-dialog.component.scss (100%) rename apps/red-ui/src/app/{screens/admin/default-colors-screen => dialogs}/edit-color-dialog/edit-color-dialog.component.ts (95%) diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index ccf7e55fe..349868a28 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -38,7 +38,7 @@ import { ServiceWorkerModule } from '@angular/service-worker'; import { environment } from '../environments/environment'; import { AuthModule } from './auth/auth.module'; import { FileUploadDownloadModule } from './upload-download/file-upload-download.module'; -import { FullPageLoadingIndicatorComponent } from './utils/full-page-loading-indicator/full-page-loading-indicator.component'; +import { FullPageLoadingIndicatorComponent } from './components/full-page-loading-indicator/full-page-loading-indicator.component'; import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; import { InitialsAvatarComponent } from './components/initials-avatar/initials-avatar.component'; import { StatusBarComponent } from './components/status-bar/status-bar.component'; @@ -59,17 +59,17 @@ import { ManualAnnotationDialogComponent } from './dialogs/manual-redaction-dial import { ToastComponent } from './components/toast/toast.component'; import { FilterComponent } from './components/filter/filter.component'; import { TableColNameComponent } from './components/table-col-name/table-col-name.component'; -import { ProjectDetailsComponent } from './screens/project-overview-screen/project-details/project-details.component'; +import { ProjectDetailsComponent } from './components/project-details/project-details.component'; import { PageIndicatorComponent } from './screens/file/page-indicator/page-indicator.component'; import { NeedsWorkBadgeComponent } from './components/needs-work-badge/needs-work-badge.component'; -import { ProjectListingEmptyComponent } from './screens/empty-states/project-listing-empty/project-listing-empty.component'; +import { ProjectListingEmptyComponent } from './components/empty-states/project-listing-empty/project-listing-empty.component'; import { AnnotationActionsComponent } from './screens/file/annotation-actions/annotation-actions.component'; -import { ProjectListingDetailsComponent } from './screens/project-listing-screen/project-listing-details/project-listing-details.component'; +import { ProjectListingDetailsComponent } from './components/project-listing-details/project-listing-details.component'; import { FileActionsComponent } from './components/file-actions/file-actions.component'; import { TypeAnnotationIconComponent } from './components/type-annotation-icon/type-annotation-icon.component'; import { TypeFilterComponent } from './components/type-filter/type-filter.component'; import { DictionaryAnnotationIconComponent } from './components/dictionary-annotation-icon/dictionary-annotation-icon.component'; -import { BulkActionsComponent } from './screens/project-overview-screen/bulk-actions/bulk-actions.component'; +import { ProjectOverviewBulkActionsComponent } from './components/bulk-actions/project-overview-bulk-actions.component'; import { HttpCacheInterceptor } from '@redaction/red-cache'; import { HiddenActionComponent } from './components/hidden-action/hidden-action.component'; import { IconButtonComponent } from './components/buttons/icon-button/icon-button.component'; @@ -78,7 +78,7 @@ import { CircleButtonComponent } from './components/buttons/circle-button/circle import { ChevronButtonComponent } from './components/buttons/chevron-button/chevron-button.component'; import { DictionaryListingScreenComponent } from './screens/admin/dictionary-listing-screen/dictionary-listing-screen.component'; import { SyncWidthDirective } from './utils/sync-width.directive'; -import { AddEditDictionaryDialogComponent } from './screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component'; +import { AddEditDictionaryDialogComponent } from './dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component'; import { DictionaryOverviewScreenComponent } from './screens/admin/dictionary-overview-screen/dictionary-overview-screen.component'; import { ColorPickerModule } from 'ngx-color-picker'; import { AceEditorModule } from 'ng2-ace-editor'; @@ -90,10 +90,10 @@ import { RulesScreenComponent } from './screens/admin/rules-screen/rules-screen. import { WatermarkScreenComponent } from './screens/admin/watermark-screen/watermark-screen.component'; import { PdfViewerScreenComponent } from './screens/pdf-viewer-screen/pdf-viewer-screen.component'; import { HtmlDebugScreenComponent } from './screens/html-debug-screen/html-debug-screen.component'; -import { ProjectListingActionsComponent } from './screens/project-listing-screen/project-listing-actions/project-listing-actions.component'; +import { ProjectListingActionsComponent } from './components/project-listing-actions/project-listing-actions.component'; import { HasScrollbarDirective } from './utils/has-scrollbar.directive'; import { RuleSetsListingScreenComponent } from './screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component'; -import { AddEditRuleSetDialogComponent } from './screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component'; +import { AddEditRuleSetDialogComponent } from './dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component'; import { RuleSetActionsComponent } from './components/rule-set-actions/rule-set-actions.component'; import { TabsComponent } from './components/rule-set-view-switch/tabs.component'; import { MatSliderModule } from '@angular/material/slider'; @@ -102,13 +102,13 @@ import { KeycloakService } from 'keycloak-angular'; import { FileDownloadBtnComponent } from './components/buttons/file-download-btn/file-download-btn.component'; import { LicenseInformationScreenComponent } from './screens/admin/license-information-screen/license-information-screen.component'; import { DefaultColorsScreenComponent } from './screens/admin/default-colors-screen/default-colors-screen.component'; -import { EditColorDialogComponent } from './screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component'; +import { EditColorDialogComponent } from './dialogs/edit-color-dialog/edit-color-dialog.component'; import { DownloadsListScreenComponent } from './screens/downloads-list-screen/downloads-list-screen.component'; import { DigitalSignatureScreenComponent } from './screens/admin/digital-signature-screen/digital-signature-screen.component'; import { ScrollingModule } from '@angular/cdk/scrolling'; import { RemoveAnnotationsDialogComponent } from './dialogs/remove-annotations-dialog/remove-annotations-dialog.component'; import { NgxChartsModule } from '@swimlane/ngx-charts'; -import { ComboChartComponent, ComboSeriesVerticalComponent } from './screens/admin/license-information-screen/combo-chart'; +import { ComboChartComponent, ComboSeriesVerticalComponent } from './components/combo-chart'; import { MatProgressBarModule } from '@angular/material/progress-bar'; import { ForceRedactionDialogComponent } from './dialogs/force-redaction-dialog/force-redaction-dialog.component'; import { AuditScreenComponent } from './screens/admin/audit-screen/audit-screen.component'; @@ -116,6 +116,7 @@ import { PaginationComponent } from './components/pagination/pagination.componen import { FileAttributesListingScreenComponent } from './screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component'; import { SearchInputComponent } from './components/search-input/search-input.component'; import { AppRoutingModule } from './app-routing.module'; +import { AddEditFileAttributeDialogComponent } from './dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component'; export function HttpLoaderFactory(httpClient: HttpClient) { return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json'); @@ -181,7 +182,7 @@ const matImports = [ TypeAnnotationIconComponent, TypeFilterComponent, DictionaryAnnotationIconComponent, - BulkActionsComponent, + ProjectOverviewBulkActionsComponent, FileActionsComponent, HiddenActionComponent, IconButtonComponent, @@ -218,7 +219,8 @@ const matImports = [ AuditScreenComponent, PaginationComponent, FileAttributesListingScreenComponent, - SearchInputComponent + SearchInputComponent, + AddEditFileAttributeDialogComponent ], imports: [ BrowserModule, diff --git a/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.html b/apps/red-ui/src/app/components/bulk-actions/project-overview-bulk-actions.component.html similarity index 100% rename from apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.html rename to apps/red-ui/src/app/components/bulk-actions/project-overview-bulk-actions.component.html diff --git a/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.scss b/apps/red-ui/src/app/components/bulk-actions/project-overview-bulk-actions.component.scss similarity index 100% rename from apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.scss rename to apps/red-ui/src/app/components/bulk-actions/project-overview-bulk-actions.component.scss diff --git a/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.ts b/apps/red-ui/src/app/components/bulk-actions/project-overview-bulk-actions.component.ts similarity index 86% rename from apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.ts rename to apps/red-ui/src/app/components/bulk-actions/project-overview-bulk-actions.component.ts index 158723fa5..9c61f246d 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/bulk-actions/bulk-actions.component.ts +++ b/apps/red-ui/src/app/components/bulk-actions/project-overview-bulk-actions.component.ts @@ -1,20 +1,20 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core'; -import { AppStateService } from '../../../state/app-state.service'; -import { UserService } from '../../../user/user.service'; +import { AppStateService } from '../../state/app-state.service'; +import { UserService } from '../../user/user.service'; import { FileManagementControllerService, ReanalysisControllerService } from '@redaction/red-ui-http'; -import { DialogService } from '../../../dialogs/dialog.service'; -import { PermissionsService } from '../../../utils/permissions.service'; -import { FileStatusWrapper } from '../../file/model/file-status.wrapper'; -import { FileActionService } from '../../file/service/file-action.service'; +import { DialogService } from '../../dialogs/dialog.service'; +import { PermissionsService } from '../../utils/permissions.service'; +import { FileStatusWrapper } from '../../screens/file/model/file-status.wrapper'; +import { FileActionService } from '../../screens/file/service/file-action.service'; import { Observable } from 'rxjs'; -import { StatusOverlayService } from '../../../upload-download/status-overlay.service'; +import { StatusOverlayService } from '../../upload-download/status-overlay.service'; @Component({ - selector: 'redaction-bulk-actions', - templateUrl: './bulk-actions.component.html', - styleUrls: ['./bulk-actions.component.scss'] + selector: 'redaction-project-overview-bulk-actions', + templateUrl: './project-overview-bulk-actions.component.html', + styleUrls: ['./project-overview-bulk-actions.component.scss'] }) -export class BulkActionsComponent { +export class ProjectOverviewBulkActionsComponent { @Input() selectedFileIds: string[]; @Output() private reload = new EventEmitter(); public loading = false; diff --git a/apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/combo-chart.component.html b/apps/red-ui/src/app/components/combo-chart/combo-chart.component.html similarity index 100% rename from apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/combo-chart.component.html rename to apps/red-ui/src/app/components/combo-chart/combo-chart.component.html diff --git a/apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/combo-chart.component.scss b/apps/red-ui/src/app/components/combo-chart/combo-chart.component.scss similarity index 100% rename from apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/combo-chart.component.scss rename to apps/red-ui/src/app/components/combo-chart/combo-chart.component.scss diff --git a/apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/combo-chart.component.ts b/apps/red-ui/src/app/components/combo-chart/combo-chart.component.ts similarity index 100% rename from apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/combo-chart.component.ts rename to apps/red-ui/src/app/components/combo-chart/combo-chart.component.ts diff --git a/apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/combo-series-vertical.component.ts b/apps/red-ui/src/app/components/combo-chart/combo-series-vertical.component.ts similarity index 100% rename from apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/combo-series-vertical.component.ts rename to apps/red-ui/src/app/components/combo-chart/combo-series-vertical.component.ts diff --git a/apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/index.ts b/apps/red-ui/src/app/components/combo-chart/index.ts similarity index 100% rename from apps/red-ui/src/app/screens/admin/license-information-screen/combo-chart/index.ts rename to apps/red-ui/src/app/components/combo-chart/index.ts diff --git a/apps/red-ui/src/app/screens/empty-states/project-listing-empty/project-listing-empty.component.html b/apps/red-ui/src/app/components/empty-states/project-listing-empty/project-listing-empty.component.html similarity index 56% rename from apps/red-ui/src/app/screens/empty-states/project-listing-empty/project-listing-empty.component.html rename to apps/red-ui/src/app/components/empty-states/project-listing-empty/project-listing-empty.component.html index a2fd1faef..a89955182 100644 --- a/apps/red-ui/src/app/screens/empty-states/project-listing-empty/project-listing-empty.component.html +++ b/apps/red-ui/src/app/components/empty-states/project-listing-empty/project-listing-empty.component.html @@ -1,12 +1,6 @@
- diff --git a/apps/red-ui/src/app/screens/empty-states/project-listing-empty/project-listing-empty.component.scss b/apps/red-ui/src/app/components/empty-states/project-listing-empty/project-listing-empty.component.scss similarity index 100% rename from apps/red-ui/src/app/screens/empty-states/project-listing-empty/project-listing-empty.component.scss rename to apps/red-ui/src/app/components/empty-states/project-listing-empty/project-listing-empty.component.scss diff --git a/apps/red-ui/src/app/screens/empty-states/project-listing-empty/project-listing-empty.component.ts b/apps/red-ui/src/app/components/empty-states/project-listing-empty/project-listing-empty.component.ts similarity index 100% rename from apps/red-ui/src/app/screens/empty-states/project-listing-empty/project-listing-empty.component.ts rename to apps/red-ui/src/app/components/empty-states/project-listing-empty/project-listing-empty.component.ts diff --git a/apps/red-ui/src/app/utils/full-page-loading-indicator/full-page-loading-indicator.component.html b/apps/red-ui/src/app/components/full-page-loading-indicator/full-page-loading-indicator.component.html similarity index 100% rename from apps/red-ui/src/app/utils/full-page-loading-indicator/full-page-loading-indicator.component.html rename to apps/red-ui/src/app/components/full-page-loading-indicator/full-page-loading-indicator.component.html diff --git a/apps/red-ui/src/app/utils/full-page-loading-indicator/full-page-loading-indicator.component.scss b/apps/red-ui/src/app/components/full-page-loading-indicator/full-page-loading-indicator.component.scss similarity index 100% rename from apps/red-ui/src/app/utils/full-page-loading-indicator/full-page-loading-indicator.component.scss rename to apps/red-ui/src/app/components/full-page-loading-indicator/full-page-loading-indicator.component.scss diff --git a/apps/red-ui/src/app/utils/full-page-loading-indicator/full-page-loading-indicator.component.ts b/apps/red-ui/src/app/components/full-page-loading-indicator/full-page-loading-indicator.component.ts similarity index 100% rename from apps/red-ui/src/app/utils/full-page-loading-indicator/full-page-loading-indicator.component.ts rename to apps/red-ui/src/app/components/full-page-loading-indicator/full-page-loading-indicator.component.ts diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.html b/apps/red-ui/src/app/components/project-details/project-details.component.html similarity index 100% rename from apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.html rename to apps/red-ui/src/app/components/project-details/project-details.component.html diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.scss b/apps/red-ui/src/app/components/project-details/project-details.component.scss similarity index 94% rename from apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.scss rename to apps/red-ui/src/app/components/project-details/project-details.component.scss index cb4f0bd9e..0ab55b1f0 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.scss +++ b/apps/red-ui/src/app/components/project-details/project-details.component.scss @@ -1,4 +1,4 @@ -@import '../../../../assets/styles/red-variables'; +@import '../../../assets/styles/red-variables'; .header-wrapper { display: flex; diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.ts b/apps/red-ui/src/app/components/project-details/project-details.component.ts similarity index 80% rename from apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.ts rename to apps/red-ui/src/app/components/project-details/project-details.component.ts index ab6e1b065..eea25d3ed 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-details/project-details.component.ts +++ b/apps/red-ui/src/app/components/project-details/project-details.component.ts @@ -1,13 +1,13 @@ import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { AppStateService } from '../../../state/app-state.service'; -import { groupBy } from '../../../utils/functions'; -import { DoughnutChartConfig } from '../../../components/simple-doughnut-chart/simple-doughnut-chart.component'; -import { DialogService } from '../../../dialogs/dialog.service'; +import { AppStateService } from '../../state/app-state.service'; +import { groupBy } from '../../utils/functions'; +import { DoughnutChartConfig } from '../simple-doughnut-chart/simple-doughnut-chart.component'; +import { DialogService } from '../../dialogs/dialog.service'; import { Router } from '@angular/router'; -import { FilterModel } from '../../../components/filter/model/filter.model'; -import { PermissionsService } from '../../../utils/permissions.service'; -import { TranslateChartService } from '../../../utils/translate-chart.service'; -import { StatusSorter } from '../../../utils/sorters/status-sorter'; +import { FilterModel } from '../filter/model/filter.model'; +import { PermissionsService } from '../../utils/permissions.service'; +import { TranslateChartService } from '../../utils/translate-chart.service'; +import { StatusSorter } from '../../utils/sorters/status-sorter'; @Component({ selector: 'redaction-project-details', diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.html b/apps/red-ui/src/app/components/project-listing-actions/project-listing-actions.component.html similarity index 100% rename from apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.html rename to apps/red-ui/src/app/components/project-listing-actions/project-listing-actions.component.html diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.scss b/apps/red-ui/src/app/components/project-listing-actions/project-listing-actions.component.scss similarity index 100% rename from apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.scss rename to apps/red-ui/src/app/components/project-listing-actions/project-listing-actions.component.scss diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.ts b/apps/red-ui/src/app/components/project-listing-actions/project-listing-actions.component.ts similarity index 86% rename from apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.ts rename to apps/red-ui/src/app/components/project-listing-actions/project-listing-actions.component.ts index cb828511b..73f8a77ca 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-actions/project-listing-actions.component.ts +++ b/apps/red-ui/src/app/components/project-listing-actions/project-listing-actions.component.ts @@ -1,12 +1,12 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { PermissionsService } from '../../../utils/permissions.service'; -import { ProjectWrapper } from '../../../state/model/project.wrapper'; -import { StatusSorter } from '../../../utils/sorters/status-sorter'; -import { download } from '../../../utils/file-download-utils'; -import { computerize } from '../../../utils/functions'; +import { PermissionsService } from '../../utils/permissions.service'; +import { ProjectWrapper } from '../../state/model/project.wrapper'; +import { StatusSorter } from '../../utils/sorters/status-sorter'; +import { download } from '../../utils/file-download-utils'; +import { computerize } from '../../utils/functions'; import { FileManagementControllerService } from '@redaction/red-ui-http'; -import { AppStateService } from '../../../state/app-state.service'; -import { DialogService } from '../../../dialogs/dialog.service'; +import { AppStateService } from '../../state/app-state.service'; +import { DialogService } from '../../dialogs/dialog.service'; @Component({ selector: 'redaction-project-listing-actions', diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.html b/apps/red-ui/src/app/components/project-listing-details/project-listing-details.component.html similarity index 100% rename from apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.html rename to apps/red-ui/src/app/components/project-listing-details/project-listing-details.component.html diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.scss b/apps/red-ui/src/app/components/project-listing-details/project-listing-details.component.scss similarity index 92% rename from apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.scss rename to apps/red-ui/src/app/components/project-listing-details/project-listing-details.component.scss index 05197f10b..91d537dd3 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.scss +++ b/apps/red-ui/src/app/components/project-listing-details/project-listing-details.component.scss @@ -1,4 +1,4 @@ -@import '../../../../assets/styles/red-variables'; +@import '../../../assets/styles/red-variables'; :host { flex: 1; diff --git a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.ts b/apps/red-ui/src/app/components/project-listing-details/project-listing-details.component.ts similarity index 81% rename from apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.ts rename to apps/red-ui/src/app/components/project-listing-details/project-listing-details.component.ts index ac3f1a42c..586e1c6af 100644 --- a/apps/red-ui/src/app/screens/project-listing-screen/project-listing-details/project-listing-details.component.ts +++ b/apps/red-ui/src/app/components/project-listing-details/project-listing-details.component.ts @@ -1,7 +1,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { DoughnutChartConfig } from '../../../components/simple-doughnut-chart/simple-doughnut-chart.component'; -import { AppStateService } from '../../../state/app-state.service'; -import { FilterModel } from '../../../components/filter/model/filter.model'; +import { DoughnutChartConfig } from '../simple-doughnut-chart/simple-doughnut-chart.component'; +import { AppStateService } from '../../state/app-state.service'; +import { FilterModel } from '../filter/model/filter.model'; @Component({ selector: 'redaction-project-listing-details', diff --git a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html b/apps/red-ui/src/app/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html similarity index 100% rename from apps/red-ui/src/app/screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html rename to apps/red-ui/src/app/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.html diff --git a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.scss b/apps/red-ui/src/app/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.scss similarity index 77% rename from apps/red-ui/src/app/screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.scss rename to apps/red-ui/src/app/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.scss index c5eefa9a6..f13f823c5 100644 --- a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.scss +++ b/apps/red-ui/src/app/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.scss @@ -1,4 +1,4 @@ -@import '../../../../../assets/styles/red-variables'; +@import '../../../assets/styles/red-variables'; .first-row { display: flex; diff --git a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts b/apps/red-ui/src/app/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts similarity index 96% rename from apps/red-ui/src/app/screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts rename to apps/red-ui/src/app/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts index 2d5d2a2e9..d5fcc1b64 100644 --- a/apps/red-ui/src/app/screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component.ts @@ -1,10 +1,10 @@ import { Component, Inject } from '@angular/core'; -import { AppStateService } from '../../../../state/app-state.service'; +import { AppStateService } from '../../state/app-state.service'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { DictionaryControllerService, TypeValue } from '@redaction/red-ui-http'; import { Observable } from 'rxjs'; -import { NotificationService, NotificationType } from '../../../../notification/notification.service'; +import { NotificationService, NotificationType } from '../../notification/notification.service'; import { TranslateService } from '@ngx-translate/core'; @Component({ diff --git a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html new file mode 100644 index 000000000..9896e1169 --- /dev/null +++ b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html @@ -0,0 +1 @@ +

add-edit-file-attribute-dialog works!

diff --git a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.scss b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts new file mode 100644 index 000000000..651fad810 --- /dev/null +++ b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts @@ -0,0 +1,12 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'redaction-add-edit-file-attribute-dialog', + templateUrl: './add-edit-file-attribute-dialog.component.html', + styleUrls: ['./add-edit-file-attribute-dialog.component.scss'] +}) +export class AddEditFileAttributeDialogComponent implements OnInit { + constructor() {} + + ngOnInit(): void {} +} diff --git a/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.html b/apps/red-ui/src/app/dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.html similarity index 100% rename from apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.html rename to apps/red-ui/src/app/dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.html diff --git a/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.scss b/apps/red-ui/src/app/dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.scss similarity index 100% rename from apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.scss rename to apps/red-ui/src/app/dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.scss diff --git a/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.ts b/apps/red-ui/src/app/dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.ts similarity index 97% rename from apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.ts rename to apps/red-ui/src/app/dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.ts index 73d38c520..1556eb426 100644 --- a/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component.ts @@ -1,5 +1,5 @@ import { Component, Inject } from '@angular/core'; -import { AppStateService } from '../../../../state/app-state.service'; +import { AppStateService } from '../../state/app-state.service'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import * as moment from 'moment'; diff --git a/apps/red-ui/src/app/dialogs/dialog.service.ts b/apps/red-ui/src/app/dialogs/dialog.service.ts index 03e7fa51b..bd10219b1 100644 --- a/apps/red-ui/src/app/dialogs/dialog.service.ts +++ b/apps/red-ui/src/app/dialogs/dialog.service.ts @@ -21,10 +21,10 @@ import { AnnotationWrapper } from '../screens/file/model/annotation.wrapper'; import { ManualAnnotationDialogComponent } from './manual-redaction-dialog/manual-annotation-dialog.component'; import { ManualAnnotationService } from '../screens/file/service/manual-annotation.service'; import { ProjectWrapper } from '../state/model/project.wrapper'; -import { AddEditDictionaryDialogComponent } from '../screens/admin/dictionary-listing-screen/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component'; -import { AddEditRuleSetDialogComponent } from '../screens/admin/rule-sets-listing-screen/add-edit-rule-set-dialog/add-edit-rule-set-dialog.component'; +import { AddEditDictionaryDialogComponent } from './add-edit-dictionary-dialog/add-edit-dictionary-dialog.component'; +import { AddEditRuleSetDialogComponent } from './add-edit-rule-set-dialog/add-edit-rule-set-dialog.component'; import { OverwriteFilesDialogComponent } from './overwrite-files-dialog/overwrite-files-dialog.component'; -import { EditColorDialogComponent } from '../screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component'; +import { EditColorDialogComponent } from './edit-color-dialog/edit-color-dialog.component'; import { RemoveAnnotationsDialogComponent } from './remove-annotations-dialog/remove-annotations-dialog.component'; import { ForceRedactionDialogComponent } from './force-redaction-dialog/force-redaction-dialog.component'; diff --git a/apps/red-ui/src/app/screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component.html b/apps/red-ui/src/app/dialogs/edit-color-dialog/edit-color-dialog.component.html similarity index 100% rename from apps/red-ui/src/app/screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component.html rename to apps/red-ui/src/app/dialogs/edit-color-dialog/edit-color-dialog.component.html diff --git a/apps/red-ui/src/app/screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component.scss b/apps/red-ui/src/app/dialogs/edit-color-dialog/edit-color-dialog.component.scss similarity index 100% rename from apps/red-ui/src/app/screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component.scss rename to apps/red-ui/src/app/dialogs/edit-color-dialog/edit-color-dialog.component.scss diff --git a/apps/red-ui/src/app/screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component.ts b/apps/red-ui/src/app/dialogs/edit-color-dialog/edit-color-dialog.component.ts similarity index 95% rename from apps/red-ui/src/app/screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component.ts rename to apps/red-ui/src/app/dialogs/edit-color-dialog/edit-color-dialog.component.ts index d7290ff44..00c52b071 100644 --- a/apps/red-ui/src/app/screens/admin/default-colors-screen/edit-color-dialog/edit-color-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/edit-color-dialog/edit-color-dialog.component.ts @@ -1,7 +1,7 @@ import { Component, Inject } from '@angular/core'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { Colors, DictionaryControllerService } from '@redaction/red-ui-http'; -import { NotificationService, NotificationType } from '../../../../notification/notification.service'; +import { NotificationService, NotificationType } from '../../notification/notification.service'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html index 8193c9626..3a1886295 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html @@ -112,7 +112,10 @@ {{ 'project-overview.table-header.title' | translate: { length: displayedFiles.length || 0 } }} - +
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts index f82de01c5..426be5039 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.ts @@ -11,7 +11,7 @@ import { TranslateService } from '@ngx-translate/core'; import { FileActionService } from '../file/service/file-action.service'; import { FilterModel } from '../../components/filter/model/filter.model'; import * as moment from 'moment'; -import { ProjectDetailsComponent } from './project-details/project-details.component'; +import { ProjectDetailsComponent } from '../../components/project-details/project-details.component'; import { FileStatusWrapper } from '../file/model/file-status.wrapper'; import { annotationFilterChecker, getFilteredEntities, keyChecker, processFilters } from '../../components/filter/utils/filter-utils'; import { SortingOption, SortingService } from '../../utils/sorting.service'; From 9c38dd83cbb2f815f07f30a14dc6dd9895bda50d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Fri, 19 Mar 2021 23:56:37 +0200 Subject: [PATCH 06/11] Add file attribute --- ...-edit-file-attribute-dialog.component.html | 26 ++++++++- ...dd-edit-file-attribute-dialog.component.ts | 55 +++++++++++++++++-- apps/red-ui/src/app/dialogs/dialog.service.ts | 18 ++++++ ...e-attributes-listing-screen.component.html | 2 + ...ile-attributes-listing-screen.component.ts | 41 +++++++------- apps/red-ui/src/assets/i18n/en.json | 12 ++++ apps/red-ui/src/assets/styles/red-input.scss | 2 +- apps/red-ui/src/assets/styles/red-toggle.scss | 29 +++++++++- 8 files changed, 158 insertions(+), 27 deletions(-) diff --git a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html index 9896e1169..e9c1a3078 100644 --- a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html +++ b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html @@ -1 +1,25 @@ -

add-edit-file-attribute-dialog works!

+
+
+ {{ (fileAttribute ? 'add-edit-file-attribute.title.edit' : 'add-edit-file-attribute.title.new') | translate: { name: fileAttribute?.name } }} +
+ +
+
+
+ + +
+ +
+ {{ 'add-edit-file-attribute.form.read-only' | translate }} +
+
+
+ +
+
+ + +
diff --git a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts index 651fad810..c84ef475a 100644 --- a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts @@ -1,12 +1,59 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, Inject } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AppStateService } from '../../state/app-state.service'; +import { FileAttribute, FileAttributesControllerService } from '@redaction/red-ui-http'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @Component({ selector: 'redaction-add-edit-file-attribute-dialog', templateUrl: './add-edit-file-attribute-dialog.component.html', styleUrls: ['./add-edit-file-attribute-dialog.component.scss'] }) -export class AddEditFileAttributeDialogComponent implements OnInit { - constructor() {} +export class AddEditFileAttributeDialogComponent { + public fileAttributeForm: FormGroup; + public fileAttribute: FileAttribute; + public ruleSetId: string; - ngOnInit(): void {} + constructor( + private readonly _appStateService: AppStateService, + private readonly _formBuilder: FormBuilder, + private readonly _fileAttributesService: FileAttributesControllerService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { fileAttribute: FileAttribute; ruleSetId: string } + ) { + this.fileAttribute = data.fileAttribute; + this.ruleSetId = data.ruleSetId; + + this.fileAttributeForm = this._formBuilder.group({ + name: [this.fileAttribute?.name, Validators.required], + readonly: [this.fileAttribute ? !this.fileAttribute.editable : false], + visible: [this.fileAttribute?.visible] + }); + } + + public get changed(): boolean { + if (!this.fileAttribute) return true; + + for (const key of Object.keys(this.fileAttributeForm.getRawValue())) { + if (key === 'readonly') { + if (this.fileAttribute.editable === this.fileAttributeForm.get(key).value) { + return true; + } + } else if (this.fileAttribute[key] !== this.fileAttributeForm.get(key).value) { + return true; + } + } + + return false; + } + + async saveFileAttribute() { + const fileAttribute = { + id: this.fileAttribute?.id, + editable: !this.fileAttributeForm.get('readonly').value, + ...this.fileAttributeForm.getRawValue() + }; + await this._fileAttributesService.setFileAttributesConfiguration({ fileAttributes: [fileAttribute] }, this.ruleSetId).toPromise(); + this.dialogRef.close(fileAttribute); + } } diff --git a/apps/red-ui/src/app/dialogs/dialog.service.ts b/apps/red-ui/src/app/dialogs/dialog.service.ts index bd10219b1..09e75dfc9 100644 --- a/apps/red-ui/src/app/dialogs/dialog.service.ts +++ b/apps/red-ui/src/app/dialogs/dialog.service.ts @@ -3,6 +3,7 @@ import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { Colors, DictionaryControllerService, + FileAttribute, FileManagementControllerService, FileStatus, ManualRedactionControllerService, @@ -27,6 +28,7 @@ import { OverwriteFilesDialogComponent } from './overwrite-files-dialog/overwrit import { EditColorDialogComponent } from './edit-color-dialog/edit-color-dialog.component'; import { RemoveAnnotationsDialogComponent } from './remove-annotations-dialog/remove-annotations-dialog.component'; import { ForceRedactionDialogComponent } from './force-redaction-dialog/force-redaction-dialog.component'; +import { AddEditFileAttributeDialogComponent } from './add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component'; const dialogConfig = { width: '662px', @@ -336,6 +338,22 @@ export class DialogService { return ref; } + public openAddEditFileAttributeDialog(fileAttribute: FileAttribute, ruleSetId: string, cb?: Function): MatDialogRef { + const ref = this._dialog.open(AddEditFileAttributeDialogComponent, { + ...dialogConfig, + data: { fileAttribute, ruleSetId }, + autoFocus: true + }); + + ref.afterClosed().subscribe((result) => { + if (result && cb) { + cb(result); + } + }); + + return ref; + } + openRemoveAnnotationModal($event: MouseEvent, annotation: AnnotationWrapper, callback: () => void) { $event?.stopPropagation(); diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html index b56c31b1b..f3fa5afba 100644 --- a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html @@ -125,3 +125,5 @@
+ + diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts index e3eecb7c6..7482a8be9 100644 --- a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts @@ -6,6 +6,7 @@ import { AppStateService } from '../../../state/app-state.service'; import { ActivatedRoute } from '@angular/router'; import { debounce } from '../../../utils/debounce'; import { SortingOption, SortingService } from '../../../utils/sorting.service'; +import { DialogService } from '../../../dialogs/dialog.service'; @Component({ selector: 'redaction-file-attributes-listing-screen', @@ -17,6 +18,7 @@ export class FileAttributesListingScreenComponent implements OnInit { public attributes: FileAttribute[] = []; public displayedAttributes: FileAttribute[] = []; public selectedFileAttributeIds: string[] = []; + public viewReady = false; constructor( public readonly permissionsService: PermissionsService, @@ -24,7 +26,8 @@ export class FileAttributesListingScreenComponent implements OnInit { private readonly _formBuilder: FormBuilder, private readonly _fileAttributesService: FileAttributesControllerService, private readonly _appStateService: AppStateService, - private readonly _activatedRoute: ActivatedRoute + private readonly _activatedRoute: ActivatedRoute, + private readonly _dialogService: DialogService ) { this._appStateService.activateRuleSet(_activatedRoute.snapshot.params.ruleSetId); @@ -36,27 +39,19 @@ export class FileAttributesListingScreenComponent implements OnInit { } async ngOnInit() { + await this._loadData(); + } + + private async _loadData() { + this.viewReady = false; try { const response = await this._fileAttributesService.getFileAttributesConfiguration(this._appStateService.activeRuleSetId).toPromise(); this.attributes = response?.fileAttributes || []; - } catch (e) { - // TODO: Remove - this.attributes = [ - { - name: 'Atribut', - editable: true, - id: '1', - visible: true - }, - { - name: 'Alt atribut', - editable: false, - id: '2', - visible: true - } - ]; + } finally { + this.displayedAttributes = [...this.attributes]; + this._executeSearch(); + this.viewReady = true; } - this.displayedAttributes = [...this.attributes]; } public get noData(): boolean { @@ -72,12 +67,18 @@ export class FileAttributesListingScreenComponent implements OnInit { } @debounce(200) - private _executeSearch(value: { query: string }) { + private _executeSearch(value?: { query: string }) { + if (!value) { + value = { query: this.searchForm.get('query').value }; + } this.displayedAttributes = this.attributes.filter((attribute) => attribute.name.toLowerCase().includes(value.query.toLowerCase())); } - public openAddEditAttributeDialog($event: MouseEvent, attribute?: FileAttribute) { + public openAddEditAttributeDialog($event: MouseEvent, fileAttribute?: FileAttribute) { $event.stopPropagation(); + this._dialogService.openAddEditFileAttributeDialog(fileAttribute, this._appStateService.activeRuleSetId, async () => { + await this._loadData(); + }); } public toggleAttributeSelected($event: MouseEvent, attribute: FileAttribute) { diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 16d75e479..db7e1ef41 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -583,6 +583,18 @@ "question": "Do you wish to proceed?" } }, + "add-edit-file-attribute": { + "title": { + "edit": "Edit {{name}} File Attribute", + "new": "Add New File Attribute" + }, + "form": { + "name": "Attribute Name", + "name-placeholder": "Enter Name", + "read-only": "Make Read-Only" + }, + "save": "Save Attribute" + }, "add-edit-dictionary": { "title": { "edit": "Edit {{name}} Dictionary", diff --git a/apps/red-ui/src/assets/styles/red-input.scss b/apps/red-ui/src/assets/styles/red-input.scss index f01563375..8c82292de 100644 --- a/apps/red-ui/src/assets/styles/red-input.scss +++ b/apps/red-ui/src/assets/styles/red-input.scss @@ -146,7 +146,7 @@ form { } } - label { + &:not(.ignore-label-styles) label { opacity: 0.7; font-size: 11px; letter-spacing: 0; diff --git a/apps/red-ui/src/assets/styles/red-toggle.scss b/apps/red-ui/src/assets/styles/red-toggle.scss index 812e1d7df..65875cbc2 100644 --- a/apps/red-ui/src/assets/styles/red-toggle.scss +++ b/apps/red-ui/src/assets/styles/red-toggle.scss @@ -1,8 +1,11 @@ -mat-slide-toggle { +@import 'red-variables'; + +.mat-slide-toggle { .mat-slide-toggle-bar { height: 16px !important; width: 30px !important; border-radius: 16px !important; + background-color: $grey-4; } .mat-slide-toggle-thumb-container { @@ -15,5 +18,29 @@ mat-slide-toggle { .mat-slide-toggle-thumb { height: 12px !important; width: 12px !important; + box-shadow: none; + background-color: $grey-2; + } + + .mat-ripple { + display: none; + } + + .mat-slide-toggle-content { + font-family: Inter, sans-serif; + } + + &.mat-primary.mat-checked { + .mat-slide-toggle-bar { + background-color: $primary; + } + + .mat-slide-toggle-thumb { + background-color: $white; + } + + .mat-slide-toggle-thumb-container { + transform: translate3d(14px, 0, 0); + } } } From f0056fee56a4793f2ee1aba07c37d39275765704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Tue, 23 Mar 2021 01:47:31 +0200 Subject: [PATCH 07/11] Delete file attribute --- apps/red-ui/src/app/app.module.ts | 4 +- ...elete-file-attribute-dialog.component.html | 21 ++++++++++ ...elete-file-attribute-dialog.component.scss | 13 +++++++ ...-delete-file-attribute-dialog.component.ts | 38 +++++++++++++++++++ apps/red-ui/src/app/dialogs/dialog.service.ts | 21 ++++++++++ ...e-attributes-listing-screen.component.html | 15 ++++---- ...e-attributes-listing-screen.component.scss | 4 +- ...ile-attributes-listing-screen.component.ts | 7 ++++ apps/red-ui/src/assets/i18n/en.json | 10 ++++- 9 files changed, 121 insertions(+), 12 deletions(-) create mode 100644 apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.html create mode 100644 apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.scss create mode 100644 apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.ts diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 349868a28..90587e9f3 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -117,6 +117,7 @@ import { FileAttributesListingScreenComponent } from './screens/admin/file-attri import { SearchInputComponent } from './components/search-input/search-input.component'; import { AppRoutingModule } from './app-routing.module'; import { AddEditFileAttributeDialogComponent } from './dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component'; +import { ConfirmDeleteFileAttributeDialogComponent } from './dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component'; export function HttpLoaderFactory(httpClient: HttpClient) { return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json'); @@ -220,7 +221,8 @@ const matImports = [ PaginationComponent, FileAttributesListingScreenComponent, SearchInputComponent, - AddEditFileAttributeDialogComponent + AddEditFileAttributeDialogComponent, + ConfirmDeleteFileAttributeDialogComponent ], imports: [ BrowserModule, diff --git a/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.html b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.html new file mode 100644 index 000000000..2b44d76b5 --- /dev/null +++ b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.html @@ -0,0 +1,21 @@ +
+
+ {{ 'confirm-delete-file-attribute.title' | translate: { name: fileAttribute.name } }} +
+ +
+
+ + + {{ 'confirm-delete-file-attribute.checkbox-' + (idx + 1) | translate }} + +
+ +
+ +
+
+ +
diff --git a/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.scss b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.scss new file mode 100644 index 000000000..7ae5f7b64 --- /dev/null +++ b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.scss @@ -0,0 +1,13 @@ +@import '../../../assets/styles/red-variables'; + +.dialog-header { + color: $primary; +} + +.heading { + margin-bottom: 24px; +} + +mat-checkbox:not(:last-of-type) { + margin-bottom: 6px; +} diff --git a/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.ts b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.ts new file mode 100644 index 000000000..62b3509a0 --- /dev/null +++ b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.ts @@ -0,0 +1,38 @@ +import { Component, Inject } from '@angular/core'; +import { AppStateService } from '../../state/app-state.service'; +import { FileAttribute, FileAttributesControllerService } from '@redaction/red-ui-http'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; + +@Component({ + selector: 'redaction-confirm-delete-file-attribute-dialog', + templateUrl: './confirm-delete-file-attribute-dialog.component.html', + styleUrls: ['./confirm-delete-file-attribute-dialog.component.scss'] +}) +export class ConfirmDeleteFileAttributeDialogComponent { + public fileAttribute: FileAttribute; + public ruleSetId: string; + public checkboxes = [{ value: false }, { value: false }]; + + constructor( + private readonly _appStateService: AppStateService, + private readonly _fileAttributesService: FileAttributesControllerService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: { fileAttribute: FileAttribute; ruleSetId: string } + ) { + this.fileAttribute = data.fileAttribute; + this.ruleSetId = data.ruleSetId; + } + + public get valid() { + return this.checkboxes[0].value && this.checkboxes[1].value; + } + + async deleteFileAttribute() { + console.log('deleting...'); + this.dialogRef.close(true); + } + + public cancel() { + this.dialogRef.close(); + } +} diff --git a/apps/red-ui/src/app/dialogs/dialog.service.ts b/apps/red-ui/src/app/dialogs/dialog.service.ts index 09e75dfc9..263d5215c 100644 --- a/apps/red-ui/src/app/dialogs/dialog.service.ts +++ b/apps/red-ui/src/app/dialogs/dialog.service.ts @@ -29,6 +29,7 @@ import { EditColorDialogComponent } from './edit-color-dialog/edit-color-dialog. import { RemoveAnnotationsDialogComponent } from './remove-annotations-dialog/remove-annotations-dialog.component'; import { ForceRedactionDialogComponent } from './force-redaction-dialog/force-redaction-dialog.component'; import { AddEditFileAttributeDialogComponent } from './add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component'; +import { ConfirmDeleteFileAttributeDialogComponent } from './confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component'; const dialogConfig = { width: '662px', @@ -354,6 +355,26 @@ export class DialogService { return ref; } + public openConfirmDeleteFileAttributeDialog( + fileAttribute: FileAttribute, + ruleSetId: string, + cb?: Function + ): MatDialogRef { + const ref = this._dialog.open(ConfirmDeleteFileAttributeDialogComponent, { + ...dialogConfig, + data: { fileAttribute, ruleSetId }, + autoFocus: true + }); + + ref.afterClosed().subscribe((result) => { + if (result && cb) { + cb(result); + } + }); + + return ref; + } + openRemoveAnnotationModal($event: MouseEvent, annotation: AnnotationWrapper, callback: () => void) { $event?.stopPropagation(); diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html index f3fa5afba..633bf9e2a 100644 --- a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html @@ -61,9 +61,9 @@ column="name" > - + - +
@@ -83,11 +83,10 @@
{{ attribute.name }}
-
- - - - -
+ + + +
div:not(.scrollbar-placeholder) { @@ -47,7 +47,7 @@ redaction-table-col-name::ng-deep { &.has-scrollbar:hover { ::ng-deep.cdk-virtual-scroll-content-wrapper { - grid-template-columns: auto 1fr 1fr 1fr 1fr; + grid-template-columns: auto 1fr 1fr 3fr; } } } diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts index 7482a8be9..15cf578f9 100644 --- a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts @@ -81,6 +81,13 @@ export class FileAttributesListingScreenComponent implements OnInit { }); } + public openConfirmDeleteAttributeDialog($event: MouseEvent, fileAttribute?: FileAttribute) { + $event.stopPropagation(); + this._dialogService.openConfirmDeleteFileAttributeDialog(fileAttribute, this._appStateService.activeRuleSetId, async () => { + await this._loadData(); + }); + } + public toggleAttributeSelected($event: MouseEvent, attribute: FileAttribute) { $event.stopPropagation(); const idx = this.selectedFileAttributeIds.indexOf(attribute.id); diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index db7e1ef41..c0b0643b4 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -715,7 +715,7 @@ "table-col-names": { "name": "Name", "created-by": "Created by", - "permissions": "Permissions" + "read-only": "Read-Only" }, "no-data": "No file attributes.", "read-only": "Read-only", @@ -724,6 +724,14 @@ "delete": "Delete attribute" } }, + "confirm-delete-file-attribute": { + "title": "Delete {{name}}", + "warning": "Warning: this cannot be undone!", + "delete": "Delete Attribute", + "cancel": "Keep Attribute", + "checkbox-1": "All documents it is used on will be impacted", + "checkbox-2": "All inputted details on the documents will be lost" + }, "user-listing": { "table-header": { "title": "{{length}} users" From 9659cbe28924055e33c5da97dcb1a598c254ea6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Tue, 23 Mar 2021 23:45:43 +0200 Subject: [PATCH 08/11] Document info --- apps/red-ui/src/app/app.module.ts | 6 +- .../document-info.component.html | 39 ++++ .../document-info.component.scss | 22 ++ .../document-info/document-info.component.ts | 21 ++ .../file-actions/file-actions.component.html | 9 + .../file-actions/file-actions.component.ts | 5 + ...-edit-file-attribute-dialog.component.html | 4 +- ...dd-edit-file-attribute-dialog.component.ts | 14 +- ...elete-file-attribute-dialog.component.html | 2 +- ...-delete-file-attribute-dialog.component.ts | 6 +- apps/red-ui/src/app/dialogs/dialog.service.ts | 27 ++- .../document-info-dialog.component.html | 24 ++ .../document-info-dialog.component.scss | 0 .../document-info-dialog.component.ts | 36 +++ apps/red-ui/src/app/icons/icons.module.ts | 3 +- ...e-attributes-listing-screen.component.html | 4 +- ...ile-attributes-listing-screen.component.ts | 17 +- .../rule-sets-listing-screen.component.ts | 2 +- .../file-preview-screen.component.html | 205 +++++++++--------- .../file-preview-screen.component.scss | 23 +- .../file-preview-screen.component.ts | 29 ++- apps/red-ui/src/assets/i18n/en.json | 18 ++ .../src/assets/icons/general/status-info.svg | 27 +++ .../src/assets/styles/red-components.scss | 2 +- 24 files changed, 402 insertions(+), 143 deletions(-) create mode 100644 apps/red-ui/src/app/components/document-info/document-info.component.html create mode 100644 apps/red-ui/src/app/components/document-info/document-info.component.scss create mode 100644 apps/red-ui/src/app/components/document-info/document-info.component.ts create mode 100644 apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.html create mode 100644 apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.scss create mode 100644 apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.ts create mode 100644 apps/red-ui/src/assets/icons/general/status-info.svg diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 90587e9f3..afdd131e0 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -118,6 +118,8 @@ import { SearchInputComponent } from './components/search-input/search-input.com import { AppRoutingModule } from './app-routing.module'; import { AddEditFileAttributeDialogComponent } from './dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component'; import { ConfirmDeleteFileAttributeDialogComponent } from './dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component'; +import { DocumentInfoDialogComponent } from './dialogs/document-info-dialog/document-info-dialog.component'; +import { DocumentInfoComponent } from './components/document-info/document-info.component'; export function HttpLoaderFactory(httpClient: HttpClient) { return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json'); @@ -222,7 +224,9 @@ const matImports = [ FileAttributesListingScreenComponent, SearchInputComponent, AddEditFileAttributeDialogComponent, - ConfirmDeleteFileAttributeDialogComponent + ConfirmDeleteFileAttributeDialogComponent, + DocumentInfoDialogComponent, + DocumentInfoComponent ], imports: [ BrowserModule, diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.html b/apps/red-ui/src/app/components/document-info/document-info.component.html new file mode 100644 index 000000000..ed28e1bde --- /dev/null +++ b/apps/red-ui/src/app/components/document-info/document-info.component.html @@ -0,0 +1,39 @@ +
+
+ + +
+
+ +
+ Attributes go here +
+ +
+
+ + {{ 'file-preview.tabs.document-info.details.project' | translate: { projectName: project.name } }} +
+
+ + {{ 'file-preview.tabs.document-info.details.pages' | translate: { pages: file.numberOfPages } }} +
+
+ + {{ 'file-preview.tabs.document-info.details.created-on' | translate: { date: file.added | date: 'mediumDate' } }} +
+
+ + {{ 'file-preview.tabs.document-info.details.due' | translate: { date: project.project.dueDate | date: 'mediumDate' } }} +
+
diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.scss b/apps/red-ui/src/app/components/document-info/document-info.component.scss new file mode 100644 index 000000000..87eaf014a --- /dev/null +++ b/apps/red-ui/src/app/components/document-info/document-info.component.scss @@ -0,0 +1,22 @@ +@import '../../../assets/styles/red-variables'; + +.right-title > div { + display: flex; + + > redaction-circle-button:not(:last-child) { + margin-right: 2px; + } +} + +.section { + padding: 25px; + flex-direction: column; + + > div { + justify-content: flex-start; + } + + &:not(:last-child) { + border-bottom: 1px solid $separator; + } +} diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.ts b/apps/red-ui/src/app/components/document-info/document-info.component.ts new file mode 100644 index 000000000..d17f725ce --- /dev/null +++ b/apps/red-ui/src/app/components/document-info/document-info.component.ts @@ -0,0 +1,21 @@ +import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; +import { FileStatus } from '@redaction/red-ui-http'; +import { AppStateService } from '../../state/app-state.service'; + +@Component({ + selector: 'redaction-document-info', + templateUrl: './document-info.component.html', + styleUrls: ['./document-info.component.scss'] +}) +export class DocumentInfoComponent implements OnInit { + @Input() file: FileStatus; + @Output() closeDocumentInfoView = new EventEmitter(); + + constructor(private _appStateService: AppStateService) {} + + ngOnInit(): void {} + + public get project() { + return this._appStateService.getProjectById(this.file.projectId); + } +} diff --git a/apps/red-ui/src/app/components/file-actions/file-actions.component.html b/apps/red-ui/src/app/components/file-actions/file-actions.component.html index fba698805..72b362611 100644 --- a/apps/red-ui/src/app/components/file-actions/file-actions.component.html +++ b/apps/red-ui/src/app/components/file-actions/file-actions.component.html @@ -49,6 +49,15 @@ > + + (); actionMenuOpen: boolean; @@ -40,6 +41,10 @@ export class FileActionsComponent implements OnInit { } } + public toggleViewDocumentInfo() { + this.actionPerformed.emit('view-document-info'); + } + public get tooltipPosition() { return this.screen === 'file-preview' ? 'below' : 'above'; } diff --git a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html index e9c1a3078..1f407e450 100644 --- a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html +++ b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html @@ -1,13 +1,13 @@
- {{ (fileAttribute ? 'add-edit-file-attribute.title.edit' : 'add-edit-file-attribute.title.new') | translate: { name: fileAttribute?.name } }} + {{ (fileAttribute ? 'add-edit-file-attribute.title.edit' : 'add-edit-file-attribute.title.new') | translate: { name: fileAttribute?.label } }}
- +
diff --git a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts index c84ef475a..d43eb3ccc 100644 --- a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts @@ -1,8 +1,9 @@ import { Component, Inject } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { AppStateService } from '../../state/app-state.service'; -import { FileAttribute, FileAttributesControllerService } from '@redaction/red-ui-http'; +import { FileAttributeConfig, FileAttributesControllerService } from '@redaction/red-ui-http'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { computerize } from '../../utils/functions'; @Component({ selector: 'redaction-add-edit-file-attribute-dialog', @@ -11,7 +12,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; }) export class AddEditFileAttributeDialogComponent { public fileAttributeForm: FormGroup; - public fileAttribute: FileAttribute; + public fileAttribute: FileAttributeConfig; public ruleSetId: string; constructor( @@ -19,13 +20,13 @@ export class AddEditFileAttributeDialogComponent { private readonly _formBuilder: FormBuilder, private readonly _fileAttributesService: FileAttributesControllerService, public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: { fileAttribute: FileAttribute; ruleSetId: string } + @Inject(MAT_DIALOG_DATA) public data: { fileAttribute: FileAttributeConfig; ruleSetId: string } ) { this.fileAttribute = data.fileAttribute; this.ruleSetId = data.ruleSetId; this.fileAttributeForm = this._formBuilder.group({ - name: [this.fileAttribute?.name, Validators.required], + label: [this.fileAttribute?.label, Validators.required], readonly: [this.fileAttribute ? !this.fileAttribute.editable : false], visible: [this.fileAttribute?.visible] }); @@ -48,12 +49,13 @@ export class AddEditFileAttributeDialogComponent { } async saveFileAttribute() { - const fileAttribute = { + const fileAttribute: FileAttributeConfig = { id: this.fileAttribute?.id, editable: !this.fileAttributeForm.get('readonly').value, + csvColumnHeader: this.fileAttribute?.csvColumnHeader || computerize(this.fileAttributeForm.get('label').value), ...this.fileAttributeForm.getRawValue() }; - await this._fileAttributesService.setFileAttributesConfiguration({ fileAttributes: [fileAttribute] }, this.ruleSetId).toPromise(); + await this._fileAttributesService.setFileAttributesConfiguration(fileAttribute, this.ruleSetId).toPromise(); this.dialogRef.close(fileAttribute); } } diff --git a/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.html b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.html index 2b44d76b5..a9f8b28d8 100644 --- a/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.html +++ b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.html @@ -1,6 +1,6 @@
- {{ 'confirm-delete-file-attribute.title' | translate: { name: fileAttribute.name } }} + {{ 'confirm-delete-file-attribute.title' | translate: { name: fileAttribute.label } }}
diff --git a/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.ts b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.ts index 62b3509a0..041d25ea5 100644 --- a/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.ts +++ b/apps/red-ui/src/app/dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component.ts @@ -1,6 +1,6 @@ import { Component, Inject } from '@angular/core'; import { AppStateService } from '../../state/app-state.service'; -import { FileAttribute, FileAttributesControllerService } from '@redaction/red-ui-http'; +import { FileAttributeConfig, FileAttributesControllerService } from '@redaction/red-ui-http'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; @Component({ @@ -9,7 +9,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; styleUrls: ['./confirm-delete-file-attribute-dialog.component.scss'] }) export class ConfirmDeleteFileAttributeDialogComponent { - public fileAttribute: FileAttribute; + public fileAttribute: FileAttributeConfig; public ruleSetId: string; public checkboxes = [{ value: false }, { value: false }]; @@ -17,7 +17,7 @@ export class ConfirmDeleteFileAttributeDialogComponent { private readonly _appStateService: AppStateService, private readonly _fileAttributesService: FileAttributesControllerService, public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: { fileAttribute: FileAttribute; ruleSetId: string } + @Inject(MAT_DIALOG_DATA) public data: { fileAttribute: FileAttributeConfig; ruleSetId: string } ) { this.fileAttribute = data.fileAttribute; this.ruleSetId = data.ruleSetId; diff --git a/apps/red-ui/src/app/dialogs/dialog.service.ts b/apps/red-ui/src/app/dialogs/dialog.service.ts index 263d5215c..d35edbca1 100644 --- a/apps/red-ui/src/app/dialogs/dialog.service.ts +++ b/apps/red-ui/src/app/dialogs/dialog.service.ts @@ -3,7 +3,7 @@ import { MatDialog, MatDialogRef } from '@angular/material/dialog'; import { Colors, DictionaryControllerService, - FileAttribute, + FileAttributeConfig, FileManagementControllerService, FileStatus, ManualRedactionControllerService, @@ -30,6 +30,7 @@ import { RemoveAnnotationsDialogComponent } from './remove-annotations-dialog/re import { ForceRedactionDialogComponent } from './force-redaction-dialog/force-redaction-dialog.component'; import { AddEditFileAttributeDialogComponent } from './add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component'; import { ConfirmDeleteFileAttributeDialogComponent } from './confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component'; +import { DocumentInfoDialogComponent } from './document-info-dialog/document-info-dialog.component'; const dialogConfig = { width: '662px', @@ -339,7 +340,11 @@ export class DialogService { return ref; } - public openAddEditFileAttributeDialog(fileAttribute: FileAttribute, ruleSetId: string, cb?: Function): MatDialogRef { + public openAddEditFileAttributeDialog( + fileAttribute: FileAttributeConfig, + ruleSetId: string, + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(AddEditFileAttributeDialogComponent, { ...dialogConfig, data: { fileAttribute, ruleSetId }, @@ -356,7 +361,7 @@ export class DialogService { } public openConfirmDeleteFileAttributeDialog( - fileAttribute: FileAttribute, + fileAttribute: FileAttributeConfig, ruleSetId: string, cb?: Function ): MatDialogRef { @@ -375,6 +380,22 @@ export class DialogService { return ref; } + public openDocumentInfoDialog(file: FileStatus, cb?: Function): MatDialogRef { + const ref = this._dialog.open(DocumentInfoDialogComponent, { + ...dialogConfig, + data: file, + autoFocus: true + }); + + ref.afterClosed().subscribe((result) => { + if (result && cb) { + cb(result); + } + }); + + return ref; + } + openRemoveAnnotationModal($event: MouseEvent, annotation: AnnotationWrapper, callback: () => void) { $event?.stopPropagation(); diff --git a/apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.html b/apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.html new file mode 100644 index 000000000..631db7764 --- /dev/null +++ b/apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.html @@ -0,0 +1,24 @@ +
+
+ + +
+ {{ file.filename }} + + + + + + + + +
+
+ +
+ + + +
diff --git a/apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.scss b/apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.ts b/apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.ts new file mode 100644 index 000000000..1e8ea59ec --- /dev/null +++ b/apps/red-ui/src/app/dialogs/document-info-dialog/document-info-dialog.component.ts @@ -0,0 +1,36 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup } from '@angular/forms'; +import { FileAttributesControllerService, FileStatus } from '@redaction/red-ui-http'; +import { AppStateService } from '../../state/app-state.service'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; + +@Component({ + selector: 'redaction-document-info-dialog', + templateUrl: './document-info-dialog.component.html', + styleUrls: ['./document-info-dialog.component.scss'] +}) +export class DocumentInfoDialogComponent implements OnInit { + public documentInfoForm: FormGroup; + public file: FileStatus; + + constructor( + private readonly _appStateService: AppStateService, + private readonly _formBuilder: FormBuilder, + private readonly _fileAttributesService: FileAttributesControllerService, + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: FileStatus + ) { + this.file = this.data; + console.log(this.data); + + this.documentInfoForm = this._formBuilder.group({ + // name: [this.fileAttribute?.name, Validators.required], + // readonly: [this.fileAttribute ? !this.fileAttribute.editable : false], + // visible: [this.fileAttribute?.visible] + }); + } + + ngOnInit(): void {} + + public saveDocumentInfo() {} +} diff --git a/apps/red-ui/src/app/icons/icons.module.ts b/apps/red-ui/src/app/icons/icons.module.ts index a4f14eae0..164c8c62a 100644 --- a/apps/red-ui/src/app/icons/icons.module.ts +++ b/apps/red-ui/src/app/icons/icons.module.ts @@ -64,8 +64,9 @@ export class IconsModule { 'sort-asc', 'sort-desc', 'status', - 'status-expand', 'status-collapse', + 'status-expand', + 'status-info', 'template', 'thumb-down', 'thumb-up', diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html index 633bf9e2a..b4feb342a 100644 --- a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.html @@ -50,7 +50,7 @@
-
+
- {{ attribute.name }} + {{ attribute.label }}
diff --git a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts index 15cf578f9..19cbd4db5 100644 --- a/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/file-attributes-listing-screen/file-attributes-listing-screen.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; import { PermissionsService } from '../../../utils/permissions.service'; import { FormBuilder, FormGroup } from '@angular/forms'; -import { FileAttribute, FileAttributesControllerService } from '@redaction/red-ui-http'; +import { FileAttributeConfig, FileAttributesControllerService } from '@redaction/red-ui-http'; import { AppStateService } from '../../../state/app-state.service'; import { ActivatedRoute } from '@angular/router'; import { debounce } from '../../../utils/debounce'; @@ -15,8 +15,8 @@ import { DialogService } from '../../../dialogs/dialog.service'; }) export class FileAttributesListingScreenComponent implements OnInit { public searchForm: FormGroup; - public attributes: FileAttribute[] = []; - public displayedAttributes: FileAttribute[] = []; + public attributes: FileAttributeConfig[] = []; + public displayedAttributes: FileAttributeConfig[] = []; public selectedFileAttributeIds: string[] = []; public viewReady = false; @@ -47,6 +47,7 @@ export class FileAttributesListingScreenComponent implements OnInit { try { const response = await this._fileAttributesService.getFileAttributesConfiguration(this._appStateService.activeRuleSetId).toPromise(); this.attributes = response?.fileAttributes || []; + } catch (e) { } finally { this.displayedAttributes = [...this.attributes]; this._executeSearch(); @@ -71,24 +72,24 @@ export class FileAttributesListingScreenComponent implements OnInit { if (!value) { value = { query: this.searchForm.get('query').value }; } - this.displayedAttributes = this.attributes.filter((attribute) => attribute.name.toLowerCase().includes(value.query.toLowerCase())); + this.displayedAttributes = this.attributes.filter((attribute) => attribute.label.toLowerCase().includes(value.query.toLowerCase())); } - public openAddEditAttributeDialog($event: MouseEvent, fileAttribute?: FileAttribute) { + public openAddEditAttributeDialog($event: MouseEvent, fileAttribute?: FileAttributeConfig) { $event.stopPropagation(); this._dialogService.openAddEditFileAttributeDialog(fileAttribute, this._appStateService.activeRuleSetId, async () => { await this._loadData(); }); } - public openConfirmDeleteAttributeDialog($event: MouseEvent, fileAttribute?: FileAttribute) { + public openConfirmDeleteAttributeDialog($event: MouseEvent, fileAttribute?: FileAttributeConfig) { $event.stopPropagation(); this._dialogService.openConfirmDeleteFileAttributeDialog(fileAttribute, this._appStateService.activeRuleSetId, async () => { await this._loadData(); }); } - public toggleAttributeSelected($event: MouseEvent, attribute: FileAttribute) { + public toggleAttributeSelected($event: MouseEvent, attribute: FileAttributeConfig) { $event.stopPropagation(); const idx = this.selectedFileAttributeIds.indexOf(attribute.id); if (idx === -1) { @@ -114,7 +115,7 @@ export class FileAttributesListingScreenComponent implements OnInit { return this.selectedFileAttributeIds.length > 0; } - public isAttributeSelected(attribute: FileAttribute) { + public isAttributeSelected(attribute: FileAttributeConfig) { return this.selectedFileAttributeIds.indexOf(attribute.id) !== -1; } } diff --git a/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component.ts b/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component.ts index 7c7b9d617..06cc809fa 100644 --- a/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component.ts +++ b/apps/red-ui/src/app/screens/admin/rule-sets-listing-screen/rule-sets-listing-screen.component.ts @@ -6,7 +6,7 @@ import { PermissionsService } from '../../../utils/permissions.service'; import { FormBuilder, FormGroup } from '@angular/forms'; import { debounce } from '../../../utils/debounce'; import { RuleSetModel } from '@redaction/red-ui-http'; -import { UserPreferenceService } from '../../../common/service/user-preference.service'; +import { UserPreferenceService } from '../../../utils/user-preference.service'; @Component({ selector: 'redaction-rule-sets-listing-screen', diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html index 94f66155c..cc7d8f9ce 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html @@ -129,7 +129,11 @@
- +
-
-
-
- -
-
-
-
-
- -
-
- - -
-
- +
+ + + + +
+
+
- -
-
- {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }} - -
- +
-
- {{ 'file-preview.no-annotations-for-page' | translate }} +
+ +
+
+ + +
+
+ +
+
+ +
+
+ {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }} +
-
-
- -
- -
-
- {{ annotation.typeLabel | translate }} -
-
- {{ annotation.descriptor | translate }}: {{ annotation.dictionary | humanize: false }} -
-
- : {{ annotation.content }} +
+ {{ 'file-preview.no-annotations-for-page' | translate }} +
+ +
+
+
+ +
+ +
+
+ {{ annotation.typeLabel | translate }} +
+
+ {{ annotation.descriptor | translate }}: {{ annotation.dictionary | humanize: false }} +
+
+ : {{ annotation.content }} +
+
- -
- - + + +
-
+
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss index 965a39992..b5e7470f2 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss @@ -30,27 +30,20 @@ width: 350px; min-width: 350px; - .right-title { + &.has-scrollbar:hover { + ::ng-deep redaction-document-info .right-title, + ::ng-deep redaction-document-info .section { + padding-right: 13px; + } + } + + ::ng-deep.right-title { height: 70px; display: flex; border-bottom: 1px solid $separator; align-items: center; justify-content: space-between; padding: 0 24px; - - .close-icon { - height: 14px; - width: 14px; - cursor: pointer; - } - - > div { - display: flex; - - redaction-circle-button { - margin-left: 2px; - } - } } .right-content { diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts index 31c9a8f79..1f00a497f 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts @@ -146,6 +146,22 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { hideSkipped = false; + private _viewDocumentInfo = false; + + public get viewDocumentInfo(): boolean { + return this._viewDocumentInfo; + } + + public set viewDocumentInfo(value: boolean) { + this._viewDocumentInfo = value; + if (!value) { + setTimeout(() => { + this._scrollQuickNavigation(); + this.scrollToSelectedAnnotation(); + }, 0); + } + } + updateViewMode() { const allAnnotations = this._instance.annotManager.getAnnotationsList(); @@ -329,13 +345,16 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { @debounce() private _scrollViews() { + if (this.viewDocumentInfo) { + return; + } this._scrollQuickNavigation(); this._scrollAnnotations(); } @debounce() private scrollToSelectedAnnotation() { - if (!this.selectedAnnotations || this.selectedAnnotations.length === 0) { + if (this.viewDocumentInfo || !this.selectedAnnotations || this.selectedAnnotations.length === 0) { return; } const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[annotation-id="${this.firstSelectedAnnotation.id}"].active`); @@ -602,6 +621,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { } public computeQuickNavButtonsState() { + if (this.viewDocumentInfo) { + return; + } const element: HTMLElement = this._quickNavigationElement.nativeElement.querySelector(`#pages`); const { scrollTop, scrollHeight, clientHeight } = element; this.quickScrollFirstEnabled = scrollTop !== 0; @@ -670,6 +692,11 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { this._updateCanPerformActions(); await this.appStateService.reloadActiveProjectFiles(); return; + + case 'view-document-info': + this.viewDocumentInfo = !this.viewDocumentInfo; + return; + default: this._updateCanPerformActions(); } diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index c0b0643b4..07b4df286 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -291,6 +291,18 @@ "view-toggle": "Redacted View", "tabs": { "quick-navigation": "Quick Navigation", + "document-info": { + "label": "Document Info", + "close": "Close Document Info", + "edit": "Edit Document Info", + "details": { + "project": "in {{projectName}}", + "pages": "{{pages}} pages", + "revised-pages": "{{pages}} revised pages", + "created-on": "Created on: {{date}}", + "due": "Due: {{date}}" + } + }, "annotations": { "label": "Workload" } @@ -303,6 +315,7 @@ "assign-me": "Assign to me", "last-reviewer": "Last Reviewed by:", "fullscreen": "Full Screen (F)", + "document-info": "Your Document Info lives here. This includes metadata required on each document.", "new-tab-ssr": "Open Document in Server Side Rendering Mode", "html-debug": "Open Document HTML Debug", "download-original-file": "Download Original File", @@ -732,6 +745,11 @@ "checkbox-1": "All documents it is used on will be impacted", "checkbox-2": "All inputted details on the documents will be lost" }, + "document-info": { + "title": "Introduce Document Info", + "save": "Save Document Info", + "save-approval": "Save and Send for Approval" + }, "user-listing": { "table-header": { "title": "{{length}} users" diff --git a/apps/red-ui/src/assets/icons/general/status-info.svg b/apps/red-ui/src/assets/icons/general/status-info.svg new file mode 100644 index 000000000..7f75f904d --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/status-info.svg @@ -0,0 +1,27 @@ + + + F8E3057D-BE44-469F-9E28-9A04A0B36DF0 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/red-ui/src/assets/styles/red-components.scss b/apps/red-ui/src/assets/styles/red-components.scss index c61dbc680..b5f038b3c 100644 --- a/apps/red-ui/src/assets/styles/red-components.scss +++ b/apps/red-ui/src/assets/styles/red-components.scss @@ -74,7 +74,7 @@ mat-icon { width: 10px; - margin-right: 4px; + margin-right: 6px; } &:not(:last-child) { From f2687264021307d321dac4526ef202b3fffee4d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Wed, 24 Mar 2021 23:24:13 +0200 Subject: [PATCH 09/11] Display document info over workload --- .../document-info.component.html | 40 ++-- .../document-info.component.scss | 27 ++- .../file-preview-screen.component.html | 198 +++++++++--------- .../file-preview-screen.component.scss | 8 +- .../file-preview-screen.component.ts | 24 +-- .../red-ui/src/assets/styles/red-loading.scss | 2 +- 6 files changed, 149 insertions(+), 150 deletions(-) diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.html b/apps/red-ui/src/app/components/document-info/document-info.component.html index ed28e1bde..95cbe235a 100644 --- a/apps/red-ui/src/app/components/document-info/document-info.component.html +++ b/apps/red-ui/src/app/components/document-info/document-info.component.html @@ -15,25 +15,27 @@
-
- Attributes go here -
+
+
+ 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 +
-
-
- - {{ 'file-preview.tabs.document-info.details.project' | translate: { projectName: project.name } }} -
-
- - {{ 'file-preview.tabs.document-info.details.pages' | translate: { pages: file.numberOfPages } }} -
-
- - {{ 'file-preview.tabs.document-info.details.created-on' | translate: { date: file.added | date: 'mediumDate' } }} -
-
- - {{ 'file-preview.tabs.document-info.details.due' | translate: { date: project.project.dueDate | date: 'mediumDate' } }} +
+
+ + {{ 'file-preview.tabs.document-info.details.project' | translate: { projectName: project.name } }} +
+
+ + {{ 'file-preview.tabs.document-info.details.pages' | translate: { pages: file.numberOfPages } }} +
+
+ + {{ 'file-preview.tabs.document-info.details.created-on' | translate: { date: file.added | date: 'mediumDate' } }} +
+
+ + {{ 'file-preview.tabs.document-info.details.due' | translate: { date: project.project.dueDate | date: 'mediumDate' } }} +
diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.scss b/apps/red-ui/src/app/components/document-info/document-info.component.scss index 87eaf014a..5f677f05a 100644 --- a/apps/red-ui/src/app/components/document-info/document-info.component.scss +++ b/apps/red-ui/src/app/components/document-info/document-info.component.scss @@ -1,4 +1,29 @@ @import '../../../assets/styles/red-variables'; +@import '../../../assets/styles/red-mixins'; + +:host { + display: block; + position: absolute; + height: 100%; + background: white; + z-index: 1; + width: 100%; + @include inset-shadow; +} + +.content { + max-height: calc(100% - 71px); + @include scroll-bar; + overflow: hidden; + + &:hover { + overflow: auto; + } + + &.has-scrollbar .section { + padding-right: 13px; + } +} .right-title > div { display: flex; @@ -9,7 +34,7 @@ } .section { - padding: 25px; + padding: 24px; flex-direction: column; > div { diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html index cc7d8f9ce..243552329 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html @@ -203,124 +203,122 @@ >
-
- +
+ - -
-
- +
+
+ +
+
+
+
+
+ +
+
+ + +
+
+
-
+ +
+
+ {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }} + +
+
-
- -
-
- - -
-
- -
-
- -
-
- {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }} - +
+ {{ 'file-preview.no-annotations-for-page' | translate }}
-
- {{ 'file-preview.no-annotations-for-page' | translate }} -
- -
-
-
- -
- -
-
- {{ annotation.typeLabel | translate }} -
-
- {{ annotation.descriptor | translate }}: {{ annotation.dictionary | humanize: false }} -
-
- : {{ annotation.content }} -
+
+
+ +
+ +
+
+ {{ annotation.typeLabel | translate }} +
+
+ {{ annotation.descriptor | translate }}: {{ annotation.dictionary | humanize: false }} +
+
+ : {{ annotation.content }}
-
- - -
+ +
+ +
- +
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss index b5e7470f2..3e6be62b9 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss @@ -29,13 +29,7 @@ padding: 0; width: 350px; min-width: 350px; - - &.has-scrollbar:hover { - ::ng-deep redaction-document-info .right-title, - ::ng-deep redaction-document-info .section { - padding-right: 13px; - } - } + position: relative; ::ng-deep.right-title { height: 70px; diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts index 1f00a497f..a792fe1c7 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts @@ -146,21 +146,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { hideSkipped = false; - private _viewDocumentInfo = false; - - public get viewDocumentInfo(): boolean { - return this._viewDocumentInfo; - } - - public set viewDocumentInfo(value: boolean) { - this._viewDocumentInfo = value; - if (!value) { - setTimeout(() => { - this._scrollQuickNavigation(); - this.scrollToSelectedAnnotation(); - }, 0); - } - } + public viewDocumentInfo = false; updateViewMode() { const allAnnotations = this._instance.annotManager.getAnnotationsList(); @@ -345,16 +331,13 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { @debounce() private _scrollViews() { - if (this.viewDocumentInfo) { - return; - } this._scrollQuickNavigation(); this._scrollAnnotations(); } @debounce() private scrollToSelectedAnnotation() { - if (this.viewDocumentInfo || !this.selectedAnnotations || this.selectedAnnotations.length === 0) { + if (!this.selectedAnnotations || this.selectedAnnotations.length === 0) { return; } const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[annotation-id="${this.firstSelectedAnnotation.id}"].active`); @@ -621,9 +604,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { } public computeQuickNavButtonsState() { - if (this.viewDocumentInfo) { - return; - } const element: HTMLElement = this._quickNavigationElement.nativeElement.querySelector(`#pages`); const { scrollTop, scrollHeight, clientHeight } = element; this.quickScrollFirstEnabled = scrollTop !== 0; diff --git a/apps/red-ui/src/assets/styles/red-loading.scss b/apps/red-ui/src/assets/styles/red-loading.scss index fb32d9e04..ac53e50bc 100644 --- a/apps/red-ui/src/assets/styles/red-loading.scss +++ b/apps/red-ui/src/assets/styles/red-loading.scss @@ -1,5 +1,5 @@ .loading:after { - content: ' .'; + content: '.'; animation: dots 1s steps(5, end) infinite; } From 5636656f767a6a0bde70e77ae0853247665627e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Thu, 25 Mar 2021 01:22:34 +0200 Subject: [PATCH 10/11] File workload separate component --- apps/red-ui/src/app/app.module.ts | 4 +- .../document-info.component.html | 2 +- .../document-info.component.scss | 5 +- .../file-workload.component.html | 133 +++++ .../file-workload.component.scss | 134 +++++ .../file-workload/file-workload.component.ts | 296 ++++++++++ .../file-preview-screen.component.html | 147 +---- .../file-preview-screen.component.scss | 263 ++++----- .../file-preview-screen.component.ts | 556 +++++------------- 9 files changed, 873 insertions(+), 667 deletions(-) create mode 100644 apps/red-ui/src/app/components/file-workload/file-workload.component.html create mode 100644 apps/red-ui/src/app/components/file-workload/file-workload.component.scss create mode 100644 apps/red-ui/src/app/components/file-workload/file-workload.component.ts diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index afdd131e0..f56c0f802 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -120,6 +120,7 @@ import { AddEditFileAttributeDialogComponent } from './dialogs/add-edit-file-att import { ConfirmDeleteFileAttributeDialogComponent } from './dialogs/confirm-delete-file-attribute-dialog/confirm-delete-file-attribute-dialog.component'; import { DocumentInfoDialogComponent } from './dialogs/document-info-dialog/document-info-dialog.component'; import { DocumentInfoComponent } from './components/document-info/document-info.component'; +import { FileWorkloadComponent } from './components/file-workload/file-workload.component'; export function HttpLoaderFactory(httpClient: HttpClient) { return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json'); @@ -226,7 +227,8 @@ const matImports = [ AddEditFileAttributeDialogComponent, ConfirmDeleteFileAttributeDialogComponent, DocumentInfoDialogComponent, - DocumentInfoComponent + DocumentInfoComponent, + FileWorkloadComponent ], imports: [ BrowserModule, diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.html b/apps/red-ui/src/app/components/document-info/document-info.component.html index 95cbe235a..69608ee31 100644 --- a/apps/red-ui/src/app/components/document-info/document-info.component.html +++ b/apps/red-ui/src/app/components/document-info/document-info.component.html @@ -15,7 +15,7 @@
-
+
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4
diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.scss b/apps/red-ui/src/app/components/document-info/document-info.component.scss index 5f677f05a..ee9825e39 100644 --- a/apps/red-ui/src/app/components/document-info/document-info.component.scss +++ b/apps/red-ui/src/app/components/document-info/document-info.component.scss @@ -11,8 +11,9 @@ @include inset-shadow; } -.content { - max-height: calc(100% - 71px); +.right-content { + flex-direction: column; + @include scroll-bar; overflow: hidden; diff --git a/apps/red-ui/src/app/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/components/file-workload/file-workload.component.html new file mode 100644 index 000000000..54f1c8512 --- /dev/null +++ b/apps/red-ui/src/app/components/file-workload/file-workload.component.html @@ -0,0 +1,133 @@ +
+
+ +
+
+
+
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }} + +
+ +
+
+ {{ 'file-preview.no-annotations-for-page' | translate }} +
+ +
+
+
+ +
+ +
+
+ {{ annotation.typeLabel | translate }} +
+
+ {{ annotation.descriptor | translate }}: {{ annotation.dictionary | humanize: false }} +
+
+ : {{ annotation.content }} +
+
+ + + + + + + + +
+
+ +
+
+
+
+
+ + + + + + {{ filter.key | humanize: false }} + + + + + + + + + diff --git a/apps/red-ui/src/app/components/file-workload/file-workload.component.scss b/apps/red-ui/src/app/components/file-workload/file-workload.component.scss new file mode 100644 index 000000000..149a4fb93 --- /dev/null +++ b/apps/red-ui/src/app/components/file-workload/file-workload.component.scss @@ -0,0 +1,134 @@ +@import '../../../assets/styles/red-variables'; +@import '../../../assets/styles/red-mixins'; + +.right-content { + .no-annotations { + padding: 24px; + text-align: center; + } + + .quick-navigation, + .annotations { + overflow-y: scroll; + outline: none; + + &.active-panel { + background-color: #fafafa; + } + } + + .quick-navigation { + border-right: 1px solid $separator; + min-width: 61px; + overflow: hidden; + display: flex; + flex-direction: column; + + .jump { + min-height: 32px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + transition: background-color 0.25s; + + &:not(.disabled):hover { + background-color: $grey-6; + } + + mat-icon { + width: 16px; + height: 16px; + } + + &.disabled { + cursor: default; + + mat-icon { + opacity: 0.3; + } + } + } + + .pages { + @include no-scroll-bar(); + overflow: auto; + flex: 1; + } + } + + .page-separator { + border-bottom: 1px solid $separator; + height: 32px; + box-sizing: border-box; + padding: 0 10px; + display: flex; + align-items: center; + background-color: $grey-6; + } + + .annotations { + overflow: hidden; + width: 100%; + height: calc(100% - 32px); + + .annotation-wrapper { + display: flex; + border-bottom: 1px solid $separator; + + .active-marker { + min-width: 4px; + min-height: 100%; + } + + &.active { + .active-marker { + background-color: $primary; + } + } + + .annotation { + padding: 10px 21px 10px 6px; + font-size: 11px; + line-height: 14px; + cursor: pointer; + display: flex; + flex-direction: column; + + &.removed { + text-decoration: line-through; + color: $grey-7; + } + + .details { + display: flex; + position: relative; + } + + redaction-type-annotation-icon { + margin-top: 6px; + margin-right: 10px; + } + } + + &:hover { + background-color: #f9fafb; + + ::ng-deep .annotation-actions { + display: flex; + } + } + } + + &:hover { + overflow-y: auto; + @include scroll-bar; + } + + &.has-scrollbar:hover { + .annotation { + padding-right: 10px; + } + } + } +} diff --git a/apps/red-ui/src/app/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/components/file-workload/file-workload.component.ts new file mode 100644 index 000000000..6d261bdfa --- /dev/null +++ b/apps/red-ui/src/app/components/file-workload/file-workload.component.ts @@ -0,0 +1,296 @@ +import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild } from '@angular/core'; +import { FilterModel } from '../filter/model/filter.model'; +import { AnnotationWrapper } from '../../screens/file/model/annotation.wrapper'; +import { AnnotationProcessingService } from '../../screens/file/service/annotation-processing.service'; +import { MatDialogRef, MatDialogState } from '@angular/material/dialog'; +import scrollIntoView from 'scroll-into-view-if-needed'; +import { debounce } from '../../utils/debounce'; +import { FileDataModel } from '../../screens/file/model/file-data.model'; + +const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape']; +const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown']; + +@Component({ + selector: 'redaction-file-workload', + templateUrl: './file-workload.component.html', + styleUrls: ['./file-workload.component.scss'] +}) +export class FileWorkloadComponent { + public displayedAnnotations: { [key: number]: { annotations: AnnotationWrapper[] } } = {}; + private _annotations: AnnotationWrapper[]; + + @Input() + set annotations(value: AnnotationWrapper[]) { + this._annotations = value; + // this.computeQuickNavButtonsState(); + } + + @Input() selectedAnnotations: AnnotationWrapper[]; + @Input() activeViewerPage: number; + @Input() shouldDeselectAnnotationsOnPageChange: boolean; + @Input() dialogRef: MatDialogRef; + @Input() annotationFilters: FilterModel[]; + @Input() fileData: FileDataModel; + @Input() hideSkipped: boolean; + @Input() annotationActionsTemplate: TemplateRef; + + @Output() selectAnnotation = new EventEmitter(); + @Output() selectPage = new EventEmitter(); + @Output() toggleSkipped = new EventEmitter(); + + public quickScrollFirstEnabled = false; + public quickScrollLastEnabled = false; + public displayedPages: number[] = []; + public pagesPanelActive = true; + + @ViewChild('annotationsElement') private _annotationsElement: ElementRef; + @ViewChild('quickNavigation') private _quickNavigationElement: ElementRef; + + constructor(private _changeDetectorRef: ChangeDetectorRef, private _annotationProcessingService: AnnotationProcessingService) {} + + private get firstSelectedAnnotation() { + return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null; + } + + private static _scrollToFirstElement(elements: HTMLElement[], mode: 'always' | 'if-needed' = 'if-needed') { + if (elements.length > 0) { + scrollIntoView(elements[0], { + behavior: 'smooth', + scrollMode: mode, + block: 'start', + inline: 'start' + }); + } + } + + public annotationIsSelected(annotation: AnnotationWrapper) { + return this.selectedAnnotations?.find((a) => a.id === annotation.id); + } + + public logAnnotation(annotation: AnnotationWrapper) { + console.log(annotation); + } + + @debounce(0) + public filtersChanged(filters: FilterModel[]) { + this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(this._annotations, filters); + this.displayedPages = Object.keys(this.displayedAnnotations).map((key) => Number(key)); + this.computeQuickNavButtonsState(); + this._changeDetectorRef.markForCheck(); + } + + public computeQuickNavButtonsState() { + setTimeout(() => { + const element: HTMLElement = this._quickNavigationElement.nativeElement.querySelector(`#pages`); + const { scrollTop, scrollHeight, clientHeight } = element; + this.quickScrollFirstEnabled = scrollTop !== 0; + this.quickScrollLastEnabled = scrollHeight !== scrollTop + clientHeight; + }, 0); + } + + public annotationClicked(annotation: AnnotationWrapper) { + this.pagesPanelActive = false; + this.selectAnnotation.emit(annotation); + } + + @HostListener('window:keyup', ['$event']) + handleKeyEvent($event: KeyboardEvent) { + if (!ALL_HOTKEY_ARRAY.includes($event.key) || this.dialogRef?.getState() === MatDialogState.OPEN) { + return; + } + + if ($event.key === 'ArrowLeft') { + this.pagesPanelActive = true; + return; + } + + if ($event.key === 'ArrowRight') { + this.pagesPanelActive = false; + // if we activated annotationsPanel - select first annotation from this page in case there is no + // selected annotation on this page + if (!this.pagesPanelActive) { + this._selectFirstAnnotationOnCurrentPageIfNecessary(); + } + return; + } + + if (!this.pagesPanelActive) { + this._navigateAnnotations($event); + } else { + this._navigatePages($event); + } + + this._changeDetectorRef.detectChanges(); + } + + public scrollAnnotations() { + if (this.firstSelectedAnnotation?.pageNumber === this.activeViewerPage) { + return; + } + this.scrollAnnotationsToPage(this.activeViewerPage, 'always'); + } + + public scrollAnnotationsToPage(page: number, mode: 'always' | 'if-needed' = 'if-needed') { + const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[anotation-page-header="${page}"]`); + FileWorkloadComponent._scrollToFirstElement(elements, mode); + } + + @debounce() + public scrollToSelectedAnnotation() { + if (!this.selectedAnnotations || this.selectedAnnotations.length === 0) { + return; + } + const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[annotation-id="${this.firstSelectedAnnotation.id}"].active`); + FileWorkloadComponent._scrollToFirstElement(elements); + } + + public scrollQuickNavigation() { + let quickNavPageIndex = this.displayedPages.findIndex((p) => p >= this.activeViewerPage); + if (quickNavPageIndex === -1 || this.displayedPages[quickNavPageIndex] !== this.activeViewerPage) { + quickNavPageIndex = Math.max(0, quickNavPageIndex - 1); + } + this._scrollQuickNavigationToPage(this.displayedPages[quickNavPageIndex]); + } + + public scrollQuickNavFirst() { + if (this.displayedPages.length > 0) { + this._scrollQuickNavigationToPage(this.displayedPages[0]); + } + } + + public scrollQuickNavLast() { + if (this.displayedPages.length > 0) { + this._scrollQuickNavigationToPage(this.displayedPages[this.displayedPages.length - 1]); + } + } + + public pageSelectedByClick($event: number) { + this.pagesPanelActive = true; + this.selectPage.emit($event); + } + + public preventKeyDefault($event: KeyboardEvent) { + if (COMMAND_KEY_ARRAY.includes($event.key)) { + $event.preventDefault(); + } + } + + private _selectFirstAnnotationOnCurrentPageIfNecessary() { + if ( + (!this.firstSelectedAnnotation || this.activeViewerPage !== this.firstSelectedAnnotation.pageNumber) && + this.displayedPages.indexOf(this.activeViewerPage) >= 0 + ) { + this.selectAnnotation.emit(this.displayedAnnotations[this.activeViewerPage].annotations[0]); + } + } + + private _navigateAnnotations($event: KeyboardEvent) { + if (!this.firstSelectedAnnotation || this.activeViewerPage !== this.firstSelectedAnnotation.pageNumber) { + const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); + if (pageIdx !== -1) { + // Displayed page has annotations + this.selectAnnotation.emit(this.displayedAnnotations[this.activeViewerPage].annotations[0]); + } else { + // Displayed page doesn't have annotations + if ($event.key === 'ArrowDown') { + const nextPage = this._nextPageWithAnnotations(); + this.shouldDeselectAnnotationsOnPageChange = false; + this.selectAnnotation.emit(this.displayedAnnotations[nextPage].annotations[0]); + } else { + const prevPage = this._prevPageWithAnnotations(); + this.shouldDeselectAnnotationsOnPageChange = false; + const prevPageAnnotations = this.displayedAnnotations[prevPage].annotations; + this.selectAnnotation.emit(prevPageAnnotations[prevPageAnnotations.length - 1]); + } + } + } else { + const page = this.firstSelectedAnnotation.pageNumber; + const pageIdx = this.displayedPages.indexOf(page); + const annotationsOnPage = this.displayedAnnotations[page].annotations; + const idx = annotationsOnPage.findIndex((a) => a.id === this.firstSelectedAnnotation.id); + + if ($event.key === 'ArrowDown') { + if (idx + 1 !== annotationsOnPage.length) { + // If not last item in page + this.selectAnnotation.emit(annotationsOnPage[idx + 1]); + } else if (pageIdx + 1 < this.displayedPages.length) { + // If not last page + const nextPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx + 1]].annotations; + this.shouldDeselectAnnotationsOnPageChange = false; + this.selectAnnotation.emit(nextPageAnnotations[0]); + } + } else { + if (idx !== 0) { + // If not first item in page + this.selectAnnotation.emit(annotationsOnPage[idx - 1]); + } else if (pageIdx) { + // If not first page + const prevPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx - 1]].annotations; + this.shouldDeselectAnnotationsOnPageChange = false; + this.selectAnnotation.emit(prevPageAnnotations[prevPageAnnotations.length - 1]); + } + } + } + } + + private _navigatePages($event: KeyboardEvent) { + const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); + + if ($event.key === 'ArrowDown') { + if (pageIdx !== -1) { + // If active page has annotations + if (pageIdx !== this.displayedPages.length - 1) { + this.selectPage.emit(this.displayedPages[pageIdx + 1]); + } + } else { + // If active page doesn't have annotations + const nextPage = this._nextPageWithAnnotations(); + if (nextPage) { + this.selectPage.emit(nextPage); + } + } + } else { + if (pageIdx !== -1) { + // If active page has annotations + if (pageIdx !== 0) { + this.selectPage.emit(this.displayedPages[pageIdx - 1]); + } + } else { + // If active page doesn't have annotations + const prevPage = this._prevPageWithAnnotations(); + if (prevPage) { + this.selectPage.emit(prevPage); + } + } + } + } + + private _nextPageWithAnnotations() { + let idx = 0; + for (const page of this.displayedPages) { + if (page > this.activeViewerPage) { + break; + } + ++idx; + } + return idx < this.displayedPages.length ? this.displayedPages[idx] : null; + } + + private _prevPageWithAnnotations() { + let idx = this.displayedPages.length - 1; + for (const page of this.displayedPages.reverse()) { + if (page < this.activeViewerPage) { + this.selectPage.emit(this.displayedPages[idx]); + this.scrollAnnotations(); + break; + } + --idx; + } + return idx >= 0 ? this.displayedPages[idx] : null; + } + + private _scrollQuickNavigationToPage(page: number) { + const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(`#quick-nav-page-${page}`); + FileWorkloadComponent._scrollToFirstElement(elements); + } +} diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html index 243552329..2599fb9dd 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html @@ -207,118 +207,21 @@ -
-
- -
-
-
-
-
- -
-
- - -
-
- -
-
- -
-
- {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }} - -
- -
-
- {{ 'file-preview.no-annotations-for-page' | translate }} -
- -
-
-
- -
- -
-
- {{ annotation.typeLabel | translate }} -
-
- {{ annotation.descriptor | translate }}: {{ annotation.dictionary | humanize: false }} -
-
- : {{ annotation.content }} -
-
- -
-
- -
-
-
-
-
+
@@ -330,17 +233,11 @@
- - - - - {{ filter.key | humanize: false }} - - - - - - - - + + diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss index 3e6be62b9..00691a2d4 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss @@ -31,7 +31,7 @@ min-width: 350px; position: relative; - ::ng-deep.right-title { + ::ng-deep .right-title { height: 70px; display: flex; border-bottom: 1px solid $separator; @@ -40,142 +40,143 @@ padding: 0 24px; } - .right-content { + ::ng-deep .right-content { height: calc(100% - 72px); box-sizing: border-box; display: flex; - - .quick-navigation, - .annotations { - overflow-y: scroll; - outline: none; - - &.active-panel { - background-color: #fafafa; - } - } - - .quick-navigation { - border-right: 1px solid $separator; - min-width: 61px; - overflow: hidden; - display: flex; - flex-direction: column; - - .jump { - min-height: 32px; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; - transition: background-color 0.25s; - - &:not(.disabled):hover { - background-color: $grey-6; - } - - mat-icon { - width: 16px; - height: 16px; - } - - &.disabled { - cursor: default; - - mat-icon { - opacity: 0.3; - } - } - } - - .pages { - @include no-scroll-bar(); - overflow: auto; - flex: 1; - } - } - - .page-separator { - border-bottom: 1px solid $separator; - height: 32px; - box-sizing: border-box; - padding: 0 10px; - display: flex; - align-items: center; - background-color: $grey-6; - } - - .annotations { - overflow: hidden; - width: 100%; - height: calc(100% - 32px); - - .annotation-wrapper { - display: flex; - border-bottom: 1px solid $separator; - - .active-marker { - min-width: 4px; - min-height: 100%; - } - - &.active { - .active-marker { - background-color: $primary; - } - } - - .annotation { - padding: 10px 21px 10px 6px; - font-size: 11px; - line-height: 14px; - cursor: pointer; - display: flex; - flex-direction: column; - - &.removed { - text-decoration: line-through; - color: $grey-7; - } - - .details { - display: flex; - position: relative; - } - - redaction-type-annotation-icon { - margin-top: 6px; - margin-right: 10px; - } - } - - &:hover { - background-color: #f9fafb; - - ::ng-deep .annotation-actions { - display: flex; - } - } - } - - &:hover { - overflow-y: auto; - @include scroll-bar; - } - - &.has-scrollbar:hover { - .annotation { - padding-right: 10px; - } - } - } } + // + // .quick-navigation, + // .annotations { + // overflow-y: scroll; + // outline: none; + // + // &.active-panel { + // background-color: #fafafa; + // } + // } + // + // .quick-navigation { + // border-right: 1px solid $separator; + // min-width: 61px; + // overflow: hidden; + // display: flex; + // flex-direction: column; + // + // .jump { + // min-height: 32px; + // display: flex; + // justify-content: center; + // align-items: center; + // cursor: pointer; + // transition: background-color 0.25s; + // + // &:not(.disabled):hover { + // background-color: $grey-6; + // } + // + // mat-icon { + // width: 16px; + // height: 16px; + // } + // + // &.disabled { + // cursor: default; + // + // mat-icon { + // opacity: 0.3; + // } + // } + // } + // + // .pages { + // @include no-scroll-bar(); + // overflow: auto; + // flex: 1; + // } + // } + // + // .page-separator { + // border-bottom: 1px solid $separator; + // height: 32px; + // box-sizing: border-box; + // padding: 0 10px; + // display: flex; + // align-items: center; + // background-color: $grey-6; + // } + // + // .annotations { + // overflow: hidden; + // width: 100%; + // height: calc(100% - 32px); + // + // .annotation-wrapper { + // display: flex; + // border-bottom: 1px solid $separator; + // + // .active-marker { + // min-width: 4px; + // min-height: 100%; + // } + // + // &.active { + // .active-marker { + // background-color: $primary; + // } + // } + // + // .annotation { + // padding: 10px 21px 10px 6px; + // font-size: 11px; + // line-height: 14px; + // cursor: pointer; + // display: flex; + // flex-direction: column; + // + // &.removed { + // text-decoration: line-through; + // color: $grey-7; + // } + // + // .details { + // display: flex; + // position: relative; + // } + // + // redaction-type-annotation-icon { + // margin-top: 6px; + // margin-right: 10px; + // } + // } + // + // &:hover { + // background-color: #f9fafb; + // + // ::ng-deep .annotation-actions { + // display: flex; + // } + // } + // } + // + // &:hover { + // overflow-y: auto; + // @include scroll-bar; + // } + // + // &.has-scrollbar:hover { + // .annotation { + // padding-right: 10px; + // } + // } + // } + //} } -.no-annotations { - padding: 24px; - text-align: center; -} +//.no-annotations { +// padding: 24px; +// text-align: center; +//} .assign-actions-wrapper { display: flex; diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts index a792fe1c7..4eb298fc9 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts @@ -30,9 +30,9 @@ import { FileManagementControllerService, StatusControllerService } from '@redac import { PdfViewerDataService } from '../service/pdf-viewer-data.service'; import { download } from '../../../utils/file-download-utils'; import { ViewMode } from '../model/view-mode'; +import { FileWorkloadComponent } from '../../../components/file-workload/file-workload.component'; -const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape']; -const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape', 'F', 'f']; +const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f']; @Component({ selector: 'redaction-file-preview-screen', @@ -40,6 +40,33 @@ const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Es styleUrls: ['./file-preview-screen.component.scss'] }) export class FilePreviewScreenComponent implements OnInit, OnDestroy { + public dialogRef: MatDialogRef; + public viewMode: ViewMode = 'STANDARD'; + public fullScreen = false; + public editingReviewer = false; + public reviewerForm: FormGroup; + public shouldDeselectAnnotationsOnPageChange = true; + public analysisProgressInSeconds = 0; + public analysisProgress: number; + public analysisInterval: number; + fileData: FileDataModel; + fileId: string; + annotationData: AnnotationData; + selectedAnnotations: AnnotationWrapper[]; + viewReady = false; + annotationFilters: FilterModel[]; + loadingMessage: string; + canPerformAnnotationActions: boolean; + filesAutoUpdateTimer: Subscription; + fileReanalysedSubscription: Subscription; + hideSkipped = false; + public viewDocumentInfo = false; + private projectId: string; + private _instance: WebViewerInstance; + + @ViewChild('fileWorkloadComponent') private _workloadComponent: FileWorkloadComponent; + @ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent; + constructor( public readonly appStateService: AppStateService, public readonly permissionsService: PermissionsService, @@ -72,7 +99,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { }); } - get annotations() { + get annotations(): AnnotationWrapper[] { return this.annotationData ? this.annotationData.visibleAnnotations : []; } @@ -92,62 +119,16 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0; } - get ignoreColor() { - return this.appStateService.getDictionaryColor('skipped'); - } - get displayData() { return this.fileData?.fileData; } - private projectId: string; - private _instance: WebViewerInstance; - private _dialogRef: MatDialogRef; - - public viewMode: ViewMode = 'STANDARD'; - public fullScreen = false; - public editingReviewer = false; - public reviewerForm: FormGroup; - public shouldDeselectAnnotationsOnPageChange = true; - - public analysisProgressInSeconds = 0; - public analysisProgress: number; - public analysisInterval: number; - - public quickScrollFirstEnabled = false; - public quickScrollLastEnabled = false; - - public displayedPages: number[] = []; - get indeterminateMode() { return ( this.analysisProgress > 100 || this.appStateService.activeFile.analysisDuration < 3 * 1000 // it takes longer than usual - switch to indeterminate ); // on less than 3 seconds show indeterminate } - @ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent; - @ViewChild('annotationsElement') private _annotationsElement: ElementRef; - @ViewChild('quickNavigation') private _quickNavigationElement: ElementRef; - - fileData: FileDataModel; - fileId: string; - annotationData: AnnotationData; - - displayedAnnotations: { [key: number]: { annotations: AnnotationWrapper[] } } = {}; - selectedAnnotations: AnnotationWrapper[]; - pagesPanelActive = true; - viewReady = false; - annotationFilters: FilterModel[]; - - loadingMessage: string; - canPerformAnnotationActions: boolean; - filesAutoUpdateTimer: Subscription; - fileReanalysedSubscription: Subscription; - - hideSkipped = false; - - public viewDocumentInfo = false; - updateViewMode() { const allAnnotations = this._instance.annotManager.getAnnotationsList(); @@ -183,15 +164,11 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { break; } - this._rebuildFilters(); + this.rebuildFilters(); this._updateCanPerformActions(); } - private _updateCanPerformActions() { - this.canPerformAnnotationActions = this.permissionsService.canPerformAnnotationActions() && this.viewMode === 'STANDARD'; - } - ngOnInit(): void { document.documentElement.addEventListener('fullscreenchange', (event) => { if (!document.fullscreenElement) { @@ -227,32 +204,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { this.fileReanalysedSubscription.unsubscribe(); } - private _loadFileData(performUpdate: boolean = false) { - return this._fileDownloadService.loadActiveFileData().pipe( - tap((fileDataModel) => { - if (fileDataModel.fileStatus.isWorkable) { - if (performUpdate) { - this.fileData.redactionLog = fileDataModel.redactionLog; - this.fileData.redactionChangeLog = fileDataModel.redactionChangeLog; - this.fileData.fileStatus = fileDataModel.fileStatus; - this.fileData.manualRedactions = fileDataModel.manualRedactions; - this._rebuildFilters(true); - } else { - this.fileData = fileDataModel; - this._rebuildFilters(); - } - } else { - if (fileDataModel.fileStatus.isError) { - this._router.navigate(['/ui/projects/' + this.appStateService.activeProjectId]); - } else { - this.loadingMessage = 'file-preview.reanalyse-file'; - } - } - }) - ); - } - - private _rebuildFilters(deletePreviousAnnotations: boolean = false) { + public rebuildFilters(deletePreviousAnnotations: boolean = false) { const startTime = new Date().getTime(); if (deletePreviousAnnotations) { this.activeViewer.annotManager.deleteAnnotations(this.activeViewer.annotManager.getAnnotationsList(), { @@ -270,7 +222,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { ); const annotationFilters = this._annotationProcessingService.getAnnotationFilter(this.annotations); this.annotationFilters = processFilters(this.annotationFilters, annotationFilters); - this.filtersChanged(this.annotationFilters); + this._workloadComponent.filtersChanged(this.annotationFilters); console.log('[REDACTION] Process time: ' + (new Date().getTime() - processStartTime) + 'ms'); console.log( '[REDACTION] Annotation Redraw and filter rebuild time: ' + @@ -283,27 +235,22 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { handleAnnotationSelected(annotationIds: string[]) { this.selectedAnnotations = annotationIds.map((annotationId) => this.annotations.find((annotationWrapper) => annotationWrapper.id === annotationId)); - this.scrollToSelectedAnnotation(); + this._workloadComponent.scrollToSelectedAnnotation(); this._changeDetectorRef.detectChanges(); } - annotationClicked(annotation: AnnotationWrapper) { - this.pagesPanelActive = false; - this.selectAnnotation(annotation); - } - selectAnnotation(annotation: AnnotationWrapper) { this._viewerComponent.selectAnnotation(annotation); } selectPage(pageNumber: number) { this._viewerComponent.navigateToPage(pageNumber); - this._scrollAnnotationsToPage(pageNumber, 'always'); + this._workloadComponent.scrollAnnotationsToPage(pageNumber, 'always'); } openManualAnnotationDialog($event: ManualRedactionEntryWrapper) { this.ngZone.run(() => { - this._dialogRef = this._dialogService.openManualAnnotationDialog($event, async (response: ManualAnnotationResponse) => { + this.dialogRef = this._dialogService.openManualAnnotationDialog($event, async (response: ManualAnnotationResponse) => { if (response?.annotationId) { const annotation = this.activeViewer.annotManager.getAnnotationById(response.manualRedactionEntryWrapper.rectId); this.activeViewer.annotManager.deleteAnnotation(annotation); @@ -317,81 +264,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { }); } - annotationIsSelected(annotation: AnnotationWrapper) { - return this.selectedAnnotations?.find((a) => a.id === annotation.id); - } - - private get firstSelectedAnnotation() { - return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null; - } - - private get lastSelectedAnnotation() { - return this.selectedAnnotations?.length ? this.selectedAnnotations[this.selectedAnnotations.length - 1] : null; - } - - @debounce() - private _scrollViews() { - this._scrollQuickNavigation(); - this._scrollAnnotations(); - } - - @debounce() - private scrollToSelectedAnnotation() { - if (!this.selectedAnnotations || this.selectedAnnotations.length === 0) { - return; - } - const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[annotation-id="${this.firstSelectedAnnotation.id}"].active`); - this._scrollToFirstElement(elements); - } - - private _scrollQuickNavigationToPage(page: number) { - const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(`#quick-nav-page-${page}`); - this._scrollToFirstElement(elements); - } - - private _scrollQuickNavigation() { - let quickNavPageIndex = this.displayedPages.findIndex((p) => p >= this.activeViewerPage); - if (quickNavPageIndex === -1 || this.displayedPages[quickNavPageIndex] !== this.activeViewerPage) { - quickNavPageIndex = Math.max(0, quickNavPageIndex - 1); - } - this._scrollQuickNavigationToPage(this.displayedPages[quickNavPageIndex]); - } - - public scrollQuickNavFirst() { - if (this.displayedPages.length > 0) { - this._scrollQuickNavigationToPage(this.displayedPages[0]); - } - } - - public scrollQuickNavLast() { - if (this.displayedPages.length > 0) { - this._scrollQuickNavigationToPage(this.displayedPages[this.displayedPages.length - 1]); - } - } - - private _scrollAnnotations() { - if (this.firstSelectedAnnotation?.pageNumber === this.activeViewerPage) { - return; - } - this._scrollAnnotationsToPage(this.activeViewerPage, 'always'); - } - - private _scrollAnnotationsToPage(page: number, mode: 'always' | 'if-needed' = 'if-needed') { - const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[anotation-page-header="${page}"]`); - this._scrollToFirstElement(elements, mode); - } - - private _scrollToFirstElement(elements: HTMLElement[], mode: 'always' | 'if-needed' = 'if-needed') { - if (elements.length > 0) { - scrollIntoView(elements[0], { - behavior: 'smooth', - scrollMode: mode, - block: 'start', - inline: 'start' - }); - } - } - public toggleFullScreen() { this.fullScreen = !this.fullScreen; if (this.fullScreen) { @@ -403,7 +275,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { @HostListener('window:keyup', ['$event']) handleKeyEvent($event: KeyboardEvent) { - if (!ALL_HOTKEY_ARRAY.includes($event.key) || this._dialogRef?.getState() === MatDialogState.OPEN) { + if (!ALL_HOTKEY_ARRAY.includes($event.key) || this.dialogRef?.getState() === MatDialogState.OPEN) { return; } @@ -421,145 +293,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { return; } - if ($event.key === 'ArrowLeft') { - this.pagesPanelActive = true; - } - if ($event.key === 'ArrowRight') { - this.pagesPanelActive = false; - // if we activated annotationsPanel - select first annotation from this page in case there is no - // selected annotation on this page - if (!this.pagesPanelActive) { - this._selectFirstAnnotationOnCurrentPageIfNecessary(); - } - } - - if ($event.key === 'ArrowLeft' || $event.key === 'ArrowRight') { - return; - } - - if (!this.pagesPanelActive) { - this._navigateAnnotations($event); - } else { - this._navigatePages($event); - } - this._changeDetectorRef.detectChanges(); } - private _selectFirstAnnotationOnCurrentPageIfNecessary() { - if ( - (!this.firstSelectedAnnotation || this.activeViewerPage !== this.firstSelectedAnnotation.pageNumber) && - this.displayedPages.indexOf(this.activeViewerPage) >= 0 - ) { - this.selectAnnotation(this.displayedAnnotations[this.activeViewerPage].annotations[0]); - } - } - - private _navigateAnnotations($event: KeyboardEvent) { - if (!this.firstSelectedAnnotation || this.activeViewerPage !== this.firstSelectedAnnotation.pageNumber) { - const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); - if (pageIdx !== -1) { - // Displayed page has annotations - this.selectAnnotation(this.displayedAnnotations[this.activeViewerPage].annotations[0]); - } else { - // Displayed page doesn't have annotations - if ($event.key === 'ArrowDown') { - const nextPage = this._nextPageWithAnnotations(); - this.shouldDeselectAnnotationsOnPageChange = false; - this.selectAnnotation(this.displayedAnnotations[nextPage].annotations[0]); - } else { - const prevPage = this._prevPageWithAnnotations(); - this.shouldDeselectAnnotationsOnPageChange = false; - const prevPageAnnotations = this.displayedAnnotations[prevPage].annotations; - this.selectAnnotation(prevPageAnnotations[prevPageAnnotations.length - 1]); - } - } - } else { - const page = this.firstSelectedAnnotation.pageNumber; - const pageIdx = this.displayedPages.indexOf(page); - const annotationsOnPage = this.displayedAnnotations[page].annotations; - const idx = annotationsOnPage.findIndex((a) => a.id === this.firstSelectedAnnotation.id); - - if ($event.key === 'ArrowDown') { - if (idx + 1 !== annotationsOnPage.length) { - // If not last item in page - this.selectAnnotation(annotationsOnPage[idx + 1]); - } else if (pageIdx + 1 < this.displayedPages.length) { - // If not last page - const nextPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx + 1]].annotations; - this.shouldDeselectAnnotationsOnPageChange = false; - this.selectAnnotation(nextPageAnnotations[0]); - } - } else { - if (idx !== 0) { - // If not first item in page - this.selectAnnotation(annotationsOnPage[idx - 1]); - } else if (pageIdx) { - // If not first page - const prevPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx - 1]].annotations; - this.shouldDeselectAnnotationsOnPageChange = false; - this.selectAnnotation(prevPageAnnotations[prevPageAnnotations.length - 1]); - } - } - } - } - - private _navigatePages($event: KeyboardEvent) { - const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); - - if ($event.key === 'ArrowDown') { - if (pageIdx !== -1) { - // If active page has annotations - if (pageIdx !== this.displayedPages.length - 1) { - this.selectPage(this.displayedPages[pageIdx + 1]); - } - } else { - // If active page doesn't have annotations - const nextPage = this._nextPageWithAnnotations(); - if (nextPage) { - this.selectPage(nextPage); - } - } - } else { - if (pageIdx !== -1) { - // If active page has annotations - if (pageIdx !== 0) { - this.selectPage(this.displayedPages[pageIdx - 1]); - } - } else { - // If active page doesn't have annotations - const prevPage = this._prevPageWithAnnotations(); - if (prevPage) { - this.selectPage(prevPage); - } - } - } - } - - private _nextPageWithAnnotations() { - let idx = 0; - for (const page of this.displayedPages) { - if (page > this.activeViewerPage) { - break; - } - ++idx; - } - return idx < this.displayedPages.length ? this.displayedPages[idx] : null; - } - - private _prevPageWithAnnotations() { - let idx = this.displayedPages.length - 1; - for (const page of this.displayedPages.reverse()) { - if (page < this.activeViewerPage) { - this.selectPage(this.displayedPages[idx]); - this._scrollAnnotations(); - break; - } - --idx; - } - return idx >= 0 ? this.displayedPages[idx] : null; - } - viewerPageChanged($event: any) { if (typeof $event === 'number') { this._scrollViews(); @@ -590,74 +326,10 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { } } - filtersChanged(filters: FilterModel[]) { - this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(this.annotations, filters); - this.displayedPages = Object.keys(this.displayedAnnotations).map((key) => Number(key)); - this.computeQuickNavButtonsState(); - this._changeDetectorRef.markForCheck(); - } - - preventKeyDefault($event: KeyboardEvent) { - if (COMMAND_KEY_ARRAY.includes($event.key)) { - $event.preventDefault(); - } - } - - public computeQuickNavButtonsState() { - const element: HTMLElement = this._quickNavigationElement.nativeElement.querySelector(`#pages`); - const { scrollTop, scrollHeight, clientHeight } = element; - this.quickScrollFirstEnabled = scrollTop !== 0; - this.quickScrollLastEnabled = scrollHeight !== scrollTop + clientHeight; - } - - private _cleanupAndRedrawManualAnnotations() { - this._fileDownloadService.loadActiveFileManualAnnotations().subscribe((manualRedactions) => { - this.fileData.manualRedactions = manualRedactions; - this._rebuildFilters(); - this._annotationDrawService.drawAnnotations(this._instance, this.annotationData.allAnnotations, this.hideSkipped); - }); - } - - private async _cleanupAndRedrawManualAnnotationsForEntirePage(page: number) { - const currentPageAnnotations = this.annotations.filter((a) => a.pageNumber === page); - const currentPageAnnotationIds = currentPageAnnotations.map((a) => a.id); - this.fileData.fileStatus = await this.appStateService.reloadActiveFile(); - - this._fileDownloadService.loadActiveFileManualAnnotations().subscribe((manualRedactions) => { - this.fileData.manualRedactions = manualRedactions; - this._rebuildFilters(); - if (this.viewMode === 'STANDARD') { - currentPageAnnotationIds.forEach((id) => { - this._findAndDeleteAnnotation(id); - }); - const newPageAnnotations = this.annotations.filter((item) => item.pageNumber === page); - this._handleDeltaAnnotationFilters(currentPageAnnotations, newPageAnnotations); - this._annotationDrawService.drawAnnotations(this._instance, newPageAnnotations, this.hideSkipped); - } - }); - } - - private _handleDeltaAnnotationFilters(currentPageAnnotations: AnnotationWrapper[], newPageAnnotations: AnnotationWrapper[]) { - const hasAnyFilterSet = this.annotationFilters.find((f) => f.checked || f.indeterminate); - if (hasAnyFilterSet) { - const oldPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations); - const newPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(newPageAnnotations); - handleFilterDelta(oldPageSpecificFilters, newPageSpecificFilters, this.annotationFilters); - this.filtersChanged(this.annotationFilters); - } - } - async annotationsChangedByReviewAction(annotation: AnnotationWrapper) { await this._cleanupAndRedrawManualAnnotationsForEntirePage(annotation.pageNumber); } - private _findAndDeleteAnnotation(id: string) { - const viewerAnnotation = this.activeViewer.annotManager.getAnnotationById(id); - if (viewerAnnotation) { - this.activeViewer.annotManager.deleteAnnotation(viewerAnnotation, { imported: true, force: true }); - } - } - async fileActionPerformed(action: string) { switch (action) { case 'delete': @@ -682,31 +354,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { } } - private _startAnalysisTimer() { - this._stopAnalysisTimer(); - - if (this.appStateService.activeFile.analysisDuration > 0) { - this.analysisProgress = 0; - this.analysisProgressInSeconds = 0; - - this.analysisInterval = setInterval(() => { - this.analysisProgressInSeconds += 1; - this.analysisProgress = (this.analysisProgressInSeconds * 100) / (this.appStateService.activeFile.analysisDuration / 1000); - }, 1000); - } else { - this.analysisInterval = 0; - this.analysisProgress = 0; - this.analysisProgressInSeconds = 0; - } - } - - private _stopAnalysisTimer() { - if (this.analysisInterval) { - clearInterval(this.analysisInterval); - this.analysisInterval = 0; - } - } - public async assignToMe() { await this._fileActionService.assignToMe(this.fileData.fileStatus, async () => { await this.appStateService.reloadActiveFile(); @@ -732,21 +379,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { this.reviewerForm.setValue({ reviewer: this.appStateService.activeFile.currentReviewer }); } - pageSelectedByClick($event: number) { - this.pagesPanelActive = true; - this.selectPage($event); - } - - /* Get the documentElement () to display the page in fullscreen */ - - /* View in fullscreen */ - private _openFullScreen() { - const documentElement = document.documentElement; - if (documentElement.requestFullscreen) { - documentElement.requestFullscreen(); - } - } - /* Close fullscreen */ closeFullScreen() { if (document.exitFullscreen) { @@ -787,8 +419,118 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { window.open(`/html-debug/${this.projectId}/${this.fileId}`, '_blank'); } - logAnnotation(annotation: AnnotationWrapper) { - console.log(annotation); + private _updateCanPerformActions() { + this.canPerformAnnotationActions = this.permissionsService.canPerformAnnotationActions() && this.viewMode === 'STANDARD'; + } + + private _loadFileData(performUpdate: boolean = false) { + return this._fileDownloadService.loadActiveFileData().pipe( + tap((fileDataModel) => { + if (fileDataModel.fileStatus.isWorkable) { + if (performUpdate) { + this.fileData.redactionLog = fileDataModel.redactionLog; + this.fileData.redactionChangeLog = fileDataModel.redactionChangeLog; + this.fileData.fileStatus = fileDataModel.fileStatus; + this.fileData.manualRedactions = fileDataModel.manualRedactions; + this.rebuildFilters(true); + } else { + this.fileData = fileDataModel; + this.rebuildFilters(); + } + } else { + if (fileDataModel.fileStatus.isError) { + this._router.navigate(['/ui/projects/' + this.appStateService.activeProjectId]); + } else { + this.loadingMessage = 'file-preview.reanalyse-file'; + } + } + }) + ); + } + + @debounce() + private _scrollViews() { + this._workloadComponent.scrollQuickNavigation(); + this._workloadComponent.scrollAnnotations(); + } + + /* Get the documentElement () to display the page in fullscreen */ + + private _cleanupAndRedrawManualAnnotations() { + this._fileDownloadService.loadActiveFileManualAnnotations().subscribe((manualRedactions) => { + this.fileData.manualRedactions = manualRedactions; + this.rebuildFilters(); + this._annotationDrawService.drawAnnotations(this._instance, this.annotationData.allAnnotations, this.hideSkipped); + }); + } + + private async _cleanupAndRedrawManualAnnotationsForEntirePage(page: number) { + const currentPageAnnotations = this.annotations.filter((a) => a.pageNumber === page); + const currentPageAnnotationIds = currentPageAnnotations.map((a) => a.id); + this.fileData.fileStatus = await this.appStateService.reloadActiveFile(); + + this._fileDownloadService.loadActiveFileManualAnnotations().subscribe((manualRedactions) => { + this.fileData.manualRedactions = manualRedactions; + this.rebuildFilters(); + if (this.viewMode === 'STANDARD') { + currentPageAnnotationIds.forEach((id) => { + this._findAndDeleteAnnotation(id); + }); + const newPageAnnotations = this.annotations.filter((item) => item.pageNumber === page); + this._handleDeltaAnnotationFilters(currentPageAnnotations, newPageAnnotations); + this._annotationDrawService.drawAnnotations(this._instance, newPageAnnotations, this.hideSkipped); + } + }); + } + + private _handleDeltaAnnotationFilters(currentPageAnnotations: AnnotationWrapper[], newPageAnnotations: AnnotationWrapper[]) { + const hasAnyFilterSet = this.annotationFilters.find((f) => f.checked || f.indeterminate); + if (hasAnyFilterSet) { + const oldPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations); + const newPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(newPageAnnotations); + handleFilterDelta(oldPageSpecificFilters, newPageSpecificFilters, this.annotationFilters); + this._workloadComponent.filtersChanged(this.annotationFilters); + } + } + + private _findAndDeleteAnnotation(id: string) { + const viewerAnnotation = this.activeViewer.annotManager.getAnnotationById(id); + if (viewerAnnotation) { + this.activeViewer.annotManager.deleteAnnotation(viewerAnnotation, { imported: true, force: true }); + } + } + + private _startAnalysisTimer() { + this._stopAnalysisTimer(); + + if (this.appStateService.activeFile.analysisDuration > 0) { + this.analysisProgress = 0; + this.analysisProgressInSeconds = 0; + + this.analysisInterval = setInterval(() => { + this.analysisProgressInSeconds += 1; + this.analysisProgress = (this.analysisProgressInSeconds * 100) / (this.appStateService.activeFile.analysisDuration / 1000); + }, 1000); + } else { + this.analysisInterval = 0; + this.analysisProgress = 0; + this.analysisProgressInSeconds = 0; + } + } + + private _stopAnalysisTimer() { + if (this.analysisInterval) { + clearInterval(this.analysisInterval); + this.analysisInterval = 0; + } + } + + /* View in fullscreen */ + private _openFullScreen() { + const documentElement = document.documentElement; + if (documentElement.requestFullscreen) { + documentElement.requestFullscreen(); + } } private _handleIgnoreAnnotationsDrawing() { From 77fc8c1b4825fb5c07f01fd7a1efdb00e1c08491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Thu, 25 Mar 2021 19:13:58 +0200 Subject: [PATCH 11/11] Finished file attributes --- .../document-info.component.html | 7 +++-- .../document-info.component.scss | 10 +++++++ .../document-info/document-info.component.ts | 17 +++++++++-- .../project-details.component.html | 2 +- ...-edit-file-attribute-dialog.component.html | 14 +++++++++ ...dd-edit-file-attribute-dialog.component.ts | 3 +- ...-delete-file-attribute-dialog.component.ts | 2 +- .../document-info-dialog.component.html | 15 ++++------ .../document-info-dialog.component.ts | 29 ++++++++++++------- ...ile-attributes-listing-screen.component.ts | 3 +- .../file-preview-screen.component.html | 6 +++- .../project-overview-screen.component.scss | 4 +++ .../red-ui/src/app/state/app-state.service.ts | 19 +++++++++++- apps/red-ui/src/assets/i18n/en.json | 7 +++-- libs/red-ui-http/src/lib/model/fileStatus.ts | 26 +++++++++-------- 15 files changed, 118 insertions(+), 46 deletions(-) diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.html b/apps/red-ui/src/app/components/document-info/document-info.component.html index 69608ee31..aafddbd4f 100644 --- a/apps/red-ui/src/app/components/document-info/document-info.component.html +++ b/apps/red-ui/src/app/components/document-info/document-info.component.html @@ -2,7 +2,7 @@
@@ -17,7 +17,10 @@
- 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 +
+
{{ attr.label }}:
+
{{ file.fileAttributes.attributeIdToValue[attr.id] || '-' }}
+
diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.scss b/apps/red-ui/src/app/components/document-info/document-info.component.scss index ee9825e39..0a3a68fc2 100644 --- a/apps/red-ui/src/app/components/document-info/document-info.component.scss +++ b/apps/red-ui/src/app/components/document-info/document-info.component.scss @@ -46,3 +46,13 @@ border-bottom: 1px solid $separator; } } + +.attribute { + > .small-label { + margin-bottom: 6px; + } + + &:not(:last-child) { + margin-bottom: 16px; + } +} diff --git a/apps/red-ui/src/app/components/document-info/document-info.component.ts b/apps/red-ui/src/app/components/document-info/document-info.component.ts index d17f725ce..aea583951 100644 --- a/apps/red-ui/src/app/components/document-info/document-info.component.ts +++ b/apps/red-ui/src/app/components/document-info/document-info.component.ts @@ -1,6 +1,7 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { FileStatus } from '@redaction/red-ui-http'; +import { FileAttributeConfig, FileAttributesControllerService, FileStatus } from '@redaction/red-ui-http'; import { AppStateService } from '../../state/app-state.service'; +import { DialogService } from '../../dialogs/dialog.service'; @Component({ selector: 'redaction-document-info', @@ -11,11 +12,23 @@ export class DocumentInfoComponent implements OnInit { @Input() file: FileStatus; @Output() closeDocumentInfoView = new EventEmitter(); - constructor(private _appStateService: AppStateService) {} + public fileAttributesConfig: FileAttributeConfig[]; + + constructor( + private readonly _appStateService: AppStateService, + private readonly _fileAttributesService: FileAttributesControllerService, + private readonly _dialogService: DialogService + ) { + this.fileAttributesConfig = this._appStateService.fileAttributesConfig.filter((attr) => attr.visible); + } ngOnInit(): void {} public get project() { return this._appStateService.getProjectById(this.file.projectId); } + + public edit() { + this._dialogService.openDocumentInfoDialog(this.file); + } } diff --git a/apps/red-ui/src/app/components/project-details/project-details.component.html b/apps/red-ui/src/app/components/project-details/project-details.component.html index 035acb908..6c27d7bc5 100644 --- a/apps/red-ui/src/app/components/project-details/project-details.component.html +++ b/apps/red-ui/src/app/components/project-details/project-details.component.html @@ -58,7 +58,7 @@
-
+
{{ 'project-overview.project-details.stats.documents' | translate: { count: appStateService.activeProject.files.length } }} diff --git a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html index 1f407e450..52179a7da 100644 --- a/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html +++ b/apps/red-ui/src/app/dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.html @@ -10,9 +10,23 @@
+
+ + +
+
{{ 'add-edit-file-attribute.form.read-only' | translate }}
+ +
+ {{ 'add-edit-file-attribute.form.visible' | translate }} +
- + rs.ruleSetId === id); } + public get fileAttributesConfig(): FileAttributeConfig[] { + return this._appState.activeFileAttributesConfig; + } + get activeDictionaryType(): string { return this._appState.activeDictionaryType; } @@ -306,8 +315,16 @@ export class AppStateService { this._appState.activeProjectId = projectId; if (!this.activeProject) { this._appState.activeProjectId = null; + this._appState.activeFileAttributesConfig = []; this._router.navigate(['/ui/projects']); + return; } + this._fileAttributesService + .getFileAttributesConfiguration(this.getProjectById(projectId).ruleSetId) + .toPromise() + .then((data) => { + this._appState.activeFileAttributesConfig = data.fileAttributeConfigs; + }); } activateFile(projectId: string, fileId: string) { diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 07b4df286..f2fd499d4 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -604,7 +604,10 @@ "form": { "name": "Attribute Name", "name-placeholder": "Enter Name", - "read-only": "Make Read-Only" + "column-header": "CSV Column Header", + "column-header-placeholder": "Enter CSV Column Header", + "read-only": "Make Read-Only", + "visible": "Visible in Document Info" }, "save": "Save Attribute" }, @@ -746,7 +749,7 @@ "checkbox-2": "All inputted details on the documents will be lost" }, "document-info": { - "title": "Introduce Document Info", + "title": "Introduce File Attributes", "save": "Save Document Info", "save-approval": "Save and Send for Approval" }, diff --git a/libs/red-ui-http/src/lib/model/fileStatus.ts b/libs/red-ui-http/src/lib/model/fileStatus.ts index 3ca542465..4429e4a45 100644 --- a/libs/red-ui-http/src/lib/model/fileStatus.ts +++ b/libs/red-ui-http/src/lib/model/fileStatus.ts @@ -9,15 +9,12 @@ * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. */ +import { FileAttributes } from './fileAttributes'; /** * Object containing information on a specific file. */ export interface FileStatus { - /** - * Time of last analysis - */ - analysisDuration?: number; /** * Date and time when the file was added to the system. */ @@ -26,6 +23,10 @@ export interface FileStatus { * Shows if all manual changes have been applied by a reanalysis. */ allManualRedactionsApplied?: boolean; + /** + * Shows how long the last analysis took + */ + analysisDuration?: number; /** * Shows the date of approval, if approved. */ @@ -38,6 +39,7 @@ export interface FileStatus { * Shows which dictionary versions was used during the analysis. */ dictionaryVersion?: number; + fileAttributes?: FileAttributes; /** * The ID of the file. */ @@ -50,6 +52,10 @@ export interface FileStatus { * Shows if any hints were found during the analysis. */ hasHints?: boolean; + /** + * Shows if any images were found during the analysis. + */ + hasImages?: boolean; /** * Shows if any redactions were found during the analysis. */ @@ -58,6 +64,10 @@ export interface FileStatus { * Shows if any requests were found during the analysis. */ hasRequests?: boolean; + /** + * Shows if there is any change between the previous and current analysis. + */ + hasUpdates?: boolean; /** * Shows the last date of a successful analysis. */ @@ -78,14 +88,6 @@ export interface FileStatus { * The number of times the file has been analyzed. */ numberOfAnalyses?: number; - /** - * Shows if any images were found during the analysis. - */ - hasImages?: boolean; - /** - * Shows if there is any change between the previous and current analysis. - */ - hasUpdates?: boolean; /** * The number of pages of the file. */