From fb106b54b7bd9ef47460c007ac798145c5eed09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Wed, 31 Aug 2022 14:03:32 +0200 Subject: [PATCH 1/9] [NAE-1684] Frontend component for data field caseRef - start creating caseref field --- package.json | 5 +++- .../case-ref-field/models/case-ref-field.ts | 14 +++++++++++ .../src/lib/data-fields/public-api.ts | 1 + .../task-content/model/field-type-resource.ts | 1 + .../services/field-converter.service.ts | 6 +++++ .../case-ref-field.component.html | 1 + .../case-ref-field.component.scss | 0 .../case-ref-field.component.spec.ts | 25 +++++++++++++++++++ .../case-ref-field.component.ts | 15 +++++++++++ .../src/lib/data-fields/data-fields.module.ts | 5 +++- .../src/lib/data-fields/public-api.ts | 1 + .../field-component-resolver.component.html | 3 +++ 12 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts create mode 100644 projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html create mode 100644 projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss create mode 100644 projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts create mode 100644 projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts diff --git a/package.json b/package.json index fa875f2e76..ff4b7cab1c 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,10 @@ "rxjs": "~6.5.4", "showdown": "^2.0.3", "tslib": "^2.0.0", - "zone.js": "~0.11.4" + "zone.js": "~0.11.4", + "panzoom": "~9.4.3", + "@netgrif/petriflow.svg": "~1.0.0", + "@netgrif/petri.svg": "~1.0.0" }, "devDependencies": { "@angular-devkit/build-angular": "~13.3.1", diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts new file mode 100644 index 0000000000..af281c3a9c --- /dev/null +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts @@ -0,0 +1,14 @@ +import {Behavior} from '../../models/behavior'; +import {Layout} from '../../models/layout'; +import {Validation} from '../../models/validation'; +import {Component} from '../../models/component'; +import {DataField} from '../../models/abstract-data-field'; +import {TextFieldView} from '../../text-field/models/text-field'; + +export class CaseRefField extends DataField { + + constructor(stringId: string, title: string, value: string, behavior: Behavior, placeholder?: string, + description?: string, layout?: Layout, validations?: Array, _component?: Component, parentTaskId?: string) { + super(stringId, title, value, behavior, placeholder, description, layout, validations, _component, parentTaskId); + } +} diff --git a/projects/netgrif-components-core/src/lib/data-fields/public-api.ts b/projects/netgrif-components-core/src/lib/data-fields/public-api.ts index 10aaaefb99..0e783fb73a 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/public-api.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/public-api.ts @@ -58,6 +58,7 @@ export * from './task-ref-field/model/task-ref-field'; export * from './enumeration-field/models/dynamic-enumeration-field'; export * from './filter-field/models/filter-field'; export * from './i18n-field/models/i18n-field'; +export * from './case-ref-field/models/case-ref-field'; /* Interfaces */ export * from './models/changed-fields'; diff --git a/projects/netgrif-components-core/src/lib/task-content/model/field-type-resource.ts b/projects/netgrif-components-core/src/lib/task-content/model/field-type-resource.ts index 17661b25c0..f6c2b552d7 100644 --- a/projects/netgrif-components-core/src/lib/task-content/model/field-type-resource.ts +++ b/projects/netgrif-components-core/src/lib/task-content/model/field-type-resource.ts @@ -16,6 +16,7 @@ export enum FieldTypeResource { ENUMERATION_MAP = 'enumeration_map', MULTICHOICE_MAP = 'multichoice_map', TASK_REF = 'taskRef', + CASE_REF = 'caseRef', FILTER = 'filter', I18N = 'i18n' } diff --git a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts index 8d74eda023..4cc67aa5ba 100644 --- a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts +++ b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts @@ -21,6 +21,7 @@ import {TaskRefField} from '../../data-fields/task-ref-field/model/task-ref-fiel import {DynamicEnumerationField} from '../../data-fields/enumeration-field/models/dynamic-enumeration-field'; import {FilterField} from '../../data-fields/filter-field/models/filter-field'; import {I18nField} from '../../data-fields/i18n-field/models/i18n-field'; +import {CaseRefField} from '../../data-fields/case-ref-field/models/case-ref-field'; @Injectable({ providedIn: 'root' @@ -117,6 +118,9 @@ export class FieldConverterService { case FieldTypeResource.I18N: return new I18nField(item.stringId, item.name, item.value ?? {defaultValue: ''}, item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component); + case FieldTypeResource.CASE_REF: + return new CaseRefField(item.stringId, item.name, item.value ?? {defaultValue: ''}, item.behavior, item.placeholder, + item.description, item.layout, item.validations, item.component); } } @@ -141,6 +145,8 @@ export class FieldConverterService { return FieldTypeResource.USER; } else if (item instanceof TaskRefField) { return FieldTypeResource.TASK_REF; + } else if (item instanceof CaseRefField) { + return FieldTypeResource.CASE_REF; } else if (item instanceof EnumerationField || item instanceof MultichoiceField) { return item.fieldType; } else if (item instanceof FilterField) { diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html new file mode 100644 index 0000000000..ecd074251a --- /dev/null +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html @@ -0,0 +1 @@ +ide diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts new file mode 100644 index 0000000000..06c59ba2c6 --- /dev/null +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CaseRefFieldComponent } from './case-ref-field.component'; + +describe('CaseRefFieldComponent', () => { + let component: CaseRefFieldComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CaseRefFieldComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CaseRefFieldComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts new file mode 100644 index 0000000000..7251b26312 --- /dev/null +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts @@ -0,0 +1,15 @@ +import {Component, Input} from '@angular/core'; +import {CaseRefField} from '@netgrif/components-core'; + +@Component({ + selector: 'nc-case-ref-field', + templateUrl: './case-ref-field.component.html', + styleUrls: ['./case-ref-field.component.scss'] +}) +export class CaseRefFieldComponent { + + @Input() public dataField: CaseRefField; + + constructor(){ + } +} diff --git a/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts b/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts index 593a48b223..1fbe9a1583 100644 --- a/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts +++ b/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts @@ -61,6 +61,7 @@ import { I18nTextFieldComponent } from './i18n-field/i18n-text-field/i18n-text-f import { EasymdeWrapperComponent } from './text-field/rich-textarea-field/easymde-wrapper/easymde-wrapper.component'; import {BrowserModule} from '@angular/platform-browser'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import { CaseRefFieldComponent } from './case-ref-field/case-ref-field.component'; @NgModule({ declarations: [ @@ -100,6 +101,7 @@ import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; I18nDividerFieldComponent, I18nTextFieldComponent, EasymdeWrapperComponent, + CaseRefFieldComponent, ], exports: [ BooleanFieldComponent, @@ -115,7 +117,8 @@ import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; TextFieldComponent, UserFieldComponent, FilterFieldComponent, - I18nFieldComponent + I18nFieldComponent, + CaseRefFieldComponent ], imports: [ CommonModule, diff --git a/projects/netgrif-components/src/lib/data-fields/public-api.ts b/projects/netgrif-components/src/lib/data-fields/public-api.ts index 5b365221eb..7d9c110e7e 100644 --- a/projects/netgrif-components/src/lib/data-fields/public-api.ts +++ b/projects/netgrif-components/src/lib/data-fields/public-api.ts @@ -15,5 +15,6 @@ export * from './text-field/text-field.component'; export * from './user-field/user-field.component'; export * from './filter-field/filter-field.component'; export * from './i18n-field/i18n-field.component'; +export * from './case-ref-field/case-ref-field.component'; /* Class */ diff --git a/projects/netgrif-components/src/lib/task-content/field-component-resolver/field-component-resolver.component.html b/projects/netgrif-components/src/lib/task-content/field-component-resolver/field-component-resolver.component.html index 5d185cca29..c981f5a9e7 100644 --- a/projects/netgrif-components/src/lib/task-content/field-component-resolver/field-component-resolver.component.html +++ b/projects/netgrif-components/src/lib/task-content/field-component-resolver/field-component-resolver.component.html @@ -44,6 +44,9 @@ + + +
{{getDataGroupTitle()}} From 3492f3012e389fdc8ee2135fc6d9b1ff7fb6c804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Mon, 5 Sep 2022 14:13:13 +0200 Subject: [PATCH 2/9] [NAE-1684] Frontend component for data field caseRef - add petriflow lib and petriflow canvas --- .../case-ref-field.component.html | 4 +++- .../case-ref-field.component.scss | 5 +++++ .../case-ref-field.component.ts | 21 ++++++++++++++++--- .../src/lib/data-fields/data-fields.module.ts | 4 +++- 4 files changed, 29 insertions(+), 5 deletions(-) diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html index ecd074251a..7ddce2594f 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html @@ -1 +1,3 @@ -ide +
+ +
diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss index e69de29bb2..620e47a391 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss @@ -0,0 +1,5 @@ +.outer { + display: flex; + min-height: 50%; + max-height: 100%; +} diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts index 7251b26312..c66d400832 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts @@ -1,15 +1,30 @@ -import {Component, Input} from '@angular/core'; +import {AfterViewInit, Component, Input} from '@angular/core'; import {CaseRefField} from '@netgrif/components-core'; +import { + PetriflowCanvasConfigurationService, + PetriflowCanvasFactoryService, + PetriflowCanvasService +} from '@netgrif/petriflow.svg'; @Component({ selector: 'nc-case-ref-field', templateUrl: './case-ref-field.component.html', styleUrls: ['./case-ref-field.component.scss'] }) -export class CaseRefFieldComponent { +export class CaseRefFieldComponent implements AfterViewInit{ @Input() public dataField: CaseRefField; - constructor(){ + constructor(private _petriflowCanvasService: PetriflowCanvasService, private _petriflowFactoryService: PetriflowCanvasFactoryService, + private _petriflowConfigService: PetriflowCanvasConfigurationService){ } + + ngAfterViewInit(): void { + const transition = this._petriflowFactoryService.createTransition(new DOMPoint(100, 100)); + this._petriflowConfigService.addTransitionEvents(transition); + + const place = this._petriflowFactoryService.createPlace(1, new DOMPoint(150, 100)); + this._petriflowConfigService.addPlaceEvents(place); + } + } diff --git a/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts b/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts index 1fbe9a1583..587306188b 100644 --- a/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts +++ b/projects/netgrif-components/src/lib/data-fields/data-fields.module.ts @@ -62,6 +62,7 @@ import { EasymdeWrapperComponent } from './text-field/rich-textarea-field/easymd import {BrowserModule} from '@angular/platform-browser'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; import { CaseRefFieldComponent } from './case-ref-field/case-ref-field.component'; +import {PetriflowCanvasModule} from '@netgrif/petriflow.svg'; @NgModule({ declarations: [ @@ -138,7 +139,8 @@ import { CaseRefFieldComponent } from './case-ref-field/case-ref-field.component MatProgressSpinnerModule, CurrencyModule, BrowserModule, - BrowserAnimationsModule + BrowserAnimationsModule, + PetriflowCanvasModule ], providers: [ { provide: DateAdapter, useClass: CustomDateAdapter } From 4be5f89e6985738e33447c679f9f66b457aa7128 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Sat, 10 Sep 2022 22:46:28 +0200 Subject: [PATCH 3/9] [NAE-1684] Frontend component for data field caseRef - finish with load a net and show it in petriflow lib --- .../petri-net-resource.service.ts | 13 ++ .../src/lib/resources/interface/arc-import.ts | 11 ++ .../resources/interface/petri-net-import.ts | 9 ++ .../lib/resources/interface/place-import.ts | 10 ++ .../src/lib/resources/interface/position.ts | 5 + .../resources/interface/transition-import.ts | 8 ++ .../src/lib/resources/public-api.ts | 6 +- .../new-case/abstract-new-case.component.ts | 4 +- .../case-ref-field.component.scss | 7 +- .../case-ref-field.component.ts | 122 +++++++++++++++++- 10 files changed, 184 insertions(+), 11 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/resources/interface/arc-import.ts create mode 100644 projects/netgrif-components-core/src/lib/resources/interface/petri-net-import.ts create mode 100644 projects/netgrif-components-core/src/lib/resources/interface/place-import.ts create mode 100644 projects/netgrif-components-core/src/lib/resources/interface/position.ts create mode 100644 projects/netgrif-components-core/src/lib/resources/interface/transition-import.ts diff --git a/projects/netgrif-components-core/src/lib/resources/engine-endpoint/petri-net-resource.service.ts b/projects/netgrif-components-core/src/lib/resources/engine-endpoint/petri-net-resource.service.ts index 7dae4f1ad2..c6b1080aed 100644 --- a/projects/netgrif-components-core/src/lib/resources/engine-endpoint/petri-net-resource.service.ts +++ b/projects/netgrif-components-core/src/lib/resources/engine-endpoint/petri-net-resource.service.ts @@ -14,6 +14,7 @@ import {Page} from '../interface/page'; import {processMessageResponse} from '../../utility/process-message-response'; import {AbstractResourceService} from '../abstract-endpoint/abstract-resource.service'; import RolesAndPermissions from '../../process/rolesAndPermissions'; +import {PetriNetImport} from '../interface/petri-net-import'; @Injectable({ providedIn: 'root' @@ -170,4 +171,16 @@ export class PetriNetResourceService extends AbstractResourceService { return this._resourceProvider.delete$('petrinet/' + netId, this.SERVER_URL) .pipe(switchMap(processMessageResponse)); } + + /** + * get One Net by ID + * + * **Request Type:** GET + * + * **Request URL:** {{baseUrl}}/api/petrinet/{id} + */ + public getNetByCaseId(caseId: string, params?: Params): Observable { + return this._resourceProvider.get$('petrinet/case/' + caseId, this.SERVER_URL, params) + .pipe(map(r => this.changeType(r, undefined))); + } } diff --git a/projects/netgrif-components-core/src/lib/resources/interface/arc-import.ts b/projects/netgrif-components-core/src/lib/resources/interface/arc-import.ts new file mode 100644 index 0000000000..6a206122f6 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/resources/interface/arc-import.ts @@ -0,0 +1,11 @@ +import {Position} from './position'; + +export interface ArcImport { + destinationId: string; + sourceId: string; + importId: string; + multiplicity: number; + stringId: string; + breakpoints: Array; + type: string; +} diff --git a/projects/netgrif-components-core/src/lib/resources/interface/petri-net-import.ts b/projects/netgrif-components-core/src/lib/resources/interface/petri-net-import.ts new file mode 100644 index 0000000000..9d04c89d09 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/resources/interface/petri-net-import.ts @@ -0,0 +1,9 @@ +import {TransitionImport} from './transition-import'; +import {PlaceImport} from './place-import'; +import {ArcImport} from './arc-import'; + +export interface PetriNetImport { + transitions: Array; + places: Array; + arcs: Array; +} diff --git a/projects/netgrif-components-core/src/lib/resources/interface/place-import.ts b/projects/netgrif-components-core/src/lib/resources/interface/place-import.ts new file mode 100644 index 0000000000..9fc878d2a4 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/resources/interface/place-import.ts @@ -0,0 +1,10 @@ +import {Position} from './position'; + +export interface PlaceImport { + importId: string; + isStatic: boolean; + position: Position; + stringId: string; + title: object; + tokens: number; +} diff --git a/projects/netgrif-components-core/src/lib/resources/interface/position.ts b/projects/netgrif-components-core/src/lib/resources/interface/position.ts new file mode 100644 index 0000000000..f24a55f19b --- /dev/null +++ b/projects/netgrif-components-core/src/lib/resources/interface/position.ts @@ -0,0 +1,5 @@ + +export interface Position { + x: number; + y: number; +} diff --git a/projects/netgrif-components-core/src/lib/resources/interface/transition-import.ts b/projects/netgrif-components-core/src/lib/resources/interface/transition-import.ts new file mode 100644 index 0000000000..6afdeaa1f5 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/resources/interface/transition-import.ts @@ -0,0 +1,8 @@ +import {Position} from './position'; + +export interface TransitionImport { + importId: string; + position: Position; + stringId: string; + title: object; +} diff --git a/projects/netgrif-components-core/src/lib/resources/public-api.ts b/projects/netgrif-components-core/src/lib/resources/public-api.ts index 5f539f1685..836b825b10 100644 --- a/projects/netgrif-components-core/src/lib/resources/public-api.ts +++ b/projects/netgrif-components-core/src/lib/resources/public-api.ts @@ -44,7 +44,11 @@ export * from './interface/user-resource'; export * from './interface/create-case-request-body'; export * from './interface/ldapGroupResponseBody'; export * from './interface/task-pair'; - +export * from './interface/arc-import'; +export * from './interface/place-import'; +export * from './interface/transition-import'; +export * from './interface/position'; +export * from './interface/petri-net-import'; export * from './types/nae-date-type'; /* ABSTRACTIONS */ diff --git a/projects/netgrif-components-core/src/lib/side-menu/content-components/new-case/abstract-new-case.component.ts b/projects/netgrif-components-core/src/lib/side-menu/content-components/new-case/abstract-new-case.component.ts index e009dad707..35e873d16b 100644 --- a/projects/netgrif-components-core/src/lib/side-menu/content-components/new-case/abstract-new-case.component.ts +++ b/projects/netgrif-components-core/src/lib/side-menu/content-components/new-case/abstract-new-case.component.ts @@ -148,12 +148,12 @@ export abstract class AbstractNewCaseComponent implements OnDestroy { this._caseResourceService.createCase(newCase) .subscribe( (response: EventOutcomeMessageResource) => { - this._snackBarService.openSuccessSnackBar(response.outcome.message === undefined + this._snackBarService.openSuccessSnackBar(response.outcome?.message === undefined ? this._translate.instant('side-menu.new-case.createCase') + ' ' + newCase.title : response.outcome.message); this._sideMenuControl.close({ opened: false, - message: response.outcome.message === undefined + message: response.outcome?.message === undefined ? 'Confirm new case setup' : response.outcome.message , diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss index 620e47a391..f93730d60d 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss @@ -1,5 +1,10 @@ .outer { display: flex; - min-height: 50%; + min-height: 300px; + width: 100%; max-height: 100%; } + +.canvas { + width: 100%; +} diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts index c66d400832..b274421ff4 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts @@ -1,10 +1,21 @@ import {AfterViewInit, Component, Input} from '@angular/core'; -import {CaseRefField} from '@netgrif/components-core'; +import {CaseRefField, CaseResourceService, PetriNetResourceService, ArcImport} from '@netgrif/components-core'; import { + PetriflowArc, PetriflowCanvasConfigurationService, PetriflowCanvasFactoryService, - PetriflowCanvasService + PetriflowCanvasService, + PetriflowInhibitorArc, + PetriflowPlace, + PetriflowPlaceTransitionArc, PetriflowReadArc, + PetriflowResetArc, + PetriflowTransition, + PetriflowTransitionPlaceArc } from '@netgrif/petriflow.svg'; +import { + Arc, InhibitorArc, ReadArc, RegularPlaceTransitionArc, + RegularTransitionPlaceArc, ResetArc +} from '@netgrif/petri.svg'; @Component({ selector: 'nc-case-ref-field', @@ -16,15 +27,112 @@ export class CaseRefFieldComponent implements AfterViewInit{ @Input() public dataField: CaseRefField; constructor(private _petriflowCanvasService: PetriflowCanvasService, private _petriflowFactoryService: PetriflowCanvasFactoryService, - private _petriflowConfigService: PetriflowCanvasConfigurationService){ + private _petriflowConfigService: PetriflowCanvasConfigurationService, private _caseResourceService: CaseResourceService, + private _petriNetResourceService: PetriNetResourceService){ } ngAfterViewInit(): void { - const transition = this._petriflowFactoryService.createTransition(new DOMPoint(100, 100)); - this._petriflowConfigService.addTransitionEvents(transition); + this._petriNetResourceService.getNetByCaseId(this.dataField.value).subscribe(net => { + if (net) { + const trans: Array = []; + const places: Array = []; + let minX: number = 1000; + let minY: number = 1000; + net.transitions.forEach((value) => { + const transition = this._petriflowFactoryService.createTransition(new DOMPoint(value.position.x, value.position.y)); + transition.changeId(value.stringId); + minX = Math.min(minX, value.position.x); + minY = Math.min(minY, value.position.y); + this._petriflowConfigService.addTransitionEvents(transition); + trans.push(transition); + }) + net.places.forEach((value) => { + const place = this._petriflowFactoryService.createPlace(value.tokens, new DOMPoint(value.position.x, value.position.y)); + place.changeId(value.stringId); + minX = Math.min(minX, value.position.x); + minY = Math.min(minY, value.position.y); + this._petriflowConfigService.addPlaceEvents(place); + places.push(place); + }) + net.arcs.forEach((arc) => { + let source: PetriflowPlace | PetriflowTransition = trans.find(value => value.canvasElement.label.textContent === arc.sourceId); + let destination: PetriflowPlace | PetriflowTransition; + if (source === undefined) { + source = places.find(value => value.canvasElement.label.textContent === arc.sourceId); + destination = trans.find(value => value.canvasElement.label.textContent === arc.destinationId); + } else { + destination = places.find(value => value.canvasElement.label.textContent === arc.destinationId); + } + if (source === undefined || destination === undefined) { + console.error("Can't find source or destination for arc [" + arc.importId + "]"); + } else { + const newArc: Arc = this.createArc(arc, source, destination); + const petriflowArc: PetriflowArc = this.createPetriflowArc(arc, newArc, source); + this._petriflowCanvasService.canvas.container.appendChild(newArc.container); + this._petriflowCanvasService.petriflowElementsCollection.arcs.push(petriflowArc); + arc.breakpoints?.forEach(value => { + minX = Math.min(minX, value.x); + minY = Math.min(minY, value.y); + }); + } + }); + this._petriflowCanvasService.panzoom?.moveTo(-minX+20, -minY+20); + setTimeout(() => { + this._petriflowCanvasService.panzoom?.pause(); + }) + } + }); + } - const place = this._petriflowFactoryService.createPlace(1, new DOMPoint(150, 100)); - this._petriflowConfigService.addPlaceEvents(place); + private createArc(arc: ArcImport, source: PetriflowTransition | PetriflowPlace, destination: PetriflowPlace | PetriflowTransition) { + if (source instanceof PetriflowPlace) { + switch (arc.type) { + case 'arc': { + return this._petriflowFactoryService.createArc(RegularPlaceTransitionArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } + case 'reset': { + return this._petriflowFactoryService.createArc(ResetArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } + case 'inhibitor': { + return this._petriflowFactoryService.createArc(InhibitorArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } + case 'read': { + return this._petriflowFactoryService.createArc(ReadArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } + default: { + return undefined; + } + } + } else if (arc.type === 'arc') { + return this._petriflowFactoryService.createArc(RegularTransitionPlaceArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } else { + return undefined; + } } + private createPetriflowArc(arc: ArcImport, newArc: Arc, source: PetriflowTransition | PetriflowPlace) { + if (source instanceof PetriflowPlace) { + switch (arc.type) { + case 'arc': { + return this._petriflowFactoryService.createArc(PetriflowPlaceTransitionArc, newArc); + } + case 'reset': { + return this._petriflowFactoryService.createArc(PetriflowResetArc, newArc); + } + case 'inhibitor': { + return this._petriflowFactoryService.createArc(PetriflowInhibitorArc, newArc); + } + case 'read': { + return this._petriflowFactoryService.createArc(PetriflowReadArc, newArc); + } + default: { + return undefined; + } + } + } else if (arc.type === 'arc') { + return this._petriflowFactoryService.createArc(PetriflowTransitionPlaceArc, newArc); + } else { + return undefined; + } + } } From f29e02078a94b8b5158ed8737b1bdbc71bcca525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Sun, 11 Sep 2022 21:59:51 +0200 Subject: [PATCH 4/9] [NAE-1684] Frontend component for data field caseRef - little refactor --- .../abstract-case-ref-field.component.ts | 158 ++++++++++++++++++ .../src/lib/data-fields/data-fields.module.ts | 4 +- .../src/lib/data-fields/public-api.ts | 1 + .../petri-net-resource.service.ts | 4 +- .../src/lib/resources/interface/arc-import.ts | 3 +- .../src/lib/resources/interface/arc-type.ts | 6 + .../src/lib/resources/public-api.ts | 1 + .../case-ref-field.component.spec.ts | 91 +++++++--- .../case-ref-field.component.ts | 132 +-------------- 9 files changed, 253 insertions(+), 147 deletions(-) create mode 100644 projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts create mode 100644 projects/netgrif-components-core/src/lib/resources/interface/arc-type.ts diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts new file mode 100644 index 0000000000..00a436deeb --- /dev/null +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts @@ -0,0 +1,158 @@ +import {AfterViewInit, Component, Input} from '@angular/core'; +import { + PetriflowArc, + PetriflowCanvasConfigurationService, + PetriflowCanvasFactoryService, + PetriflowCanvasService, + PetriflowInhibitorArc, + PetriflowPlace, + PetriflowPlaceTransitionArc, PetriflowReadArc, + PetriflowResetArc, + PetriflowTransition, PetriflowTransitionPlaceArc +} from '@netgrif/petriflow.svg'; +import { + Arc, + InhibitorArc, + ReadArc, + RegularPlaceTransitionArc, + RegularTransitionPlaceArc, + ResetArc +} from '@netgrif/petri.svg'; +import {CaseRefField} from './models/case-ref-field'; +import {PetriNetResourceService} from '../../resources/engine-endpoint/petri-net-resource.service'; +import {CaseResourceService} from '../../resources/engine-endpoint/case-resource.service'; +import {TransitionImport} from '../../resources/interface/transition-import'; +import {PlaceImport} from '../../resources/interface/place-import'; +import {ArcImport} from '../../resources/interface/arc-import'; +import {ArcType} from '../../resources/interface/arc-type'; + +@Component({ + selector: 'ncc-abstract-case-ref-field', + template: '' +}) +export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { + + @Input() public dataField: CaseRefField; + + constructor(protected _petriflowCanvasService: PetriflowCanvasService, protected _petriflowFactoryService: PetriflowCanvasFactoryService, + protected _petriflowConfigService: PetriflowCanvasConfigurationService, protected _caseResourceService: CaseResourceService, + protected _petriNetResourceService: PetriNetResourceService){ + } + + ngAfterViewInit(): void { + this._petriNetResourceService.getNetByCaseId(this.dataField.value).subscribe(net => { + if (net) { + const trans: Array = []; + const places: Array = []; + let minX: number = Number.MAX_SAFE_INTEGER; + let minY: number = Number.MAX_SAFE_INTEGER; + net.transitions.forEach((value) => { + trans.push(this.createTransitions(value)); + minX = Math.min(minX, value.position.x); + minY = Math.min(minY, value.position.y); + }) + net.places.forEach((value) => { + places.push(this.createPlace(value)); + minX = Math.min(minX, value.position.x); + minY = Math.min(minY, value.position.y); + }) + net.arcs.forEach((arc) => { + this.createArcs(trans, places, arc); + arc.breakpoints?.forEach(value => { + minX = Math.min(minX, value.x); + minY = Math.min(minY, value.y); + }); + }); + this._petriflowCanvasService.panzoom?.moveTo(-minX+20, -minY+20); + setTimeout(() => { + this._petriflowCanvasService.panzoom?.pause(); + }) + } + }); + } + + protected createTransitions(value: TransitionImport): PetriflowTransition { + const transition = this._petriflowFactoryService.createTransition(new DOMPoint(value.position.x, value.position.y)); + transition.changeId(value.stringId); + this._petriflowConfigService.addTransitionEvents(transition); + return transition; + } + + protected createPlace(value: PlaceImport): PetriflowPlace { + const place = this._petriflowFactoryService.createPlace(value.tokens, new DOMPoint(value.position.x, value.position.y)); + place.changeId(value.stringId); + this._petriflowConfigService.addPlaceEvents(place); + return place; + } + + protected createArcs(trans: Array, places: Array, arc: ArcImport) { + let source: PetriflowPlace | PetriflowTransition = trans.find(value => value.canvasElement.label.textContent === arc.sourceId); + let destination: PetriflowPlace | PetriflowTransition; + if (source === undefined) { + source = places.find(value => value.canvasElement.label.textContent === arc.sourceId); + destination = trans.find(value => value.canvasElement.label.textContent === arc.destinationId); + } else { + destination = places.find(value => value.canvasElement.label.textContent === arc.destinationId); + } + if (source === undefined || destination === undefined) { + console.error("Can't find source or destination for arc [" + arc.importId + "]"); + } else { + const newArc: Arc = this.createArc(arc, source, destination); + const petriflowArc: PetriflowArc = this.createPetriflowArc(arc, newArc, source); + this._petriflowCanvasService.canvas.container.appendChild(newArc.container); + this._petriflowCanvasService.petriflowElementsCollection.arcs.push(petriflowArc); + } + } + + protected createArc(arc: ArcImport, source: PetriflowTransition | PetriflowPlace, destination: PetriflowPlace | PetriflowTransition) { + if (source instanceof PetriflowPlace) { + switch (arc.type) { + case ArcType.ARC: { + return this._petriflowFactoryService.createArc(RegularPlaceTransitionArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } + case ArcType.RESET: { + return this._petriflowFactoryService.createArc(ResetArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } + case ArcType.INHIBITOR: { + return this._petriflowFactoryService.createArc(InhibitorArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } + case ArcType.READ: { + return this._petriflowFactoryService.createArc(ReadArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } + default: { + return undefined; + } + } + } else if (arc.type === ArcType.ARC) { + return this._petriflowFactoryService.createArc(RegularTransitionPlaceArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); + } else { + return undefined; + } + } + + protected createPetriflowArc(arc: ArcImport, newArc: Arc, source: PetriflowTransition | PetriflowPlace) { + if (source instanceof PetriflowPlace) { + switch (arc.type) { + case ArcType.ARC: { + return this._petriflowFactoryService.createArc(PetriflowPlaceTransitionArc, newArc); + } + case ArcType.RESET: { + return this._petriflowFactoryService.createArc(PetriflowResetArc, newArc); + } + case ArcType.INHIBITOR: { + return this._petriflowFactoryService.createArc(PetriflowInhibitorArc, newArc); + } + case ArcType.READ: { + return this._petriflowFactoryService.createArc(PetriflowReadArc, newArc); + } + default: { + return undefined; + } + } + } else if (arc.type === ArcType.ARC) { + return this._petriflowFactoryService.createArc(PetriflowTransitionPlaceArc, newArc); + } else { + return undefined; + } + } +} diff --git a/projects/netgrif-components-core/src/lib/data-fields/data-fields.module.ts b/projects/netgrif-components-core/src/lib/data-fields/data-fields.module.ts index 318d13b7b5..15a2cd257b 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/data-fields.module.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/data-fields.module.ts @@ -11,6 +11,7 @@ import {NgxMatDatetimePickerModule} from '@angular-material-components/datetime- import {NgxMatMomentModule} from '@angular-material-components/moment-adapter'; import {TranslateLibModule} from '../translate/translate-lib.module'; import {DateAdapter} from '@angular/material/core'; +import {PetriflowCanvasModule} from '@netgrif/petriflow.svg'; @NgModule({ imports: [ @@ -23,7 +24,8 @@ import {DateAdapter} from '@angular/material/core'; ReactiveFormsModule, NgxMatDatetimePickerModule, NgxMatMomentModule, - TranslateLibModule + TranslateLibModule, + PetriflowCanvasModule ], providers: [ {provide: DateAdapter, useClass: CustomDateAdapter} diff --git a/projects/netgrif-components-core/src/lib/data-fields/public-api.ts b/projects/netgrif-components-core/src/lib/data-fields/public-api.ts index 0e783fb73a..7a2f8c4ce6 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/public-api.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/public-api.ts @@ -37,6 +37,7 @@ export * from './i18n-field/abstract-i18n-field.component'; export * from './i18n-field/i18n-text-field/abstract-i18n-text-field.component'; export * from './i18n-field/i18n-divider-field/abstract-i18n-divider-field.component'; export * from './i18n-field/abstract-i18n-errors.component'; +export * from './case-ref-field/abstract-case-ref-field.component'; /* Class */ export * from './models/abstract-data-field'; diff --git a/projects/netgrif-components-core/src/lib/resources/engine-endpoint/petri-net-resource.service.ts b/projects/netgrif-components-core/src/lib/resources/engine-endpoint/petri-net-resource.service.ts index c6b1080aed..4c42a7b0fc 100644 --- a/projects/netgrif-components-core/src/lib/resources/engine-endpoint/petri-net-resource.service.ts +++ b/projects/netgrif-components-core/src/lib/resources/engine-endpoint/petri-net-resource.service.ts @@ -173,11 +173,11 @@ export class PetriNetResourceService extends AbstractResourceService { } /** - * get One Net by ID + * get One Net by case ID * * **Request Type:** GET * - * **Request URL:** {{baseUrl}}/api/petrinet/{id} + * **Request URL:** {{baseUrl}}/api/petrinet/case/{id} */ public getNetByCaseId(caseId: string, params?: Params): Observable { return this._resourceProvider.get$('petrinet/case/' + caseId, this.SERVER_URL, params) diff --git a/projects/netgrif-components-core/src/lib/resources/interface/arc-import.ts b/projects/netgrif-components-core/src/lib/resources/interface/arc-import.ts index 6a206122f6..7b653e06bd 100644 --- a/projects/netgrif-components-core/src/lib/resources/interface/arc-import.ts +++ b/projects/netgrif-components-core/src/lib/resources/interface/arc-import.ts @@ -1,4 +1,5 @@ import {Position} from './position'; +import {ArcType} from './arc-type'; export interface ArcImport { destinationId: string; @@ -7,5 +8,5 @@ export interface ArcImport { multiplicity: number; stringId: string; breakpoints: Array; - type: string; + type: ArcType; } diff --git a/projects/netgrif-components-core/src/lib/resources/interface/arc-type.ts b/projects/netgrif-components-core/src/lib/resources/interface/arc-type.ts new file mode 100644 index 0000000000..68adc9cf57 --- /dev/null +++ b/projects/netgrif-components-core/src/lib/resources/interface/arc-type.ts @@ -0,0 +1,6 @@ +export enum ArcType { + ARC = 'arc', + RESET = 'reset', + INHIBITOR = 'inhibitor', + READ = 'read' +} diff --git a/projects/netgrif-components-core/src/lib/resources/public-api.ts b/projects/netgrif-components-core/src/lib/resources/public-api.ts index 836b825b10..a2c23652b9 100644 --- a/projects/netgrif-components-core/src/lib/resources/public-api.ts +++ b/projects/netgrif-components-core/src/lib/resources/public-api.ts @@ -49,6 +49,7 @@ export * from './interface/place-import'; export * from './interface/transition-import'; export * from './interface/position'; export * from './interface/petri-net-import'; +export * from './interface/arc-type'; export * from './types/nae-date-type'; /* ABSTRACTIONS */ diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts index 06c59ba2c6..dff37a92ca 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts @@ -1,25 +1,78 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { CaseRefFieldComponent } from './case-ref-field.component'; +import {ComponentFixture, TestBed} from '@angular/core/testing'; +import { + MaterialModule, + TranslateLibModule, + AuthenticationMethodService, + MockAuthenticationMethodService, + AuthenticationService, + MockAuthenticationService, + ConfigurationService, + TestConfigurationService, + CaseRefField, + PetriNetResourceService +} from '@netgrif/components-core'; +import {CaseRefFieldComponent} from './case-ref-field.component'; +import {AngularResizeEventModule} from 'angular-resize-event'; +import {HttpClientTestingModule} from '@angular/common/http/testing'; +import {NoopAnimationsModule} from '@angular/platform-browser/animations'; +import {PetriflowCanvasModule} from '@netgrif/petriflow.svg'; +import {Component} from '@angular/core'; +import {of} from 'rxjs'; describe('CaseRefFieldComponent', () => { - let component: CaseRefFieldComponent; - let fixture: ComponentFixture; + let component: CaseRefFieldComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ + MaterialModule, + AngularResizeEventModule, + TranslateLibModule, + HttpClientTestingModule, + NoopAnimationsModule, + PetriflowCanvasModule, - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ CaseRefFieldComponent ] - }) - .compileComponents(); - }); + ], + providers: [ + {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, + {provide: AuthenticationService, useClass: MockAuthenticationService}, + {provide: ConfigurationService, useClass: TestConfigurationService}, + {provide: PetriNetResourceService, useClass: MyPetriNetResource}, + ], + declarations: [CaseRefFieldComponent] + }) + .compileComponents(); + fixture = TestBed.createComponent(TestWrapperComponent); + component = fixture.debugElement.children[0].componentInstance; + fixture.detectChanges(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(CaseRefFieldComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + afterEach(() => { + TestBed.resetTestingModule(); + }); }); + +@Component({ + selector: 'nc-test-wrapper', + template: '' +}) +class TestWrapperComponent { + field = new CaseRefField('', '', '', { + required: true, + }); +} + +class MyPetriNetResource { + public getNetByCaseId(caseId: string) { + return of({ + transitions: [], + places: [], + arcs: [] + }); + } +} diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts index b274421ff4..85342010da 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts @@ -1,138 +1,22 @@ -import {AfterViewInit, Component, Input} from '@angular/core'; -import {CaseRefField, CaseResourceService, PetriNetResourceService, ArcImport} from '@netgrif/components-core'; +import {Component} from '@angular/core'; +import {AbstractCaseRefFieldComponent, CaseResourceService, PetriNetResourceService} from '@netgrif/components-core'; import { - PetriflowArc, PetriflowCanvasConfigurationService, PetriflowCanvasFactoryService, - PetriflowCanvasService, - PetriflowInhibitorArc, - PetriflowPlace, - PetriflowPlaceTransitionArc, PetriflowReadArc, - PetriflowResetArc, - PetriflowTransition, - PetriflowTransitionPlaceArc + PetriflowCanvasService } from '@netgrif/petriflow.svg'; -import { - Arc, InhibitorArc, ReadArc, RegularPlaceTransitionArc, - RegularTransitionPlaceArc, ResetArc -} from '@netgrif/petri.svg'; @Component({ selector: 'nc-case-ref-field', templateUrl: './case-ref-field.component.html', styleUrls: ['./case-ref-field.component.scss'] }) -export class CaseRefFieldComponent implements AfterViewInit{ - - @Input() public dataField: CaseRefField; - - constructor(private _petriflowCanvasService: PetriflowCanvasService, private _petriflowFactoryService: PetriflowCanvasFactoryService, - private _petriflowConfigService: PetriflowCanvasConfigurationService, private _caseResourceService: CaseResourceService, - private _petriNetResourceService: PetriNetResourceService){ - } +export class CaseRefFieldComponent extends AbstractCaseRefFieldComponent { - ngAfterViewInit(): void { - this._petriNetResourceService.getNetByCaseId(this.dataField.value).subscribe(net => { - if (net) { - const trans: Array = []; - const places: Array = []; - let minX: number = 1000; - let minY: number = 1000; - net.transitions.forEach((value) => { - const transition = this._petriflowFactoryService.createTransition(new DOMPoint(value.position.x, value.position.y)); - transition.changeId(value.stringId); - minX = Math.min(minX, value.position.x); - minY = Math.min(minY, value.position.y); - this._petriflowConfigService.addTransitionEvents(transition); - trans.push(transition); - }) - net.places.forEach((value) => { - const place = this._petriflowFactoryService.createPlace(value.tokens, new DOMPoint(value.position.x, value.position.y)); - place.changeId(value.stringId); - minX = Math.min(minX, value.position.x); - minY = Math.min(minY, value.position.y); - this._petriflowConfigService.addPlaceEvents(place); - places.push(place); - }) - net.arcs.forEach((arc) => { - let source: PetriflowPlace | PetriflowTransition = trans.find(value => value.canvasElement.label.textContent === arc.sourceId); - let destination: PetriflowPlace | PetriflowTransition; - if (source === undefined) { - source = places.find(value => value.canvasElement.label.textContent === arc.sourceId); - destination = trans.find(value => value.canvasElement.label.textContent === arc.destinationId); - } else { - destination = places.find(value => value.canvasElement.label.textContent === arc.destinationId); - } - if (source === undefined || destination === undefined) { - console.error("Can't find source or destination for arc [" + arc.importId + "]"); - } else { - const newArc: Arc = this.createArc(arc, source, destination); - const petriflowArc: PetriflowArc = this.createPetriflowArc(arc, newArc, source); - this._petriflowCanvasService.canvas.container.appendChild(newArc.container); - this._petriflowCanvasService.petriflowElementsCollection.arcs.push(petriflowArc); - arc.breakpoints?.forEach(value => { - minX = Math.min(minX, value.x); - minY = Math.min(minY, value.y); - }); - } - }); - this._petriflowCanvasService.panzoom?.moveTo(-minX+20, -minY+20); - setTimeout(() => { - this._petriflowCanvasService.panzoom?.pause(); - }) - } - }); + constructor(protected _petriflowCanvasService: PetriflowCanvasService, protected _petriflowFactoryService: PetriflowCanvasFactoryService, + protected _petriflowConfigService: PetriflowCanvasConfigurationService, protected _caseResourceService: CaseResourceService, + protected _petriNetResourceService: PetriNetResourceService){ + super(_petriflowCanvasService, _petriflowFactoryService, _petriflowConfigService, _caseResourceService, _petriNetResourceService); } - private createArc(arc: ArcImport, source: PetriflowTransition | PetriflowPlace, destination: PetriflowPlace | PetriflowTransition) { - if (source instanceof PetriflowPlace) { - switch (arc.type) { - case 'arc': { - return this._petriflowFactoryService.createArc(RegularPlaceTransitionArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); - } - case 'reset': { - return this._petriflowFactoryService.createArc(ResetArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); - } - case 'inhibitor': { - return this._petriflowFactoryService.createArc(InhibitorArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); - } - case 'read': { - return this._petriflowFactoryService.createArc(ReadArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); - } - default: { - return undefined; - } - } - } else if (arc.type === 'arc') { - return this._petriflowFactoryService.createArc(RegularTransitionPlaceArc, source.canvasElement, destination.canvasElement, arc.breakpoints, arc.multiplicity); - } else { - return undefined; - } - } - - private createPetriflowArc(arc: ArcImport, newArc: Arc, source: PetriflowTransition | PetriflowPlace) { - if (source instanceof PetriflowPlace) { - switch (arc.type) { - case 'arc': { - return this._petriflowFactoryService.createArc(PetriflowPlaceTransitionArc, newArc); - } - case 'reset': { - return this._petriflowFactoryService.createArc(PetriflowResetArc, newArc); - } - case 'inhibitor': { - return this._petriflowFactoryService.createArc(PetriflowInhibitorArc, newArc); - } - case 'read': { - return this._petriflowFactoryService.createArc(PetriflowReadArc, newArc); - } - default: { - return undefined; - } - } - } else if (arc.type === 'arc') { - return this._petriflowFactoryService.createArc(PetriflowTransitionPlaceArc, newArc); - } else { - return undefined; - } - } } From 4341b1186e7f66275c021fe66b9d442c5b8edc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Thu, 15 Sep 2022 12:03:31 +0200 Subject: [PATCH 5/9] [NAE-1684] Frontend component for data field caseRef - add highlighting - add error handling - add new translations --- .../src/assets/i18n/de.json | 3 +- .../src/assets/i18n/en.json | 3 +- .../src/assets/i18n/sk.json | 3 +- .../abstract-case-ref-field.component.ts | 88 +++++++++++++++++-- .../case-ref-field/models/case-ref-field.ts | 2 + .../resources/interface/petri-net-import.ts | 2 + .../case-ref-field.component.html | 2 +- .../case-ref-field.component.scss | 1 - .../case-ref-field.component.spec.ts | 10 ++- .../case-ref-field.component.ts | 15 +++- .../src/lib/data-fields/data-field.theme.scss | 21 +++++ 11 files changed, 129 insertions(+), 21 deletions(-) diff --git a/projects/netgrif-components-core/src/assets/i18n/de.json b/projects/netgrif-components-core/src/assets/i18n/de.json index d6d251d723..8ac86d6381 100644 --- a/projects/netgrif-components-core/src/assets/i18n/de.json +++ b/projects/netgrif-components-core/src/assets/i18n/de.json @@ -245,7 +245,8 @@ "maxFilesExceeded": "Die maximale Anzahl hochladbarer Dateien ist überschritten: ", "maxFilesSizeExceeded": "Die maximale Größe der hochgeladenen Dateien wird überschritten: ", "notSelectedUser": "Es wurde kein Benutzer ausgewählt", - "userAssigned": "Benutzer {{userName}} wurde zugewiesen" + "userAssigned": "Benutzer {{userName}} wurde zugewiesen", + "caseNetGetFailed": "Das Abrufen des Fallnetzes ist fehlgeschlagen" }, "values": { "boolean": { diff --git a/projects/netgrif-components-core/src/assets/i18n/en.json b/projects/netgrif-components-core/src/assets/i18n/en.json index 8ef1814019..00a220db7b 100644 --- a/projects/netgrif-components-core/src/assets/i18n/en.json +++ b/projects/netgrif-components-core/src/assets/i18n/en.json @@ -245,7 +245,8 @@ "maxFilesExceeded": "Maximum number of uploadable files exceeded: ", "maxFilesSizeExceeded": "The maximum size of uploaded files is exceeded: ", "notSelectedUser": "No user has been selected", - "userAssigned": "User {{userName}} was assigned" + "userAssigned": "User {{userName}} was assigned", + "caseNetGetFailed": "Getting case Net failed" }, "values": { "boolean": { diff --git a/projects/netgrif-components-core/src/assets/i18n/sk.json b/projects/netgrif-components-core/src/assets/i18n/sk.json index 12e820de73..4a73c9b0bf 100644 --- a/projects/netgrif-components-core/src/assets/i18n/sk.json +++ b/projects/netgrif-components-core/src/assets/i18n/sk.json @@ -245,7 +245,8 @@ "maxFilesExceeded": "Je presiahnutý maximálny počet nahratých súborov: ", "maxFilesSizeExceeded": "Je presiahnutá maximálna veľkosť nahrávaných súborov: ", "notSelectedUser": "Nebol vybraný žiadny používateľ", - "userAssigned": "Používateľ {{userName}} bol pridelený" + "userAssigned": "Používateľ {{userName}} bol pridelený", + "caseNetGetFailed": "Načítanie siete podľa prípadu zlyhalo" }, "values": { "boolean": { diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts index 00a436deeb..4c32ac5bcf 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts @@ -12,7 +12,7 @@ import { } from '@netgrif/petriflow.svg'; import { Arc, - InhibitorArc, + InhibitorArc, Place, ReadArc, RegularPlaceTransitionArc, RegularTransitionPlaceArc, @@ -25,6 +25,10 @@ import {TransitionImport} from '../../resources/interface/transition-import'; import {PlaceImport} from '../../resources/interface/place-import'; import {ArcImport} from '../../resources/interface/arc-import'; import {ArcType} from '../../resources/interface/arc-type'; +import {PetriNetImport} from '../../resources/interface/petri-net-import'; +import {LoggerService} from '../../logger/services/logger.service'; +import {SnackBarService} from '../../snack-bar/services/snack-bar.service'; +import {TranslateService} from '@ngx-translate/core'; @Component({ selector: 'ncc-abstract-case-ref-field', @@ -36,7 +40,8 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { constructor(protected _petriflowCanvasService: PetriflowCanvasService, protected _petriflowFactoryService: PetriflowCanvasFactoryService, protected _petriflowConfigService: PetriflowCanvasConfigurationService, protected _caseResourceService: CaseResourceService, - protected _petriNetResourceService: PetriNetResourceService){ + protected _petriNetResourceService: PetriNetResourceService, protected _log: LoggerService, protected _snackBar: SnackBarService, + protected _translate: TranslateService) { } ngAfterViewInit(): void { @@ -44,6 +49,7 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { if (net) { const trans: Array = []; const places: Array = []; + const arcs: Array> = []; let minX: number = Number.MAX_SAFE_INTEGER; let minY: number = Number.MAX_SAFE_INTEGER; net.transitions.forEach((value) => { @@ -57,17 +63,30 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { minY = Math.min(minY, value.position.y); }) net.arcs.forEach((arc) => { - this.createArcs(trans, places, arc); + arcs.push(this.createArcs(trans, places, arc, net)); arc.breakpoints?.forEach(value => { minX = Math.min(minX, value.x); minY = Math.min(minY, value.y); }); }); - this._petriflowCanvasService.panzoom?.moveTo(-minX+20, -minY+20); - setTimeout(() => { - this._petriflowCanvasService.panzoom?.pause(); - }) + trans.forEach(value => { + if (net.assignedTasks.includes(value.canvasElement.label.textContent)) { + value.activate(); + } + if (this.isEnabled(value, places, arcs)) { + value.canvasElement.element.classList.add('svg-transition-enabled'); + } + }); + this._petriflowCanvasService.panzoom?.moveTo(-minX + 20, -minY + 20); + if (this.dataField.component?.properties?.lock === 'true') { + setTimeout(() => { + this._petriflowCanvasService.panzoom?.pause(); + }) + } } + }, error => { + this._log.error('Getting net by Case ID failed', error); + this._snackBar.openErrorSnackBar(this._translate.instant('dataField.snackBar.caseNetGetFailed')); }); } @@ -85,23 +104,38 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { return place; } - protected createArcs(trans: Array, places: Array, arc: ArcImport) { + protected createArcs(trans: Array, places: Array, arc: ArcImport, net: PetriNetImport) { let source: PetriflowPlace | PetriflowTransition = trans.find(value => value.canvasElement.label.textContent === arc.sourceId); let destination: PetriflowPlace | PetriflowTransition; + let activable: boolean = false; if (source === undefined) { source = places.find(value => value.canvasElement.label.textContent === arc.sourceId); destination = trans.find(value => value.canvasElement.label.textContent === arc.destinationId); + if (net.assignedTasks.includes(destination.canvasElement.label.textContent)) { + source.activate(); + destination.activate(); + activable = true; + } } else { destination = places.find(value => value.canvasElement.label.textContent === arc.destinationId); + if (net.finishedTasks.includes(source.canvasElement.label.textContent)) { + source.activate(); + activable = true; + } } if (source === undefined || destination === undefined) { - console.error("Can't find source or destination for arc [" + arc.importId + "]"); + this._log.error("Can't find source or destination for arc [" + arc.importId + "]"); } else { const newArc: Arc = this.createArc(arc, source, destination); + if (activable) { + newArc.activate(); + } const petriflowArc: PetriflowArc = this.createPetriflowArc(arc, newArc, source); this._petriflowCanvasService.canvas.container.appendChild(newArc.container); this._petriflowCanvasService.petriflowElementsCollection.arcs.push(petriflowArc); + return petriflowArc; } + return undefined } protected createArc(arc: ArcImport, source: PetriflowTransition | PetriflowPlace, destination: PetriflowPlace | PetriflowTransition) { @@ -155,4 +189,40 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { return undefined; } } + + protected isEnabled(t: PetriflowTransition, places: Array, arcs: Array>): boolean { + const testMarking: Map = new Map(); + + for (const place of places) { + testMarking.set(place.canvasElement.id, place.canvasElement.tokensCount); + } + for (const arc of arcs) { + if (arc.element.end.id === t.canvasElement.id && (arc instanceof PetriflowInhibitorArc) && testMarking.get((arc.element.start as Place).id) >= parseInt(arc.element.multiplicity.data, 10)) { + return false; + } + } + for (const arc of arcs) { + if (arc.element.end.id === t.canvasElement.id && (arc instanceof PetriflowReadArc) && testMarking.get((arc.element.start as Place).id) < parseInt(arc.element.multiplicity.data, 10)) { + return false; + } + } + for (const arc of arcs) { + if (arc.element.end.id === t.canvasElement.id && arc instanceof PetriflowPlaceTransitionArc) { + const place = testMarking.get((arc.element.start as Place).id) + testMarking.set((arc.element.start as Place).id, place - parseInt(arc.element.multiplicity.data, 10)); + } + } + for (const place of testMarking.values()) { + if (place < 0) { + return false; + } + } + + return true; + } + + public getHeight() { + return (this.dataField.layout && this.dataField.layout.rows && this.dataField.layout.rows) > 1 ? + this.dataField.layout.rows * CaseRefField.FIELD_HEIGHT : CaseRefField.FIELD_HEIGHT; + } } diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts index af281c3a9c..1f27932406 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts @@ -7,6 +7,8 @@ import {TextFieldView} from '../../text-field/models/text-field'; export class CaseRefField extends DataField { + public static FIELD_HEIGHT: number = 75; + constructor(stringId: string, title: string, value: string, behavior: Behavior, placeholder?: string, description?: string, layout?: Layout, validations?: Array, _component?: Component, parentTaskId?: string) { super(stringId, title, value, behavior, placeholder, description, layout, validations, _component, parentTaskId); diff --git a/projects/netgrif-components-core/src/lib/resources/interface/petri-net-import.ts b/projects/netgrif-components-core/src/lib/resources/interface/petri-net-import.ts index 9d04c89d09..1991637156 100644 --- a/projects/netgrif-components-core/src/lib/resources/interface/petri-net-import.ts +++ b/projects/netgrif-components-core/src/lib/resources/interface/petri-net-import.ts @@ -6,4 +6,6 @@ export interface PetriNetImport { transitions: Array; places: Array; arcs: Array; + assignedTasks: Array; + finishedTasks: Array; } diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html index 7ddce2594f..add89d36dd 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.html @@ -1,3 +1,3 @@
- +
diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss index f93730d60d..7ce06c7f7a 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.scss @@ -1,6 +1,5 @@ .outer { display: flex; - min-height: 300px; width: 100%; max-height: 100%; } diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts index dff37a92ca..e633224473 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts @@ -9,7 +9,9 @@ import { ConfigurationService, TestConfigurationService, CaseRefField, - PetriNetResourceService + PetriNetResourceService, + SnackBarModule, + ErrorSnackBarComponent } from '@netgrif/components-core'; import {CaseRefFieldComponent} from './case-ref-field.component'; import {AngularResizeEventModule} from 'angular-resize-event'; @@ -18,6 +20,7 @@ import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {PetriflowCanvasModule} from '@netgrif/petriflow.svg'; import {Component} from '@angular/core'; import {of} from 'rxjs'; +import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing'; describe('CaseRefFieldComponent', () => { let component: CaseRefFieldComponent; @@ -32,7 +35,7 @@ describe('CaseRefFieldComponent', () => { HttpClientTestingModule, NoopAnimationsModule, PetriflowCanvasModule, - + SnackBarModule ], providers: [ {provide: AuthenticationMethodService, useClass: MockAuthenticationMethodService}, @@ -41,8 +44,7 @@ describe('CaseRefFieldComponent', () => { {provide: PetriNetResourceService, useClass: MyPetriNetResource}, ], declarations: [CaseRefFieldComponent] - }) - .compileComponents(); + }).compileComponents(); fixture = TestBed.createComponent(TestWrapperComponent); component = fixture.debugElement.children[0].componentInstance; fixture.detectChanges(); diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts index 85342010da..361622f848 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts @@ -1,10 +1,17 @@ import {Component} from '@angular/core'; -import {AbstractCaseRefFieldComponent, CaseResourceService, PetriNetResourceService} from '@netgrif/components-core'; +import { + AbstractCaseRefFieldComponent, + CaseResourceService, + PetriNetResourceService, + LoggerService, + SnackBarService +} from '@netgrif/components-core'; import { PetriflowCanvasConfigurationService, PetriflowCanvasFactoryService, PetriflowCanvasService } from '@netgrif/petriflow.svg'; +import {TranslateService} from '@ngx-translate/core'; @Component({ selector: 'nc-case-ref-field', @@ -15,8 +22,10 @@ export class CaseRefFieldComponent extends AbstractCaseRefFieldComponent { constructor(protected _petriflowCanvasService: PetriflowCanvasService, protected _petriflowFactoryService: PetriflowCanvasFactoryService, protected _petriflowConfigService: PetriflowCanvasConfigurationService, protected _caseResourceService: CaseResourceService, - protected _petriNetResourceService: PetriNetResourceService){ - super(_petriflowCanvasService, _petriflowFactoryService, _petriflowConfigService, _caseResourceService, _petriNetResourceService); + protected _petriNetResourceService: PetriNetResourceService, protected _log: LoggerService, protected _snackBar: SnackBarService, + protected _translate: TranslateService){ + super(_petriflowCanvasService, _petriflowFactoryService, _petriflowConfigService, _caseResourceService, _petriNetResourceService, + _log, _snackBar, _translate); } } diff --git a/projects/netgrif-components/src/lib/data-fields/data-field.theme.scss b/projects/netgrif-components/src/lib/data-fields/data-field.theme.scss index 3297a91a4e..8b7169cbc2 100644 --- a/projects/netgrif-components/src/lib/data-fields/data-field.theme.scss +++ b/projects/netgrif-components/src/lib/data-fields/data-field.theme.scss @@ -220,5 +220,26 @@ .form-input-error { border-color: mat.get-color-from-palette($warn) !important; } + + .svg-inactive-stroke { + stroke: black !important; + } + + .svg-inactive-fill { + fill: black !important; + } + + .svg-active-stroke { + stroke: map-get($primary, A200) !important; + } + + .svg-active-fill { + fill: map-get($primary, A200) !important; + } + + .svg-transition-enabled { + stroke: green; + fill: yellowgreen; + } } From 532b3db60172bb690e665b4cc4c7428353d05f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Wed, 21 Sep 2022 10:42:56 +0200 Subject: [PATCH 6/9] [NAE-1684] Frontend component for data field caseRef - little refactor - fix the problem with highlighting --- .../abstract-case-ref-field.component.ts | 106 +++++++++++------- 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts index 4c32ac5bcf..a2814186e8 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts @@ -47,49 +47,64 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { ngAfterViewInit(): void { this._petriNetResourceService.getNetByCaseId(this.dataField.value).subscribe(net => { if (net) { - const trans: Array = []; - const places: Array = []; - const arcs: Array> = []; - let minX: number = Number.MAX_SAFE_INTEGER; - let minY: number = Number.MAX_SAFE_INTEGER; - net.transitions.forEach((value) => { - trans.push(this.createTransitions(value)); - minX = Math.min(minX, value.position.x); - minY = Math.min(minY, value.position.y); - }) - net.places.forEach((value) => { - places.push(this.createPlace(value)); - minX = Math.min(minX, value.position.x); - minY = Math.min(minY, value.position.y); - }) - net.arcs.forEach((arc) => { - arcs.push(this.createArcs(trans, places, arc, net)); - arc.breakpoints?.forEach(value => { - minX = Math.min(minX, value.x); - minY = Math.min(minY, value.y); - }); - }); - trans.forEach(value => { - if (net.assignedTasks.includes(value.canvasElement.label.textContent)) { - value.activate(); - } - if (this.isEnabled(value, places, arcs)) { - value.canvasElement.element.classList.add('svg-transition-enabled'); - } - }); - this._petriflowCanvasService.panzoom?.moveTo(-minX + 20, -minY + 20); - if (this.dataField.component?.properties?.lock === 'true') { - setTimeout(() => { - this._petriflowCanvasService.panzoom?.pause(); - }) - } + this.createNet(net); } }, error => { - this._log.error('Getting net by Case ID failed', error); + this._log.error('Getting net by Case ID failed in field ['+ this.dataField.stringId + ']', error); this._snackBar.openErrorSnackBar(this._translate.instant('dataField.snackBar.caseNetGetFailed')); }); } + protected createNet(net: PetriNetImport) { + const trans: Array = []; + const places: Array = []; + const arcs: Array> = []; + let minX: number = Number.MAX_SAFE_INTEGER; + let minY: number = Number.MAX_SAFE_INTEGER; + net.transitions.forEach((value) => { + const t = this.createTransitions(value) + trans.push(t); + minX = Math.min(minX, value.position.x); + minY = Math.min(minY, value.position.y); + this.setPlaceActions(t.canvasElement.element); + }) + net.places.forEach((value) => { + const p = this.createPlace(value) + places.push(p); + minX = Math.min(minX, value.position.x); + minY = Math.min(minY, value.position.y); + this.setPlaceActions(p.canvasElement.element); + p.canvasElement.markingTokens.forEach(markingToken => { + this.setPlaceActions(markingToken); + }); + }) + net.arcs.forEach((arc) => { + const a = this.createArcs(trans, places, arc, net) + arcs.push(a); + arc.breakpoints?.forEach(value => { + minX = Math.min(minX, value.x); + minY = Math.min(minY, value.y); + }); + this.setPlaceActions(a.element.arcLine); + }); + trans.forEach(value => { + if (net.assignedTasks.includes(value.canvasElement.label.textContent)) { + value.select(); + } + if (this.isEnabled(value, places, arcs)) { + value.canvasElement.element.classList.add('svg-transition-enabled'); + value.canvasElement.element.setAttributeNS(null, 'fill', 'yellowgreen'); + value.canvasElement.element.setAttributeNS(null, 'stroke', 'green'); + } + }); + this._petriflowCanvasService.panzoom?.moveTo(-minX + 20, -minY + 20); + if (this.dataField.component?.properties?.lock === 'true') { + setTimeout(() => { + this._petriflowCanvasService.panzoom?.pause(); + }) + } + } + protected createTransitions(value: TransitionImport): PetriflowTransition { const transition = this._petriflowFactoryService.createTransition(new DOMPoint(value.position.x, value.position.y)); transition.changeId(value.stringId); @@ -112,14 +127,15 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { source = places.find(value => value.canvasElement.label.textContent === arc.sourceId); destination = trans.find(value => value.canvasElement.label.textContent === arc.destinationId); if (net.assignedTasks.includes(destination.canvasElement.label.textContent)) { - source.activate(); - destination.activate(); + source.select(); + destination.select(); activable = true; } } else { destination = places.find(value => value.canvasElement.label.textContent === arc.destinationId); if (net.finishedTasks.includes(source.canvasElement.label.textContent)) { - source.activate(); + source.select(); + destination.select(); activable = true; } } @@ -127,10 +143,10 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { this._log.error("Can't find source or destination for arc [" + arc.importId + "]"); } else { const newArc: Arc = this.createArc(arc, source, destination); + const petriflowArc: PetriflowArc = this.createPetriflowArc(arc, newArc, source); if (activable) { - newArc.activate(); + petriflowArc.select(); } - const petriflowArc: PetriflowArc = this.createPetriflowArc(arc, newArc, source); this._petriflowCanvasService.canvas.container.appendChild(newArc.container); this._petriflowCanvasService.petriflowElementsCollection.arcs.push(petriflowArc); return petriflowArc; @@ -225,4 +241,10 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { return (this.dataField.layout && this.dataField.layout.rows && this.dataField.layout.rows) > 1 ? this.dataField.layout.rows * CaseRefField.FIELD_HEIGHT : CaseRefField.FIELD_HEIGHT; } + + protected setPlaceActions(svgElement: SVGElement) { + svgElement.onmouseenter = () => {}; + svgElement.onmouseleave = () => {}; + } + } From 133c7b6554322009e36b9291e9c7dd7f87595de3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Wed, 21 Sep 2022 12:44:28 +0200 Subject: [PATCH 7/9] [NAE-1684] Frontend component for data field caseRef - fix tests after merge --- .../lib/data-fields/case-ref-field/models/case-ref-field.ts | 1 - .../case-ref-field/case-ref-field.component.spec.ts | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts index 1f27932406..2590c59035 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts @@ -3,7 +3,6 @@ import {Layout} from '../../models/layout'; import {Validation} from '../../models/validation'; import {Component} from '../../models/component'; import {DataField} from '../../models/abstract-data-field'; -import {TextFieldView} from '../../text-field/models/text-field'; export class CaseRefField extends DataField { diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts index e633224473..97f42afac5 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts @@ -10,8 +10,7 @@ import { TestConfigurationService, CaseRefField, PetriNetResourceService, - SnackBarModule, - ErrorSnackBarComponent + SnackBarModule } from '@netgrif/components-core'; import {CaseRefFieldComponent} from './case-ref-field.component'; import {AngularResizeEventModule} from 'angular-resize-event'; @@ -20,7 +19,6 @@ import {NoopAnimationsModule} from '@angular/platform-browser/animations'; import {PetriflowCanvasModule} from '@netgrif/petriflow.svg'; import {Component} from '@angular/core'; import {of} from 'rxjs'; -import {BrowserDynamicTestingModule} from '@angular/platform-browser-dynamic/testing'; describe('CaseRefFieldComponent', () => { let component: CaseRefFieldComponent; From c5e74cdddc9d190a1335eb6323af744deb1350aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Thu, 22 Sep 2022 16:12:47 +0200 Subject: [PATCH 8/9] [NAE-1684] Frontend component for data field caseRef - fix according to PR --- .../src/assets/i18n/en.json | 2 +- .../abstract-case-ref-field.component.ts | 33 +++++++++++-------- .../case-ref-field/models/case-ref-field.ts | 4 +-- .../services/field-converter.service.ts | 2 +- .../case-ref-field.component.spec.ts | 2 +- .../case-ref-field.component.ts | 8 ++--- 6 files changed, 28 insertions(+), 23 deletions(-) diff --git a/projects/netgrif-components-core/src/assets/i18n/en.json b/projects/netgrif-components-core/src/assets/i18n/en.json index 02b28e6c64..f13446f0f4 100644 --- a/projects/netgrif-components-core/src/assets/i18n/en.json +++ b/projects/netgrif-components-core/src/assets/i18n/en.json @@ -246,7 +246,7 @@ "maxFilesSizeExceeded": "The maximum size of uploaded files is exceeded: ", "notSelectedUser": "No user has been selected", "userAssigned": "User {{userName}} was assigned", - "caseNetGetFailed": "Getting case Net failed" + "caseNetGetFailed": "Getting case net failed" }, "values": { "boolean": { diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts index a2814186e8..ac210641bf 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, Input} from '@angular/core'; +import {AfterViewInit, Component, Inject, Input, Optional} from '@angular/core'; import { PetriflowArc, PetriflowCanvasConfigurationService, @@ -29,29 +29,34 @@ import {PetriNetImport} from '../../resources/interface/petri-net-import'; import {LoggerService} from '../../logger/services/logger.service'; import {SnackBarService} from '../../snack-bar/services/snack-bar.service'; import {TranslateService} from '@ngx-translate/core'; +import {AbstractDataFieldComponent} from '../models/abstract-data-field-component'; +import {NAE_INFORM_ABOUT_INVALID_DATA} from '../models/invalid-data-policy-token'; @Component({ selector: 'ncc-abstract-case-ref-field', template: '' }) -export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { +export abstract class AbstractCaseRefFieldComponent extends AbstractDataFieldComponent implements AfterViewInit { @Input() public dataField: CaseRefField; constructor(protected _petriflowCanvasService: PetriflowCanvasService, protected _petriflowFactoryService: PetriflowCanvasFactoryService, protected _petriflowConfigService: PetriflowCanvasConfigurationService, protected _caseResourceService: CaseResourceService, protected _petriNetResourceService: PetriNetResourceService, protected _log: LoggerService, protected _snackBar: SnackBarService, - protected _translate: TranslateService) { + protected _translate: TranslateService, @Optional() @Inject(NAE_INFORM_ABOUT_INVALID_DATA) informAboutInvalidData: boolean | null) { + super(informAboutInvalidData); } ngAfterViewInit(): void { - this._petriNetResourceService.getNetByCaseId(this.dataField.value).subscribe(net => { - if (net) { - this.createNet(net); + this.formControl.valueChanges.subscribe(value => { + if (value?.length > 0) { + this._petriNetResourceService.getNetByCaseId(value[0]).subscribe(net => { + this.createNet(net); + }, error => { + this._log.error('Getting net by Case ID failed in field ['+ this.dataField.stringId + ']', error); + this._snackBar.openErrorSnackBar(this._translate.instant('dataField.snackBar.caseNetGetFailed')); + }); } - }, error => { - this._log.error('Getting net by Case ID failed in field ['+ this.dataField.stringId + ']', error); - this._snackBar.openErrorSnackBar(this._translate.instant('dataField.snackBar.caseNetGetFailed')); }); } @@ -66,16 +71,16 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { trans.push(t); minX = Math.min(minX, value.position.x); minY = Math.min(minY, value.position.y); - this.setPlaceActions(t.canvasElement.element); + this.setEmptyEvents(t.canvasElement.element); }) net.places.forEach((value) => { const p = this.createPlace(value) places.push(p); minX = Math.min(minX, value.position.x); minY = Math.min(minY, value.position.y); - this.setPlaceActions(p.canvasElement.element); + this.setEmptyEvents(p.canvasElement.element); p.canvasElement.markingTokens.forEach(markingToken => { - this.setPlaceActions(markingToken); + this.setEmptyEvents(markingToken); }); }) net.arcs.forEach((arc) => { @@ -85,7 +90,7 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { minX = Math.min(minX, value.x); minY = Math.min(minY, value.y); }); - this.setPlaceActions(a.element.arcLine); + this.setEmptyEvents(a.element.arcLine); }); trans.forEach(value => { if (net.assignedTasks.includes(value.canvasElement.label.textContent)) { @@ -242,7 +247,7 @@ export abstract class AbstractCaseRefFieldComponent implements AfterViewInit { this.dataField.layout.rows * CaseRefField.FIELD_HEIGHT : CaseRefField.FIELD_HEIGHT; } - protected setPlaceActions(svgElement: SVGElement) { + protected setEmptyEvents(svgElement: SVGElement) { svgElement.onmouseenter = () => {}; svgElement.onmouseleave = () => {}; } diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts index 2590c59035..bec9e38508 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/models/case-ref-field.ts @@ -4,11 +4,11 @@ import {Validation} from '../../models/validation'; import {Component} from '../../models/component'; import {DataField} from '../../models/abstract-data-field'; -export class CaseRefField extends DataField { +export class CaseRefField extends DataField> { public static FIELD_HEIGHT: number = 75; - constructor(stringId: string, title: string, value: string, behavior: Behavior, placeholder?: string, + constructor(stringId: string, title: string, value: Array, behavior: Behavior, placeholder?: string, description?: string, layout?: Layout, validations?: Array, _component?: Component, parentTaskId?: string) { super(stringId, title, value, behavior, placeholder, description, layout, validations, _component, parentTaskId); } diff --git a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts index b01866092e..6c1f67304a 100644 --- a/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts +++ b/projects/netgrif-components-core/src/lib/task-content/services/field-converter.service.ts @@ -109,7 +109,7 @@ export class FieldConverterService { return new I18nField(item.stringId, item.name, item.value ?? {defaultValue: ''}, item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component); case FieldTypeResource.CASE_REF: - return new CaseRefField(item.stringId, item.name, item.value ?? {defaultValue: ''}, item.behavior, item.placeholder, + return new CaseRefField(item.stringId, item.name, item.value ?? [], item.behavior, item.placeholder, item.description, item.layout, item.validations, item.component); } } diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts index 97f42afac5..b2a6fdde79 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.spec.ts @@ -62,7 +62,7 @@ describe('CaseRefFieldComponent', () => { template: '' }) class TestWrapperComponent { - field = new CaseRefField('', '', '', { + field = new CaseRefField('', '', [], { required: true, }); } diff --git a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts index 361622f848..b18545cbd1 100644 --- a/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts +++ b/projects/netgrif-components/src/lib/data-fields/case-ref-field/case-ref-field.component.ts @@ -1,10 +1,10 @@ -import {Component} from '@angular/core'; +import {Component, Inject, Optional} from '@angular/core'; import { AbstractCaseRefFieldComponent, CaseResourceService, PetriNetResourceService, LoggerService, - SnackBarService + SnackBarService, NAE_INFORM_ABOUT_INVALID_DATA } from '@netgrif/components-core'; import { PetriflowCanvasConfigurationService, @@ -23,9 +23,9 @@ export class CaseRefFieldComponent extends AbstractCaseRefFieldComponent { constructor(protected _petriflowCanvasService: PetriflowCanvasService, protected _petriflowFactoryService: PetriflowCanvasFactoryService, protected _petriflowConfigService: PetriflowCanvasConfigurationService, protected _caseResourceService: CaseResourceService, protected _petriNetResourceService: PetriNetResourceService, protected _log: LoggerService, protected _snackBar: SnackBarService, - protected _translate: TranslateService){ + protected _translate: TranslateService, @Optional() @Inject(NAE_INFORM_ABOUT_INVALID_DATA) informAboutInvalidData: boolean | null){ super(_petriflowCanvasService, _petriflowFactoryService, _petriflowConfigService, _caseResourceService, _petriNetResourceService, - _log, _snackBar, _translate); + _log, _snackBar, _translate, informAboutInvalidData); } } From b4d227fc17b68bd13de62c8da4505c1b612e6b9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Kov=C3=A1=C4=8Dik?= Date: Tue, 27 Sep 2022 10:41:54 +0200 Subject: [PATCH 9/9] [NAE-1684] Frontend component for data field caseRef - fix according to PR --- .../abstract-case-ref-field.component.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts index ac210641bf..27434c1268 100644 --- a/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts +++ b/projects/netgrif-components-core/src/lib/data-fields/case-ref-field/abstract-case-ref-field.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, Inject, Input, Optional} from '@angular/core'; +import {AfterViewInit, Component, Inject, Input, OnDestroy, Optional} from '@angular/core'; import { PetriflowArc, PetriflowCanvasConfigurationService, @@ -31,14 +31,16 @@ import {SnackBarService} from '../../snack-bar/services/snack-bar.service'; import {TranslateService} from '@ngx-translate/core'; import {AbstractDataFieldComponent} from '../models/abstract-data-field-component'; import {NAE_INFORM_ABOUT_INVALID_DATA} from '../models/invalid-data-policy-token'; +import { Subscription } from 'rxjs'; @Component({ selector: 'ncc-abstract-case-ref-field', template: '' }) -export abstract class AbstractCaseRefFieldComponent extends AbstractDataFieldComponent implements AfterViewInit { +export abstract class AbstractCaseRefFieldComponent extends AbstractDataFieldComponent implements AfterViewInit, OnDestroy { @Input() public dataField: CaseRefField; + protected sub: Subscription; constructor(protected _petriflowCanvasService: PetriflowCanvasService, protected _petriflowFactoryService: PetriflowCanvasFactoryService, protected _petriflowConfigService: PetriflowCanvasConfigurationService, protected _caseResourceService: CaseResourceService, @@ -48,7 +50,7 @@ export abstract class AbstractCaseRefFieldComponent extends AbstractDataFieldCom } ngAfterViewInit(): void { - this.formControl.valueChanges.subscribe(value => { + this.sub = this.formControl.valueChanges.subscribe(value => { if (value?.length > 0) { this._petriNetResourceService.getNetByCaseId(value[0]).subscribe(net => { this.createNet(net); @@ -252,4 +254,8 @@ export abstract class AbstractCaseRefFieldComponent extends AbstractDataFieldCom svgElement.onmouseleave = () => {}; } + ngOnDestroy() { + super.ngOnDestroy(); + this.sub.unsubscribe(); + } }