From 6a77c49ea6bd7300ff0a36299a2b5011e590534c Mon Sep 17 00:00:00 2001 From: 1lutz Date: Tue, 16 Jul 2024 13:38:09 +0200 Subject: [PATCH 1/5] import workflow editor --- package-lock.json | 50 ++++++- package.json | 1 + projects/core/src/lib/core.module.ts | 3 +- .../workflow-editor.component.html | 9 ++ .../workflow-editor.component.scss | 137 ++++++++++++++++++ .../workflow-editor.component.ts | 81 +++++++++++ 6 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 projects/core/src/lib/workflow-editor/workflow-editor.component.html create mode 100644 projects/core/src/lib/workflow-editor/workflow-editor.component.scss create mode 100644 projects/core/src/lib/workflow-editor/workflow-editor.component.ts diff --git a/package-lock.json b/package-lock.json index 76ef0fdbb..6f20ab6e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,6 +43,7 @@ "vis-data": "7.1.9", "vis-timeline": "7.7.3", "vis-util": "5.0.7", + "workflow-editor": "file:../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", "xss": "1.0.15", "zone.js": "~0.14.4" }, @@ -89,6 +90,29 @@ "typescript": "~5.3.3" } }, + "../../../D/Documents/Universität/Bachelorarbeit/Code/workflow-editor": { + "extraneous": true + }, + "../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor": { + "version": "1.0.0", + "dependencies": { + "@dagrejs/dagre": "^1.1.3", + "@json-editor/json-editor": "^2.14.0", + "bootstrap": "^5.3.2", + "error-polyfill": "^0.1.3", + "jsonschema": "^1.4.1", + "litegraph.js": "^0.7.18", + "yaml": "^2.4.5", + "zod": "^3.23.4" + }, + "devDependencies": { + "@anywidget/types": "^0.1.4", + "@types/bootstrap": "^5.2.10", + "esbuild": "^0.19.11", + "esbuild-plugin-polyfill-node": "^0.3.0", + "typescript": "^5.3.3" + } + }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -20544,6 +20568,7 @@ "node_modules/vega-embed/node_modules/yallist": { "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "extraneous": true, "inBundle": true }, "node_modules/vega-encode": { @@ -21571,6 +21596,10 @@ "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.3.tgz", "integrity": "sha512-ZnV3yH8/k58ZPACOXeiHaMuXIiaTk1t0hSUVisbO0t4RjA5wPpUytcxeyiN2h+LZRrmuHIh/1UlrR9e7DHDvTw==" }, + "node_modules/workflow-editor": { + "resolved": "../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", + "link": true + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -36980,7 +37009,8 @@ "yallist": { "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "bundled": true + "bundled": true, + "extraneous": true } } }, @@ -37766,6 +37796,24 @@ "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.3.3.tgz", "integrity": "sha512-ZnV3yH8/k58ZPACOXeiHaMuXIiaTk1t0hSUVisbO0t4RjA5wPpUytcxeyiN2h+LZRrmuHIh/1UlrR9e7DHDvTw==" }, + "workflow-editor": { + "version": "file:../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", + "requires": { + "@anywidget/types": "^0.1.4", + "@dagrejs/dagre": "^1.1.3", + "@json-editor/json-editor": "^2.14.0", + "@types/bootstrap": "^5.2.10", + "bootstrap": "^5.3.2", + "error-polyfill": "^0.1.3", + "esbuild": "^0.19.11", + "esbuild-plugin-polyfill-node": "^0.3.0", + "jsonschema": "^1.4.1", + "litegraph.js": "^0.7.18", + "typescript": "^5.3.3", + "yaml": "^2.4.5", + "zod": "^3.23.4" + } + }, "wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/package.json b/package.json index de564600d..70b1cf6d9 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "vis-data": "7.1.9", "vis-timeline": "7.7.3", "vis-util": "5.0.7", + "workflow-editor": "file:../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", "xss": "1.0.15", "zone.js": "~0.14.4" }, diff --git a/projects/core/src/lib/core.module.ts b/projects/core/src/lib/core.module.ts index 5b8dc7ba7..f01329582 100644 --- a/projects/core/src/lib/core.module.ts +++ b/projects/core/src/lib/core.module.ts @@ -149,6 +149,7 @@ import {SymbologyEditorComponent} from './layers/symbology/symbology-editor/symb import {MapResolutionExtentOverlayComponent} from './map/map-info/map-resolution-extent-overlay.component'; import {DownloadLayerComponent} from './download-layer/download-layer.component'; import {BandwiseExpressionOperatorComponent} from './operators/dialogs/bandwise-expression-operator/bandwise-expression-operator.component'; +import {WorkflowEditorComponent} from "./workflow-editor/workflow-editor.component"; export const MATERIAL_MODULES = [ MatAutocompleteModule, @@ -232,7 +233,6 @@ const CORE_COMPONENTS = [ LayerListMenuComponent, LayerSelectionComponent, LineageGraphComponent, - LineageGraphComponent, LineSimplificationComponent, LoadProjectComponent, LoginComponent, @@ -303,6 +303,7 @@ const CORE_COMPONENTS = [ WorkspaceSettingsComponent, ZoomHandlesComponent, + WorkflowEditorComponent ]; @NgModule({ diff --git a/projects/core/src/lib/workflow-editor/workflow-editor.component.html b/projects/core/src/lib/workflow-editor/workflow-editor.component.html new file mode 100644 index 000000000..cbbd1236c --- /dev/null +++ b/projects/core/src/lib/workflow-editor/workflow-editor.component.html @@ -0,0 +1,9 @@ +{{ title }} +
+ +
+
diff --git a/projects/core/src/lib/workflow-editor/workflow-editor.component.scss b/projects/core/src/lib/workflow-editor/workflow-editor.component.scss new file mode 100644 index 000000000..dd49f196f --- /dev/null +++ b/projects/core/src/lib/workflow-editor/workflow-editor.component.scss @@ -0,0 +1,137 @@ +.detail { + overflow-y: auto; +} + +$general-width: 200px; +$general-header-height: 48px; +$general-margin: 5px; +$operator-height: 136px; +$operator-border-height: 1px; + +.graph { + background-color: #f5f5f5; + height: 50px; + width: 50px; +} + +/* node header */ +:host .graph ::ng-deep .label .header { + width: $general-width - (2 * $general-margin); + padding: $general-margin; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-family: RobotoDraft, Roboto, 'Helvetica Neue', sans-serif; +} + +/* operator header */ +:host .graph ::ng-deep .operator .label .header { + height: $general-header-height - (2 * $general-margin) - $general-header-height; + line-height: $general-header-height - (2 * $general-margin) - $operator-border-height; + color: rgba(0, 0, 0, 0.87); + border-bottom: $operator-border-height solid rgba(0, 0, 0, 0.12); +} + +/* layer header */ +:host .graph ::ng-deep .layer .label .header { + height: $general-header-height - (2 * $general-margin); + line-height: $general-header-height - (2 * $general-margin); + background-color: #3f51b5; + color: rgba(255, 255, 255, 0.87059); +} + +/* layer header accent */ +:host .graph ::ng-deep .layer.accent .label .header { + background-color: #e91e63 !important; +} + +/* operator header icon */ +:host .graph ::ng-deep .label .header .icon { + display: block; + float: left; + width: $general-header-height - (2 * $general-margin) - $operator-border-height; + height: $general-header-height - (2 * $general-margin) - $operator-border-height; + margin-right: $general-margin; + border-radius: $general-margin; +} + +/* operator parameter content */ +:host .graph ::ng-deep .label .parameters { + width: $general-width - (2 * $general-margin); + height: $operator-height - $general-header-height - (2 * $general-margin); + padding: $general-margin; + overflow: hidden; +} + +/* operator parameter content table */ +:host .graph ::ng-deep .label .parameters table { + width: $general-width - (2 * $general-margin); + table-layout: fixed; +} + +:host .graph ::ng-deep .label .parameters .key, +:host .graph ::ng-deep .label .parameters .value { + overflow: hidden; + text-overflow: ellipsis; +} + +:host .graph ::ng-deep .label .parameters .key { + width: 33%; +} + +:host .graph ::ng-deep .label .parameters .value { + width: 67%; +} + +/* node box */ +:host .graph ::ng-deep .node rect { + stroke: rgba(0, 0, 0, 0.12); + fill: #fff; + stroke-width: 1.5px; +} + +/* node box shadow */ +:host .graph ::ng-deep .label > g > foreignObject > div { + box-shadow: + 0 3px 5px -1px rgba(0, 0, 0, 0.2), + 0px 5px 8px 0px rgba(0, 0, 0, 0.14), + 0px 1px 14px 0px rgba(0, 0, 0, 0.12); +} + +/* pointer */ +:host .graph ::ng-deep .operator .label > g > foreignObject > div { + cursor: pointer; +} + +/* highlight */ +:host .graph ::ng-deep .highlight rect { + stroke: #3f51b5 !important; +} + +/* edge */ +:host .graph ::ng-deep .edgePath path { + stroke: #333; + stroke-width: 1.5px; +} + +/* edge to layer */ +:host .graph ::ng-deep .layer-edge path { + stroke-dasharray: 5, 5; +} + +::ng-deep .mat-mdc-list .mat-mdc-list-item .mat-line { + word-wrap: break-word; + white-space: pre-wrap; +} + +::ng-deep .mat-mdc-list .mat-mdc-list-item { + height: initial !important; +} + +::ng-deep .mat-mdc-list .mat-mdc-list-item code { + font-size: smaller !important; +} + +mat-spinner.loading { + position: absolute; +} diff --git a/projects/core/src/lib/workflow-editor/workflow-editor.component.ts b/projects/core/src/lib/workflow-editor/workflow-editor.component.ts new file mode 100644 index 000000000..9b694aadf --- /dev/null +++ b/projects/core/src/lib/workflow-editor/workflow-editor.component.ts @@ -0,0 +1,81 @@ +import {BehaviorSubject, Observable, ReplaySubject} from 'rxjs'; +import {map} from 'rxjs/operators'; +import {Component, ChangeDetectionStrategy, ViewChild, ElementRef, AfterViewInit, Inject} from '@angular/core'; +import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; +import {Layer} from '@geoengine/common'; +import {TypedOperatorOperator} from '@geoengine/openapi-client'; +import {ProjectService} from "../project/project.service"; +import {LayoutService} from "../layout.service"; +import {render, WidgetModel} from "workflow-editor"; +import {UserService} from "../users/user.service"; + +@Component({ + selector: 'geoengine-workflow-editor', + templateUrl: './workflow-editor.component.html', + styleUrls: ['./workflow-editor.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, +}) +export class WorkflowEditorComponent implements AfterViewInit { + readonly title: string; + readonly layer: Layer; + + @ViewChild("widget") + widgetRef!: ElementRef; + + loading: boolean = true; + readonly widgetModel = { + data: {} as WidgetModel, + listeners: {} as Record void>, + get: function (key: K): WidgetModel[K] { + return this.data[key]; + }, + set: function (key: K, value: WidgetModel[K]): void { + const oldValue = this.data[key]; + + if (oldValue !== value) { + this.data[key] = value; + this.listeners["change:" + key]?.call(this, null, []); + } + }, + off: function (eventName?: string, callback?: (...args: any[]) => void): void { + throw new Error('Function not implemented.'); + }, + on: function (eventName: string, callback: (msg: any, buffers: DataView[]) => void): void { + this.listeners[eventName] = callback; + }, + save_changes: function (): void { + throw new Error('Function not implemented.'); + }, + send: function (content: any, callbacks?: any, buffers?: ArrayBuffer[] | ArrayBufferView[] | undefined): void { + throw new Error('Function not implemented.'); + }, + widget_manager: undefined + }; + + constructor( + private elementRef: ElementRef, + private projectService: ProjectService, + private layoutService: LayoutService, + private readonly userService: UserService, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) private config: { layer: Layer }, + ) { + this.layer = this.config.layer; + this.title = `Workflow Editor for ${this.layer.name}`; + this.userService.getSessionStream().subscribe(session => { + this.widgetModel.set("token", session.sessionToken); + this.widgetModel.set("serverUrl", session.apiConfiguration.basePath); + }); + } + + ngAfterViewInit(): void { + this.projectService.getWorkflow(this.layer.workflowId).subscribe(workflow => { + this.loading = false; + this.widgetModel + render({ + model: this.widgetModel, + el: this.widgetRef.nativeElement + }); + }); + } +} From a25b51b74ad7c86a7876cf2b98d2cd43db3f7624 Mon Sep 17 00:00:00 2001 From: 1lutz Date: Fri, 19 Jul 2024 15:52:56 +0200 Subject: [PATCH 2/5] workflow editor now visible --- angular.json | 4 +- package-lock.json | 21 ++- package.json | 1 + .../layer-list-element.component.html | 4 +- .../layer-list-element.component.ts | 4 +- .../workflow-editor.component.scss | 137 ------------------ .../workflow-editor.component.ts | 13 +- projects/core/src/public-api.ts | 1 + 8 files changed, 31 insertions(+), 154 deletions(-) diff --git a/angular.json b/angular.json index cc6bb425e..4fcecf184 100644 --- a/angular.json +++ b/angular.json @@ -108,7 +108,9 @@ "dist/common/assets/fonts/material-design-icons/material-icons.css", "node_modules/codemirror/lib/codemirror.css", "node_modules/ol/ol.css", - "./node_modules/vis-timeline/dist/vis-timeline-graph2d.min.css" + "./node_modules/vis-timeline/dist/vis-timeline-graph2d.min.css", + "D:/Documents/Universität/Bachelorarbeit/Code/workflow-editor/src/workflow_editor/static/widget.css", + "node_modules/@fortawesome/fontawesome-free/css/all.min.css" ], "scripts": ["node_modules/vis-timeline/peer/esm/vis-timeline-graph2d.min.js"], "vendorChunk": true, diff --git a/package-lock.json b/package-lock.json index 6f20ab6e6..3bd16f25b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", "@egjs/hammerjs": "^2.0.17", + "@fortawesome/fontawesome-free": "^5.15.4", "@geoengine/openapi-client": "0.0.9", "codemirror": "~5.65.16", "d3": "~7.9.0", @@ -106,7 +107,6 @@ "zod": "^3.23.4" }, "devDependencies": { - "@anywidget/types": "^0.1.4", "@types/bootstrap": "^5.2.10", "esbuild": "^0.19.11", "esbuild-plugin-polyfill-node": "^0.3.0", @@ -3513,6 +3513,15 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz", + "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, "node_modules/@geoengine/openapi-client": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/@geoengine/openapi-client/-/openapi-client-0.0.9.tgz", @@ -20568,7 +20577,6 @@ "node_modules/vega-embed/node_modules/yallist": { "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "extraneous": true, "inBundle": true }, "node_modules/vega-encode": { @@ -24039,6 +24047,11 @@ "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true }, + "@fortawesome/fontawesome-free": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.4.tgz", + "integrity": "sha512-eYm8vijH/hpzr/6/1CJ/V/Eb1xQFW2nnUKArb3z+yUWv7HTwj6M7SP957oMjfZjAHU6qpoNc2wQvIxBLWYa/Jg==" + }, "@geoengine/openapi-client": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/@geoengine/openapi-client/-/openapi-client-0.0.9.tgz", @@ -37009,8 +37022,7 @@ "yallist": { "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "bundled": true, - "extraneous": true + "bundled": true } } }, @@ -37799,7 +37811,6 @@ "workflow-editor": { "version": "file:../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", "requires": { - "@anywidget/types": "^0.1.4", "@dagrejs/dagre": "^1.1.3", "@json-editor/json-editor": "^2.14.0", "@types/bootstrap": "^5.2.10", diff --git a/package.json b/package.json index 70b1cf6d9..fddcdb1a7 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "@angular/platform-browser-dynamic": "^17.3.0", "@angular/router": "^17.3.0", "@egjs/hammerjs": "^2.0.17", + "@fortawesome/fontawesome-free": "^5.15.4", "@geoengine/openapi-client": "0.0.9", "codemirror": "~5.65.16", "d3": "~7.9.0", diff --git a/projects/core/src/lib/layers/layer-list/layer-list-element/layer-list-element.component.html b/projects/core/src/lib/layers/layer-list/layer-list-element/layer-list-element.component.html index f8a5e46c2..655e1ddaf 100644 --- a/projects/core/src/lib/layers/layer-list/layer-list-element/layer-list-element.component.html +++ b/projects/core/src/lib/layers/layer-list/layer-list-element/layer-list-element.component.html @@ -20,9 +20,9 @@ Hide Legend - + + diff --git a/projects/core/src/lib/datasets/create-workflow/create-workflow.component.scss b/projects/core/src/lib/datasets/create-workflow/create-workflow.component.scss new file mode 100644 index 000000000..ebcbe1e2f --- /dev/null +++ b/projects/core/src/lib/datasets/create-workflow/create-workflow.component.scss @@ -0,0 +1,17 @@ +:host { + display: block; + padding: 1rem; +} + +mat-form-field, +button { + width: 100% !important; +} + +.error { + color: var(--geoengine-warn-color, red); +} + +button { + margin-top: 1rem; +} diff --git a/projects/core/src/lib/datasets/create-workflow/create-workflow.component.ts b/projects/core/src/lib/datasets/create-workflow/create-workflow.component.ts new file mode 100644 index 000000000..9144e3407 --- /dev/null +++ b/projects/core/src/lib/datasets/create-workflow/create-workflow.component.ts @@ -0,0 +1,30 @@ +import { ChangeDetectionStrategy, Component } from '@angular/core'; +import {UntypedFormControl, UntypedFormGroup, Validators} from "@angular/forms"; +import {MatDialog} from "@angular/material/dialog"; +import {WorkflowEditorComponent} from "../../workflow-editor/workflow-editor.component"; +import {LayoutService} from "../../layout.service"; + +@Component({ + selector: 'geoengine-create-workflow', + templateUrl: './create-workflow.component.html', + styleUrl: './create-workflow.component.scss', + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class CreateWorkflowComponent { + readonly form: UntypedFormGroup; + + constructor( + protected readonly dialog: MatDialog, + protected readonly layoutService: LayoutService + ) { + this.form = new UntypedFormGroup({ + layerName: new UntypedFormControl('New Layer', Validators.required) + }); + } + + openEditor(): void { + this.layoutService.setSidenavContentComponent(undefined); + const layerName: string = this.form.controls.layerName.value; + this.dialog.open(WorkflowEditorComponent, {data: {layerOrNewName: layerName}}); + } +} diff --git a/projects/core/src/lib/datasets/dataset.service.ts b/projects/core/src/lib/datasets/dataset.service.ts index 6fee0a38a..b1a000807 100644 --- a/projects/core/src/lib/datasets/dataset.service.ts +++ b/projects/core/src/lib/datasets/dataset.service.ts @@ -8,12 +8,12 @@ import { AutoCreateDatasetDict, CreateDatasetDict, DatasetNameResponseDict, - MetaDataSuggestionDict, + MetaDataSuggestionDict, RasterResultDescriptorDict, SuggestMetaDataDict, UploadFileLayersResponseDict, UploadFilesResponseDict, UploadResponseDict, - UUID, + UUID, VectorResultDescriptorDict, } from '../backend/backend.model'; import {RandomColorService} from '../util/services/random-color.service'; import {ProjectService} from '../project/project.service'; @@ -31,6 +31,7 @@ import { VectorResultDescriptor, VectorSymbology, colorToDict, + createVectorSymbology, } from '@geoengine/common'; import {Workflow as WorkflowDict} from '@geoengine/openapi-client'; @@ -44,7 +45,8 @@ export class DatasetService { protected userService: UserService, protected projectService: ProjectService, protected randomColorService: RandomColorService, - ) {} + ) { + } getDatasets(offset = 0, limit = 20): Observable> { return this.userService.getSessionStream().pipe( @@ -59,6 +61,7 @@ export class DatasetService { map((dict) => Dataset.fromDict(dict)), ); } + upload(form: FormData): Observable> { return this.userService.getSessionTokenForRequest().pipe(mergeMap((token) => this.backend.upload(token, form))); } @@ -103,6 +106,60 @@ export class DatasetService { return this.projectService.registerWorkflow(workflow).pipe(map((workflowId) => this.createLayer(workflowId, dataset))); } + createLayerFromWorkflow(layerName: string, workflowId: UUID): Observable { + return this.projectService.getWorkflowMetaData(workflowId).pipe( + map(resultDescriptorDict => { + const keys = Object.keys(resultDescriptorDict); + + if (keys.includes('columns')) { + return this.createVectorLayer(layerName, workflowId, resultDescriptorDict as VectorResultDescriptorDict); + } else if (keys.includes('bands')) { + return this.createRasterLayer(layerName, workflowId, resultDescriptorDict as RasterResultDescriptorDict); + } else { + // TODO: implement plots, etc. + throw new Error('Adding this workflow type is unimplemented, yet'); + } + }) + ); + } + + private createVectorLayer(layerName: string, workflowId: UUID, resultDescriptor: VectorResultDescriptorDict): VectorLayer { + return new VectorLayer({ + name: layerName, + workflowId, + isVisible: true, + isLegendVisible: false, + symbology: createVectorSymbology(resultDescriptor.dataType, this.randomColorService.getRandomColorRgba()), + }); + } + + private createRasterLayer(layerName: string, workflowId: UUID, _resultDescriptor: RasterResultDescriptorDict): RasterLayer { + return new RasterLayer({ + name: layerName, + workflowId, + isVisible: true, + isLegendVisible: false, + symbology: RasterSymbology.fromRasterSymbologyDict({ + type: 'raster', + opacity: 1.0, + rasterColorizer: { + type: 'singleBand', + band: 0, + bandColorizer: { + type: 'linearGradient', + breakpoints: [ + {value: 1, color: [0, 0, 0, 255]}, + {value: 255, color: [255, 255, 255, 255]}, + ], + overColor: [255, 255, 255, 127], + underColor: [0, 0, 0, 127], + noDataColor: [0, 0, 0, 0], + }, + }, + }), + }); + } + createLayer(workflowId: string, dataset: Dataset): Layer { if (dataset.resultDescriptor.getTypeString() === 'Raster') { const symbology = dataset.symbology as RasterSymbology; @@ -112,23 +169,23 @@ export class DatasetService { symbology: symbology ? symbology : RasterSymbology.fromRasterSymbologyDict({ - type: 'raster', - opacity: 1.0, - rasterColorizer: { - type: 'singleBand', - band: 0, - bandColorizer: { - type: 'linearGradient', - breakpoints: [ - {value: 1, color: [0, 0, 0, 255]}, - {value: 255, color: [255, 255, 255, 255]}, - ], - overColor: [255, 255, 255, 127], - underColor: [0, 0, 0, 127], - noDataColor: [0, 0, 0, 0], - }, - }, - }), + type: 'raster', + opacity: 1.0, + rasterColorizer: { + type: 'singleBand', + band: 0, + bandColorizer: { + type: 'linearGradient', + breakpoints: [ + {value: 1, color: [0, 0, 0, 255]}, + {value: 255, color: [255, 255, 255, 255]}, + ], + overColor: [255, 255, 255, 127], + underColor: [0, 0, 0, 127], + noDataColor: [0, 0, 0, 0], + }, + }, + }), isLegendVisible: false, isVisible: true, }); @@ -142,63 +199,63 @@ export class DatasetService { symbology = (dataset.symbology as PointSymbology) ? (dataset.symbology as PointSymbology) : ClusteredPointSymbology.fromPointSymbologyDict({ - type: 'point', - radius: { - type: 'static', - value: PointSymbology.DEFAULT_POINT_RADIUS, - }, - stroke: { - width: { - type: 'static', - value: 1, - }, - color: { - type: 'static', - color: [0, 0, 0, 255], - }, - }, - fillColor: { - type: 'static', - color: colorToDict(this.randomColorService.getRandomColorRgba()), - }, - }); + type: 'point', + radius: { + type: 'static', + value: PointSymbology.DEFAULT_POINT_RADIUS, + }, + stroke: { + width: { + type: 'static', + value: 1, + }, + color: { + type: 'static', + color: [0, 0, 0, 255], + }, + }, + fillColor: { + type: 'static', + color: colorToDict(this.randomColorService.getRandomColorRgba()), + }, + }); break; case VectorDataTypes.MultiLineString: symbology = (dataset.symbology as LineSymbology) ? (dataset.symbology as LineSymbology) : LineSymbology.fromLineSymbologyDict({ - type: 'line', - stroke: { - width: {type: 'static', value: 1}, - color: { - type: 'static', - color: colorToDict(this.randomColorService.getRandomColorRgba()), - }, - }, - autoSimplified: true, - }); + type: 'line', + stroke: { + width: {type: 'static', value: 1}, + color: { + type: 'static', + color: colorToDict(this.randomColorService.getRandomColorRgba()), + }, + }, + autoSimplified: true, + }); break; case VectorDataTypes.MultiPolygon: symbology = (dataset.symbology as PolygonSymbology) ? (dataset.symbology as PolygonSymbology) : PolygonSymbology.fromPolygonSymbologyDict({ - type: 'polygon', - stroke: { - width: { - type: 'static', - value: 1, - }, - color: { - type: 'static', - color: [0, 0, 0, 255], - }, - }, - fillColor: { - type: 'static', - color: colorToDict(this.randomColorService.getRandomColorRgba()), - }, - autoSimplified: true, - }); + type: 'polygon', + stroke: { + width: { + type: 'static', + value: 1, + }, + color: { + type: 'static', + color: [0, 0, 0, 255], + }, + }, + fillColor: { + type: 'static', + color: colorToDict(this.randomColorService.getRandomColorRgba()), + }, + autoSimplified: true, + }); break; default: throw Error('unknown symbology type'); diff --git a/projects/core/src/lib/layers/layer-list/layer-list-element/layer-list-element.component.html b/projects/core/src/lib/layers/layer-list/layer-list-element/layer-list-element.component.html index 655e1ddaf..5373b6cf5 100644 --- a/projects/core/src/lib/layers/layer-list/layer-list-element/layer-list-element.component.html +++ b/projects/core/src/lib/layers/layer-list/layer-list-element/layer-list-element.component.html @@ -20,7 +20,7 @@ Hide Legend - diff --git a/projects/core/src/lib/workflow-editor/workflow-editor.component.html b/projects/core/src/lib/workflow-editor/workflow-editor.component.html index cbbd1236c..2f01fabc1 100644 --- a/projects/core/src/lib/workflow-editor/workflow-editor.component.html +++ b/projects/core/src/lib/workflow-editor/workflow-editor.component.html @@ -1,9 +1,21 @@ {{ title }} -
- -
+
+
+
+ + + + + +
diff --git a/projects/core/src/lib/workflow-editor/workflow-editor.component.ts b/projects/core/src/lib/workflow-editor/workflow-editor.component.ts index 268c4b2fc..ed745e5bb 100644 --- a/projects/core/src/lib/workflow-editor/workflow-editor.component.ts +++ b/projects/core/src/lib/workflow-editor/workflow-editor.component.ts @@ -2,9 +2,53 @@ import {Component, ChangeDetectionStrategy, ViewChild, ElementRef, AfterViewInit import {MAT_DIALOG_DATA, MatDialogRef} from '@angular/material/dialog'; import {Layer} from '@geoengine/common'; import {ProjectService} from "../project/project.service"; -import {LayoutService} from "../layout.service"; import {render, WidgetModel} from "workflow-editor"; import {UserService} from "../users/user.service"; +import {BehaviorSubject, mergeMap} from "rxjs"; +import {map} from "rxjs/operators"; +import {NotificationService} from "../notification.service"; +import {DatasetService} from "../datasets/dataset.service"; + +class WidgetModelWrapper { + data: WidgetModel = {} as any; + listeners: Record void)[]> = {}; + widget_manager: undefined; + + get(key: K): WidgetModel[K] { + return this.data[key]; + } + + set(key: K, value: WidgetModel[K]): void { + const oldValue = this.data[key]; + + if (oldValue !== value) { + this.data[key] = value; + this.listeners["change:" + key]?.forEach(listener => listener.call(this, null, [])); + } + } + + off(_eventName?: string, _callback?: (...args: any[]) => void): void { + throw new Error('Function not implemented.'); + } + + on(eventName: string, callback: (msg: any, buffers: DataView[]) => void): void { + let selectedListeners = this.listeners[eventName]; + + if (selectedListeners) { + selectedListeners.push(callback); + } else { + this.listeners[eventName] = [callback]; + } + } + + save_changes(): void { + //noop + } + + send(_content: any, _callbacks?: any, _buffers?: ArrayBuffer[] | ArrayBufferView[] | undefined): void { + throw new Error('Function not implemented.'); + } +} @Component({ selector: 'geoengine-workflow-editor', @@ -14,67 +58,80 @@ import {UserService} from "../users/user.service"; }) export class WorkflowEditorComponent implements AfterViewInit { readonly title: string; - readonly layer: Layer; + readonly layerName: string; + readonly layer?: Layer; @ViewChild("widget") - widgetRef!: ElementRef; - loading: boolean = true; - readonly widgetModel = { - data: {} as WidgetModel, - listeners: {} as Record void>, - get: function (key: K): WidgetModel[K] { - return this.data[key]; - }, - set: function (key: K, value: WidgetModel[K]): void { - const oldValue = this.data[key]; - - if (oldValue !== value) { - this.data[key] = value; - this.listeners["change:" + key]?.call(this, null, []); - } - }, - off: function (eventName?: string, callback?: (...args: any[]) => void): void { - throw new Error('Function not implemented.'); - }, - on: function (eventName: string, callback: (msg: any, buffers: DataView[]) => void): void { - this.listeners[eventName] = callback; - }, - save_changes: function (): void { - //noop - }, - send: function (content: any, callbacks?: any, buffers?: ArrayBuffer[] | ArrayBufferView[] | undefined): void { - throw new Error('Function not implemented.'); - }, - widget_manager: undefined - }; + readonly widgetRef!: ElementRef; + readonly loading$; + readonly isValid$ = new BehaviorSubject(false); + readonly widgetModel = new WidgetModelWrapper(); constructor( private elementRef: ElementRef, private projectService: ProjectService, - private layoutService: LayoutService, private userService: UserService, private dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) private config: { layer: Layer }, + private notificationService: NotificationService, + private datasetService: DatasetService, + @Inject(MAT_DIALOG_DATA) private config: { layerOrNewName: Layer | string }, ) { - this.layer = this.config.layer; - this.title = `Workflow Editor for ${this.layer.name}`; + if (typeof this.config.layerOrNewName === "string") { + this.layerName = this.config.layerOrNewName; + this.loading$ = new BehaviorSubject(false); + } else { + this.layer = this.config.layerOrNewName; + this.layerName = this.layer.name; + this.loading$ = new BehaviorSubject(true); + } + this.title = `Workflow Editor for ${this.layerName}`; this.userService.getSessionStream().subscribe(session => { this.widgetModel.set("token", session.sessionToken); this.widgetModel.set("serverUrl", session.apiConfiguration.basePath); }); + this.widgetModel.on("change:workflow", () => { + const workflow = this.widgetModel.get("workflow"); + this.isValid$.next(workflow != null); + }); } ngAfterViewInit(): void { - this.projectService.getWorkflow(this.layer.workflowId).subscribe(workflow => { - this.loading = false; - this.widgetModel.set("workflow", workflow as any); + if (this.layer) { + this.projectService.getWorkflow(this.layer.workflowId).subscribe(workflow => { + this.widgetModel.set("workflow", workflow as any); + render({ + model: this.widgetModel, + el: this.widgetRef.nativeElement + }); + this.loading$.next(false); + }); + } else { render({ model: this.widgetModel, el: this.widgetRef.nativeElement }); - this.widgetModel.on("change:workflow", () => { - console.log("New workflow was exported to UI:", this.widgetModel.get("workflow")); + } + } + + onSave() { + const layerCopy = this.layer; + + if (layerCopy) { + this.projectService.registerWorkflow(this.widgetModel.get("workflow")!).pipe( + map(workflowId => this.projectService.changeLayer(layerCopy, { + workflowId + })) + ).subscribe(() => { + this.dialogRef.close(); + this.notificationService.info(`Updated layer »${this.layerName}«`); }); - }); + } else { + this.projectService.registerWorkflow(this.widgetModel.get("workflow")!).pipe( + mergeMap(workflowId => this.datasetService.createLayerFromWorkflow(this.layerName, workflowId)), + map(layer => this.projectService.addLayer(layer)) + ).subscribe(() => { + this.dialogRef.close(); + }) + } } } diff --git a/projects/core/src/public-api.ts b/projects/core/src/public-api.ts index c32ac223d..59b082795 100644 --- a/projects/core/src/public-api.ts +++ b/projects/core/src/public-api.ts @@ -23,6 +23,7 @@ export * from './lib/util/services/random-color.service'; // Components export * from './lib/datasets/add-data/add-data.component'; export * from './lib/datasets/add-workflow/add-workflow.component'; +export * from './lib/datasets/create-workflow/create-workflow.component'; export * from './lib/datasets/dataset-list/dataset-list.component'; export * from './lib/datasets/dataset/dataset.component'; export * from './lib/datasets/drag-and-drop/drag-and-drop.component'; diff --git a/projects/dashboards/gfbio/src/app/app.component.ts b/projects/dashboards/gfbio/src/app/app.component.ts index dbf69f2f2..98d09f77c 100644 --- a/projects/dashboards/gfbio/src/app/app.component.ts +++ b/projects/dashboards/gfbio/src/app/app.component.ts @@ -248,6 +248,7 @@ export class AppComponent implements OnInit, AfterViewInit { AddDataComponent.createUploadButton(), AddDataComponent.createDrawFeaturesButton(), AddDataComponent.createAddWorkflowByIdButton(), + AddDataComponent.createWorkflowEditorButton() ]), ); } diff --git a/projects/gis/src/app/main/main.component.ts b/projects/gis/src/app/main/main.component.ts index 7235d0458..eb1af0db0 100644 --- a/projects/gis/src/app/main/main.component.ts +++ b/projects/gis/src/app/main/main.component.ts @@ -36,7 +36,6 @@ import { TimeConfigComponent, PlotListComponent, SidenavConfig, - SpatialReferenceService, LayerCollectionService, TaskListComponent, } from '@geoengine/core'; @@ -87,7 +86,6 @@ export class MainComponent implements OnInit, AfterViewInit { private readonly activatedRoute: ActivatedRoute, private readonly notificationService: NotificationService, private readonly mapService: MapService, - private readonly spatialReferenceService: SpatialReferenceService, ) { vcRef.length; // eslint-disable-line @typescript-eslint/no-unused-expressions @@ -233,6 +231,7 @@ export class MainComponent implements OnInit, AfterViewInit { AddDataComponent.createUploadButton(), AddDataComponent.createDrawFeaturesButton(), AddDataComponent.createAddWorkflowByIdButton(), + AddDataComponent.createWorkflowEditorButton() ]), ); } From 511a2e818c00bed168e7ff9b6d5d0d977b5ee783 Mon Sep 17 00:00:00 2001 From: 1lutz Date: Thu, 19 Sep 2024 16:45:19 +0200 Subject: [PATCH 4/5] use workflow-editor as git dependency --- package-lock.json | 255 +++++++++++++++++++++++++++++++++++++++++----- package.json | 2 +- 2 files changed, 229 insertions(+), 28 deletions(-) diff --git a/package-lock.json b/package-lock.json index 93a8e98a9..465aea5f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,7 +44,7 @@ "vis-data": "7.1.9", "vis-timeline": "7.7.3", "vis-util": "5.0.7", - "workflow-editor": "file:../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", + "workflow-editor": "git+https://github.com/1lutz/workflow-editor.git", "xss": "1.0.15", "zone.js": "~0.14.4" }, @@ -94,25 +94,6 @@ "../../../D/Documents/Universität/Bachelorarbeit/Code/workflow-editor": { "extraneous": true }, - "../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor": { - "version": "1.0.0", - "dependencies": { - "@dagrejs/dagre": "^1.1.3", - "@json-editor/json-editor": "^2.14.0", - "bootstrap": "^5.3.2", - "error-polyfill": "^0.1.3", - "jsonschema": "^1.4.1", - "litegraph.js": "^0.7.18", - "yaml": "^2.4.5", - "zod": "^3.23.4" - }, - "devDependencies": { - "@types/bootstrap": "^5.2.10", - "esbuild": "^0.19.11", - "esbuild-plugin-polyfill-node": "^0.3.0", - "typescript": "^5.3.3" - } - }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", @@ -2988,6 +2969,22 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@dagrejs/dagre": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@dagrejs/dagre/-/dagre-1.1.4.tgz", + "integrity": "sha512-QUTc54Cg/wvmlEUxB+uvoPVKFazM1H18kVHBQNmK2NbrDR5ihOCR6CXLnDSZzMcSQKJtabPUWridBOlJM3WkDg==", + "dependencies": { + "@dagrejs/graphlib": "2.2.4" + } + }, + "node_modules/@dagrejs/graphlib": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.2.4.tgz", + "integrity": "sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw==", + "engines": { + "node": ">17.0.0" + } + }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -3751,6 +3748,17 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@json-editor/json-editor": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/@json-editor/json-editor/-/json-editor-2.15.1.tgz", + "integrity": "sha512-Z4KFXpL7I9wrKD94c1PcIwFfCvUzYhwM0jH2ihP2OSH8wut0FnqzCfKCL0gdNHG3A2UVsyVJBoU9Iwsc0xB6zQ==", + "dependencies": { + "core-js": "^3.27.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -5126,6 +5134,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@puppeteer/browsers": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.2.0.tgz", @@ -8085,6 +8103,24 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, + "node_modules/bootstrap": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "@popperjs/core": "^2.11.8" + } + }, "node_modules/bplist-parser": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", @@ -8376,6 +8412,11 @@ } ] }, + "node_modules/capability": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/capability/-/capability-0.2.5.tgz", + "integrity": "sha512-rsJZYVCgXd08sPqwmaIqjAd5SUTfonV0z/gDJ8D6cN8wQphky1kkAYEqQ+hmDxTw7UihvBfjUVUSY+DBEe44jg==" + }, "node_modules/caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -8848,6 +8889,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/core-js": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-js-compat": { "version": "3.36.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", @@ -10656,6 +10707,16 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/error-polyfill": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/error-polyfill/-/error-polyfill-0.1.3.tgz", + "integrity": "sha512-XHJk60ufE+TG/ydwp4lilOog549iiQF2OAPhkk9DdiYWMrltz5yhDz/xnKuenNwP7gy3dsibssO5QpVhkrSzzg==", + "dependencies": { + "capability": "^0.2.5", + "o3": "^1.0.3", + "u3": "^0.1.1" + } + }, "node_modules/es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -14192,6 +14253,14 @@ "node >= 0.2.0" ] }, + "node_modules/jsonschema": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "engines": { + "node": "*" + } + }, "node_modules/jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", @@ -14623,6 +14692,11 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/litegraph.js": { + "version": "0.7.18", + "resolved": "https://registry.npmjs.org/litegraph.js/-/litegraph.js-0.7.18.tgz", + "integrity": "sha512-1WEwjOO58j4FcLX8DvsuMXM371MEq4Y+8pBr3q2pBhJ9nDkwBtBd9Gj6bxArBKhW6i42bSOyv9ybeuez6NAxoQ==" + }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -16402,6 +16476,14 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/o3": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/o3/-/o3-1.0.3.tgz", + "integrity": "sha512-f+4n+vC6s4ysy7YO7O2gslWZBUu8Qj2i2OUJOvjRxQva7jVjYjB29jrr9NCjmxZQR0gzrOcv1RnqoYOeMs5VRQ==", + "dependencies": { + "capability": "^0.2.5" + } + }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -20228,6 +20310,11 @@ "node": ">=14.17" } }, + "node_modules/u3": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/u3/-/u3-0.1.1.tgz", + "integrity": "sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w==" + }, "node_modules/ua-parser-js": { "version": "0.7.35", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz", @@ -21605,8 +21692,26 @@ "integrity": "sha512-ZnV3yH8/k58ZPACOXeiHaMuXIiaTk1t0hSUVisbO0t4RjA5wPpUytcxeyiN2h+LZRrmuHIh/1UlrR9e7DHDvTw==" }, "node_modules/workflow-editor": { - "resolved": "../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", - "link": true + "version": "1.0.0", + "resolved": "git+ssh://git@github.com/1lutz/workflow-editor.git#af6d7d29e2da77c9f123d253c3672ba0135b8ad8", + "dependencies": { + "@dagrejs/dagre": "^1.1.3", + "@json-editor/json-editor": "^2.14.0", + "bootstrap": "^5.3.2", + "error-polyfill": "^0.1.3", + "jsonschema": "^1.4.1", + "litegraph.js": "^0.7.18", + "yaml": "^2.4.5", + "zod": "^3.23.4" + } + }, + "node_modules/workflow-editor/node_modules/zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } }, "node_modules/wrap-ansi": { "version": "7.0.0", @@ -21793,6 +21898,17 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -23773,6 +23889,19 @@ } } }, + "@dagrejs/dagre": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@dagrejs/dagre/-/dagre-1.1.4.tgz", + "integrity": "sha512-QUTc54Cg/wvmlEUxB+uvoPVKFazM1H18kVHBQNmK2NbrDR5ihOCR6CXLnDSZzMcSQKJtabPUWridBOlJM3WkDg==", + "requires": { + "@dagrejs/graphlib": "2.2.4" + } + }, + "@dagrejs/graphlib": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@dagrejs/graphlib/-/graphlib-2.2.4.tgz", + "integrity": "sha512-mepCf/e9+SKYy1d02/UkvSy6+6MoyXhVxP8lLDfA7BPE1X1d4dR0sZznmbM8/XVJ1GPM+Svnx7Xj6ZweByWUkw==" + }, "@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -24222,6 +24351,14 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "@json-editor/json-editor": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/@json-editor/json-editor/-/json-editor-2.15.1.tgz", + "integrity": "sha512-Z4KFXpL7I9wrKD94c1PcIwFfCvUzYhwM0jH2ihP2OSH8wut0FnqzCfKCL0gdNHG3A2UVsyVJBoU9Iwsc0xB6zQ==", + "requires": { + "core-js": "^3.27.2" + } + }, "@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", @@ -25392,6 +25529,12 @@ } } }, + "@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "peer": true + }, "@puppeteer/browsers": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-2.2.0.tgz", @@ -27747,6 +27890,12 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, + "bootstrap": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.3.tgz", + "integrity": "sha512-8HLCdWgyoMguSO9o+aH+iuZ+aht+mzW0u3HIMzVu7Srrpv7EBBxTnrFlSCskwdY1+EOFQSm7uMJhNQHkdPcmjg==", + "requires": {} + }, "bplist-parser": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", @@ -27943,6 +28092,11 @@ "integrity": "sha512-7LjJvmQU6Sj7bL0j5b5WY/3n7utXUJvAe1lxhsHDbLmwX9mdL86Yjtr+5SRCyf8qME4M7pU2hswj0FpyBVCv9w==", "dev": true }, + "capability": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/capability/-/capability-0.2.5.tgz", + "integrity": "sha512-rsJZYVCgXd08sPqwmaIqjAd5SUTfonV0z/gDJ8D6cN8wQphky1kkAYEqQ+hmDxTw7UihvBfjUVUSY+DBEe44jg==" + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -28319,6 +28473,11 @@ } } }, + "core-js": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.38.1.tgz", + "integrity": "sha512-OP35aUorbU3Zvlx7pjsFdu1rGNnD4pgw/CWoYzRY3t2EzoVT7shKHY1dlAy3f41cGIO7ZDPQimhGFTlEYkG/Hw==" + }, "core-js-compat": { "version": "3.36.0", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", @@ -29689,6 +29848,16 @@ "is-arrayish": "^0.2.1" } }, + "error-polyfill": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/error-polyfill/-/error-polyfill-0.1.3.tgz", + "integrity": "sha512-XHJk60ufE+TG/ydwp4lilOog549iiQF2OAPhkk9DdiYWMrltz5yhDz/xnKuenNwP7gy3dsibssO5QpVhkrSzzg==", + "requires": { + "capability": "^0.2.5", + "o3": "^1.0.3", + "u3": "^0.1.1" + } + }, "es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -32314,6 +32483,11 @@ "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", "dev": true }, + "jsonschema": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", + "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==" + }, "jsprim": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", @@ -32658,6 +32832,11 @@ "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==", "dev": true }, + "litegraph.js": { + "version": "0.7.18", + "resolved": "https://registry.npmjs.org/litegraph.js/-/litegraph.js-0.7.18.tgz", + "integrity": "sha512-1WEwjOO58j4FcLX8DvsuMXM371MEq4Y+8pBr3q2pBhJ9nDkwBtBd9Gj6bxArBKhW6i42bSOyv9ybeuez6NAxoQ==" + }, "loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", @@ -33890,6 +34069,14 @@ } } }, + "o3": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/o3/-/o3-1.0.3.tgz", + "integrity": "sha512-f+4n+vC6s4ysy7YO7O2gslWZBUu8Qj2i2OUJOvjRxQva7jVjYjB29jrr9NCjmxZQR0gzrOcv1RnqoYOeMs5VRQ==", + "requires": { + "capability": "^0.2.5" + } + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -36762,6 +36949,11 @@ "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true }, + "u3": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/u3/-/u3-0.1.1.tgz", + "integrity": "sha512-+J5D5ir763y+Am/QY6hXNRlwljIeRMZMGs0cT6qqZVVzzT3X3nFPXVyPOFRMOR4kupB0T8JnCdpWdp6Q/iXn3w==" + }, "ua-parser-js": { "version": "0.7.35", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.35.tgz", @@ -37809,20 +38001,24 @@ "integrity": "sha512-ZnV3yH8/k58ZPACOXeiHaMuXIiaTk1t0hSUVisbO0t4RjA5wPpUytcxeyiN2h+LZRrmuHIh/1UlrR9e7DHDvTw==" }, "workflow-editor": { - "version": "file:../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", + "version": "git+ssh://git@github.com/1lutz/workflow-editor.git#af6d7d29e2da77c9f123d253c3672ba0135b8ad8", + "from": "workflow-editor@git+https://github.com/1lutz/workflow-editor.git", "requires": { "@dagrejs/dagre": "^1.1.3", "@json-editor/json-editor": "^2.14.0", - "@types/bootstrap": "^5.2.10", "bootstrap": "^5.3.2", "error-polyfill": "^0.1.3", - "esbuild": "^0.19.11", - "esbuild-plugin-polyfill-node": "^0.3.0", "jsonschema": "^1.4.1", "litegraph.js": "^0.7.18", - "typescript": "^5.3.3", "yaml": "^2.4.5", "zod": "^3.23.4" + }, + "dependencies": { + "zod": { + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==" + } } }, "wrap-ansi": { @@ -37956,6 +38152,11 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==" + }, "yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", diff --git a/package.json b/package.json index 4e018ede5..96a3263fb 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "vis-data": "7.1.9", "vis-timeline": "7.7.3", "vis-util": "5.0.7", - "workflow-editor": "file:../../../Documents/Universität/Bachelorarbeit/Code/workflow-editor", + "workflow-editor": "git+https://github.com/1lutz/workflow-editor.git", "xss": "1.0.15", "zone.js": "~0.14.4" }, From 0d3aaaffe626d2d591e8548612b28d4d72f62d13 Mon Sep 17 00:00:00 2001 From: 1lutz Date: Sat, 1 Mar 2025 15:17:07 +0100 Subject: [PATCH 5/5] fix workflow-editor ref --- angular.json | 2 +- package-lock.json | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/angular.json b/angular.json index 4fcecf184..f2f5a0297 100644 --- a/angular.json +++ b/angular.json @@ -109,7 +109,7 @@ "node_modules/codemirror/lib/codemirror.css", "node_modules/ol/ol.css", "./node_modules/vis-timeline/dist/vis-timeline-graph2d.min.css", - "D:/Documents/Universität/Bachelorarbeit/Code/workflow-editor/src/workflow_editor/static/widget.css", + "node_modules/workflow-editor/src/workflow_editor/static/widget.css", "node_modules/@fortawesome/fontawesome-free/css/all.min.css" ], "scripts": ["node_modules/vis-timeline/peer/esm/vis-timeline-graph2d.min.js"], diff --git a/package-lock.json b/package-lock.json index 465aea5f8..b24a711ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -91,9 +91,6 @@ "typescript": "~5.3.3" } }, - "../../../D/Documents/Universität/Bachelorarbeit/Code/workflow-editor": { - "extraneous": true - }, "node_modules/@aashutoshrathi/word-wrap": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",