Merge branch 'master' into VM/RED-2614

This commit is contained in:
Valentin 2022-01-18 16:54:50 +02:00
commit d30c270d72
25 changed files with 107 additions and 1161 deletions

View File

@ -109,7 +109,7 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent {
let technicalName = baseTechnicalName;
let suffix = 1;
while (existingTechnicalNames.includes(technicalName)) {
technicalName = [baseTechnicalName, suffix++].join('-');
technicalName = [baseTechnicalName, suffix++].join('_');
}
return technicalName;
}

View File

@ -99,6 +99,9 @@ export class ReportsScreenComponent implements OnInit {
question: _('confirmation-dialog.report-template-same-name.question'),
confirmationText: _('confirmation-dialog.report-template-same-name.confirmation-text'),
denyText: _('confirmation-dialog.report-template-same-name.deny-text'),
translateParams: {
fileName: file.name,
},
});
this._dialogService.openDialog('confirm', null, data, null, async result => {

View File

@ -11,7 +11,7 @@
</div>
<form [formGroup]="form" *ngIf="form">
<div class="iqser-input-group" *ngIf="canEdit">
<div class="iqser-input-group">
<mat-checkbox color="primary" formControlName="addToDictionaryAction" name="addToDictionaryAction">
{{ 'add-edit-dictionary.form.add-to-dictionary-action' | translate }}
</mat-checkbox>

View File

@ -7,7 +7,7 @@ import { DictionaryService } from '@shared/services/dictionary.service';
import { CircleButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FormBuilder, FormGroup } from '@angular/forms';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
selector: 'redaction-edit-dossier-dictionary',
@ -116,7 +116,12 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
private _getForm(): FormGroup {
return this._formBuilder.group({
addToDictionaryAction: [this.dossierDictionary.addToDictionaryAction],
addToDictionaryAction: [
{
value: this.dossierDictionary.addToDictionaryAction,
disabled: !this._permissionsService.isOwner(this.dossier),
},
],
});
}

View File

@ -38,10 +38,10 @@ export class DossiersListingDetailsComponent {
private async _toDossierChartData(dossiers: Dossier[]): Promise<DoughnutChartConfig[]> {
// TODO: deleted dossiers count should come with stats
const deletedDossiers = await this.dossiersService.getDeleted();
// const deletedDossiers = await this.dossiersService.getDeleted();
return [
{ value: dossiers.length, color: 'ACTIVE', label: _('active') },
{ value: deletedDossiers.length, color: 'DELETED', label: _('archived') },
// { value: deletedDossiers.length, color: 'DELETED', label: _('archived') },
];
}

View File

@ -161,7 +161,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
this.instance,
this.file,
() => {
this.viewModeService.set('COMPARE');
this.viewModeService.compareMode = true;
},
() => {
this.utils.navigateToPage(1);
@ -198,7 +198,7 @@ export class PdfViewerComponent implements OnInit, OnChanges {
}
async closeCompareMode() {
this.viewModeService.set('STANDARD');
this.viewModeService.compareMode = false;
const pdfNet = this.instance.Core.PDFNet;
await pdfNet.initialize(environment.licenseKey ? atob(environment.licenseKey) : null);
const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this.fileData.arrayBuffer());
@ -390,36 +390,34 @@ export class PdfViewerComponent implements OnInit, OnChanges {
const originalHeaderItems = header.getItems();
originalHeaderItems.splice(8, 0, ...headerItems);
if (this._userPreferenceService.areDevFeaturesEnabled) {
const devHeaderItems = [
{
type: 'actionButton',
element: 'compare',
dataElement: dataElements.COMPARE_BUTTON,
img: this._convertPath('/assets/icons/general/pdftron-action-compare.svg'),
title: 'Compare',
onClick: () => {
this.compareFileInput.nativeElement.click();
},
const compareHeaderItems = [
{
type: 'actionButton',
element: 'compare',
dataElement: dataElements.COMPARE_BUTTON,
img: this._convertPath('/assets/icons/general/pdftron-action-compare.svg'),
title: 'Compare',
onClick: () => {
this.compareFileInput.nativeElement.click();
},
{
type: 'actionButton',
element: 'closeCompare',
dataElement: dataElements.CLOSE_COMPARE_BUTTON,
img: this._convertPath('/assets/icons/general/pdftron-action-close-compare.svg'),
title: 'Leave Compare Mode',
onClick: async () => {
await this.closeCompareMode();
},
},
{
type: 'actionButton',
element: 'closeCompare',
dataElement: dataElements.CLOSE_COMPARE_BUTTON,
img: this._convertPath('/assets/icons/general/pdftron-action-close-compare.svg'),
title: 'Leave Compare Mode',
onClick: async () => {
await this.closeCompareMode();
},
{
type: 'divider',
dataElement: dataElements.COMPARE_TOOL_DIVIDER,
},
];
},
{
type: 'divider',
dataElement: dataElements.COMPARE_TOOL_DIVIDER,
},
];
originalHeaderItems.splice(9, 0, ...devHeaderItems);
}
originalHeaderItems.splice(9, 0, ...compareHeaderItems);
});
this.instance.UI.disableElements([dataElements.CLOSE_COMPARE_BUTTON]);

View File

@ -154,7 +154,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
private get _canPerformAnnotationActions$() {
return combineLatest([this.file$, this.viewModeService.viewMode$]).pipe(
return combineLatest([this.file$, this.viewModeService.viewMode$, this.viewModeService.compareMode$]).pipe(
map(([file, viewMode]) => this.permissionsService.canPerformAnnotationActions(file) && viewMode === 'STANDARD'),
shareDistinctLast(),
);
@ -208,7 +208,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
if (!file.canBeOpened) {
return this._router.navigate([this._dossiersService.find(this.dossierId)?.routerLink]);
}
this.viewModeService.set('STANDARD');
this.viewModeService.viewMode = 'STANDARD';
await this.ngOnInit();
this._lastPage = previousRoute.queryParams.page;
@ -425,7 +425,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
async switchView(viewMode: ViewMode) {
this.viewModeService.set(viewMode);
this.viewModeService.viewMode = viewMode;
await this.updateViewMode();
this._scrollViews();
}
@ -466,7 +466,16 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
private async _reloadFile(file: File): Promise<void> {
const previousFile = this.fileData?.file;
await this._loadFileData(file);
const fileHasBeenExcludedOrIncluded = previousFile?.excluded !== this.fileData?.file?.excluded;
const excludedPagesHaveChanged = JSON.stringify(previousFile?.excludedPages) !== JSON.stringify(this.fileData?.file?.excludedPages);
if (fileHasBeenExcludedOrIncluded || excludedPagesHaveChanged) {
await this._deleteAnnotations();
await this._cleanupAndRedrawAnnotations();
}
await this._stampPDF();
}

View File

@ -5,10 +5,14 @@ import { ViewMode } from '@red/domain';
@Injectable()
export class ViewModeService {
readonly viewMode$: Observable<ViewMode>;
readonly compareMode$: Observable<Boolean>;
private readonly _viewMode$ = new BehaviorSubject<ViewMode>('STANDARD');
private readonly _compareMode$ = new BehaviorSubject<Boolean>(false);
constructor() {
this.viewMode$ = this._viewMode$.asObservable();
this.compareMode$ = this._compareMode$.asObservable();
}
get viewMode() {
@ -23,15 +27,19 @@ export class ViewModeService {
return this._viewMode$.value === 'DELTA';
}
get isCompare() {
return this._viewMode$.value === 'COMPARE';
}
get isRedacted() {
return this._viewMode$.value === 'REDACTED';
}
set(mode: ViewMode) {
set viewMode(mode: ViewMode) {
this._viewMode$.next(mode);
}
get isCompare() {
return this._compareMode$.value;
}
set compareMode(compareMode: boolean) {
this._compareMode$.next(compareMode);
}
}

View File

@ -1,13 +0,0 @@
{
"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"
}
}

View File

@ -1,13 +0,0 @@
{
"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"
}
}

4
cypress/.gitignore vendored
View File

@ -1,4 +0,0 @@
/videos
/screenshots
/results
/test-reports

View File

@ -1,4 +0,0 @@
{
"username": "manager",
"password": "OsloImWinter"
}

View File

@ -1,4 +0,0 @@
{
"username": "user",
"password": "OsloImWinter"
}

View File

@ -1,18 +0,0 @@
/// <reference types="cypress" />
/// <reference path="../../support/index.d.ts" />
describe('it should only test login/logout flow', () => {
before(() => {
// cy.init('user');
});
after(() => {
// cy.cleanup();
});
it('it should land on homepage with no projects', () => {
console.log('no-op');
// cy.visit('/main/projects');
// cy.get('redaction-project-listing-empty', { timeout: 30000 });
});
});

View File

@ -1,20 +0,0 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)
/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
return config;
};

View File

@ -1,43 +0,0 @@
import 'cypress-localstorage-commands';
import 'cypress-file-upload';
import 'cypress-keycloak-commands';
Cypress.Commands.add('cleanup', () => {
localStorage.clear();
cy.clearLocalStorageSnapshot();
cy.kcLogout();
});
Cypress.Commands.add('init', (user) => {
cy.kcLogin('manager').as('tokens');
cy.deleteAllProjects();
cy.kcLogout();
cy.kcLogin(user).as('tokens');
});
Cypress.Commands.add('deleteAllProjects', () => {
cy.get('@tokens').then((tokens) => {
const projectListRequest = {
method: 'GET',
url: Cypress.env('api_url') + '/project',
headers: {
Authorization: 'bearer ' + tokens.access_token
}
};
cy.request(projectListRequest).then((projects) => {
projects.body.forEach((project) => {
const deleteProjectRequest = {
method: 'DELETE',
url: Cypress.env('api_url') + '/project/' + project.projectId,
headers: {
Authorization: 'bearer ' + tokens.access_token
}
};
cy.request(deleteProjectRequest).then((response) => {
console.log('Project Deleted', project.projectId, response);
});
});
});
});
});

View File

@ -1,20 +0,0 @@
/// <reference types="cypress" />
declare namespace Cypress {
interface Chainable {
/**
* Should run before each spec!
*/
init(user?: string): Chainable<Element>;
/**
* Should run after each spec!
*/
cleanup(): Chainable<Element>;
/**
* Deletes user uploads before tests
*/
deleteAllProjects(): Chainable<Element>;
}
}

View File

@ -1,20 +0,0 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands';
// Alternatively you can use CommonJS syntax:
// require('./commands')

View File

@ -1,8 +0,0 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
"types": ["cypress"]
},
"include": ["**/*.ts"]
}

View File

@ -1,4 +0,0 @@
FROM cypress/included:5.6.0
COPY package.json yarn.lock ./
RUN yarn install
COPY . .

View File

@ -1 +1 @@
export type ViewMode = 'STANDARD' | 'DELTA' | 'REDACTED' | 'COMPARE';
export type ViewMode = 'STANDARD' | 'DELTA' | 'REDACTED';

View File

@ -39,8 +39,7 @@
"generators": {
"@nrwl/angular:application": {
"linter": "eslint",
"unitTestRunner": "jest",
"e2eTestRunner": "cypress"
"unitTestRunner": "jest"
},
"@nrwl/angular:library": {
"linter": "eslint",

View File

@ -1,6 +1,6 @@
{
"name": "redaction",
"version": "3.163.0",
"version": "3.168.0",
"private": true,
"license": "MIT",
"scripts": {
@ -71,24 +71,18 @@
"@angular/language-service": "13.1.2",
"@bartholomej/ngx-translate-extract": "^8.0.2",
"@nrwl/cli": "13.4.5",
"@nrwl/cypress": "13.4.5",
"@nrwl/eslint-plugin-nx": "13.4.5",
"@nrwl/jest": "13.4.5",
"@nrwl/linter": "13.4.5",
"@nrwl/tao": "13.4.5",
"@nrwl/workspace": "13.4.5",
"@types/cypress": "^1.1.3",
"@types/jest": "27.4.0",
"@types/lodash": "^4.14.178",
"@types/node": "17.0.9",
"@types/puppeteer": "^5.4.4",
"@typescript-eslint/eslint-plugin": "5.9.1",
"@typescript-eslint/parser": "5.3.1",
"axios": "^0.24.0",
"cypress": "^6.9.1",
"cypress-file-upload": "^5.0.8",
"cypress-keycloak": "^1.7.0",
"cypress-keycloak-commands": "^1.2.0",
"cypress-localstorage-commands": "^1.5.0",
"dotenv": "10.0.0",
"eslint": "8.7.0",
"eslint-config-airbnb-base": "^15.0.0",

Binary file not shown.

973
yarn.lock

File diff suppressed because it is too large Load Diff