diff --git a/.editorconfig b/.editorconfig index 4a2be7a8c..92c6e7b4b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,7 +8,11 @@ indent_size = 4 insert_final_newline = true trim_trailing_whitespace = true ij_html_quote_style = double +max_line_length = 100 [*.md] max_line_length = off trim_trailing_whitespace = false + +[{*.json, .prettierrc, .eslintrc}] +indent_size = 2 diff --git a/.eslintrc.json b/.eslintrc.json index e3fb306bc..2b9f0ef98 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,182 +1,190 @@ { - "root": true, - "ignorePatterns": ["**/*"], - "plugins": ["@nrwl/nx"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": { - "@nrwl/nx/enforce-module-boundaries": [ - "error", - { - "enforceBuildableLibDependency": true, - "allow": [], - "depConstraints": [ - { - "sourceTag": "*", - "onlyDependOnLibsWithTags": ["*"] - } - ] - } - ] - } - }, - { - "files": ["*.ts", "*.tsx"], - "extends": ["plugin:@nrwl/nx/typescript"], - "rules": {} - }, - { - "files": ["*.js", "*.jsx"], - "extends": ["plugin:@nrwl/nx/javascript"], - "rules": {} - }, - { - "files": ["*.ts"], - "rules": { - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "app", - "style": "kebab-case" - } - ], - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "app", - "style": "camelCase" - } - ], - "@angular-eslint/no-conflicting-lifecycle": "error", - "@angular-eslint/no-host-metadata-property": "error", - "@angular-eslint/no-input-rename": "error", - "@angular-eslint/no-inputs-metadata-property": "error", - "@angular-eslint/no-output-native": "error", - "@angular-eslint/no-output-on-prefix": "error", - "@angular-eslint/no-output-rename": "error", - "@angular-eslint/no-outputs-metadata-property": "error", - "@angular-eslint/use-lifecycle-interface": "error", - "@angular-eslint/use-pipe-transform-interface": "error", - "@typescript-eslint/consistent-type-definitions": "error", - "@typescript-eslint/dot-notation": "off", - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/ban-types": "off", - "@typescript-eslint/explicit-member-accessibility": [ - "warn", - { - "accessibility": "no-public" - } - ], - "@typescript-eslint/member-ordering": "error", - "@typescript-eslint/naming-convention": [ - "error", - { - "selector": "memberLike", - "modifiers": ["readonly"], - "format": ["UPPER_CASE", "camelCase"] - }, - { - "selector": "enumMember", - "format": ["UPPER_CASE"] - }, - { - "selector": "memberLike", - "modifiers": ["private"], - "format": ["camelCase"], - "leadingUnderscore": "require" - }, - { - "selector": "memberLike", - "modifiers": ["protected"], - "format": ["camelCase"], - "leadingUnderscore": "require" - }, - { - "selector": "memberLike", - "modifiers": ["private", "readonly"], - "format": ["UPPER_CASE", "camelCase"], - "leadingUnderscore": "require" - } - ], - "@typescript-eslint/no-empty-function": "off", - "@typescript-eslint/no-empty-interface": "error", - "@typescript-eslint/no-inferrable-types": [ - "error", - { - "ignoreParameters": true - } - ], - "@typescript-eslint/no-misused-new": "error", - "@typescript-eslint/no-non-null-assertion": "error", - "@typescript-eslint/no-shadow": [ - "error", - { - "hoist": "all" - } - ], - "@typescript-eslint/no-unused-expressions": "error", - "@typescript-eslint/prefer-function-type": "error", - "@typescript-eslint/unified-signatures": "error", - "arrow-body-style": "error", - "constructor-super": "error", - "eqeqeq": ["error", "smart"], - "guard-for-in": "error", - "id-blacklist": "off", - "id-match": "off", - "import/no-deprecated": "warn", - "no-bitwise": "error", - "no-caller": "error", - "no-console": [ - "error", - { - "allow": [ - "log", - "warn", - "dir", - "timeLog", - "assert", - "clear", - "count", - "countReset", - "group", - "groupEnd", - "table", - "dirxml", - "error", - "groupCollapsed", - "Console", - "profile", - "profileEnd", - "timeStamp", - "context" - ] - } - ], - "no-debugger": "error", - "no-empty": "off", - "no-eval": "error", - "no-fallthrough": "error", - "no-new-wrappers": "error", - "no-restricted-imports": ["error", "rxjs/Rx"], - "no-throw-literal": "error", - "no-undef-init": "error", - "no-underscore-dangle": "off", - "no-var": "error", - "prefer-const": "error", - "radix": "error" - }, - "plugins": ["eslint-plugin-import", "@angular-eslint/eslint-plugin", "@typescript-eslint"] - }, - { - "files": ["*.html"], - "rules": { - "@angular-eslint/template/banana-in-box": "error", - "@angular-eslint/template/no-negated-async": "error" - }, - "plugins": ["@angular-eslint/eslint-plugin-template"] - } - ] + "root": true, + "ignorePatterns": ["**/*"], + "plugins": ["@nrwl/nx"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], + "rules": { + "@nrwl/nx/enforce-module-boundaries": [ + "error", + { + "enforceBuildableLibDependency": true, + "allow": [], + "depConstraints": [ + { + "sourceTag": "*", + "onlyDependOnLibsWithTags": ["*"] + } + ] + } + ] + } + }, + { + "files": ["*.ts", "*.tsx"], + "extends": ["plugin:@nrwl/nx/typescript"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "extends": ["plugin:@nrwl/nx/javascript"], + "rules": {} + }, + { + "files": ["*.ts"], + "rules": { + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "app", + "style": "kebab-case" + } + ], + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "app", + "style": "camelCase" + } + ], + "@angular-eslint/no-conflicting-lifecycle": "error", + "@angular-eslint/no-host-metadata-property": "error", + "@angular-eslint/no-input-rename": "error", + "@angular-eslint/no-inputs-metadata-property": "error", + "@angular-eslint/no-output-native": "error", + "@angular-eslint/no-output-on-prefix": "error", + "@angular-eslint/no-output-rename": "error", + "@angular-eslint/no-outputs-metadata-property": "error", + "@angular-eslint/use-lifecycle-interface": "error", + "@angular-eslint/use-pipe-transform-interface": "error", + "@typescript-eslint/consistent-type-definitions": "error", + "@typescript-eslint/dot-notation": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-types": "off", + "@typescript-eslint/explicit-member-accessibility": [ + "warn", + { + "accessibility": "no-public" + } + ], + "@typescript-eslint/member-ordering": "error", + "@typescript-eslint/naming-convention": [ + "error", + { + "selector": "memberLike", + "modifiers": ["readonly"], + "format": ["UPPER_CASE", "camelCase"] + }, + { + "selector": "enumMember", + "format": ["UPPER_CASE"] + }, + { + "selector": "memberLike", + "modifiers": ["private"], + "format": ["camelCase"], + "leadingUnderscore": "require" + }, + { + "selector": "memberLike", + "modifiers": ["protected"], + "format": ["camelCase"], + "leadingUnderscore": "require" + }, + { + "selector": "memberLike", + "modifiers": ["private", "readonly"], + "format": ["UPPER_CASE", "camelCase"], + "leadingUnderscore": "require" + } + ], + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-empty-interface": "error", + "@typescript-eslint/no-inferrable-types": [ + "error", + { + "ignoreParameters": true + } + ], + "@typescript-eslint/no-misused-new": "error", + "@typescript-eslint/no-non-null-assertion": "error", + "@typescript-eslint/no-shadow": [ + "error", + { + "hoist": "all" + } + ], + "@typescript-eslint/no-unused-expressions": "error", + "@typescript-eslint/prefer-function-type": "error", + "@typescript-eslint/unified-signatures": "error", + "arrow-body-style": "error", + "constructor-super": "error", + "eqeqeq": ["error", "smart"], + "guard-for-in": "error", + "id-blacklist": "off", + "id-match": "off", + "import/no-deprecated": "warn", + "no-bitwise": "error", + "no-caller": "error", + "no-console": [ + "error", + { + "allow": [ + "log", + "warn", + "dir", + "timeLog", + "assert", + "clear", + "count", + "countReset", + "group", + "groupEnd", + "table", + "dirxml", + "error", + "groupCollapsed", + "Console", + "profile", + "profileEnd", + "timeStamp", + "context" + ] + } + ], + "no-debugger": "error", + "no-empty": "off", + "no-eval": "error", + "no-fallthrough": "error", + "no-new-wrappers": "error", + "no-restricted-imports": ["error", "rxjs/Rx"], + "no-throw-literal": "error", + "no-undef-init": "error", + "no-underscore-dangle": "off", + "no-var": "error", + "prefer-const": "error", + "radix": "error", + "max-len": [ + "error", + { + "code": 100, + "tabWidth": 4, + "ignorePattern": "^import .*" + } + ] + }, + "plugins": ["eslint-plugin-import", "@angular-eslint/eslint-plugin", "@typescript-eslint"] + }, + { + "files": ["*.html"], + "rules": { + "@angular-eslint/template/banana-in-box": "error", + "@angular-eslint/template/no-negated-async": "error" + }, + "plugins": ["@angular-eslint/eslint-plugin-template"] + } + ] } diff --git a/.prettierignore b/.prettierignore index d0b804da2..62d06f966 100644 --- a/.prettierignore +++ b/.prettierignore @@ -2,3 +2,5 @@ /dist /coverage +/node_modules +/bamboo-specs diff --git a/.prettierrc b/.prettierrc index d23118991..6a8dd18db 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,6 +1,6 @@ { "useTabs": false, - "printWidth": 160, + "printWidth": 100, "tabWidth": 4, "singleQuote": true, "trailingComma": "none", @@ -10,6 +10,12 @@ "options": { "parser": "angular" } + }, + { + "files": ["*.json"], + "options": { + "tabWidth": 2 + } } ] } diff --git a/angular.json b/angular.json index 4109803d4..44a3ef9c5 100644 --- a/angular.json +++ b/angular.json @@ -1,194 +1,195 @@ { - "version": 1, - "cli": { - "defaultCollection": "@nrwl/angular", - "analytics": false, - "packageManager": "yarn" + "$schema": "node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "cli": { + "defaultCollection": "@nrwl/angular", + "analytics": false, + "packageManager": "yarn" + }, + "defaultProject": "red-ui", + "schematics": { + "@nrwl/angular:application": { + "unitTestRunner": "jest", + "e2eTestRunner": "cypress" }, - "defaultProject": "red-ui", - "schematics": { - "@nrwl/angular:application": { - "unitTestRunner": "jest", - "e2eTestRunner": "cypress" - }, - "@nrwl/angular:library": { - "unitTestRunner": "jest" - } - }, - "projects": { - "red-ui": { - "projectType": "application", - "schematics": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "root": "apps/red-ui", - "sourceRoot": "apps/red-ui/src", - "prefix": "redaction", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:browser", - "options": { - "outputPath": "dist/apps/red-ui", - "index": "apps/red-ui/src/index.html", - "main": "apps/red-ui/src/main.ts", - "polyfills": "apps/red-ui/src/polyfills.ts", - "tsConfig": "apps/red-ui/tsconfig.app.json", - "aot": true, - "assets": [ - "apps/red-ui/src/favicon.ico", - { - "glob": "**/*", - "input": "node_modules/@pdftron/webviewer/public/", - "output": "/assets/wv-resources/" - }, - { - "glob": "**/*", - "input": "apps/red-ui/src/assets/", - "output": "/assets/" - }, - { - "glob": "**/*", - "input": "node_modules/ace-builds/src-min/", - "output": "/assets/ace-builds" - }, - "apps/red-ui/src/manifest.webmanifest" - ], - "styles": ["apps/red-ui/src/styles.scss"], - "scripts": [ - "node_modules/@pdftron/webviewer/webviewer.min.js", - "node_modules/ace-builds/src-min/ace.js", - "node_modules/ace-builds/src-min/mode-java.js", - "node_modules/ace-builds/src-min/theme-eclipse.js" - ] - }, - "configurations": { - "production": { - "fileReplacements": [ - { - "replace": "apps/red-ui/src/environments/environment.ts", - "with": "apps/red-ui/src/environments/environment.prod.ts" - } - ], - "optimization": true, - "outputHashing": "all", - "sourceMap": false, - "namedChunks": false, - "extractLicenses": true, - "vendorChunk": false, - "buildOptimizer": true, - "budgets": [ - { - "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" - } - ], - "serviceWorker": true, - "ngswConfigPath": "apps/red-ui/ngsw-config.json" - } - }, - "outputs": ["{options.outputPath}"] - }, - "serve": { - "builder": "@angular-devkit/build-angular:dev-server", - "options": { - "browserTarget": "red-ui:build" - }, - "configurations": { - "production": { - "browserTarget": "red-ui:build:production" - } - } - }, - "extract-i18n": { - "builder": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "red-ui:build" - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["apps/red-ui/src/**/*.ts", "apps/red-ui/src/**/*.html"] - } - }, - "test": { - "builder": "@nrwl/jest:jest", - "options": { - "jestConfig": "apps/red-ui/jest.config.js", - "passWithNoTests": true - }, - "outputs": ["coverage/apps/red-ui"] - } - } - }, - "red-ui-http": { - "projectType": "library", - "root": "libs/red-ui-http", - "sourceRoot": "libs/red-ui-http/src", - "prefix": "redaction", - "architect": { - "build": { - "builder": "@angular-devkit/build-angular:ng-packagr", - "options": { - "tsConfig": "libs/red-ui-http/tsconfig.lib.json", - "project": "libs/red-ui-http/ng-package.json" - } - }, - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/red-ui-http/src/**/*.ts", "libs/red-ui-http/src/**/*.html"] - } - }, - "test": { - "builder": "@nrwl/jest:jest", - "options": { - "jestConfig": "libs/red-ui-http/jest.config.js", - "passWithNoTests": true - }, - "outputs": ["coverage/libs/red-ui-http"] - } - }, - "schematics": { - "@schematics/angular:component": { - "style": "scss" - } - } - }, - "red-cache": { - "projectType": "library", - "root": "libs/red-cache", - "sourceRoot": "libs/red-cache/src", - "prefix": "redaction", - "architect": { - "lint": { - "builder": "@nrwl/linter:eslint", - "options": { - "lintFilePatterns": ["libs/red-cache/src/**/*.ts", "libs/red-cache/src/**/*.html"] - } - }, - "test": { - "builder": "@nrwl/jest:jest", - "options": { - "jestConfig": "libs/red-cache/jest.config.js", - "passWithNoTests": true - }, - "outputs": ["coverage/libs/red-cache"] - } - }, - "schematics": { - "@schematics/angular:component": { - "style": "scss" - } - } - } + "@nrwl/angular:library": { + "unitTestRunner": "jest" } + }, + "projects": { + "red-ui": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "root": "apps/red-ui", + "sourceRoot": "apps/red-ui/src", + "prefix": "redaction", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/apps/red-ui", + "index": "apps/red-ui/src/index.html", + "main": "apps/red-ui/src/main.ts", + "polyfills": "apps/red-ui/src/polyfills.ts", + "tsConfig": "apps/red-ui/tsconfig.app.json", + "aot": true, + "assets": [ + "apps/red-ui/src/favicon.ico", + { + "glob": "**/*", + "input": "node_modules/@pdftron/webviewer/public/", + "output": "/assets/wv-resources/" + }, + { + "glob": "**/*", + "input": "apps/red-ui/src/assets/", + "output": "/assets/" + }, + { + "glob": "**/*", + "input": "node_modules/ace-builds/src-min/", + "output": "/assets/ace-builds" + }, + "apps/red-ui/src/manifest.webmanifest" + ], + "styles": ["apps/red-ui/src/styles.scss"], + "scripts": [ + "node_modules/@pdftron/webviewer/webviewer.min.js", + "node_modules/ace-builds/src-min/ace.js", + "node_modules/ace-builds/src-min/mode-java.js", + "node_modules/ace-builds/src-min/theme-eclipse.js" + ] + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "apps/red-ui/src/environments/environment.ts", + "with": "apps/red-ui/src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "namedChunks": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ], + "serviceWorker": true, + "ngswConfigPath": "apps/red-ui/ngsw-config.json" + } + }, + "outputs": ["{options.outputPath}"] + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "red-ui:build" + }, + "configurations": { + "production": { + "browserTarget": "red-ui:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "red-ui:build" + } + }, + "lint": { + "builder": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": ["apps/red-ui/src/**/*.ts", "apps/red-ui/src/**/*.html"] + } + }, + "test": { + "builder": "@nrwl/jest:jest", + "options": { + "jestConfig": "apps/red-ui/jest.config.js", + "passWithNoTests": true + }, + "outputs": ["coverage/apps/red-ui"] + } + } + }, + "red-ui-http": { + "projectType": "library", + "root": "libs/red-ui-http", + "sourceRoot": "libs/red-ui-http/src", + "prefix": "redaction", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:ng-packagr", + "options": { + "tsConfig": "libs/red-ui-http/tsconfig.lib.json", + "project": "libs/red-ui-http/ng-package.json" + } + }, + "lint": { + "builder": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": ["libs/red-ui-http/src/**/*.ts", "libs/red-ui-http/src/**/*.html"] + } + }, + "test": { + "builder": "@nrwl/jest:jest", + "options": { + "jestConfig": "libs/red-ui-http/jest.config.js", + "passWithNoTests": true + }, + "outputs": ["coverage/libs/red-ui-http"] + } + }, + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + } + }, + "red-cache": { + "projectType": "library", + "root": "libs/red-cache", + "sourceRoot": "libs/red-cache/src", + "prefix": "redaction", + "architect": { + "lint": { + "builder": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": ["libs/red-cache/src/**/*.ts", "libs/red-cache/src/**/*.html"] + } + }, + "test": { + "builder": "@nrwl/jest:jest", + "options": { + "jestConfig": "libs/red-cache/jest.config.js", + "passWithNoTests": true + }, + "outputs": ["coverage/libs/red-cache"] + } + }, + "schematics": { + "@schematics/angular:component": { + "style": "scss" + } + } + } + } } diff --git a/apps/red-ui/.eslintrc.json b/apps/red-ui/.eslintrc.json index bfaea24bb..4a28d3d82 100644 --- a/apps/red-ui/.eslintrc.json +++ b/apps/red-ui/.eslintrc.json @@ -1,37 +1,40 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": ["plugin:@nrwl/nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], - "parserOptions": { - "project": ["apps/red-ui/tsconfig.*?.json"] - }, - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "redaction", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "redaction", - "style": "kebab-case" - } - ] - }, - "plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nrwl/nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nrwl/nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "parserOptions": { + "project": ["apps/red-ui/tsconfig.*?.json"] + }, + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "redaction", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "redaction", + "style": "kebab-case" + } + ] + }, + "plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nrwl/nx/angular-template"], + "rules": {} + } + ] } diff --git a/apps/red-ui/jest.config.js b/apps/red-ui/jest.config.js index 91536f49b..01f238567 100644 --- a/apps/red-ui/jest.config.js +++ b/apps/red-ui/jest.config.js @@ -4,7 +4,12 @@ module.exports = { globals: { 'ts-jest': { stringifyContentPathRegex: '\\.(html|svg)$', - astTransformers: { before: ['jest-preset-angular/build/InlineFilesTransformer', 'jest-preset-angular/build/StripStylesTransformer'] }, + astTransformers: { + before: [ + 'jest-preset-angular/build/InlineFilesTransformer', + 'jest-preset-angular/build/StripStylesTransformer' + ] + }, tsconfig: '/tsconfig.spec.json' } }, diff --git a/apps/red-ui/ngsw-config.json b/apps/red-ui/ngsw-config.json index 3e250575f..5b78c22f4 100644 --- a/apps/red-ui/ngsw-config.json +++ b/apps/red-ui/ngsw-config.json @@ -1,21 +1,21 @@ { - "$schema": "../../node_modules/@angular/service-worker/config/schema.json", - "index": "/index.html", - "assetGroups": [ - { - "name": "app", - "installMode": "prefetch", - "resources": { - "files": ["/favicon.ico", "/index.html", "/manifest.webmanifest", "/*.css", "/*.js"] - } - }, - { - "name": "assets", - "installMode": "lazy", - "updateMode": "prefetch", - "resources": { - "files": ["/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"] - } - } - ] + "$schema": "../../node_modules/@angular/service-worker/config/schema.json", + "index": "/index.html", + "assetGroups": [ + { + "name": "app", + "installMode": "prefetch", + "resources": { + "files": ["/favicon.ico", "/index.html", "/manifest.webmanifest", "/*.css", "/*.js"] + } + }, + { + "name": "assets", + "installMode": "lazy", + "updateMode": "prefetch", + "resources": { + "files": ["/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"] + } + } + ] } diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts index 737cf6a86..d950c8d82 100644 --- a/apps/red-ui/src/app/app-routing.module.ts +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -43,7 +43,8 @@ const routes = [ { path: 'main/projects', component: BaseScreenComponent, - loadChildren: () => import('./modules/projects/projects.module').then((m) => m.ProjectsModule) + loadChildren: () => + import('./modules/projects/projects.module').then((m) => m.ProjectsModule) }, { path: 'main/downloads', diff --git a/apps/red-ui/src/app/app.component.html b/apps/red-ui/src/app/app.component.html index 80f9c88ad..7115e458f 100644 --- a/apps/red-ui/src/app/app.component.html +++ b/apps/red-ui/src/app/app.component.html @@ -1,2 +1,4 @@ - + diff --git a/apps/red-ui/src/app/app.component.ts b/apps/red-ui/src/app/app.component.ts index d916c2840..711e2bffb 100644 --- a/apps/red-ui/src/app/app.component.ts +++ b/apps/red-ui/src/app/app.component.ts @@ -8,5 +8,8 @@ import { RouterHistoryService } from '@services/router-history.service'; styleUrls: ['./app.component.scss'] }) export class AppComponent { - constructor(public appLoadStateService: AppLoadStateService, private readonly _routerHistoryService: RouterHistoryService) {} + constructor( + public appLoadStateService: AppLoadStateService, + private readonly _routerHistoryService: RouterHistoryService + ) {} } diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index 7313a7497..3b5d314a6 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -47,7 +47,14 @@ function cleanupBaseUrl(baseUrl: string) { const screens = [BaseScreenComponent, DownloadsListScreenComponent, UserProfileScreenComponent]; -const components = [AppComponent, LogoComponent, AuthErrorComponent, ToastComponent, NotificationsComponent, ...screens]; +const components = [ + AppComponent, + LogoComponent, + AuthErrorComponent, + ToastComponent, + NotificationsComponent, + ...screens +]; @NgModule({ declarations: [...components], @@ -113,7 +120,11 @@ export class AppModule { private _configureKeyCloakRouteHandling() { this._route.queryParamMap.subscribe((queryParams) => { - if (queryParams.has('code') || queryParams.has('state') || queryParams.has('session_state')) { + if ( + queryParams.has('code') || + queryParams.has('state') || + queryParams.has('session_state') + ) { this._router.navigate([], { queryParams: { state: null, diff --git a/apps/red-ui/src/app/components/auth-error/auth-error.component.html b/apps/red-ui/src/app/components/auth-error/auth-error.component.html index a3d625205..f397401ee 100644 --- a/apps/red-ui/src/app/components/auth-error/auth-error.component.html +++ b/apps/red-ui/src/app/components/auth-error/auth-error.component.html @@ -1,8 +1,15 @@
-

+

- - + -

- + diff --git a/apps/red-ui/src/app/guards/can-deactivate.guard.ts b/apps/red-ui/src/app/guards/can-deactivate.guard.ts index 401591a4e..b92aabb6c 100644 --- a/apps/red-ui/src/app/guards/can-deactivate.guard.ts +++ b/apps/red-ui/src/app/guards/can-deactivate.guard.ts @@ -30,8 +30,10 @@ export class PendingChangesGuard implements CanDeactivate { this._appLoadStateService.pushLoadingEvent(true); @@ -21,7 +31,10 @@ export class CompositeRouteGuard implements CanActivate { if (canActivateResult instanceof Promise) { canActivateResult = from(canActivateResult); } - if (typeof canActivateResult === 'boolean' || canActivateResult instanceof UrlTree) { + if ( + typeof canActivateResult === 'boolean' || + canActivateResult instanceof UrlTree + ) { canActivateResult = of(canActivateResult); } diff --git a/apps/red-ui/src/app/models/file/annotation.permissions.ts b/apps/red-ui/src/app/models/file/annotation.permissions.ts index eee7f8890..91077d613 100644 --- a/apps/red-ui/src/app/models/file/annotation.permissions.ts +++ b/apps/red-ui/src/app/models/file/annotation.permissions.ts @@ -30,22 +30,34 @@ export class AnnotationPermissions { const permissions: AnnotationPermissions = new AnnotationPermissions(); permissions.canUndo = - annotation.isUndoableSuperType && (annotation.userId === user.id || (annotation.userId && isApprover && !annotation.isSuggestion)); + annotation.isUndoableSuperType && + (annotation.userId === user.id || + (annotation.userId && isApprover && !annotation.isSuggestion)); permissions.canForceRedaction = annotation.isSkipped && !permissions.canUndo; permissions.canAcceptRecommendation = annotation.isRecommendation; - permissions.canMarkAsFalsePositive = annotation.canBeMarkedAsFalsePositive && !annotation.force; - permissions.canMarkTextOnlyAsFalsePositive = annotation.canBeMarkedAsFalsePositiveWithTextOnly && !annotation.force; + permissions.canMarkAsFalsePositive = + annotation.canBeMarkedAsFalsePositive && !annotation.force; + permissions.canMarkTextOnlyAsFalsePositive = + annotation.canBeMarkedAsFalsePositiveWithTextOnly && !annotation.force; permissions.canRemoveOrSuggestToRemoveOnlyHere = annotation.isRedacted && !annotation.force; permissions.canRemoveOrSuggestToRemoveFromDictionary = - annotation.isRedacted && !annotation.isManualRedaction && annotation.isModifyDictionary && !annotation.force; + annotation.isRedacted && + !annotation.isManualRedaction && + annotation.isModifyDictionary && + !annotation.force; - permissions.canAcceptSuggestion = isApprover && (annotation.isSuggestion || annotation.isDeclinedSuggestion); + permissions.canAcceptSuggestion = + isApprover && (annotation.isSuggestion || annotation.isDeclinedSuggestion); permissions.canRejectSuggestion = - isApprover && (annotation.isSuggestion || (annotation.isReadyForAnalysis && !permissions.canUndo && annotation.superType !== 'pending-analysis')); + isApprover && + (annotation.isSuggestion || + (annotation.isReadyForAnalysis && + !permissions.canUndo && + annotation.superType !== 'pending-analysis')); return permissions; } diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index 6fb4338b6..a851d613a 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -79,15 +79,28 @@ export class AnnotationWrapper { } get canBeMarkedAsFalsePositive() { - return (this.isRecommendation || this.superType === 'redaction') && (this.hasTextAfter || this.hasTextBefore) && !this.isImage; + return ( + (this.isRecommendation || this.superType === 'redaction') && + (this.hasTextAfter || this.hasTextBefore) && + !this.isImage + ); } get canBeMarkedAsFalsePositiveWithTextOnly() { - return !this.canBeMarkedAsFalsePositive && (this.isRecommendation || this.superType === 'redaction') && !this.isImage; + return ( + !this.canBeMarkedAsFalsePositive && + (this.isRecommendation || this.superType === 'redaction') && + !this.isImage + ); } get isSuperTypeBasedColor() { - return this.isSkipped || this.isSuggestion || this.isReadyForAnalysis || this.isDeclinedSuggestion; + return ( + this.isSkipped || + this.isSuggestion || + this.isReadyForAnalysis || + this.isDeclinedSuggestion + ); } get isSkipped() { @@ -104,7 +117,10 @@ export class AnnotationWrapper { get isFalsePositive() { return ( - this.dictionary?.toLowerCase() === 'false_positive' && (this.superType === 'skipped' || this.superType === 'hint' || this.superType === 'redaction') + this.dictionary?.toLowerCase() === 'false_positive' && + (this.superType === 'skipped' || + this.superType === 'hint' || + this.superType === 'redaction') ); } @@ -142,11 +158,18 @@ export class AnnotationWrapper { } get isSuggestionAdd() { - return this.superType === 'suggestion-add' || this.superType === 'suggestion-add-dictionary' || this.superType === 'suggestion-force-redaction'; + return ( + this.superType === 'suggestion-add' || + this.superType === 'suggestion-add-dictionary' || + this.superType === 'suggestion-force-redaction' + ); } get isSuggestionRemove() { - return this.superType === 'suggestion-remove' || this.superType === 'suggestion-remove-dictionary'; + return ( + this.superType === 'suggestion-remove' || + this.superType === 'suggestion-remove-dictionary' + ); } get isModifyDictionary() { @@ -154,7 +177,10 @@ export class AnnotationWrapper { } get isConvertedRecommendation() { - return this.isRecommendation && (this.superType === 'suggestion-add-dictionary' || this.superType === 'add-dictionary'); + return ( + this.isRecommendation && + (this.superType === 'suggestion-add-dictionary' || this.superType === 'add-dictionary') + ); } get isRecommendation() { @@ -203,13 +229,21 @@ export class AnnotationWrapper { return annotationWrapper; } - private static _handleRecommendations(annotationWrapper: AnnotationWrapper, redactionLogEntry: RedactionLogEntryWrapper) { + private static _handleRecommendations( + annotationWrapper: AnnotationWrapper, + redactionLogEntry: RedactionLogEntryWrapper + ) { if (annotationWrapper.superType === 'recommendation') { - annotationWrapper.recommendationType = redactionLogEntry.type.substr('recommendation_'.length); + annotationWrapper.recommendationType = redactionLogEntry.type.substr( + 'recommendation_'.length + ); } } - private static _setSuperType(annotationWrapper: AnnotationWrapper, redactionLogEntryWrapper: RedactionLogEntryWrapper) { + private static _setSuperType( + annotationWrapper: AnnotationWrapper, + redactionLogEntryWrapper: RedactionLogEntryWrapper + ) { if (redactionLogEntryWrapper.recommendation) { if (redactionLogEntryWrapper.redacted) { annotationWrapper.superType = 'recommendation'; @@ -235,23 +269,40 @@ export class AnnotationWrapper { } else { if (redactionLogEntryWrapper.redacted) { if (redactionLogEntryWrapper.force) { - annotationWrapper.superType = redactionLogEntryWrapper.status === 'REQUESTED' ? 'suggestion-add' : 'redaction'; + annotationWrapper.superType = + redactionLogEntryWrapper.status === 'REQUESTED' + ? 'suggestion-add' + : 'redaction'; } else if (redactionLogEntryWrapper.type === 'manual') { - annotationWrapper.superType = redactionLogEntryWrapper.status === 'REQUESTED' ? 'suggestion-add' : 'manual-redaction'; + annotationWrapper.superType = + redactionLogEntryWrapper.status === 'REQUESTED' + ? 'suggestion-add' + : 'manual-redaction'; } else { if (redactionLogEntryWrapper.status === 'REQUESTED') { if (redactionLogEntryWrapper.dictionaryEntry) { annotationWrapper.superType = - redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'suggestion-add-dictionary' : 'suggestion-remove-dictionary'; + redactionLogEntryWrapper.manualRedactionType === 'ADD' + ? 'suggestion-add-dictionary' + : 'suggestion-remove-dictionary'; } else { - annotationWrapper.superType = redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'suggestion-add' : 'suggestion-remove'; + annotationWrapper.superType = + redactionLogEntryWrapper.manualRedactionType === 'ADD' + ? 'suggestion-add' + : 'suggestion-remove'; } } if (redactionLogEntryWrapper.status === 'APPROVED') { if (redactionLogEntryWrapper.dictionaryEntry) { - annotationWrapper.superType = redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'add-dictionary' : 'remove-dictionary'; + annotationWrapper.superType = + redactionLogEntryWrapper.manualRedactionType === 'ADD' + ? 'add-dictionary' + : 'remove-dictionary'; } else { - annotationWrapper.superType = redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'manual-redaction' : 'remove-only-here'; + annotationWrapper.superType = + redactionLogEntryWrapper.manualRedactionType === 'ADD' + ? 'manual-redaction' + : 'remove-only-here'; } } } @@ -259,14 +310,24 @@ export class AnnotationWrapper { } if (!annotationWrapper.superType) { - annotationWrapper.superType = annotationWrapper.redaction ? 'redaction' : annotationWrapper.hint ? 'hint' : 'skipped'; + annotationWrapper.superType = annotationWrapper.redaction + ? 'redaction' + : annotationWrapper.hint + ? 'hint' + : 'skipped'; } } - private static _handleSkippedState(annotationWrapper: AnnotationWrapper, redactionLogEntryWrapper: RedactionLogEntryWrapper) { + private static _handleSkippedState( + annotationWrapper: AnnotationWrapper, + redactionLogEntryWrapper: RedactionLogEntryWrapper + ) { if (annotationWrapper.superType === 'skipped') { if (!annotationWrapper.userId) { - if (redactionLogEntryWrapper.manualRedactionType === 'REMOVE' || redactionLogEntryWrapper.manualRedactionType === 'UNDO') { + if ( + redactionLogEntryWrapper.manualRedactionType === 'REMOVE' || + redactionLogEntryWrapper.manualRedactionType === 'UNDO' + ) { annotationWrapper.superType = 'pending-analysis'; return; } @@ -283,7 +344,10 @@ export class AnnotationWrapper { } } - private static _createContent(annotationWrapper: AnnotationWrapper, entry: RedactionLogEntryWrapper) { + private static _createContent( + annotationWrapper: AnnotationWrapper, + entry: RedactionLogEntryWrapper + ) { let content = ''; if (entry.matchedRule) { content += 'Rule ' + entry.matchedRule + ' matched \n\n'; diff --git a/apps/red-ui/src/app/models/file/file-data.model.ts b/apps/red-ui/src/app/models/file/file-data.model.ts index f4b00dc77..6492c7699 100644 --- a/apps/red-ui/src/app/models/file/file-data.model.ts +++ b/apps/red-ui/src/app/models/file/file-data.model.ts @@ -33,7 +33,12 @@ export class FileDataModel { return this.redactionLog.redactionLogEntry; } - getAnnotations(dictionaryData: { [p: string]: TypeValue }, currentUser: UserWrapper, viewMode: ViewMode, areDevFeaturesEnabled: boolean): AnnotationData { + getAnnotations( + dictionaryData: { [p: string]: TypeValue }, + currentUser: UserWrapper, + viewMode: ViewMode, + areDevFeaturesEnabled: boolean + ): AnnotationData { const entries: RedactionLogEntryWrapper[] = this._convertData(dictionaryData); let allAnnotations = entries.map((entry) => AnnotationWrapper.fromData(entry)); @@ -70,11 +75,14 @@ export class FileDataModel { return; } - const redactionLogEntryWrapper: RedactionLogEntryWrapper = { actionPendingReanalysis: false }; + const redactionLogEntryWrapper: RedactionLogEntryWrapper = { + actionPendingReanalysis: false + }; Object.assign(redactionLogEntryWrapper, changeLogEntry); - redactionLogEntryWrapper.comments = this.manualRedactions.comments[redactionLogEntryWrapper.id]; + redactionLogEntryWrapper.comments = + this.manualRedactions.comments[redactionLogEntryWrapper.id]; redactionLogEntryWrapper.isChangeLogEntry = true; redactionLogEntryWrapper.changeLogType = changeLogEntry.changeType; redactionLogEntryWrapper.id = 'changed-log-removed-' + redactionLogEntryWrapper.id; @@ -88,12 +96,17 @@ export class FileDataModel { return; } - const existingChangeLogEntry = this.redactionChangeLog?.redactionLogEntry?.find((rle) => rle.id === redactionLogEntry.id); + const existingChangeLogEntry = this.redactionChangeLog?.redactionLogEntry?.find( + (rle) => rle.id === redactionLogEntry.id + ); // copy the redactionLog Entry - const redactionLogEntryWrapper: RedactionLogEntryWrapper = { actionPendingReanalysis: false }; + const redactionLogEntryWrapper: RedactionLogEntryWrapper = { + actionPendingReanalysis: false + }; Object.assign(redactionLogEntryWrapper, redactionLogEntry); - redactionLogEntryWrapper.comments = this.manualRedactions.comments[redactionLogEntryWrapper.id]; + redactionLogEntryWrapper.comments = + this.manualRedactions.comments[redactionLogEntryWrapper.id]; redactionLogEntryWrapper.isChangeLogEntry = !!existingChangeLogEntry; redactionLogEntryWrapper.changeLogType = 'ADDED'; result.push(redactionLogEntryWrapper); @@ -117,7 +130,10 @@ export class FileDataModel { relevantRedactionLogEntry.force = true; // if statuses differ - if (!forceRedaction.processedDate || forceRedaction.status !== relevantRedactionLogEntry.status) { + if ( + !forceRedaction.processedDate || + forceRedaction.status !== relevantRedactionLogEntry.status + ) { relevantRedactionLogEntry.actionPendingReanalysis = true; relevantRedactionLogEntry.status = forceRedaction.status; } @@ -152,7 +168,8 @@ export class FileDataModel { relevantRedactionLogEntry.status = manual.status; } } else { - // dictionary modifying requests that have been processed already updated the dictionary and should not be drawn + // dictionary modifying requests that have been processed already updated + // the dictionary and should not be drawn if (manual.addToDictionary && this._hasAlreadyBeenProcessed(manual)) { return; } @@ -175,9 +192,11 @@ export class FileDataModel { redactionLogEntryWrapper.hint = dictionary.hint; redactionLogEntryWrapper.manualRedactionType = 'ADD'; redactionLogEntryWrapper.manual = true; - redactionLogEntryWrapper.comments = this.manualRedactions.comments[redactionLogEntryWrapper.id]; + redactionLogEntryWrapper.comments = + this.manualRedactions.comments[redactionLogEntryWrapper.id]; if (markedAsReasonRedactionLogEntry) { - // cleanup reason if the reason is another annotationId - it is not needed for drawing + // cleanup reason if the reason is another annotationId + // it is not needed for drawing redactionLogEntryWrapper.reason = null; } @@ -212,14 +231,18 @@ export class FileDataModel { result.forEach((redactionLogEntry) => { if (redactionLogEntry.manual) { if (redactionLogEntry.manualRedactionType === 'ADD') { - const foundManualEntry = this.manualRedactions.entriesToAdd.find((me) => me.id === redactionLogEntry.id); + const foundManualEntry = this.manualRedactions.entriesToAdd.find( + (me) => me.id === redactionLogEntry.id + ); // ADD has been undone - not yet processed if (!foundManualEntry) { redactionLogEntry.hidden = true; } } if (redactionLogEntry.manualRedactionType === 'REMOVE') { - const foundManualEntry = this.manualRedactions.idsToRemove.find((me) => me.id === redactionLogEntry.id); + const foundManualEntry = this.manualRedactions.idsToRemove.find( + (me) => me.id === redactionLogEntry.id + ); // REMOVE has been undone - not yet processed if (!foundManualEntry) { redactionLogEntry.manual = false; @@ -236,6 +259,9 @@ export class FileDataModel { } private _hasAlreadyBeenProcessed(entry: ManualRedactionEntry | IdRemoval): boolean { - return !entry.processedDate ? false : new Date(entry.processedDate).getTime() < new Date(this.fileStatus.lastProcessed).getTime(); + return !entry.processedDate + ? false + : new Date(entry.processedDate).getTime() < + new Date(this.fileStatus.lastProcessed).getTime(); } } diff --git a/apps/red-ui/src/app/models/file/file-status.wrapper.ts b/apps/red-ui/src/app/models/file/file-status.wrapper.ts index 5296eee52..79663fae3 100644 --- a/apps/red-ui/src/app/models/file/file-status.wrapper.ts +++ b/apps/red-ui/src/app/models/file/file-status.wrapper.ts @@ -5,11 +5,18 @@ export class FileStatusWrapper { primaryAttribute: string; searchField: string; - constructor(public fileStatus: FileStatus, public reviewerName: string, public ruleSetId: string, fileAttributesConfig?: FileAttributesConfig) { + constructor( + public fileStatus: FileStatus, + public reviewerName: string, + public ruleSetId: string, + fileAttributesConfig?: FileAttributesConfig + ) { this.searchField = fileStatus.filename; if (fileAttributesConfig) { - const primary = fileAttributesConfig.fileAttributeConfigs?.find((c) => c.primaryAttribute); + const primary = fileAttributesConfig.fileAttributeConfigs?.find( + (c) => c.primaryAttribute + ); if (primary && fileStatus.fileAttributes?.attributeIdToValue) { this.primaryAttribute = fileStatus.fileAttributes?.attributeIdToValue[primary.id]; this.searchField += ' ' + this.primaryAttribute; @@ -125,7 +132,9 @@ export class FileStatusWrapper { } get status() { - return this.fileStatus.status === 'REPROCESS' || this.fileStatus.status === 'FULLREPROCESS' ? 'PROCESSING' : this.fileStatus.status; + return this.fileStatus.status === 'REPROCESS' || this.fileStatus.status === 'FULLREPROCESS' + ? 'PROCESSING' + : this.fileStatus.status; } get numberOfPages() { @@ -187,6 +196,8 @@ export class FileStatusWrapper { get newestDate() { const uploadedDate = new Date(this.fileStatus.lastUploaded); const updatedDate = new Date(this.fileStatus.lastUpdated); - return updatedDate && updatedDate.getTime() > uploadedDate.getTime() ? updatedDate : uploadedDate; + return updatedDate && updatedDate.getTime() > uploadedDate.getTime() + ? updatedDate + : uploadedDate; } } diff --git a/apps/red-ui/src/app/models/file/manual-annotation-response.ts b/apps/red-ui/src/app/models/file/manual-annotation-response.ts index c19074328..6902baf78 100644 --- a/apps/red-ui/src/app/models/file/manual-annotation-response.ts +++ b/apps/red-ui/src/app/models/file/manual-annotation-response.ts @@ -5,9 +5,16 @@ export class ManualAnnotationResponse { annotationId; commentId; - constructor(public manualRedactionEntryWrapper: ManualRedactionEntryWrapper, public manualAddResponse: ManualAddResponse) { - this.annotationId = manualAddResponse?.annotationId ? manualAddResponse.annotationId : new Date().getTime(); - this.commentId = manualAddResponse?.commentId ? manualAddResponse.commentId : new Date().getTime(); + constructor( + public manualRedactionEntryWrapper: ManualRedactionEntryWrapper, + public manualAddResponse: ManualAddResponse + ) { + this.annotationId = manualAddResponse?.annotationId + ? manualAddResponse.annotationId + : new Date().getTime(); + this.commentId = manualAddResponse?.commentId + ? manualAddResponse.commentId + : new Date().getTime(); } get dictionary() { diff --git a/apps/red-ui/src/app/modules/admin/admin.module.ts b/apps/red-ui/src/app/modules/admin/admin.module.ts index bdc0e2bde..843569443 100644 --- a/apps/red-ui/src/app/modules/admin/admin.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin.module.ts @@ -77,6 +77,13 @@ const components = [ @NgModule({ declarations: [...components], providers: [AdminDialogService], - imports: [CommonModule, SharedModule, AdminRoutingModule, AceEditorModule, NgxChartsModule, ColorPickerModule] + imports: [ + CommonModule, + SharedModule, + AdminRoutingModule, + AceEditorModule, + NgxChartsModule, + ColorPickerModule + ] }) export class AdminModule {} diff --git a/apps/red-ui/src/app/modules/admin/components/breadcrumbs/admin-breadcrumbs.component.html b/apps/red-ui/src/app/modules/admin/components/breadcrumbs/admin-breadcrumbs.component.html index c8a6720b6..791984c80 100644 --- a/apps/red-ui/src/app/modules/admin/components/breadcrumbs/admin-breadcrumbs.component.html +++ b/apps/red-ui/src/app/modules/admin/components/breadcrumbs/admin-breadcrumbs.component.html @@ -1,5 +1,10 @@ @@ -25,7 +28,15 @@ -
+
- + diff --git a/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.html index 6bae2c2a5..7087e823e 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.html @@ -1,5 +1,8 @@
-
+
@@ -19,17 +22,32 @@ [style.background]="colorForm.get('color').value" class="input-icon" > - +
-
- +
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts index ff00039a9..cd749fb06 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/edit-color-dialog/edit-color-dialog.component.ts @@ -23,7 +23,8 @@ export class EditColorDialogComponent { private readonly _notificationService: NotificationService, private readonly _translateService: TranslateService, public dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) public data: { colors: Colors; colorKey: string; ruleSetId: string } + @Inject(MAT_DIALOG_DATA) + public data: { colors: Colors; colorKey: string; ruleSetId: string } ) { this.colors = data.colors; this.colorKey = data.colorKey; @@ -50,11 +51,17 @@ export class EditColorDialogComponent { this.dialogRef.close(true); this._notificationService.showToastNotification( this._translateService.instant('edit-color-dialog.success', { - color: this._translateService.instant('default-colors-screen.types.' + this.colorKey) + color: this._translateService.instant( + 'default-colors-screen.types.' + this.colorKey + ) }) ); } catch (e) { - this._notificationService.showToastNotification(this._translateService.instant('edit-color-dialog.error'), null, NotificationType.ERROR); + this._notificationService.showToastNotification( + this._translateService.instant('edit-color-dialog.error'), + null, + NotificationType.ERROR + ); } } } diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html index 6b8e98d14..6a2674d3f 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.html @@ -7,7 +7,10 @@ > - {{ 'file-attributes-csv-import.table-header.title' | translate: { length: allEntities.length } }} + {{ + 'file-attributes-csv-import.table-header.title' + | translate: { length: allEntities.length } + }} @@ -29,7 +32,10 @@
- + @@ -55,9 +65,14 @@
- + - +
- + @@ -93,7 +112,10 @@
{{ field.name }}
-
+
@@ -139,7 +161,10 @@
- +
diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts index 3187b5e94..d763d57aa 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component.ts @@ -1,4 +1,12 @@ -import { Component, EventEmitter, Injector, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; +import { + Component, + EventEmitter, + Injector, + Input, + OnChanges, + Output, + SimpleChanges +} from '@angular/core'; import { BaseListingComponent } from '@shared/base/base-listing.component'; import { Field } from '../file-attributes-csv-import-dialog.component'; import { FileAttributeConfig } from '@redaction/red-ui-http'; @@ -14,7 +22,11 @@ export class ActiveFieldsListingComponent extends BaseListingComponent im @Output() setHoveredColumn = new EventEmitter(); @Output() toggleFieldActive = new EventEmitter(); - readonly typeOptions = [FileAttributeConfig.TypeEnum.TEXT, FileAttributeConfig.TypeEnum.NUMBER, FileAttributeConfig.TypeEnum.DATE]; + readonly typeOptions = [ + FileAttributeConfig.TypeEnum.TEXT, + FileAttributeConfig.TypeEnum.NUMBER, + FileAttributeConfig.TypeEnum.DATE + ]; protected readonly _selectionKey = 'csvColumn'; @@ -30,7 +42,9 @@ export class ActiveFieldsListingComponent extends BaseListingComponent im } deactivateSelection() { - this.allEntities.filter((field) => this.isEntitySelected(field)).forEach((field) => (field.primaryAttribute = false)); + this.allEntities + .filter((field) => this.isEntitySelected(field)) + .forEach((field) => (field.primaryAttribute = false)); this.allEntities = [...this.allEntities.filter((field) => !this.isEntitySelected(field))]; this.allEntitiesChange.emit(this.allEntities); this.selectedEntitiesIds = []; diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html index 633afe952..c2a160f1c 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.html @@ -4,25 +4,37 @@
-
{{ csvFile.name }}
+
+ {{ csvFile.name }} +
- {{ 'file-attributes-csv-import.total-rows' | translate: { rows: parseResult?.data?.length } }} + {{ + 'file-attributes-csv-import.total-rows' + | translate: { rows: parseResult?.data?.length } + }}
- {{ 'file-attributes-csv-import.key-column' | translate }} + {{ + 'file-attributes-csv-import.key-column' | translate + }} - + {{ field }} @@ -32,7 +44,9 @@
{{ - 'file-attributes-csv-import.available' | translate: { value: parseResult?.meta?.fields.length } + 'file-attributes-csv-import.available' + | translate: { value: parseResult?.meta?.fields.length } + }} + {{ + 'file-attributes-csv-import.selected' + | translate: { value: activeFields.length } }} - {{ 'file-attributes-csv-import.selected' | translate: { value: activeFields.length } }}
-
{{ getEntries(field.csvColumn) }} entries
-
Sample: {{ getSample(field.csvColumn) }}
+
+ {{ getEntries(field.csvColumn) }} entries +
+
+ Sample: {{ getSample(field.csvColumn) }} +
-
+
- {{ 'file-attributes-csv-import.csv-column' + (previewExpanded ? '' : '-preview') | translate }} + {{ + 'file-attributes-csv-import.csv-column' + + (previewExpanded ? '' : '-preview') | translate + }}
-
+
- {{ 'file-attributes-csv-import.no-sample-data-for' | translate: { column: hoveredColumn } }} + {{ + 'file-attributes-csv-import.no-sample-data-for' + | translate: { column: hoveredColumn } + }}
{{ row }} @@ -144,12 +183,23 @@
- -
{{ 'file-attributes-csv-import.cancel' | translate }}
+
+ {{ 'file-attributes-csv-import.cancel' | translate }} +
- + diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts index 3299cf870..183db47cc 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts @@ -3,7 +3,11 @@ import { AbstractControl, FormGroup, ValidatorFn, Validators } from '@angular/fo import { AppStateService } from '@state/app-state.service'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import * as Papa from 'papaparse'; -import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http'; +import { + FileAttributeConfig, + FileAttributesConfig, + FileAttributesControllerService +} from '@redaction/red-ui-http'; import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; import { Observable } from 'rxjs'; import { map, startWith } from 'rxjs/operators'; @@ -40,7 +44,8 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent keepPreview = false; columnSample = []; initialParseConfig: { delimiter?: string; encoding?: string } = {}; - @ViewChild(CdkVirtualScrollViewport, { static: false }) cdkVirtualScrollViewport: CdkVirtualScrollViewport; + @ViewChild(CdkVirtualScrollViewport, { static: false }) + cdkVirtualScrollViewport: CdkVirtualScrollViewport; protected readonly _searchKey = 'csvColumn'; constructor( @@ -50,14 +55,18 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent private readonly _notificationService: NotificationService, public dialogRef: MatDialogRef, protected readonly _injector: Injector, - @Inject(MAT_DIALOG_DATA) public data: { csv: File; ruleSetId: string; existingConfiguration: FileAttributesConfig } + @Inject(MAT_DIALOG_DATA) + public data: { csv: File; ruleSetId: string; existingConfiguration: FileAttributesConfig } ) { super(_injector); this.csvFile = data.csv; this.ruleSetId = data.ruleSetId; this.baseConfigForm = this._formBuilder.group({ - filenameMappingColumnHeaderName: ['', [Validators.required, this._autocompleteStringValidator()]], + filenameMappingColumnHeaderName: [ + '', + [Validators.required, this._autocompleteStringValidator()] + ], delimiter: [undefined, Validators.required], encoding: ['UTF-8', Validators.required] }); @@ -87,12 +96,16 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent this.parseResult.meta.fields = Object.keys(this.parseResult.data[0]); } - this.allEntities = this.parseResult.meta.fields.map((field) => this._buildAttribute(field)); + this.allEntities = this.parseResult.meta.fields.map((field) => + this._buildAttribute(field) + ); this.displayedEntities = [...this.allEntities]; this.activeFields = []; for (const entity of this.allEntities) { - const existing = this.data.existingConfiguration.fileAttributeConfigs.find((a) => a.csvColumnHeader === entity.csvColumn); + const existing = this.data.existingConfiguration.fileAttributeConfigs.find( + (a) => a.csvColumnHeader === entity.csvColumn + ); if (existing) { entity.id = existing.id; entity.name = existing.label; @@ -104,18 +117,35 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent } } - this.filteredKeyOptions = this.baseConfigForm.get('filenameMappingColumnHeaderName').valueChanges.pipe( - startWith(this.baseConfigForm.get('filenameMappingColumnHeaderName').value as string), - map((value: string) => - this.allEntities.filter((field) => field.csvColumn.toLowerCase().indexOf(value.toLowerCase()) !== -1).map((field) => field.csvColumn) - ) - ); + this.filteredKeyOptions = this.baseConfigForm + .get('filenameMappingColumnHeaderName') + .valueChanges.pipe( + startWith( + this.baseConfigForm.get('filenameMappingColumnHeaderName').value as string + ), + map((value: string) => + this.allEntities + .filter( + (field) => + field.csvColumn.toLowerCase().indexOf(value.toLowerCase()) !== + -1 + ) + .map((field) => field.csvColumn) + ) + ); if ( this.data.existingConfiguration && - this.allEntities.find((entity) => entity.csvColumn === this.data.existingConfiguration.filenameMappingColumnHeaderName) + this.allEntities.find( + (entity) => + entity.csvColumn === + this.data.existingConfiguration.filenameMappingColumnHeaderName + ) ) { - this.baseConfigForm.patchValue({ filenameMappingColumnHeaderName: this.data.existingConfiguration.filenameMappingColumnHeaderName }); + this.baseConfigForm.patchValue({ + filenameMappingColumnHeaderName: + this.data.existingConfiguration.filenameMappingColumnHeaderName + }); } this.initialParseConfig = { @@ -169,14 +199,17 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent const newPrimary = !!this.activeFields.find((attr) => attr.primaryAttribute); if (newPrimary) { - this.data.existingConfiguration.fileAttributeConfigs.forEach((attr) => (attr.primaryAttribute = false)); + this.data.existingConfiguration.fileAttributeConfigs.forEach( + (attr) => (attr.primaryAttribute = false) + ); } const fileAttributes = { ...this.baseConfigForm.getRawValue(), fileAttributeConfigs: [ ...this.data.existingConfiguration.fileAttributeConfigs.filter( - (a) => !this.allEntities.find((entity) => entity.csvColumn === a.csvColumnHeader) + (a) => + !this.allEntities.find((entity) => entity.csvColumn === a.csvColumnHeader) ), ...this.activeFields.map((field) => ({ id: field.id, @@ -190,9 +223,13 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent }; try { - await this._fileAttributesControllerService.setFileAttributesConfig(fileAttributes, this.ruleSetId).toPromise(); + await this._fileAttributesControllerService + .setFileAttributesConfig(fileAttributes, this.ruleSetId) + .toPromise(); this._notificationService.showToastNotification( - this._translateService.instant('file-attributes-csv-import.save.success', { count: this.activeFields.length }), + this._translateService.instant('file-attributes-csv-import.save.success', { + count: this.activeFields.length + }), null, NotificationType.SUCCESS ); @@ -217,7 +254,9 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent if (!column) { this.columnSample = []; } else { - this.columnSample = this.parseResult.data.filter((row) => !!row[column]).map((row) => row[column]); + this.columnSample = this.parseResult.data + .filter((row) => !!row[column]) + .map((row) => row[column]); } }, 0); } @@ -238,7 +277,9 @@ export class FileAttributesCsvImportDialogComponent extends BaseListingComponent csvColumn, name: csvColumn, temporaryName: csvColumn, - type: isNumber ? FileAttributeConfig.TypeEnum.NUMBER : FileAttributeConfig.TypeEnum.TEXT, + type: isNumber + ? FileAttributeConfig.TypeEnum.NUMBER + : FileAttributeConfig.TypeEnum.TEXT, readonly: false, primaryAttribute: false }; diff --git a/apps/red-ui/src/app/modules/admin/dialogs/smtp-auth-dialog/smtp-auth-dialog.component.html b/apps/red-ui/src/app/modules/admin/dialogs/smtp-auth-dialog/smtp-auth-dialog.component.html index e3b00f0eb..68f9dfa0b 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/smtp-auth-dialog/smtp-auth-dialog.component.html +++ b/apps/red-ui/src/app/modules/admin/dialogs/smtp-auth-dialog/smtp-auth-dialog.component.html @@ -5,7 +5,12 @@
- +
@@ -18,9 +23,17 @@ -
+
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.html index dc51ab6e1..c09f65c50 100644 --- a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.html @@ -22,7 +22,10 @@
- {{ 'audit-screen.table-header.title' | translate: { length: logs?.totalHits || 0 } }} + {{ + 'audit-screen.table-header.title' + | translate: { length: logs?.totalHits || 0 } + }}
- + {{ category | translate }} @@ -50,7 +56,10 @@ [withName]="true" size="small" > -
+
-
+
·
- + - +
@@ -76,9 +95,16 @@
- + - +
@@ -87,14 +113,31 @@
- - - - + + + +
- +
@@ -105,7 +148,11 @@ {{ log.recordDate | date: 'd MMM. yyyy, hh:mm a' }}
- +
{{ log.category }} @@ -118,4 +165,6 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts index 224bf5237..19a29640f 100644 --- a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts @@ -61,7 +61,16 @@ export class AuditScreenComponent { } private _updateDateFilters(value): boolean { - if (applyIntervalConstraints(value, this._previousFrom, this._previousTo, this.filterForm, 'from', 'to')) { + if ( + applyIntervalConstraints( + value, + this._previousFrom, + this._previousTo, + this.filterForm, + 'from', + 'to' + ) + ) { return true; } diff --git a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html index 5fa10723c..b4e23db7a 100644 --- a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.html @@ -5,7 +5,12 @@
- +
@@ -17,7 +22,10 @@
- {{ 'default-colors-screen.table-header.title' | translate: { length: allEntities.length } }} + {{ + 'default-colors-screen.table-header.title' + | translate: { length: allEntities.length } + }}
@@ -30,7 +38,10 @@ label="default-colors-screen.table-col-names.key" > - +
@@ -38,13 +49,24 @@ -
+
-
+
-
+
@@ -66,4 +88,6 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts index e3f98d3b1..79f03f9a5 100644 --- a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts @@ -11,7 +11,10 @@ import { BaseListingComponent } from '@shared/base/base-listing.component'; templateUrl: './default-colors-screen.component.html', styleUrls: ['./default-colors-screen.component.scss'] }) -export class DefaultColorsScreenComponent extends BaseListingComponent<{ key: string; value: string }> { +export class DefaultColorsScreenComponent extends BaseListingComponent<{ + key: string; + value: string; +}> { viewReady = false; protected readonly _sortKey = 'default-colors'; private _colorsObj: Colors; @@ -35,9 +38,14 @@ export class DefaultColorsScreenComponent extends BaseListingComponent<{ key: st openEditColorDialog($event: any, color: { key: string; value: string }) { $event.stopPropagation(); - this._dialogService.openEditColorsDialog(this._colorsObj, color.key, this._appStateService.activeRuleSetId, async () => { - this._loadColors(); - }); + this._dialogService.openEditColorsDialog( + this._colorsObj, + color.key, + this._appStateService.activeRuleSetId, + async () => { + this._loadColors(); + } + ); } private _loadColors() { diff --git a/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html index 04ca839ae..a8c8201e9 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.html @@ -5,7 +5,12 @@
- +
@@ -25,11 +30,17 @@
- {{ 'dictionary-listing.table-header.title' | translate: { length: displayedEntities.length } }} + {{ + 'dictionary-listing.table-header.title' + | translate: { length: displayedEntities.length } + }}
- +
-
+
- +
@@ -75,20 +93,32 @@ screen="dictionary-listing" > - +
- +
-
+
{{ dict.label }} @@ -111,7 +141,10 @@
- +
@@ -154,4 +187,6 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.ts index e8dc49242..f07b18611 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dictionary-listing/dictionary-listing-screen.component.ts @@ -14,7 +14,10 @@ import { BaseListingComponent } from '@shared/base/base-listing.component'; templateUrl: './dictionary-listing-screen.component.html', styleUrls: ['./dictionary-listing-screen.component.scss'] }) -export class DictionaryListingScreenComponent extends BaseListingComponent implements OnInit { +export class DictionaryListingScreenComponent + extends BaseListingComponent + implements OnInit +{ viewReady = false; chartData: DoughnutChartConfig[] = []; protected readonly _searchKey = 'label'; @@ -39,38 +42,50 @@ export class DictionaryListingScreenComponent extends BaseListingComponent { - if (newDictionary) { - await this._appStateService.loadDictionaryData(); - this._loadDictionaryData(); + this._dialogService.openAddEditDictionaryDialog( + dict, + this._appStateService.activeRuleSetId, + async (newDictionary) => { + if (newDictionary) { + await this._appStateService.loadDictionaryData(); + this._loadDictionaryData(); + } } - }); + ); } openDeleteDictionaryDialog($event: any, dict: TypeValue) { - this._dialogService.openDeleteDictionaryDialog($event, dict, this._appStateService.activeRuleSetId, async () => { - await this._appStateService.loadDictionaryData(); - this._loadDictionaryData(); - }); + this._dialogService.openDeleteDictionaryDialog( + $event, + dict, + this._appStateService.activeRuleSetId, + async () => { + await this._appStateService.loadDictionaryData(); + this._loadDictionaryData(); + } + ); } private _loadDictionaryData() { - const appStateDictionaryData = this._appStateService.dictionaryData[this._appStateService.activeRuleSetId]; + const appStateDictionaryData = + this._appStateService.dictionaryData[this._appStateService.activeRuleSetId]; this.allEntities = Object.keys(appStateDictionaryData) .map((key) => appStateDictionaryData[key]) .filter((d) => !d.virtual); this.displayedEntities = [...this.allEntities]; const dataObs = this.allEntities.map((dict) => - this._dictionaryControllerService.getDictionaryForType(this._appStateService.activeRuleSetId, dict.type).pipe( - tap((values) => { - dict.entries = values.entries ? values.entries : []; - }), - catchError(() => { - console.log('error'); - dict.entries = []; - return of({}); - }) - ) + this._dictionaryControllerService + .getDictionaryForType(this._appStateService.activeRuleSetId, dict.type) + .pipe( + tap((values) => { + dict.entries = values.entries ? values.entries : []; + }), + catchError(() => { + console.log('error'); + dict.entries = []; + return of({}); + }) + ) ); forkJoin(dataObs) .pipe(defaultIfEmpty(null)) diff --git a/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.html index 172710bbd..71c1a07b2 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.html @@ -38,7 +38,14 @@ tooltipPosition="below" > - +
-
+
{{ dictionary.description }}
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.ts index 0517b0fd1..d8c5b401d 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dictionary-overview/dictionary-overview-screen.component.ts @@ -21,7 +21,8 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple processing = false; entries: string[] = []; - @ViewChild('dictionaryManager', { static: false }) private _dictionaryManager: DictionaryManagerComponent; + @ViewChild('dictionaryManager', { static: false }) + private _dictionaryManager: DictionaryManagerComponent; @ViewChild('fileInput') private _fileInput: ElementRef; constructor( @@ -37,7 +38,10 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple private readonly _formBuilder: FormBuilder ) { super(_translateService); - this._appStateService.activateDictionary(this._activatedRoute.snapshot.params.type, this._activatedRoute.snapshot.params.ruleSetId); + this._appStateService.activateDictionary( + this._activatedRoute.snapshot.params.type, + this._activatedRoute.snapshot.params.ruleSetId + ); } ngOnInit(): void { @@ -54,16 +58,25 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple openEditDictionaryDialog($event: any) { $event.stopPropagation(); - this._dialogService.openAddEditDictionaryDialog(this.dictionary, this.dictionary.ruleSetId, async () => { - await this._appStateService.loadDictionaryData(); - }); + this._dialogService.openAddEditDictionaryDialog( + this.dictionary, + this.dictionary.ruleSetId, + async () => { + await this._appStateService.loadDictionaryData(); + } + ); } openDeleteDictionaryDialog($event: any) { - this._dialogService.openDeleteDictionaryDialog($event, this.dictionary, this.dictionary.ruleSetId, async () => { - await this._appStateService.loadDictionaryData(); - this._router.navigate(['..']); - }); + this._dialogService.openDeleteDictionaryDialog( + $event, + this.dictionary, + this.dictionary.ruleSetId, + async () => { + await this._appStateService.loadDictionaryData(); + this._router.navigate(['..']); + } + ); } download(): void { @@ -89,28 +102,40 @@ export class DictionaryOverviewScreenComponent extends ComponentHasChanges imple saveEntries(entries: string[]) { this.processing = true; - this._dictionarySaveService.saveEntries(entries, this.entries, this.dictionary.ruleSetId, this.dictionary.type, null).subscribe( - () => { - this.processing = false; - this._loadEntries(); - }, - () => { - this.processing = false; - } - ); + this._dictionarySaveService + .saveEntries( + entries, + this.entries, + this.dictionary.ruleSetId, + this.dictionary.type, + null + ) + .subscribe( + () => { + this.processing = false; + this._loadEntries(); + }, + () => { + this.processing = false; + } + ); } private _loadEntries() { this.processing = true; - this._dictionaryControllerService.getDictionaryForType(this.dictionary.ruleSetId, this.dictionary.type).subscribe( - (data) => { - this.processing = false; - this.entries = data.entries.sort((str1, str2) => str1.localeCompare(str2, undefined, { sensitivity: 'accent' })); - }, - () => { - this.processing = false; - this.entries = []; - } - ); + this._dictionaryControllerService + .getDictionaryForType(this.dictionary.ruleSetId, this.dictionary.type) + .subscribe( + (data) => { + this.processing = false; + this.entries = data.entries.sort((str1, str2) => + str1.localeCompare(str2, undefined, { sensitivity: 'accent' }) + ); + }, + () => { + this.processing = false; + this.entries = []; + } + ); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.html index 1802aeb11..40f512e2e 100644 --- a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.html @@ -22,8 +22,19 @@
-
- + + -
- +
+
-
+
- +
- +
- +
@@ -96,4 +139,6 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts index a22970fd6..261f8caa0 100644 --- a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts @@ -29,7 +29,10 @@ export class DigitalSignatureScreenComponent { } get hasDigitalSignatureSet() { - return this.digitalSignatureExists || !!this.digitalSignatureForm.get('base64EncodedPrivateKey').value; + return ( + this.digitalSignatureExists || + !!this.digitalSignatureForm.get('base64EncodedPrivateKey').value + ); } saveDigitalSignature() { @@ -55,13 +58,17 @@ export class DigitalSignatureScreenComponent { (error) => { if (error.status === 400) { this._notificationService.showToastNotification( - this._translateService.instant('digital-signature-screen.action.certificate-not-valid-error'), + this._translateService.instant( + 'digital-signature-screen.action.certificate-not-valid-error' + ), null, NotificationType.ERROR ); } else { this._notificationService.showToastNotification( - this._translateService.instant('digital-signature-screen.action.save-error'), + this._translateService.instant( + 'digital-signature-screen.action.save-error' + ), null, NotificationType.ERROR ); @@ -75,7 +82,9 @@ export class DigitalSignatureScreenComponent { () => { this.loadDigitalSignatureAndInitializeForm(); this._notificationService.showToastNotification( - this._translateService.instant('digital-signature-screen.action.delete-success'), + this._translateService.instant( + 'digital-signature-screen.action.delete-success' + ), null, NotificationType.SUCCESS ); @@ -130,9 +139,13 @@ export class DigitalSignatureScreenComponent { certificateName: [this.digitalSignature.certificateName, Validators.required], contactInfo: this.digitalSignature.contactInfo, location: this.digitalSignature.location, - keySecret: this.digitalSignatureExists ? null : [this.digitalSignature.password, Validators.required], + keySecret: this.digitalSignatureExists + ? null + : [this.digitalSignature.password, Validators.required], reason: this.digitalSignature.reason, - base64EncodedPrivateKey: this.digitalSignatureExists ? null : [this.digitalSignature.base64EncodedPrivateKey, Validators.required] + base64EncodedPrivateKey: this.digitalSignatureExists + ? null + : [this.digitalSignature.base64EncodedPrivateKey, Validators.required] }); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html index 8c463c46d..d4f6afcef 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.html @@ -3,7 +3,12 @@
- +
@@ -23,7 +28,10 @@
- {{ 'file-attributes-listing.table-header.title' | translate: { length: displayedEntities.length } }} + {{ + 'file-attributes-listing.table-header.title' + | translate: { length: displayedEntities.length } + }}
- - + +
-
+
- +
- + -
+
- +
{{ attribute.label }}
-
+
- +
@@ -162,4 +204,6 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts index d81a256b0..d22b8298d 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts @@ -1,6 +1,10 @@ import { Component, ElementRef, Injector, OnInit, ViewChild } from '@angular/core'; import { PermissionsService } from '@services/permissions.service'; -import { FileAttributeConfig, FileAttributesConfig, FileAttributesControllerService } from '@redaction/red-ui-http'; +import { + FileAttributeConfig, + FileAttributesConfig, + FileAttributesControllerService +} from '@redaction/red-ui-http'; import { AppStateService } from '@state/app-state.service'; import { ActivatedRoute } from '@angular/router'; import { AdminDialogService } from '../../services/admin-dialog.service'; @@ -11,7 +15,10 @@ import { BaseListingComponent } from '@shared/base/base-listing.component'; templateUrl: './file-attributes-listing-screen.component.html', styleUrls: ['./file-attributes-listing-screen.component.scss'] }) -export class FileAttributesListingScreenComponent extends BaseListingComponent implements OnInit { +export class FileAttributesListingScreenComponent + extends BaseListingComponent + implements OnInit +{ viewReady = false; loading = false; protected readonly _searchKey = 'label'; @@ -39,38 +46,65 @@ export class FileAttributesListingScreenComponent extends BaseListingComponent { - this.loading = true; - await this._fileAttributesService.setFileAttributesConfiguration(newValue, this._appStateService.activeRuleSetId).toPromise(); - await this._loadData(); - }); + this._dialogService.openAddEditFileAttributeDialog( + fileAttribute, + this._appStateService.activeRuleSetId, + async (newValue: FileAttributeConfig) => { + this.loading = true; + await this._fileAttributesService + .setFileAttributesConfiguration(newValue, this._appStateService.activeRuleSetId) + .toPromise(); + await this._loadData(); + } + ); } openConfirmDeleteAttributeDialog($event: MouseEvent, fileAttribute?: FileAttributeConfig) { $event.stopPropagation(); - this._dialogService.openConfirmDeleteFileAttributeDialog(fileAttribute, this._appStateService.activeRuleSetId, async () => { - this.loading = true; - if (fileAttribute) { - await this._fileAttributesService.deleteFileAttribute(this._appStateService.activeRuleSetId, fileAttribute.id).toPromise(); - } else { - await this._fileAttributesService.deleteFileAttributes(this.selectedEntitiesIds, this._appStateService.activeRuleSetId).toPromise(); + this._dialogService.openConfirmDeleteFileAttributeDialog( + fileAttribute, + this._appStateService.activeRuleSetId, + async () => { + this.loading = true; + if (fileAttribute) { + await this._fileAttributesService + .deleteFileAttribute( + this._appStateService.activeRuleSetId, + fileAttribute.id + ) + .toPromise(); + } else { + await this._fileAttributesService + .deleteFileAttributes( + this.selectedEntitiesIds, + this._appStateService.activeRuleSetId + ) + .toPromise(); + } + await this._loadData(); } - await this._loadData(); - }); + ); } importCSV(files: FileList | File[]) { const csvFile = files[0]; this._fileInput.nativeElement.value = null; - this._dialogService.openImportFileAttributeCSVDialog(csvFile, this._appStateService.activeRuleSetId, this._existingConfiguration, async () => { - await this._loadData(); - }); + this._dialogService.openImportFileAttributeCSVDialog( + csvFile, + this._appStateService.activeRuleSetId, + this._existingConfiguration, + async () => { + await this._loadData(); + } + ); } private async _loadData() { try { - const response = await this._fileAttributesService.getFileAttributesConfiguration(this._appStateService.activeRuleSetId).toPromise(); + const response = await this._fileAttributesService + .getFileAttributesConfiguration(this._appStateService.activeRuleSetId) + .toPromise(); this._existingConfiguration = response; this.allEntities = response?.fileAttributeConfigs || []; } catch (e) { diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.html index d4a664759..b2ea2231b 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.html @@ -8,7 +8,12 @@
- +
-
{{ 'license-info-screen.copyright-claim-text' | translate: { currentYear: currentYear } }}
+
+ {{ + 'license-info-screen.copyright-claim-text' + | translate: { currentYear: currentYear } + }} +
@@ -54,7 +64,10 @@ -
+
@@ -63,7 +76,10 @@
-
{{ appConfigService.getConfig('LICENSE_START', '-') }} / {{ appConfigService.getConfig('LICENSE_END', '-') }}
+
+ {{ appConfigService.getConfig('LICENSE_START', '-') }} / + {{ appConfigService.getConfig('LICENSE_END', '-') }} +
@@ -76,16 +92,28 @@
{{ currentInfo.numberOfAnalyzedPages }}
-
+
-
{{ 'license-info-screen.total-analyzed' | translate: { date: totalInfo.startDate | date: 'longDate' } }}
+
+ {{ + 'license-info-screen.total-analyzed' + | translate: { date: totalInfo.startDate | date: 'longDate' } + }} +
{{ totalInfo.numberOfAnalyzedPages }}
-
{{ currentInfo.numberOfAnalyzedPages }} ({{ analysisPercentageOfLicense | number: '1.0-2' }}%)
+
+ {{ currentInfo.numberOfAnalyzedPages }} ({{ + analysisPercentageOfLicense | number: '1.0-2' + }}%) +
@@ -123,4 +151,6 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.ts index e2080c449..13653695f 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license-information/license-information-screen.component.ts @@ -54,31 +54,47 @@ export class LicenseInformationScreenComponent implements OnInit { startDate: startDate.toDate(), endDate: endDate.toDate() }; - const promises = [this._licenseReportController.licenseReport(currentConfig).toPromise(), this._licenseReportController.licenseReport({}).toPromise()]; + const promises = [ + this._licenseReportController.licenseReport(currentConfig).toPromise(), + this._licenseReportController.licenseReport({}).toPromise() + ]; if (endDate.isBefore(moment())) { const unlicensedConfig = { startDate: endDate.toDate() }; - promises.push(this._licenseReportController.licenseReport(unlicensedConfig).toPromise()); + promises.push( + this._licenseReportController.licenseReport(unlicensedConfig).toPromise() + ); } Promise.all(promises).then((reports) => { [this.currentInfo, this.totalInfo, this.unlicensedInfo] = reports; this.viewReady = true; this.analysisPercentageOfLicense = - this.totalLicensedNumberOfPages > 0 ? (this.currentInfo.numberOfAnalyzedPages / this.totalLicensedNumberOfPages) * 100 : 100; + this.totalLicensedNumberOfPages > 0 + ? (this.currentInfo.numberOfAnalyzedPages / this.totalLicensedNumberOfPages) * + 100 + : 100; }); } sendMail(): void { const licenseCustomer = this.appConfigService.getConfig('LICENSE_CUSTOMER'); - const subject = this._translateService.instant('license-info-screen.email.title', { licenseCustomer }); + const subject = this._translateService.instant('license-info-screen.email.title', { + licenseCustomer + }); const body = [ - this._translateService.instant('license-info-screen.email.body.analyzed', { pages: this.currentInfo.numberOfAnalyzedPages }), - this._translateService.instant('license-info-screen.email.body.licensed', { pages: this.totalLicensedNumberOfPages }) + this._translateService.instant('license-info-screen.email.body.analyzed', { + pages: this.currentInfo.numberOfAnalyzedPages + }), + this._translateService.instant('license-info-screen.email.body.licensed', { + pages: this.totalLicensedNumberOfPages + }) ].join('%0D%0A'); - window.location.href = `mailto:${this.appConfigService.getConfig('LICENSE_EMAIL')}?subject=${subject}&body=${body}`; + window.location.href = `mailto:${this.appConfigService.getConfig( + 'LICENSE_EMAIL' + )}?subject=${subject}&body=${body}`; } private async _setMonthlyStats(startDate: moment.Moment, endDate: moment.Moment) { diff --git a/apps/red-ui/src/app/modules/admin/screens/rule-sets-listing/rule-sets-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/rule-sets-listing/rule-sets-listing-screen.component.html index ab8bf5626..80e07c98c 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rule-sets-listing/rule-sets-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/rule-sets-listing/rule-sets-listing-screen.component.html @@ -28,15 +28,24 @@
- {{ 'project-templates-listing.table-header.title' | translate: { length: displayedEntities.length } }} + {{ + 'project-templates-listing.table-header.title' + | translate: { length: displayedEntities.length } + }}
- +
-
+
- +
- +
-
- +
+
@@ -97,13 +125,19 @@
- {{ 'project-templates-listing.dictionaries' | translate: { length: ruleSet.dictionariesCount } }} + {{ + 'project-templates-listing.dictionaries' + | translate: { length: ruleSet.dictionariesCount } + }}
- +
{{ ruleSet.dateAdded | date: 'd MMM. yyyy' }} diff --git a/apps/red-ui/src/app/modules/admin/screens/rule-sets-listing/rule-sets-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/rule-sets-listing/rule-sets-listing-screen.component.ts index 00902537a..f81ffe5b5 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rule-sets-listing/rule-sets-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/rule-sets-listing/rule-sets-listing-screen.component.ts @@ -11,7 +11,10 @@ import { RuleSetModel } from '@redaction/red-ui-http'; templateUrl: './rule-sets-listing-screen.component.html', styleUrls: ['./rule-sets-listing-screen.component.scss'] }) -export class RuleSetsListingScreenComponent extends BaseListingComponent implements OnInit { +export class RuleSetsListingScreenComponent + extends BaseListingComponent + implements OnInit +{ protected readonly _searchKey = 'name'; protected readonly _selectionKey = 'ruleSetId'; protected readonly _sortKey = 'rule-sets-listing'; diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html index c246bd3df..8a4495749 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.html @@ -5,7 +5,12 @@
- +
@@ -29,10 +34,21 @@
- -
+ +
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.ts index cc5b75b16..4d17a85dd 100644 --- a/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/rules/rules-screen.component.ts @@ -69,7 +69,12 @@ export class RulesScreenComponent extends ComponentHasChanges { const entry = this.currentLines[i]; if (entry?.trim().length > 0) { // only mark non-empty lines - this.activeEditMarkers.push(this.editorComponent.getEditor().getSession().addMarker(new range(i, 0, i, 1), 'changed-row-marker', 'fullLine')); + this.activeEditMarkers.push( + this.editorComponent + .getEditor() + .getSession() + .addMarker(new range(i, 0, i, 1), 'changed-row-marker', 'fullLine') + ); } } } @@ -92,7 +97,11 @@ export class RulesScreenComponent extends ComponentHasChanges { }, () => { this.processing = false; - this._notificationService.showToastNotification(this._translateService.instant('rules-screen.error.generic'), null, NotificationType.ERROR); + this._notificationService.showToastNotification( + this._translateService.instant('rules-screen.error.generic'), + null, + NotificationType.ERROR + ); } ); } diff --git a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.html index cc725dfe2..7d294e8a6 100644 --- a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.html @@ -34,7 +34,9 @@
@@ -44,7 +46,9 @@
@@ -54,20 +58,30 @@
- + - +
@@ -75,44 +89,69 @@
- +
- + - +
- +
- +
- +
- @@ -141,4 +185,6 @@
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts index 3a1ae84f1..09f82b5ae 100644 --- a/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/smtp-config/smtp-config-screen.component.ts @@ -65,32 +65,43 @@ export class SmtpConfigScreenComponent implements OnInit { async save() { this.viewReady = false; - await this._smtpConfigService.updateSMTPConfiguration(this.configForm.getRawValue()).toPromise(); + await this._smtpConfigService + .updateSMTPConfiguration(this.configForm.getRawValue()) + .toPromise(); this._initialValue = this.configForm.getRawValue(); this.viewReady = true; } openAuthConfigDialog(skipDisableOnCancel?: boolean) { - this._dialogService.openSMTPAuthConfigDialog(this.configForm.getRawValue(), (authConfig) => { - if (authConfig) { - this.configForm.patchValue(authConfig); - } else if (!skipDisableOnCancel) { - this.configForm.patchValue({ auth: false }, { emitEvent: false }); + this._dialogService.openSMTPAuthConfigDialog( + this.configForm.getRawValue(), + (authConfig) => { + if (authConfig) { + this.configForm.patchValue(authConfig); + } else if (!skipDisableOnCancel) { + this.configForm.patchValue({ auth: false }, { emitEvent: false }); + } } - }); + ); } async testConnection() { this.viewReady = false; try { - await this._smtpConfigService.testSMTPConfiguration(this.configForm.getRawValue()).toPromise(); + await this._smtpConfigService + .testSMTPConfiguration(this.configForm.getRawValue()) + .toPromise(); this._notificationService.showToastNotification( this._translateService.instant('smtp-config-screen.test.success'), undefined, NotificationType.SUCCESS ); } catch (e) { - this._notificationService.showToastNotification(this._translateService.instant('smtp-config-screen.test.error'), undefined, NotificationType.ERROR); + this._notificationService.showToastNotification( + this._translateService.instant('smtp-config-screen.test.error'), + undefined, + NotificationType.ERROR + ); } finally { this.viewReady = true; } @@ -98,7 +109,9 @@ export class SmtpConfigScreenComponent implements OnInit { private async _loadData() { try { - this._initialValue = await this._smtpConfigService.getCurrentSMTPConfiguration().toPromise(); + this._initialValue = await this._smtpConfigService + .getCurrentSMTPConfiguration() + .toPromise(); this.configForm.patchValue(this._initialValue, { emitEvent: false }); } catch (e) { } finally { diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html index c5e2b5fd9..733292754 100644 --- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.html @@ -8,7 +8,10 @@
- + - {{ 'user-listing.table-header.title' | translate: { length: displayedEntities.length } }} + {{ + 'user-listing.table-header.title' + | translate: { length: displayedEntities.length } + }}
- + - + - + - +
- +
- +
- +
{{ user.email || '-' }}
- +
{{ getDisplayRoles(user) }}
@@ -113,10 +146,15 @@
- +
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts index 918f4d6d0..76274e4e9 100644 --- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts @@ -50,7 +50,9 @@ export class UserListingScreenComponent extends BaseListingComponent imple if (result.action === 'CREATE') { await this._userControllerService.createUser(result.user).toPromise(); } else if (result.action === 'UPDATE') { - await this._userControllerService.updateProfile(result.user, user.userId).toPromise(); + await this._userControllerService + .updateProfile(result.user, user.userId) + .toPromise(); } await this._loadData(); } @@ -67,7 +69,10 @@ export class UserListingScreenComponent extends BaseListingComponent imple } getDisplayRoles(user: User) { - return user.roles.map((role) => this._translateService.instant('roles.' + role)).join(', ') || this._translateService.instant('roles.NO_ROLE'); + return ( + user.roles.map((role) => this._translateService.instant('roles.' + role)).join(', ') || + this._translateService.instant('roles.NO_ROLE') + ); } async toggleActive(user: User) { @@ -101,32 +106,46 @@ export class UserListingScreenComponent extends BaseListingComponent imple this.chartData = this._translateChartService.translateRoles( [ { - value: this.allEntities.filter((user) => !this.userService.isActive(user)).length, + value: this.allEntities.filter((user) => !this.userService.isActive(user)) + .length, color: 'INACTIVE', label: 'INACTIVE' }, { - value: this.allEntities.filter((user) => user.roles.length === 1 && user.roles[0] === 'RED_USER').length, + value: this.allEntities.filter( + (user) => user.roles.length === 1 && user.roles[0] === 'RED_USER' + ).length, color: 'REGULAR', label: 'REGULAR' }, { - value: this.allEntities.filter((user) => this.userService.isManager(user) && !this.userService.isAdmin(user)).length, + value: this.allEntities.filter( + (user) => + this.userService.isManager(user) && !this.userService.isAdmin(user) + ).length, color: 'MANAGER', label: 'RED_MANAGER' }, { - value: this.allEntities.filter((user) => this.userService.isManager(user) && this.userService.isAdmin(user)).length, + value: this.allEntities.filter( + (user) => this.userService.isManager(user) && this.userService.isAdmin(user) + ).length, color: 'MANAGER_ADMIN', label: 'MANAGER_ADMIN' }, { - value: this.allEntities.filter((user) => this.userService.isUserAdmin(user) && !this.userService.isAdmin(user)).length, + value: this.allEntities.filter( + (user) => + this.userService.isUserAdmin(user) && !this.userService.isAdmin(user) + ).length, color: 'USER_ADMIN', label: 'RED_USER_ADMIN' }, { - value: this.allEntities.filter((user) => this.userService.isAdmin(user) && !this.userService.isManager(user)).length, + value: this.allEntities.filter( + (user) => + this.userService.isAdmin(user) && !this.userService.isManager(user) + ).length, color: 'ADMIN', label: 'RED_ADMIN' } diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.html index f23aaf099..950e118b1 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.html @@ -3,7 +3,12 @@
- +
@@ -22,7 +27,11 @@ text="watermark-screen.action.save" type="primary" > -
+
@@ -43,7 +52,10 @@
- +
- - + +
- +
- +
- +
- + diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.ts index 76a2e0f57..6d40b9cbe 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen.component.ts @@ -78,20 +78,33 @@ export class WatermarkScreenComponent implements OnInit { }; const observable = watermark.text - ? this._watermarkControllerService.saveWatermark(watermark, this.appStateService.activeRuleSetId) - : this._watermarkControllerService.deleteWatermark(this.appStateService.activeRuleSetId); + ? this._watermarkControllerService.saveWatermark( + watermark, + this.appStateService.activeRuleSetId + ) + : this._watermarkControllerService.deleteWatermark( + this.appStateService.activeRuleSetId + ); observable.subscribe( () => { this._loadWatermark(); this._notificationService.showToastNotification( - this._translateService.instant(watermark.text ? 'watermark-screen.action.change-success' : 'watermark-screen.action.delete-success'), + this._translateService.instant( + watermark.text + ? 'watermark-screen.action.change-success' + : 'watermark-screen.action.delete-success' + ), null, NotificationType.SUCCESS ); }, () => { - this._notificationService.showToastNotification(this._translateService.instant('watermark-screen.action.error'), null, NotificationType.ERROR); + this._notificationService.showToastNotification( + this._translateService.instant('watermark-screen.action.error'), + null, + NotificationType.ERROR + ); } ); } @@ -111,18 +124,20 @@ export class WatermarkScreenComponent implements OnInit { } private _loadWatermark() { - this._watermarkControllerService.getWatermark(this.appStateService.activeRuleSetId).subscribe( - (watermark) => { - this._watermark = watermark; - this.configForm.setValue({ ...this._watermark }); - this._loadViewer(); - }, - () => { - this._watermark = DEFAULT_WATERMARK; - this.configForm.setValue({ ...this._watermark }); - this._loadViewer(); - } - ); + this._watermarkControllerService + .getWatermark(this.appStateService.activeRuleSetId) + .subscribe( + (watermark) => { + this._watermark = watermark; + this.configForm.setValue({ ...this._watermark }); + this._loadViewer(); + }, + () => { + this._watermark = DEFAULT_WATERMARK; + this.configForm.setValue({ ...this._watermark }); + this._loadViewer(); + } + ); } private _loadViewer() { @@ -177,14 +192,17 @@ export class WatermarkScreenComponent implements OnInit { const text = this.configForm.get('text').value || ''; const fontSize = this.configForm.get('fontSize').value; const fontType = this.configForm.get('fontType').value; - const orientation: WatermarkModel.WatermarkOrientationEnum = this.configForm.get('orientation').value; + const orientation: WatermarkModel.WatermarkOrientationEnum = + this.configForm.get('orientation').value; const opacity = this.configForm.get('opacity').value; const color = this.configForm.get('hexColor').value; const rgbColor = hexToRgb(color); const stamper = await pdfNet.Stamper.create(3, fontSize, 0); - await stamper.setFontColor(await pdfNet.ColorPt.init(rgbColor.r / 255, rgbColor.g / 255, rgbColor.b / 255)); + await stamper.setFontColor( + await pdfNet.ColorPt.init(rgbColor.r / 255, rgbColor.g / 255, rgbColor.b / 255) + ); await stamper.setOpacity(opacity / 100); switch (orientation) { @@ -200,7 +218,10 @@ export class WatermarkScreenComponent implements OnInit { await stamper.setRotation(-45); } - const font = await pdfNet.Font.createAndEmbed(document, this._convertFont(fontType)); + const font = await pdfNet.Font.createAndEmbed( + document, + this._convertFont(fontType) + ); await stamper.setFont(font); await stamper.setTextAlignment(0); await stamper.stampText(document, text, pageSet); @@ -216,11 +237,26 @@ export class WatermarkScreenComponent implements OnInit { private _initForm() { this.configForm = this._formBuilder.group({ text: [{ value: null, disabled: !this.permissionsService.isAdmin() }], - hexColor: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required], - opacity: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required], - fontSize: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required], - fontType: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required], - orientation: [{ value: null, disabled: !this.permissionsService.isAdmin() }, Validators.required] + hexColor: [ + { value: null, disabled: !this.permissionsService.isAdmin() }, + Validators.required + ], + opacity: [ + { value: null, disabled: !this.permissionsService.isAdmin() }, + Validators.required + ], + fontSize: [ + { value: null, disabled: !this.permissionsService.isAdmin() }, + Validators.required + ], + fontType: [ + { value: null, disabled: !this.permissionsService.isAdmin() }, + Validators.required + ], + orientation: [ + { value: null, disabled: !this.permissionsService.isAdmin() }, + Validators.required + ] }); } diff --git a/apps/red-ui/src/app/modules/admin/services/admin-dialog.service.ts b/apps/red-ui/src/app/modules/admin/services/admin-dialog.service.ts index 447a76fd7..fa5d22c68 100644 --- a/apps/red-ui/src/app/modules/admin/services/admin-dialog.service.ts +++ b/apps/red-ui/src/app/modules/admin/services/admin-dialog.service.ts @@ -53,19 +53,30 @@ export class AdminDialogService { private readonly _manualRedactionControllerService: ManualRedactionControllerService ) {} - openDeleteDictionaryDialog($event: MouseEvent, dictionary: TypeValue, ruleSetId: string, cb?: Function): MatDialogRef { + openDeleteDictionaryDialog( + $event: MouseEvent, + dictionary: TypeValue, + ruleSetId: string, + cb?: Function + ): MatDialogRef { $event.stopPropagation(); const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig); ref.afterClosed().subscribe(async (result) => { if (result) { - await this._dictionaryControllerService.deleteType(dictionary.type, ruleSetId).toPromise(); + await this._dictionaryControllerService + .deleteType(dictionary.type, ruleSetId) + .toPromise(); if (cb) cb(); } }); return ref; } - openDeleteRuleSetDialog($event: MouseEvent, ruleSet: RuleSetModel, cb?: Function): MatDialogRef { + openDeleteRuleSetDialog( + $event: MouseEvent, + ruleSet: RuleSetModel, + cb?: Function + ): MatDialogRef { $event.stopPropagation(); const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig); ref.afterClosed().subscribe(async (result) => { @@ -77,7 +88,11 @@ export class AdminDialogService { return ref; } - openAddEditDictionaryDialog(dictionary: TypeValue, ruleSetId: string, cb?: Function): MatDialogRef { + openAddEditDictionaryDialog( + dictionary: TypeValue, + ruleSetId: string, + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(AddEditDictionaryDialogComponent, { ...dialogConfig, data: { dictionary, ruleSetId }, @@ -93,7 +108,12 @@ export class AdminDialogService { return ref; } - openEditColorsDialog(colors: Colors, colorKey: string, ruleSetId: string, cb?: Function): MatDialogRef { + openEditColorsDialog( + colors: Colors, + colorKey: string, + ruleSetId: string, + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(EditColorDialogComponent, { ...dialogConfig, data: { colors, colorKey, ruleSetId }, @@ -109,7 +129,10 @@ export class AdminDialogService { return ref; } - openAddEditRuleSetDialog(ruleSet: RuleSetModel, cb?: Function): MatDialogRef { + openAddEditRuleSetDialog( + ruleSet: RuleSetModel, + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(AddEditRuleSetDialogComponent, { ...dialogConfig, width: '900px', @@ -146,7 +169,11 @@ export class AdminDialogService { return ref; } - openAddEditFileAttributeDialog(fileAttribute: FileAttributeConfig, ruleSetId: string, cb?: Function): MatDialogRef { + openAddEditFileAttributeDialog( + fileAttribute: FileAttributeConfig, + ruleSetId: string, + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(AddEditFileAttributeDialogComponent, { ...dialogConfig, data: { fileAttribute, ruleSetId }, @@ -182,7 +209,10 @@ export class AdminDialogService { return ref; } - openSMTPAuthConfigDialog(smtpConfig: SMTPConfigurationModel, cb?: Function): MatDialogRef { + openSMTPAuthConfigDialog( + smtpConfig: SMTPConfigurationModel, + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(SmtpAuthDialogComponent, { ...dialogConfig, data: smtpConfig, @@ -214,7 +244,10 @@ export class AdminDialogService { return ref; } - openConfirmDeleteUsersDialog(users: User[], cb?: Function): MatDialogRef { + openConfirmDeleteUsersDialog( + users: User[], + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(ConfirmDeleteUsersDialogComponent, { ...dialogConfig, data: users, diff --git a/apps/red-ui/src/app/modules/app-config/app-config.service.ts b/apps/red-ui/src/app/modules/app-config/app-config.service.ts index ba0d7ee79..a879d0e8e 100644 --- a/apps/red-ui/src/app/modules/app-config/app-config.service.ts +++ b/apps/red-ui/src/app/modules/app-config/app-config.service.ts @@ -34,17 +34,28 @@ export enum AppConfigKey { export class AppConfigService { private _config: { [key in AppConfigKey]?: any } = {}; - constructor(private readonly _httpClient: HttpClient, private readonly _cacheApiService: CacheApiService, private readonly _titleService: Title) {} + constructor( + private readonly _httpClient: HttpClient, + private readonly _cacheApiService: CacheApiService, + private readonly _titleService: Title + ) {} loadAppConfig(): Observable { - this._cacheApiService.getCachedValue(AppConfigKey.FRONTEND_APP_VERSION).then(async (lastVersion) => { - console.log('[REDACTION] Last app version: ', lastVersion, ' current version ', version); - if (lastVersion !== version) { - console.log('[REDACTION] Version-missmatch - wiping caches!'); - await wipeCaches(); - } - await this._cacheApiService.cacheValue(AppConfigKey.FRONTEND_APP_VERSION, version); - }); + this._cacheApiService + .getCachedValue(AppConfigKey.FRONTEND_APP_VERSION) + .then(async (lastVersion) => { + console.log( + '[REDACTION] Last app version: ', + lastVersion, + ' current version ', + version + ); + if (lastVersion !== version) { + console.log('[REDACTION] Version-missmatch - wiping caches!'); + await wipeCaches(); + } + await this._cacheApiService.cacheValue(AppConfigKey.FRONTEND_APP_VERSION, version); + }); return this._httpClient.get('/assets/config/config.json').pipe( tap((config) => { diff --git a/apps/red-ui/src/app/modules/auth/auth.module.ts b/apps/red-ui/src/app/modules/auth/auth.module.ts index eead711f4..33336be2a 100644 --- a/apps/red-ui/src/app/modules/auth/auth.module.ts +++ b/apps/red-ui/src/app/modules/auth/auth.module.ts @@ -7,7 +7,11 @@ import { KeycloakAngularModule, KeycloakOptions, KeycloakService } from 'keycloa import { AppConfigKey, AppConfigService } from '@app-config/app-config.service'; import { BASE_HREF } from '../../tokens'; -export function keycloakInitializer(keycloak: KeycloakService, appConfigService: AppConfigService, baseUrl) { +export function keycloakInitializer( + keycloak: KeycloakService, + appConfigService: AppConfigService, + baseUrl +) { return () => appConfigService .loadAppConfig() @@ -26,12 +30,15 @@ export function keycloakInitializer(keycloak: KeycloakService, appConfigService: initOptions: { checkLoginIframe: false, onLoad: 'check-sso', - silentCheckSsoRedirectUri: window.location.origin + baseUrl + '/assets/oauth/silent-refresh.html', + silentCheckSsoRedirectUri: + window.location.origin + baseUrl + '/assets/oauth/silent-refresh.html', flow: 'standard' }, enableBearerInterceptor: true }; - return keycloak.init(options).then(() => configureAutomaticRedirectToLoginScreen(keycloak)); + return keycloak + .init(options) + .then(() => configureAutomaticRedirectToLoginScreen(keycloak)); }); } diff --git a/apps/red-ui/src/app/modules/auth/red-role.guard.ts b/apps/red-ui/src/app/modules/auth/red-role.guard.ts index a457bfb82..1d9dfecc4 100644 --- a/apps/red-ui/src/app/modules/auth/red-role.guard.ts +++ b/apps/red-ui/src/app/modules/auth/red-role.guard.ts @@ -8,7 +8,11 @@ import { Observable } from 'rxjs'; providedIn: 'root' }) export class RedRoleGuard implements CanActivate { - constructor(protected readonly _router: Router, private readonly _appLoadStateService: AppLoadStateService, private readonly _userService: UserService) {} + constructor( + protected readonly _router: Router, + private readonly _appLoadStateService: AppLoadStateService, + private readonly _userService: UserService + ) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { return new Observable((obs) => { @@ -20,7 +24,11 @@ export class RedRoleGuard implements CanActivate { } else { // we have at least 1 RED Role -> if it's not user he must be admin - if (this._userService.user.isUserAdmin && !this._userService.user.isAdmin && !state.url.startsWith('/main/admin/users')) { + if ( + this._userService.user.isUserAdmin && + !this._userService.user.isAdmin && + !state.url.startsWith('/main/admin/users') + ) { this._router.navigate(['/main/admin/users']); obs.next(false); obs.complete(); diff --git a/apps/red-ui/src/app/modules/icons/icons.module.ts b/apps/red-ui/src/app/modules/icons/icons.module.ts index 4a388f7ef..78e1045d3 100644 --- a/apps/red-ui/src/app/modules/icons/icons.module.ts +++ b/apps/red-ui/src/app/modules/icons/icons.module.ts @@ -9,7 +9,10 @@ import { DomSanitizer } from '@angular/platform-browser'; exports: [MatIconModule] }) export class IconsModule { - constructor(private readonly _iconRegistry: MatIconRegistry, private readonly _sanitizer: DomSanitizer) { + constructor( + private readonly _iconRegistry: MatIconRegistry, + private readonly _sanitizer: DomSanitizer + ) { const icons = [ 'add', 'analyse', @@ -84,7 +87,11 @@ export class IconsModule { ]; for (const icon of icons) { - _iconRegistry.addSvgIconInNamespace('red', icon, _sanitizer.bypassSecurityTrustResourceUrl(`/assets/icons/general/${icon}.svg`)); + _iconRegistry.addSvgIconInNamespace( + 'red', + icon, + _sanitizer.bypassSecurityTrustResourceUrl(`/assets/icons/general/${icon}.svg`) + ); } } } diff --git a/apps/red-ui/src/app/modules/projects/components/annotation-actions/annotation-actions.component.html b/apps/red-ui/src/app/modules/projects/components/annotation-actions/annotation-actions.component.html index 936fdffbe..2fbf16500 100644 --- a/apps/red-ui/src/app/modules/projects/components/annotation-actions/annotation-actions.component.html +++ b/apps/red-ui/src/app/modules/projects/components/annotation-actions/annotation-actions.component.html @@ -10,7 +10,13 @@ -
- +
+
-
- +
+
-
+
diff --git a/apps/red-ui/src/app/modules/projects/components/annotation-remove-actions/annotation-remove-actions.component.ts b/apps/red-ui/src/app/modules/projects/components/annotation-remove-actions/annotation-remove-actions.component.ts index 69b8cef19..897641459 100644 --- a/apps/red-ui/src/app/modules/projects/components/annotation-remove-actions/annotation-remove-actions.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/annotation-remove-actions/annotation-remove-actions.component.ts @@ -65,20 +65,44 @@ export class AnnotationRemoveActionsComponent { suggestRemoveAnnotations($event, removeFromDict: boolean) { $event.stopPropagation(); - this._annotationActionsService.suggestRemoveAnnotation($event, this.annotations, removeFromDict, this.annotationsChanged); + this._annotationActionsService.suggestRemoveAnnotation( + $event, + this.annotations, + removeFromDict, + this.annotationsChanged + ); } markAsFalsePositive($event) { - this._annotationActionsService.markAsFalsePositive($event, this.annotations, this.annotationsChanged); + this._annotationActionsService.markAsFalsePositive( + $event, + this.annotations, + this.annotationsChanged + ); } private _setPermissions() { this.permissions = { - canRemoveOrSuggestToRemoveOnlyHere: this._annotationsPermissions(['canRemoveOrSuggestToRemoveOnlyHere'], true), - canPerformMultipleRemoveActions: this._annotationsPermissions(['canPerformMultipleRemoveActions'], true), - canNotPerformMultipleRemoveActions: this._annotationsPermissions(['canPerformMultipleRemoveActions'], false), - canRemoveOrSuggestToRemoveFromDictionary: this._annotationsPermissions(['canRemoveOrSuggestToRemoveFromDictionary'], true), - canMarkAsFalsePositive: this._annotationsPermissions(['canMarkAsFalsePositive', 'canMarkTextOnlyAsFalsePositive'], true) + canRemoveOrSuggestToRemoveOnlyHere: this._annotationsPermissions( + ['canRemoveOrSuggestToRemoveOnlyHere'], + true + ), + canPerformMultipleRemoveActions: this._annotationsPermissions( + ['canPerformMultipleRemoveActions'], + true + ), + canNotPerformMultipleRemoveActions: this._annotationsPermissions( + ['canPerformMultipleRemoveActions'], + false + ), + canRemoveOrSuggestToRemoveFromDictionary: this._annotationsPermissions( + ['canRemoveOrSuggestToRemoveFromDictionary'], + true + ), + canMarkAsFalsePositive: this._annotationsPermissions( + ['canMarkAsFalsePositive', 'canMarkTextOnlyAsFalsePositive'], + true + ) }; } @@ -89,7 +113,10 @@ export class AnnotationRemoveActionsComponent { this._permissionsService.currentUser, annotation ); - const hasAtLeastOnePermission = keys.reduce((acc, key) => acc || annotationPermissions[key] === expectedValue, false); + const hasAtLeastOnePermission = keys.reduce( + (acc, key) => acc || annotationPermissions[key] === expectedValue, + false + ); return prevValue && hasAtLeastOnePermission; }, true); } diff --git a/apps/red-ui/src/app/modules/projects/components/bulk-actions/project-overview-bulk-actions.component.html b/apps/red-ui/src/app/modules/projects/components/bulk-actions/project-overview-bulk-actions.component.html index 20c695b5b..e51a4f28a 100644 --- a/apps/red-ui/src/app/modules/projects/components/bulk-actions/project-overview-bulk-actions.component.html +++ b/apps/red-ui/src/app/modules/projects/components/bulk-actions/project-overview-bulk-actions.component.html @@ -15,7 +15,10 @@ type="dark-bg" > - + - + @@ -41,10 +50,22 @@ - + - + this._appStateService.getFileById(this._appStateService.activeProject.project.projectId, fileId)); + return this.selectedFileIds.map((fileId) => + this._appStateService.getFileById( + this._appStateService.activeProject.project.projectId, + fileId + ) + ); } get areAllFilesSelected() { - return this._appStateService.activeProject.files.length !== 0 && this.selectedFileIds.length === this._appStateService.activeProject.files.length; + return ( + this._appStateService.activeProject.files.length !== 0 && + this.selectedFileIds.length === this._appStateService.activeProject.files.length + ); } get areSomeFilesSelected() { @@ -51,19 +62,31 @@ export class ProjectOverviewBulkActionsComponent { } get canDelete() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canDeleteFile(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canDeleteFile(file), + true + ); } get canAssign() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canAssignReviewer(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canAssignReviewer(file), + true + ); } get canReanalyse() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canReanalyseFile(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canReanalyseFile(file), + true + ); } get canOcr() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canOcrFile(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canOcrFile(file), + true + ); } get fileStatuses() { @@ -72,35 +95,55 @@ export class ProjectOverviewBulkActionsComponent { // Under review get canSetToUnderReview() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderReview(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canSetUnderReview(file), + true + ); } // Under approval get canSetToUnderApproval() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canSetUnderApproval(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canSetUnderApproval(file), + true + ); } // Approve get isReadyForApproval() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.isReadyForApproval(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.isReadyForApproval(file), + true + ); } get canApprove() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canApprove(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canApprove(file), + true + ); } // Undo approval get canUndoApproval() { - return this.selectedFiles.reduce((acc, file) => acc && this._permissionsService.canUndoApproval(file), true); + return this.selectedFiles.reduce( + (acc, file) => acc && this._permissionsService.canUndoApproval(file), + true + ); } delete() { this.loading = true; - this._dialogService.openDeleteFilesDialog(null, this._appStateService.activeProject.project.projectId, this.selectedFileIds, () => { - this.reload.emit(); - this.loading = false; - this.selectedFileIds.splice(0, this.selectedFileIds.length); - }); + this._dialogService.openDeleteFilesDialog( + null, + this._appStateService.activeProject.project.projectId, + this.selectedFileIds, + () => { + this.reload.emit(); + this.loading = false; + this.selectedFileIds.splice(0, this.selectedFileIds.length); + } + ); } assign() { @@ -112,8 +155,15 @@ export class ProjectOverviewBulkActionsComponent { } async reanalyse() { - const fileIds = this.selectedFiles.filter((file) => this._permissionsService.fileRequiresReanalysis(file)).map((file) => file.fileId); - this._performBulkAction(this._reanalysisControllerService.reanalyzeFilesForProject(fileIds, this._appStateService.activeProject.projectId)); + const fileIds = this.selectedFiles + .filter((file) => this._permissionsService.fileRequiresReanalysis(file)) + .map((file) => file.fileId); + this._performBulkAction( + this._reanalysisControllerService.reanalyzeFilesForProject( + fileIds, + this._appStateService.activeProject.projectId + ) + ); } ocr() { diff --git a/apps/red-ui/src/app/modules/projects/components/comments/comments.component.html b/apps/red-ui/src/app/modules/projects/components/comments/comments.component.html index 68c459c82..abd019aa0 100644 --- a/apps/red-ui/src/app/modules/projects/components/comments/comments.component.html +++ b/apps/red-ui/src/app/modules/projects/components/comments/comments.component.html @@ -1,10 +1,20 @@
-
- +
+
-
+
@@ -20,9 +30,14 @@ {{ expanded ? translateService.instant('comments.hide-comments') - : translateService.instant(annotation.comments.length === 1 ? 'comments.comment' : 'comments.comments', { - count: annotation.comments.length - }) + : translateService.instant( + annotation.comments.length === 1 + ? 'comments.comment' + : 'comments.comments', + { + count: annotation.comments.length + } + ) }}
- +
- +
- -
+ +
diff --git a/apps/red-ui/src/app/modules/projects/components/comments/comments.component.ts b/apps/red-ui/src/app/modules/projects/components/comments/comments.component.ts index 30a1c421b..7dd82fc20 100644 --- a/apps/red-ui/src/app/modules/projects/components/comments/comments.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/comments/comments.component.ts @@ -58,25 +58,29 @@ export class CommentsComponent { addComment(): void { const value = this.commentForm.value.comment; if (value) { - this._manualAnnotationService.addComment(value, this.annotation.id).subscribe((commentResponse) => { - this.annotation.comments.push({ - text: value, - id: commentResponse.commentId, - user: this._userService.userId + this._manualAnnotationService + .addComment(value, this.annotation.id) + .subscribe((commentResponse) => { + this.annotation.comments.push({ + text: value, + id: commentResponse.commentId, + user: this._userService.userId + }); }); - }); this.commentForm.reset(); this.toggleAddingComment(); } } deleteComment(comment: Comment): void { - this._manualAnnotationService.deleteComment(comment.id, this.annotation.id).subscribe(() => { - this.annotation.comments.splice(this.annotation.comments.indexOf(comment), 1); - if (!this.annotation.comments.length) { - this.expanded = false; - } - }); + this._manualAnnotationService + .deleteComment(comment.id, this.annotation.id) + .subscribe(() => { + this.annotation.comments.splice(this.annotation.comments.indexOf(comment), 1); + if (!this.annotation.comments.length) { + this.expanded = false; + } + }); } isCommentOwner(comment: Comment): boolean { diff --git a/apps/red-ui/src/app/modules/projects/components/document-info/document-info.component.html b/apps/red-ui/src/app/modules/projects/components/document-info/document-info.component.html index 027063856..afea53c5d 100644 --- a/apps/red-ui/src/app/modules/projects/components/document-info/document-info.component.html +++ b/apps/red-ui/src/app/modules/projects/components/document-info/document-info.component.html @@ -26,19 +26,31 @@
- {{ 'file-preview.tabs.document-info.details.project' | translate: { projectName: project.name } }} + {{ + '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.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.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.due' + | translate: { date: project.project.dueDate | date: 'mediumDate' } + }}
diff --git a/apps/red-ui/src/app/modules/projects/components/document-info/document-info.component.ts b/apps/red-ui/src/app/modules/projects/components/document-info/document-info.component.ts index 443ef4c89..5c3b73055 100644 --- a/apps/red-ui/src/app/modules/projects/components/document-info/document-info.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/document-info/document-info.component.ts @@ -14,7 +14,10 @@ export class DocumentInfoComponent { fileAttributesConfig: FileAttributesConfig; - constructor(private readonly _appStateService: AppStateService, private readonly _dialogService: ProjectsDialogService) { + constructor( + private readonly _appStateService: AppStateService, + private readonly _dialogService: ProjectsDialogService + ) { this.fileAttributesConfig = this._appStateService.activeFileAttributesConfig; } diff --git a/apps/red-ui/src/app/modules/projects/components/file-actions/file-actions.component.html b/apps/red-ui/src/app/modules/projects/components/file-actions/file-actions.component.html index 4d10597f0..cefb7423f 100644 --- a/apps/red-ui/src/app/modules/projects/components/file-actions/file-actions.component.html +++ b/apps/red-ui/src/app/modules/projects/components/file-actions/file-actions.component.html @@ -31,10 +31,16 @@ @@ -86,7 +92,11 @@ *ngIf="permissionsService.isReadyForApproval(fileStatus)" [disabled]="!permissionsService.canApprove(fileStatus)" [tooltipPosition]="tooltipPosition" - [tooltip]="permissionsService.canApprove(fileStatus) ? 'project-overview.approve' : 'project-overview.approve-disabled'" + [tooltip]=" + permissionsService.canApprove(fileStatus) + ? 'project-overview.approve' + : 'project-overview.approve-disabled' + " [type]="buttonType" icon="red:approved" > diff --git a/apps/red-ui/src/app/modules/projects/components/file-actions/file-actions.component.ts b/apps/red-ui/src/app/modules/projects/components/file-actions/file-actions.component.ts index 948ea01c7..dcc3ec7ec 100644 --- a/apps/red-ui/src/app/modules/projects/components/file-actions/file-actions.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/file-actions/file-actions.component.ts @@ -38,7 +38,9 @@ export class FileActionsComponent implements OnInit { return 'file-preview.toggle-analysis.only-managers'; } - return this.fileStatus?.isExcluded ? 'file-preview.toggle-analysis.enable' : 'file-preview.toggle-analysis.disable'; + return this.fileStatus?.isExcluded + ? 'file-preview.toggle-analysis.enable' + : 'file-preview.toggle-analysis.disable'; } ngOnInit(): void { @@ -60,14 +62,21 @@ export class FileActionsComponent implements OnInit { } openDeleteFileDialog($event: MouseEvent, fileStatusWrapper: FileStatusWrapper) { - this._dialogService.openDeleteFilesDialog($event, fileStatusWrapper.projectId, [fileStatusWrapper.fileId], () => { - this.actionPerformed.emit('delete'); - }); + this._dialogService.openDeleteFilesDialog( + $event, + fileStatusWrapper.projectId, + [fileStatusWrapper.fileId], + () => { + this.actionPerformed.emit('delete'); + } + ); } async assignReviewer($event: MouseEvent, file: FileStatusWrapper) { $event.stopPropagation(); - await this._fileActionService.assignProjectReviewerFromOverview(file, () => this.actionPerformed.emit('assign-reviewer')); + await this._fileActionService.assignProjectReviewerFromOverview(file, () => + this.actionPerformed.emit('assign-reviewer') + ); } reanalyseFile($event: MouseEvent, fileStatusWrapper: FileStatusWrapper, priority = -1) { @@ -98,12 +107,20 @@ export class FileActionsComponent implements OnInit { }); } - setFileUnderReview($event: MouseEvent, fileStatus: FileStatusWrapper, ignoreDialogChanges = false) { + setFileUnderReview( + $event: MouseEvent, + fileStatus: FileStatusWrapper, + ignoreDialogChanges = false + ) { $event.stopPropagation(); // this._fileActionService.setFileUnderReview(fileStatus).subscribe(() => { // this.reloadProjects('set-review'); // }); - this._fileActionService.assignProjectReviewer(fileStatus, () => this.actionPerformed.emit('assign-reviewer'), ignoreDialogChanges); + this._fileActionService.assignProjectReviewer( + fileStatus, + () => this.actionPerformed.emit('assign-reviewer'), + ignoreDialogChanges + ); } reloadProjects(action: string) { @@ -116,6 +133,8 @@ export class FileActionsComponent implements OnInit { $event.stopPropagation(); await this._fileActionService.toggleAnalysis(this.fileStatus).toPromise(); await this.appStateService.getFiles(); - this.actionPerformed.emit(this.fileStatus?.isExcluded ? 'enable-analysis' : 'disable-analysis'); + this.actionPerformed.emit( + this.fileStatus?.isExcluded ? 'enable-analysis' : 'disable-analysis' + ); } } diff --git a/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.html index 41a8dd59a..44f74eff2 100644 --- a/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.html +++ b/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.html @@ -33,7 +33,11 @@ tooltipPosition="above" >
- +
{{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }} - {{ activeViewerPage }} - + {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }} +
-
All
-
None
+
+ All +
+
+ None +
@@ -98,7 +113,12 @@ tabindex="1" > - +
- +
- +
{{ annotation.typeLabel | translate }}
-
+
{{ annotation.descriptor | translate }}: {{ annotation.dictionary | humanize: false }}
- : {{ annotation.content }} + : {{ annotation.content }}
{{ annotation.id }}
@@ -155,7 +188,9 @@
@@ -170,16 +205,25 @@
- + - + {{ filter.key | humanize: false }} - + diff --git a/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.ts index d94baac43..fcee9cb23 100644 --- a/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/file-workload/file-workload.component.ts @@ -1,4 +1,14 @@ -import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + ElementRef, + EventEmitter, + HostListener, + Input, + Output, + TemplateRef, + ViewChild +} from '@angular/core'; import { FilterModel } from '@shared/components/filter/model/filter.model'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { AnnotationProcessingService } from '../../services/annotation-processing.service'; @@ -27,7 +37,9 @@ export class FileWorkloadComponent { @Input() hideSkipped: boolean; @Input() annotationActionsTemplate: TemplateRef; @Output() shouldDeselectAnnotationsOnPageChangeChange = new EventEmitter(); - @Output() selectAnnotations = new EventEmitter(); + @Output() selectAnnotations = new EventEmitter< + AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean } + >(); @Output() deselectAnnotations = new EventEmitter(); @Output() selectPage = new EventEmitter(); @Output() toggleSkipped = new EventEmitter(); @@ -39,7 +51,10 @@ export class FileWorkloadComponent { @ViewChild('annotationsElement') private _annotationsElement: ElementRef; @ViewChild('quickNavigation') private _quickNavigationElement: ElementRef; - constructor(private readonly _changeDetectorRef: ChangeDetectorRef, private readonly _annotationProcessingService: AnnotationProcessingService) {} + constructor( + private readonly _changeDetectorRef: ChangeDetectorRef, + private readonly _annotationProcessingService: AnnotationProcessingService + ) {} private _annotations: AnnotationWrapper[]; @@ -68,7 +83,10 @@ export class FileWorkloadComponent { return this.selectedAnnotations?.length ? this.selectedAnnotations[0] : null; } - private static _scrollToFirstElement(elements: HTMLElement[], mode: 'always' | 'if-needed' = 'if-needed') { + private static _scrollToFirstElement( + elements: HTMLElement[], + mode: 'always' | 'if-needed' = 'if-needed' + ) { if (elements.length > 0) { scrollIntoView(elements[0], { behavior: 'smooth', @@ -88,7 +106,9 @@ export class FileWorkloadComponent { } pageHasSelection(page: number) { - return this.multiSelectActive && !!this.selectedAnnotations?.find((a) => a.pageNumber === page); + return ( + this.multiSelectActive && !!this.selectedAnnotations?.find((a) => a.pageNumber === page) + ); } selectAllOnActivePage() { @@ -103,7 +123,11 @@ export class FileWorkloadComponent { @debounce(0) filtersChanged(filters: { primary: FilterModel[]; secondary?: FilterModel[] }) { - this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(this._annotations, filters.primary, filters.secondary); + this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations( + this._annotations, + filters.primary, + filters.secondary + ); this.displayedPages = Object.keys(this.displayedAnnotations).map((key) => Number(key)); this.computeQuickNavButtonsState(); this._changeDetectorRef.markForCheck(); @@ -111,7 +135,8 @@ export class FileWorkloadComponent { computeQuickNavButtonsState() { setTimeout(() => { - const element: HTMLElement = this._quickNavigationElement.nativeElement.querySelector(`#pages`); + const element: HTMLElement = + this._quickNavigationElement.nativeElement.querySelector(`#pages`); const { scrollTop, scrollHeight, clientHeight } = element; this.quickScrollFirstEnabled = scrollTop !== 0; this.quickScrollLastEnabled = scrollHeight !== scrollTop + clientHeight; @@ -126,13 +151,20 @@ export class FileWorkloadComponent { if (($event.ctrlKey || $event.metaKey) && this.selectedAnnotations.length > 0) { this.multiSelectActive = true; } - this.selectAnnotations.emit({ annotations: [annotation], multiSelect: this.multiSelectActive }); + this.selectAnnotations.emit({ + annotations: [annotation], + multiSelect: this.multiSelectActive + }); } } @HostListener('window:keyup', ['$event']) handleKeyEvent($event: KeyboardEvent) { - if (!ALL_HOTKEY_ARRAY.includes($event.key) || this.dialogRef?.getState() === MatDialogState.OPEN || ($event.target as any).localName === 'input') { + if ( + !ALL_HOTKEY_ARRAY.includes($event.key) || + this.dialogRef?.getState() === MatDialogState.OPEN || + ($event.target as any).localName === 'input' + ) { return; } @@ -143,7 +175,8 @@ export class FileWorkloadComponent { if ($event.key === 'ArrowRight') { this.pagesPanelActive = false; - // if we activated annotationsPanel - select first annotation from this page in case there is no + // if we activated annotationsPanel - + // select first annotation from this page in case there is no // selected annotation on this page and not in multi select mode if (!this.pagesPanelActive && !this.multiSelectActive) { this._selectFirstAnnotationOnCurrentPageIfNecessary(); @@ -152,7 +185,8 @@ export class FileWorkloadComponent { } if (!this.pagesPanelActive) { - // Disable annotation navigation in multi select mode => TODO: maybe implement selection on enter? + // Disable annotation navigation in multi select mode + // => TODO: maybe implement selection on enter? if (!this.multiSelectActive) { this._navigateAnnotations($event); } @@ -171,7 +205,9 @@ export class FileWorkloadComponent { } scrollAnnotationsToPage(page: number, mode: 'always' | 'if-needed' = 'if-needed') { - const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[anotation-page-header="${page}"]`); + const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll( + `div[anotation-page-header="${page}"]` + ); FileWorkloadComponent._scrollToFirstElement(elements, mode); } @@ -180,13 +216,18 @@ export class FileWorkloadComponent { if (!this.selectedAnnotations || this.selectedAnnotations.length === 0) { return; } - const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll(`div[annotation-id="${this._firstSelectedAnnotation?.id}"].active`); + const elements: any[] = this._annotationsElement.nativeElement.querySelectorAll( + `div[annotation-id="${this._firstSelectedAnnotation?.id}"].active` + ); FileWorkloadComponent._scrollToFirstElement(elements); } scrollQuickNavigation() { let quickNavPageIndex = this.displayedPages.findIndex((p) => p >= this.activeViewerPage); - if (quickNavPageIndex === -1 || this.displayedPages[quickNavPageIndex] !== this.activeViewerPage) { + if ( + quickNavPageIndex === -1 || + this.displayedPages[quickNavPageIndex] !== this.activeViewerPage + ) { quickNavPageIndex = Math.max(0, quickNavPageIndex - 1); } this._scrollQuickNavigationToPage(this.displayedPages[quickNavPageIndex]); @@ -210,7 +251,10 @@ export class FileWorkloadComponent { } preventKeyDefault($event: KeyboardEvent) { - if (COMMAND_KEY_ARRAY.includes($event.key) && !(($event.target as any).localName === 'input')) { + if ( + COMMAND_KEY_ARRAY.includes($event.key) && + !(($event.target as any).localName === 'input') + ) { $event.preventDefault(); } } @@ -229,39 +273,53 @@ export class FileWorkloadComponent { private _selectFirstAnnotationOnCurrentPageIfNecessary() { if ( - (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) && + (!this._firstSelectedAnnotation || + this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) && this.displayedPages.indexOf(this.activeViewerPage) >= 0 ) { - this.selectAnnotations.emit([this.displayedAnnotations[this.activeViewerPage].annotations[0]]); + this.selectAnnotations.emit([ + this.displayedAnnotations[this.activeViewerPage].annotations[0] + ]); } } private _navigateAnnotations($event: KeyboardEvent) { - if (!this._firstSelectedAnnotation || this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber) { + if ( + !this._firstSelectedAnnotation || + this.activeViewerPage !== this._firstSelectedAnnotation.pageNumber + ) { const pageIdx = this.displayedPages.indexOf(this.activeViewerPage); if (pageIdx !== -1) { // Displayed page has annotations - this.selectAnnotations.emit([this.displayedAnnotations[this.activeViewerPage].annotations[0]]); + this.selectAnnotations.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.shouldDeselectAnnotationsOnPageChangeChange.emit(false); - this.selectAnnotations.emit([this.displayedAnnotations[nextPage].annotations[0]]); + this.selectAnnotations.emit([ + this.displayedAnnotations[nextPage].annotations[0] + ]); } else { const prevPage = this._prevPageWithAnnotations(); this.shouldDeselectAnnotationsOnPageChange = false; this.shouldDeselectAnnotationsOnPageChangeChange.emit(false); const prevPageAnnotations = this.displayedAnnotations[prevPage].annotations; - this.selectAnnotations.emit([prevPageAnnotations[prevPageAnnotations.length - 1]]); + this.selectAnnotations.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); + const idx = annotationsOnPage.findIndex( + (a) => a.id === this._firstSelectedAnnotation.id + ); if ($event.key === 'ArrowDown') { if (idx + 1 !== annotationsOnPage.length) { @@ -269,7 +327,8 @@ export class FileWorkloadComponent { this.selectAnnotations.emit([annotationsOnPage[idx + 1]]); } else if (pageIdx + 1 < this.displayedPages.length) { // If not last page - const nextPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx + 1]].annotations; + const nextPageAnnotations = + this.displayedAnnotations[this.displayedPages[pageIdx + 1]].annotations; this.shouldDeselectAnnotationsOnPageChange = false; this.shouldDeselectAnnotationsOnPageChangeChange.emit(false); this.selectAnnotations.emit([nextPageAnnotations[0]]); @@ -280,10 +339,13 @@ export class FileWorkloadComponent { this.selectAnnotations.emit([annotationsOnPage[idx - 1]]); } else if (pageIdx) { // If not first page - const prevPageAnnotations = this.displayedAnnotations[this.displayedPages[pageIdx - 1]].annotations; + const prevPageAnnotations = + this.displayedAnnotations[this.displayedPages[pageIdx - 1]].annotations; this.shouldDeselectAnnotationsOnPageChange = false; this.shouldDeselectAnnotationsOnPageChangeChange.emit(false); - this.selectAnnotations.emit([prevPageAnnotations[prevPageAnnotations.length - 1]]); + this.selectAnnotations.emit([ + prevPageAnnotations[prevPageAnnotations.length - 1] + ]); } } } @@ -345,7 +407,9 @@ export class FileWorkloadComponent { } private _scrollQuickNavigationToPage(page: number) { - const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(`#quick-nav-page-${page}`); + const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll( + `#quick-nav-page-${page}` + ); FileWorkloadComponent._scrollToFirstElement(elements); } } diff --git a/apps/red-ui/src/app/modules/projects/components/needs-work-badge/needs-work-badge.component.html b/apps/red-ui/src/app/modules/projects/components/needs-work-badge/needs-work-badge.component.html index ced0314a7..0a14004fe 100644 --- a/apps/red-ui/src/app/modules/projects/components/needs-work-badge/needs-work-badge.component.html +++ b/apps/red-ui/src/app/modules/projects/components/needs-work-badge/needs-work-badge.component.html @@ -1,9 +1,39 @@
- - - - - - + + + + + +
diff --git a/apps/red-ui/src/app/modules/projects/components/needs-work-badge/needs-work-badge.component.ts b/apps/red-ui/src/app/modules/projects/components/needs-work-badge/needs-work-badge.component.ts index 7fc415b67..45dd53f38 100644 --- a/apps/red-ui/src/app/modules/projects/components/needs-work-badge/needs-work-badge.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/needs-work-badge/needs-work-badge.component.ts @@ -12,7 +12,10 @@ import { ProjectWrapper } from '@state/model/project.wrapper'; export class NeedsWorkBadgeComponent { @Input() needsWorkInput: FileStatusWrapper | ProjectWrapper; - constructor(private readonly _appStateService: AppStateService, private readonly _permissionsService: PermissionsService) {} + constructor( + private readonly _appStateService: AppStateService, + private readonly _permissionsService: PermissionsService + ) {} get suggestionColor() { return this._getDictionaryColor('suggestion'); @@ -47,7 +50,10 @@ export class NeedsWorkBadgeComponent { } get hasAnnotationComments(): boolean { - return this.needsWorkInput instanceof FileStatusWrapper && (this.needsWorkInput).hasAnnotationComments; + return ( + this.needsWorkInput instanceof FileStatusWrapper && + (this.needsWorkInput).hasAnnotationComments + ); } reanalysisRequired() { diff --git a/apps/red-ui/src/app/modules/projects/components/page-indicator/page-indicator.component.ts b/apps/red-ui/src/app/modules/projects/components/page-indicator/page-indicator.component.ts index f7b1e8e65..95f63ad02 100644 --- a/apps/red-ui/src/app/modules/projects/components/page-indicator/page-indicator.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/page-indicator/page-indicator.component.ts @@ -1,4 +1,13 @@ -import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core'; +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 '@services/permissions.service'; @@ -95,15 +104,25 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy { private _markPageRead() { this._viewedPagesControllerService - .addPage({ page: this.number }, this._appStateService.activeProjectId, this._appStateService.activeFileId) + .addPage( + { page: this.number }, + this._appStateService.activeProjectId, + this._appStateService.activeFileId + ) .subscribe(() => { this.viewedPages?.pages?.push(this.number); }); } private _markPageUnread() { - this._viewedPagesControllerService.removePage(this._appStateService.activeProjectId, this._appStateService.activeFileId, this.number).subscribe(() => { - this.viewedPages?.pages?.splice(this.viewedPages?.pages?.indexOf(this.number), 1); - }); + this._viewedPagesControllerService + .removePage( + this._appStateService.activeProjectId, + this._appStateService.activeFileId, + this.number + ) + .subscribe(() => { + this.viewedPages?.pages?.splice(this.viewedPages?.pages?.indexOf(this.number), 1); + }); } } diff --git a/apps/red-ui/src/app/modules/projects/components/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/modules/projects/components/pdf-viewer/pdf-viewer.component.ts index 2fa608302..7529fa3b6 100644 --- a/apps/red-ui/src/app/modules/projects/components/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/pdf-viewer/pdf-viewer.component.ts @@ -1,4 +1,17 @@ -import { AfterViewInit, Component, ElementRef, EventEmitter, Inject, Input, NgZone, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'; +import { + AfterViewInit, + Component, + ElementRef, + EventEmitter, + Inject, + Input, + NgZone, + OnChanges, + OnInit, + Output, + SimpleChanges, + ViewChild +} from '@angular/core'; import { ManualRedactionEntry, Rectangle } from '@redaction/red-ui-http'; import WebViewer, { Annotations, Tools, WebViewerInstance } from '@pdftron/webviewer'; import { TranslateService } from '@ngx-translate/core'; @@ -72,7 +85,9 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { this.instance.annotManager.deselectAllAnnotations(); } - selectAnnotations($event: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }) { + selectAnnotations( + $event: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean } + ) { let annotations: AnnotationWrapper[]; let multiSelect: boolean; if ($event instanceof Array) { @@ -87,14 +102,18 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { this.deselectAllAnnotations(); } - const annotationsFromViewer = annotations.map((ann) => this.instance.annotManager.getAnnotationById(ann.id)); + const annotationsFromViewer = annotations.map((ann) => + this.instance.annotManager.getAnnotationById(ann.id) + ); this.instance.annotManager.selectAnnotations(annotationsFromViewer); this.navigateToPage(annotations[0].pageNumber); this.instance.annotManager.jumpToAnnotation(annotationsFromViewer[0]); } deselectAnnotations(annotations: AnnotationWrapper[]) { - this.instance.annotManager.deselectAnnotations(annotations.map((ann) => this.instance.annotManager.getAnnotationById(ann.id))); + this.instance.annotManager.deselectAnnotations( + annotations.map((ann) => this.instance.annotManager.getAnnotationById(ann.id)) + ); } navigateToPage(pageNumber: number) { @@ -107,7 +126,9 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { setInitialViewerState() { // viewer init this.instance.setFitMode('FitPage'); - const instanceDisplayMode = this.instance.docViewer.getDisplayModeManager().getDisplayMode(); + const instanceDisplayMode = this.instance.docViewer + .getDisplayModeManager() + .getDisplayMode(); instanceDisplayMode.mode = 'Single'; this.instance.docViewer.getDisplayModeManager().setDisplayMode(instanceDisplayMode); } @@ -127,20 +148,28 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { this._configureTextPopup(); instance.annotManager.on('annotationSelected', (annotations, action) => { - this.annotationSelected.emit(instance.annotManager.getSelectedAnnotations().map((ann) => ann.Id)); + this.annotationSelected.emit( + instance.annotManager.getSelectedAnnotations().map((ann) => ann.Id) + ); if (action === 'deselected') { this._toggleRectangleAnnotationAction(true); } else { this._configureAnnotationSpecificActions(annotations); - this._toggleRectangleAnnotationAction(annotations.length === 1 && annotations[0].ReadOnly); + this._toggleRectangleAnnotationAction( + annotations.length === 1 && annotations[0].ReadOnly + ); // this.annotationSelected.emit(annotations.map((a) => a.Id)); } }); instance.annotManager.on('annotationChanged', (annotations) => { - // when a rectangle is drawn, it returns one annotation with tool name 'AnnotationCreateRectangle; + // when a rectangle is drawn, + // it returns one annotation with tool name 'AnnotationCreateRectangle; // this will auto select rectangle after drawing - if (annotations.length === 1 && annotations[0].ToolName === 'AnnotationCreateRectangle') { + if ( + annotations.length === 1 && + annotations[0].ToolName === 'AnnotationCreateRectangle' + ) { instance.annotManager.selectAnnotations(annotations); } }); @@ -183,7 +212,9 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { instance.iframeWindow.addEventListener('visibilityChanged', (event: any) => { if (event.detail.element === 'searchPanel') { - const inputElement = instance.iframeWindow.document.getElementById('SearchPanel__input') as HTMLInputElement; + const inputElement = instance.iframeWindow.document.getElementById( + 'SearchPanel__input' + ) as HTMLInputElement; setTimeout(() => { inputElement.value = ''; }, 0); @@ -253,43 +284,58 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { private _configureAnnotationSpecificActions(viewerAnnotations: Annotations.Annotation[]) { console.log('configure actions', viewerAnnotations); - if (this.canPerformActions) { - const annotationWrappers = viewerAnnotations.map((va) => this.annotations.find((a) => a.id === va.Id)).filter((va) => !!va); - this.instance.annotationPopup.update([]); - - if (annotationWrappers.length === 0) { - this._configureRectangleAnnotationPopup(); - return; - } - - // Add hide action as last item - const allAnnotationsHaveImageAction = annotationWrappers.reduce((acc, next) => acc && next.isImage, true); - if (allAnnotationsHaveImageAction) { - const allAreVisible = viewerAnnotations.reduce((acc, next) => next.isVisible() && acc, true); - - this.instance.annotationPopup.add([ - { - type: 'actionButton', - img: allAreVisible - ? this._convertPath('/assets/icons/general/visibility-off.svg') - : this._convertPath('/assets/icons/general/visibility.svg'), - title: this._translateService.instant('annotation-actions.hide'), - onClick: () => { - this._ngZone.run(() => { - if (allAreVisible) { - this.instance.annotManager.hideAnnotations(viewerAnnotations); - } else { - this.instance.annotManager.showAnnotations(viewerAnnotations); - } - this.instance.annotManager.deselectAllAnnotations(); - }); - } - } - ]); - } - - this.instance.annotationPopup.add(this._annotationActionsService.getViewerAvailableActions(annotationWrappers, this.annotationsChanged)); + if (!this.canPerformActions) { + return; } + + const annotationWrappers = viewerAnnotations + .map((va) => this.annotations.find((a) => a.id === va.Id)) + .filter((va) => !!va); + this.instance.annotationPopup.update([]); + + if (annotationWrappers.length === 0) { + this._configureRectangleAnnotationPopup(); + return; + } + + // Add hide action as last item + const allAnnotationsHaveImageAction = annotationWrappers.reduce( + (acc, next) => acc && next.isImage, + true + ); + if (allAnnotationsHaveImageAction) { + const allAreVisible = viewerAnnotations.reduce( + (acc, next) => next.isVisible() && acc, + true + ); + + this.instance.annotationPopup.add([ + { + type: 'actionButton', + img: allAreVisible + ? this._convertPath('/assets/icons/general/visibility-off.svg') + : this._convertPath('/assets/icons/general/visibility.svg'), + title: this._translateService.instant('annotation-actions.hide'), + onClick: () => { + this._ngZone.run(() => { + if (allAreVisible) { + this.instance.annotManager.hideAnnotations(viewerAnnotations); + } else { + this.instance.annotManager.showAnnotations(viewerAnnotations); + } + this.instance.annotManager.deselectAllAnnotations(); + }); + } + } + ]); + } + + this.instance.annotationPopup.add( + this._annotationActionsService.getViewerAvailableActions( + annotationWrappers, + this.annotationsChanged + ) + ); } private _configureRectangleAnnotationPopup() { @@ -297,12 +343,17 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { type: 'actionButton', dataElement: 'add-rectangle', img: this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'), - title: this._translateService.instant(this._manualAnnotationService.getTitle('REDACTION')), + title: this._translateService.instant( + this._manualAnnotationService.getTitle('REDACTION') + ), onClick: () => { const selectedAnnotations = this.instance.annotManager.getSelectedAnnotations(); const activeAnnotation = selectedAnnotations[0]; const activePage = selectedAnnotations[0].getPageNumber(); - const quad = this._annotationDrawService.annotationToQuads(activeAnnotation, this.instance); + const quad = this._annotationDrawService.annotationToQuads( + activeAnnotation, + this.instance + ); const quadsObject = {}; quadsObject[activePage] = [quad]; const mre = this._getManualRedactionEntry(quadsObject, 'Rectangle'); @@ -311,7 +362,15 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { this.instance.disableElements(['shapeToolGroupButton']); this.instance.enableElements(['shapeToolGroupButton']); // dispatch event - this.manualAnnotationRequested.emit(new ManualRedactionEntryWrapper([quad], mre, 'REDACTION', 'RECTANGLE', activeAnnotation.Id)); + this.manualAnnotationRequested.emit( + new ManualRedactionEntryWrapper( + [quad], + mre, + 'REDACTION', + 'RECTANGLE', + activeAnnotation.Id + ) + ); } }); } @@ -344,12 +403,20 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { type: 'actionButton', dataElement: 'add-false-positive', img: this._convertPath('/assets/icons/general/pdftron-action-false-positive.svg'), - title: this._translateService.instant(this._manualAnnotationService.getTitle('FALSE_POSITIVE')), + title: this._translateService.instant( + this._manualAnnotationService.getTitle('FALSE_POSITIVE') + ), onClick: () => { const selectedQuads = this.instance.docViewer.getSelectedTextQuads(); const text = this.instance.docViewer.getSelectedText(); const mre = this._getManualRedactionEntry(selectedQuads, text, true); - this.manualAnnotationRequested.emit(new ManualRedactionEntryWrapper(this.instance.docViewer.getSelectedTextQuads(), mre, 'FALSE_POSITIVE')); + this.manualAnnotationRequested.emit( + new ManualRedactionEntryWrapper( + this.instance.docViewer.getSelectedTextQuads(), + mre, + 'FALSE_POSITIVE' + ) + ); } }); } @@ -358,12 +425,20 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { type: 'actionButton', dataElement: 'add-dictionary', img: this._convertPath('/assets/icons/general/pdftron-action-add-dict.svg'), - title: this._translateService.instant(this._manualAnnotationService.getTitle('DICTIONARY')), + title: this._translateService.instant( + this._manualAnnotationService.getTitle('DICTIONARY') + ), onClick: () => { const selectedQuads = this.instance.docViewer.getSelectedTextQuads(); const text = this.instance.docViewer.getSelectedText(); const mre = this._getManualRedactionEntry(selectedQuads, text, true); - this.manualAnnotationRequested.emit(new ManualRedactionEntryWrapper(this.instance.docViewer.getSelectedTextQuads(), mre, 'DICTIONARY')); + this.manualAnnotationRequested.emit( + new ManualRedactionEntryWrapper( + this.instance.docViewer.getSelectedTextQuads(), + mre, + 'DICTIONARY' + ) + ); } }); @@ -371,12 +446,20 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { type: 'actionButton', dataElement: 'add-redaction', img: this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'), - title: this._translateService.instant(this._manualAnnotationService.getTitle('REDACTION')), + title: this._translateService.instant( + this._manualAnnotationService.getTitle('REDACTION') + ), onClick: () => { const selectedQuads = this.instance.docViewer.getSelectedTextQuads(); const text = this.instance.docViewer.getSelectedText(); const mre = this._getManualRedactionEntry(selectedQuads, text, true); - this.manualAnnotationRequested.emit(new ManualRedactionEntryWrapper(this.instance.docViewer.getSelectedTextQuads(), mre, 'REDACTION')); + this.manualAnnotationRequested.emit( + new ManualRedactionEntryWrapper( + this.instance.docViewer.getSelectedTextQuads(), + mre, + 'REDACTION' + ) + ); } }); this._handleCustomActions(); @@ -386,7 +469,13 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { this.instance.setToolMode('AnnotationEdit'); if (this.canPerformActions) { this.instance.enableTools(['AnnotationCreateRectangle']); - this.instance.enableElements(['add-redaction', 'add-rectangle', 'add-false-positive', 'shapeToolGroupButton', 'annotationPopup']); + this.instance.enableElements([ + 'add-redaction', + 'add-rectangle', + 'add-false-positive', + 'shapeToolGroupButton', + 'annotationPopup' + ]); if (this._selectedText.length > 2) { this.instance.enableElements(['add-dictionary', 'add-false-positive']); } @@ -403,13 +492,19 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { } } - private _getManualRedactionEntry(quads: any, text: string, convertQuads: boolean = false): ManualRedactionEntry { + private _getManualRedactionEntry( + quads: any, + text: string, + convertQuads: boolean = false + ): ManualRedactionEntry { text = text.replace(/-\n/gi, ''); const entry: ManualRedactionEntry = { positions: [] }; for (const key of Object.keys(quads)) { for (const quad of quads[key]) { const page = parseInt(key, 10); - entry.positions.push(this._toPosition(page, convertQuads ? this._translateQuads(page, quad) : quad)); + entry.positions.push( + this._toPosition(page, convertQuads ? this._translateQuads(page, quad) : quad) + ); } } entry.value = text; diff --git a/apps/red-ui/src/app/modules/projects/components/project-details/project-details.component.html b/apps/red-ui/src/app/modules/projects/components/project-details/project-details.component.html index 93688a94f..b3039a9e1 100644 --- a/apps/red-ui/src/app/modules/projects/components/project-details/project-details.component.html +++ b/apps/red-ui/src/app/modules/projects/components/project-details/project-details.component.html @@ -53,7 +53,11 @@
-
+
@@ -61,37 +65,63 @@
- {{ 'project-overview.project-details.stats.documents' | translate: { count: appStateService.activeProject.files.length } }} + {{ + 'project-overview.project-details.stats.documents' + | translate: { count: appStateService.activeProject.files.length } + }}
- {{ 'project-overview.project-details.stats.people' | translate: { count: appStateService.activeProject.memberCount } }} + {{ + 'project-overview.project-details.stats.people' + | translate: { count: appStateService.activeProject.memberCount } + }}
{{ - 'project-overview.project-details.stats.analysed-pages' | translate: { count: appStateService.activeProject.totalNumberOfPages | number } + 'project-overview.project-details.stats.analysed-pages' + | translate + : { count: appStateService.activeProject.totalNumberOfPages | number } }}
{{ - 'project-overview.project-details.stats.created-on' | translate: { date: appStateService.activeProject.project.date | date: 'd MMM. yyyy' } + 'project-overview.project-details.stats.created-on' + | translate + : { + date: + appStateService.activeProject.project.date + | date: 'd MMM. yyyy' + } }}
{{ - 'project-overview.project-details.stats.due-date' | translate: { date: appStateService.activeProject.project.dueDate | date: 'd MMM. yyyy' } + 'project-overview.project-details.stats.due-date' + | translate + : { + date: + appStateService.activeProject.project.dueDate + | date: 'd MMM. yyyy' + } }}
- {{ appStateService.getRuleSetById(appStateService.activeProject.ruleSetId)?.name }} + {{ appStateService.getRuleSetById(appStateService.activeProject.ruleSetId)?.name }} +
-
+
{{ 'project-overview.project-details.dictionary' | translate }}
diff --git a/apps/red-ui/src/app/modules/projects/components/project-details/project-details.component.ts b/apps/red-ui/src/app/modules/projects/components/project-details/project-details.component.ts index 04761517b..0535bbc2f 100644 --- a/apps/red-ui/src/app/modules/projects/components/project-details/project-details.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/project-details/project-details.component.ts @@ -51,10 +51,17 @@ export class ProjectDetailsComponent implements OnInit { const groups = groupBy(this.appStateService.activeProject?.files, 'status'); this.documentsChartData = []; for (const key of Object.keys(groups)) { - this.documentsChartData.push({ value: groups[key].length, color: key, label: key, key: key }); + this.documentsChartData.push({ + value: groups[key].length, + color: key, + label: key, + key: key + }); } this.documentsChartData.sort((a, b) => StatusSorter[a.key] - StatusSorter[b.key]); - this.documentsChartData = this.translateChartService.translateStatus(this.documentsChartData); + this.documentsChartData = this.translateChartService.translateStatus( + this.documentsChartData + ); this._changeDetectorRef.detectChanges(); } } diff --git a/apps/red-ui/src/app/modules/projects/components/project-listing-actions/project-listing-actions.component.html b/apps/red-ui/src/app/modules/projects/components/project-listing-actions/project-listing-actions.component.html index 16a7efa5f..199708e26 100644 --- a/apps/red-ui/src/app/modules/projects/components/project-listing-actions/project-listing-actions.component.html +++ b/apps/red-ui/src/app/modules/projects/components/project-listing-actions/project-listing-actions.component.html @@ -36,5 +36,9 @@ > - +
diff --git a/apps/red-ui/src/app/modules/projects/components/project-listing-actions/project-listing-actions.component.ts b/apps/red-ui/src/app/modules/projects/components/project-listing-actions/project-listing-actions.component.ts index 1dfa5f355..86213eace 100644 --- a/apps/red-ui/src/app/modules/projects/components/project-listing-actions/project-listing-actions.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/project-listing-actions/project-listing-actions.component.ts @@ -26,9 +26,13 @@ export class ProjectListingActionsComponent { ) {} openAssignProjectOwnerDialog($event: MouseEvent, project: ProjectWrapper) { - this._dialogService.openAssignProjectMembersAndOwnerDialog($event, project, (pw: ProjectWrapper) => { - this.actionPerformed.emit(pw); - }); + this._dialogService.openAssignProjectMembersAndOwnerDialog( + $event, + project, + (pw: ProjectWrapper) => { + this.actionPerformed.emit(pw); + } + ); } openDeleteProjectDialog($event: MouseEvent, project: ProjectWrapper) { @@ -54,14 +58,25 @@ export class ProjectListingActionsComponent { downloadRedactedFiles($event: MouseEvent, project: ProjectWrapper) { $event.stopPropagation(); this._fileManagementControllerService - .downloadRedactedFiles({ fileIds: project.files.map((file) => file.fileId) }, project.projectId, false, 'response') + .downloadRedactedFiles( + { fileIds: project.files.map((file) => file.fileId) }, + project.projectId, + false, + 'response' + ) .subscribe((data) => { download(data, 'redacted_files_' + computerize(project.name) + '.zip'); }); } canDownloadRedactedFiles(project: ProjectWrapper) { - return project.files.length > 0 && project.files.reduce((acc, file) => acc && this.permissionsService.canDownloadRedactedFile(file), true); + return ( + project.files.length > 0 && + project.files.reduce( + (acc, file) => acc && this.permissionsService.canDownloadRedactedFile(file), + true + ) + ); } getProjectStatusConfig(pw: ProjectWrapper) { diff --git a/apps/red-ui/src/app/modules/projects/components/team-members/team-members.component.html b/apps/red-ui/src/app/modules/projects/components/team-members/team-members.component.html index a78cf5394..625cdb6b8 100644 --- a/apps/red-ui/src/app/modules/projects/components/team-members/team-members.component.html +++ b/apps/red-ui/src/app/modules/projects/components/team-members/team-members.component.html @@ -6,12 +6,20 @@ [class.large-spacing]="largeSpacing" class="member" > - +
-
+
+{{ overflowCount }}
-
+
diff --git a/apps/red-ui/src/app/modules/projects/components/team-members/team-members.component.ts b/apps/red-ui/src/app/modules/projects/components/team-members/team-members.component.ts index 8648cc76a..0df0e7e19 100644 --- a/apps/red-ui/src/app/modules/projects/components/team-members/team-members.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/team-members/team-members.component.ts @@ -27,11 +27,15 @@ export class TeamMembersComponent { } get displayedMembers(): string[] { - return this.expandedTeam || !this.overflowCount ? this.memberIds : this.memberIds.slice(0, this.maxTeamMembersBeforeExpand - 1); + return this.expandedTeam || !this.overflowCount + ? this.memberIds + : this.memberIds.slice(0, this.maxTeamMembersBeforeExpand - 1); } get overflowCount() { - return this.memberIds.length > this.maxTeamMembersBeforeExpand ? this.memberIds.length - (this.maxTeamMembersBeforeExpand - 1) : 0; + return this.memberIds.length > this.maxTeamMembersBeforeExpand + ? this.memberIds.length - (this.maxTeamMembersBeforeExpand - 1) + : 0; } toggleExpandedTeam() { diff --git a/apps/red-ui/src/app/modules/projects/components/type-annotation-icon/type-annotation-icon.component.html b/apps/red-ui/src/app/modules/projects/components/type-annotation-icon/type-annotation-icon.component.html index 22eb999b5..7b97cafac 100644 --- a/apps/red-ui/src/app/modules/projects/components/type-annotation-icon/type-annotation-icon.component.html +++ b/apps/red-ui/src/app/modules/projects/components/type-annotation-icon/type-annotation-icon.component.html @@ -1 +1,5 @@ - + diff --git a/apps/red-ui/src/app/modules/projects/components/type-filter/type-filter.component.html b/apps/red-ui/src/app/modules/projects/components/type-filter/type-filter.component.html index c860ce914..4360a889c 100644 --- a/apps/red-ui/src/app/modules/projects/components/type-filter/type-filter.component.html +++ b/apps/red-ui/src/app/modules/projects/components/type-filter/type-filter.component.html @@ -1,15 +1,70 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/apps/red-ui/src/app/modules/projects/components/type-filter/type-filter.component.ts b/apps/red-ui/src/app/modules/projects/components/type-filter/type-filter.component.ts index b733c0211..cc34c5248 100644 --- a/apps/red-ui/src/app/modules/projects/components/type-filter/type-filter.component.ts +++ b/apps/red-ui/src/app/modules/projects/components/type-filter/type-filter.component.ts @@ -20,7 +20,13 @@ export class TypeFilterComponent implements OnInit { 'suggestion-remove-dictionary', 'suggestion-add-dictionary' ]; - private _needsAnalysisKeys = ['add-dictionary', 'remove-dictionary', 'remove-only-here', 'pending-analysis', 'analysis']; + private _needsAnalysisKeys = [ + 'add-dictionary', + 'remove-dictionary', + 'remove-only-here', + 'pending-analysis', + 'analysis' + ]; constructor(private readonly _appStateService: AppStateService) {} diff --git a/apps/red-ui/src/app/modules/projects/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.html b/apps/red-ui/src/app/modules/projects/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.html index d7ee77d0a..552740c92 100644 --- a/apps/red-ui/src/app/modules/projects/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.html +++ b/apps/red-ui/src/app/modules/projects/dialogs/add-edit-project-dialog/add-edit-project-dialog.component.html @@ -1,7 +1,11 @@
@@ -9,7 +13,9 @@
- {{ 'project-listing.add-edit-dialog.form.template' | translate }} - + {{ + 'project-listing.add-edit-dialog.form.template' | translate + }} + +
@@ -30,5 +53,9 @@
- + diff --git a/apps/red-ui/src/app/modules/projects/dialogs/force-redaction-dialog/force-redaction-dialog.component.ts b/apps/red-ui/src/app/modules/projects/dialogs/force-redaction-dialog/force-redaction-dialog.component.ts index 4c88ebead..68799cbe4 100644 --- a/apps/red-ui/src/app/modules/projects/dialogs/force-redaction-dialog/force-redaction-dialog.component.ts +++ b/apps/red-ui/src/app/modules/projects/dialogs/force-redaction-dialog/force-redaction-dialog.component.ts @@ -38,17 +38,19 @@ export class ForceRedactionDialogComponent implements OnInit { ) {} async ngOnInit() { - this._legalBasisMappingControllerService.getLegalBasisMapping(this._appStateService.activeProject.ruleSetId).subscribe((data) => { - data.map((lbm) => { - this.legalOptions.push({ - legalBasis: lbm.reason, - description: lbm.description, - label: lbm.name + this._legalBasisMappingControllerService + .getLegalBasisMapping(this._appStateService.activeProject.ruleSetId) + .subscribe((data) => { + data.map((lbm) => { + this.legalOptions.push({ + legalBasis: lbm.reason, + description: lbm.description, + label: lbm.name + }); }); - }); - this.legalOptions.sort((a, b) => a.label.localeCompare(b.label)); - }); + this.legalOptions.sort((a, b) => a.label.localeCompare(b.label)); + }); this.isDocumentAdmin = this._permissionsService.isApprover(); diff --git a/apps/red-ui/src/app/modules/projects/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html b/apps/red-ui/src/app/modules/projects/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html index 90ada6d30..b62deb489 100644 --- a/apps/red-ui/src/app/modules/projects/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html +++ b/apps/red-ui/src/app/modules/projects/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html @@ -18,8 +18,19 @@
- - + + {{ option.label }} @@ -27,15 +38,28 @@
- +
- +
-
+
@@ -61,5 +85,9 @@
- + diff --git a/apps/red-ui/src/app/modules/projects/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/projects/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts index 8eb6522a7..f2bb79f92 100644 --- a/apps/red-ui/src/app/modules/projects/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/projects/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts @@ -2,7 +2,11 @@ import { Component, Inject, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { AppStateService } from '@state/app-state.service'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { AddRedactionRequest, LegalBasisMappingControllerService, TypeValue } from '@redaction/red-ui-http'; +import { + AddRedactionRequest, + LegalBasisMappingControllerService, + TypeValue +} from '@redaction/red-ui-http'; import { NotificationService } from '@services/notification.service'; import { TranslateService } from '@ngx-translate/core'; import { UserService } from '@services/user.service'; @@ -58,22 +62,25 @@ export class ManualAnnotationDialogComponent implements OnInit { } async ngOnInit() { - this._legalBasisMappingControllerService.getLegalBasisMapping(this._appStateService.activeProject.ruleSetId).subscribe((data) => { - data.map((lbm) => { - this.legalOptions.push({ - legalBasis: lbm.reason, - description: lbm.description, - label: lbm.name + this._legalBasisMappingControllerService + .getLegalBasisMapping(this._appStateService.activeProject.ruleSetId) + .subscribe((data) => { + data.map((lbm) => { + this.legalOptions.push({ + legalBasis: lbm.reason, + description: lbm.description, + label: lbm.name + }); }); - }); - this.legalOptions.sort((a, b) => a.label.localeCompare(b.label)); - }); + this.legalOptions.sort((a, b) => a.label.localeCompare(b.label)); + }); this.isDocumentAdmin = this._permissionsService.isApprover(); this.isFalsePositiveRequest = this.manualRedactionEntryWrapper.type === 'FALSE_POSITIVE'; - this.isDictionaryRequest = this.manualRedactionEntryWrapper.type === 'DICTIONARY' || this.isFalsePositiveRequest; + this.isDictionaryRequest = + this.manualRedactionEntryWrapper.type === 'DICTIONARY' || this.isFalsePositiveRequest; this.redactionForm = this._formBuilder.group({ reason: this.isDictionaryRequest ? [null] : [null, Validators.required], @@ -83,7 +90,9 @@ export class ManualAnnotationDialogComponent implements OnInit { comment: this.isDocumentAdmin ? [null] : [null, Validators.required] }); - for (const key of Object.keys(this._appStateService.dictionaryData[this._appStateService.activeProject.ruleSetId])) { + for (const key of Object.keys( + this._appStateService.dictionaryData[this._appStateService.activeProject.ruleSetId] + )) { const dictionaryData = this._appStateService.getDictionaryTypeValue(key); if (!dictionaryData.virtual && dictionaryData.addToDictionaryAction) { this.redactionDictionaries.push(dictionaryData); @@ -94,14 +103,18 @@ export class ManualAnnotationDialogComponent implements OnInit { handleAddRedaction() { this._enhanceManualRedaction(this.manualRedactionEntryWrapper.manualRedactionEntry); - this._manualAnnotationService.addAnnotation(this.manualRedactionEntryWrapper.manualRedactionEntry).subscribe( - (response) => { - this.dialogRef.close(new ManualAnnotationResponse(this.manualRedactionEntryWrapper, response)); - }, - () => { - this.dialogRef.close(); - } - ); + this._manualAnnotationService + .addAnnotation(this.manualRedactionEntryWrapper.manualRedactionEntry) + .subscribe( + (response) => { + this.dialogRef.close( + new ManualAnnotationResponse(this.manualRedactionEntryWrapper, response) + ); + }, + () => { + this.dialogRef.close(); + } + ); } private _enhanceManualRedaction(addRedactionRequest: AddRedactionRequest) { diff --git a/apps/red-ui/src/app/modules/projects/dialogs/remove-annotations-dialog/remove-annotations-dialog.component.html b/apps/red-ui/src/app/modules/projects/dialogs/remove-annotations-dialog/remove-annotations-dialog.component.html index 8dddb8199..56d67ca60 100644 --- a/apps/red-ui/src/app/modules/projects/dialogs/remove-annotations-dialog/remove-annotations-dialog.component.html +++ b/apps/red-ui/src/app/modules/projects/dialogs/remove-annotations-dialog/remove-annotations-dialog.component.html @@ -1,15 +1,19 @@
{{ - (data.removeFromDictionary ? 'remove-annotations-dialog.remove-from-dictionary.title' : 'remove-annotations-dialog.remove-only-here.title') - | translate + (data.removeFromDictionary + ? 'remove-annotations-dialog.remove-from-dictionary.title' + : 'remove-annotations-dialog.remove-only-here.title' + ) | translate }}
{{ - (data.removeFromDictionary ? 'remove-annotations-dialog.remove-from-dictionary.question' : 'remove-annotations-dialog.remove-only-here.question') - | translate + (data.removeFromDictionary + ? 'remove-annotations-dialog.remove-from-dictionary.question' + : 'remove-annotations-dialog.remove-only-here.question' + ) | translate }}
@@ -45,5 +49,9 @@
- +
diff --git a/apps/red-ui/src/app/modules/projects/projects.module.ts b/apps/red-ui/src/app/modules/projects/projects.module.ts index af2361d8d..4dafa01fe 100644 --- a/apps/red-ui/src/app/modules/projects/projects.module.ts +++ b/apps/red-ui/src/app/modules/projects/projects.module.ts @@ -37,7 +37,11 @@ import { AnnotationProcessingService } from './services/annotation-processing.se import { AnnotationRemoveActionsComponent } from './components/annotation-remove-actions/annotation-remove-actions.component'; import { DossierDictionaryDialogComponent } from './dialogs/dossier-dictionary-dialog/dossier-dictionary-dialog.component'; -const screens = [ProjectListingScreenComponent, ProjectOverviewScreenComponent, FilePreviewScreenComponent]; +const screens = [ + ProjectListingScreenComponent, + ProjectOverviewScreenComponent, + FilePreviewScreenComponent +]; const dialogs = [ AddEditProjectDialogComponent, diff --git a/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.html index 322bd99b5..a106c48f3 100644 --- a/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.html @@ -30,7 +30,11 @@
- +
@@ -47,7 +51,11 @@
{{ appStateService.activeFile.status | translate }} - {{ 'by' | translate }}:
@@ -62,7 +70,9 @@
- - + +
-
+
- +
- +
@@ -231,10 +269,16 @@
- +

{{ loadingMessage | translate }}

- +
diff --git a/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.ts index cbcd81e74..931ad29b1 100644 --- a/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/projects/screens/file-preview-screen/file-preview-screen.component.ts @@ -1,4 +1,12 @@ -import { ChangeDetectorRef, Component, HostListener, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + HostListener, + NgZone, + OnDestroy, + OnInit, + ViewChild +} from '@angular/core'; import { ActivatedRoute, ActivatedRouteSnapshot, Router } from '@angular/router'; import { AppStateService } from '@state/app-state.service'; import { WebViewerInstance } from '@pdftron/webviewer'; @@ -103,11 +111,19 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, } get canSwitchToRedactedView() { - return this.fileData && !this.permissionsService.fileRequiresReanalysis() && !this.fileData.fileStatus.isExcluded; + return ( + this.fileData && + !this.permissionsService.fileRequiresReanalysis() && + !this.fileData.fileStatus.isExcluded + ); } get canSwitchToDeltaView() { - return this.fileData && this.fileData.redactionChangeLog?.redactionLogEntry?.length > 0 && !this.fileData.fileStatus.isExcluded; + return ( + this.fileData && + this.fileData.redactionChangeLog?.redactionLogEntry?.length > 0 && + !this.fileData.fileStatus.isExcluded + ); } get displayData() { @@ -116,7 +132,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, get indeterminateMode() { return ( - this.analysisProgress > 100 || this.appStateService.activeFile.analysisDuration < 3 * 1000 // it takes longer than usual - switch to indeterminate + this.analysisProgress > 100 || + this.appStateService.activeFile.analysisDuration < 3 * 1000 + // it takes longer than usual - switch to indeterminate ); // on less than 3 seconds show indeterminate } @@ -135,8 +153,12 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, switch (this.viewMode) { case 'STANDARD': { - const standardEntries = allAnnotations.filter((a) => !a.getCustomData('changeLogRemoved')); - const nonStandardEntries = allAnnotations.filter((a) => a.getCustomData('changeLogRemoved')); + const standardEntries = allAnnotations.filter( + (a) => !a.getCustomData('changeLogRemoved') + ); + const nonStandardEntries = allAnnotations.filter((a) => + a.getCustomData('changeLogRemoved') + ); redactions.forEach((redaction) => { redaction['StrokeColor'] = redaction.getCustomData('annotationColor'); }); @@ -146,7 +168,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, } case 'DELTA': { const changeLogEntries = allAnnotations.filter((a) => a.getCustomData('changeLog')); - const nonChangeLogEntries = allAnnotations.filter((a) => !a.getCustomData('changeLog')); + const nonChangeLogEntries = allAnnotations.filter( + (a) => !a.getCustomData('changeLog') + ); redactions.forEach((redaction) => { redaction['StrokeColor'] = redaction.getCustomData('annotationColor'); }); @@ -156,7 +180,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, } case 'REDACTED': { const redactionEntries = allAnnotations.filter((a) => a.getCustomData('redaction')); - const nonRedactionEntries = allAnnotations.filter((a) => !a.getCustomData('redaction')); + const nonRedactionEntries = allAnnotations.filter( + (a) => !a.getCustomData('redaction') + ); redactions.forEach((redaction) => { redaction['StrokeColor'] = redaction.getCustomData('redactionColor'); }); @@ -206,12 +232,19 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, rebuildFilters(deletePreviousAnnotations: boolean = false) { const startTime = new Date().getTime(); if (deletePreviousAnnotations) { - this.activeViewer.annotManager.deleteAnnotations(this.activeViewer.annotManager.getAnnotationsList(), { - imported: true, - force: true - }); + this.activeViewer.annotManager.deleteAnnotations( + this.activeViewer.annotManager.getAnnotationsList(), + { + imported: true, + force: true + } + ); } - console.log('[REDACTION] Delete previous annotations time: ' + (new Date().getTime() - startTime) + 'ms'); + console.log( + '[REDACTION] Delete previous annotations time: ' + + (new Date().getTime() - startTime) + + 'ms' + ); const processStartTime = new Date().getTime(); this.annotationData = this.fileData.getAnnotations( this.appStateService.dictionaryData[this.appStateService.activeProject.ruleSetId], @@ -219,14 +252,21 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, this.viewMode, this.userPreferenceService.areDevFeaturesEnabled ); - const annotationFilters = this._annotationProcessingService.getAnnotationFilter(this.annotations); + const annotationFilters = this._annotationProcessingService.getAnnotationFilter( + this.annotations + ); this.primaryFilters = processFilters(this.primaryFilters, annotationFilters); - this.secondaryFilters = processFilters(this.secondaryFilters, AnnotationProcessingService.secondaryAnnotationFilters); + this.secondaryFilters = processFilters( + this.secondaryFilters, + AnnotationProcessingService.secondaryAnnotationFilters + ); this._workloadComponent?.filtersChanged({ primary: this.primaryFilters, secondary: this.secondaryFilters }); - console.log('[REDACTION] Process time: ' + (new Date().getTime() - processStartTime) + 'ms'); + console.log( + '[REDACTION] Process time: ' + (new Date().getTime() - processStartTime) + 'ms' + ); console.log( '[REDACTION] Annotation Redraw and filter rebuild time: ' + (new Date().getTime() - startTime) + @@ -238,7 +278,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, handleAnnotationSelected(annotationIds: string[]) { this.selectedAnnotations = annotationIds - .map((annotationId) => this.annotations.find((annotationWrapper) => annotationWrapper.id === annotationId)) + .map((annotationId) => + this.annotations.find((annotationWrapper) => annotationWrapper.id === annotationId) + ) .filter((ann) => ann !== undefined); if (this.selectedAnnotations.length > 1) { this._workloadComponent.multiSelectActive = true; @@ -247,7 +289,11 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, this._changeDetectorRef.detectChanges(); } - selectAnnotations(annotations?: AnnotationWrapper[] | { annotations: AnnotationWrapper[]; multiSelect: boolean }) { + selectAnnotations( + annotations?: + | AnnotationWrapper[] + | { annotations: AnnotationWrapper[]; multiSelect: boolean } + ) { if (annotations) { this._viewerComponent.selectAnnotations(annotations); } else { @@ -266,17 +312,24 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, openManualAnnotationDialog($event: ManualRedactionEntryWrapper) { this._ngZone.run(() => { - 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); - this.fileData.fileStatus = await this.appStateService.reloadActiveFile(); - const distinctPages = $event.manualRedactionEntry.positions.map((p) => p.page).filter((item, pos, self) => self.indexOf(item) === pos); - distinctPages.forEach((page) => { - this._cleanupAndRedrawManualAnnotationsForEntirePage(page); - }); + 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); + this.fileData.fileStatus = await this.appStateService.reloadActiveFile(); + const distinctPages = $event.manualRedactionEntry.positions + .map((p) => p.page) + .filter((item, pos, self) => self.indexOf(item) === pos); + distinctPages.forEach((page) => { + this._cleanupAndRedrawManualAnnotationsForEntirePage(page); + }); + } } - }); + ); }); } @@ -291,7 +344,10 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, @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; } @@ -384,14 +440,23 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, assignReviewer() { const reviewerId = this.reviewerForm.get('reviewer').value; - this._statusControllerService.setFileReviewer(this.fileData.fileStatus.projectId, this.fileData.fileStatus.fileId, reviewerId).subscribe(async () => { - this._notificationService.showToastNotification( - 'Successfully assigned ' + this.userService.getNameForId(reviewerId) + ' to file: ' + this.fileData.fileStatus.filename - ); - await this.appStateService.reloadActiveFile(); - this._updateCanPerformActions(); - this.editingReviewer = false; - }); + this._statusControllerService + .setFileReviewer( + this.fileData.fileStatus.projectId, + this.fileData.fileStatus.fileId, + reviewerId + ) + .subscribe(async () => { + this._notificationService.showToastNotification( + 'Successfully assigned ' + + this.userService.getNameForId(reviewerId) + + ' to file: ' + + this.fileData.fileStatus.filename + ); + await this.appStateService.reloadActiveFile(); + this._updateCanPerformActions(); + this.editingReviewer = false; + }); } resetReviewerForm() { @@ -413,7 +478,13 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, downloadOriginalFile() { this._fileManagementControllerService - .downloadOriginalFile(this.projectId, this.fileId, true, this.fileData.fileStatus.lastUploaded, 'response') + .downloadOriginalFile( + this.projectId, + this.fileId, + true, + this.fileData.fileStatus.lastUploaded, + 'response' + ) .subscribe((data) => { download(data, this.fileData.fileStatus.filename); }); @@ -446,17 +517,19 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, }) ) .subscribe(); - this.fileReanalysedSubscription = this.appStateService.fileReanalysed.subscribe((fileStatus: FileStatusWrapper) => { - if (fileStatus.fileId === this.fileId) { - this._loadFileData(true).subscribe(() => { - this.viewReady = true; - this.loadingMessage = null; - this._stopAnalysisTimer(); - this._updateCanPerformActions(); - this._cleanupAndRedrawManualAnnotations(); - }); + this.fileReanalysedSubscription = this.appStateService.fileReanalysed.subscribe( + (fileStatus: FileStatusWrapper) => { + if (fileStatus.fileId === this.fileId) { + this._loadFileData(true).subscribe(() => { + this.viewReady = true; + this.loadingMessage = null; + this._stopAnalysisTimer(); + this._updateCanPerformActions(); + this._cleanupAndRedrawManualAnnotations(); + }); + } } - }); + ); } private _unsubscribeFromFileUpdates(): void { @@ -465,7 +538,8 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, } private _updateCanPerformActions() { - this.canPerformAnnotationActions = this.permissionsService.canPerformAnnotationActions() && this.viewMode === 'STANDARD'; + this.canPerformAnnotationActions = + this.permissionsService.canPerformAnnotationActions() && this.viewMode === 'STANDARD'; } private _loadFileData(performUpdate: boolean = false) { @@ -484,7 +558,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, } } else { if (fileDataModel.fileStatus.isError) { - this._router.navigate(['/main/projects/' + this.appStateService.activeProjectId]); + this._router.navigate([ + '/main/projects/' + this.appStateService.activeProjectId + ]); } else { this.loadingMessage = 'file-preview.reanalyse-file'; } @@ -502,11 +578,17 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, /* 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); - }); + 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) { @@ -514,35 +596,55 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, 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); - } - }); + 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[]) { + private _handleDeltaAnnotationFilters( + currentPageAnnotations: AnnotationWrapper[], + newPageAnnotations: AnnotationWrapper[] + ) { const hasAnyFilterSet = - this.primaryFilters.find((f) => f.checked || f.indeterminate) || this.secondaryFilters.find((f) => f.checked || f.indeterminate); + this.primaryFilters.find((f) => f.checked || f.indeterminate) || + this.secondaryFilters.find((f) => f.checked || f.indeterminate); if (hasAnyFilterSet) { - const oldPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations); - const newPageSpecificFilters = this._annotationProcessingService.getAnnotationFilter(newPageAnnotations); + const oldPageSpecificFilters = + this._annotationProcessingService.getAnnotationFilter(currentPageAnnotations); + const newPageSpecificFilters = + this._annotationProcessingService.getAnnotationFilter(newPageAnnotations); handleFilterDelta(oldPageSpecificFilters, newPageSpecificFilters, this.primaryFilters); - this._workloadComponent.filtersChanged({ primary: this.primaryFilters, secondary: this.secondaryFilters }); + this._workloadComponent.filtersChanged({ + primary: this.primaryFilters, + secondary: this.secondaryFilters + }); } } private _findAndDeleteAnnotation(id: string) { const viewerAnnotation = this.activeViewer.annotManager.getAnnotationById(id); if (viewerAnnotation) { - this.activeViewer.annotManager.deleteAnnotation(viewerAnnotation, { imported: true, force: true }); + this.activeViewer.annotManager.deleteAnnotation(viewerAnnotation, { + imported: true, + force: true + }); } } @@ -555,7 +657,9 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy, OnAttach, this.analysisInterval = setInterval(() => { this.analysisProgressInSeconds += 1; - this.analysisProgress = (this.analysisProgressInSeconds * 100) / (this.appStateService.activeFile.analysisDuration / 1000); + this.analysisProgress = + (this.analysisProgressInSeconds * 100) / + (this.appStateService.activeFile.analysisDuration / 1000); }, 1000); } else { this.analysisInterval = 0; diff --git a/apps/red-ui/src/app/modules/projects/screens/project-listing-screen/project-listing-screen.component.html b/apps/red-ui/src/app/modules/projects/screens/project-listing-screen/project-listing-screen.component.html index 705909549..e8e69eb5b 100644 --- a/apps/red-ui/src/app/modules/projects/screens/project-listing-screen/project-listing-screen.component.html +++ b/apps/red-ui/src/app/modules/projects/screens/project-listing-screen/project-listing-screen.component.html @@ -32,8 +32,16 @@ [icon]="'red:template'" [primaryFilters]="ruleSetFilters" > - -
+ +
- {{ 'project-listing.table-header.title' | translate: { length: displayedEntities.length || 0 } }} + {{ + 'project-listing.table-header.title' + | translate: { length: displayedEntities.length || 0 } + }}
@@ -63,11 +74,19 @@ label="project-listing.table-col-names.name" > - + - + - +
@@ -79,13 +98,22 @@ screen="project-listing" > - +
@@ -122,13 +150,21 @@
- +
- +
- +
diff --git a/apps/red-ui/src/app/modules/projects/screens/project-listing-screen/project-listing-screen.component.ts b/apps/red-ui/src/app/modules/projects/screens/project-listing-screen/project-listing-screen.component.ts index 0ed9ff36d..f861e72d9 100644 --- a/apps/red-ui/src/app/modules/projects/screens/project-listing-screen/project-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/projects/screens/project-listing-screen/project-listing-screen.component.ts @@ -32,7 +32,10 @@ import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy'; templateUrl: './project-listing-screen.component.html', styleUrls: ['./project-listing-screen.component.scss'] }) -export class ProjectListingScreenComponent extends BaseListingComponent implements OnInit, OnDestroy, OnAttach, OnDetach { +export class ProjectListingScreenComponent + extends BaseListingComponent + implements OnInit, OnDestroy, OnAttach, OnDetach +{ projectsChartData: DoughnutChartConfig[] = []; documentsChartData: DoughnutChartConfig[] = []; statusFilters: FilterModel[]; @@ -83,7 +86,8 @@ export class ProjectListingScreenComponent extends BaseListingComponent p.project.status === Project.StatusEnum.ACTIVE).length; + return this.allEntities.filter((p) => p.project.status === Project.StatusEnum.ACTIVE) + .length; } get inactiveProjectsCount() { @@ -91,10 +95,20 @@ export class ProjectListingScreenComponent extends BaseListingComponent events instanceof NavigationStart || events instanceof NavigationEnd)) + .pipe( + filter( + (events) => events instanceof NavigationStart || events instanceof NavigationEnd + ) + ) .subscribe((event) => { if (event instanceof NavigationStart && event.url !== '/main/projects') { this._lastScrollPosition = this._scrollBar.measureScrollOffset('top'); @@ -212,7 +230,9 @@ export class ProjectListingScreenComponent extends BaseListingComponent StatusSorter[a.key] - StatusSorter[b.key]); - this.documentsChartData = this._translateChartService.translateStatus(this.documentsChartData); + this.documentsChartData = this._translateChartService.translateStatus( + this.documentsChartData + ); } private _computeAllFilters() { @@ -230,7 +250,8 @@ export class ProjectListingScreenComponent extends BaseListingComponent { - if (this.permissionsService.fileRequiresReanalysis(file)) allDistinctNeedsWork.add('analysis'); + if (this.permissionsService.fileRequiresReanalysis(file)) + allDistinctNeedsWork.add('analysis'); if (entry.hintsOnly) allDistinctNeedsWork.add('hint'); if (entry.hasRedactions) allDistinctNeedsWork.add('redaction'); if (entry.hasRequests) allDistinctNeedsWork.add('suggestion'); @@ -268,7 +289,9 @@ export class ProjectListingScreenComponent extends BaseListingComponent RedactionFilterSorter[a.key] - RedactionFilterSorter[b.key]); + needsWorkFilters.sort( + (a, b) => RedactionFilterSorter[a.key] - RedactionFilterSorter[b.key] + ); this.needsWorkFilters = processFilters(this.needsWorkFilters, needsWorkFilters); const ruleSetFilters = []; diff --git a/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.html b/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.html index ce6d0ee1f..1e6ba2781 100644 --- a/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.html @@ -25,9 +25,17 @@ [primaryFilters]="needsWorkFilters" > - + -
+
@@ -54,7 +62,11 @@ tooltipPosition="below" > - + - {{ 'project-overview.table-header.title' | translate: { length: displayedEntities.length || 0 } }} + {{ + 'project-overview.table-header.title' + | translate: { length: displayedEntities.length || 0 } + }}
-
+
@@ -126,7 +145,9 @@ label="project-overview.table-col-names.added-on" > - + - +
-
- +
+
@@ -192,13 +226,19 @@
- + {{ fileStatus.primaryAttribute }}
-
+
{{ fileStatus.ocrTime | date: 'mediumDate' }}
@@ -213,14 +253,23 @@
- +
- +
- +
@@ -231,8 +280,16 @@
-
-
+
+
- + diff --git a/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.ts b/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.ts index 698e823ec..90aa23fe2 100644 --- a/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/projects/screens/project-overview-screen/project-overview-screen.component.ts @@ -11,7 +11,11 @@ import { FilterModel } from '@shared/components/filter/model/filter.model'; import * as moment from 'moment'; import { ProjectDetailsComponent } from '../../components/project-details/project-details.component'; import { FileStatusWrapper } from '@models/file/file-status.wrapper'; -import { annotationFilterChecker, keyChecker, processFilters } from '@shared/components/filter/utils/filter-utils'; +import { + annotationFilterChecker, + keyChecker, + processFilters +} from '@shared/components/filter/utils/filter-utils'; import { PermissionsService } from '@services/permissions.service'; import { UserService } from '@services/user.service'; import { FileStatus } from '@redaction/red-ui-http'; @@ -32,7 +36,10 @@ import { OnAttach, OnDetach } from '@utils/custom-route-reuse.strategy'; templateUrl: './project-overview-screen.component.html', styleUrls: ['./project-overview-screen.component.scss'] }) -export class ProjectOverviewScreenComponent extends BaseListingComponent implements OnInit, OnDestroy, OnDetach, OnAttach { +export class ProjectOverviewScreenComponent + extends BaseListingComponent + implements OnInit, OnDestroy, OnDetach, OnAttach +{ statusFilters: FilterModel[]; peopleFilters: FilterModel[]; needsWorkFilters: FilterModel[]; @@ -79,10 +86,19 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent allDistinctFileStatusWrapper.add(file.status)); // Added dates - this.allEntities.forEach((file) => allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY'))); + this.allEntities.forEach((file) => + allDistinctAddedDates.add(moment(file.added).format('DD/MM/YYYY')) + ); // Needs work this.allEntities.forEach((file) => { - if (this.permissionsService.fileRequiresReanalysis(file)) allDistinctNeedsWork.add('analysis'); + if (this.permissionsService.fileRequiresReanalysis(file)) + allDistinctNeedsWork.add('analysis'); if (file.hintsOnly) allDistinctNeedsWork.add('hint'); if (file.hasRedactions) allDistinctNeedsWork.add('redaction'); if (file.hasRequests) allDistinctNeedsWork.add('suggestion'); @@ -326,7 +356,9 @@ export class ProjectOverviewScreenComponent extends BaseListingComponent RedactionFilterSorter[a.key] - RedactionFilterSorter[b.key]); + needsWorkFilters.sort( + (a, b) => RedactionFilterSorter[a.key] - RedactionFilterSorter[b.key] + ); this.needsWorkFilters = processFilters(this.needsWorkFilters, needsWorkFilters); } } diff --git a/apps/red-ui/src/app/modules/projects/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/projects/services/annotation-actions.service.ts index 7fec78338..b1e7380b5 100644 --- a/apps/red-ui/src/app/modules/projects/services/annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/projects/services/annotation-actions.service.ts @@ -21,26 +21,52 @@ export class AnnotationActionsService { private readonly _dialogService: ProjectsDialogService ) {} - acceptSuggestion($event: MouseEvent, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter) { + acceptSuggestion( + $event: MouseEvent, + annotations: AnnotationWrapper[], + annotationsChanged: EventEmitter + ) { $event?.stopPropagation(); annotations.forEach((annotation) => { - this._processObsAndEmit(this._manualAnnotationService.approveRequest(annotation.id, annotation.isModifyDictionary), annotation, annotationsChanged); + this._processObsAndEmit( + this._manualAnnotationService.approveRequest( + annotation.id, + annotation.isModifyDictionary + ), + annotation, + annotationsChanged + ); }); } - rejectSuggestion($event: MouseEvent, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter) { + rejectSuggestion( + $event: MouseEvent, + annotations: AnnotationWrapper[], + annotationsChanged: EventEmitter + ) { $event?.stopPropagation(); annotations.forEach((annotation) => { - this._processObsAndEmit(this._manualAnnotationService.declineOrRemoveRequest(annotation), annotation, annotationsChanged); + this._processObsAndEmit( + this._manualAnnotationService.declineOrRemoveRequest(annotation), + annotation, + annotationsChanged + ); }); } - forceRedaction($event: MouseEvent, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter) { + forceRedaction( + $event: MouseEvent, + annotations: AnnotationWrapper[], + annotationsChanged: EventEmitter + ) { $event?.stopPropagation(); this._dialogService.openForceRedactionDialog($event, (request) => { annotations.forEach((annotation) => { this._processObsAndEmit( - this._manualAnnotationService.forceRedaction({ ...request, annotationId: annotation.id }), + this._manualAnnotationService.forceRedaction({ + ...request, + annotationId: annotation.id + }), annotation, annotationsChanged ); @@ -54,51 +80,95 @@ export class AnnotationActionsService { removeFromDictionary: boolean, annotationsChanged: EventEmitter ) { - this._dialogService.openRemoveFromDictionaryDialog($event, annotations, removeFromDictionary, () => { - annotations.forEach((annotation) => { - this._processObsAndEmit( - this._manualAnnotationService.removeOrSuggestRemoveAnnotation(annotation, removeFromDictionary), - annotation, - annotationsChanged - ); - }); - }); + this._dialogService.openRemoveFromDictionaryDialog( + $event, + annotations, + removeFromDictionary, + () => { + annotations.forEach((annotation) => { + this._processObsAndEmit( + this._manualAnnotationService.removeOrSuggestRemoveAnnotation( + annotation, + removeFromDictionary + ), + annotation, + annotationsChanged + ); + }); + } + ); } - markAsFalsePositive($event: MouseEvent, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter) { + markAsFalsePositive( + $event: MouseEvent, + annotations: AnnotationWrapper[], + annotationsChanged: EventEmitter + ) { annotations.forEach((annotation) => { - const permissions = AnnotationPermissions.forUser(this._permissionsService.isApprover(), this._permissionsService.currentUser, annotation); - const value = permissions.canMarkTextOnlyAsFalsePositive ? annotation.value : this._getFalsePositiveText(annotation); + const permissions = AnnotationPermissions.forUser( + this._permissionsService.isApprover(), + this._permissionsService.currentUser, + annotation + ); + const value = permissions.canMarkTextOnlyAsFalsePositive + ? annotation.value + : this._getFalsePositiveText(annotation); this._markAsFalsePositive($event, annotation, value, annotationsChanged); }); } - undoDirectAction($event: MouseEvent, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter) { + undoDirectAction( + $event: MouseEvent, + annotations: AnnotationWrapper[], + annotationsChanged: EventEmitter + ) { $event?.stopPropagation(); annotations.forEach((annotation) => { - this._processObsAndEmit(this._manualAnnotationService.undoRequest(annotation), annotation, annotationsChanged); + this._processObsAndEmit( + this._manualAnnotationService.undoRequest(annotation), + annotation, + annotationsChanged + ); }); } - convertRecommendationToAnnotation($event: any, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter) { + convertRecommendationToAnnotation( + $event: any, + annotations: AnnotationWrapper[], + annotationsChanged: EventEmitter + ) { $event?.stopPropagation(); annotations.forEach((annotation) => { - this._processObsAndEmit(this._manualAnnotationService.addRecommendation(annotation), annotation, annotationsChanged); + this._processObsAndEmit( + this._manualAnnotationService.addRecommendation(annotation), + annotation, + annotationsChanged + ); }); } - getViewerAvailableActions(annotations: AnnotationWrapper[], annotationsChanged: EventEmitter): Record[] { + getViewerAvailableActions( + annotations: AnnotationWrapper[], + annotationsChanged: EventEmitter + ): Record[] { const availableActions = []; const annotationPermissions = annotations.map((a) => ({ annotation: a, - permissions: AnnotationPermissions.forUser(this._permissionsService.isApprover(), this._permissionsService.currentUser, a) + permissions: AnnotationPermissions.forUser( + this._permissionsService.isApprover(), + this._permissionsService.currentUser, + a + ) })); - const canForceRedaction = annotationPermissions.reduce((acc, next) => acc && next.permissions.canForceRedaction, true); + const canForceRedaction = annotationPermissions.reduce( + (acc, next) => acc && next.permissions.canForceRedaction, + true + ); if (canForceRedaction) { availableActions.push({ type: 'actionButton', @@ -112,21 +182,33 @@ export class AnnotationActionsService { }); } - const canAcceptRecommendation = annotationPermissions.reduce((acc, next) => acc && next.permissions.canAcceptRecommendation, true); + const canAcceptRecommendation = annotationPermissions.reduce( + (acc, next) => acc && next.permissions.canAcceptRecommendation, + true + ); if (canAcceptRecommendation) { availableActions.push({ type: 'actionButton', img: this._convertPath('/assets/icons/general/check.svg'), - title: this._translateService.instant('annotation-actions.accept-recommendation.label'), + title: this._translateService.instant( + 'annotation-actions.accept-recommendation.label' + ), onClick: () => { this._ngZone.run(() => { - this.convertRecommendationToAnnotation(null, annotations, annotationsChanged); + this.convertRecommendationToAnnotation( + null, + annotations, + annotationsChanged + ); }); } }); } - const canAcceptSuggestion = annotationPermissions.reduce((acc, next) => acc && next.permissions.canAcceptSuggestion, true); + const canAcceptSuggestion = annotationPermissions.reduce( + (acc, next) => acc && next.permissions.canAcceptSuggestion, + true + ); if (canAcceptSuggestion) { availableActions.push({ type: 'actionButton', @@ -140,7 +222,10 @@ export class AnnotationActionsService { }); } - const canUndo = annotationPermissions.reduce((acc, next) => acc && next.permissions.canUndo, true); + const canUndo = annotationPermissions.reduce( + (acc, next) => acc && next.permissions.canUndo, + true + ); if (canUndo) { availableActions.push({ type: 'actionButton', @@ -154,7 +239,10 @@ export class AnnotationActionsService { }); } - const canRejectSuggestion = annotationPermissions.reduce((acc, next) => acc && next.permissions.canRejectSuggestion, true); + const canRejectSuggestion = annotationPermissions.reduce( + (acc, next) => acc && next.permissions.canRejectSuggestion, + true + ); if (canRejectSuggestion) { availableActions.push({ type: 'actionButton', @@ -176,7 +264,9 @@ export class AnnotationActionsService { availableActions.push({ type: 'actionButton', img: this._convertPath('/assets/icons/general/close.svg'), - title: this._translateService.instant('annotation-actions.suggest-remove-annotation'), + title: this._translateService.instant( + 'annotation-actions.suggest-remove-annotation' + ), onClick: () => { this._ngZone.run(() => { this.suggestRemoveAnnotation(null, annotations, false, annotationsChanged); @@ -193,7 +283,9 @@ export class AnnotationActionsService { availableActions.push({ type: 'actionButton', img: this._convertPath('/assets/icons/general/trash.svg'), - title: this._translateService.instant('annotation-actions.remove-annotation.remove-from-dict'), + title: this._translateService.instant( + 'annotation-actions.remove-annotation.remove-from-dict' + ), onClick: () => { this._ngZone.run(() => { this.suggestRemoveAnnotation(null, annotations, true, annotationsChanged); @@ -203,14 +295,19 @@ export class AnnotationActionsService { } const canMarkAsFalsePositive = annotationPermissions.reduce( - (acc, next) => acc && (next.permissions.canMarkAsFalsePositive || next.permissions.canMarkTextOnlyAsFalsePositive), + (acc, next) => + acc && + (next.permissions.canMarkAsFalsePositive || + next.permissions.canMarkTextOnlyAsFalsePositive), true ); if (canMarkAsFalsePositive) { availableActions.push({ type: 'actionButton', img: this._convertPath('/assets/icons/general/thumb-down.svg'), - title: this._translateService.instant('annotation-actions.remove-annotation.false-positive'), + title: this._translateService.instant( + 'annotation-actions.remove-annotation.false-positive' + ), onClick: () => { this._ngZone.run(() => { this.markAsFalsePositive(null, annotations, annotationsChanged); @@ -222,7 +319,11 @@ export class AnnotationActionsService { return availableActions; } - private _processObsAndEmit(obs: Observable, annotation: AnnotationWrapper, annotationsChanged: EventEmitter) { + private _processObsAndEmit( + obs: Observable, + annotation: AnnotationWrapper, + annotationsChanged: EventEmitter + ) { obs.subscribe( () => { annotationsChanged.emit(annotation); @@ -246,7 +347,12 @@ export class AnnotationActionsService { } } - private _markAsFalsePositive($event: MouseEvent, annotation: AnnotationWrapper, text: string, annotationsChanged: EventEmitter) { + private _markAsFalsePositive( + $event: MouseEvent, + annotation: AnnotationWrapper, + text: string, + annotationsChanged: EventEmitter + ) { $event?.stopPropagation(); const falsePositiveRequest: AddRedactionRequest = {}; @@ -257,7 +363,11 @@ export class AnnotationActionsService { falsePositiveRequest.addToDictionary = true; falsePositiveRequest.comment = { text: 'False Positive' }; - this._processObsAndEmit(this._manualAnnotationService.addAnnotation(falsePositiveRequest), annotation, annotationsChanged); + this._processObsAndEmit( + this._manualAnnotationService.addAnnotation(falsePositiveRequest), + annotation, + annotationsChanged + ); } private _convertPath(path: string): string { diff --git a/apps/red-ui/src/app/modules/projects/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/projects/services/annotation-draw.service.ts index a538707c0..25493794c 100644 --- a/apps/red-ui/src/app/modules/projects/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/projects/services/annotation-draw.service.ts @@ -1,6 +1,11 @@ import { Injectable } from '@angular/core'; import { Annotations, WebViewerInstance } from '@pdftron/webviewer'; -import { Rectangle, RedactionLogControllerService, SectionGrid, SectionRectangle } from '@redaction/red-ui-http'; +import { + Rectangle, + RedactionLogControllerService, + SectionGrid, + SectionRectangle +} from '@redaction/red-ui-http'; import { hexToRgb } from '@utils/functions'; import { AppStateService } from '@state/app-state.service'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; @@ -14,7 +19,11 @@ export class AnnotationDrawService { private readonly _userPreferenceService: UserPreferenceService ) {} - drawAnnotations(activeViewer: WebViewerInstance, annotationWrappers: AnnotationWrapper[], hideSkipped: boolean = false) { + drawAnnotations( + activeViewer: WebViewerInstance, + annotationWrappers: AnnotationWrapper[], + hideSkipped: boolean = false + ) { const annotations = []; annotationWrappers.forEach((annotation) => { annotations.push(this.computeAnnotation(activeViewer, annotation, hideSkipped)); @@ -26,7 +35,10 @@ export class AnnotationDrawService { if (this._userPreferenceService.areDevFeaturesEnabled) { this._redactionLogControllerService - .getSectionGrid(this._appStateService.activeProjectId, this._appStateService.activeFileId) + .getSectionGrid( + this._appStateService.activeProjectId, + this._appStateService.activeFileId + ) .subscribe((sectionGrid) => { this.drawSections(activeViewer, sectionGrid); }); @@ -38,7 +50,9 @@ export class AnnotationDrawService { for (const page of Object.keys(sectionGrid.rectanglesPerPage)) { const sectionRectangles: SectionRectangle[] = sectionGrid.rectanglesPerPage[page]; sectionRectangles.forEach((sectionRectangle) => { - sections.push(this.computeSection(activeViewer, parseInt(page, 10), sectionRectangle)); + sections.push( + this.computeSection(activeViewer, parseInt(page, 10), sectionRectangle) + ); // sectionRectangle.tableCells?.forEach(cell =>{ // sections.push(this.computeSection(activeViewer, parseInt(page, 10), cell)); // }) @@ -49,7 +63,11 @@ export class AnnotationDrawService { annotationManager.drawAnnotationsFromList(sections); } - computeSection(activeViewer: WebViewerInstance, pageNumber: number, sectionRectangle: SectionRectangle) { + computeSection( + activeViewer: WebViewerInstance, + pageNumber: number, + sectionRectangle: SectionRectangle + ) { const rectangleAnnot = new activeViewer.Annotations.RectangleAnnotation(); const pageHeight = activeViewer.docViewer.getPageHeight(pageNumber); const rectangle = { @@ -70,25 +88,46 @@ export class AnnotationDrawService { return rectangleAnnot; } - computeAnnotation(activeViewer: WebViewerInstance, annotationWrapper: AnnotationWrapper, hideSkipped: boolean = false) { + computeAnnotation( + activeViewer: WebViewerInstance, + annotationWrapper: AnnotationWrapper, + hideSkipped: boolean = false + ) { const pageNumber = annotationWrapper.pageNumber; const highlight = new activeViewer.Annotations.TextHighlightAnnotation(); highlight.PageNumber = pageNumber; - highlight.StrokeColor = this.getColor(activeViewer, annotationWrapper.superType, annotationWrapper.dictionary); + highlight.StrokeColor = this.getColor( + activeViewer, + annotationWrapper.superType, + annotationWrapper.dictionary + ); highlight.setContents(annotationWrapper.content); - highlight.Quads = this._rectanglesToQuads(annotationWrapper.positions, activeViewer, pageNumber); + highlight.Quads = this._rectanglesToQuads( + annotationWrapper.positions, + activeViewer, + pageNumber + ); highlight.Id = annotationWrapper.id; highlight.ReadOnly = true; // change log entries are drawn lighter highlight.Opacity = annotationWrapper.isChangeLogRemoved ? 0.2 : 1; - highlight.Hidden = annotationWrapper.isChangeLogRemoved || (hideSkipped && annotationWrapper.isSkipped) || annotationWrapper.isOCR; + highlight.Hidden = + annotationWrapper.isChangeLogRemoved || + (hideSkipped && annotationWrapper.isSkipped) || + annotationWrapper.isOCR; highlight.setCustomData('redaction', annotationWrapper.isRedacted); highlight.setCustomData('skipped', annotationWrapper.isSkipped); highlight.setCustomData('changeLog', annotationWrapper.isChangeLogEntry); highlight.setCustomData('changeLogRemoved', annotationWrapper.isChangeLogRemoved); - highlight.setCustomData('redactionColor', this.getColor(activeViewer, 'redaction', 'redaction')); - highlight.setCustomData('annotationColor', this.getColor(activeViewer, annotationWrapper.superType, annotationWrapper.dictionary)); + highlight.setCustomData( + 'redactionColor', + this.getColor(activeViewer, 'redaction', 'redaction') + ); + highlight.setCustomData( + 'annotationColor', + this.getColor(activeViewer, annotationWrapper.superType, annotationWrapper.dictionary) + ); return highlight; } @@ -128,12 +167,20 @@ export class AnnotationDrawService { return new activeViewer.CoreControls.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4); } - private _rectanglesToQuads(positions: Rectangle[], activeViewer: WebViewerInstance, pageNumber: number): any[] { + private _rectanglesToQuads( + positions: Rectangle[], + activeViewer: WebViewerInstance, + pageNumber: number + ): any[] { const pageHeight = activeViewer.docViewer.getPageHeight(pageNumber); return positions.map((p) => this._rectangleToQuad(p, activeViewer, pageHeight)); } - private _rectangleToQuad(rectangle: Rectangle, activeViewer: WebViewerInstance, pageHeight: number): any { + private _rectangleToQuad( + rectangle: Rectangle, + activeViewer: WebViewerInstance, + pageHeight: number + ): any { const x1 = rectangle.topLeft.x; const y1 = pageHeight - (rectangle.topLeft.y + rectangle.height); diff --git a/apps/red-ui/src/app/modules/projects/services/annotation-processing.service.ts b/apps/red-ui/src/app/modules/projects/services/annotation-processing.service.ts index c2bd0f64d..9e02bd836 100644 --- a/apps/red-ui/src/app/modules/projects/services/annotation-processing.service.ts +++ b/apps/red-ui/src/app/modules/projects/services/annotation-processing.service.ts @@ -25,7 +25,10 @@ export class AnnotationProcessingService { const filters: FilterModel[] = []; annotations?.forEach((a) => { - const topLevelFilter = a.superType !== 'hint' && a.superType !== 'redaction' && a.superType !== 'recommendation'; + const topLevelFilter = + a.superType !== 'hint' && + a.superType !== 'redaction' && + a.superType !== 'recommendation'; const key = topLevelFilter ? a.superType : a.superType + a.dictionary; const filter = filterMap.get(key); if (filter) { @@ -76,11 +79,20 @@ export class AnnotationProcessingService { const secondaryFlatFilters = this._getFlatFilters(secondaryFilters, (f) => f.checked); for (const annotation of annotations) { - if (!this._matchesOne(primaryFlatFilters, (f) => this._checkByFilterKey(f, annotation))) { + if ( + !this._matchesOne(primaryFlatFilters, (f) => this._checkByFilterKey(f, annotation)) + ) { continue; } - if (!this._matchesAll(secondaryFlatFilters, (f) => (!!f.checker && f.checker(annotation)) || this._checkByFilterKey(f, annotation))) { + if ( + !this._matchesAll( + secondaryFlatFilters, + (f) => + (!!f.checker && f.checker(annotation)) || + this._checkByFilterKey(f, annotation) + ) + ) { continue; } @@ -107,7 +119,11 @@ export class AnnotationProcessingService { return obj; } - private _createParentFilter(key: string, filterMap: Map, filters: FilterModel[]) { + private _createParentFilter( + key: string, + filterMap: Map, + filters: FilterModel[] + ) { const filter: FilterModel = { key: key, topLevelFilter: true, @@ -131,7 +147,10 @@ export class AnnotationProcessingService { return filterBy ? flatFilters.filter((f) => filterBy(f)) : flatFilters; } - private _matchesOne = (filters: FilterModel[], condition: (filter: FilterModel) => boolean): boolean => { + private _matchesOne = ( + filters: FilterModel[], + condition: (filter: FilterModel) => boolean + ): boolean => { if (filters.length === 0) return true; for (const filter of filters) { @@ -141,7 +160,10 @@ export class AnnotationProcessingService { return false; }; - private _matchesAll = (filters: FilterModel[], condition: (filter: FilterModel) => boolean): boolean => { + private _matchesAll = ( + filters: FilterModel[], + condition: (filter: FilterModel) => boolean + ): boolean => { if (filters.length === 0) return true; for (const filter of filters) { @@ -153,9 +175,13 @@ export class AnnotationProcessingService { private _checkByFilterKey = (filter: FilterModel, annotation: AnnotationWrapper) => { const superType = annotation.superType; - const isNotTopLevelFilter = superType === 'hint' || superType === 'redaction' || superType === 'recommendation'; + const isNotTopLevelFilter = + superType === 'hint' || superType === 'redaction' || superType === 'recommendation'; - return filter.key === superType || (filter.key === annotation.dictionary && isNotTopLevelFilter); + return ( + filter.key === superType || + (filter.key === annotation.dictionary && isNotTopLevelFilter) + ); }; private _sortAnnotations(annotations: AnnotationWrapper[]): AnnotationWrapper[] { diff --git a/apps/red-ui/src/app/modules/projects/services/file-action.service.ts b/apps/red-ui/src/app/modules/projects/services/file-action.service.ts index df15668e7..0fde2cd24 100644 --- a/apps/red-ui/src/app/modules/projects/services/file-action.service.ts +++ b/apps/red-ui/src/app/modules/projects/services/file-action.service.ts @@ -1,7 +1,11 @@ import { Injectable } from '@angular/core'; import { AppStateService } from '@state/app-state.service'; import { UserService } from '@services/user.service'; -import { FileStatus, ReanalysisControllerService, StatusControllerService } from '@redaction/red-ui-http'; +import { + FileStatus, + ReanalysisControllerService, + StatusControllerService +} from '@redaction/red-ui-http'; import { FileStatusWrapper } from '@models/file/file-status.wrapper'; import { PermissionsService } from '@services/permissions.service'; import { isArray } from 'rxjs/internal-compatibility'; @@ -22,14 +26,22 @@ export class FileActionService { if (!fileStatusWrapper) { fileStatusWrapper = this._appStateService.activeFile; } - return this._reanalysisControllerService.reanalyzeFile(this._appStateService.activeProject.project.projectId, fileStatusWrapper.fileId, priority); + return this._reanalysisControllerService.reanalyzeFile( + this._appStateService.activeProject.project.projectId, + fileStatusWrapper.fileId, + priority + ); } toggleAnalysis(fileStatusWrapper?: FileStatusWrapper) { if (!fileStatusWrapper) { fileStatusWrapper = this._appStateService.activeFile; } - return this._reanalysisControllerService.toggleAnalysis(fileStatusWrapper.projectId, fileStatusWrapper.fileId, fileStatusWrapper.isExcluded); + return this._reanalysisControllerService.toggleAnalysis( + fileStatusWrapper.projectId, + fileStatusWrapper.fileId, + fileStatusWrapper.isExcluded + ); } async assignProjectReviewerFromOverview(file?: FileStatusWrapper, callback?: Function) { @@ -57,9 +69,12 @@ export class FileActionService { if (!file.currentReviewer) { await this._assignReviewerToCurrentUser(file, callback); } else { - this._dialogService.openAssignFileToMeDialog(file ? file : this._appStateService.activeFile, async () => { - await this._assignReviewerToCurrentUser(file, callback); - }); + this._dialogService.openAssignFileToMeDialog( + file ? file : this._appStateService.activeFile, + async () => { + await this._assignReviewerToCurrentUser(file, callback); + } + ); } } @@ -104,16 +119,25 @@ export class FileActionService { } private _openAssignReviewerDialog(file?: FileStatusWrapper, callback?: Function) { - this._dialogService.openAssignFileReviewerDialog(file ? file : this._appStateService.activeFile, async () => { - await this._appStateService.reloadActiveProjectFiles(); - if (callback) { - callback(); + this._dialogService.openAssignFileReviewerDialog( + file ? file : this._appStateService.activeFile, + async () => { + await this._appStateService.reloadActiveProjectFiles(); + if (callback) { + callback(); + } } - }); + ); } private async _assignReviewerToCurrentUser(file?: FileStatus, callback?: Function) { - await this._statusControllerService.setFileReviewer(this._appStateService.activeProjectId, file.fileId, this._userService.userId).toPromise(); + await this._statusControllerService + .setFileReviewer( + this._appStateService.activeProjectId, + file.fileId, + this._userService.userId + ) + .toPromise(); await this._appStateService.reloadActiveProjectFiles(); if (callback) { await callback(); diff --git a/apps/red-ui/src/app/modules/projects/services/manual-annotation.service.ts b/apps/red-ui/src/app/modules/projects/services/manual-annotation.service.ts index 627fb4f52..a3ece8118 100644 --- a/apps/red-ui/src/app/modules/projects/services/manual-annotation.service.ts +++ b/apps/red-ui/src/app/modules/projects/services/manual-annotation.service.ts @@ -1,6 +1,11 @@ import { Injectable } from '@angular/core'; import { AppStateService } from '@state/app-state.service'; -import { AddRedactionRequest, DictionaryControllerService, ForceRedactionRequest, ManualRedactionControllerService } from '@redaction/red-ui-http'; +import { + AddRedactionRequest, + DictionaryControllerService, + ForceRedactionRequest, + ManualRedactionControllerService +} from '@redaction/red-ui-http'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { NotificationService, NotificationType } from '@services/notification.service'; import { TranslateService } from '@ngx-translate/core'; @@ -44,7 +49,8 @@ export class ManualAnnotationService { addRecommendation(annotation: AnnotationWrapper) { const manualRedactionEntry: AddRedactionRequest = {}; manualRedactionEntry.addToDictionary = true; - manualRedactionEntry.reason = annotation.id; // set the ID as reason, so we can hide the suggestion + // set the ID as reason, so we can hide the suggestion + manualRedactionEntry.reason = annotation.id; manualRedactionEntry.value = annotation.value; manualRedactionEntry.positions = annotation.positions; manualRedactionEntry.type = annotation.recommendationType; @@ -88,18 +94,35 @@ export class ManualAnnotationService { .pipe( tap( () => this._notify(this._getMessage('approve', addToDictionary)), - (error) => this._notify(this._getMessage('approve', addToDictionary, true), NotificationType.ERROR, error) + (error) => + this._notify( + this._getMessage('approve', addToDictionary, true), + NotificationType.ERROR, + error + ) ) ); } undoRequest(annotationWrapper: AnnotationWrapper) { return this._manualRedactionControllerService - .undo(this._appStateService.activeProjectId, this._appStateService.activeFileId, annotationWrapper.id) + .undo( + this._appStateService.activeProjectId, + this._appStateService.activeFileId, + annotationWrapper.id + ) .pipe( tap( - () => this._notify(this._getMessage('undo', annotationWrapper.isModifyDictionary)), - (error) => this._notify(this._getMessage('undo', annotationWrapper.isModifyDictionary, true), NotificationType.ERROR, error) + () => + this._notify( + this._getMessage('undo', annotationWrapper.isModifyDictionary) + ), + (error) => + this._notify( + this._getMessage('undo', annotationWrapper.isModifyDictionary, true), + NotificationType.ERROR, + error + ) ) ); } @@ -110,20 +133,52 @@ export class ManualAnnotationService { declineOrRemoveRequest(annotationWrapper: AnnotationWrapper) { if (this._permissionsService.isApprover()) { return this._manualRedactionControllerService - .declineRequest(this._appStateService.activeProjectId, this._appStateService.activeFileId, annotationWrapper.id) + .declineRequest( + this._appStateService.activeProjectId, + this._appStateService.activeFileId, + annotationWrapper.id + ) .pipe( tap( - () => this._notify(this._getMessage('decline', annotationWrapper.isModifyDictionary)), - (error) => this._notify(this._getMessage('decline', annotationWrapper.isModifyDictionary, true), NotificationType.ERROR, error) + () => + this._notify( + this._getMessage('decline', annotationWrapper.isModifyDictionary) + ), + (error) => + this._notify( + this._getMessage( + 'decline', + annotationWrapper.isModifyDictionary, + true + ), + NotificationType.ERROR, + error + ) ) ); } else { return this._manualRedactionControllerService - .undo(this._appStateService.activeProjectId, this._appStateService.activeFileId, annotationWrapper.id) + .undo( + this._appStateService.activeProjectId, + this._appStateService.activeFileId, + annotationWrapper.id + ) .pipe( tap( - () => this._notify(this._getMessage('undo', annotationWrapper.isModifyDictionary)), - (error) => this._notify(this._getMessage('undo', annotationWrapper.isModifyDictionary, true), NotificationType.ERROR, error) + () => + this._notify( + this._getMessage('undo', annotationWrapper.isModifyDictionary) + ), + (error) => + this._notify( + this._getMessage( + 'undo', + annotationWrapper.isModifyDictionary, + true + ), + NotificationType.ERROR, + error + ) ) ); } @@ -132,16 +187,28 @@ export class ManualAnnotationService { // this wraps // /manualRedaction/redaction/remove/ // /manualRedaction/request/remove/ - removeOrSuggestRemoveAnnotation(annotationWrapper: AnnotationWrapper, removeFromDictionary: boolean = false) { + removeOrSuggestRemoveAnnotation( + annotationWrapper: AnnotationWrapper, + removeFromDictionary: boolean = false + ) { if (this._permissionsService.isApprover()) { // if it was something manual simply decline the existing request if (annotationWrapper.dictionary === 'manual') { return this._manualRedactionControllerService - .declineRequest(this._appStateService.activeProjectId, this._appStateService.activeFileId, annotationWrapper.id) + .declineRequest( + this._appStateService.activeProjectId, + this._appStateService.activeFileId, + annotationWrapper.id + ) .pipe( tap( () => this._notify(this._getMessage('decline', false)), - (error) => this._notify(this._getMessage('decline', false, true), NotificationType.ERROR, error) + (error) => + this._notify( + this._getMessage('decline', false, true), + NotificationType.ERROR, + error + ) ) ); } else { @@ -158,7 +225,12 @@ export class ManualAnnotationService { .pipe( tap( () => this._notify(this._getMessage('remove', removeFromDictionary)), - (error) => this._notify(this._getMessage('remove', removeFromDictionary, true), NotificationType.ERROR, error) + (error) => + this._notify( + this._getMessage('remove', removeFromDictionary, true), + NotificationType.ERROR, + error + ) ) ); } @@ -175,8 +247,14 @@ export class ManualAnnotationService { ) .pipe( tap( - () => this._notify(this._getMessage('request-remove', removeFromDictionary)), - (error) => this._notify(this._getMessage('request-remove', removeFromDictionary, true), NotificationType.ERROR, error) + () => + this._notify(this._getMessage('request-remove', removeFromDictionary)), + (error) => + this._notify( + this._getMessage('request-remove', removeFromDictionary, true), + NotificationType.ERROR, + error + ) ) ); } @@ -206,53 +284,98 @@ export class ManualAnnotationService { private _makeForceRedactionRequest(forceRedactionRequest: ForceRedactionRequest) { return this._manualRedactionControllerService - .requestForceRedaction(forceRedactionRequest, this._appStateService.activeProject.project.projectId, this._appStateService.activeFile.fileId) + .requestForceRedaction( + forceRedactionRequest, + this._appStateService.activeProject.project.projectId, + this._appStateService.activeFile.fileId + ) .pipe( tap( () => this._notify(this._getMessage('suggest', false)), - (error) => this._notify(this._getMessage('suggest', false, true), NotificationType.ERROR, error) + (error) => + this._notify( + this._getMessage('suggest', false, true), + NotificationType.ERROR, + error + ) ) ); } private _makeForceRedaction(forceRedactionRequest: ForceRedactionRequest) { return this._manualRedactionControllerService - .forceRedaction(forceRedactionRequest, this._appStateService.activeProject.project.projectId, this._appStateService.activeFile.fileId) + .forceRedaction( + forceRedactionRequest, + this._appStateService.activeProject.project.projectId, + this._appStateService.activeFile.fileId + ) .pipe( tap( () => this._notify(this._getMessage('add', false)), - (error) => this._notify(this._getMessage('add', false, true), NotificationType.ERROR, error) + (error) => + this._notify( + this._getMessage('add', false, true), + NotificationType.ERROR, + error + ) ) ); } private _makeRedactionRequest(manualRedactionEntry: AddRedactionRequest) { return this._manualRedactionControllerService - .requestAddRedaction(manualRedactionEntry, this._appStateService.activeProject.project.projectId, this._appStateService.activeFile.fileId) + .requestAddRedaction( + manualRedactionEntry, + this._appStateService.activeProject.project.projectId, + this._appStateService.activeFile.fileId + ) .pipe( tap( - () => this._notify(this._getMessage('suggest', manualRedactionEntry.addToDictionary)), - (error) => this._notify(this._getMessage('suggest', manualRedactionEntry.addToDictionary, true), NotificationType.ERROR, error) + () => + this._notify( + this._getMessage('suggest', manualRedactionEntry.addToDictionary) + ), + (error) => + this._notify( + this._getMessage('suggest', manualRedactionEntry.addToDictionary, true), + NotificationType.ERROR, + error + ) ) ); } private _makeRedaction(manualRedactionEntry: AddRedactionRequest) { return this._manualRedactionControllerService - .addRedaction(manualRedactionEntry, this._appStateService.activeProject.project.projectId, this._appStateService.activeFile.fileId) + .addRedaction( + manualRedactionEntry, + this._appStateService.activeProject.project.projectId, + this._appStateService.activeFile.fileId + ) .pipe( tap( - () => this._notify(this._getMessage('add', manualRedactionEntry.addToDictionary)), - (error) => this._notify(this._getMessage('add', manualRedactionEntry.addToDictionary, true), NotificationType.ERROR, error) + () => + this._notify(this._getMessage('add', manualRedactionEntry.addToDictionary)), + (error) => + this._notify( + this._getMessage('add', manualRedactionEntry.addToDictionary, true), + NotificationType.ERROR, + error + ) ) ); } private _notify(key: string, type: NotificationType = NotificationType.SUCCESS, data?: any) { - this._notificationService.showToastNotification(this._translateService.instant(key, data), null, type, { - positionClass: 'toast-file-preview', - actions: [] - }); + this._notificationService.showToastNotification( + this._translateService.instant(key, data), + null, + type, + { + positionClass: 'toast-file-preview', + actions: [] + } + ); } private _getMessage( @@ -260,6 +383,11 @@ export class ManualAnnotationService { modifyDictionary?: boolean, error: boolean = false ) { - return 'annotation-actions.message.' + (modifyDictionary ? 'dictionary.' : 'manual-redaction.') + mode + (error ? '.error' : '.success'); + return ( + 'annotation-actions.message.' + + (modifyDictionary ? 'dictionary.' : 'manual-redaction.') + + mode + + (error ? '.error' : '.success') + ); } } diff --git a/apps/red-ui/src/app/modules/projects/services/pdf-viewer-data.service.ts b/apps/red-ui/src/app/modules/projects/services/pdf-viewer-data.service.ts index b064f9225..44ae014cc 100644 --- a/apps/red-ui/src/app/modules/projects/services/pdf-viewer-data.service.ts +++ b/apps/red-ui/src/app/modules/projects/services/pdf-viewer-data.service.ts @@ -24,35 +24,60 @@ export class PdfViewerDataService { ) {} loadActiveFileManualAnnotations() { - return this._manualRedactionControllerService.getManualRedaction(this._appStateService.activeProjectId, this._appStateService.activeFileId); + return this._manualRedactionControllerService.getManualRedaction( + this._appStateService.activeProjectId, + this._appStateService.activeFileId + ); } loadActiveFileData(): Observable { const fileObs = this.downloadOriginalFile(this._appStateService.activeFile); const reactionLogObs = this._redactionLogControllerService - .getRedactionLog(this._appStateService.activeProjectId, this._appStateService.activeFileId) + .getRedactionLog( + this._appStateService.activeProjectId, + this._appStateService.activeFileId + ) .pipe(catchError(() => of({}))); const redactionChangeLogObs = this._redactionLogControllerService - .getRedactionChangeLog(this._appStateService.activeProjectId, this._appStateService.activeFileId) + .getRedactionChangeLog( + this._appStateService.activeProjectId, + this._appStateService.activeFileId + ) .pipe(catchError(() => of({}))); const manualRedactionsObs = this._manualRedactionControllerService - .getManualRedaction(this._appStateService.activeProjectId, this._appStateService.activeFileId) + .getManualRedaction( + this._appStateService.activeProjectId, + this._appStateService.activeFileId + ) .pipe(catchError(() => of({}))); const viewedPagesObs = this.getViewedPagesForActiveFile(); - return forkJoin([fileObs, reactionLogObs, redactionChangeLogObs, manualRedactionsObs, viewedPagesObs]).pipe( - map((data) => new FileDataModel(this._appStateService.activeFile, ...data)) - ); + return forkJoin([ + fileObs, + reactionLogObs, + redactionChangeLogObs, + manualRedactionsObs, + viewedPagesObs + ]).pipe(map((data) => new FileDataModel(this._appStateService.activeFile, ...data))); } getViewedPagesForActiveFile() { if (this._permissionsService.canMarkPagesAsViewed()) { - return this._viewedPagesControllerService.getViewedPages(this._appStateService.activeProjectId, this._appStateService.activeFileId); + return this._viewedPagesControllerService.getViewedPages( + this._appStateService.activeProjectId, + this._appStateService.activeFileId + ); } return of({ pages: [] }); } downloadOriginalFile(fileStatus: FileStatusWrapper): Observable { - return this._fileManagementControllerService.downloadOriginalFile(fileStatus.projectId, fileStatus.fileId, true, fileStatus.lastUploaded, 'body'); + return this._fileManagementControllerService.downloadOriginalFile( + fileStatus.projectId, + fileStatus.fileId, + true, + fileStatus.lastUploaded, + 'body' + ); } } diff --git a/apps/red-ui/src/app/modules/projects/services/projects-dialog.service.ts b/apps/red-ui/src/app/modules/projects/services/projects-dialog.service.ts index bc869d051..18db34040 100644 --- a/apps/red-ui/src/app/modules/projects/services/projects-dialog.service.ts +++ b/apps/red-ui/src/app/modules/projects/services/projects-dialog.service.ts @@ -12,7 +12,10 @@ import { RemoveAnnotationsDialogComponent } from '../dialogs/remove-annotations- import { NotificationService, NotificationType } from '@services/notification.service'; import { ForceRedactionDialogComponent } from '../dialogs/force-redaction-dialog/force-redaction-dialog.component'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { ConfirmationDialogComponent, ConfirmationDialogInput } from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component'; +import { + ConfirmationDialogComponent, + ConfirmationDialogInput +} from '@shared/dialogs/confirmation-dialog/confirmation-dialog.component'; import { ProjectWrapper } from '@state/model/project.wrapper'; import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component'; import { AppStateService } from '@state/app-state.service'; @@ -43,7 +46,12 @@ export class ProjectsDialogService { private readonly _manualRedactionControllerService: ManualRedactionControllerService ) {} - openDeleteFilesDialog($event: MouseEvent, projectId: string, fileIds: string[], cb?: Function): MatDialogRef { + openDeleteFilesDialog( + $event: MouseEvent, + projectId: string, + fileIds: string[], + cb?: Function + ): MatDialogRef { $event?.stopPropagation(); const ref = this._dialog.open(ConfirmationDialogComponent, { @@ -57,11 +65,17 @@ export class ProjectsDialogService { ref.afterClosed().subscribe(async (result) => { if (result) { try { - await this._fileManagementControllerService.deleteFiles(fileIds, projectId).toPromise(); + await this._fileManagementControllerService + .deleteFiles(fileIds, projectId) + .toPromise(); await this._appStateService.reloadActiveProjectFiles(); if (cb) cb(); } catch (e) { - this._notificationService.showToastNotification(this._translateService.instant('delete-files-error'), null, NotificationType.ERROR); + this._notificationService.showToastNotification( + this._translateService.instant('delete-files-error'), + null, + NotificationType.ERROR + ); } } }); @@ -69,7 +83,10 @@ export class ProjectsDialogService { return ref; } - openManualAnnotationDialog($event: ManualRedactionEntryWrapper, cb?: Function): MatDialogRef { + openManualAnnotationDialog( + $event: ManualRedactionEntryWrapper, + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(ManualAnnotationDialogComponent, { ...dialogConfig, autoFocus: true, @@ -85,24 +102,34 @@ export class ProjectsDialogService { return ref; } - openAcceptSuggestionModal($event: MouseEvent, annotation: AnnotationWrapper, callback?: Function): MatDialogRef { + openAcceptSuggestionModal( + $event: MouseEvent, + annotation: AnnotationWrapper, + callback?: Function + ): MatDialogRef { $event?.stopPropagation(); const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig); ref.afterClosed().subscribe((result) => { if (result) { - this._manualAnnotationService.approveRequest(annotation.id).subscribe((acceptResult) => { - if (callback) { - callback(acceptResult); - } - }); + this._manualAnnotationService + .approveRequest(annotation.id) + .subscribe((acceptResult) => { + if (callback) { + callback(acceptResult); + } + }); } }); return ref; } - openRejectSuggestionModal($event: MouseEvent, annotation: AnnotationWrapper, rejectCallback: () => void): MatDialogRef { + openRejectSuggestionModal( + $event: MouseEvent, + annotation: AnnotationWrapper, + rejectCallback: () => void + ): MatDialogRef { $event?.stopPropagation(); const ref = this._dialog.open(ConfirmationDialogComponent, { @@ -121,7 +148,11 @@ export class ProjectsDialogService { return ref; } - openEditProjectDialog($event: MouseEvent, project: ProjectWrapper, cb?: Function): MatDialogRef { + openEditProjectDialog( + $event: MouseEvent, + project: ProjectWrapper, + cb?: Function + ): MatDialogRef { $event.stopPropagation(); const ref = this._dialog.open(AddEditProjectDialogComponent, { ...dialogConfig, @@ -137,7 +168,10 @@ export class ProjectsDialogService { return ref; } - openForceRedactionDialog($event: MouseEvent, cb?: Function): MatDialogRef { + openForceRedactionDialog( + $event: MouseEvent, + cb?: Function + ): MatDialogRef { $event?.stopPropagation(); const ref = this._dialog.open(ForceRedactionDialogComponent, { ...dialogConfig @@ -169,7 +203,11 @@ export class ProjectsDialogService { return ref; } - openDeleteProjectDialog($event: MouseEvent, project: ProjectWrapper, cb?: Function): MatDialogRef { + openDeleteProjectDialog( + $event: MouseEvent, + project: ProjectWrapper, + cb?: Function + ): MatDialogRef { $event.stopPropagation(); const ref = this._dialog.open(ConfirmationDialogComponent, { ...dialogConfig, @@ -188,7 +226,11 @@ export class ProjectsDialogService { return ref; } - openAssignProjectMembersAndOwnerDialog($event: MouseEvent, project: ProjectWrapper, cb?: Function): MatDialogRef { + openAssignProjectMembersAndOwnerDialog( + $event: MouseEvent, + project: ProjectWrapper, + cb?: Function + ): MatDialogRef { $event?.stopPropagation(); const ref = this._dialog.open(AssignOwnerDialogComponent, { ...dialogConfig, @@ -202,7 +244,11 @@ export class ProjectsDialogService { return ref; } - openDossierDictionaryDialog($event: MouseEvent, project: ProjectWrapper, cb?: Function): MatDialogRef { + openDossierDictionaryDialog( + $event: MouseEvent, + project: ProjectWrapper, + cb?: Function + ): MatDialogRef { $event?.stopPropagation(); const ref = this._dialog.open(DossierDictionaryDialogComponent, { ...dialogConfig, @@ -219,7 +265,11 @@ export class ProjectsDialogService { return ref; } - openAssignFileReviewerDialog(file: FileStatus, cb?: Function, ignoreDialogChanges = false): MatDialogRef { + openAssignFileReviewerDialog( + file: FileStatus, + cb?: Function, + ignoreDialogChanges = false + ): MatDialogRef { const ref = this._dialog.open(AssignOwnerDialogComponent, { ...dialogConfig, data: { type: 'file', files: [file], ignoreChanged: ignoreDialogChanges } @@ -245,7 +295,10 @@ export class ProjectsDialogService { }); } - openBulkAssignFileReviewerDialog(fileIds: string[], cb?: Function): MatDialogRef { + openBulkAssignFileReviewerDialog( + fileIds: string[], + cb?: Function + ): MatDialogRef { const projectId = this._appStateService.activeProject.project.projectId; const ref = this._dialog.open(AssignOwnerDialogComponent, { ...dialogConfig, @@ -275,7 +328,10 @@ export class ProjectsDialogService { return ref; } - openDocumentInfoDialog(file: FileStatus, cb?: Function): MatDialogRef { + openDocumentInfoDialog( + file: FileStatus, + cb?: Function + ): MatDialogRef { const ref = this._dialog.open(DocumentInfoDialogComponent, { ...dialogConfig, data: file, @@ -291,7 +347,11 @@ export class ProjectsDialogService { return ref; } - openRemoveAnnotationModal($event: MouseEvent, annotation: AnnotationWrapper, callback: () => void) { + openRemoveAnnotationModal( + $event: MouseEvent, + annotation: AnnotationWrapper, + callback: () => void + ) { $event?.stopPropagation(); const ref = this._dialog.open(ConfirmationDialogComponent, { @@ -301,11 +361,13 @@ export class ProjectsDialogService { ref.afterClosed().subscribe((result) => { if (result) { - this._manualAnnotationService.removeOrSuggestRemoveAnnotation(annotation).subscribe(() => { - if (callback) { - callback(); - } - }); + this._manualAnnotationService + .removeOrSuggestRemoveAnnotation(annotation) + .subscribe(() => { + if (callback) { + callback(); + } + }); } }); diff --git a/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts b/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts index ec0921270..773384350 100644 --- a/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts +++ b/apps/red-ui/src/app/modules/shared/base/base-listing.component.ts @@ -37,13 +37,18 @@ export abstract class BaseListingComponent { get hasActiveFilters() { return ( - this._filterComponents.filter((f) => !!f).reduce((prev, component) => prev || component?.hasActiveFilters, false) || + this._filterComponents + .filter((f) => !!f) + .reduce((prev, component) => prev || component?.hasActiveFilters, false) || this.searchForm.get('query').value ); } get areAllEntitiesSelected() { - return this.displayedEntities.length !== 0 && this.selectedEntitiesIds.length === this.displayedEntities.length; + return ( + this.displayedEntities.length !== 0 && + this.selectedEntitiesIds.length === this.displayedEntities.length + ); } get areSomeEntitiesSelected() { @@ -54,7 +59,12 @@ export abstract class BaseListingComponent { return this._sortingService.getSortingOption(this._getSortKey); } - protected get _filters(): { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] { + protected get _filters(): { + values: FilterModel[]; + checker: Function; + matchAll?: boolean; + checkerArgs?: any; + }[] { return []; } @@ -119,7 +129,9 @@ export abstract class BaseListingComponent { if (this.areSomeEntitiesSelected) { this.selectedEntitiesIds = []; } else { - this.selectedEntitiesIds = this.displayedEntities.map((entity) => entity[this._getSelectionKey]); + this.selectedEntitiesIds = this.displayedEntities.map( + (entity) => entity[this._getSelectionKey] + ); } } @@ -147,8 +159,12 @@ export abstract class BaseListingComponent { } protected _executeSearchImmediately() { - this.displayedEntities = (this._filters.length ? this.filteredEntities : this.allEntities).filter((entity) => - this._searchField(entity).toLowerCase().includes(this.searchForm.get('query').value.toLowerCase()) + this.displayedEntities = ( + this._filters.length ? this.filteredEntities : this.allEntities + ).filter((entity) => + this._searchField(entity) + .toLowerCase() + .includes(this.searchForm.get('query').value.toLowerCase()) ); this._updateSelection(); } diff --git a/apps/red-ui/src/app/modules/shared/components/annotation-icon/annotation-icon.component.html b/apps/red-ui/src/app/modules/shared/components/annotation-icon/annotation-icon.component.html index 249118c75..c5748ee0d 100644 --- a/apps/red-ui/src/app/modules/shared/components/annotation-icon/annotation-icon.component.html +++ b/apps/red-ui/src/app/modules/shared/components/annotation-icon/annotation-icon.component.html @@ -1,3 +1,10 @@ -
+
{{ label || dictType.label.charAt(0) }}
diff --git a/apps/red-ui/src/app/modules/shared/components/buttons/circle-button/circle-button.component.html b/apps/red-ui/src/app/modules/shared/components/buttons/circle-button/circle-button.component.html index 8307ca328..d15810ec0 100644 --- a/apps/red-ui/src/app/modules/shared/components/buttons/circle-button/circle-button.component.html +++ b/apps/red-ui/src/app/modules/shared/components/buttons/circle-button/circle-button.component.html @@ -1,4 +1,8 @@ -
+
diff --git a/apps/red-ui/src/app/modules/shared/components/checkbox/round-checkbox.component.html b/apps/red-ui/src/app/modules/shared/components/checkbox/round-checkbox.component.html index 6f8249aac..39f6e5eda 100644 --- a/apps/red-ui/src/app/modules/shared/components/checkbox/round-checkbox.component.html +++ b/apps/red-ui/src/app/modules/shared/components/checkbox/round-checkbox.component.html @@ -1,4 +1,9 @@ -
+
diff --git a/apps/red-ui/src/app/modules/shared/components/checkbox/round-checkbox.component.ts b/apps/red-ui/src/app/modules/shared/components/checkbox/round-checkbox.component.ts index e39cb4c0f..212bd9ede 100644 --- a/apps/red-ui/src/app/modules/shared/components/checkbox/round-checkbox.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/checkbox/round-checkbox.component.ts @@ -1,4 +1,12 @@ -import { Component, ElementRef, HostBinding, Input, OnChanges, OnInit, ViewChild } from '@angular/core'; +import { + Component, + ElementRef, + HostBinding, + Input, + OnChanges, + OnInit, + ViewChild +} from '@angular/core'; @Component({ selector: 'redaction-round-checkbox', diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-annotation-icon/dictionary-annotation-icon.component.html b/apps/red-ui/src/app/modules/shared/components/dictionary-annotation-icon/dictionary-annotation-icon.component.html index 22eb999b5..7b97cafac 100644 --- a/apps/red-ui/src/app/modules/shared/components/dictionary-annotation-icon/dictionary-annotation-icon.component.html +++ b/apps/red-ui/src/app/modules/shared/components/dictionary-annotation-icon/dictionary-annotation-icon.component.html @@ -1 +1,5 @@ - + diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-annotation-icon/dictionary-annotation-icon.component.ts b/apps/red-ui/src/app/modules/shared/components/dictionary-annotation-icon/dictionary-annotation-icon.component.ts index 95806e5bf..087cd8fe9 100644 --- a/apps/red-ui/src/app/modules/shared/components/dictionary-annotation-icon/dictionary-annotation-icon.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/dictionary-annotation-icon/dictionary-annotation-icon.component.ts @@ -19,8 +19,14 @@ export class DictionaryAnnotationIconComponent implements OnChanges { ngOnChanges(): void { if (this.dictionaryKey) { - const typeValue: TypeValue = this._appStateService.getDictionaryTypeValue(this.dictionaryKey, this.ruleSetId); - this.color = this._appStateService.getDictionaryColor(this.dictionaryKey, this.ruleSetId); + const typeValue: TypeValue = this._appStateService.getDictionaryTypeValue( + this.dictionaryKey, + this.ruleSetId + ); + this.color = this._appStateService.getDictionaryColor( + this.dictionaryKey, + this.ruleSetId + ); this.type = typeValue.hint ? 'circle' : 'square'; this.label = this.dictionaryKey[0].toUpperCase(); } diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html index 829b735e8..05fb01e55 100644 --- a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html +++ b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.html @@ -18,15 +18,29 @@
{{ currentMatch + '/' + searchPositions.length }}
- - - + + +
- {{ 'dictionary-overview.compare.compare' | translate }} + + {{ 'dictionary-overview.compare.compare' | translate }} +
@@ -38,7 +52,11 @@
- {{ dictionary === selectDictionary ? (dictionary.label | translate) : dictionary.label }} + {{ + dictionary === selectDictionary + ? (dictionary.label | translate) + : dictionary.label + }}
@@ -57,13 +75,22 @@ class="ace-redaction" > -
+
-
- -
+
+ +
diff --git a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts index ff9f5e2cd..480aa56ad 100644 --- a/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/dictionary-manager/dictionary-manager.component.ts @@ -1,4 +1,12 @@ -import { Component, EventEmitter, Input, OnChanges, OnInit, Output, ViewChild } from '@angular/core'; +import { + Component, + EventEmitter, + Input, + OnChanges, + OnInit, + Output, + ViewChild +} from '@angular/core'; import { DictionaryControllerService, RuleSetModel, TypeValue } from '@redaction/red-ui-http'; import { FormBuilder, FormGroup } from '@angular/forms'; import { AceEditorComponent } from 'ng2-ace-editor'; @@ -64,7 +72,10 @@ export class DictionaryManagerComponent implements OnInit, OnChanges { this.compareForm.valueChanges.subscribe((value) => { this._setFieldStatus('ruleSet', value.active); - this._setFieldStatus('dictionary', value.active && this.compareForm.get('ruleSet').value !== this.selectRuleSet); + this._setFieldStatus( + 'dictionary', + value.active && this.compareForm.get('ruleSet').value !== this.selectRuleSet + ); this._loadDictionaries(); }); @@ -100,7 +111,10 @@ export class DictionaryManagerComponent implements OnInit, OnChanges { } revert() { - DictionaryManagerComponent._setEditorValue(this._editorComponent, this.initialDictionaryEntries); + DictionaryManagerComponent._setEditorValue( + this._editorComponent, + this.initialDictionaryEntries + ); this.searchChanged(''); } @@ -134,11 +148,21 @@ export class DictionaryManagerComponent implements OnInit, OnChanges { const entry = this.currentDictionaryEntries[i]; if (entry?.trim().length > 0) { // only mark non-empty lines - this.activeEditMarkers.push(this._editorComponent.getEditor().getSession().addMarker(new range(i, 0, i, 1), 'changed-row-marker', 'fullLine')); + this.activeEditMarkers.push( + this._editorComponent + .getEditor() + .getSession() + .addMarker(new range(i, 0, i, 1), 'changed-row-marker', 'fullLine') + ); } if (entry?.trim().length > 0 && entry.trim().length < MIN_WORD_LENGTH) { // show lines that are too short - this.activeEditMarkers.push(this._editorComponent.getEditor().getSession().addMarker(new range(i, 0, i, 1), 'too-short-marker', 'fullLine')); + this.activeEditMarkers.push( + this._editorComponent + .getEditor() + .getSession() + .addMarker(new range(i, 0, i, 1), 'too-short-marker', 'fullLine') + ); } } } @@ -147,21 +171,24 @@ export class DictionaryManagerComponent implements OnInit, OnChanges { return ( this.currentDictionaryEntries.length && (this.activeEditMarkers.length > 0 || - this.currentDictionaryEntries.filter((e) => e && e.trim().length > 0).length < this.initialDictionaryEntries.length) + this.currentDictionaryEntries.filter((e) => e && e.trim().length > 0).length < + this.initialDictionaryEntries.length) ); } nextSearchMatch() { // length = 3 if (this.searchPositions.length > 0) { - this.currentMatch = this.currentMatch < this.searchPositions.length ? this.currentMatch + 1 : 1; + this.currentMatch = + this.currentMatch < this.searchPositions.length ? this.currentMatch + 1 : 1; this._gotoLine(); } } previousSearchMatch() { if (this.searchPositions.length > 0) { - this.currentMatch = this.currentMatch > 1 ? this.currentMatch - 1 : this.searchPositions.length; + this.currentMatch = + this.currentMatch > 1 ? this.currentMatch - 1 : this.searchPositions.length; this._gotoLine(); } } @@ -198,7 +225,16 @@ export class DictionaryManagerComponent implements OnInit, OnChanges { this._editorComponent .getEditor() .getSession() - .addMarker(new range(position.row, position.column, position.row, position.column + position.length), 'search-marker', 'text') + .addMarker( + new range( + position.row, + position.column, + position.row, + position.column + position.length + ), + 'search-marker', + 'text' + ) ); } } @@ -228,14 +264,21 @@ export class DictionaryManagerComponent implements OnInit, OnChanges { private _onDictionaryChanged(dictionary: TypeValue) { if (dictionary !== this.selectDictionary) { - this._dictionaryControllerService.getDictionaryForType(dictionary.ruleSetId, dictionary.type).subscribe( - (data) => { - this.compareDictionaryEntries = data.entries.sort((str1, str2) => str1.localeCompare(str2, undefined, { sensitivity: 'accent' })); - DictionaryManagerComponent._setEditorValue(this._compareEditorComponent, this.compareDictionaryEntries); - this._syncActiveLines(); - }, - () => {} - ); + this._dictionaryControllerService + .getDictionaryForType(dictionary.ruleSetId, dictionary.type) + .subscribe( + (data) => { + this.compareDictionaryEntries = data.entries.sort((str1, str2) => + str1.localeCompare(str2, undefined, { sensitivity: 'accent' }) + ); + DictionaryManagerComponent._setEditorValue( + this._compareEditorComponent, + this.compareDictionaryEntries + ); + this._syncActiveLines(); + }, + () => {} + ); } } diff --git a/apps/red-ui/src/app/modules/shared/components/empty-state/empty-state.component.html b/apps/red-ui/src/app/modules/shared/components/empty-state/empty-state.component.html index bab3f9c9a..e3154f74e 100644 --- a/apps/red-ui/src/app/modules/shared/components/empty-state/empty-state.component.html +++ b/apps/red-ui/src/app/modules/shared/components/empty-state/empty-state.component.html @@ -1,9 +1,19 @@
- +
diff --git a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.html b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.html index 57f2ab817..84d13420b 100644 --- a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.html +++ b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.html @@ -6,20 +6,43 @@ [text]="filterLabel" > - + -
+
-
-
+
+
@@ -28,7 +51,13 @@
@@ -39,29 +68,66 @@ {{ _(filter)?.label }} - +
- + +
+
+  
-
 
- + - +
-
- - +
+ + - +
diff --git a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.ts b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.ts index 41ef4094a..448882d57 100644 --- a/apps/red-ui/src/app/modules/shared/components/filter/filter.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/filter/filter.component.ts @@ -1,4 +1,12 @@ -import { ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, TemplateRef } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + EventEmitter, + Input, + OnChanges, + Output, + TemplateRef +} from '@angular/core'; import { FilterModel } from './model/filter.model'; import { handleCheckedValue } from './utils/filter-utils'; import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox'; @@ -18,7 +26,10 @@ import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox'; ] }) export class FilterComponent implements OnChanges { - @Output() filtersChanged = new EventEmitter<{ primary: FilterModel[]; secondary?: FilterModel[] }>(); + @Output() filtersChanged = new EventEmitter<{ + primary: FilterModel[]; + secondary?: FilterModel[]; + }>(); @Input() filterTemplate: TemplateRef; @Input() actionsTemplate: TemplateRef; @Input() primaryFilters: FilterModel[] = []; @@ -52,10 +63,12 @@ export class FilterComponent implements OnChanges { this.atLeastOneFilterIsExpandable = false; this.atLeastOneSecondaryFilterIsExpandable = false; this.primaryFilters?.forEach((f) => { - this.atLeastOneFilterIsExpandable = this.atLeastOneFilterIsExpandable || this.isExpandable(f); + this.atLeastOneFilterIsExpandable = + this.atLeastOneFilterIsExpandable || this.isExpandable(f); }); this.secondaryFilters?.forEach((f) => { - this.atLeastOneSecondaryFilterIsExpandable = this.atLeastOneSecondaryFilterIsExpandable || this.isExpandable(f); + this.atLeastOneSecondaryFilterIsExpandable = + this.atLeastOneSecondaryFilterIsExpandable || this.isExpandable(f); }); } @@ -85,7 +98,10 @@ export class FilterComponent implements OnChanges { } applyFilters() { - this.filtersChanged.emit({ primary: this.primaryFilters, secondary: this.secondaryFilters }); + this.filtersChanged.emit({ + primary: this.primaryFilters, + secondary: this.secondaryFilters + }); } toggleFilterExpanded($event: MouseEvent, filter: FilterModel) { diff --git a/apps/red-ui/src/app/modules/shared/components/filter/utils/filter-utils.ts b/apps/red-ui/src/app/modules/shared/components/filter/utils/filter-utils.ts index b80a9a7ad..41f6da0dd 100644 --- a/apps/red-ui/src/app/modules/shared/components/filter/utils/filter-utils.ts +++ b/apps/red-ui/src/app/modules/shared/components/filter/utils/filter-utils.ts @@ -13,13 +13,19 @@ export function processFilters(oldFilters: FilterModel[], newFilters: FilterMode return newFilters; } -export function handleFilterDelta(oldFilters: FilterModel[], newFilters: FilterModel[], allFilters: FilterModel[]) { +export function handleFilterDelta( + oldFilters: FilterModel[], + newFilters: FilterModel[], + allFilters: FilterModel[] +) { const newFiltersDelta = {}; for (const newFilter of newFilters) { const oldFilter = oldFilters.find((f) => f.key === newFilter.key); if (!oldFilter || oldFilter.matches !== newFilter.matches) { newFiltersDelta[newFilter.key] = {}; - newFilter.filters.forEach((filter) => (newFiltersDelta[newFilter.key][filter.key] = {})); + newFilter.filters.forEach( + (filter) => (newFiltersDelta[newFilter.key][filter.key] = {}) + ); } if (!oldFilter) { @@ -82,7 +88,13 @@ export function handleCheckedValue(filter: FilterModel) { } } -export function checkFilter(entity: any, filters: FilterModel[], validate: Function, validateArgs: any = [], matchAll: boolean = false) { +export function checkFilter( + entity: any, + filters: FilterModel[], + validate: Function, + validateArgs: any = [], + matchAll: boolean = false +) { const hasChecked = filters.find((f) => f.checked); if (validateArgs) { @@ -110,9 +122,14 @@ export function checkFilter(entity: any, filters: FilterModel[], validate: Funct return filterMatched; } -export const keyChecker = (key: string) => (entity: any, filter: FilterModel) => entity[key] === filter.key; +export const keyChecker = (key: string) => (entity: any, filter: FilterModel) => + entity[key] === filter.key; -export const annotationFilterChecker = (input: FileStatusWrapper | ProjectWrapper, filter: FilterModel, permissionsService: PermissionsService) => { +export const annotationFilterChecker = ( + input: FileStatusWrapper | ProjectWrapper, + filter: FilterModel, + permissionsService: PermissionsService +) => { switch (filter.key) { case 'analysis': { if (input instanceof ProjectWrapper) { @@ -142,22 +159,38 @@ export const annotationFilterChecker = (input: FileStatusWrapper | ProjectWrappe } }; -export const projectStatusChecker = (pw: ProjectWrapper, filter: FilterModel) => pw.hasStatus(filter.key); +export const projectStatusChecker = (pw: ProjectWrapper, filter: FilterModel) => + pw.hasStatus(filter.key); -export const projectMemberChecker = (pw: ProjectWrapper, filter: FilterModel) => pw.hasMember(filter.key); +export const projectMemberChecker = (pw: ProjectWrapper, filter: FilterModel) => + pw.hasMember(filter.key); -export const ruleSetChecker = (pw: ProjectWrapper, filter: FilterModel) => pw.ruleSetId === filter.key; +export const ruleSetChecker = (pw: ProjectWrapper, filter: FilterModel) => + pw.ruleSetId === filter.key; -export const dueDateChecker = (pw: ProjectWrapper, filter: FilterModel) => pw.dueDateMatches(filter.key); +export const dueDateChecker = (pw: ProjectWrapper, filter: FilterModel) => + pw.dueDateMatches(filter.key); -export const addedDateChecker = (pw: ProjectWrapper, filter: FilterModel) => pw.addedDateMatches(filter.key); +export const addedDateChecker = (pw: ProjectWrapper, filter: FilterModel) => + pw.addedDateMatches(filter.key); -export function getFilteredEntities(entities: any[], filters: { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[]) { +export function getFilteredEntities( + entities: any[], + filters: { values: FilterModel[]; checker: Function; matchAll?: boolean; checkerArgs?: any }[] +) { const filteredEntities = []; for (const entity of entities) { let add = true; for (const filter of filters) { - add = add && checkFilter(entity, filter.values, filter.checker, filter.checkerArgs, filter.matchAll); + add = + add && + checkFilter( + entity, + filter.values, + filter.checker, + filter.checkerArgs, + filter.matchAll + ); } if (add) { filteredEntities.push(entity); diff --git a/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts b/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts index dd45bb8c7..d81c0fdef 100644 --- a/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/initials-avatar/initials-avatar.component.ts @@ -21,7 +21,10 @@ export class InitialsAvatarComponent implements OnChanges { initials: string; colorClass: string; - constructor(private readonly _userService: UserService, private readonly _translateService: TranslateService) {} + constructor( + private readonly _userService: UserService, + private readonly _translateService: TranslateService + ) {} get hasBorder(): boolean { return !!this.user && !this._isCurrentUser && this._userService.isManager(this.user); diff --git a/apps/red-ui/src/app/modules/shared/components/pagination/pagination.component.html b/apps/red-ui/src/app/modules/shared/components/pagination/pagination.component.html index 1132b89e6..61fb9d393 100644 --- a/apps/red-ui/src/app/modules/shared/components/pagination/pagination.component.html +++ b/apps/red-ui/src/app/modules/shared/components/pagination/pagination.component.html @@ -1,7 +1,23 @@ -
+
| -
+
{{ displayValue(page) }}
| -
+
diff --git a/apps/red-ui/src/app/modules/shared/components/pagination/pagination.component.ts b/apps/red-ui/src/app/modules/shared/components/pagination/pagination.component.ts index 951c66126..b6ce6b86d 100644 --- a/apps/red-ui/src/app/modules/shared/components/pagination/pagination.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/pagination/pagination.component.ts @@ -50,7 +50,11 @@ export class PaginationComponent { if (Math.max(1, this.currentPage - 1) > 1) { this.displayedPages.push('...'); } - for (let page = Math.max(1, this.currentPage - 1); page <= Math.min(this.currentPage + 1, this.totalPages - 1); ++page) { + for ( + let page = Math.max(1, this.currentPage - 1); + page <= Math.min(this.currentPage + 1, this.totalPages - 1); + ++page + ) { this.displayedPages.push(page); } if (Math.min(this.currentPage + 1, this.totalPages - 1) !== this.totalPages - 1) { diff --git a/apps/red-ui/src/app/modules/shared/components/search-input/search-input.component.html b/apps/red-ui/src/app/modules/shared/components/search-input/search-input.component.html index f1fc3a100..3fb32e84f 100644 --- a/apps/red-ui/src/app/modules/shared/components/search-input/search-input.component.html +++ b/apps/red-ui/src/app/modules/shared/components/search-input/search-input.component.html @@ -1,7 +1,18 @@
- + - +
diff --git a/apps/red-ui/src/app/modules/shared/components/select/select.component.html b/apps/red-ui/src/app/modules/shared/components/select/select.component.html index 10d7fc79b..ab2c056cf 100644 --- a/apps/red-ui/src/app/modules/shared/components/select/select.component.html +++ b/apps/red-ui/src/app/modules/shared/components/select/select.component.html @@ -2,13 +2,31 @@
{{ label }}
-
-
+
+
- - + + {{ translatePrefix + option | translate }} diff --git a/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.html b/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.html index 6ebc25363..709f2f4f5 100644 --- a/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.html +++ b/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.html @@ -1,5 +1,11 @@
- + -
+
{{ displayedDataTotal }}
{{ subtitle | translate }}
-
+
-
+
- -
+ +
diff --git a/apps/red-ui/src/app/modules/shared/dialogs/confirmation-dialog/confirmation-dialog.component.html b/apps/red-ui/src/app/modules/shared/dialogs/confirmation-dialog/confirmation-dialog.component.html index cb48ba6d0..a39da3077 100644 --- a/apps/red-ui/src/app/modules/shared/dialogs/confirmation-dialog/confirmation-dialog.component.html +++ b/apps/red-ui/src/app/modules/shared/dialogs/confirmation-dialog/confirmation-dialog.component.html @@ -4,17 +4,32 @@
-

+

- + diff --git a/apps/red-ui/src/app/modules/shared/dialogs/confirmation-dialog/confirmation-dialog.component.ts b/apps/red-ui/src/app/modules/shared/dialogs/confirmation-dialog/confirmation-dialog.component.ts index 7f578339e..aa505a42e 100644 --- a/apps/red-ui/src/app/modules/shared/dialogs/confirmation-dialog/confirmation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/shared/dialogs/confirmation-dialog/confirmation-dialog.component.ts @@ -12,9 +12,11 @@ export class ConfirmationDialogInput { constructor(options: ConfirmationDialogInput) { this.title = options.title || ConfirmationDialogInput.default().title; this.question = options.question || ConfirmationDialogInput.default().question; - this.confirmationText = options.confirmationText || ConfirmationDialogInput.default().confirmationText; + this.confirmationText = + options.confirmationText || ConfirmationDialogInput.default().confirmationText; this.denyText = options.denyText || ConfirmationDialogInput.default().denyText; - this.translateParams = options.translateParams || ConfirmationDialogInput.default().translateParams; + this.translateParams = + options.translateParams || ConfirmationDialogInput.default().translateParams; } static default() { diff --git a/apps/red-ui/src/app/modules/shared/directives/has-scrollbar.directive.ts b/apps/red-ui/src/app/modules/shared/directives/has-scrollbar.directive.ts index d0c832652..8fb57ac82 100644 --- a/apps/red-ui/src/app/modules/shared/directives/has-scrollbar.directive.ts +++ b/apps/red-ui/src/app/modules/shared/directives/has-scrollbar.directive.ts @@ -10,7 +10,10 @@ export class HasScrollbarDirective implements AfterContentChecked { constructor(private readonly _elementRef: ElementRef) {} get hasScrollbar() { - return this._elementRef?.nativeElement.clientHeight < this._elementRef?.nativeElement.scrollHeight; + return ( + this._elementRef?.nativeElement.clientHeight < + this._elementRef?.nativeElement.scrollHeight + ); } ngAfterContentChecked() { diff --git a/apps/red-ui/src/app/modules/shared/directives/sync-width.directive.ts b/apps/red-ui/src/app/modules/shared/directives/sync-width.directive.ts index 495cbeb5e..0f1b5f46b 100644 --- a/apps/red-ui/src/app/modules/shared/directives/sync-width.directive.ts +++ b/apps/red-ui/src/app/modules/shared/directives/sync-width.directive.ts @@ -1,4 +1,11 @@ -import { AfterViewInit, Directive, ElementRef, HostListener, Input, OnDestroy } from '@angular/core'; +import { + AfterViewInit, + Directive, + ElementRef, + HostListener, + Input, + OnDestroy +} from '@angular/core'; import { debounce } from '@utils/debounce'; @Directive({ @@ -25,7 +32,9 @@ export class SyncWidthDirective implements AfterViewInit, OnDestroy { @debounce(10) matchWidth() { const headerItems = this._elementRef.nativeElement.children; - const tableRows = this._elementRef.nativeElement.parentElement.getElementsByClassName(this.redactionSyncWidth); + const tableRows = this._elementRef.nativeElement.parentElement.getElementsByClassName( + this.redactionSyncWidth + ); if (!tableRows || !tableRows.length) { return; @@ -39,8 +48,12 @@ export class SyncWidthDirective implements AfterViewInit, OnDestroy { for (let idx = 0; idx < length - hasExtraColumns - 1; ++idx) { if (headerItems[idx]) { - headerItems[idx].style.width = `${tableRow.children[idx].getBoundingClientRect().width}px`; - headerItems[idx].style.minWidth = `${tableRow.children[idx].getBoundingClientRect().width}px`; + headerItems[idx].style.width = `${ + tableRow.children[idx].getBoundingClientRect().width + }px`; + headerItems[idx].style.minWidth = `${ + tableRow.children[idx].getBoundingClientRect().width + }px`; } } @@ -56,7 +69,10 @@ export class SyncWidthDirective implements AfterViewInit, OnDestroy { this.matchWidth(); } - private _sampleRow(tableRows: HTMLCollectionOf): { tableRow: Element; length: number } { + private _sampleRow(tableRows: HTMLCollectionOf): { + tableRow: Element; + length: number; + } { let length = 0; let tableRow: Element; diff --git a/apps/red-ui/src/app/modules/shared/services/dictionary-save.service.ts b/apps/red-ui/src/app/modules/shared/services/dictionary-save.service.ts index dc72fa7f0..a6254f7a7 100644 --- a/apps/red-ui/src/app/modules/shared/services/dictionary-save.service.ts +++ b/apps/red-ui/src/app/modules/shared/services/dictionary-save.service.ts @@ -17,7 +17,13 @@ export class DictionarySaveService { private readonly _dictionaryControllerService: DictionaryControllerService ) {} - saveEntries(entries: string[], initialEntries: string[], ruleSetId: string, type: string, dossierId: string): Observable { + saveEntries( + entries: string[], + initialEntries: string[], + ruleSetId: string, + type: string, + dossierId: string + ): Observable { let entriesToAdd = []; entries.forEach((currentEntry) => { entriesToAdd.push(currentEntry); @@ -29,9 +35,20 @@ export class DictionarySaveService { // can add at least 1 - block UI let obs: Observable; if (entriesToAdd.length > 0) { - obs = this._dictionaryControllerService.addEntry(entriesToAdd, ruleSetId, type, dossierId, true); + obs = this._dictionaryControllerService.addEntry( + entriesToAdd, + ruleSetId, + type, + dossierId, + true + ); } else { - obs = this._dictionaryControllerService.deleteEntries(initialEntries, ruleSetId, type, dossierId); + obs = this._dictionaryControllerService.deleteEntries( + initialEntries, + ruleSetId, + type, + dossierId + ); } return obs.pipe( diff --git a/apps/red-ui/src/app/modules/shared/shared.module.ts b/apps/red-ui/src/app/modules/shared/shared.module.ts index 5a570d5f7..690e5f3ad 100644 --- a/apps/red-ui/src/app/modules/shared/shared.module.ts +++ b/apps/red-ui/src/app/modules/shared/shared.module.ts @@ -35,7 +35,13 @@ import { NavigateLastProjectsScreenDirective } from './directives/navigate-last- import { DictionaryManagerComponent } from './components/dictionary-manager/dictionary-manager.component'; import { AceEditorModule } from 'ng2-ace-editor'; -const buttons = [ChevronButtonComponent, CircleButtonComponent, FileDownloadBtnComponent, IconButtonComponent, UserButtonComponent]; +const buttons = [ + ChevronButtonComponent, + CircleButtonComponent, + FileDownloadBtnComponent, + IconButtonComponent, + UserButtonComponent +]; const components = [ FullPageLoadingIndicatorComponent, @@ -58,9 +64,21 @@ const components = [ ...buttons ]; -const utils = [HumanizePipe, SyncWidthDirective, HasScrollbarDirective, NavigateLastProjectsScreenDirective]; +const utils = [ + HumanizePipe, + SyncWidthDirective, + HasScrollbarDirective, + NavigateLastProjectsScreenDirective +]; -const modules = [MatConfigModule, TranslateModule, ScrollingModule, IconsModule, FormsModule, ReactiveFormsModule]; +const modules = [ + MatConfigModule, + TranslateModule, + ScrollingModule, + IconsModule, + FormsModule, + ReactiveFormsModule +]; @NgModule({ declarations: [...components, ...utils, DictionaryManagerComponent], diff --git a/apps/red-ui/src/app/modules/upload-download/dialogs/overwrite-files-dialog/overwrite-files-dialog.component.html b/apps/red-ui/src/app/modules/upload-download/dialogs/overwrite-files-dialog/overwrite-files-dialog.component.html index bdfaead61..0cc5b1431 100644 --- a/apps/red-ui/src/app/modules/upload-download/dialogs/overwrite-files-dialog/overwrite-files-dialog.component.html +++ b/apps/red-ui/src/app/modules/upload-download/dialogs/overwrite-files-dialog/overwrite-files-dialog.component.html @@ -4,14 +4,32 @@

- + {{ 'overwrite-files-dialog.options.remember' | translate }}
- - -
+ + +
diff --git a/apps/red-ui/src/app/modules/upload-download/file-upload-download.module.ts b/apps/red-ui/src/app/modules/upload-download/file-upload-download.module.ts index e045fab1e..feb65ed38 100644 --- a/apps/red-ui/src/app/modules/upload-download/file-upload-download.module.ts +++ b/apps/red-ui/src/app/modules/upload-download/file-upload-download.module.ts @@ -15,7 +15,13 @@ import { FileDropOverlayService } from './services/file-drop-overlay.service'; imports: [CommonModule, SharedModule, OverlayModule], declarations: [FileDropComponent, UploadStatusOverlayComponent, OverwriteFilesDialogComponent], entryComponents: [FileDropComponent, UploadStatusOverlayComponent], - providers: [UploadDownloadDialogService, FileUploadService, FileDownloadService, StatusOverlayService, FileDropOverlayService], + providers: [ + UploadDownloadDialogService, + FileUploadService, + FileDownloadService, + StatusOverlayService, + FileDropOverlayService + ], exports: [FileDropComponent, UploadStatusOverlayComponent] }) export class FileUploadDownloadModule {} diff --git a/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts b/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts index 973e43f94..28cd99f95 100644 --- a/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts +++ b/apps/red-ui/src/app/modules/upload-download/model/download-status.wrapper.ts @@ -6,8 +6,15 @@ export class DownloadStatusWrapper { constructor(private _downloadStatus: DownloadStatus) {} get size() { - const i = this._downloadStatus.fileSize === 0 ? 0 : Math.floor(Math.log(this._downloadStatus.fileSize) / Math.log(1024)); - return (this._downloadStatus.fileSize / Math.pow(1024, i)).toFixed(2) + ' ' + ['B', 'kB', 'MB', 'GB', 'TB'][i]; + const i = + this._downloadStatus.fileSize === 0 + ? 0 + : Math.floor(Math.log(this._downloadStatus.fileSize) / Math.log(1024)); + return ( + (this._downloadStatus.fileSize / Math.pow(1024, i)).toFixed(2) + + ' ' + + ['B', 'kB', 'MB', 'GB', 'TB'][i] + ); } get creationDate() { diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts index 82fdb953c..7608696b9 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-download.service.ts @@ -34,12 +34,19 @@ export class FileDownloadService { }); } - downloadFiles(fileStatusWrappers: FileStatusWrapper[], project: ProjectWrapper): Observable { + downloadFiles( + fileStatusWrappers: FileStatusWrapper[], + project: ProjectWrapper + ): Observable { return this._downloadControllerService .prepareDownload({ fileIds: fileStatusWrappers.map((f) => f.fileId), projectId: project.projectId, - reportTypes: ['WORD_SINGLE_FILE_EFSA_TEMPLATE', 'WORD_SINGLE_FILE_SYNGENTA_TEMPLATE', 'EXCEL_MULTI_FILE'], + reportTypes: [ + 'WORD_SINGLE_FILE_EFSA_TEMPLATE', + 'WORD_SINGLE_FILE_SYNGENTA_TEMPLATE', + 'EXCEL_MULTI_FILE' + ], downloadFileTypes: ['PREVIEW', 'REDACTED'] }) .pipe(mergeMap(() => this.getDownloadStatus())); @@ -48,8 +55,12 @@ export class FileDownloadService { getDownloadStatus() { return this._downloadControllerService.getDownloadStatus().pipe( tap((statusResponse) => { - this.downloads = statusResponse.downloadStatus.map((d) => new DownloadStatusWrapper(d)); - this.hasPendingDownloads = !!this.downloads.find((f) => !f.lastDownload && f.isReady); + this.downloads = statusResponse.downloadStatus.map( + (d) => new DownloadStatusWrapper(d) + ); + this.hasPendingDownloads = !!this.downloads.find( + (f) => !f.lastDownload && f.isReady + ); }) ); } diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-drop-overlay.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-drop-overlay.service.ts index 8783d5b24..849c0e596 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-drop-overlay.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-drop-overlay.service.ts @@ -42,15 +42,25 @@ export class FileDropOverlayService { }; initFileDropHandling() { - document.getElementsByTagName('body')[0].addEventListener('dragenter', this.dragListener, false); - document.getElementsByTagName('body')[0].addEventListener('mouseenter', this.mouseIn, false); + document + .getElementsByTagName('body')[0] + .addEventListener('dragenter', this.dragListener, false); + document + .getElementsByTagName('body')[0] + .addEventListener('mouseenter', this.mouseIn, false); document.getElementsByTagName('body')[0].addEventListener('mouseout', this.mouseOut, false); } cleanupFileDropHandling() { - document.getElementsByTagName('body')[0].removeEventListener('dragenter', this.dragListener, false); - document.getElementsByTagName('body')[0].removeEventListener('mouseenter', this.mouseIn, false); - document.getElementsByTagName('body')[0].removeEventListener('mouseout', this.mouseOut, false); + document + .getElementsByTagName('body')[0] + .removeEventListener('dragenter', this.dragListener, false); + document + .getElementsByTagName('body')[0] + .removeEventListener('mouseenter', this.mouseIn, false); + document + .getElementsByTagName('body')[0] + .removeEventListener('mouseout', this.mouseOut, false); } openFileDropOverlay() { diff --git a/apps/red-ui/src/app/modules/upload-download/services/file-upload.service.ts b/apps/red-ui/src/app/modules/upload-download/services/file-upload.service.ts index 1329b6f0a..3b8e44ad6 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/file-upload.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/file-upload.service.ts @@ -38,7 +38,9 @@ export class FileUploadService { } get activeProjectKeys() { - return Object.keys(this.groupedFiles).filter((projectId) => this.groupedFiles[projectId].length > 0); + return Object.keys(this.groupedFiles).filter( + (projectId) => this.groupedFiles[projectId].length > 0 + ); } scheduleUpload(item: FileUploadModel) { @@ -76,7 +78,11 @@ export class FileUploadService { } if (file.size > maxSizeBytes) { file.completed = true; - file.error = { message: this._translateService.instant('upload-status.error.file-size', { size: maxSizeMB }) }; + file.error = { + message: this._translateService.instant('upload-status.error.file-size', { + size: maxSizeMB + }) + }; file.sizeError = true; } } @@ -124,14 +130,20 @@ export class FileUploadService { } private _handleUploads() { - if (this._activeUploads.length < FileUploadService.MAX_PARALLEL_UPLOADS && this._pendingUploads.length > 0) { + if ( + this._activeUploads.length < FileUploadService.MAX_PARALLEL_UPLOADS && + this._pendingUploads.length > 0 + ) { let cnt = FileUploadService.MAX_PARALLEL_UPLOADS - this._activeUploads.length; while (cnt > 0) { cnt--; const poppedFileUploadModel = this._pendingUploads.shift(); if (poppedFileUploadModel) { const subscription = this._createSubscription(poppedFileUploadModel); - this._activeUploads.push({ subscription: subscription, fileUploadModel: poppedFileUploadModel }); + this._activeUploads.push({ + subscription: subscription, + fileUploadModel: poppedFileUploadModel + }); } else { return; } @@ -141,11 +153,18 @@ export class FileUploadService { private _createSubscription(uploadFile: FileUploadModel) { this.activeUploads++; - const obs = this._fileManagementControllerService.uploadFileForm(uploadFile.file, uploadFile.projectId, 'events', true); + const obs = this._fileManagementControllerService.uploadFileForm( + uploadFile.file, + uploadFile.projectId, + 'events', + true + ); const subscription = obs.subscribe( async (event) => { if (event.type === HttpEventType.UploadProgress) { - uploadFile.progress = Math.round((event.loaded / (event.total || event.loaded)) * 100); + uploadFile.progress = Math.round( + (event.loaded / (event.total || event.loaded)) * 100 + ); this._applicationRef.tick(); } if (event.type === HttpEventType.Response) { @@ -154,7 +173,9 @@ export class FileUploadService { uploadFile.completed = true; } else { uploadFile.completed = true; - uploadFile.error = { message: this._translateService.instant('upload-status.error.generic') }; + uploadFile.error = { + message: this._translateService.instant('upload-status.error.generic') + }; } this._removeUpload(uploadFile); await this._appStateService.reloadActiveProjectFiles(); @@ -162,7 +183,9 @@ export class FileUploadService { }, () => { uploadFile.completed = true; - uploadFile.error = { message: this._translateService.instant('upload-status.error.generic') }; + uploadFile.error = { + message: this._translateService.instant('upload-status.error.generic') + }; this._removeUpload(uploadFile); if (uploadFile.retryCount < 5) { uploadFile.retryCount += 1; diff --git a/apps/red-ui/src/app/modules/upload-download/services/status-overlay.service.ts b/apps/red-ui/src/app/modules/upload-download/services/status-overlay.service.ts index 2bd7148bd..091c8425b 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/status-overlay.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/status-overlay.service.ts @@ -12,7 +12,11 @@ export class StatusOverlayService { } openUploadStatusOverlay() { - const component = new ComponentPortal(UploadStatusOverlayComponent, null, this._createUploadInjector()); + const component = new ComponentPortal( + UploadStatusOverlayComponent, + null, + this._createUploadInjector() + ); if (!this._uploadStatusOverlayRef.hasAttached()) { this._uploadStatusOverlayRef.attach(component); } diff --git a/apps/red-ui/src/app/modules/upload-download/services/upload-download-dialog.service.ts b/apps/red-ui/src/app/modules/upload-download/services/upload-download-dialog.service.ts index 686f04943..705cd75ab 100644 --- a/apps/red-ui/src/app/modules/upload-download/services/upload-download-dialog.service.ts +++ b/apps/red-ui/src/app/modules/upload-download/services/upload-download-dialog.service.ts @@ -12,7 +12,9 @@ const dialogConfig = { export class UploadDownloadDialogService { constructor(private readonly _dialog: MatDialog) {} - openOverwriteFileDialog(filename: string): Promise<{ option?: 'overwrite' | 'skip'; remember?: boolean; cancel?: boolean }> { + openOverwriteFileDialog( + filename: string + ): Promise<{ option?: 'overwrite' | 'skip'; remember?: boolean; cancel?: boolean }> { const ref = this._dialog.open(OverwriteFilesDialogComponent, { ...dialogConfig, data: filename diff --git a/apps/red-ui/src/app/modules/upload-download/upload-status-overlay/upload-status-overlay.component.html b/apps/red-ui/src/app/modules/upload-download/upload-status-overlay/upload-status-overlay.component.html index 5d95c9694..37189cd38 100644 --- a/apps/red-ui/src/app/modules/upload-download/upload-status-overlay/upload-status-overlay.component.html +++ b/apps/red-ui/src/app/modules/upload-download/upload-status-overlay/upload-status-overlay.component.html @@ -1,17 +1,30 @@
-
+
{{ 'upload-status.dialog.title' | translate: { len: uploadService.files.length } }}
- - + +
{{ uploadService.groupedFiles[projectId][0].projectName }}
-
+
- +
-
+
{ diff --git a/apps/red-ui/src/app/services/permissions.service.ts b/apps/red-ui/src/app/services/permissions.service.ts index ff22c66e8..765a5abec 100644 --- a/apps/red-ui/src/app/services/permissions.service.ts +++ b/apps/red-ui/src/app/services/permissions.service.ts @@ -9,7 +9,10 @@ import { ProjectWrapper } from '@state/model/project.wrapper'; providedIn: 'root' }) export class PermissionsService { - constructor(private readonly _appStateService: AppStateService, private _userService: UserService) {} + constructor( + private readonly _appStateService: AppStateService, + private _userService: UserService + ) {} get currentUser() { return this._userService.user; @@ -44,8 +47,11 @@ export class PermissionsService { return false; } return ( - ((fileStatus.status === 'UNASSIGNED' || fileStatus.status === 'UNDER_REVIEW' || fileStatus.status === 'UNDER_APPROVAL') && - (!this._appStateService.fileIsUpToDateWithLatestVersions(fileStatus) || fileStatus.hasUnappliedSuggestions)) || + ((fileStatus.status === 'UNASSIGNED' || + fileStatus.status === 'UNDER_REVIEW' || + fileStatus.status === 'UNDER_APPROVAL') && + (!this._appStateService.fileIsUpToDateWithLatestVersions(fileStatus) || + fileStatus.hasUnappliedSuggestions)) || fileStatus.isError ); } @@ -57,7 +63,10 @@ export class PermissionsService { if (!project) { return false; } - return this.isApprover(project) && project.files.filter((file) => this.fileRequiresReanalysis(file)).length > 0; + return ( + this.isApprover(project) && + project.files.filter((file) => this.fileRequiresReanalysis(file)).length > 0 + ); } canReanalyseFile(fileStatus?: FileStatusWrapper) { @@ -68,7 +77,8 @@ export class PermissionsService { return false; } return ( - (this.fileRequiresReanalysis(fileStatus) && (this.isReviewerOrApprover(fileStatus) || fileStatus.isUnassigned)) || + (this.fileRequiresReanalysis(fileStatus) && + (this.isReviewerOrApprover(fileStatus) || fileStatus.isUnassigned)) || (fileStatus.isError && fileStatus.isUnassigned) ); } @@ -134,7 +144,11 @@ export class PermissionsService { if (!fileStatus) { return false; } - return !fileStatus.hasRequests && !fileStatus.hasUnappliedSuggestions && this._appStateService.fileIsUpToDateWithLatestVersions(fileStatus); + return ( + !fileStatus.hasRequests && + !fileStatus.hasUnappliedSuggestions && + this._appStateService.fileIsUpToDateWithLatestVersions(fileStatus) + ); } canSetUnderApproval(fileStatus?: FileStatusWrapper) { @@ -193,7 +207,10 @@ export class PermissionsService { if (!fileStatus) { return false; } - return (fileStatus.status === 'UNDER_APPROVAL' || fileStatus.status === 'UNDER_REVIEW') && this.isFileReviewer(fileStatus); + return ( + (fileStatus.status === 'UNDER_APPROVAL' || fileStatus.status === 'UNDER_REVIEW') && + this.isFileReviewer(fileStatus) + ); } canOpenFile(fileStatus: FileStatusWrapper) { @@ -203,7 +220,7 @@ export class PermissionsService { if (!fileStatus) { return false; } - return !fileStatus.isError && !fileStatus.isProcessing && !fileStatus.isPending; //&& this.isReviewerOrOwner(fileStatus); + return !fileStatus.isError && !fileStatus.isProcessing && !fileStatus.isPending; } canAssignReviewer(fileStatus?: FileStatusWrapper) { @@ -250,7 +267,10 @@ export class PermissionsService { if (!fileStatus) { return false; } - return (fileStatus.status === 'UNDER_REVIEW' && this.isFileReviewer(fileStatus)) || (fileStatus.status === 'UNDER_APPROVAL' && this.isApprover()); + return ( + (fileStatus.status === 'UNDER_REVIEW' && this.isFileReviewer(fileStatus)) || + (fileStatus.status === 'UNDER_APPROVAL' && this.isApprover()) + ); } canDownloadRedactedFile(fileStatus: FileStatusWrapper) { @@ -314,7 +334,11 @@ export class PermissionsService { if (!fileStatus) { return false; } - return fileStatus.status === 'UNASSIGNED' || fileStatus.status === 'UNDER_REVIEW' || fileStatus.status === 'UNDER_APPROVAL'; + return ( + fileStatus.status === 'UNASSIGNED' || + fileStatus.status === 'UNDER_REVIEW' || + fileStatus.status === 'UNDER_APPROVAL' + ); } canManageUsers(user?: UserWrapper) { diff --git a/apps/red-ui/src/app/services/router-history.service.ts b/apps/red-ui/src/app/services/router-history.service.ts index 8eee3e7ff..4daac8afc 100644 --- a/apps/red-ui/src/app/services/router-history.service.ts +++ b/apps/red-ui/src/app/services/router-history.service.ts @@ -9,11 +9,13 @@ export class RouterHistoryService { private _lastProjectsScreen = '/main/projects'; constructor(private readonly _router: Router) { - this._router.events.pipe(filter((event) => event instanceof NavigationEnd)).subscribe((event: NavigationEnd) => { - if (event.url.startsWith('/main/projects')) { - this._lastProjectsScreen = event.url; - } - }); + this._router.events + .pipe(filter((event) => event instanceof NavigationEnd)) + .subscribe((event: NavigationEnd) => { + if (event.url.startsWith('/main/projects')) { + this._lastProjectsScreen = event.url; + } + }); } navigateToLastProjectsScreen() { diff --git a/apps/red-ui/src/app/services/sorting.service.ts b/apps/red-ui/src/app/services/sorting.service.ts index cccd17686..a1848880e 100644 --- a/apps/red-ui/src/app/services/sorting.service.ts +++ b/apps/red-ui/src/app/services/sorting.service.ts @@ -5,7 +5,13 @@ export class SortingOption { column: string; } -export type ScreenName = 'project-listing' | 'project-overview' | 'dictionary-listing' | 'rule-sets-listing' | 'default-colors' | 'file-attributes-listing'; +export type ScreenName = + | 'project-listing' + | 'project-overview' + | 'dictionary-listing' + | 'rule-sets-listing' + | 'default-colors' + | 'file-attributes-listing'; @Injectable({ providedIn: 'root' diff --git a/apps/red-ui/src/app/services/user.service.ts b/apps/red-ui/src/app/services/user.service.ts index 7454b9f8c..27bc9295a 100644 --- a/apps/red-ui/src/app/services/user.service.ts +++ b/apps/red-ui/src/app/services/user.service.ts @@ -75,7 +75,9 @@ export class UserService { } get eligibleUsers(): User[] { - return this._allUsers.filter((u) => u.roles.indexOf('RED_USER') >= 0 || u.roles.indexOf('RED_MANAGER') >= 0); + return this._allUsers.filter( + (u) => u.roles.indexOf('RED_USER') >= 0 || u.roles.indexOf('RED_MANAGER') >= 0 + ); } get user() { @@ -103,7 +105,11 @@ export class UserService { const token = await this._keycloakService.getToken(); const decoded = jwt_decode(token) as any; const userId = decoded.sub; - this._currentUser = new UserWrapper(await this._keycloakService.loadUserProfile(false), this._keycloakService.getUserRoles(true), userId); + this._currentUser = new UserWrapper( + await this._keycloakService.loadUserProfile(false), + this._keycloakService.getUserRoles(true), + userId + ); } getUserById(id: string) { @@ -115,7 +121,11 @@ export class UserService { } getName(user?: User) { - return user ? (user.firstName && user.lastName ? `${user.firstName} ${user.lastName}` : user.username) : undefined; + return user + ? user.firstName && user.lastName + ? `${user.firstName} ${user.lastName}` + : user.username + : undefined; } isManager(user?: User): boolean { diff --git a/apps/red-ui/src/app/state/app-state.guard.ts b/apps/red-ui/src/app/state/app-state.guard.ts index d6853bc96..e9912a4d0 100644 --- a/apps/red-ui/src/app/state/app-state.guard.ts +++ b/apps/red-ui/src/app/state/app-state.guard.ts @@ -7,7 +7,11 @@ import { UserService } from '@services/user.service'; providedIn: 'root' }) export class AppStateGuard implements CanActivate { - constructor(private readonly _appStateService: AppStateService, private readonly _userService: UserService, private readonly _router: Router) {} + constructor( + private readonly _appStateService: AppStateService, + private readonly _userService: UserService, + private readonly _router: Router + ) {} async canActivate(route: ActivatedRouteSnapshot): Promise { if (this._userService.user.isUserAdmin) { diff --git a/apps/red-ui/src/app/state/app-state.service.ts b/apps/red-ui/src/app/state/app-state.service.ts index 2dee840ff..d34171f20 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -122,7 +122,9 @@ export class AppStateService { } get activeDictionary(): TypeValue { - return this.activeRuleSetId && this.dictionaryData[this.activeRuleSetId] ? this.dictionaryData[this.activeRuleSetId][this.activeDictionaryType] : null; + return this.activeRuleSetId && this.dictionaryData[this.activeRuleSetId] + ? this.dictionaryData[this.activeRuleSetId][this.activeDictionaryType] + : null; } get activeProjectId(): string { @@ -162,15 +164,27 @@ export class AppStateService { } private static _isFileOverviewRoute(event: Event) { - return event instanceof ResolveStart && event.url.includes('/main/projects/') && event.url.includes('/file/'); + return ( + event instanceof ResolveStart && + event.url.includes('/main/projects/') && + event.url.includes('/file/') + ); } private static _isProjectOverviewRoute(event: Event) { - return event instanceof ResolveStart && event.url.includes('/main/projects/') && !event.url.includes('/file/'); + return ( + event instanceof ResolveStart && + event.url.includes('/main/projects/') && + !event.url.includes('/file/') + ); } private static _isRandomRoute(event: Event) { - return event instanceof NavigationEnd && !event.url.includes('/main/projects/') && !event.url.includes('/file/'); + return ( + event instanceof NavigationEnd && + !event.url.includes('/main/projects/') && + !event.url.includes('/file/') + ); } async reloadActiveProjectFilesIfNecessary() { @@ -192,7 +206,8 @@ export class AppStateService { return ( fileStatus.dictionaryVersion === this._dictionaryVersion(ruleSetId) && fileStatus.rulesVersion === this._rulesVersion(ruleSetId) && - (!project.dictionaryVersion || fileStatus.dossierDictionaryVersion === project.dictionaryVersion) + (!project.dictionaryVersion || + fileStatus.dossierDictionaryVersion === project.dictionaryVersion) ); } @@ -268,9 +283,13 @@ export class AppStateService { async loadAllProjects(emitEvents: boolean = true) { const projects = await this._projectControllerService.getProjects().toPromise(); if (projects) { - const mappedProjects = projects.map((p) => new ProjectWrapper(p, this._getExistingFiles(p.projectId))); + const mappedProjects = projects.map( + (p) => new ProjectWrapper(p, this._getExistingFiles(p.projectId)) + ); - const fileData = await this._statusControllerService.getFileStatusForProjects(mappedProjects.map((p) => p.projectId)).toPromise(); + const fileData = await this._statusControllerService + .getFileStatusForProjects(mappedProjects.map((p) => p.projectId)) + .toPromise(); for (const projectId of Object.keys(fileData)) { const project = mappedProjects.find((p) => p.projectId === projectId); @@ -289,7 +308,9 @@ export class AppStateService { return null; } const oldProcessedDate = this.activeFile.lastProcessed; - const activeFile = await this._statusControllerService.getFileStatus(this.activeProjectId, this.activeFileId).toPromise(); + const activeFile = await this._statusControllerService + .getFileStatus(this.activeProjectId, this.activeFileId) + .toPromise(); const activeFileWrapper = new FileStatusWrapper( activeFile, @@ -297,7 +318,9 @@ export class AppStateService { this.activeProject.ruleSetId, this._appState.fileAttributesConfig[this.activeProject.ruleSetId] ); - this.activeProject.files = this.activeProject.files.map((file) => (file.fileId === activeFileWrapper.fileId ? activeFileWrapper : file)); + this.activeProject.files = this.activeProject.files.map((file) => + file.fileId === activeFileWrapper.fileId ? activeFileWrapper : file + ); await this.updateDictionaryVersion(); this._computeStats(); @@ -312,7 +335,9 @@ export class AppStateService { if (!project) { project = this.activeProject; } - const files = await this._statusControllerService.getProjectStatus(project.projectId).toPromise(); + const files = await this._statusControllerService + .getProjectStatus(project.projectId) + .toPromise(); return this._processFiles(project, files, emitEvents); } @@ -338,18 +363,21 @@ export class AppStateService { updateProjectDictionary(ruleSetId: string, projectId: string) { // project exists, load it's dictionary - this._dictionaryControllerService.getDictionaryForType(ruleSetId, 'dossier_redaction', projectId).subscribe( - (typeData) => { - this.activeProject.type = typeData; - }, - () => { - this.activeProject.type = null; - } - ); + this._dictionaryControllerService + .getDictionaryForType(ruleSetId, 'dossier_redaction', projectId) + .subscribe( + (typeData) => { + this.activeProject.type = typeData; + }, + () => { + this.activeProject.type = null; + } + ); } activateFile(projectId: string, fileId: string) { - if (this._appState.activeProjectId === projectId && this._appState.activeFileId === fileId) return; + if (this._appState.activeProjectId === projectId && this._appState.activeFileId === fileId) + return; this.activateProject(projectId); if (this.activeProject) { this._appState.activeFileId = fileId; @@ -393,7 +421,9 @@ export class AppStateService { .toPromise() .then( () => { - const index = this._appState.projects.findIndex((p) => p.project.projectId === project.projectId); + const index = this._appState.projects.findIndex( + (p) => p.project.projectId === project.projectId + ); this._appState.projects.splice(index, 1); this._appState.projects = [...this._appState.projects]; }, @@ -409,8 +439,12 @@ export class AppStateService { async addOrUpdateProject(project: Project) { try { - const updatedProject = await this._projectControllerService.createOrUpdateProject(project).toPromise(); - let foundProject = this._appState.projects.find((p) => p.project.projectId === updatedProject.projectId); + const updatedProject = await this._projectControllerService + .createOrUpdateProject(project) + .toPromise(); + let foundProject = this._appState.projects.find( + (p) => p.project.projectId === updatedProject.projectId + ); if (foundProject) { Object.assign((foundProject.project = updatedProject)); } else { @@ -422,7 +456,9 @@ export class AppStateService { } catch (error) { this._notificationService.showToastNotification( this._translateService.instant( - error.status === 409 ? 'project-listing.add-edit-dialog.errors.project-already-exists' : 'project-listing.add-edit-dialog.errors.generic' + error.status === 409 + ? 'project-listing.add-edit-dialog.errors.project-already-exists' + : 'project-listing.add-edit-dialog.errors.generic' ), null, NotificationType.ERROR @@ -437,13 +473,16 @@ export class AppStateService { } async loadAllRuleSets() { - this._appState.ruleSets = await this._ruleSetControllerService.getAllRuleSets1().toPromise(); + this._appState.ruleSets = await this._ruleSetControllerService + .getAllRuleSets1() + .toPromise(); this._appState.fileAttributesConfig = {}; for (const ruleSet of this._appState.ruleSets) { - this._appState.fileAttributesConfig[ruleSet.ruleSetId] = await this._fileAttributesService - .getFileAttributesConfiguration(ruleSet.ruleSetId) - .pipe(catchError(() => of({}))) - .toPromise(); + this._appState.fileAttributesConfig[ruleSet.ruleSetId] = + await this._fileAttributesService + .getFileAttributesConfiguration(ruleSet.ruleSetId) + .pipe(catchError(() => of({}))) + .toPromise(); } } @@ -467,7 +506,10 @@ export class AppStateService { } } - getDictionaryDataForRuleSetObservables(ruleSetId: string, dictionaryData: { [key: string]: any }): Observable[] { + getDictionaryDataForRuleSetObservables( + ruleSetId: string, + dictionaryData: { [key: string]: any } + ): Observable[] { const typeObs = this._dictionaryControllerService.getAllTypes(ruleSetId).pipe( tap((typesResponse) => { for (const type of typesResponse.types) { @@ -610,7 +652,12 @@ export class AppStateService { for (const ruleSet of this.ruleSets) { obj[ruleSet.ruleSetId] = {}; - observables.push(...this.getDictionaryDataForRuleSetObservables(ruleSet.ruleSetId, obj[ruleSet.ruleSetId])); + observables.push( + ...this.getDictionaryDataForRuleSetObservables( + ruleSet.ruleSetId, + obj[ruleSet.ruleSetId] + ) + ); } await forkJoin(observables).toPromise(); @@ -619,7 +666,9 @@ export class AppStateService { async updateDictionaryVersion() { const ruleSetIds = this.ruleSets.map((rs) => rs.ruleSetId); - this._appState.versions = await this._versionsControllerService.getVersions(ruleSetIds).toPromise(); + this._appState.versions = await this._versionsControllerService + .getVersions(ruleSetIds) + .toPromise(); } updateProjectDictionaryVersions() { @@ -630,7 +679,9 @@ export class AppStateService { } async updateProjectDictionaryVersion(project: ProjectWrapper) { - project.dictionaryVersion = await this._versionsControllerService.getDossierDictionaryVersion(project.projectId, project.ruleSetId).toPromise(); + project.dictionaryVersion = await this._versionsControllerService + .getDossierDictionaryVersion(project.projectId, project.ruleSetId) + .toPromise(); } private _getExistingFiles(projectId: string) { @@ -638,7 +689,11 @@ export class AppStateService { return found ? found.files : []; } - private _processFiles(project: ProjectWrapper, files: FileStatus[], emitEvents: boolean = true) { + private _processFiles( + project: ProjectWrapper, + files: FileStatus[], + emitEvents: boolean = true + ) { const oldFiles = [...project.files]; const fileStatusChangedEvent = []; diff --git a/apps/red-ui/src/app/state/model/project.wrapper.ts b/apps/red-ui/src/app/state/model/project.wrapper.ts index f2827c1d0..43557d58b 100644 --- a/apps/red-ui/src/app/state/model/project.wrapper.ts +++ b/apps/red-ui/src/app/state/model/project.wrapper.ts @@ -113,7 +113,8 @@ export class ProjectWrapper { this.hasRequests = this.hasRequests || f.hasRequests; this.allFilesApproved = this.allFilesApproved && f.isApproved; this.totalNumberOfPages += f.numberOfPages; - this.hasPendingOrProcessing = this.hasPendingOrProcessing || f.isPending || f.isProcessing; + this.hasPendingOrProcessing = + this.hasPendingOrProcessing || f.isPending || f.isProcessing; }); this.hasNone = !this.hasRequests && !this.hasRedactions && !this.hintsOnly; } diff --git a/apps/red-ui/src/app/utils/api-path-interceptor.ts b/apps/red-ui/src/app/utils/api-path-interceptor.ts index 61d262e22..78ae4a1f6 100644 --- a/apps/red-ui/src/app/utils/api-path-interceptor.ts +++ b/apps/red-ui/src/app/utils/api-path-interceptor.ts @@ -6,7 +6,10 @@ import { BASE_HREF } from '../tokens'; @Injectable() export class ApiPathInterceptor implements HttpInterceptor { - constructor(@Inject(BASE_HREF) private readonly _baseHref: string, private readonly _appConfigService: AppConfigService) {} + constructor( + @Inject(BASE_HREF) private readonly _baseHref: string, + private readonly _appConfigService: AppConfigService + ) {} intercept(req: HttpRequest, next: HttpHandler): Observable> { if (!req.url.startsWith('/assets')) { diff --git a/apps/red-ui/src/app/utils/custom-route-reuse.strategy.ts b/apps/red-ui/src/app/utils/custom-route-reuse.strategy.ts index a1075e72e..d3a1155d2 100644 --- a/apps/red-ui/src/app/utils/custom-route-reuse.strategy.ts +++ b/apps/red-ui/src/app/utils/custom-route-reuse.strategy.ts @@ -30,7 +30,10 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy { this._onDetach(element.componentRef?.instance); } - this._storedRoutes[this._getKey(route)] = { handle: element as DetachedRouteHandle, previousRoute: route }; + this._storedRoutes[this._getKey(route)] = { + handle: element as DetachedRouteHandle, + previousRoute: route + }; } shouldAttach(route: ActivatedRouteSnapshot): boolean { @@ -49,12 +52,17 @@ export class CustomRouteReuseStrategy implements RouteReuseStrategy { } shouldReuseRoute(future: ActivatedRouteSnapshot, current: ActivatedRouteSnapshot): boolean { - return future.routeConfig === current.routeConfig || this._getKey(future) === this._getKey(current); + return ( + future.routeConfig === current.routeConfig || + this._getKey(future) === this._getKey(current) + ); } private _getKey(route: ActivatedRouteSnapshot): string { return route.pathFromRoot - .map((el: ActivatedRouteSnapshot) => (el.routeConfig ? el.routeConfig.path + JSON.stringify(el.params) : '')) + .map((el: ActivatedRouteSnapshot) => + el.routeConfig ? el.routeConfig.path + JSON.stringify(el.params) : '' + ) .filter((str) => str.length > 0) .join(''); } diff --git a/apps/red-ui/src/app/utils/date-inputs-utils.ts b/apps/red-ui/src/app/utils/date-inputs-utils.ts index 5b5e30e3a..40770d10f 100644 --- a/apps/red-ui/src/app/utils/date-inputs-utils.ts +++ b/apps/red-ui/src/app/utils/date-inputs-utils.ts @@ -1,7 +1,14 @@ import { FormGroup } from '@angular/forms'; import { Moment } from 'moment'; -export function applyIntervalConstraints(value, previousFrom: Moment, previousTo: Moment, form: FormGroup, fromKey: string, toKey: string): boolean { +export function applyIntervalConstraints( + value, + previousFrom: Moment, + previousTo: Moment, + form: FormGroup, + fromKey: string, + toKey: string +): boolean { if (!!value[fromKey] && !!value[toKey]) { if (previousFrom !== value[fromKey]) { if (value[toKey].isBefore(value[fromKey])) { diff --git a/apps/red-ui/src/app/utils/dialog-helper.ts b/apps/red-ui/src/app/utils/dialog-helper.ts index 653b86897..e8f3940c4 100644 --- a/apps/red-ui/src/app/utils/dialog-helper.ts +++ b/apps/red-ui/src/app/utils/dialog-helper.ts @@ -59,14 +59,22 @@ export class DialogHelper { config.backdropClass = 'dark-backdrop'; config.panelClass = 'gin-file-upload-dialog-panel'; config.scrollStrategy = overlay.scrollStrategies.block(); - config.positionStrategy = overlay.position().global().centerHorizontally().centerVertically(); + config.positionStrategy = overlay + .position() + .global() + .centerHorizontally() + .centerVertically(); return config; } static generateUploadStatusConfig(overlay: Overlay): OverlayConfig { const config = new OverlayConfig(); config.hasBackdrop = false; - config.positionStrategy = overlay.position().global().bottom(DialogHelper._MARGIN).right(DialogHelper._MARGIN); + config.positionStrategy = overlay + .position() + .global() + .bottom(DialogHelper._MARGIN) + .right(DialogHelper._MARGIN); return config; } } diff --git a/apps/red-ui/src/app/utils/file-download-utils.ts b/apps/red-ui/src/app/utils/file-download-utils.ts index 2e48879b5..697509c6a 100644 --- a/apps/red-ui/src/app/utils/file-download-utils.ts +++ b/apps/red-ui/src/app/utils/file-download-utils.ts @@ -5,7 +5,9 @@ export function download(event: HttpResponse, altName?: string) { const contentDisposition = event.headers.get('Content-Disposition'); let fileName; try { - fileName = contentDisposition ? contentDisposition.split('filename=')[1].replace(/"/g, '') : undefined; + fileName = contentDisposition + ? contentDisposition.split('filename=')[1].replace(/"/g, '') + : undefined; } catch (e) { console.log('[REDACTION] Failed to parse content-disposition: ', contentDisposition); } diff --git a/apps/red-ui/src/app/utils/file-drop-utils.ts b/apps/red-ui/src/app/utils/file-drop-utils.ts index 687c439bd..7ae9d1d0b 100644 --- a/apps/red-ui/src/app/utils/file-drop-utils.ts +++ b/apps/red-ui/src/app/utils/file-drop-utils.ts @@ -1,7 +1,11 @@ import { FileUploadModel } from '@upload-download/model/file-upload.model'; import { ProjectWrapper } from '@state/model/project.wrapper'; -export function handleFileDrop(event: DragEvent, project: ProjectWrapper, uploadFiles: (files: FileUploadModel[]) => void) { +export function handleFileDrop( + event: DragEvent, + project: ProjectWrapper, + uploadFiles: (files: FileUploadModel[]) => void +) { event.preventDefault(); event.stopPropagation(); const { dataTransfer } = event; diff --git a/apps/red-ui/src/app/utils/sync-scroll.ts b/apps/red-ui/src/app/utils/sync-scroll.ts index 4c888cd4c..0a1c34e43 100644 --- a/apps/red-ui/src/app/utils/sync-scroll.ts +++ b/apps/red-ui/src/app/utils/sync-scroll.ts @@ -35,7 +35,13 @@ export function syncScroll(elements: HTMLElement[]) { if ( updateX && Math.round( - otherEl['scrollLeft'] - (scrollX = otherEl.eX = Math.round(xRate * (otherEl['scrollWidth'] - otherEl['clientWidth']))) + otherEl['scrollLeft'] - + (scrollX = otherEl.eX = + Math.round( + xRate * + (otherEl['scrollWidth'] - + otherEl['clientWidth']) + )) ) ) { otherEl['scrollLeft'] = scrollX; @@ -44,7 +50,13 @@ export function syncScroll(elements: HTMLElement[]) { if ( updateY && Math.round( - otherEl['scrollTop'] - (scrollY = otherEl.eY = Math.round(yRate * (otherEl['scrollHeight'] - otherEl['clientHeight']))) + otherEl['scrollTop'] - + (scrollY = otherEl.eY = + Math.round( + yRate * + (otherEl['scrollHeight'] - + otherEl['clientHeight']) + )) ) ) { otherEl['scrollTop'] = scrollY; diff --git a/apps/red-ui/src/app/utils/uuid-helper.ts b/apps/red-ui/src/app/utils/uuid-helper.ts index 3cd05d407..0f925537b 100644 --- a/apps/red-ui/src/app/utils/uuid-helper.ts +++ b/apps/red-ui/src/app/utils/uuid-helper.ts @@ -5,7 +5,9 @@ for (let i = 0; i < 256; i++) { } export function isUUID(uuid: string) { - return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(uuid); + return /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test( + uuid + ); } export function UUID() { diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index 61103f817..d5d3e7847 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,14 +1,14 @@ { - "OAUTH_URL": "https://adi-dev.iqser.cloud/auth/realms/redaction", - "API_URL": "https://adi-dev.iqser.cloud/redaction-gateway-v1", - "OAUTH_CLIENT_ID": "redaction", - "BACKEND_APP_VERSION": "4.4.40", - "FRONTEND_APP_VERSION": "1.1", - "EULA_URL": "EULA_URL", - "LICENSE_CUSTOMER": "Development License", - "LICENSE_EMAIL": "todo-license@email.com", - "LICENSE_START": "01-01-2021", - "LICENSE_END": "31-12-2021", - "LICENSE_PAGE_COUNT": 1000000, - "MAX_FILE_SIZE_MB": 100 + "OAUTH_URL": "https://adi-dev.iqser.cloud/auth/realms/redaction", + "API_URL": "https://adi-dev.iqser.cloud/redaction-gateway-v1", + "OAUTH_CLIENT_ID": "redaction", + "BACKEND_APP_VERSION": "4.4.40", + "FRONTEND_APP_VERSION": "1.1", + "EULA_URL": "EULA_URL", + "LICENSE_CUSTOMER": "Development License", + "LICENSE_EMAIL": "todo-license@email.com", + "LICENSE_START": "01-01-2021", + "LICENSE_END": "31-12-2021", + "LICENSE_PAGE_COUNT": 1000000, + "MAX_FILE_SIZE_MB": 100 } diff --git a/apps/red-ui/src/assets/i18n/de.json b/apps/red-ui/src/assets/i18n/de.json index 8cbd7726a..5a3e94e6c 100644 --- a/apps/red-ui/src/assets/i18n/de.json +++ b/apps/red-ui/src/assets/i18n/de.json @@ -1,1249 +1,1249 @@ { - "auth-error": { - "heading": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie Ihren Administrator für den Zugriff!", - "heading-with-name-and-link": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie {{adminName}} für den Zugriff!", - "heading-with-name": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie {{adminName}} für den Zugriff!", - "heading-with-link": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie Ihren Administrator für den Zugriff!", - "logout": "Ausloggen" + "auth-error": { + "heading": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie Ihren Administrator für den Zugriff!", + "heading-with-name-and-link": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie {{adminName}} für den Zugriff!", + "heading-with-name": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie {{adminName}} für den Zugriff!", + "heading-with-link": "Ihr Benutzer verfügt nicht über die erforderlichen RED- * -Rollen, um auf diese Anwendung zuzugreifen. Bitte kontaktieren Sie Ihren Administrator für den Zugriff!", + "logout": "Ausloggen" + }, + "app-name": "DDA-R", + "dev-mode": "[DEV-MODUS]", + "upload-status": { + "error": { + "file-size": "Datei zu groß. Das Limit ist {{size}} MB.", + "generic": "Datei konnte nicht hochgeladen werden ..." }, - "app-name": "DDA-R", - "dev-mode": "[DEV-MODUS]", - "upload-status": { - "error": { - "file-size": "Datei zu groß. Das Limit ist {{size}} MB.", - "generic": "Datei konnte nicht hochgeladen werden ..." - }, - "dialog": { - "title": "Datei-Uploads ({{len}})", - "actions": { - "re-upload": "Wiederholen Sie den Upload", - "cancel": "Upload abbrechen" - } - } + "dialog": { + "title": "Datei-Uploads ({{len}})", + "actions": { + "re-upload": "Wiederholen Sie den Upload", + "cancel": "Upload abbrechen" + } + } + }, + "download-status": { + "queued": "Ihr Download wurde in die Warteschlange gestellt. Alle angeforderten Downloads finden Sie hier: Meine Downloads .", + "error": { + "generic": "Herunterladen fehlgeschlagen" }, - "download-status": { - "queued": "Ihr Download wurde in die Warteschlange gestellt. Alle angeforderten Downloads finden Sie hier: Meine Downloads .", - "error": { - "generic": "Herunterladen fehlgeschlagen" - }, - "dialog": { - "title": "Downloads ({{len}})", - "tooltip": "{{len}} Dateien", - "actions": { - "download": "jetzt downloaden", - "cancel": "Download abbrechen" - } - } + "dialog": { + "title": "Downloads ({{len}})", + "tooltip": "{{len}} Dateien", + "actions": { + "download": "jetzt downloaden", + "cancel": "Download abbrechen" + } + } + }, + "pdf-viewer": { + "text-popup": { + "actions": { + "search": "Suche nach Auswahl" + } }, - "pdf-viewer": { - "text-popup": { - "actions": { - "search": "Suche nach Auswahl" - } - }, - "search-in-progress": "Suche läuft ..." - }, - "common": { - "close": "Ansicht schließen", - "dialog": { - "close": "Dialog schließen" - }, - "confirmation-dialog": { - "title": "Aktion bestätigen", - "description": "Diese Aktion muss bestätigt werden. Möchten Sie fortfahren?", - "confirm": "Ja", - "deny": "Nein" - } - }, - "top-bar": { - "navigation-items": { - "projects": "Aktives Dossier", - "back": "Zurück", - "my-account": { - "children": { - "admin": "die Einstellungen", - "downloads": "Meine Downloads", - "my-profile": "Mein Profil", - "language": { - "label": "Sprache", - "en": "Englisch", - "de": "Deutsche" - }, - "logout": "Ausloggen" - } - } - } - }, - "filters": { - "filter-by": "Filter:", - "status": "Status", - "people": "Dossiermitglied (e)", - "assigned-people": "Beauftragter", - "due-date": "Geburtstermin", - "created-on": "Erstellt am", - "project": "Dossier", - "document": "Dokument", - "needs-work": "Arbeitsbelastung", - "rulesets": "Regelsätze" - }, - "report": { - "unavailable": "Der Redaktionsbericht ist erst verfügbar, wenn alle Dateien genehmigt wurden.", - "unavailable-single": "Der Redaktionsbericht ist erst verfügbar, wenn diese Datei genehmigt wurde.", - "action": { - "label": "Redaktionsbericht herunterladen", - "efsa": "Mit EFSA-Vorlage herunterladen", - "syngenta": "Mit Syngenta-Vorlage herunterladen" - } - }, - "project-listing": { - "search": "Dossiername ...", - "reanalyse": { - "action": "Analysieren Sie das gesamte Dossier" - }, - "assign": { - "action": "Eigentümer zuweisen" - }, - "download-files": { - "action": "Laden Sie redigierte Dateien herunter" - }, - "table-header": { - "title": "{{length}} aktive Dossiers", - "bulk-select": "Auswahl umschalten", - "recent": "Kürzlich" - }, - "table-col-names": { - "name": "Dokument", - "needs-work": "Arbeitsbelastung", - "owner": "Inhaber", - "status": "Status", - "ruleset": "Regelsatz" - }, - "stats": { - "analyzed-pages": "Seiten", - "total-people": "Benutzer insgesamt", - "charts": { - "projects": "Dossiers", - "total-documents": "Gesamtdokument (e)" - } - }, - "no-data": { - "title": "Sie haben derzeit keine Dossiers.", - "action": "Neues Dossier" - }, - "add-new": "Neues Dossier", - "add-edit-dialog": { - "header-new": "Dossier erstellen", - "header-edit": "Dossier bearbeiten", - "form": { - "name": { - "label": "Name des Dossiers", - "placeholder": "Name eingeben" - }, - "description": { - "label": "Beschreibung", - "placeholder": "Beschreibung eingeben" - }, - "due-date": "Geburtstermin", - "template": "Dossiervorlage" - }, - "errors": { - "project-already-exists": "Dossier mit diesem Namen existiert bereits!", - "generic": "Dossier konnte nicht gespeichert werden" - }, - "actions": { - "save": "speichern", - "save-and-add-members": "Team speichern und bearbeiten" - } - }, - "header": "Dossiers", - "edit": { - "action": "Dossier bearbeiten" - }, - "delete": { - "action": "Dossier löschen", - "delete-failed": "Fehler beim Löschen des Dossiers: {{projectName}}" - }, - "no-match": { - "title": "Keine Dossiers stimmen mit Ihren aktuellen Filtern überein." - } - }, - "project-details": { - "title": "Dossier Details", - "dialog": { - "title": "Dossier Details", - "info": { - "file-count": "Anzahl der Dateien: {{fileCount}}" - }, - "actions": { - "reanalyse-project": "Analysieren Sie das Dossier" - } - }, - "owner": "Inhaber", - "members": "Mitglieder", - "see-less": "Weniger sehen", - "assign-members": "Mitglieder zuweisen", - "expand": "Zeige Details", - "collapse": "Details ausblenden" - }, - "project-overview": { - "no-ocr": "Keine OCR", - "ocr-performed": "Für diese Datei wurde eine OCR durchgeführt.", - "no-data": { - "title": "Es liegen noch keine Dokumente vor.", - "action": "Dokument hochladen" - }, - "no-match": { - "title": "Keine Dokumente stimmen mit Ihren aktuellen Filtern überein." - }, - "search": "Dokumentname...", - "header-actions": { - "edit": "Bearbeiten", - "delete": "Löschen", - "assign": "Eigentümer zuweisen", - "upload-document": "Dokument hochladen", - "download-redacted-files": "Laden Sie redigierte Dateien herunter" - }, - "ocr-file": "OCR-Dokument", - "download-file": "Herunterladen", - "download-file-disabled": "Das Herunterladen ist nur für genehmigte Dateien zulässig", - "under-approval": "Zur Genehmigung", - "approve": "Genehmigen", - "approve-disabled": "Die Datei kann erst genehmigt werden, wenn sie mit den neuesten Wörterbüchern analysiert und alle Vorschläge verarbeitet wurden", - "under-review": "Wird überprüft", - "upload-files": "Ziehen", - "upload-files-btn": "Daten hochladen", - "new-rule": { - "label": "Veraltet", - "toast": { - "message-project": "Erneute Analyse erforderlich:", - "actions": { - "reanalyse-all": "Analysieren Sie alle", - "reanalyse-file": "Analysieren Sie diese Datei", - "later": "Später" - } - } - }, - "report": { - "action": "Redaktionsbericht herunterladen" - }, - "assign": "Prüfer zuweisen", - "assign-me": "Zuweisen zu mir", - "table-header": { - "title": "{{length}} Dokumente", - "bulk-select": "Auswahl umschalten" - }, - "table-col-names": { - "name": "Name", - "added-on": "Hinzugefügt", - "needs-work": "Arbeitsbelastung", - "assigned-to": "Zugewiesen an", - "pages": "Seiten", - "status": "Status" - }, - "upload-error": "Datei konnte nicht hochgeladen werden: {{name}}", - "delete-file-error": "Fehler beim Löschen der Datei: {{filename}}", - "delete-files-error": "Dateien konnten nicht gelöscht werden.", - "reanalyse": { - "action": "Datei analysieren" - }, - "delete": { - "action": "Datei löschen" - }, - "file-listing": { - "file-entry": { - "status": "Status: {{status}}", - "number-of-pages": "Anzahl der Seiten: {{numberOfPages}}", - "number-of-analyses": "Anzahl der Analysen: {{numberOfAnalyses}}", - "added": "Datum hinzugefügt: {{added}}", - "last-updated": "Letzte Aktualisierung: {{lastUpdated}}", - "file-pending": "Steht aus...", - "file-processing": "wird bearbeitet", - "file-error": "Nachbearbeitung erforderlich" - } - }, - "project-details": { - "charts": { - "documents-in-project": "Dokumente im Dossier" - }, - "stats": { - "documents": "{{count}} Dokumente", - "analysed-pages": "{{count}} Seiten", - "people": "{{count}} Benutzer", - "created-on": "Erstellt am {{date}}", - "due-date": "Geburtstermin}}" - }, - "description": "Beschreibung" - }, - "header": "Dossierübersicht", - "no-project": "Angefordertes Dossier: {{projectId}} existiert nicht! Zurück zur Dossierliste.", - "bulk": { - "delete": "Dokumente löschen", - "assign": "Prüfer zuweisen", - "reanalyse": "Dokumente analysieren", - "reanalyse-error-outdated": "Nicht alle ausgewählten Dokumente können analysiert werden, einige sind Ihnen möglicherweise nicht zugeordnet oder bereits analysiert." - }, - "reanalyse-project": { - "success": "Dateien, die erneut analysiert werden sollen.", - "error": "Dateien für die erneute Analyse konnten nicht geplant werden. Bitte versuche es erneut." - } - }, - "file-preview": { - "delta": "Delta", - "redacted": "Vorschau", - "standard": "Standard", - "standard-tooltip": "In der Standard-Workload-Ansicht werden alle Hinweise, Redaktionen und Empfehlungen angezeigt", - "redacted-tooltip": "Die Redaktionsvorschau zeigt nur Redaktionen an. Betrachten Sie dies als Vorschau für die endgültige redigierte Version. Diese Ansicht ist nur verfügbar, wenn für die Datei keine Änderungen ausstehen", - "delta-tooltip": "Delta View zeigt nur die Änderungen seit der letzten erneuten Analyse an. Diese Ansicht ist nur verfügbar, wenn mindestens eine Änderung vorliegt", - "no-data": { - "title": "Auf dieser Seite befinden sich keine Anmerkungen." - }, - "show-redacted-view": "Redigierte Vorschau anzeigen", - "cannot-show-redacted-view": "Redaktionen nicht synchron. Die redigierte Vorschau ist nur nach einer erneuten Analyse verfügbar", - "reanalyse-notification": "Dieses Dokument wurde nicht mit dem neuesten Regel- / Wörterbuchsatz verarbeitet. Analysieren Sie jetzt, um aktualisierte Anmerkungen zu erhalten.", - "reanalyse-file": "Datei-Reanalyse läuft", - "view-toggle": "Redigierte Ansicht", - "tabs": { - "quick-navigation": "Schnelle Navigation", - "document-info": { - "label": "Dokumentinfo", - "close": "Dokumentinfo schließen", - "edit": "Dokumentinformationen bearbeiten", - "details": { - "project": "in {{projectName}}", - "pages": "{{pages}} Seiten", - "revised-pages": "{{pages}} überarbeitete Seiten", - "created-on": "Erstellt am: {{date}}", - "due": "Geburtstermin}}" - } - }, - "annotations": { - "label": "Arbeitsbelastung", - "select": "Wählen", - "jump-to-previous": "Zum vorherigen springen", - "jump-to-next": "Zum nächsten springen" - }, - "is-excluded": "Die Redaktion ist für dieses Dokument deaktiviert." - }, - "toggle-analysis": { - "enable": "Zur Redaktion aktivieren", - "disable": "Deaktivieren Sie die Redaktion", - "only-managers": "Das Aktivieren / Deaktivieren ist nur für Manager zulässig" - }, - "reviewer": "Zugewiesen an", - "unassigned": "Nicht zugewiesen", - "assign-reviewer": "Prüfer zuweisen", - "cancel-assign-reviewer": "Stornieren", - "save-assign-reviewer": "speichern", - "assign-me": "Weisen Sie mir zu", - "last-reviewer": "Zuletzt überprüft von:", - "fullscreen": "Vollbild (F)", - "document-info": "Ihre Dokumenteninfo lebt hier. Dies schließt Metadaten ein, die für jedes Dokument erforderlich sind.", - "new-tab-ssr": "Öffnen Sie das Dokument im serverseitigen Rendering-Modus", - "html-debug": "Öffnen Sie das Dokument-HTML-Debug", - "download-original-file": "Originaldatei herunterladen", - "exit-fullscreen": "Beenden Sie den Vollbildmodus (F)", - "quick-nav": { - "jump-first": "Zur ersten Anmerkung springen", - "jump-last": "Zur letzten Anmerkung springen" - } - }, - "annotation-actions": { - "message": { - "manual-redaction": { - "undo": { - "success": "Rückgängig machen erfolgreich", - "error": "Fehler beim Rückgängigmachen: {{error}}" - }, - "suggest": { - "success": "Redaktionsvorschlag gespeichert", - "error": "Fehler beim Speichern des Redaktionsvorschlags: {{error}}" - }, - "add": { - "success": "Redaktion hinzugefügt!", - "error": "Fehler beim Speichern der Redaktion: {{error}}" - }, - "decline": { - "success": "Redaktionsvorschlag abgelehnt!", - "error": "Redaktion konnte nicht abgelehnt werden: {{error}}" - }, - "approve": { - "success": "Redaktionsvorschlag genehmigt!", - "error": "Fehler beim Genehmigen der Redaktion: {{error}}" - }, - "request-remove": { - "success": "Angefordert, Redaktion zu entfernen!", - "error": "Fehler beim Anfordern der Entfernung der Redaktion: {{error}}" - }, - "remove": { - "success": "Redaktion entfernt!", - "error": "Redaktion konnte nicht entfernt werden: {{error}}" - } - }, - "dictionary": { - "undo": { - "success": "Rückgängig machen erfolgreich", - "error": "Fehler beim Rückgängigmachen: {{error}}" - }, - "suggest": { - "success": "Vorschlag zur Wörterbuchänderung gespeichert!", - "error": "Vorschlag zum Ändern des Wörterbuchs konnte nicht gespeichert werden: {{error}}" - }, - "add": { - "success": "Eintrag zum Wörterbuch hinzugefügt. Änderungen werden nach einer erneuten Analyse sichtbar.", - "error": "Fehler beim Hinzufügen des Eintrags zum Wörterbuch: {{error}}" - }, - "decline": { - "success": "Wörterbuchvorschlag abgelehnt.", - "error": "Fehler beim Ablehnen des Wörterbuchvorschlags: {{error}}" - }, - "approve": { - "success": "Wörterbucheintrag genehmigt. Änderungen werden nach einer erneuten Analyse sichtbar.", - "error": "Wörterbucheintrag konnte nicht genehmigt werden: {{error}}" - }, - "request-remove": { - "success": "Angefordert, Wörterbucheintrag zu entfernen!", - "error": "Das Entfernen des Wörterbucheintrags konnte nicht angefordert werden: {{error}}" - }, - "remove": { - "success": "Wörterbucheintrag entfernt!", - "error": "Fehler beim Entfernen des Wörterbucheintrags: {{error}}" - } - } - }, - "force-redaction": { - "label": "Redaktion erzwingen" - }, - "accept-suggestion": { - "label": "Vorschlag annehmen", - "add-to-dict": "Genehmigen und zum Wörterbuch hinzufügen", - "remove-from-dict": "Genehmigen und aus dem Wörterbuch entfernen", - "only-here": "Nur hier genehmigen" - }, - "accept-recommendation": { - "label": "Empfehlung annehmen" - }, - "suggest-remove-annotation": "Entfernen oder vorschlagen, diesen Eintrag zu entfernen", - "suggest-remove-annotations": "Entfernen oder Vorschlagen, um ausgewählte Einträge zu entfernen", - "reject-suggestion": "Vorschlag ablehnen", - "remove-annotation": { - "suggest-remove-from-dict": "Schlagen Sie vor, aus dem Wörterbuch zu entfernen", - "suggest-only-here": "Schlagen Sie vor, nur hier zu entfernen", - "remove-from-dict": "Aus dem Wörterbuch entfernen", - "only-here": "Nur hier entfernen", - "false-positive": "Falsch positiv" - }, - "remove": "Entfernen", - "undo": "Rückgängig machen", - "reject": "Ablehnen", - "hide": "Ausblenden", - "show": "Show" - }, - "initials-avatar": { - "unassigned": "Nicht zugewiesen", - "you": "Sie" - }, - "assign-file-owner": { - "dialog": { - "single-user": "Gutachter", - "title": "File Reviewer verwalten", - "save": "speichern", - "cancel": "Stornieren" - } - }, - "assign-project-owner": { - "dialog": { - "single-user": "Inhaber", - "multi-user": "Team überprüfen", - "title": "Dossier-Team verwalten", - "members": "Mitglieder", - "save": "Änderungen speichern", - "cancel": "Stornieren", - "search": "Suche...", - "no-members": "Noch keine Mitglieder. Wählen Sie aus der Liste unten." - } - }, - "project-member-guard": { - "access-denied": "Sie dürfen nicht auf diese Seite zugreifen." - }, - "comments": { - "comment": "{{count}} Kommentar", - "comments": "{{count}} Kommentare", - "add-comment": "Einen Kommentar hinzufügen", - "hide-comments": "Ausblenden", - "cancel": "Stornieren" - }, - "UNPROCESSED": "Unverarbeitet", - "REPROCESS": "wird bearbeitet", - "FULLREPROCESS": "wird bearbeitet", - "PROCESSING": "wird bearbeitet", - "OCR_PROCESSING": "OCR-Verarbeitung", - "ERROR": "Nachbearbeitung erforderlich", - "UNASSIGNED": "Nicht zugewiesen", - "UNDER_REVIEW": "Wird überprüft", - "UNDER_APPROVAL": "Unter Genehmigung", - "APPROVED": "Genehmigt", - "EXCLUDED": "Ausgeschlossen", - "by": "durch", - "efsa": "EFSA-Genehmigung", - "finished": "Fertig", - "submitted": "Eingereicht", - "active": "Aktiv", - "archived": "Archiviert", - "hint": "Hinweis", - "skipped": "Übersprungen", - "redaction": "Redaktion", - "comment": "Kommentar", - "pending-analysis": "Bis zur erneuten Analyse", - "suggestion": "Redaktionsvorschlag", - "dictionary": "Wörterbuch", - "type": "Art", - "content": "Grund", - "page": "Seite", - "annotation": "Anmerkung", - "annotations": "Anmerkungen", - "filter": { - "hint": "Nur Hinweise", - "redaction": "Redigiert", - "suggestion": "Vorgeschlagene Redaktion", - "analysis": "Analyse erforderlich", - "none": "Keine Anmerkungen", - "updated": "Aktualisiert", - "image": "Bilder" - }, - "filter-menu": { - "label": "Filter", - "filter-types": "Filtertypen", - "filter-options": "Filteroptionen", - "with-comments": "Nur Anmerkungen mit Kommentaren anzeigen" - }, - "sorting": { - "recent": "Kürzlich", - "oldest": "Älteste", - "alphabetically": "Alphabetisch", - "number-of-pages": "Seitenzahl", - "number-of-analyses": "Anzahl der Analysen", - "custom": "Benutzerdefiniert" - }, - "readonly-pill": "Schreibgeschützt", - "group": { - "redactions": "Redaktionswörterbücher", - "hints": "Tipp Wörterbücher" - }, - "annotation-type": { - "recommendation": "Empfehlung", - "remove-only-here": "Ausstehende Entfernung (nur hier)", - "add-dictionary": "Ausstehend zum Wörterbuch hinzufügen", - "remove-dictionary": "Ausstehend aus dem Wörterbuch entfernen", - "suggestion-add-dictionary": "Vorgeschlagenes Wörterbuch hinzufügen", - "suggestion-force-redaction": "Redaktion der Vorschlagskraft", - "suggestion-remove-dictionary": "Vorgeschlagene Wörterbuchentfernung", - "suggestion-add": "Vorgeschlagene Redaktion", - "suggestion-remove": "Vorgeschlagene Redaktionsentfernung", - "skipped": "Übersprungen", - "pending-analysis": "Bis zur erneuten Analyse", - "hint": "Hinweis", - "redaction": "Redaktion", - "manual-redaction": "Manuelle Redaktion", - "declined-suggestion": "Abgelehnter Vorschlag" - }, - "manual-annotation": { - "dialog": { - "header": { - "dictionary": "Zum Wörterbuch hinzufügen", - "redaction": "Redaktion", - "force": "Redaktion erzwingen", - "request-dictionary": "Anfrage zum Wörterbuch hinzufügen", - "request-redaction": "Redaktion anfordern", - "false-positive": "Falsch positiv setzen", - "request-false-positive": "Falsch positiv anfordern" - }, - "add-redaction": { - "success": "Redaktionsvorschlag hinzugefügt!", - "failed": "Fehler beim Hinzufügen der Redaktion: {{message}}" - }, - "actions": { - "save": "speichern" - }, - "content": { - "text": "Ausgewählter Text:", - "rectangle": "Benutzerdefiniertes Rechteck", - "dictionary": "Wörterbuch", - "reason": "Grund", - "reason-placeholder": "Wähle einen Grund ...", - "legalBasis": "Rechtliche Grundlage", - "comment": "Kommentar" - } - }, - "approve-request": { - "success": "Anfrage genehmigt.", - "error": "Anfrage konnte nicht genehmigt werden." - }, - "undo": { - "success": "Aktion rückgängig gemacht.", - "error": "Aktion konnte nicht rückgängig gemacht werden." - }, - "redaction-request": { - "success": "Redaktion angefordert.", - "error": "Redaktion konnte nicht angefordert werden." - }, - "remove-redaction-request": { - "success": "Redaktion entfernt.", - "error": "Redaktion konnte nicht entfernt werden." - }, - "redaction-add": { - "success": "Redaktion hinzugefügt.", - "error": "Redaktion konnte nicht hinzugefügt werden." - } - }, - "remove-annotations-dialog": { - "remove-from-dictionary": { - "title": "Aus dem Wörterbuch entfernen", - "question": "Folgende Einträge werden aus ihren jeweiligen Wörterbüchern entfernt:" - }, - "remove-only-here": { - "title": "Redaktion entfernen", - "question": "Folgende Redaktionen werden nur hier entfernt:" - }, - "dictionary": "Wörterbuch", - "value": "Wert", - "confirm": "Ja, fortfahren und entfernen!", - "deny": "Stornieren" + "search-in-progress": "Suche läuft ..." + }, + "common": { + "close": "Ansicht schließen", + "dialog": { + "close": "Dialog schließen" }, "confirmation-dialog": { - "assign-file-to-me": { - "title": "Prüfer neu zuweisen", - "question": "Dieses Dokument wird derzeit von einer anderen Person geprüft. Möchten Sie der Prüfer werden und sich diesem Dokument zuordnen?" - }, - "delete-file": { - "title": "Dokument löschen", - "question": "Möchten Sie fortfahren?" - }, - "delete-project": { - "title": "Dossier löschen", - "question": "Möchten Sie fortfahren?" + "title": "Aktion bestätigen", + "description": "Diese Aktion muss bestätigt werden. Möchten Sie fortfahren?", + "confirm": "Ja", + "deny": "Nein" + } + }, + "top-bar": { + "navigation-items": { + "projects": "Aktives Dossier", + "back": "Zurück", + "my-account": { + "children": { + "admin": "die Einstellungen", + "downloads": "Meine Downloads", + "my-profile": "Mein Profil", + "language": { + "label": "Sprache", + "en": "Englisch", + "de": "Deutsche" + }, + "logout": "Ausloggen" } + } + } + }, + "filters": { + "filter-by": "Filter:", + "status": "Status", + "people": "Dossiermitglied (e)", + "assigned-people": "Beauftragter", + "due-date": "Geburtstermin", + "created-on": "Erstellt am", + "project": "Dossier", + "document": "Dokument", + "needs-work": "Arbeitsbelastung", + "rulesets": "Regelsätze" + }, + "report": { + "unavailable": "Der Redaktionsbericht ist erst verfügbar, wenn alle Dateien genehmigt wurden.", + "unavailable-single": "Der Redaktionsbericht ist erst verfügbar, wenn diese Datei genehmigt wurde.", + "action": { + "label": "Redaktionsbericht herunterladen", + "efsa": "Mit EFSA-Vorlage herunterladen", + "syngenta": "Mit Syngenta-Vorlage herunterladen" + } + }, + "project-listing": { + "search": "Dossiername ...", + "reanalyse": { + "action": "Analysieren Sie das gesamte Dossier" }, - "add-edit-file-attribute": { - "title": { - "edit": "Bearbeiten Sie das {{name}} Dateiattribut", - "new": "Neues Dateiattribut hinzufügen" - }, - "form": { - "name": "Attributname", - "name-placeholder": "Name eingeben", - "column-header": "CSV-Spaltenüberschrift", - "column-header-placeholder": "Geben Sie den CSV-Spaltenkopf ein", - "read-only": "Schreibgeschützt machen", - "type": "Art", - "primary": "Als primär festlegen" - }, - "save": "Attribut speichern" + "assign": { + "action": "Eigentümer zuweisen" }, - "file-attribute-types": { - "TEXT": "Freier Text", - "NUMBER": "Nummer", - "DATE": "Datum" + "download-files": { + "action": "Laden Sie redigierte Dateien herunter" }, - "add-edit-dictionary": { - "title": { - "edit": "Bearbeiten Sie das {{name}} Wörterbuch", - "new": "Wörterbuch erstellen" - }, - "form": { - "name": "Wörterbuchname", - "name-placeholder": "Name eingeben", - "name-hint": "Kann nach dem Speichern nicht bearbeitet werden.", - "description": "Beschreibung", - "description-placeholder": "Beschreibung eingeben", - "rank": "Rang", - "rank-placeholder": "1000", - "color": "Hex Farbe", - "color-placeholder": "#", - "redaction": "Redaktion", - "hint": "Hinweis", - "case-sensitive": "Groß- und Kleinschreibung beachten", - "add-to-dictionary-action": "Verfügbar zum Hinzufügen zum Wörterbuch" - }, - "error": { - "dictionary-already-exists": "Wörterbuch mit diesem Namen existiert bereits!", - "invalid-color-or-rank": "Ungültige Farbe oder Rang! Der Rang wird bereits von einem anderen Wörterbuch verwendet oder die Farbe ist keine gültige HexColor!", - "generic": "Wörterbuch konnte nicht gespeichert werden!" - }, - "save": "Wörterbuch speichern" + "table-header": { + "title": "{{length}} aktive Dossiers", + "bulk-select": "Auswahl umschalten", + "recent": "Kürzlich" }, - "add-edit-project-template": { - "title": { - "edit": "Bearbeiten Sie die {{name}} Dossiervorlage", - "new": "Erstellen Sie eine Dossiervorlage" - }, - "form": { - "name": "Name der Dossiervorlage", - "name-placeholder": "Name eingeben", - "description": "Beschreibung", - "description-placeholder": "Beschreibung eingeben", - "valid-from": "Gültig ab", - "valid-to": "Gültig bis" - }, - "save": "Speichern Sie die Dossiervorlage" + "table-col-names": { + "name": "Dokument", + "needs-work": "Arbeitsbelastung", + "owner": "Inhaber", + "status": "Status", + "ruleset": "Regelsatz" }, - "dictionary-overview": { - "action": { - "delete": "Wörterbuch löschen", - "edit": "Wörterbuch bearbeiten", - "download": "Wörterbuch herunterladen", - "upload": "Wörterbuch hochladen" - }, - "error": { - "entries-too-short": "Einige Einträge des Wörterbuchs liegen unter der Mindestlänge von 2. Diese sind rot hervorgehoben!", - "generic": "Etwas ist schief gelaufen ... Wörterbuch-Update fehlgeschlagen!" - }, - "success": { - "generic": "Wörterbuch aktualisiert!" - }, - "search": "Suche...", - "save-changes": "Änderungen speichern", - "revert-changes": "Zurückkehren", - "dictionary-details": { - "description": "Beschreibung" - }, - "compare": { - "compare": "Vergleichen Sie", - "select-ruleset": "Wählen Sie Dossiervorlage", - "select-dictionary": "Wählen Sie Wörterbuch" - }, - "select-dictionary": "Wählen Sie oben ein Wörterbuch aus, um es mit dem aktuellen zu vergleichen." + "stats": { + "analyzed-pages": "Seiten", + "total-people": "Benutzer insgesamt", + "charts": { + "projects": "Dossiers", + "total-documents": "Gesamtdokument (e)" + } }, - "dictionary-listing": { - "action": { - "delete": "Wörterbuch löschen", - "edit": "Wörterbuch bearbeiten" - }, - "case-sensitive": "Groß- und Kleinschreibung beachten", - "add-new": "Neues Wörterbuch", - "stats": { - "charts": { - "types": "Typen", - "entries": "Einträge" - } - }, - "table-header": { - "title": "{{length}} Wörterbücher" - }, - "table-col-names": { - "type": "Art", - "order-of-importance": "Reihenfolge der Wichtigkeit", - "hint-redaction": "Hinweis / Redaktion" - }, - "search": "Suche...", - "no-data": { - "title": "Es gibt noch keine Wörterbücher.", - "action": "Neues Wörterbuch" - }, - "no-match": { - "title": "Keine Wörterbücher stimmen mit Ihren aktuellen Filtern überein." - } + "no-data": { + "title": "Sie haben derzeit keine Dossiers.", + "action": "Neues Dossier" }, - "digital-signature": "Digitale Unterschrift", - "project-templates": "Dossiervorlagen", - "settings": "die Einstellungen", - "project-templates-listing": { - "table-header": { - "title": "{{length}} Dossiervorlagen" + "add-new": "Neues Dossier", + "add-edit-dialog": { + "header-new": "Dossier erstellen", + "header-edit": "Dossier bearbeiten", + "form": { + "name": { + "label": "Name des Dossiers", + "placeholder": "Name eingeben" }, - "entries": "{{length}} Einträge", - "dictionaries": "{{length}} Wörterbücher", - "action": { - "delete": "Vorlage löschen", - "edit": "Vorlage bearbeiten" + "description": { + "label": "Beschreibung", + "placeholder": "Beschreibung eingeben" }, - "add-new": "Neue Dossiervorlage", - "search": "Suche...", - "table-col-names": { - "name": "Name", - "created-by": "Erstellt von", - "created-on": "Erstellt am", - "modified-on": "Geändert am" - }, - "no-data": { - "title": "Es gibt noch keine Dossiervorlagen." - }, - "no-match": { - "title": "Keine Dossiervorlagen stimmen mit Ihren aktuellen Filtern überein." - } - }, - "file-attributes-listing": { - "search": "Suche nach Attributnamen ...", - "add-new": "Neues Attribut", - "table-header": { - "title": "{{length}} Dateiattribute" - }, - "bulk-actions": { - "delete": "Ausgewählte Attribute löschen" - }, - "table-col-names": { - "name": "Name", - "type": "Eingabetyp", - "read-only": "Schreibgeschützt", - "csv-column": "CSV-Spalte", - "primary": "Primär", - "primary-info-tooltip": "Der Wert des als primär eingestellten Attributs wird unter dem Dateinamen in der Dokumentenliste angezeigt." - }, - "no-data": { - "title": "Es sind noch keine Dateiattribute vorhanden." - }, - "no-match": { - "title": "Keine Dateiattribute stimmen mit Ihren aktuellen Filtern überein." - }, - "read-only": "Schreibgeschützt", - "action": { - "edit": "Attribut bearbeiten", - "delete": "Attribut löschen" - }, - "upload-csv": "Konfiguration der Dateiattribute hochladen" - }, - "confirm-delete-file-attribute": { - "title": { - "single": "Löschen Sie {{name}}", - "bulk": "Dateiattribute löschen" - }, - "warning": "Achtung: Dies kann nicht rückgängig gemacht werden!", - "delete": { - "single": "Attribut löschen", - "bulk": "Attribute löschen" - }, - "cancel": { - "single": "Attribut behalten", - "bulk": "Attribute behalten" - }, - "impacted-documents": { - "single": "Alle Dokumente, für die es verwendet wird, sind betroffen", - "bulk": "Alle Dokumente, für die sie verwendet werden, sind betroffen" - }, - "lost-details": "Alle eingegebenen Details in den Dokumenten gehen verloren", - "toast-error": "Bitte bestätigen Sie, dass Sie die Auswirkungen Ihrer Handlung verstehen!" - }, - "confirm-delete-users": { - "title": { - "single": "Benutzer aus Arbeitsbereich löschen", - "bulk": "Benutzer aus dem Arbeitsbereich löschen" - }, - "warning": "Achtung: Dies kann nicht rückgängig gemacht werden!", - "impacted-projects": "{{projectsCount}} Dossiers sind betroffen", - "impacted-documents": { - "single": "Alle Dokumente, deren Überprüfung durch den Benutzer aussteht, sind betroffen", - "bulk": "Alle Dokumente, deren Überprüfung durch die Benutzer aussteht, sind betroffen" - }, - "delete": { - "single": "Benutzer löschen", - "bulk": "Benutzer löschen" - }, - "cancel": { - "single": "Benutzer behalten", - "bulk": "Benutzer behalten" - }, - "toast-error": "Bitte bestätigen Sie, dass Sie die Auswirkungen Ihrer Handlung verstehen!" - }, - "document-info": { - "title": "Dateiattribute einführen", - "save": "Dokumentinformationen speichern", - "save-approval": "Speichern und zur Genehmigung senden" - }, - "user-profile": { - "title": "Mein Profil", - "form": { - "email": "Email", - "first-name": "Vorname", - "last-name": "Nachname" - }, - "actions": { - "save": "Profil speichern" - } - }, - "user-listing": { - "table-header": { - "title": "{{length}} Benutzer" - }, - "table-col-names": { - "name": "Name", - "email": "Email", - "active": "Aktiv", - "roles": "Rollen" - }, - "action": { - "edit": "Benutzer bearbeiten", - "delete": "Benutzer löschen" - }, - "bulk": { - "delete": "Benutzer löschen", - "delete-disabled": "Sie können Ihr eigenes Konto nicht löschen." - }, - "search": "Suche...", - "add-new": "Neuer Benutzer", - "no-match": { - "title": "Keine Benutzer stimmen mit Ihren aktuellen Filtern überein." - } - }, - "add-edit-user": { - "title": { - "new": "Neuen Benutzer hinzufügen", - "edit": "Benutzer bearbeiten" - }, - "form": { - "first-name": "Vorname", - "last-name": "Nachname", - "email": "Email", - "role": "Rolle" - }, - "actions": { - "save": "Benutzer speichern", - "save-changes": "Änderungen speichern", - "delete": "Benutzer löschen", - "cancel": "Stornieren" - } - }, - "user-stats": { - "title": "Benutzer", - "chart": { - "users": "Benutzer im Arbeitsbereich" - }, - "expand": "Zeige Details", - "collapse": "Details ausblenden" - }, - "rules-screen": { - "error": { - "generic": "Etwas ist schief gelaufen ... Regelaktualisierung fehlgeschlagen!" - }, - "success": { - "generic": "Regeln aktualisiert!" - }, - "action": { - "download": "Regeln herunterladen", - "upload": "Regeln hochladen" - }, - "save-changes": "Änderungen speichern", - "revert-changes": "Zurückkehren" - }, - "watermark-screen": { - "form": { - "text-placeholder": "Text eingeben", - "opacity": "Opazität", - "color": "Farbe", - "font-size": "Schriftgröße", - "font-type": "Schriftart", - "orientation": "Orientierung" - }, - "action": { - "save": "Änderungen speichern", - "revert": "Zurückkehren", - "change-success": "Wasserzeichen aktualisiert!", - "delete-success": "Wasserzeichen gelöscht.", - "error": "Wasserzeichen konnte nicht aktualisiert werden" - }, - "title": "Wasserzeichen" - }, - "dictionaries": "Wörterbücher", - "user-management": "Benutzerverwaltung", - "license-information": "Lizenzinformationen", - "notifications": { - "today": "Heute", - "yesterday": "Gestern", - "tomorrow": "Morgen", - "mark-read": "als gelesen markieren", - "mark-unread": "als ungelesen markieren" - }, - "rule-editor": "Regeleditor", - "watermark": "Wasserzeichen", - "file-attributes": "Dateiattribute", - "pending-changes-guard": "WARNUNG: Sie haben nicht gespeicherte Änderungen. Drücken Sie Abbrechen, um zurück zu gehen und diese Änderungen zu speichern, oder OK, um diese Änderungen zu verlieren.", - "reset-filters": "Filter zurücksetzen", - "overwrite-files-dialog": { - "title": "Dokument existiert bereits!", - "question": "{{filename}} existiert bereits. Wählen Sie, wie Sie fortfahren möchten:", - "options": { - "overwrite": "Ersetzen Sie das vorhandene Dokument", - "skip": "Vorhandenes Dokument behalten", - "cancel": "Alle Uploads abbrechen", - "remember": "Erinnere dich an die Wahl und frag mich nicht noch einmal" - } - }, - "license-info-screen": { - "backend-version": "Backend-Anwendungsversion", - "frontend-version": "Frontend-Anwendungsversion", - "custom-app-title": "Titel der benutzerdefinierten Anwendung", - "copyright-claim-title": "Urheberrechtsanspruch", - "copyright-claim-text": "Copyright © 2020 - {{currentYear}} knecon AG (unterstützt von IQSER)", - "end-user-license-title": "Endbenutzer-Lizenzvereinbarung", - "end-user-license-text": "Die Verwendung dieses Produkts unterliegt den Bestimmungen der Redaction End User Agreement, sofern nicht anders angegeben.", - "3rd-party-title": "Verweis auf Lizenzen von Drittanbietern", - "licensing-details": "Lizenzdetails", - "licensed-to": "Lizenziert an", - "licensing-period": "Lizenzzeitraum", - "analyzed-pages": "Analysierte Seiten", - "usage-details": "Verwendungsdetails", - "total-analyzed": "Insgesamt analysierte Seiten seit {{date}}", - "licensed-page-count": "Anzahl der lizenzierten Seiten", - "current-analyzed": "Analysierte Seiten im aktuellen Lizenzierungszeitraum", - "unlicensed-analyzed": "Nicht lizenzierte analysierte Seiten", - "email-report": "E-Mail-Bericht", - "email": { - "title": "Lizenzbericht {{licenseCustomer}}", - "body": { - "analyzed": "Insgesamt analysierte Seiten im aktuellen Lizenzzeitraum: {{pages}}.", - "licensed": "Lizenzierte Seiten: {{pages}}." - } - }, - "chart": { - "licensed-total": "Lizenzierte Summe", - "cumulative": "Kumulative Seiten", - "pages-per-month": "Seiten pro Monat", - "total-pages": "Alle Seiten", - "legend": "Legende" - } - }, - "audit": "Prüfung", - "audit-screen": { - "table-header": { - "title": "{{length}} Protokolle" - }, - "table-col-names": { - "message": "Botschaft", - "user": "Benutzer", - "date": "Datum", - "category": "Kategorie" - }, - "all-categories": "Alle Kategorien", - "all-users": "Alle Nutzer", - "to": "zu", - "no-data": { - "title": "Keine verfügbaren Protokolle." - } - }, - "pagination": { - "previous": "Zurück", - "next": "Nächster" - }, - "configurations": "Konfigurationen", - "smtp-config-screen": { - "title": "Konfigurieren Sie das SMTP-Konto", - "subtitle": "Mit SMTP (Simple Mail Transfer Protocol) können Sie Ihre E-Mails über die angegebenen Servereinstellungen senden.", - "actions": { - "save": "Konfigurationen speichern", - "test-connection": "Testverbindung" - }, - "form": { - "host": "Gastgeber", - "host-placeholder": "SMTP-Host", - "port": "Hafen", - "from": "Von", - "from-placeholder": "Absender-E-Mail-Adresse", - "from-display-name": "Name für Absender", - "from-display-name-placeholder": "Anzeigename für die Absender-E-Mail-Adresse", - "from-display-name-hint": "Infotext zum Namen des Absenders.", - "reply-to": "Antwort an", - "reply-to-placeholder": "Antwort an E-Mail-Adresse", - "reply-to-display-name": "Name für die Antwort an", - "reply-to-display-name-placeholder": "Anzeigename für die Antwort auf die E-Mail-Adresse", - "envelope-from": "Umschlag von", - "envelope-from-placeholder": "E-Mail-Adresse des Absenderumschlags", - "envelope-from-hint": "Infotext zum Umschlag aus dem Feld.", - "ssl": "Aktivieren Sie SSL", - "starttls": "Aktivieren Sie StartTLS", - "auth": "Aktivieren Sie die Authentifizierung", - "change-credentials": "Anmeldeinformationen ändern" - }, - "test": { - "success": "Test-E-Mail wurde erfolgreich gesendet!", - "error": "Test-E-Mail konnte nicht gesendet werden! Bitte überarbeiten Sie die E-Mail-Adresse." - } - }, - "smtp-auth-config": { - "title": "Aktivieren Sie die Authentifizierung", - "form": { - "username": "Nutzername", - "username-placeholder": "Login Benutzername", - "password": "Passwort" - }, - "actions": { - "save": "Anmeldeinformationen speichern", - "cancel": "Stornieren" - } - }, - "default-colors": "Standardfarben", - "default-colors-screen": { - "table-header": { - "title": "{{length}} Standardfarben" - }, - "table-col-names": { - "key": "Art", - "color": "Farbe" - }, - "types": { - "defaultColor": "Standardfarbe", - "requestAdd": "Anfrage hinzufügen", - "requestRemove": "Anfrage entfernen", - "notRedacted": "Übersprungen", - "analysisColor": "Analyse", - "dictionaryRequestColor": "Wörterbuchanforderung", - "manualRedactionColor": "Manuelle Redaktion", - "previewColor": "Vorschau", - "updatedColor": "Aktualisiert" - }, - "action": { - "edit": "Farbe bearbeiten" - } - }, - "edit-color-dialog": { - "success": "Die Farbe für {{color}} wurde erfolgreich aktualisiert.", - "error": "Fehler beim Aktualisieren der Farben.", + "due-date": "Geburtstermin", + "template": "Dossiervorlage" + }, + "errors": { + "project-already-exists": "Dossier mit diesem Namen existiert bereits!", + "generic": "Dossier konnte nicht gespeichert werden" + }, + "actions": { "save": "speichern", - "form": { - "color": "Farbe", - "color-placeholder": "Farbe" - } + "save-and-add-members": "Team speichern und bearbeiten" + } }, - "downloads-list": { - "table-header": { - "title": "{{length}} Downloads" - }, - "no-data": { - "title": "Keine aktiven Downloads." - }, - "table-col-names": { - "name": "Name", - "size": "Größe", - "type": "Art", - "date": "Datum", - "status": "Status" - }, + "header": "Dossiers", + "edit": { + "action": "Dossier bearbeiten" + }, + "delete": { + "action": "Dossier löschen", + "delete-failed": "Fehler beim Löschen des Dossiers: {{projectName}}" + }, + "no-match": { + "title": "Keine Dossiers stimmen mit Ihren aktuellen Filtern überein." + } + }, + "project-details": { + "title": "Dossier Details", + "dialog": { + "title": "Dossier Details", + "info": { + "file-count": "Anzahl der Dateien: {{fileCount}}" + }, + "actions": { + "reanalyse-project": "Analysieren Sie das Dossier" + } + }, + "owner": "Inhaber", + "members": "Mitglieder", + "see-less": "Weniger sehen", + "assign-members": "Mitglieder zuweisen", + "expand": "Zeige Details", + "collapse": "Details ausblenden" + }, + "project-overview": { + "no-ocr": "Keine OCR", + "ocr-performed": "Für diese Datei wurde eine OCR durchgeführt.", + "no-data": { + "title": "Es liegen noch keine Dokumente vor.", + "action": "Dokument hochladen" + }, + "no-match": { + "title": "Keine Dokumente stimmen mit Ihren aktuellen Filtern überein." + }, + "search": "Dokumentname...", + "header-actions": { + "edit": "Bearbeiten", + "delete": "Löschen", + "assign": "Eigentümer zuweisen", + "upload-document": "Dokument hochladen", + "download-redacted-files": "Laden Sie redigierte Dateien herunter" + }, + "ocr-file": "OCR-Dokument", + "download-file": "Herunterladen", + "download-file-disabled": "Das Herunterladen ist nur für genehmigte Dateien zulässig", + "under-approval": "Zur Genehmigung", + "approve": "Genehmigen", + "approve-disabled": "Die Datei kann erst genehmigt werden, wenn sie mit den neuesten Wörterbüchern analysiert und alle Vorschläge verarbeitet wurden", + "under-review": "Wird überprüft", + "upload-files": "Ziehen", + "upload-files-btn": "Daten hochladen", + "new-rule": { + "label": "Veraltet", + "toast": { + "message-project": "Erneute Analyse erforderlich:", "actions": { - "delete": "Löschen", - "download": "Herunterladen" + "reanalyse-all": "Analysieren Sie alle", + "reanalyse-file": "Analysieren Sie diese Datei", + "later": "Später" } + } }, - "digital-signature-screen": { - "title": "Digitale Unterschrift", - "no-data": { - "title": "Es ist kein Zertifikat für digitale Signatur konfiguriert. Laden Sie zum Signieren redigierter Dokumente ein PCKS.12-Zertifikat hoch.", - "action": "Zertifikat hochladen" - }, - "reason": { - "label": "Grund", - "placeholder": "Grund" - }, - "certificate-name": { - "label": "Zertifikatname", - "placeholder": "Zertifikatname" - }, - "contact-info": { - "label": "Kontakt Informationen", - "placeholder": "Kontakt Informationen" - }, - "location": { - "label": "Ort", - "placeholder": "Ort" - }, - "password": { - "label": "Zertifikat Passwort / Schlüssel", - "placeholder": "Passwort" - }, - "action": { - "save": "Digitale Signatur speichern", - "delete": "Digitale Signatur löschen", - "reset": "Zurücksetzen", - "save-success": "Digitale Signatur erfolgreich gespeichert", - "save-error": "Fehler beim Speichern der digitalen Signatur", - "certificate-not-valid-error": "Das hochgeladene Zertifikat gilt nicht zum Signieren von PDFs. Das PCKS.12-Format ist erforderlich.", - "delete-success": "Digitale Signatur entfernt. Redigierte Dateien werden nicht mehr signiert!", - "delete-error": "Fehler beim Entfernen der digitalen Signatur. Versuchen Sie es erneut." + "report": { + "action": "Redaktionsbericht herunterladen" + }, + "assign": "Prüfer zuweisen", + "assign-me": "Zuweisen zu mir", + "table-header": { + "title": "{{length}} Dokumente", + "bulk-select": "Auswahl umschalten" + }, + "table-col-names": { + "name": "Name", + "added-on": "Hinzugefügt", + "needs-work": "Arbeitsbelastung", + "assigned-to": "Zugewiesen an", + "pages": "Seiten", + "status": "Status" + }, + "upload-error": "Datei konnte nicht hochgeladen werden: {{name}}", + "delete-file-error": "Fehler beim Löschen der Datei: {{filename}}", + "delete-files-error": "Dateien konnten nicht gelöscht werden.", + "reanalyse": { + "action": "Datei analysieren" + }, + "delete": { + "action": "Datei löschen" + }, + "file-listing": { + "file-entry": { + "status": "Status: {{status}}", + "number-of-pages": "Anzahl der Seiten: {{numberOfPages}}", + "number-of-analyses": "Anzahl der Analysen: {{numberOfAnalyses}}", + "added": "Datum hinzugefügt: {{added}}", + "last-updated": "Letzte Aktualisierung: {{lastUpdated}}", + "file-pending": "Steht aus...", + "file-processing": "wird bearbeitet", + "file-error": "Nachbearbeitung erforderlich" + } + }, + "project-details": { + "charts": { + "documents-in-project": "Dokumente im Dossier" + }, + "stats": { + "documents": "{{count}} Dokumente", + "analysed-pages": "{{count}} Seiten", + "people": "{{count}} Benutzer", + "created-on": "Erstellt am {{date}}", + "due-date": "Geburtstermin}}" + }, + "description": "Beschreibung" + }, + "header": "Dossierübersicht", + "no-project": "Angefordertes Dossier: {{projectId}} existiert nicht! Zurück zur Dossierliste.", + "bulk": { + "delete": "Dokumente löschen", + "assign": "Prüfer zuweisen", + "reanalyse": "Dokumente analysieren", + "reanalyse-error-outdated": "Nicht alle ausgewählten Dokumente können analysiert werden, einige sind Ihnen möglicherweise nicht zugeordnet oder bereits analysiert." + }, + "reanalyse-project": { + "success": "Dateien, die erneut analysiert werden sollen.", + "error": "Dateien für die erneute Analyse konnten nicht geplant werden. Bitte versuche es erneut." + } + }, + "file-preview": { + "delta": "Delta", + "redacted": "Vorschau", + "standard": "Standard", + "standard-tooltip": "In der Standard-Workload-Ansicht werden alle Hinweise, Redaktionen und Empfehlungen angezeigt", + "redacted-tooltip": "Die Redaktionsvorschau zeigt nur Redaktionen an. Betrachten Sie dies als Vorschau für die endgültige redigierte Version. Diese Ansicht ist nur verfügbar, wenn für die Datei keine Änderungen ausstehen", + "delta-tooltip": "Delta View zeigt nur die Änderungen seit der letzten erneuten Analyse an. Diese Ansicht ist nur verfügbar, wenn mindestens eine Änderung vorliegt", + "no-data": { + "title": "Auf dieser Seite befinden sich keine Anmerkungen." + }, + "show-redacted-view": "Redigierte Vorschau anzeigen", + "cannot-show-redacted-view": "Redaktionen nicht synchron. Die redigierte Vorschau ist nur nach einer erneuten Analyse verfügbar", + "reanalyse-notification": "Dieses Dokument wurde nicht mit dem neuesten Regel- / Wörterbuchsatz verarbeitet. Analysieren Sie jetzt, um aktualisierte Anmerkungen zu erhalten.", + "reanalyse-file": "Datei-Reanalyse läuft", + "view-toggle": "Redigierte Ansicht", + "tabs": { + "quick-navigation": "Schnelle Navigation", + "document-info": { + "label": "Dokumentinfo", + "close": "Dokumentinfo schließen", + "edit": "Dokumentinformationen bearbeiten", + "details": { + "project": "in {{projectName}}", + "pages": "{{pages}} Seiten", + "revised-pages": "{{pages}} überarbeitete Seiten", + "created-on": "Erstellt am: {{date}}", + "due": "Geburtstermin}}" } + }, + "annotations": { + "label": "Arbeitsbelastung", + "select": "Wählen", + "jump-to-previous": "Zum vorherigen springen", + "jump-to-next": "Zum nächsten springen" + }, + "is-excluded": "Die Redaktion ist für dieses Dokument deaktiviert." }, - "stream-download": { - "abort": "Sie haben einen aktiven Download. Wenn Sie dieses Fenster schließen, wird es gestoppt!", - "error": "Fehler beim Herunterladen von {{Dateiname}}. Bitte versuche es erneut ..." + "toggle-analysis": { + "enable": "Zur Redaktion aktivieren", + "disable": "Deaktivieren Sie die Redaktion", + "only-managers": "Das Aktivieren / Deaktivieren ist nur für Manager zulässig" }, - "roles": { - "RED_USER": "Benutzer", - "RED_MANAGER": "Manager", - "RED_USER_ADMIN": "Benutzer Admin", - "RED_ADMIN": "Anwendungsadministrator", - "NO_ROLE": "Keine Rolle definiert", - "INACTIVE": "Inaktiv", - "MANAGER_ADMIN": "Manager", - "REGULAR": "Regulär" - }, - "file-attributes-csv-import": { - "title": "Wählen Sie CSV-Spalten aus, die als Dateiattribute verwendet werden sollen", - "cancel": "Stornieren", - "save": { - "label": "Attribute speichern", - "success": "{{count}} Dateiattribute erfolgreich erstellt!", - "error": "Fehler beim Erstellen der Dateiattribute!" + "reviewer": "Zugewiesen an", + "unassigned": "Nicht zugewiesen", + "assign-reviewer": "Prüfer zuweisen", + "cancel-assign-reviewer": "Stornieren", + "save-assign-reviewer": "speichern", + "assign-me": "Weisen Sie mir zu", + "last-reviewer": "Zuletzt überprüft von:", + "fullscreen": "Vollbild (F)", + "document-info": "Ihre Dokumenteninfo lebt hier. Dies schließt Metadaten ein, die für jedes Dokument erforderlich sind.", + "new-tab-ssr": "Öffnen Sie das Dokument im serverseitigen Rendering-Modus", + "html-debug": "Öffnen Sie das Dokument-HTML-Debug", + "download-original-file": "Originaldatei herunterladen", + "exit-fullscreen": "Beenden Sie den Vollbildmodus (F)", + "quick-nav": { + "jump-first": "Zur ersten Anmerkung springen", + "jump-last": "Zur letzten Anmerkung springen" + } + }, + "annotation-actions": { + "message": { + "manual-redaction": { + "undo": { + "success": "Rückgängig machen erfolgreich", + "error": "Fehler beim Rückgängigmachen: {{error}}" }, - "delimiter": "Trennzeichen", - "delimiter-placeholder": ",", - "encoding": "Codierung", - "encoding-placeholder": "UTF-8", - "key-column": "Schlüsselspalte", - "key-column-placeholder": "Spalte auswählen ...", - "parse-csv": "Analysieren Sie CSV mit neuen Optionen", - "total-rows": "{{rows}} Zeilen insgesamt", - "available": "{{value}} verfügbar", - "selected": "{{value}} ausgewählt", - "csv-column": "CSV-Spalte", - "csv-column-preview": "CSV-Spaltenvorschau", - "no-hovered-column": "Zeigen Sie eine Vorschau der CSV-Spalte an, indem Sie den Mauszeiger über den Eintrag bewegen.", - "no-sample-data-for": "Keine Beispieldaten für {{column}}.", - "search": { - "placeholder": "Suche nach Spaltennamen ..." + "suggest": { + "success": "Redaktionsvorschlag gespeichert", + "error": "Fehler beim Speichern des Redaktionsvorschlags: {{error}}" }, - "table-header": { - "title": "{{length}} Dateiattribute", - "actions": { - "remove-selected": "Ausgewählte entfernen", - "read-only": "Nur schreibgeschützt machen", - "enable-read-only": "Aktivieren Sie Schreibgeschützt für alle Attribute", - "disable-read-only": "Deaktivieren Sie Schreibgeschützt für alle Attribute", - "type": "Art" - } + "add": { + "success": "Redaktion hinzugefügt!", + "error": "Fehler beim Speichern der Redaktion: {{error}}" }, - "file": "Datei:", - "table-col-names": { - "name": "Name", - "type": "Art", - "read-only": "Schreibgeschützt", - "primary": "primär", - "primary-info-tooltip": "Der Wert des als primär eingestellten Attributs wird unter dem Dateinamen in der Dokumentenliste angezeigt." + "decline": { + "success": "Redaktionsvorschlag abgelehnt!", + "error": "Redaktion konnte nicht abgelehnt werden: {{error}}" }, - "quick-activation": { - "all": "Alle", - "none": "Keiner" + "approve": { + "success": "Redaktionsvorschlag genehmigt!", + "error": "Fehler beim Genehmigen der Redaktion: {{error}}" }, - "action": { - "edit-name": "Namen bearbeiten", - "save-name": "speichern", - "cancel-edit-name": "Stornieren", - "remove": "Entfernen" + "request-remove": { + "success": "Angefordert, Redaktion zu entfernen!", + "error": "Fehler beim Anfordern der Entfernung der Redaktion: {{error}}" }, - "no-data": { - "title": "Keine Dateiattribute definiert. Wählen Sie im linken Bereich eine Spalte aus, um mit der Definition der Dateiattribute zu beginnen." + "remove": { + "success": "Redaktion entfernt!", + "error": "Redaktion konnte nicht entfernt werden: {{error}}" } + }, + "dictionary": { + "undo": { + "success": "Rückgängig machen erfolgreich", + "error": "Fehler beim Rückgängigmachen: {{error}}" + }, + "suggest": { + "success": "Vorschlag zur Wörterbuchänderung gespeichert!", + "error": "Vorschlag zum Ändern des Wörterbuchs konnte nicht gespeichert werden: {{error}}" + }, + "add": { + "success": "Eintrag zum Wörterbuch hinzugefügt. Änderungen werden nach einer erneuten Analyse sichtbar.", + "error": "Fehler beim Hinzufügen des Eintrags zum Wörterbuch: {{error}}" + }, + "decline": { + "success": "Wörterbuchvorschlag abgelehnt.", + "error": "Fehler beim Ablehnen des Wörterbuchvorschlags: {{error}}" + }, + "approve": { + "success": "Wörterbucheintrag genehmigt. Änderungen werden nach einer erneuten Analyse sichtbar.", + "error": "Wörterbucheintrag konnte nicht genehmigt werden: {{error}}" + }, + "request-remove": { + "success": "Angefordert, Wörterbucheintrag zu entfernen!", + "error": "Das Entfernen des Wörterbucheintrags konnte nicht angefordert werden: {{error}}" + }, + "remove": { + "success": "Wörterbucheintrag entfernt!", + "error": "Fehler beim Entfernen des Wörterbucheintrags: {{error}}" + } + } }, - "download-includes": "Wählen Sie aus, was beim Download enthalten ist:", - "download-type": { - "label": "{{length}} Dokumentversionen", - "PREVIEW": "Vorschau PDF", - "ORIGINAL": "Original PDF", - "REDACTED": "Redigiertes PDF" + "force-redaction": { + "label": "Redaktion erzwingen" }, - "report-type": { - "label": "{{length}} Berichtstypen", - "WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE": "Begründung Anhang A1", - "WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE": "Begründung Anhang A2", - "EXCEL_MULTI_FILE": "Excel (für alle)", - "EXCEL_SINGLE_FILE": "Excel (pro Datei)" + "accept-suggestion": { + "label": "Vorschlag annehmen", + "add-to-dict": "Genehmigen und zum Wörterbuch hinzufügen", + "remove-from-dict": "Genehmigen und aus dem Wörterbuch entfernen", + "only-here": "Nur hier genehmigen" + }, + "accept-recommendation": { + "label": "Empfehlung annehmen" + }, + "suggest-remove-annotation": "Entfernen oder vorschlagen, diesen Eintrag zu entfernen", + "suggest-remove-annotations": "Entfernen oder Vorschlagen, um ausgewählte Einträge zu entfernen", + "reject-suggestion": "Vorschlag ablehnen", + "remove-annotation": { + "suggest-remove-from-dict": "Schlagen Sie vor, aus dem Wörterbuch zu entfernen", + "suggest-only-here": "Schlagen Sie vor, nur hier zu entfernen", + "remove-from-dict": "Aus dem Wörterbuch entfernen", + "only-here": "Nur hier entfernen", + "false-positive": "Falsch positiv" + }, + "remove": "Entfernen", + "undo": "Rückgängig machen", + "reject": "Ablehnen", + "hide": "Ausblenden", + "show": "Show" + }, + "initials-avatar": { + "unassigned": "Nicht zugewiesen", + "you": "Sie" + }, + "assign-file-owner": { + "dialog": { + "single-user": "Gutachter", + "title": "File Reviewer verwalten", + "save": "speichern", + "cancel": "Stornieren" + } + }, + "assign-project-owner": { + "dialog": { + "single-user": "Inhaber", + "multi-user": "Team überprüfen", + "title": "Dossier-Team verwalten", + "members": "Mitglieder", + "save": "Änderungen speichern", + "cancel": "Stornieren", + "search": "Suche...", + "no-members": "Noch keine Mitglieder. Wählen Sie aus der Liste unten." + } + }, + "project-member-guard": { + "access-denied": "Sie dürfen nicht auf diese Seite zugreifen." + }, + "comments": { + "comment": "{{count}} Kommentar", + "comments": "{{count}} Kommentare", + "add-comment": "Einen Kommentar hinzufügen", + "hide-comments": "Ausblenden", + "cancel": "Stornieren" + }, + "UNPROCESSED": "Unverarbeitet", + "REPROCESS": "wird bearbeitet", + "FULLREPROCESS": "wird bearbeitet", + "PROCESSING": "wird bearbeitet", + "OCR_PROCESSING": "OCR-Verarbeitung", + "ERROR": "Nachbearbeitung erforderlich", + "UNASSIGNED": "Nicht zugewiesen", + "UNDER_REVIEW": "Wird überprüft", + "UNDER_APPROVAL": "Unter Genehmigung", + "APPROVED": "Genehmigt", + "EXCLUDED": "Ausgeschlossen", + "by": "durch", + "efsa": "EFSA-Genehmigung", + "finished": "Fertig", + "submitted": "Eingereicht", + "active": "Aktiv", + "archived": "Archiviert", + "hint": "Hinweis", + "skipped": "Übersprungen", + "redaction": "Redaktion", + "comment": "Kommentar", + "pending-analysis": "Bis zur erneuten Analyse", + "suggestion": "Redaktionsvorschlag", + "dictionary": "Wörterbuch", + "type": "Art", + "content": "Grund", + "page": "Seite", + "annotation": "Anmerkung", + "annotations": "Anmerkungen", + "filter": { + "hint": "Nur Hinweise", + "redaction": "Redigiert", + "suggestion": "Vorgeschlagene Redaktion", + "analysis": "Analyse erforderlich", + "none": "Keine Anmerkungen", + "updated": "Aktualisiert", + "image": "Bilder" + }, + "filter-menu": { + "label": "Filter", + "filter-types": "Filtertypen", + "filter-options": "Filteroptionen", + "with-comments": "Nur Anmerkungen mit Kommentaren anzeigen" + }, + "sorting": { + "recent": "Kürzlich", + "oldest": "Älteste", + "alphabetically": "Alphabetisch", + "number-of-pages": "Seitenzahl", + "number-of-analyses": "Anzahl der Analysen", + "custom": "Benutzerdefiniert" + }, + "readonly-pill": "Schreibgeschützt", + "group": { + "redactions": "Redaktionswörterbücher", + "hints": "Tipp Wörterbücher" + }, + "annotation-type": { + "recommendation": "Empfehlung", + "remove-only-here": "Ausstehende Entfernung (nur hier)", + "add-dictionary": "Ausstehend zum Wörterbuch hinzufügen", + "remove-dictionary": "Ausstehend aus dem Wörterbuch entfernen", + "suggestion-add-dictionary": "Vorgeschlagenes Wörterbuch hinzufügen", + "suggestion-force-redaction": "Redaktion der Vorschlagskraft", + "suggestion-remove-dictionary": "Vorgeschlagene Wörterbuchentfernung", + "suggestion-add": "Vorgeschlagene Redaktion", + "suggestion-remove": "Vorgeschlagene Redaktionsentfernung", + "skipped": "Übersprungen", + "pending-analysis": "Bis zur erneuten Analyse", + "hint": "Hinweis", + "redaction": "Redaktion", + "manual-redaction": "Manuelle Redaktion", + "declined-suggestion": "Abgelehnter Vorschlag" + }, + "manual-annotation": { + "dialog": { + "header": { + "dictionary": "Zum Wörterbuch hinzufügen", + "redaction": "Redaktion", + "force": "Redaktion erzwingen", + "request-dictionary": "Anfrage zum Wörterbuch hinzufügen", + "request-redaction": "Redaktion anfordern", + "false-positive": "Falsch positiv setzen", + "request-false-positive": "Falsch positiv anfordern" + }, + "add-redaction": { + "success": "Redaktionsvorschlag hinzugefügt!", + "failed": "Fehler beim Hinzufügen der Redaktion: {{message}}" + }, + "actions": { + "save": "speichern" + }, + "content": { + "text": "Ausgewählter Text:", + "rectangle": "Benutzerdefiniertes Rechteck", + "dictionary": "Wörterbuch", + "reason": "Grund", + "reason-placeholder": "Wähle einen Grund ...", + "legalBasis": "Rechtliche Grundlage", + "comment": "Kommentar" + } + }, + "approve-request": { + "success": "Anfrage genehmigt.", + "error": "Anfrage konnte nicht genehmigt werden." + }, + "undo": { + "success": "Aktion rückgängig gemacht.", + "error": "Aktion konnte nicht rückgängig gemacht werden." + }, + "redaction-request": { + "success": "Redaktion angefordert.", + "error": "Redaktion konnte nicht angefordert werden." + }, + "remove-redaction-request": { + "success": "Redaktion entfernt.", + "error": "Redaktion konnte nicht entfernt werden." + }, + "redaction-add": { + "success": "Redaktion hinzugefügt.", + "error": "Redaktion konnte nicht hinzugefügt werden." + } + }, + "remove-annotations-dialog": { + "remove-from-dictionary": { + "title": "Aus dem Wörterbuch entfernen", + "question": "Folgende Einträge werden aus ihren jeweiligen Wörterbüchern entfernt:" + }, + "remove-only-here": { + "title": "Redaktion entfernen", + "question": "Folgende Redaktionen werden nur hier entfernt:" + }, + "dictionary": "Wörterbuch", + "value": "Wert", + "confirm": "Ja, fortfahren und entfernen!", + "deny": "Stornieren" + }, + "confirmation-dialog": { + "assign-file-to-me": { + "title": "Prüfer neu zuweisen", + "question": "Dieses Dokument wird derzeit von einer anderen Person geprüft. Möchten Sie der Prüfer werden und sich diesem Dokument zuordnen?" + }, + "delete-file": { + "title": "Dokument löschen", + "question": "Möchten Sie fortfahren?" + }, + "delete-project": { + "title": "Dossier löschen", + "question": "Möchten Sie fortfahren?" + } + }, + "add-edit-file-attribute": { + "title": { + "edit": "Bearbeiten Sie das {{name}} Dateiattribut", + "new": "Neues Dateiattribut hinzufügen" + }, + "form": { + "name": "Attributname", + "name-placeholder": "Name eingeben", + "column-header": "CSV-Spaltenüberschrift", + "column-header-placeholder": "Geben Sie den CSV-Spaltenkopf ein", + "read-only": "Schreibgeschützt machen", + "type": "Art", + "primary": "Als primär festlegen" + }, + "save": "Attribut speichern" + }, + "file-attribute-types": { + "TEXT": "Freier Text", + "NUMBER": "Nummer", + "DATE": "Datum" + }, + "add-edit-dictionary": { + "title": { + "edit": "Bearbeiten Sie das {{name}} Wörterbuch", + "new": "Wörterbuch erstellen" + }, + "form": { + "name": "Wörterbuchname", + "name-placeholder": "Name eingeben", + "name-hint": "Kann nach dem Speichern nicht bearbeitet werden.", + "description": "Beschreibung", + "description-placeholder": "Beschreibung eingeben", + "rank": "Rang", + "rank-placeholder": "1000", + "color": "Hex Farbe", + "color-placeholder": "#", + "redaction": "Redaktion", + "hint": "Hinweis", + "case-sensitive": "Groß- und Kleinschreibung beachten", + "add-to-dictionary-action": "Verfügbar zum Hinzufügen zum Wörterbuch" + }, + "error": { + "dictionary-already-exists": "Wörterbuch mit diesem Namen existiert bereits!", + "invalid-color-or-rank": "Ungültige Farbe oder Rang! Der Rang wird bereits von einem anderen Wörterbuch verwendet oder die Farbe ist keine gültige HexColor!", + "generic": "Wörterbuch konnte nicht gespeichert werden!" + }, + "save": "Wörterbuch speichern" + }, + "add-edit-project-template": { + "title": { + "edit": "Bearbeiten Sie die {{name}} Dossiervorlage", + "new": "Erstellen Sie eine Dossiervorlage" + }, + "form": { + "name": "Name der Dossiervorlage", + "name-placeholder": "Name eingeben", + "description": "Beschreibung", + "description-placeholder": "Beschreibung eingeben", + "valid-from": "Gültig ab", + "valid-to": "Gültig bis" + }, + "save": "Speichern Sie die Dossiervorlage" + }, + "dictionary-overview": { + "action": { + "delete": "Wörterbuch löschen", + "edit": "Wörterbuch bearbeiten", + "download": "Wörterbuch herunterladen", + "upload": "Wörterbuch hochladen" + }, + "error": { + "entries-too-short": "Einige Einträge des Wörterbuchs liegen unter der Mindestlänge von 2. Diese sind rot hervorgehoben!", + "generic": "Etwas ist schief gelaufen ... Wörterbuch-Update fehlgeschlagen!" + }, + "success": { + "generic": "Wörterbuch aktualisiert!" + }, + "search": "Suche...", + "save-changes": "Änderungen speichern", + "revert-changes": "Zurückkehren", + "dictionary-details": { + "description": "Beschreibung" + }, + "compare": { + "compare": "Vergleichen Sie", + "select-ruleset": "Wählen Sie Dossiervorlage", + "select-dictionary": "Wählen Sie Wörterbuch" + }, + "select-dictionary": "Wählen Sie oben ein Wörterbuch aus, um es mit dem aktuellen zu vergleichen." + }, + "dictionary-listing": { + "action": { + "delete": "Wörterbuch löschen", + "edit": "Wörterbuch bearbeiten" + }, + "case-sensitive": "Groß- und Kleinschreibung beachten", + "add-new": "Neues Wörterbuch", + "stats": { + "charts": { + "types": "Typen", + "entries": "Einträge" + } + }, + "table-header": { + "title": "{{length}} Wörterbücher" + }, + "table-col-names": { + "type": "Art", + "order-of-importance": "Reihenfolge der Wichtigkeit", + "hint-redaction": "Hinweis / Redaktion" + }, + "search": "Suche...", + "no-data": { + "title": "Es gibt noch keine Wörterbücher.", + "action": "Neues Wörterbuch" + }, + "no-match": { + "title": "Keine Wörterbücher stimmen mit Ihren aktuellen Filtern überein." + } + }, + "digital-signature": "Digitale Unterschrift", + "project-templates": "Dossiervorlagen", + "settings": "die Einstellungen", + "project-templates-listing": { + "table-header": { + "title": "{{length}} Dossiervorlagen" + }, + "entries": "{{length}} Einträge", + "dictionaries": "{{length}} Wörterbücher", + "action": { + "delete": "Vorlage löschen", + "edit": "Vorlage bearbeiten" + }, + "add-new": "Neue Dossiervorlage", + "search": "Suche...", + "table-col-names": { + "name": "Name", + "created-by": "Erstellt von", + "created-on": "Erstellt am", + "modified-on": "Geändert am" + }, + "no-data": { + "title": "Es gibt noch keine Dossiervorlagen." + }, + "no-match": { + "title": "Keine Dossiervorlagen stimmen mit Ihren aktuellen Filtern überein." + } + }, + "file-attributes-listing": { + "search": "Suche nach Attributnamen ...", + "add-new": "Neues Attribut", + "table-header": { + "title": "{{length}} Dateiattribute" + }, + "bulk-actions": { + "delete": "Ausgewählte Attribute löschen" + }, + "table-col-names": { + "name": "Name", + "type": "Eingabetyp", + "read-only": "Schreibgeschützt", + "csv-column": "CSV-Spalte", + "primary": "Primär", + "primary-info-tooltip": "Der Wert des als primär eingestellten Attributs wird unter dem Dateinamen in der Dokumentenliste angezeigt." + }, + "no-data": { + "title": "Es sind noch keine Dateiattribute vorhanden." + }, + "no-match": { + "title": "Keine Dateiattribute stimmen mit Ihren aktuellen Filtern überein." + }, + "read-only": "Schreibgeschützt", + "action": { + "edit": "Attribut bearbeiten", + "delete": "Attribut löschen" + }, + "upload-csv": "Konfiguration der Dateiattribute hochladen" + }, + "confirm-delete-file-attribute": { + "title": { + "single": "Löschen Sie {{name}}", + "bulk": "Dateiattribute löschen" + }, + "warning": "Achtung: Dies kann nicht rückgängig gemacht werden!", + "delete": { + "single": "Attribut löschen", + "bulk": "Attribute löschen" + }, + "cancel": { + "single": "Attribut behalten", + "bulk": "Attribute behalten" + }, + "impacted-documents": { + "single": "Alle Dokumente, für die es verwendet wird, sind betroffen", + "bulk": "Alle Dokumente, für die sie verwendet werden, sind betroffen" + }, + "lost-details": "Alle eingegebenen Details in den Dokumenten gehen verloren", + "toast-error": "Bitte bestätigen Sie, dass Sie die Auswirkungen Ihrer Handlung verstehen!" + }, + "confirm-delete-users": { + "title": { + "single": "Benutzer aus Arbeitsbereich löschen", + "bulk": "Benutzer aus dem Arbeitsbereich löschen" + }, + "warning": "Achtung: Dies kann nicht rückgängig gemacht werden!", + "impacted-projects": "{{projectsCount}} Dossiers sind betroffen", + "impacted-documents": { + "single": "Alle Dokumente, deren Überprüfung durch den Benutzer aussteht, sind betroffen", + "bulk": "Alle Dokumente, deren Überprüfung durch die Benutzer aussteht, sind betroffen" + }, + "delete": { + "single": "Benutzer löschen", + "bulk": "Benutzer löschen" + }, + "cancel": { + "single": "Benutzer behalten", + "bulk": "Benutzer behalten" + }, + "toast-error": "Bitte bestätigen Sie, dass Sie die Auswirkungen Ihrer Handlung verstehen!" + }, + "document-info": { + "title": "Dateiattribute einführen", + "save": "Dokumentinformationen speichern", + "save-approval": "Speichern und zur Genehmigung senden" + }, + "user-profile": { + "title": "Mein Profil", + "form": { + "email": "Email", + "first-name": "Vorname", + "last-name": "Nachname" }, "actions": { - "all": "Alle", - "none": "Keiner" + "save": "Profil speichern" } + }, + "user-listing": { + "table-header": { + "title": "{{length}} Benutzer" + }, + "table-col-names": { + "name": "Name", + "email": "Email", + "active": "Aktiv", + "roles": "Rollen" + }, + "action": { + "edit": "Benutzer bearbeiten", + "delete": "Benutzer löschen" + }, + "bulk": { + "delete": "Benutzer löschen", + "delete-disabled": "Sie können Ihr eigenes Konto nicht löschen." + }, + "search": "Suche...", + "add-new": "Neuer Benutzer", + "no-match": { + "title": "Keine Benutzer stimmen mit Ihren aktuellen Filtern überein." + } + }, + "add-edit-user": { + "title": { + "new": "Neuen Benutzer hinzufügen", + "edit": "Benutzer bearbeiten" + }, + "form": { + "first-name": "Vorname", + "last-name": "Nachname", + "email": "Email", + "role": "Rolle" + }, + "actions": { + "save": "Benutzer speichern", + "save-changes": "Änderungen speichern", + "delete": "Benutzer löschen", + "cancel": "Stornieren" + } + }, + "user-stats": { + "title": "Benutzer", + "chart": { + "users": "Benutzer im Arbeitsbereich" + }, + "expand": "Zeige Details", + "collapse": "Details ausblenden" + }, + "rules-screen": { + "error": { + "generic": "Etwas ist schief gelaufen ... Regelaktualisierung fehlgeschlagen!" + }, + "success": { + "generic": "Regeln aktualisiert!" + }, + "action": { + "download": "Regeln herunterladen", + "upload": "Regeln hochladen" + }, + "save-changes": "Änderungen speichern", + "revert-changes": "Zurückkehren" + }, + "watermark-screen": { + "form": { + "text-placeholder": "Text eingeben", + "opacity": "Opazität", + "color": "Farbe", + "font-size": "Schriftgröße", + "font-type": "Schriftart", + "orientation": "Orientierung" + }, + "action": { + "save": "Änderungen speichern", + "revert": "Zurückkehren", + "change-success": "Wasserzeichen aktualisiert!", + "delete-success": "Wasserzeichen gelöscht.", + "error": "Wasserzeichen konnte nicht aktualisiert werden" + }, + "title": "Wasserzeichen" + }, + "dictionaries": "Wörterbücher", + "user-management": "Benutzerverwaltung", + "license-information": "Lizenzinformationen", + "notifications": { + "today": "Heute", + "yesterday": "Gestern", + "tomorrow": "Morgen", + "mark-read": "als gelesen markieren", + "mark-unread": "als ungelesen markieren" + }, + "rule-editor": "Regeleditor", + "watermark": "Wasserzeichen", + "file-attributes": "Dateiattribute", + "pending-changes-guard": "WARNUNG: Sie haben nicht gespeicherte Änderungen. Drücken Sie Abbrechen, um zurück zu gehen und diese Änderungen zu speichern, oder OK, um diese Änderungen zu verlieren.", + "reset-filters": "Filter zurücksetzen", + "overwrite-files-dialog": { + "title": "Dokument existiert bereits!", + "question": "{{filename}} existiert bereits. Wählen Sie, wie Sie fortfahren möchten:", + "options": { + "overwrite": "Ersetzen Sie das vorhandene Dokument", + "skip": "Vorhandenes Dokument behalten", + "cancel": "Alle Uploads abbrechen", + "remember": "Erinnere dich an die Wahl und frag mich nicht noch einmal" + } + }, + "license-info-screen": { + "backend-version": "Backend-Anwendungsversion", + "frontend-version": "Frontend-Anwendungsversion", + "custom-app-title": "Titel der benutzerdefinierten Anwendung", + "copyright-claim-title": "Urheberrechtsanspruch", + "copyright-claim-text": "Copyright © 2020 - {{currentYear}} knecon AG (unterstützt von IQSER)", + "end-user-license-title": "Endbenutzer-Lizenzvereinbarung", + "end-user-license-text": "Die Verwendung dieses Produkts unterliegt den Bestimmungen der Redaction End User Agreement, sofern nicht anders angegeben.", + "3rd-party-title": "Verweis auf Lizenzen von Drittanbietern", + "licensing-details": "Lizenzdetails", + "licensed-to": "Lizenziert an", + "licensing-period": "Lizenzzeitraum", + "analyzed-pages": "Analysierte Seiten", + "usage-details": "Verwendungsdetails", + "total-analyzed": "Insgesamt analysierte Seiten seit {{date}}", + "licensed-page-count": "Anzahl der lizenzierten Seiten", + "current-analyzed": "Analysierte Seiten im aktuellen Lizenzierungszeitraum", + "unlicensed-analyzed": "Nicht lizenzierte analysierte Seiten", + "email-report": "E-Mail-Bericht", + "email": { + "title": "Lizenzbericht {{licenseCustomer}}", + "body": { + "analyzed": "Insgesamt analysierte Seiten im aktuellen Lizenzzeitraum: {{pages}}.", + "licensed": "Lizenzierte Seiten: {{pages}}." + } + }, + "chart": { + "licensed-total": "Lizenzierte Summe", + "cumulative": "Kumulative Seiten", + "pages-per-month": "Seiten pro Monat", + "total-pages": "Alle Seiten", + "legend": "Legende" + } + }, + "audit": "Prüfung", + "audit-screen": { + "table-header": { + "title": "{{length}} Protokolle" + }, + "table-col-names": { + "message": "Botschaft", + "user": "Benutzer", + "date": "Datum", + "category": "Kategorie" + }, + "all-categories": "Alle Kategorien", + "all-users": "Alle Nutzer", + "to": "zu", + "no-data": { + "title": "Keine verfügbaren Protokolle." + } + }, + "pagination": { + "previous": "Zurück", + "next": "Nächster" + }, + "configurations": "Konfigurationen", + "smtp-config-screen": { + "title": "Konfigurieren Sie das SMTP-Konto", + "subtitle": "Mit SMTP (Simple Mail Transfer Protocol) können Sie Ihre E-Mails über die angegebenen Servereinstellungen senden.", + "actions": { + "save": "Konfigurationen speichern", + "test-connection": "Testverbindung" + }, + "form": { + "host": "Gastgeber", + "host-placeholder": "SMTP-Host", + "port": "Hafen", + "from": "Von", + "from-placeholder": "Absender-E-Mail-Adresse", + "from-display-name": "Name für Absender", + "from-display-name-placeholder": "Anzeigename für die Absender-E-Mail-Adresse", + "from-display-name-hint": "Infotext zum Namen des Absenders.", + "reply-to": "Antwort an", + "reply-to-placeholder": "Antwort an E-Mail-Adresse", + "reply-to-display-name": "Name für die Antwort an", + "reply-to-display-name-placeholder": "Anzeigename für die Antwort auf die E-Mail-Adresse", + "envelope-from": "Umschlag von", + "envelope-from-placeholder": "E-Mail-Adresse des Absenderumschlags", + "envelope-from-hint": "Infotext zum Umschlag aus dem Feld.", + "ssl": "Aktivieren Sie SSL", + "starttls": "Aktivieren Sie StartTLS", + "auth": "Aktivieren Sie die Authentifizierung", + "change-credentials": "Anmeldeinformationen ändern" + }, + "test": { + "success": "Test-E-Mail wurde erfolgreich gesendet!", + "error": "Test-E-Mail konnte nicht gesendet werden! Bitte überarbeiten Sie die E-Mail-Adresse." + } + }, + "smtp-auth-config": { + "title": "Aktivieren Sie die Authentifizierung", + "form": { + "username": "Nutzername", + "username-placeholder": "Login Benutzername", + "password": "Passwort" + }, + "actions": { + "save": "Anmeldeinformationen speichern", + "cancel": "Stornieren" + } + }, + "default-colors": "Standardfarben", + "default-colors-screen": { + "table-header": { + "title": "{{length}} Standardfarben" + }, + "table-col-names": { + "key": "Art", + "color": "Farbe" + }, + "types": { + "defaultColor": "Standardfarbe", + "requestAdd": "Anfrage hinzufügen", + "requestRemove": "Anfrage entfernen", + "notRedacted": "Übersprungen", + "analysisColor": "Analyse", + "dictionaryRequestColor": "Wörterbuchanforderung", + "manualRedactionColor": "Manuelle Redaktion", + "previewColor": "Vorschau", + "updatedColor": "Aktualisiert" + }, + "action": { + "edit": "Farbe bearbeiten" + } + }, + "edit-color-dialog": { + "success": "Die Farbe für {{color}} wurde erfolgreich aktualisiert.", + "error": "Fehler beim Aktualisieren der Farben.", + "save": "speichern", + "form": { + "color": "Farbe", + "color-placeholder": "Farbe" + } + }, + "downloads-list": { + "table-header": { + "title": "{{length}} Downloads" + }, + "no-data": { + "title": "Keine aktiven Downloads." + }, + "table-col-names": { + "name": "Name", + "size": "Größe", + "type": "Art", + "date": "Datum", + "status": "Status" + }, + "actions": { + "delete": "Löschen", + "download": "Herunterladen" + } + }, + "digital-signature-screen": { + "title": "Digitale Unterschrift", + "no-data": { + "title": "Es ist kein Zertifikat für digitale Signatur konfiguriert. Laden Sie zum Signieren redigierter Dokumente ein PCKS.12-Zertifikat hoch.", + "action": "Zertifikat hochladen" + }, + "reason": { + "label": "Grund", + "placeholder": "Grund" + }, + "certificate-name": { + "label": "Zertifikatname", + "placeholder": "Zertifikatname" + }, + "contact-info": { + "label": "Kontakt Informationen", + "placeholder": "Kontakt Informationen" + }, + "location": { + "label": "Ort", + "placeholder": "Ort" + }, + "password": { + "label": "Zertifikat Passwort / Schlüssel", + "placeholder": "Passwort" + }, + "action": { + "save": "Digitale Signatur speichern", + "delete": "Digitale Signatur löschen", + "reset": "Zurücksetzen", + "save-success": "Digitale Signatur erfolgreich gespeichert", + "save-error": "Fehler beim Speichern der digitalen Signatur", + "certificate-not-valid-error": "Das hochgeladene Zertifikat gilt nicht zum Signieren von PDFs. Das PCKS.12-Format ist erforderlich.", + "delete-success": "Digitale Signatur entfernt. Redigierte Dateien werden nicht mehr signiert!", + "delete-error": "Fehler beim Entfernen der digitalen Signatur. Versuchen Sie es erneut." + } + }, + "stream-download": { + "abort": "Sie haben einen aktiven Download. Wenn Sie dieses Fenster schließen, wird es gestoppt!", + "error": "Fehler beim Herunterladen von {{Dateiname}}. Bitte versuche es erneut ..." + }, + "roles": { + "RED_USER": "Benutzer", + "RED_MANAGER": "Manager", + "RED_USER_ADMIN": "Benutzer Admin", + "RED_ADMIN": "Anwendungsadministrator", + "NO_ROLE": "Keine Rolle definiert", + "INACTIVE": "Inaktiv", + "MANAGER_ADMIN": "Manager", + "REGULAR": "Regulär" + }, + "file-attributes-csv-import": { + "title": "Wählen Sie CSV-Spalten aus, die als Dateiattribute verwendet werden sollen", + "cancel": "Stornieren", + "save": { + "label": "Attribute speichern", + "success": "{{count}} Dateiattribute erfolgreich erstellt!", + "error": "Fehler beim Erstellen der Dateiattribute!" + }, + "delimiter": "Trennzeichen", + "delimiter-placeholder": ",", + "encoding": "Codierung", + "encoding-placeholder": "UTF-8", + "key-column": "Schlüsselspalte", + "key-column-placeholder": "Spalte auswählen ...", + "parse-csv": "Analysieren Sie CSV mit neuen Optionen", + "total-rows": "{{rows}} Zeilen insgesamt", + "available": "{{value}} verfügbar", + "selected": "{{value}} ausgewählt", + "csv-column": "CSV-Spalte", + "csv-column-preview": "CSV-Spaltenvorschau", + "no-hovered-column": "Zeigen Sie eine Vorschau der CSV-Spalte an, indem Sie den Mauszeiger über den Eintrag bewegen.", + "no-sample-data-for": "Keine Beispieldaten für {{column}}.", + "search": { + "placeholder": "Suche nach Spaltennamen ..." + }, + "table-header": { + "title": "{{length}} Dateiattribute", + "actions": { + "remove-selected": "Ausgewählte entfernen", + "read-only": "Nur schreibgeschützt machen", + "enable-read-only": "Aktivieren Sie Schreibgeschützt für alle Attribute", + "disable-read-only": "Deaktivieren Sie Schreibgeschützt für alle Attribute", + "type": "Art" + } + }, + "file": "Datei:", + "table-col-names": { + "name": "Name", + "type": "Art", + "read-only": "Schreibgeschützt", + "primary": "primär", + "primary-info-tooltip": "Der Wert des als primär eingestellten Attributs wird unter dem Dateinamen in der Dokumentenliste angezeigt." + }, + "quick-activation": { + "all": "Alle", + "none": "Keiner" + }, + "action": { + "edit-name": "Namen bearbeiten", + "save-name": "speichern", + "cancel-edit-name": "Stornieren", + "remove": "Entfernen" + }, + "no-data": { + "title": "Keine Dateiattribute definiert. Wählen Sie im linken Bereich eine Spalte aus, um mit der Definition der Dateiattribute zu beginnen." + } + }, + "download-includes": "Wählen Sie aus, was beim Download enthalten ist:", + "download-type": { + "label": "{{length}} Dokumentversionen", + "PREVIEW": "Vorschau PDF", + "ORIGINAL": "Original PDF", + "REDACTED": "Redigiertes PDF" + }, + "report-type": { + "label": "{{length}} Berichtstypen", + "WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE": "Begründung Anhang A1", + "WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE": "Begründung Anhang A2", + "EXCEL_MULTI_FILE": "Excel (für alle)", + "EXCEL_SINGLE_FILE": "Excel (pro Datei)" + }, + "actions": { + "all": "Alle", + "none": "Keiner" + } } diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 3dac708dc..308d90a0d 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -1,1258 +1,1258 @@ { - "auth-error": { - "heading": "Your user doesn't have the required RED-* roles to access this application. Please contact your admin for access!", - "heading-with-name-and-link": "Your user doesn't have the required RED-* roles to access this application. Please contact {{adminName}} for access!", - "heading-with-name": "Your user doesn't have the required RED-* roles to access this application. Please contact {{adminName}} for access!", - "heading-with-link": "Your user doesn't have the required RED-* roles to access this application. Please contact your admin for access!", - "logout": "Logout" + "auth-error": { + "heading": "Your user doesn't have the required RED-* roles to access this application. Please contact your admin for access!", + "heading-with-name-and-link": "Your user doesn't have the required RED-* roles to access this application. Please contact {{adminName}} for access!", + "heading-with-name": "Your user doesn't have the required RED-* roles to access this application. Please contact {{adminName}} for access!", + "heading-with-link": "Your user doesn't have the required RED-* roles to access this application. Please contact your admin for access!", + "logout": "Logout" + }, + "app-name": "DDA-R", + "dev-mode": "[ DEV MODE ]", + "upload-status": { + "error": { + "file-size": "File to large. Limit is {{size}}MB.", + "generic": "Failed to upload file... " }, - "app-name": "DDA-R", - "dev-mode": "[ DEV MODE ]", - "upload-status": { - "error": { - "file-size": "File to large. Limit is {{size}}MB.", - "generic": "Failed to upload file... " - }, - "dialog": { - "title": "File Uploads ({{len}})", - "actions": { - "re-upload": "Retry Upload", - "cancel": "Cancel Upload" - } - } + "dialog": { + "title": "File Uploads ({{len}})", + "actions": { + "re-upload": "Retry Upload", + "cancel": "Cancel Upload" + } + } + }, + "download-status": { + "queued": "Your download has been queued, you can see all your requested downloads here: My Downloads .", + "error": { + "generic": "Download failed" }, - "download-status": { - "queued": "Your download has been queued, you can see all your requested downloads here: My Downloads .", - "error": { - "generic": "Download failed" - }, - "dialog": { - "title": "Downloads ({{len}})", - "tooltip": "{{len}} files", - "actions": { - "download": "Download now", - "cancel": "Cancel Download" - } - } + "dialog": { + "title": "Downloads ({{len}})", + "tooltip": "{{len}} files", + "actions": { + "download": "Download now", + "cancel": "Cancel Download" + } + } + }, + "pdf-viewer": { + "text-popup": { + "actions": { + "search": "Search for selection" + } }, - "pdf-viewer": { - "text-popup": { - "actions": { - "search": "Search for selection" - } - }, - "search-in-progress": "Search in progress..." - }, - "common": { - "close": "Close View", - "dialog": { - "close": "Close Dialog" - }, - "confirmation-dialog": { - "title": "Confirm Action", - "description": "This action requires confirmation, do you wish to proceed?", - "confirm": "Yes", - "deny": "No" - } - }, - "top-bar": { - "navigation-items": { - "projects": "Active Dossier", - "back": "Back", - "my-account": { - "children": { - "admin": "Settings", - "downloads": "My Downloads", - "my-profile": "My Profile", - "language": { - "label": "Language", - "en": "English", - "de": "German" - }, - "logout": "Logout" - } - } - } - }, - "filters": { - "filter-by": "Filter:", - "status": "Status", - "people": "Dossier Member(s)", - "assigned-people": "Assignee(s)", - "due-date": "Due Date", - "created-on": "Created On", - "project": "Dossier", - "document": "Document", - "needs-work": "Workload", - "rulesets": "Rule Sets" - }, - "report": { - "unavailable": "Redaction report is only available once all files have been approved.", - "unavailable-single": "Redaction report is only available once this file has been approved.", - "action": { - "label": "Download Redaction Report", - "efsa": "Download with EFSA Template", - "syngenta": "Download with Syngenta Template" - } - }, - "project-listing": { - "search": "Dossier name...", - "reanalyse": { - "action": "Analyze entire dossier" - }, - "assign": { - "action": "Assign Owner & Members" - }, - "download-files": { - "action": "Download Redacted Files" - }, - "table-header": { - "title": "{{length}} active dossiers", - "bulk-select": "Toggle Selection", - "recent": "Recent" - }, - "table-col-names": { - "name": "Document", - "needs-work": "Workload", - "owner": "Owner", - "status": "Status", - "ruleset": "Rule Set" - }, - "stats": { - "analyzed-pages": "Pages", - "total-people": "Total user(s)", - "charts": { - "projects": "Dossiers", - "total-documents": "Total Document(s)" - } - }, - "no-data": { - "title": "You currently have no dossiers.", - "action": "New Dossier" - }, - "add-new": "New Dossier", - "add-edit-dialog": { - "header-new": "Create Dossier", - "header-edit": "Edit Dossier", - "form": { - "name": { - "label": "Dossier Name", - "placeholder": "Enter Name" - }, - "description": { - "label": "Description", - "placeholder": "Enter Description" - }, - "due-date": "Due Date", - "template": "Dossier Template" - }, - "errors": { - "project-already-exists": "Dossier with this name already exists!", - "generic": "Failed to save dossier" - }, - "actions": { - "save": "Save", - "save-and-add-members": "Save and Edit Team" - } - }, - "header": "Dossiers", - "edit": { - "action": "Edit Dossier" - }, - "delete": { - "action": "Delete Dossier", - "delete-failed": "Failed to delete dossier: {{projectName}}" - }, - "no-match": { - "title": "No dossiers match your current filters." - } - }, - "project-details": { - "title": "Dossier Details", - "dialog": { - "title": "Dossier Details", - "info": { - "file-count": "Number of files: {{fileCount}}" - }, - "actions": { - "reanalyse-project": "Analyze Dossier" - } - }, - "owner": "Owner", - "members": "Members", - "see-less": "See less", - "assign-members": "Assign Members", - "expand": "Show Details", - "collapse": "Hide Details" - }, - "dossier-dictionary-dialog": { - "title": "Dossier Dictionary", - "save-changes": "Save Changes", - "cancel": "cancel" - }, - "project-overview": { - "no-ocr": "No OCR", - "ocr-performed": "OCR was performed for this file.", - "no-data": { - "title": "There are no documents yet.", - "action": "Upload Document" - }, - "no-match": { - "title": "No documents match your current filters." - }, - "search": "Document name...", - "header-actions": { - "edit": "Edit", - "delete": "Delete", - "assign": "Assign Owner & Members", - "upload-document": "Upload Document", - "download-redacted-files": "Download Redacted Files" - }, - "ocr-file": "OCR Document", - "download-file": "Download", - "download-file-disabled": "Download is only permitted for approved files", - "under-approval": "For Approval", - "approve": "Approve", - "approve-disabled": "File can only be approved once it has been analysed with the latest dictionaries and all suggestions have been processed", - "under-review": "Under Review", - "upload-files": "Drag & Drop files anywhere", - "upload-files-btn": "Upload Files", - "new-rule": { - "label": "Outdated", - "toast": { - "message-project": "Reanalysis required: ", - "actions": { - "reanalyse-all": "Analyze all", - "reanalyse-file": "Analyze this file", - "later": "Later" - } - } - }, - "report": { - "action": "Download redaction report" - }, - "assign": "Assign Reviewer", - "assign-me": "Assign To Me", - "table-header": { - "title": "{{length}} documents", - "bulk-select": "Toggle Selection" - }, - "table-col-names": { - "name": "Name", - "added-on": "Added", - "needs-work": "Workload", - "assigned-to": "Assigned to", - "pages": "Pages", - "status": "Status" - }, - "upload-error": "Failed to upload file: {{name}}", - "delete-file-error": "Failed to delete file: {{filename}}", - "delete-files-error": "Failed to delete files.", - "reanalyse": { - "action": "Analyze File" - }, - "delete": { - "action": "Delete File" - }, - "file-listing": { - "file-entry": { - "status": "Status: {{status}}", - "number-of-pages": "Number of pages: {{numberOfPages}}", - "number-of-analyses": "Analysis count: {{numberOfAnalyses}}", - "added": "Date added: {{added}}", - "last-updated": "Last updated: {{lastUpdated}}", - "file-pending": "Pending...", - "file-processing": "Processing", - "file-error": "Re-processing required" - } - }, - "project-details": { - "charts": { - "documents-in-project": "Documents in Dossier" - }, - "stats": { - "documents": "{{count}} documents", - "analysed-pages": "{{count}} pages", - "people": "{{count}} user(s)", - "created-on": "Created on {{date}}", - "due-date": "Due {{date}}" - }, - "dictionary": "Dossier Dictionary", - "description": "Description" - }, - "header": "Dossier Overview", - "no-project": "Requested dossier: {{projectId}} does not exist! Back to Dossier Listing. ", - "bulk": { - "delete": "Delete Documents", - "assign": "Assign Reviewer", - "reanalyse": "Analyze Documents", - "reanalyse-error-outdated": "Not all selected documents can be analyzed, some may not be assigned to you or are already analyzed." - }, - "reanalyse-project": { - "success": "Files scheduled for reanalysis.", - "error": "Failed to schedule files for reanalysis. Please try again." - } - }, - "file-preview": { - "delta": "Delta", - "redacted": "Preview", - "standard": "Standard", - "standard-tooltip": "Standard Workload view shows all hints, redactions, recommendations & suggestions. This view allows editing.", - "redacted-tooltip": "Redaction preview shows only redactions. Consider this a preview for the final redacted version. This view is only available if the file has no pending changes & doesn't require a reanalysis", - "delta-tooltip": "Delta View shows only the changes since last re-analysis. This view is only available if there is at least 1 change", - "no-data": { - "title": "There are no annotations on this page." - }, - "show-redacted-view": "Show Redacted Preview", - "cannot-show-redacted-view": "Redactions out of sync. Redacted Preview only available after reanalysis", - "reanalyse-notification": "This document was not processed with the latest rule/dictionary set. Analyze now to get updated annotations.", - "reanalyse-file": "File reanalysis in progress", - "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", - "select": "Select", - "jump-to-previous": "Jump to Previous", - "jump-to-next": "Jump to Next" - }, - "is-excluded": "Redaction is disabled for this document." - }, - "toggle-analysis": { - "enable": "Enable for redaction", - "disable": "Disable redaction", - "only-managers": "Enabling / disabling is permitted only for managers" - }, - "reviewer": "Assigned to", - "unassigned": "Unassigned", - "assign-reviewer": "Assign Reviewer", - "cancel-assign-reviewer": "Cancel", - "save-assign-reviewer": "Save", - "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", - "exit-fullscreen": "Exit Full Screen (F)", - "quick-nav": { - "jump-first": "Jump to first annotation", - "jump-last": "Jump to last annotation" - } - }, - "annotation-actions": { - "message": { - "manual-redaction": { - "undo": { - "success": "Undo successful", - "error": "Failed to undo: {{error}}" - }, - "suggest": { - "success": "Redaction suggestion saved", - "error": "Failed to save redaction suggestion: {{error}}" - }, - "add": { - "success": "Redaction added!", - "error": "Failed to save redaction: {{error}}" - }, - "decline": { - "success": "Redaction suggestion declined!", - "error": "Failed to decline redaction: {{error}}" - }, - "approve": { - "success": "Redaction suggestion approved!", - "error": "Failed to approved redaction: {{error}}" - }, - "request-remove": { - "success": "Requested to remove redaction!", - "error": "Failed to request removal of redaction: {{error}}" - }, - "remove": { - "success": "Redaction removed!", - "error": "Failed to remove redaction: {{error}}" - } - }, - "dictionary": { - "undo": { - "success": "Undo successful", - "error": "Failed to undo: {{error}}" - }, - "suggest": { - "success": "Suggestion for dictionary modification saved!", - "error": "Failed to save suggestion for dictionary modification: {{error}}" - }, - "add": { - "success": "Entry added to dictionary. Changes will be visible after reanalysis.", - "error": "Failed to add entry to dictionary: {{error}}" - }, - "decline": { - "success": "Dictionary suggestion declined.", - "error": "Failed to decline dictionary suggestion: {{error}}" - }, - "approve": { - "success": "Dictionary entry approved. Changes will be visible after reanalysis.", - "error": "Failed to approve dictionary entry: {{error}}" - }, - "request-remove": { - "success": "Requested to remove dictionary entry!", - "error": "Failed to request removal of dictionary entry: {{error}}" - }, - "remove": { - "success": "Dictionary entry removed!", - "error": "Failed to remove dictionary entry: {{error}}" - } - } - }, - "force-redaction": { - "label": "Force Redaction" - }, - "accept-suggestion": { - "label": "Accept Suggestion", - "add-to-dict": "Approve and add to dictionary", - "remove-from-dict": "Approve and remove from dictionary", - "only-here": "Approve only here" - }, - "accept-recommendation": { - "label": "Accept Recommendation" - }, - "suggest-remove-annotation": "Remove or Suggest to remove this entry", - "suggest-remove-annotations": "Remove or Suggest to remove selected entries", - "reject-suggestion": "Reject Suggestion", - "remove-annotation": { - "suggest-remove-from-dict": "Suggest to remove from dictionary", - "suggest-only-here": "Suggest to remove only here", - "remove-from-dict": "Remove from dictionary", - "only-here": "Remove only here", - "false-positive": "False Positive" - }, - "remove": "Remove", - "undo": "Undo", - "reject": "Reject", - "hide": "Hide", - "show": "Show" - }, - "initials-avatar": { - "unassigned": "Unassigned", - "you": "You" - }, - "assign-file-owner": { - "dialog": { - "single-user": "Reviewer", - "title": "Manage File Reviewer", - "save": "Save", - "cancel": "Cancel" - } - }, - "assign-project-owner": { - "dialog": { - "single-user": "Owner", - "multi-user": "Review Team", - "title": "Manage Dossier Team", - "approvers": "Approvers", - "reviewers": "Reviewers", - "save": "Save Changes", - "cancel": "Cancel", - "search": "Search...", - "no-approvers": "No approvers yet.\nSelect from the list below.", - "no-reviewers": "No reviewers yet.\nSelect from the list below.", - "make-approver": "Make Approver" - } - }, - "project-member-guard": { - "access-denied": "You are not allowed to access that page." - }, - "comments": { - "comment": "{{count}} comment", - "comments": "{{count}} comments", - "add-comment": "Add a comment", - "hide-comments": "Hide", - "cancel": "Cancel" - }, - "UNPROCESSED": "Unprocessed", - "REPROCESS": "Processing", - "FULLREPROCESS": "Processing", - "PROCESSING": "Processing", - "OCR_PROCESSING": "OCR Processing", - "ERROR": "Re-processing required", - "UNASSIGNED": "Unassigned", - "UNDER_REVIEW": "Under Review", - "UNDER_APPROVAL": "Under Approval", - "APPROVED": "Approved", - "EXCLUDED": "Excluded", - "by": "by", - "efsa": "EFSA Approval", - "finished": "Finished", - "submitted": "Submitted", - "active": "Active", - "archived": "Archived", - "hint": "Hint", - "skipped": "Skipped", - "redaction": "Redaction", - "comment": "Comment", - "pending-analysis": "Pending Re-Analysis", - "suggestion": "Suggestion for redaction", - "dictionary": "Dictionary", - "type": "Type", - "content": "Reason", - "page": "Page", - "annotation": "Annotation", - "annotations": "Annotations", - "filter": { - "hint": "Hints only", - "redaction": "Redacted", - "suggestion": "Suggested Redaction", - "analysis": "Analysis required", - "none": "No Annotations", - "updated": "Updated", - "image": "Images" - }, - "filter-menu": { - "label": "Filter", - "filter-types": "Filter types", - "filter-options": "Filter options", - "with-comments": "Show only annotations with comments" - }, - "sorting": { - "recent": "Recent", - "oldest": "Oldest", - "alphabetically": "Alphabetically", - "number-of-pages": "Number of pages", - "number-of-analyses": "Number of analyses", - "custom": "Custom" - }, - "readonly-pill": "Read-only", - "group": { - "redactions": "Redaction Dictionaries", - "hints": "Hint Dictionaries" - }, - "annotation-type": { - "recommendation": "Recommendation", - "remove-only-here": "Pending removal ( only here )", - "add-dictionary": "Pending add to dictionary", - "remove-dictionary": "Pending remove from dictionary", - "suggestion-add-dictionary": "Suggested dictionary add", - "suggestion-force-redaction": "Suggestion force redaction", - "suggestion-remove-dictionary": "Suggested dictionary removal", - "suggestion-add": "Suggested redaction", - "suggestion-remove": "Suggested redaction removal", - "skipped": "Skipped", - "pending-analysis": "Pending Re-Analysis", - "hint": "Hint", - "redaction": "Redaction", - "manual-redaction": "Manual Redaction", - "declined-suggestion": "Declined Suggestion" - }, - "manual-annotation": { - "dialog": { - "header": { - "dictionary": "Add to dictionary", - "redaction": "Redaction", - "force": "Force Redaction", - "request-dictionary": "Request add to dictionary", - "request-redaction": "Request Redaction", - "false-positive": "Set false positive", - "request-false-positive": "Request false positive" - }, - "add-redaction": { - "success": "Redaction suggestion added!", - "failed": "Failed to add redaction: {{message}}" - }, - "actions": { - "save": "Save" - }, - "content": { - "text": "Selected text:", - "rectangle": "Custom Rectangle", - "dictionary": "Dictionary", - "reason": "Reason", - "reason-placeholder": "Select a reason ...", - "legalBasis": "Legal Basis", - "comment": "Comment" - } - }, - "approve-request": { - "success": "Request approved.", - "error": "Failed to approve request." - }, - "undo": { - "success": "Action undone.", - "error": "Failed to undo action." - }, - "redaction-request": { - "success": "Redaction requested.", - "error": "Failed to request redaction." - }, - "remove-redaction-request": { - "success": "Redaction removed.", - "error": "Failed to remove redaction." - }, - "redaction-add": { - "success": "Redaction added.", - "error": "Failed to add redaction." - } - }, - "remove-annotations-dialog": { - "remove-from-dictionary": { - "title": "Remove From Dictionary", - "question": "Following entries will be removed from their respective dictionaries:" - }, - "remove-only-here": { - "title": "Remove Redaction", - "question": "Following redactions will be removed only here:" - }, - "dictionary": "Dictionary", - "value": "Value", - "confirm": "Yes, proceed and remove!", - "deny": "Cancel" + "search-in-progress": "Search in progress..." + }, + "common": { + "close": "Close View", + "dialog": { + "close": "Close Dialog" }, "confirmation-dialog": { - "assign-file-to-me": { - "title": "Re-assign reviewer", - "question": "This document is currently reviewed by someone else. Do you want to become the reviewer and assign yourself to this document?" - }, - "delete-file": { - "title": "Delete Document", - "question": "Do you wish to proceed?" - }, - "delete-project": { - "title": "Delete Dossier", - "question": "Do you wish to proceed?" + "title": "Confirm Action", + "description": "This action requires confirmation, do you wish to proceed?", + "confirm": "Yes", + "deny": "No" + } + }, + "top-bar": { + "navigation-items": { + "projects": "Active Dossier", + "back": "Back", + "my-account": { + "children": { + "admin": "Settings", + "downloads": "My Downloads", + "my-profile": "My Profile", + "language": { + "label": "Language", + "en": "English", + "de": "German" + }, + "logout": "Logout" } + } + } + }, + "filters": { + "filter-by": "Filter:", + "status": "Status", + "people": "Dossier Member(s)", + "assigned-people": "Assignee(s)", + "due-date": "Due Date", + "created-on": "Created On", + "project": "Dossier", + "document": "Document", + "needs-work": "Workload", + "rulesets": "Rule Sets" + }, + "report": { + "unavailable": "Redaction report is only available once all files have been approved.", + "unavailable-single": "Redaction report is only available once this file has been approved.", + "action": { + "label": "Download Redaction Report", + "efsa": "Download with EFSA Template", + "syngenta": "Download with Syngenta Template" + } + }, + "project-listing": { + "search": "Dossier name...", + "reanalyse": { + "action": "Analyze entire dossier" }, - "add-edit-file-attribute": { - "title": { - "edit": "Edit {{name}} File Attribute", - "new": "Add New File Attribute" - }, - "form": { - "name": "Attribute Name", - "name-placeholder": "Enter Name", - "column-header": "CSV Column Header", - "column-header-placeholder": "Enter CSV Column Header", - "read-only": "Make Read-Only", - "type": "Type", - "primary": "Set as Primary" - }, - "save": "Save Attribute" + "assign": { + "action": "Assign Owner & Members" }, - "file-attribute-types": { - "TEXT": "Free Text", - "NUMBER": "Number", - "DATE": "Date" + "download-files": { + "action": "Download Redacted Files" }, - "add-edit-dictionary": { - "title": { - "edit": "Edit {{name}} Dictionary", - "new": "Create Dictionary" - }, - "form": { - "name": "Dictionary Name", - "name-placeholder": "Enter Name", - "name-hint": "Cannot be edited after saving.", - "description": "Description", - "description-placeholder": "Enter Description", - "rank": "Rank", - "rank-placeholder": "1000", - "color": "Hex Color", - "color-placeholder": "#", - "redaction": "Redaction", - "hint": "Hint", - "case-sensitive": "Case Sensitive", - "add-to-dictionary-action": "Available for add to dictionary" - }, - "error": { - "dictionary-already-exists": "Dictionary with this name already exists!", - "invalid-color-or-rank": "Invalid color or rank! Rank is already used by another dictionary or the color is not a valid hexColor!", - "generic": "Failed to save dictionary!" - }, - "save": "Save Dictionary" + "table-header": { + "title": "{{length}} active dossiers", + "bulk-select": "Toggle Selection", + "recent": "Recent" }, - "add-edit-project-template": { - "title": { - "edit": "Edit {{name}} Dossier Template", - "new": "Create Dossier Template" - }, - "form": { - "name": "Dossier Template Name", - "name-placeholder": "Enter Name", - "description": "Description", - "description-placeholder": "Enter Description", - "valid-from": "Valid from", - "valid-to": "Valid to" - }, - "save": "Save Dossier Template" + "table-col-names": { + "name": "Document", + "needs-work": "Workload", + "owner": "Owner", + "status": "Status", + "ruleset": "Rule Set" }, - "dictionary-overview": { - "action": { - "delete": "Delete Dictionary", - "edit": "Edit Dictionary", - "download": "Download Dictionary", - "upload": "Upload Dictionary" - }, - "error": { - "entries-too-short": "Some entries of the dictionary are below the minimum length of 2. These are highlighted with red!", - "generic": "Something went wrong... Dictionary update failed!" - }, - "success": { - "generic": "Dictionary updated!" - }, - "search": "Search...", - "save-changes": "Save Changes", - "revert-changes": "Revert", - "dictionary-details": { - "description": "Description" - }, - "compare": { - "compare": "Compare", - "select-ruleset": "Select Dossier Template", - "select-dictionary": "Select Dictionary" - }, - "select-dictionary": "Select a dictionary above to compare with the current one." + "stats": { + "analyzed-pages": "Pages", + "total-people": "Total user(s)", + "charts": { + "projects": "Dossiers", + "total-documents": "Total Document(s)" + } }, - "dictionary-listing": { - "action": { - "delete": "Delete Dictionary", - "edit": "Edit Dictionary" - }, - "case-sensitive": "Case Sensitive", - "add-new": "New Dictionary", - "stats": { - "charts": { - "types": "Types", - "entries": "Entries" - } - }, - "table-header": { - "title": "{{length}} dictionaries" - }, - "table-col-names": { - "type": "Type", - "order-of-importance": "Order Of Importance", - "hint-redaction": "Hint/Redaction" - }, - "search": "Search...", - "no-data": { - "title": "There are no dictionaries yet.", - "action": "New Dictionary" - }, - "no-match": { - "title": "No dictionaries match your current filters." - } + "no-data": { + "title": "You currently have no dossiers.", + "action": "New Dossier" }, - "digital-signature": "Digital Signature", - "project-templates": "Dossier Templates", - "settings": "Settings", - "project-templates-listing": { - "table-header": { - "title": "{{length}} dossier templates" + "add-new": "New Dossier", + "add-edit-dialog": { + "header-new": "Create Dossier", + "header-edit": "Edit Dossier", + "form": { + "name": { + "label": "Dossier Name", + "placeholder": "Enter Name" }, - "entries": "{{length}} entries", - "dictionaries": "{{length}} dictionaries", - "action": { - "delete": "Delete Template", - "edit": "Edit Template" + "description": { + "label": "Description", + "placeholder": "Enter Description" }, - "add-new": "New Dossier Template", - "search": "Search...", - "table-col-names": { - "name": "Name", - "created-by": "Created by", - "created-on": "Created on", - "modified-on": "Modified on" - }, - "no-data": { - "title": "There are no dossier templates yet." - }, - "no-match": { - "title": "No dossier templates match your current filters." - } - }, - "file-attributes-listing": { - "search": "Search by attribute name...", - "add-new": "New Attribute", - "table-header": { - "title": "{{length}} file attributes" - }, - "bulk-actions": { - "delete": "Delete Selected Attributes" - }, - "table-col-names": { - "name": "Name", - "type": "Input Type", - "read-only": "Read-Only", - "csv-column": "CSV Column", - "primary": "Primary", - "primary-info-tooltip": "The value of the attribute set as primary shows up under the file name in the documents list." - }, - "no-data": { - "title": "There are no file attributes yet." - }, - "no-match": { - "title": "No file attributes match your current filters." - }, - "read-only": "Read-only", - "action": { - "edit": "Edit Attribute", - "delete": "Delete Attribute" - }, - "upload-csv": "Upload File Attributes Configuration" - }, - "confirm-delete-file-attribute": { - "title": { - "single": "Delete {{name}}", - "bulk": "Delete File Attributes" - }, - "warning": "Warning: this cannot be undone!", - "delete": { - "single": "Delete Attribute", - "bulk": "Delete Attributes" - }, - "cancel": { - "single": "Keep Attribute", - "bulk": "Keep Attributes" - }, - "impacted-documents": { - "single": "All documents it is used on will be impacted", - "bulk": "All documents they are used on will be impacted" - }, - "lost-details": "All inputted details on the documents will be lost", - "toast-error": "Please confirm that you understand the ramifications of your action!" - }, - "confirm-delete-users": { - "title": { - "single": "Delete User from Workspace", - "bulk": "Delete Users from Workspace" - }, - "warning": "Warning: this cannot be undone!", - "impacted-projects": "{{projectsCount}} dossiers will be impacted", - "impacted-documents": { - "single": "All documents pending review from the user will be impacted", - "bulk": "All documents pending review from the users will be impacted" - }, - "delete": { - "single": "Delete User", - "bulk": "Delete Users" - }, - "cancel": { - "single": "Keep User", - "bulk": "Keep Users" - }, - "toast-error": "Please confirm that you understand the ramifications of your action!" - }, - "document-info": { - "title": "Introduce File Attributes", - "save": "Save Document Info", - "save-approval": "Save and Send for Approval" - }, - "user-profile": { - "title": "My profile", - "form": { - "email": "Email", - "first-name": "First name", - "last-name": "Last name" - }, - "actions": { - "save": "Save profile" - } - }, - "user-listing": { - "table-header": { - "title": "{{length}} users" - }, - "table-col-names": { - "name": "Name", - "email": "Email", - "active": "Active", - "roles": "Roles" - }, - "action": { - "edit": "Edit User", - "delete": "Delete User" - }, - "bulk": { - "delete": "Delete Users", - "delete-disabled": "You cannot delete your own account." - }, - "search": "Search...", - "add-new": "New User", - "no-match": { - "title": "No users match your current filters." - } - }, - "add-edit-user": { - "title": { - "new": "Add New User", - "edit": "Edit User" - }, - "form": { - "first-name": "First Name", - "last-name": "Last Name", - "email": "Email", - "role": "Role" - }, - "actions": { - "save": "Save User", - "save-changes": "Save Changes", - "delete": "Delete User", - "cancel": "Cancel" - } - }, - "user-stats": { - "title": "Users", - "chart": { - "users": "Users in Workspace" - }, - "expand": "Show Details", - "collapse": "Hide Details" - }, - "rules-screen": { - "error": { - "generic": "Something went wrong... Rules update failed!" - }, - "success": { - "generic": "Rules updated!" - }, - "action": { - "download": "Download Rules", - "upload": "Upload Rules" - }, - "save-changes": "Save Changes", - "revert-changes": "Revert" - }, - "watermark-screen": { - "form": { - "text-placeholder": "Enter text", - "opacity": "Opacity", - "color": "Color", - "font-size": "Font Size", - "font-type": "Font Type", - "orientation": "Orientation" - }, - "action": { - "save": "Save Changes", - "revert": "Revert", - "change-success": "Watermark updated!", - "delete-success": "Watermark deleted.", - "error": "Failed to update Watermark" - }, - "title": "Watermark" - }, - "dictionaries": "Dictionaries", - "user-management": "User Management", - "license-information": "License Information", - "notifications": { - "today": "Today", - "yesterday": "Yesterday", - "tomorrow": "Tomorrow", - "mark-read": "Mark as read", - "mark-unread": "Mark as unread" - }, - "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": { - "title": "Document already exists!", - "question": "{{filename}} already exists. Choose how to proceed:", - "options": { - "overwrite": "Replace existing document", - "skip": "Keep existing document", - "cancel": "Cancel all uploads", - "remember": "Remember choice and don't ask me again" - } - }, - "license-info-screen": { - "backend-version": "Backend Application Version", - "frontend-version": "Frontend Application Version", - "custom-app-title": "Custom Application Title", - "copyright-claim-title": "Copyright Claim", - "copyright-claim-text": "Copyright © 2020 - {{currentYear}} knecon AG (powered by IQSER)", - "end-user-license-title": "End User License Agreement", - "end-user-license-text": "The use of this product is subject to the terms of the Redaction End User Agreement, unless other specified therein.", - "3rd-party-title": "Reference to 3rd Party Licenses", - "licensing-details": "Licensing Details", - "licensed-to": "Licensed to", - "licensing-period": "Licensing Period", - "analyzed-pages": "Analyzed Pages", - "usage-details": "Usage Details", - "total-analyzed": "Total Analyzed Pages Since {{date}}", - "licensed-page-count": "Number of licensed pages", - "current-analyzed": "Analyzed Pages in Current Licensing Period", - "unlicensed-analyzed": "Unlicensed Analyzed Pages", - "email-report": "Email Report", - "email": { - "title": "License Report {{licenseCustomer}}", - "body": { - "analyzed": "Total Analyzed Pages in current license period: {{pages}}.", - "licensed": "Licensed Pages: {{pages}}." - } - }, - "chart": { - "licensed-total": "Licensed Total", - "cumulative": "Cumulative Pages", - "pages-per-month": "Pages per Month", - "total-pages": "Total Pages", - "legend": "Legend" - } - }, - "audit": "Audit", - "audit-screen": { - "table-header": { - "title": "{{length}} Logs" - }, - "table-col-names": { - "message": "Message", - "user": "User", - "date": "Date", - "category": "Category" - }, - "all-categories": "All Categories", - "all-users": "All Users", - "to": "to", - "no-data": { - "title": "No available logs." - } - }, - "pagination": { - "previous": "Prev", - "next": "Next" - }, - "configurations": "Configurations", - "smtp-config-screen": { - "title": "Configure SMTP Account", - "subtitle": "SMTP (Simple Mail Transfer Protocol) enables you to send your emails through the specified server settings.", - "actions": { - "save": "Save Configurations", - "test-connection": "Test Connection" - }, - "form": { - "host": "Host", - "host-placeholder": "SMTP Host", - "port": "Port", - "from": "From", - "from-placeholder": "Sender Email Address", - "from-display-name": "Name for Sender", - "from-display-name-placeholder": "Display Name for Sender Email Address", - "from-display-name-hint": "Info text regarding the name for sender.", - "reply-to": "Reply To", - "reply-to-placeholder": "Reply To Email Address", - "reply-to-display-name": "Name for Reply To", - "reply-to-display-name-placeholder": "Display Name for Reply To Email Address", - "envelope-from": "Envelope From", - "envelope-from-placeholder": "Sender Envelope Email Address", - "envelope-from-hint": "Info text regarding envelope from field.", - "ssl": "Enable SSL", - "starttls": "Enable StartTLS", - "auth": "Enable Authentication", - "change-credentials": "Change Credentials" - }, - "test": { - "success": "Test email was sent successfully!", - "error": "Test email could not be sent! Please revise the email address." - } - }, - "smtp-auth-config": { - "title": "Enable Authentication", - "form": { - "username": "Username", - "username-placeholder": "Login Username", - "password": "Password" - }, - "actions": { - "save": "Save Credentials", - "cancel": "Cancel" - } - }, - "default-colors": "Default Colors", - "default-colors-screen": { - "table-header": { - "title": "{{length}} Default Colors" - }, - "table-col-names": { - "key": "Type", - "color": "Color" - }, - "types": { - "defaultColor": "Default Color", - "requestAdd": "Request Add", - "requestRemove": "Request Remove", - "notRedacted": "Skipped", - "analysisColor": "Analysis", - "dictionaryRequestColor": "Dictionary Request", - "manualRedactionColor": "Manual Redaction", - "previewColor": "Preview", - "updatedColor": "Updated" - }, - "action": { - "edit": "Edit Color" - } - }, - "edit-color-dialog": { - "success": "Successfully updated color for {{color}}.", - "error": "Failed to update colors.", + "due-date": "Due Date", + "template": "Dossier Template" + }, + "errors": { + "project-already-exists": "Dossier with this name already exists!", + "generic": "Failed to save dossier" + }, + "actions": { "save": "Save", - "form": { - "color": "Color", - "color-placeholder": "Color" - } + "save-and-add-members": "Save and Edit Team" + } }, - "downloads-list": { - "table-header": { - "title": "{{length}} downloads" - }, - "no-data": { - "title": "No active downloads." - }, - "table-col-names": { - "name": "Name", - "size": "Size", - "type": "Type", - "date": "Date", - "status": "Status" - }, + "header": "Dossiers", + "edit": { + "action": "Edit Dossier" + }, + "delete": { + "action": "Delete Dossier", + "delete-failed": "Failed to delete dossier: {{projectName}}" + }, + "no-match": { + "title": "No dossiers match your current filters." + } + }, + "project-details": { + "title": "Dossier Details", + "dialog": { + "title": "Dossier Details", + "info": { + "file-count": "Number of files: {{fileCount}}" + }, + "actions": { + "reanalyse-project": "Analyze Dossier" + } + }, + "owner": "Owner", + "members": "Members", + "see-less": "See less", + "assign-members": "Assign Members", + "expand": "Show Details", + "collapse": "Hide Details" + }, + "dossier-dictionary-dialog": { + "title": "Dossier Dictionary", + "save-changes": "Save Changes", + "cancel": "cancel" + }, + "project-overview": { + "no-ocr": "No OCR", + "ocr-performed": "OCR was performed for this file.", + "no-data": { + "title": "There are no documents yet.", + "action": "Upload Document" + }, + "no-match": { + "title": "No documents match your current filters." + }, + "search": "Document name...", + "header-actions": { + "edit": "Edit", + "delete": "Delete", + "assign": "Assign Owner & Members", + "upload-document": "Upload Document", + "download-redacted-files": "Download Redacted Files" + }, + "ocr-file": "OCR Document", + "download-file": "Download", + "download-file-disabled": "Download is only permitted for approved files", + "under-approval": "For Approval", + "approve": "Approve", + "approve-disabled": "File can only be approved once it has been analysed with the latest dictionaries and all suggestions have been processed", + "under-review": "Under Review", + "upload-files": "Drag & Drop files anywhere", + "upload-files-btn": "Upload Files", + "new-rule": { + "label": "Outdated", + "toast": { + "message-project": "Reanalysis required: ", "actions": { - "delete": "Delete", - "download": "Download" + "reanalyse-all": "Analyze all", + "reanalyse-file": "Analyze this file", + "later": "Later" } + } }, - "digital-signature-screen": { - "title": "Digital Signature", - "no-data": { - "title": "No Digital Signature certificate is configured. For signing redacted documents please upload a PCKS.12 certificate.", - "action": "Upload Certificate" - }, - "reason": { - "label": "Reason", - "placeholder": "Reason" - }, - "certificate-name": { - "label": "Certificate Name", - "placeholder": "Certificate Name" - }, - "contact-info": { - "label": "Contact Information", - "placeholder": "Contact Information" - }, - "location": { - "label": "Location", - "placeholder": "Location" - }, - "password": { - "label": "Certificate Password/Key", - "placeholder": "Password" - }, - "action": { - "save": "Save Digital Signature", - "delete": "Delete Digital Signature", - "reset": "Reset", - "save-success": "Digital signature saved successfully", - "save-error": "Failed to save digital signature", - "certificate-not-valid-error": "Uploaded Certificate is not valid for signing PDFs. PCKS.12 format is required.", - "delete-success": "Digital signature removed. Redacted files will no longer be signed!", - "delete-error": "Failed to remove digital signature, please try again." + "report": { + "action": "Download redaction report" + }, + "assign": "Assign Reviewer", + "assign-me": "Assign To Me", + "table-header": { + "title": "{{length}} documents", + "bulk-select": "Toggle Selection" + }, + "table-col-names": { + "name": "Name", + "added-on": "Added", + "needs-work": "Workload", + "assigned-to": "Assigned to", + "pages": "Pages", + "status": "Status" + }, + "upload-error": "Failed to upload file: {{name}}", + "delete-file-error": "Failed to delete file: {{filename}}", + "delete-files-error": "Failed to delete files.", + "reanalyse": { + "action": "Analyze File" + }, + "delete": { + "action": "Delete File" + }, + "file-listing": { + "file-entry": { + "status": "Status: {{status}}", + "number-of-pages": "Number of pages: {{numberOfPages}}", + "number-of-analyses": "Analysis count: {{numberOfAnalyses}}", + "added": "Date added: {{added}}", + "last-updated": "Last updated: {{lastUpdated}}", + "file-pending": "Pending...", + "file-processing": "Processing", + "file-error": "Re-processing required" + } + }, + "project-details": { + "charts": { + "documents-in-project": "Documents in Dossier" + }, + "stats": { + "documents": "{{count}} documents", + "analysed-pages": "{{count}} pages", + "people": "{{count}} user(s)", + "created-on": "Created on {{date}}", + "due-date": "Due {{date}}" + }, + "dictionary": "Dossier Dictionary", + "description": "Description" + }, + "header": "Dossier Overview", + "no-project": "Requested dossier: {{projectId}} does not exist! Back to Dossier Listing. ", + "bulk": { + "delete": "Delete Documents", + "assign": "Assign Reviewer", + "reanalyse": "Analyze Documents", + "reanalyse-error-outdated": "Not all selected documents can be analyzed, some may not be assigned to you or are already analyzed." + }, + "reanalyse-project": { + "success": "Files scheduled for reanalysis.", + "error": "Failed to schedule files for reanalysis. Please try again." + } + }, + "file-preview": { + "delta": "Delta", + "redacted": "Preview", + "standard": "Standard", + "standard-tooltip": "Standard Workload view shows all hints, redactions, recommendations & suggestions. This view allows editing.", + "redacted-tooltip": "Redaction preview shows only redactions. Consider this a preview for the final redacted version. This view is only available if the file has no pending changes & doesn't require a reanalysis", + "delta-tooltip": "Delta View shows only the changes since last re-analysis. This view is only available if there is at least 1 change", + "no-data": { + "title": "There are no annotations on this page." + }, + "show-redacted-view": "Show Redacted Preview", + "cannot-show-redacted-view": "Redactions out of sync. Redacted Preview only available after reanalysis", + "reanalyse-notification": "This document was not processed with the latest rule/dictionary set. Analyze now to get updated annotations.", + "reanalyse-file": "File reanalysis in progress", + "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", + "select": "Select", + "jump-to-previous": "Jump to Previous", + "jump-to-next": "Jump to Next" + }, + "is-excluded": "Redaction is disabled for this document." }, - "stream-download": { - "abort": "You have an active download, closing this window will cause it to stop!", - "error": "Failed to download {{filename}}. Please try again ..." + "toggle-analysis": { + "enable": "Enable for redaction", + "disable": "Disable redaction", + "only-managers": "Enabling / disabling is permitted only for managers" }, - "roles": { - "RED_USER": "User", - "RED_MANAGER": "Manager", - "RED_USER_ADMIN": "Users Admin", - "RED_ADMIN": "Application Admin", - "NO_ROLE": "No role defined", - "INACTIVE": "Inactive", - "MANAGER_ADMIN": "Manager & Admin", - "REGULAR": "Regular" - }, - "file-attributes-csv-import": { - "title": "Select CSV columns to use as File Attributes", - "cancel": "Cancel", - "save": { - "label": "Save Attributes", - "success": "{{count}} File Attributes created successfully!", - "error": "Failed to create File Attributes!" + "reviewer": "Assigned to", + "unassigned": "Unassigned", + "assign-reviewer": "Assign Reviewer", + "cancel-assign-reviewer": "Cancel", + "save-assign-reviewer": "Save", + "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", + "exit-fullscreen": "Exit Full Screen (F)", + "quick-nav": { + "jump-first": "Jump to first annotation", + "jump-last": "Jump to last annotation" + } + }, + "annotation-actions": { + "message": { + "manual-redaction": { + "undo": { + "success": "Undo successful", + "error": "Failed to undo: {{error}}" }, - "delimiter": "Delimiter", - "delimiter-placeholder": ",", - "encoding": "Encoding", - "encoding-placeholder": "UTF-8", - "key-column": "Key Column", - "key-column-placeholder": "Select column...", - "parse-csv": "Parse CSV with new options", - "total-rows": "{{rows}} rows in total", - "available": "{{value}} available", - "selected": "{{value}} selected", - "csv-column": "CSV Column", - "csv-column-preview": "CSV Column Preview", - "no-hovered-column": "Preview CSV column by hovering the entry.", - "no-sample-data-for": "No sample data for {{column}}.", - "search": { - "placeholder": "Search by column name..." + "suggest": { + "success": "Redaction suggestion saved", + "error": "Failed to save redaction suggestion: {{error}}" }, - "table-header": { - "title": "{{length}} file attributes", - "actions": { - "remove-selected": "Remove Selected", - "read-only": "Make Read-only", - "enable-read-only": "Enable Read-only for all attributes", - "disable-read-only": "Disable Read-only for all attributes", - "type": "Type" - } + "add": { + "success": "Redaction added!", + "error": "Failed to save redaction: {{error}}" }, - "file": "File:", - "table-col-names": { - "name": "Name", - "type": "Type", - "read-only": "Read-Only", - "primary": "primary", - "primary-info-tooltip": "The value of the attribute set as primary shows up under the file name in the documents list." + "decline": { + "success": "Redaction suggestion declined!", + "error": "Failed to decline redaction: {{error}}" }, - "quick-activation": { - "all": "All", - "none": "None" + "approve": { + "success": "Redaction suggestion approved!", + "error": "Failed to approved redaction: {{error}}" }, - "action": { - "edit-name": "Edit Name", - "save-name": "Save", - "cancel-edit-name": "Cancel", - "remove": "Remove" + "request-remove": { + "success": "Requested to remove redaction!", + "error": "Failed to request removal of redaction: {{error}}" }, - "no-data": { - "title": "No file attributes defined. Select a column from the left panel to start defining file attributes." + "remove": { + "success": "Redaction removed!", + "error": "Failed to remove redaction: {{error}}" } + }, + "dictionary": { + "undo": { + "success": "Undo successful", + "error": "Failed to undo: {{error}}" + }, + "suggest": { + "success": "Suggestion for dictionary modification saved!", + "error": "Failed to save suggestion for dictionary modification: {{error}}" + }, + "add": { + "success": "Entry added to dictionary. Changes will be visible after reanalysis.", + "error": "Failed to add entry to dictionary: {{error}}" + }, + "decline": { + "success": "Dictionary suggestion declined.", + "error": "Failed to decline dictionary suggestion: {{error}}" + }, + "approve": { + "success": "Dictionary entry approved. Changes will be visible after reanalysis.", + "error": "Failed to approve dictionary entry: {{error}}" + }, + "request-remove": { + "success": "Requested to remove dictionary entry!", + "error": "Failed to request removal of dictionary entry: {{error}}" + }, + "remove": { + "success": "Dictionary entry removed!", + "error": "Failed to remove dictionary entry: {{error}}" + } + } }, - "download-includes": "Choose what is included at download:", - "download-type": { - "label": "{{length}} document versions", - "PREVIEW": "Preview PDF", - "ORIGINAL": "Optimized PDF", - "REDACTED": "Redacted PDF" + "force-redaction": { + "label": "Force Redaction" }, - "report-type": { - "label": "{{length}} report types", - "WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE": "Justification Appendix A1", - "WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE": "Justification Appendix A2", - "EXCEL_MULTI_FILE": "Excel (for all)", - "EXCEL_SINGLE_FILE": "Excel (per file)" + "accept-suggestion": { + "label": "Accept Suggestion", + "add-to-dict": "Approve and add to dictionary", + "remove-from-dict": "Approve and remove from dictionary", + "only-here": "Approve only here" + }, + "accept-recommendation": { + "label": "Accept Recommendation" + }, + "suggest-remove-annotation": "Remove or Suggest to remove this entry", + "suggest-remove-annotations": "Remove or Suggest to remove selected entries", + "reject-suggestion": "Reject Suggestion", + "remove-annotation": { + "suggest-remove-from-dict": "Suggest to remove from dictionary", + "suggest-only-here": "Suggest to remove only here", + "remove-from-dict": "Remove from dictionary", + "only-here": "Remove only here", + "false-positive": "False Positive" + }, + "remove": "Remove", + "undo": "Undo", + "reject": "Reject", + "hide": "Hide", + "show": "Show" + }, + "initials-avatar": { + "unassigned": "Unassigned", + "you": "You" + }, + "assign-file-owner": { + "dialog": { + "single-user": "Reviewer", + "title": "Manage File Reviewer", + "save": "Save", + "cancel": "Cancel" + } + }, + "assign-project-owner": { + "dialog": { + "single-user": "Owner", + "multi-user": "Review Team", + "title": "Manage Dossier Team", + "approvers": "Approvers", + "reviewers": "Reviewers", + "save": "Save Changes", + "cancel": "Cancel", + "search": "Search...", + "no-approvers": "No approvers yet.\nSelect from the list below.", + "no-reviewers": "No reviewers yet.\nSelect from the list below.", + "make-approver": "Make Approver" + } + }, + "project-member-guard": { + "access-denied": "You are not allowed to access that page." + }, + "comments": { + "comment": "{{count}} comment", + "comments": "{{count}} comments", + "add-comment": "Add a comment", + "hide-comments": "Hide", + "cancel": "Cancel" + }, + "UNPROCESSED": "Unprocessed", + "REPROCESS": "Processing", + "FULLREPROCESS": "Processing", + "PROCESSING": "Processing", + "OCR_PROCESSING": "OCR Processing", + "ERROR": "Re-processing required", + "UNASSIGNED": "Unassigned", + "UNDER_REVIEW": "Under Review", + "UNDER_APPROVAL": "Under Approval", + "APPROVED": "Approved", + "EXCLUDED": "Excluded", + "by": "by", + "efsa": "EFSA Approval", + "finished": "Finished", + "submitted": "Submitted", + "active": "Active", + "archived": "Archived", + "hint": "Hint", + "skipped": "Skipped", + "redaction": "Redaction", + "comment": "Comment", + "pending-analysis": "Pending Re-Analysis", + "suggestion": "Suggestion for redaction", + "dictionary": "Dictionary", + "type": "Type", + "content": "Reason", + "page": "Page", + "annotation": "Annotation", + "annotations": "Annotations", + "filter": { + "hint": "Hints only", + "redaction": "Redacted", + "suggestion": "Suggested Redaction", + "analysis": "Analysis required", + "none": "No Annotations", + "updated": "Updated", + "image": "Images" + }, + "filter-menu": { + "label": "Filter", + "filter-types": "Filter types", + "filter-options": "Filter options", + "with-comments": "Show only annotations with comments" + }, + "sorting": { + "recent": "Recent", + "oldest": "Oldest", + "alphabetically": "Alphabetically", + "number-of-pages": "Number of pages", + "number-of-analyses": "Number of analyses", + "custom": "Custom" + }, + "readonly-pill": "Read-only", + "group": { + "redactions": "Redaction Dictionaries", + "hints": "Hint Dictionaries" + }, + "annotation-type": { + "recommendation": "Recommendation", + "remove-only-here": "Pending removal ( only here )", + "add-dictionary": "Pending add to dictionary", + "remove-dictionary": "Pending remove from dictionary", + "suggestion-add-dictionary": "Suggested dictionary add", + "suggestion-force-redaction": "Suggestion force redaction", + "suggestion-remove-dictionary": "Suggested dictionary removal", + "suggestion-add": "Suggested redaction", + "suggestion-remove": "Suggested redaction removal", + "skipped": "Skipped", + "pending-analysis": "Pending Re-Analysis", + "hint": "Hint", + "redaction": "Redaction", + "manual-redaction": "Manual Redaction", + "declined-suggestion": "Declined Suggestion" + }, + "manual-annotation": { + "dialog": { + "header": { + "dictionary": "Add to dictionary", + "redaction": "Redaction", + "force": "Force Redaction", + "request-dictionary": "Request add to dictionary", + "request-redaction": "Request Redaction", + "false-positive": "Set false positive", + "request-false-positive": "Request false positive" + }, + "add-redaction": { + "success": "Redaction suggestion added!", + "failed": "Failed to add redaction: {{message}}" + }, + "actions": { + "save": "Save" + }, + "content": { + "text": "Selected text:", + "rectangle": "Custom Rectangle", + "dictionary": "Dictionary", + "reason": "Reason", + "reason-placeholder": "Select a reason ...", + "legalBasis": "Legal Basis", + "comment": "Comment" + } + }, + "approve-request": { + "success": "Request approved.", + "error": "Failed to approve request." + }, + "undo": { + "success": "Action undone.", + "error": "Failed to undo action." + }, + "redaction-request": { + "success": "Redaction requested.", + "error": "Failed to request redaction." + }, + "remove-redaction-request": { + "success": "Redaction removed.", + "error": "Failed to remove redaction." + }, + "redaction-add": { + "success": "Redaction added.", + "error": "Failed to add redaction." + } + }, + "remove-annotations-dialog": { + "remove-from-dictionary": { + "title": "Remove From Dictionary", + "question": "Following entries will be removed from their respective dictionaries:" + }, + "remove-only-here": { + "title": "Remove Redaction", + "question": "Following redactions will be removed only here:" + }, + "dictionary": "Dictionary", + "value": "Value", + "confirm": "Yes, proceed and remove!", + "deny": "Cancel" + }, + "confirmation-dialog": { + "assign-file-to-me": { + "title": "Re-assign reviewer", + "question": "This document is currently reviewed by someone else. Do you want to become the reviewer and assign yourself to this document?" + }, + "delete-file": { + "title": "Delete Document", + "question": "Do you wish to proceed?" + }, + "delete-project": { + "title": "Delete Dossier", + "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", + "column-header": "CSV Column Header", + "column-header-placeholder": "Enter CSV Column Header", + "read-only": "Make Read-Only", + "type": "Type", + "primary": "Set as Primary" + }, + "save": "Save Attribute" + }, + "file-attribute-types": { + "TEXT": "Free Text", + "NUMBER": "Number", + "DATE": "Date" + }, + "add-edit-dictionary": { + "title": { + "edit": "Edit {{name}} Dictionary", + "new": "Create Dictionary" + }, + "form": { + "name": "Dictionary Name", + "name-placeholder": "Enter Name", + "name-hint": "Cannot be edited after saving.", + "description": "Description", + "description-placeholder": "Enter Description", + "rank": "Rank", + "rank-placeholder": "1000", + "color": "Hex Color", + "color-placeholder": "#", + "redaction": "Redaction", + "hint": "Hint", + "case-sensitive": "Case Sensitive", + "add-to-dictionary-action": "Available for add to dictionary" + }, + "error": { + "dictionary-already-exists": "Dictionary with this name already exists!", + "invalid-color-or-rank": "Invalid color or rank! Rank is already used by another dictionary or the color is not a valid hexColor!", + "generic": "Failed to save dictionary!" + }, + "save": "Save Dictionary" + }, + "add-edit-project-template": { + "title": { + "edit": "Edit {{name}} Dossier Template", + "new": "Create Dossier Template" + }, + "form": { + "name": "Dossier Template Name", + "name-placeholder": "Enter Name", + "description": "Description", + "description-placeholder": "Enter Description", + "valid-from": "Valid from", + "valid-to": "Valid to" + }, + "save": "Save Dossier Template" + }, + "dictionary-overview": { + "action": { + "delete": "Delete Dictionary", + "edit": "Edit Dictionary", + "download": "Download Dictionary", + "upload": "Upload Dictionary" + }, + "error": { + "entries-too-short": "Some entries of the dictionary are below the minimum length of 2. These are highlighted with red!", + "generic": "Something went wrong... Dictionary update failed!" + }, + "success": { + "generic": "Dictionary updated!" + }, + "search": "Search...", + "save-changes": "Save Changes", + "revert-changes": "Revert", + "dictionary-details": { + "description": "Description" + }, + "compare": { + "compare": "Compare", + "select-ruleset": "Select Dossier Template", + "select-dictionary": "Select Dictionary" + }, + "select-dictionary": "Select a dictionary above to compare with the current one." + }, + "dictionary-listing": { + "action": { + "delete": "Delete Dictionary", + "edit": "Edit Dictionary" + }, + "case-sensitive": "Case Sensitive", + "add-new": "New Dictionary", + "stats": { + "charts": { + "types": "Types", + "entries": "Entries" + } + }, + "table-header": { + "title": "{{length}} dictionaries" + }, + "table-col-names": { + "type": "Type", + "order-of-importance": "Order Of Importance", + "hint-redaction": "Hint/Redaction" + }, + "search": "Search...", + "no-data": { + "title": "There are no dictionaries yet.", + "action": "New Dictionary" + }, + "no-match": { + "title": "No dictionaries match your current filters." + } + }, + "digital-signature": "Digital Signature", + "project-templates": "Dossier Templates", + "settings": "Settings", + "project-templates-listing": { + "table-header": { + "title": "{{length}} dossier templates" + }, + "entries": "{{length}} entries", + "dictionaries": "{{length}} dictionaries", + "action": { + "delete": "Delete Template", + "edit": "Edit Template" + }, + "add-new": "New Dossier Template", + "search": "Search...", + "table-col-names": { + "name": "Name", + "created-by": "Created by", + "created-on": "Created on", + "modified-on": "Modified on" + }, + "no-data": { + "title": "There are no dossier templates yet." + }, + "no-match": { + "title": "No dossier templates match your current filters." + } + }, + "file-attributes-listing": { + "search": "Search by attribute name...", + "add-new": "New Attribute", + "table-header": { + "title": "{{length}} file attributes" + }, + "bulk-actions": { + "delete": "Delete Selected Attributes" + }, + "table-col-names": { + "name": "Name", + "type": "Input Type", + "read-only": "Read-Only", + "csv-column": "CSV Column", + "primary": "Primary", + "primary-info-tooltip": "The value of the attribute set as primary shows up under the file name in the documents list." + }, + "no-data": { + "title": "There are no file attributes yet." + }, + "no-match": { + "title": "No file attributes match your current filters." + }, + "read-only": "Read-only", + "action": { + "edit": "Edit Attribute", + "delete": "Delete Attribute" + }, + "upload-csv": "Upload File Attributes Configuration" + }, + "confirm-delete-file-attribute": { + "title": { + "single": "Delete {{name}}", + "bulk": "Delete File Attributes" + }, + "warning": "Warning: this cannot be undone!", + "delete": { + "single": "Delete Attribute", + "bulk": "Delete Attributes" + }, + "cancel": { + "single": "Keep Attribute", + "bulk": "Keep Attributes" + }, + "impacted-documents": { + "single": "All documents it is used on will be impacted", + "bulk": "All documents they are used on will be impacted" + }, + "lost-details": "All inputted details on the documents will be lost", + "toast-error": "Please confirm that you understand the ramifications of your action!" + }, + "confirm-delete-users": { + "title": { + "single": "Delete User from Workspace", + "bulk": "Delete Users from Workspace" + }, + "warning": "Warning: this cannot be undone!", + "impacted-projects": "{{projectsCount}} dossiers will be impacted", + "impacted-documents": { + "single": "All documents pending review from the user will be impacted", + "bulk": "All documents pending review from the users will be impacted" + }, + "delete": { + "single": "Delete User", + "bulk": "Delete Users" + }, + "cancel": { + "single": "Keep User", + "bulk": "Keep Users" + }, + "toast-error": "Please confirm that you understand the ramifications of your action!" + }, + "document-info": { + "title": "Introduce File Attributes", + "save": "Save Document Info", + "save-approval": "Save and Send for Approval" + }, + "user-profile": { + "title": "My profile", + "form": { + "email": "Email", + "first-name": "First name", + "last-name": "Last name" }, "actions": { - "all": "All", - "none": "None" + "save": "Save profile" } + }, + "user-listing": { + "table-header": { + "title": "{{length}} users" + }, + "table-col-names": { + "name": "Name", + "email": "Email", + "active": "Active", + "roles": "Roles" + }, + "action": { + "edit": "Edit User", + "delete": "Delete User" + }, + "bulk": { + "delete": "Delete Users", + "delete-disabled": "You cannot delete your own account." + }, + "search": "Search...", + "add-new": "New User", + "no-match": { + "title": "No users match your current filters." + } + }, + "add-edit-user": { + "title": { + "new": "Add New User", + "edit": "Edit User" + }, + "form": { + "first-name": "First Name", + "last-name": "Last Name", + "email": "Email", + "role": "Role" + }, + "actions": { + "save": "Save User", + "save-changes": "Save Changes", + "delete": "Delete User", + "cancel": "Cancel" + } + }, + "user-stats": { + "title": "Users", + "chart": { + "users": "Users in Workspace" + }, + "expand": "Show Details", + "collapse": "Hide Details" + }, + "rules-screen": { + "error": { + "generic": "Something went wrong... Rules update failed!" + }, + "success": { + "generic": "Rules updated!" + }, + "action": { + "download": "Download Rules", + "upload": "Upload Rules" + }, + "save-changes": "Save Changes", + "revert-changes": "Revert" + }, + "watermark-screen": { + "form": { + "text-placeholder": "Enter text", + "opacity": "Opacity", + "color": "Color", + "font-size": "Font Size", + "font-type": "Font Type", + "orientation": "Orientation" + }, + "action": { + "save": "Save Changes", + "revert": "Revert", + "change-success": "Watermark updated!", + "delete-success": "Watermark deleted.", + "error": "Failed to update Watermark" + }, + "title": "Watermark" + }, + "dictionaries": "Dictionaries", + "user-management": "User Management", + "license-information": "License Information", + "notifications": { + "today": "Today", + "yesterday": "Yesterday", + "tomorrow": "Tomorrow", + "mark-read": "Mark as read", + "mark-unread": "Mark as unread" + }, + "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": { + "title": "Document already exists!", + "question": "{{filename}} already exists. Choose how to proceed:", + "options": { + "overwrite": "Replace existing document", + "skip": "Keep existing document", + "cancel": "Cancel all uploads", + "remember": "Remember choice and don't ask me again" + } + }, + "license-info-screen": { + "backend-version": "Backend Application Version", + "frontend-version": "Frontend Application Version", + "custom-app-title": "Custom Application Title", + "copyright-claim-title": "Copyright Claim", + "copyright-claim-text": "Copyright © 2020 - {{currentYear}} knecon AG (powered by IQSER)", + "end-user-license-title": "End User License Agreement", + "end-user-license-text": "The use of this product is subject to the terms of the Redaction End User Agreement, unless other specified therein.", + "3rd-party-title": "Reference to 3rd Party Licenses", + "licensing-details": "Licensing Details", + "licensed-to": "Licensed to", + "licensing-period": "Licensing Period", + "analyzed-pages": "Analyzed Pages", + "usage-details": "Usage Details", + "total-analyzed": "Total Analyzed Pages Since {{date}}", + "licensed-page-count": "Number of licensed pages", + "current-analyzed": "Analyzed Pages in Current Licensing Period", + "unlicensed-analyzed": "Unlicensed Analyzed Pages", + "email-report": "Email Report", + "email": { + "title": "License Report {{licenseCustomer}}", + "body": { + "analyzed": "Total Analyzed Pages in current license period: {{pages}}.", + "licensed": "Licensed Pages: {{pages}}." + } + }, + "chart": { + "licensed-total": "Licensed Total", + "cumulative": "Cumulative Pages", + "pages-per-month": "Pages per Month", + "total-pages": "Total Pages", + "legend": "Legend" + } + }, + "audit": "Audit", + "audit-screen": { + "table-header": { + "title": "{{length}} Logs" + }, + "table-col-names": { + "message": "Message", + "user": "User", + "date": "Date", + "category": "Category" + }, + "all-categories": "All Categories", + "all-users": "All Users", + "to": "to", + "no-data": { + "title": "No available logs." + } + }, + "pagination": { + "previous": "Prev", + "next": "Next" + }, + "configurations": "Configurations", + "smtp-config-screen": { + "title": "Configure SMTP Account", + "subtitle": "SMTP (Simple Mail Transfer Protocol) enables you to send your emails through the specified server settings.", + "actions": { + "save": "Save Configurations", + "test-connection": "Test Connection" + }, + "form": { + "host": "Host", + "host-placeholder": "SMTP Host", + "port": "Port", + "from": "From", + "from-placeholder": "Sender Email Address", + "from-display-name": "Name for Sender", + "from-display-name-placeholder": "Display Name for Sender Email Address", + "from-display-name-hint": "Info text regarding the name for sender.", + "reply-to": "Reply To", + "reply-to-placeholder": "Reply To Email Address", + "reply-to-display-name": "Name for Reply To", + "reply-to-display-name-placeholder": "Display Name for Reply To Email Address", + "envelope-from": "Envelope From", + "envelope-from-placeholder": "Sender Envelope Email Address", + "envelope-from-hint": "Info text regarding envelope from field.", + "ssl": "Enable SSL", + "starttls": "Enable StartTLS", + "auth": "Enable Authentication", + "change-credentials": "Change Credentials" + }, + "test": { + "success": "Test email was sent successfully!", + "error": "Test email could not be sent! Please revise the email address." + } + }, + "smtp-auth-config": { + "title": "Enable Authentication", + "form": { + "username": "Username", + "username-placeholder": "Login Username", + "password": "Password" + }, + "actions": { + "save": "Save Credentials", + "cancel": "Cancel" + } + }, + "default-colors": "Default Colors", + "default-colors-screen": { + "table-header": { + "title": "{{length}} Default Colors" + }, + "table-col-names": { + "key": "Type", + "color": "Color" + }, + "types": { + "defaultColor": "Default Color", + "requestAdd": "Request Add", + "requestRemove": "Request Remove", + "notRedacted": "Skipped", + "analysisColor": "Analysis", + "dictionaryRequestColor": "Dictionary Request", + "manualRedactionColor": "Manual Redaction", + "previewColor": "Preview", + "updatedColor": "Updated" + }, + "action": { + "edit": "Edit Color" + } + }, + "edit-color-dialog": { + "success": "Successfully updated color for {{color}}.", + "error": "Failed to update colors.", + "save": "Save", + "form": { + "color": "Color", + "color-placeholder": "Color" + } + }, + "downloads-list": { + "table-header": { + "title": "{{length}} downloads" + }, + "no-data": { + "title": "No active downloads." + }, + "table-col-names": { + "name": "Name", + "size": "Size", + "type": "Type", + "date": "Date", + "status": "Status" + }, + "actions": { + "delete": "Delete", + "download": "Download" + } + }, + "digital-signature-screen": { + "title": "Digital Signature", + "no-data": { + "title": "No Digital Signature certificate is configured. For signing redacted documents please upload a PCKS.12 certificate.", + "action": "Upload Certificate" + }, + "reason": { + "label": "Reason", + "placeholder": "Reason" + }, + "certificate-name": { + "label": "Certificate Name", + "placeholder": "Certificate Name" + }, + "contact-info": { + "label": "Contact Information", + "placeholder": "Contact Information" + }, + "location": { + "label": "Location", + "placeholder": "Location" + }, + "password": { + "label": "Certificate Password/Key", + "placeholder": "Password" + }, + "action": { + "save": "Save Digital Signature", + "delete": "Delete Digital Signature", + "reset": "Reset", + "save-success": "Digital signature saved successfully", + "save-error": "Failed to save digital signature", + "certificate-not-valid-error": "Uploaded Certificate is not valid for signing PDFs. PCKS.12 format is required.", + "delete-success": "Digital signature removed. Redacted files will no longer be signed!", + "delete-error": "Failed to remove digital signature, please try again." + } + }, + "stream-download": { + "abort": "You have an active download, closing this window will cause it to stop!", + "error": "Failed to download {{filename}}. Please try again ..." + }, + "roles": { + "RED_USER": "User", + "RED_MANAGER": "Manager", + "RED_USER_ADMIN": "Users Admin", + "RED_ADMIN": "Application Admin", + "NO_ROLE": "No role defined", + "INACTIVE": "Inactive", + "MANAGER_ADMIN": "Manager & Admin", + "REGULAR": "Regular" + }, + "file-attributes-csv-import": { + "title": "Select CSV columns to use as File Attributes", + "cancel": "Cancel", + "save": { + "label": "Save Attributes", + "success": "{{count}} File Attributes created successfully!", + "error": "Failed to create File Attributes!" + }, + "delimiter": "Delimiter", + "delimiter-placeholder": ",", + "encoding": "Encoding", + "encoding-placeholder": "UTF-8", + "key-column": "Key Column", + "key-column-placeholder": "Select column...", + "parse-csv": "Parse CSV with new options", + "total-rows": "{{rows}} rows in total", + "available": "{{value}} available", + "selected": "{{value}} selected", + "csv-column": "CSV Column", + "csv-column-preview": "CSV Column Preview", + "no-hovered-column": "Preview CSV column by hovering the entry.", + "no-sample-data-for": "No sample data for {{column}}.", + "search": { + "placeholder": "Search by column name..." + }, + "table-header": { + "title": "{{length}} file attributes", + "actions": { + "remove-selected": "Remove Selected", + "read-only": "Make Read-only", + "enable-read-only": "Enable Read-only for all attributes", + "disable-read-only": "Disable Read-only for all attributes", + "type": "Type" + } + }, + "file": "File:", + "table-col-names": { + "name": "Name", + "type": "Type", + "read-only": "Read-Only", + "primary": "primary", + "primary-info-tooltip": "The value of the attribute set as primary shows up under the file name in the documents list." + }, + "quick-activation": { + "all": "All", + "none": "None" + }, + "action": { + "edit-name": "Edit Name", + "save-name": "Save", + "cancel-edit-name": "Cancel", + "remove": "Remove" + }, + "no-data": { + "title": "No file attributes defined. Select a column from the left panel to start defining file attributes." + } + }, + "download-includes": "Choose what is included at download:", + "download-type": { + "label": "{{length}} document versions", + "PREVIEW": "Preview PDF", + "ORIGINAL": "Optimized PDF", + "REDACTED": "Redacted PDF" + }, + "report-type": { + "label": "{{length}} report types", + "WORD_SINGLE_FILE_APPENDIX_A1_TEMPLATE": "Justification Appendix A1", + "WORD_SINGLE_FILE_APPENDIX_A2_TEMPLATE": "Justification Appendix A2", + "EXCEL_MULTI_FILE": "Excel (for all)", + "EXCEL_SINGLE_FILE": "Excel (per file)" + }, + "actions": { + "all": "All", + "none": "None" + } } diff --git a/apps/red-ui/src/environments/environment.prod.ts b/apps/red-ui/src/environments/environment.prod.ts index 244865992..e3dce0fb3 100644 --- a/apps/red-ui/src/environments/environment.prod.ts +++ b/apps/red-ui/src/environments/environment.prod.ts @@ -1,5 +1,6 @@ export const environment = { production: true, licenseKey: - 'S25lY29uIEFHKGVuLmtuZWNvbi5zd2lzcyk6T0VNOkREQS1SOjpCKzpBTVMoMjAyMTEwMjkpOkNGQ0MwRDMzMDdEQUI0RjM0QjMxM0JDOUIyNDMzODJDNEU2RjZGQ0I4M0NEOEFDNTc0MzU4QTk1OTczMEI2MjJGQUJFRjVDNw==' + 'S25lY29uIEFHKGVuLmtuZWNvbi5zd2lzcyk6T0VNOkREQS1SOjpCKzpBTVMoMjAyMTEwMjkpOkNGQ0MwRDMzMDd' + + 'EQUI0RjM0QjMxM0JDOUIyNDMzODJDNEU2RjZGQ0I4M0NEOEFDNTc0MzU4QTk1OTczMEI2MjJGQUJFRjVDNw==' }; diff --git a/apps/red-ui/src/environments/environment.ts b/apps/red-ui/src/environments/environment.ts index df8fb0275..5291f9fe4 100644 --- a/apps/red-ui/src/environments/environment.ts +++ b/apps/red-ui/src/environments/environment.ts @@ -1,5 +1,6 @@ export const environment = { production: false, licenseKey: - 'S25lY29uIEFHKGVuLmtuZWNvbi5zd2lzcyk6T0VNOkREQS1SOjpCKzpBTVMoMjAyMTEwMjkpOkNGQ0MwRDMzMDdEQUI0RjM0QjMxM0JDOUIyNDMzODJDNEU2RjZGQ0I4M0NEOEFDNTc0MzU4QTk1OTczMEI2MjJGQUJFRjVDNw==' + 'S25lY29uIEFHKGVuLmtuZWNvbi5zd2lzcyk6T0VNOkREQS1SOjpCKzpBTVMoMjAyMTEwMjkpOkNGQ0MwRDMzMDd' + + 'EQUI0RjM0QjMxM0JDOUIyNDMzODJDNEU2RjZGQ0I4M0NEOEFDNTc0MzU4QTk1OTczMEI2MjJGQUJFRjVDNw==' }; diff --git a/apps/red-ui/src/polyfills.ts b/apps/red-ui/src/polyfills.ts index e49856ec9..68ea94dde 100644 --- a/apps/red-ui/src/polyfills.ts +++ b/apps/red-ui/src/polyfills.ts @@ -41,9 +41,12 @@ * * The following flags will work for all browsers. * - * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame - * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick - * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + * // disable patch requestAnimationFrame + * (window as any).__Zone_disable_requestAnimationFrame = true; + * // disable patch onProperty such as onclick + * (window as any).__Zone_disable_on_property = true; + * // disable patch specified eventNames + * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; * * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js * with the following flag, it will bypass `zone.js` patch for IE/Edge diff --git a/apps/red-ui/tsconfig.app.json b/apps/red-ui/tsconfig.app.json index 8289972bc..e9fa6dfd9 100644 --- a/apps/red-ui/tsconfig.app.json +++ b/apps/red-ui/tsconfig.app.json @@ -1,8 +1,8 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [] - }, - "files": ["src/main.ts", "src/polyfills.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [] + }, + "files": ["src/main.ts", "src/polyfills.ts"] } diff --git a/apps/red-ui/tsconfig.eslint.json b/apps/red-ui/tsconfig.eslint.json index 9db49faab..56fd56806 100644 --- a/apps/red-ui/tsconfig.eslint.json +++ b/apps/red-ui/tsconfig.eslint.json @@ -1,4 +1,4 @@ { - "extends": "./tsconfig.json", - "include": ["src/**/*.ts"] + "extends": "./tsconfig.json", + "include": ["src/**/*.ts"] } diff --git a/apps/red-ui/tsconfig.json b/apps/red-ui/tsconfig.json index e23d75a22..63dbe35fb 100644 --- a/apps/red-ui/tsconfig.json +++ b/apps/red-ui/tsconfig.json @@ -1,13 +1,13 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - } - ] + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] } diff --git a/apps/red-ui/tsconfig.spec.json b/apps/red-ui/tsconfig.spec.json index 26a878ced..cfff29a54 100644 --- a/apps/red-ui/tsconfig.spec.json +++ b/apps/red-ui/tsconfig.spec.json @@ -1,10 +1,10 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts"] } diff --git a/cypress.env.json b/cypress.env.json index 47db238c1..4d776336f 100644 --- a/cypress.env.json +++ b/cypress.env.json @@ -1,13 +1,13 @@ { - "reporter": "junit", - "baseUrl": "http://localhost:4200", - "env": { - "api_url": "https://timo-redaction-dev.iqser.cloud", - "auth_base_url": "https://redkc-staging.iqser.cloud/auth", - "auth_realm": "redaction", - "auth_client_id": "redaction" - }, - "reporterOptions": { - "mochaFile": "cypress/test-reports/test-[hash].xml" - } + "reporter": "junit", + "baseUrl": "http://localhost:4200", + "env": { + "api_url": "https://timo-redaction-dev.iqser.cloud", + "auth_base_url": "https://redkc-staging.iqser.cloud/auth", + "auth_realm": "redaction", + "auth_client_id": "redaction" + }, + "reporterOptions": { + "mochaFile": "cypress/test-reports/test-[hash].xml" + } } diff --git a/cypress.json b/cypress.json index ab2b572e4..68104c293 100644 --- a/cypress.json +++ b/cypress.json @@ -1,13 +1,13 @@ { - "reporter": "junit", - "baseUrl": "https://app-ui-automated.iqser.cloud", - "env": { - "api_url": "https://api-ui-automated.iqser.cloud", - "auth_base_url": "https://keycloak-ui-automated.iqser.cloud/auth", - "auth_realm": "redaction", - "auth_client_id": "redaction" - }, - "reporterOptions": { - "mochaFile": "cypress/test-reports/test-[hash].xml" - } + "reporter": "junit", + "baseUrl": "https://app-ui-automated.iqser.cloud", + "env": { + "api_url": "https://api-ui-automated.iqser.cloud", + "auth_base_url": "https://keycloak-ui-automated.iqser.cloud/auth", + "auth_realm": "redaction", + "auth_client_id": "redaction" + }, + "reporterOptions": { + "mochaFile": "cypress/test-reports/test-[hash].xml" + } } diff --git a/libs/red-cache/.eslintrc.json b/libs/red-cache/.eslintrc.json index 95e9d0d25..34f0525ad 100644 --- a/libs/red-cache/.eslintrc.json +++ b/libs/red-cache/.eslintrc.json @@ -1,37 +1,41 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": ["plugin:@nrwl/nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], - "parserOptions": { - "project": ["libs/red-cache/tsconfig.*?.json"] - }, - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "redaction", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "redaction", - "style": "kebab-case" - } - ] - }, - "plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nrwl/nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nrwl/nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "parserOptions": { + "project": ["libs/red-cache/tsconfig.*?.json"] + }, + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "redaction", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "redaction", + "style": "kebab-case" + } + ], + "max-len": "off" + }, + "plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nrwl/nx/angular-template"], + "rules": {} + } + ] } diff --git a/libs/red-cache/tsconfig.json b/libs/red-cache/tsconfig.json index 1e5701a22..62ebbd946 100644 --- a/libs/red-cache/tsconfig.json +++ b/libs/red-cache/tsconfig.json @@ -1,13 +1,13 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ] + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] } diff --git a/libs/red-cache/tsconfig.lib.json b/libs/red-cache/tsconfig.lib.json index 8334eb341..d5befaafb 100644 --- a/libs/red-cache/tsconfig.lib.json +++ b/libs/red-cache/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts"], + "include": ["**/*.ts"] } diff --git a/libs/red-cache/tsconfig.spec.json b/libs/red-cache/tsconfig.spec.json index 26a878ced..cfff29a54 100644 --- a/libs/red-cache/tsconfig.spec.json +++ b/libs/red-cache/tsconfig.spec.json @@ -1,10 +1,10 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts"] } diff --git a/libs/red-ui-http/.eslintrc.json b/libs/red-ui-http/.eslintrc.json index a0318568d..086670f3a 100644 --- a/libs/red-ui-http/.eslintrc.json +++ b/libs/red-ui-http/.eslintrc.json @@ -1,42 +1,46 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": ["plugin:@nrwl/nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], - "parserOptions": { - "project": ["libs/red-ui-http/tsconfig.*?.json"] - }, - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "redaction", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "redaction", - "style": "kebab-case" - } - ], - "@typescript-eslint/no-namespace": "off", - "@typescript-eslint/no-inferrable-types": "off", - "@typescript-eslint/explicit-member-accessibility": "off", - "@typescript-eslint/naming-convention": "off", - "no-control-regex": "off" - }, - "plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nrwl/nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": [ + "plugin:@nrwl/nx/angular", + "plugin:@angular-eslint/template/process-inline-templates" + ], + "parserOptions": { + "project": ["libs/red-ui-http/tsconfig.*?.json"] + }, + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "redaction", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "redaction", + "style": "kebab-case" + } + ], + "@typescript-eslint/no-namespace": "off", + "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/explicit-member-accessibility": "off", + "@typescript-eslint/naming-convention": "off", + "no-control-regex": "off", + "max-len": "off" + }, + "plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nrwl/nx/angular-template"], + "rules": {} + } + ] } diff --git a/libs/red-ui-http/ng-package.json b/libs/red-ui-http/ng-package.json index e5fbba5fa..f29047cf7 100644 --- a/libs/red-ui-http/ng-package.json +++ b/libs/red-ui-http/ng-package.json @@ -1,7 +1,7 @@ { - "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", - "dest": "../../dist/libs/red-ui-http", - "lib": { - "entryFile": "src/index.ts" - } + "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", + "dest": "../../dist/libs/red-ui-http", + "lib": { + "entryFile": "src/index.ts" + } } diff --git a/libs/red-ui-http/package.json b/libs/red-ui-http/package.json index 3f157248b..fe8f1348b 100644 --- a/libs/red-ui-http/package.json +++ b/libs/red-ui-http/package.json @@ -1,8 +1,8 @@ { - "name": "@redaction/red-ui-http", - "version": "1.1", - "peerDependencies": { - "@angular/common": "^7.2.0", - "@angular/core": "^7.2.0" - } + "name": "@redaction/red-ui-http", + "version": "1.1", + "peerDependencies": { + "@angular/common": "^7.2.0", + "@angular/core": "^7.2.0" + } } diff --git a/libs/red-ui-http/tsconfig.json b/libs/red-ui-http/tsconfig.json index 1e5701a22..62ebbd946 100644 --- a/libs/red-ui-http/tsconfig.json +++ b/libs/red-ui-http/tsconfig.json @@ -1,13 +1,13 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ] + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] } diff --git a/libs/red-ui-http/tsconfig.lib.json b/libs/red-ui-http/tsconfig.lib.json index 68536f23b..6d38c126a 100644 --- a/libs/red-ui-http/tsconfig.lib.json +++ b/libs/red-ui-http/tsconfig.lib.json @@ -1,18 +1,18 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts"], + "include": ["**/*.ts"] } diff --git a/nx.json b/nx.json index 8036349b0..8b9c0489f 100644 --- a/nx.json +++ b/nx.json @@ -1,18 +1,35 @@ { - "implicitDependencies": { - "workspace.json": "*", - "package.json": { - "dependencies": "*", - "devDependencies": "*" - }, - "tsconfig.base.json": "*", - "tslint.json": "*", - "nx.json": "*" + "implicitDependencies": { + "workspace.json": "*", + "package.json": { + "dependencies": "*", + "devDependencies": "*" }, - "affected": { "defaultBase": "master" }, - "npmScope": "redaction", - "tasksRunnerOptions": { - "default": { "runner": "@nrwl/workspace/tasks-runners/default", "options": { "cacheableOperations": ["build", "lint", "test", "e2e"] } } + "tsconfig.base.json": "*", + "tslint.json": "*", + "nx.json": "*" + }, + "affected": { + "defaultBase": "master" + }, + "npmScope": "redaction", + "tasksRunnerOptions": { + "default": { + "runner": "@nrwl/workspace/tasks-runners/default", + "options": { + "cacheableOperations": ["build", "lint", "test", "e2e"] + } + } + }, + "projects": { + "red-ui": { + "tags": [] }, - "projects": { "red-ui": { "tags": [] }, "red-ui-http": { "tags": [] }, "red-cache": { "tags": [] } } + "red-ui-http": { + "tags": [] + }, + "red-cache": { + "tags": [] + } + } } diff --git a/tsconfig.base.json b/tsconfig.base.json index 31fcd116e..e033abefc 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,41 +1,41 @@ { - "compileOnSave": false, - "compilerOptions": { - "rootDir": ".", - "resolveJsonModule": true, - "sourceMap": true, - "declaration": false, - "moduleResolution": "node", - "emitDecoratorMetadata": true, - "experimentalDecorators": true, - "importHelpers": true, - "target": "es2015", - "module": "esnext", - "typeRoots": ["node_modules/@types"], - "lib": ["es2019", "dom"], - "skipLibCheck": true, - "skipDefaultLibCheck": true, - "baseUrl": ".", - "paths": { - "@redaction/red-ui-http": ["libs/red-ui-http/src/index.ts"], - "@redaction/red-cache": ["libs/red-cache/src/index.ts"], - "@services/*": ["apps/red-ui/src/app/services/*"], - "@components/*": ["apps/red-ui/src/app/components/*"], - "@guards/*": ["apps/red-ui/src/app/guards/*"], - "@i18n/*": ["apps/red-ui/src/app/i18n/*"], - "@state/*": ["apps/red-ui/src/app/state/*"], - "@utils/*": ["apps/red-ui/src/app/utils/*"], - "@models/*": ["apps/red-ui/src/app/models/*"], - "@environments/*": ["apps/red-ui/src/environments/*"], - "@shared/*": ["apps/red-ui/src/app/modules/shared/*"], - "@app-config/*": ["apps/red-ui/src/app/modules/app-config/*"], - "@upload-download/*": ["apps/red-ui/src/app/modules/upload-download/*"] - } - }, - "exclude": ["node_modules", "tmp"], - "angularCompilerOptions": { - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true + "compileOnSave": false, + "compilerOptions": { + "rootDir": ".", + "resolveJsonModule": true, + "sourceMap": true, + "declaration": false, + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "importHelpers": true, + "target": "es2015", + "module": "esnext", + "typeRoots": ["node_modules/@types"], + "lib": ["es2019", "dom"], + "skipLibCheck": true, + "skipDefaultLibCheck": true, + "baseUrl": ".", + "paths": { + "@redaction/red-ui-http": ["libs/red-ui-http/src/index.ts"], + "@redaction/red-cache": ["libs/red-cache/src/index.ts"], + "@services/*": ["apps/red-ui/src/app/services/*"], + "@components/*": ["apps/red-ui/src/app/components/*"], + "@guards/*": ["apps/red-ui/src/app/guards/*"], + "@i18n/*": ["apps/red-ui/src/app/i18n/*"], + "@state/*": ["apps/red-ui/src/app/state/*"], + "@utils/*": ["apps/red-ui/src/app/utils/*"], + "@models/*": ["apps/red-ui/src/app/models/*"], + "@environments/*": ["apps/red-ui/src/environments/*"], + "@shared/*": ["apps/red-ui/src/app/modules/shared/*"], + "@app-config/*": ["apps/red-ui/src/app/modules/app-config/*"], + "@upload-download/*": ["apps/red-ui/src/app/modules/upload-download/*"] } + }, + "exclude": ["node_modules", "tmp"], + "angularCompilerOptions": { + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } }