This is an automated email from the ASF dual-hosted git repository. zehnder pushed a commit to branch 3112-opc-ua-multi-node-selection-editor in repository https://gitbox.apache.org/repos/asf/streampipes.git
commit 81007e260b5949ca4ba0afcc4c8a7fdf2d070a9f Author: Philipp Zehnder <[email protected]> AuthorDate: Tue Aug 13 10:16:33 2024 +0200 feat(#3112): First version of text input works now --- ui/cypress/support/builder/AdapterBuilder.ts | 4 +- .../support/builder/TreeNodeUserInputBuilder.ts | 24 +++++---- ui/cypress/support/model/TreeNodeUserInput.ts | 4 +- ui/cypress/support/model/UserInput.ts | 4 +- .../utils/userInput/TreeStaticPropertyUtils.ts | 41 +++++++++++---- ui/cypress/tests/connect/opcua/opcAdapter.spec.ts | 58 ++++++++++------------ .../connect/opcua/opcAdapterConfiguration.spec.ts | 52 +++++++++---------- ui/src/app/core-ui/core-ui.module.ts | 2 + ...ic-runtime-resolvable-tree-input.component.html | 31 ++++++++---- .../static-tree-input-button-menu.component.html | 6 ++- .../static-tree-input-button-menu.component.ts | 2 +- .../static-tree-input-text-editor.component.html | 10 ++-- .../static-tree-input-text-editor.component.ts | 6 +-- 13 files changed, 135 insertions(+), 109 deletions(-) diff --git a/ui/cypress/support/builder/AdapterBuilder.ts b/ui/cypress/support/builder/AdapterBuilder.ts index 03a5ac46ba..1bf5d2257d 100644 --- a/ui/cypress/support/builder/AdapterBuilder.ts +++ b/ui/cypress/support/builder/AdapterBuilder.ts @@ -19,7 +19,7 @@ import { UserInput } from '../model/UserInput'; import { UserInputType } from '../model/UserInputType'; import { AdapterInput } from '../model/AdapterInput'; -import { TreeNodeBuilder } from './TreeNodeBuilder'; +import { TreeNodeUserInputBuilder } from './TreeNodeUserInputBuilder'; export class AdapterBuilder { adapterInput: AdapterInput; @@ -71,7 +71,7 @@ export class AdapterBuilder { return this; } - public addTreeNode(treeNode: TreeNodeBuilder) { + public addTreeNode(treeNode: TreeNodeUserInputBuilder) { const userInput = new UserInput(); userInput.type = 'tree'; userInput.treeNode = treeNode.build(); diff --git a/ui/cypress/support/builder/TreeNodeUserInputBuilder.ts b/ui/cypress/support/builder/TreeNodeUserInputBuilder.ts index fcec8db9ef..b25c4e1017 100644 --- a/ui/cypress/support/builder/TreeNodeUserInputBuilder.ts +++ b/ui/cypress/support/builder/TreeNodeUserInputBuilder.ts @@ -16,39 +16,41 @@ * */ -import { TreeNode } from '../model/TreeNode'; +import { TreeNodeUserInput } from '../model/TreeNodeUserInput'; -export class TreeNodeBuilder { - private readonly node: TreeNode; +export class TreeNodeUserInputBuilder { + private readonly node: TreeNodeUserInput; constructor(name: string) { - this.node = { name, children: [] , isTextConfig: false}; + this.node = { name, children: [], isTextConfig: false }; } - addChildren(...childrenBuilders: TreeNodeBuilder[]): TreeNodeBuilder { + addChildren( + ...childrenBuilders: TreeNodeUserInputBuilder[] + ): TreeNodeUserInputBuilder { for (const childBuilder of childrenBuilders) { this.node.children!.push(childBuilder.build()); } return this; } - isTextConfig(): TreeNodeBuilder { + isTextConfig(): TreeNodeUserInputBuilder { this.node.isTextConfig = true; - return this + return this; } static create( name: string, - ...children: TreeNodeBuilder[] - ): TreeNodeBuilder { - const builder = new TreeNodeBuilder(name); + ...children: TreeNodeUserInputBuilder[] + ): TreeNodeUserInputBuilder { + const builder = new TreeNodeUserInputBuilder(name); if (children.length > 0) { builder.addChildren(...children); } return builder; } - build(): TreeNode { + build(): TreeNodeUserInput { return this.node; } } diff --git a/ui/cypress/support/model/TreeNodeUserInput.ts b/ui/cypress/support/model/TreeNodeUserInput.ts index 681a0a4629..cb68542e71 100644 --- a/ui/cypress/support/model/TreeNodeUserInput.ts +++ b/ui/cypress/support/model/TreeNodeUserInput.ts @@ -15,8 +15,8 @@ * limitations under the License. * */ -export class TreeNode { +export class TreeNodeUserInput { name: string; - children?: TreeNode[]; + children?: TreeNodeUserInput[]; isTextConfig?: boolean = false; } diff --git a/ui/cypress/support/model/UserInput.ts b/ui/cypress/support/model/UserInput.ts index 175a3abe97..b6fd38b96f 100644 --- a/ui/cypress/support/model/UserInput.ts +++ b/ui/cypress/support/model/UserInput.ts @@ -17,11 +17,11 @@ */ import { UserInputType } from './UserInputType'; -import { TreeNode } from './TreeNode'; +import { TreeNodeUserInput } from './TreeNodeUserInput'; export class UserInput { type: UserInputType; selector: string; value: string; - treeNode?: TreeNode; + treeNode?: TreeNodeUserInput; } diff --git a/ui/cypress/support/utils/userInput/TreeStaticPropertyUtils.ts b/ui/cypress/support/utils/userInput/TreeStaticPropertyUtils.ts index 9c74d4aa20..b632426fc7 100644 --- a/ui/cypress/support/utils/userInput/TreeStaticPropertyUtils.ts +++ b/ui/cypress/support/utils/userInput/TreeStaticPropertyUtils.ts @@ -16,22 +16,35 @@ * */ -import { TreeNode } from '../../model/TreeNode'; +import { TreeNodeUserInput } from '../../model/TreeNodeUserInput'; export class TreeStaticPropertyUtils { - /** * Returns the tree editor */ public static treeEditor() { - return cy.dataCy('opc-ua-tree-editor'); + return cy.dataCy('tree-editor'); } /** * Return the text editor */ public static textEditor() { - return cy.dataCy('opc-ua-text-editor'); + return cy.dataCy('text-editor'); + } + + /** + * Opens the text editor + */ + public static switchToTextEditor() { + cy.dataCy('opc-ua-editor-mode-text').click(); + } + + /** + * Appends the @param text to the text editor + */ + public static typeInTextEditor(text: string) { + cy.dataCy('static-tree-input-text-editor').type(text); } /** @@ -39,14 +52,20 @@ export class TreeStaticPropertyUtils { * children, it will expand the tree node and recursivly navigate through * the selected node. */ - public static selectTreeNode(treeNode: TreeNode) { - if (treeNode.children && treeNode.children.length > 0) { - cy.dataCy('expand-' + treeNode.name).click(); - treeNode.children.forEach(child => { - this.selectTreeNode(child); - }); + public static selectTreeNode(treeNode: TreeNodeUserInput) { + if (!treeNode.isTextConfig) { + // configure tree node + if (treeNode.children && treeNode.children.length > 0) { + cy.dataCy('expand-' + treeNode.name).click(); + treeNode.children.forEach(child => { + this.selectTreeNode(child); + }); + } else { + cy.dataCy('select-' + treeNode.name).click(); + } } else { - cy.dataCy('select-' + treeNode.name).click(); + TreeStaticPropertyUtils.switchToTextEditor(); + TreeStaticPropertyUtils.typeInTextEditor(treeNode.name); } } diff --git a/ui/cypress/tests/connect/opcua/opcAdapter.spec.ts b/ui/cypress/tests/connect/opcua/opcAdapter.spec.ts index 1e3cd8c907..708baa99d6 100644 --- a/ui/cypress/tests/connect/opcua/opcAdapter.spec.ts +++ b/ui/cypress/tests/connect/opcua/opcAdapter.spec.ts @@ -1,25 +1,25 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * */ -import { ConnectUtils } from '../../support/utils/connect/ConnectUtils'; -import { ParameterUtils } from '../../support/utils/ParameterUtils'; -import { AdapterBuilder } from '../../support/builder/AdapterBuilder'; -import { TreeNodeBuilder } from '../../support/builder/TreeNodeBuilder'; +import { ConnectUtils } from '../../../support/utils/connect/ConnectUtils'; +import { ParameterUtils } from '../../../support/utils/ParameterUtils'; +import { AdapterBuilder } from '../../../support/builder/AdapterBuilder'; +import { TreeNodeUserInputBuilder } from '../../../support/builder/TreeNodeUserInputBuilder'; describe('Test OPC-UA Adapter Pull Mode', () => { beforeEach('Setup Test', () => { @@ -46,44 +46,38 @@ describe('Test OPC-UA Adapter Pull Mode', () => { }); const getAdapterBuilderWithTreeNodes = (pullMode: boolean) => { - const builder = getBaseAdapterConfigBuilder(pullMode); builder.addTreeNode( - TreeNodeBuilder.create( + TreeNodeUserInputBuilder.create( 'Objects', - TreeNodeBuilder.create( + TreeNodeUserInputBuilder.create( 'OpcPlc', - TreeNodeBuilder.create( + TreeNodeUserInputBuilder.create( 'Telemetry', - TreeNodeBuilder.create('Basic').addChildren( - TreeNodeBuilder.create('AlternatingBoolean'), - TreeNodeBuilder.create('StepUp'), - TreeNodeBuilder.create('RandomSignedInt32'), - TreeNodeBuilder.create('RandomUnsignedInt32'), + TreeNodeUserInputBuilder.create('Basic').addChildren( + TreeNodeUserInputBuilder.create('AlternatingBoolean'), + TreeNodeUserInputBuilder.create('StepUp'), + TreeNodeUserInputBuilder.create('RandomSignedInt32'), + TreeNodeUserInputBuilder.create('RandomUnsignedInt32'), ), ), ), ), ); - return builder.build(); }; const getAdapterBuilderWithTextNodes = (pullMode: boolean) => { const builder = getBaseAdapterConfigBuilder(pullMode); builder.addTreeNode( - TreeNodeBuilder.create('ns=3;s=StepUp') - .isTextConfig() + TreeNodeUserInputBuilder.create('ns=3;s=StepUp').isTextConfig(), ); return builder.build(); }; - - - -const getBaseAdapterConfigBuilder = (pullMode: boolean) : AdapterBuilder => { +const getBaseAdapterConfigBuilder = (pullMode: boolean): AdapterBuilder => { const host: string = ParameterUtils.get('localhost', 'opcua'); const builder = AdapterBuilder.create('OPC_UA').setName( diff --git a/ui/cypress/tests/connect/opcua/opcAdapterConfiguration.spec.ts b/ui/cypress/tests/connect/opcua/opcAdapterConfiguration.spec.ts index 24173c88b5..a4786842cd 100644 --- a/ui/cypress/tests/connect/opcua/opcAdapterConfiguration.spec.ts +++ b/ui/cypress/tests/connect/opcua/opcAdapterConfiguration.spec.ts @@ -1,27 +1,27 @@ /* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * */ -import { ConnectUtils } from '../../support/utils/connect/ConnectUtils'; -import { ParameterUtils } from '../../support/utils/ParameterUtils'; -import { AdapterBuilder } from '../../support/builder/AdapterBuilder'; -import { TreeNodeBuilder } from '../../support/builder/TreeNodeBuilder'; -import { StaticPropertyUtils } from '../../support/utils/userInput/StaticPropertyUtils'; -import { TreeStaticPropertyUtils } from '../../support/utils/userInput/TreeStaticPropertyUtils'; +import { ConnectUtils } from '../../../support/utils/connect/ConnectUtils'; +import { ParameterUtils } from '../../../support/utils/ParameterUtils'; +import { AdapterBuilder } from '../../../support/builder/AdapterBuilder'; +import { TreeNodeUserInputBuilder } from '../../../support/builder/TreeNodeUserInputBuilder'; +import { StaticPropertyUtils } from '../../../support/utils/userInput/StaticPropertyUtils'; +import { TreeStaticPropertyUtils } from '../../../support/utils/userInput/TreeStaticPropertyUtils'; describe('Test OPC-UA Adapter Configuration', () => { beforeEach('Setup Test', () => { @@ -31,15 +31,17 @@ describe('Test OPC-UA Adapter Configuration', () => { it('Test OPC-UA Tree Node Configuration', () => { const adapterBuilder = getAdapterBuilder(); adapterBuilder.addTreeNode( - TreeNodeBuilder.create( + TreeNodeUserInputBuilder.create( 'Objects', - TreeNodeBuilder.create( + TreeNodeUserInputBuilder.create( 'OpcPlc', - TreeNodeBuilder.create( + TreeNodeUserInputBuilder.create( 'Telemetry', - TreeNodeBuilder.create('Basic').addChildren( - TreeNodeBuilder.create('AlternatingBoolean'), - TreeNodeBuilder.create('StepUp'), + TreeNodeUserInputBuilder.create('Basic').addChildren( + TreeNodeUserInputBuilder.create( + 'AlternatingBoolean', + ), + TreeNodeUserInputBuilder.create('StepUp'), ), ), ), @@ -89,7 +91,6 @@ describe('Test OPC-UA Adapter Configuration', () => { ConnectUtils.selectAdapter(adapterConfiguration.adapterType); StaticPropertyUtils.input(adapterConfiguration.adapterConfiguration); - TreeStaticPropertyUtils.treeEditor().should('be.visible'); TreeStaticPropertyUtils.textEditor().should('not.exist'); @@ -101,7 +102,6 @@ describe('Test OPC-UA Adapter Configuration', () => { TreeStaticPropertyUtils.textEditor().should('be.visible'); TreeStaticPropertyUtils.typeInTextEditor('ns=3;s=StepUp'); - }); }); diff --git a/ui/src/app/core-ui/core-ui.module.ts b/ui/src/app/core-ui/core-ui.module.ts index 8b589c4b18..971206876f 100644 --- a/ui/src/app/core-ui/core-ui.module.ts +++ b/ui/src/app/core-ui/core-ui.module.ts @@ -113,6 +113,7 @@ import { StaticTreeInputButtonMenuComponent } from './static-properties/static-r import { StaticTreeInputSelectedNodesComponent } from './static-properties/static-runtime-resolvable-tree-input/static-tree-input-selected-nodes/static-tree-input-selected-nodes.component'; import { StaticTreeInputBrowseNodesComponent } from './static-properties/static-runtime-resolvable-tree-input/static-tree-input-browse-nodes/static-tree-input-browse-nodes.component'; import { StaticTreeInputNodeDetailsComponent } from './static-properties/static-runtime-resolvable-tree-input/static-tree-input-node-details/static-tree-input-node-details.component'; +import { StaticTreeInputTextEditorComponent } from './static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component'; @NgModule({ imports: [ @@ -194,6 +195,7 @@ import { StaticTreeInputNodeDetailsComponent } from './static-properties/static- StaticRuntimeResolvableTreeInputComponent, StaticTreeInputBrowseNodesComponent, StaticTreeInputNodeDetailsComponent, + StaticTreeInputTextEditorComponent, StaticSlideToggleComponent, ErrorHintComponent, AddToCollectionComponent, diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component.html b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component.html index 129e467870..73efc2aaae 100644 --- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component.html +++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-runtime-resolvable-tree-input.component.html @@ -19,8 +19,8 @@ <sp-static-tree-input-button-menu [showOptions]="showOptions" [loading]="loading" - [editorMode]='editorMode' - (selectedEditorModeEmitter)='changeEditorMode($event)' + [editorMode]="editorMode" + (selectedEditorModeEmitter)="changeEditorMode($event)" (resetOptionsAndReload)="resetOptionsAndReload()" (reload)="reload()" > @@ -30,10 +30,12 @@ <sp-exception-message [message]="errorMessage"></sp-exception-message> </div> - <div fxLayout="row" - fxLayoutGap="15px" - data-cy='opc-ua-tree-editor' - *ngIf='editorMode === "tree"'> + <div + fxLayout="row" + fxLayoutGap="15px" + data-cy="tree-editor" + *ngIf="editorMode === 'tree'" + > <div fxFlex="30" class="tree-input-section" fxLayout="column"> <sp-static-tree-input-browse-nodes #staticTreeInputBrowseNodesComponent @@ -62,10 +64,17 @@ </div> </div> - - <div fxLayout="row" - data-cy='opc-ua-text-editor' - *ngIf='editorMode === "text"'> - <h1 >Text Editor</h1> + <div + fxLayout="row" + fxFlex="100" + data-cy="text-editor" + *ngIf="editorMode === 'text'" + > + <sp-static-tree-input-text-editor + fxFlex="100" + [staticProperty]="staticProperty" + (performValidationEmitter)="performValidation()" + > + </sp-static-tree-input-text-editor> </div> </div> diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-button-menu/static-tree-input-button-menu.component.html b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-button-menu/static-tree-input-button-menu.component.html index 4779d830ad..dc4244aafc 100644 --- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-button-menu/static-tree-input-button-menu.component.html +++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-button-menu/static-tree-input-button-menu.component.html @@ -39,7 +39,11 @@ <span>Reload</span> </button> </div> - <div fxLayout="column" *ngIf="loading" class="mt-10"> + <div + fxLayout="column" + *ngIf="loading && editorMode === 'tree'" + class="mt-10" + > <mat-spinner color="accent" [mode]="'indeterminate'" diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-button-menu/static-tree-input-button-menu.component.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-button-menu/static-tree-input-button-menu.component.ts index 182d0ce72e..75d0332178 100644 --- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-button-menu/static-tree-input-button-menu.component.ts +++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-button-menu/static-tree-input-button-menu.component.ts @@ -44,7 +44,7 @@ export class StaticTreeInputButtonMenuComponent { this.reload.emit(); } - onChangeEditor(mode:'tree' | 'text') { + onChangeEditor(mode: 'tree' | 'text') { this.selectedEditorModeEmitter.emit(mode); } } diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component.html b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component.html index c1d07b3dad..8e3d97b00f 100644 --- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component.html +++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component.html @@ -17,10 +17,10 @@ --> <ngx-codemirror - style='width: 100%' - [(ngModel)]='textEditor' - (ngModelChange)='onTextEditorChange($event)' - [options]='editorOptions' - data-cy='static-tree-input-text-editor' + style="width: 100%" + [(ngModel)]="textEditor" + (ngModelChange)="onTextEditorChange($event)" + [options]="editorOptions" + data-cy="static-tree-input-text-editor" > </ngx-codemirror> diff --git a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component.ts b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component.ts index 6042c9554d..1651519ff8 100644 --- a/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component.ts +++ b/ui/src/app/core-ui/static-properties/static-runtime-resolvable-tree-input/static-tree-input-text-editor/static-tree-input-text-editor.component.ts @@ -26,7 +26,6 @@ import { RuntimeResolvableTreeInputStaticProperty } from '@streampipes/platform- templateUrl: './static-tree-input-text-editor.component.html', }) export class StaticTreeInputTextEditorComponent { - @Input() staticProperty: RuntimeResolvableTreeInputStaticProperty; @@ -50,9 +49,7 @@ export class StaticTreeInputTextEditorComponent { private textChangeSubject: Subject<string> = new Subject<string>(); constructor() { - this.textChangeSubject.pipe( - debounceTime(500), - ).subscribe(value => { + this.textChangeSubject.pipe(debounceTime(500)).subscribe(value => { this.onTextChange(value); }); } @@ -66,5 +63,4 @@ export class StaticTreeInputTextEditorComponent { this.staticProperty.selectedNodesInternalNames = lines; this.performValidationEmitter.emit(); } - }
