This is an automated email from the ASF dual-hosted git repository.

zehnder pushed a commit to branch refactor-configure-shema-component
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit c6ca0a7c5edd5de61211ef4fe4da5e68bc7e5de8
Author: Philipp Zehnder <[email protected]>
AuthorDate: Fri Jan 23 16:02:02 2026 +0100

    refactor: Replace script configuration panel with dedicated components for 
script editing, sample preview, and result display
---
 .../configure-schema.component.html                | 263 +++------------------
 .../configure-schema/configure-schema.component.ts |   8 +
 .../adapter-result-preview.component.html          |  61 +++++
 .../adapter-result-preview.component.ts            |  34 +++
 .../adapter-sample-preview.component.html          |  73 ++++++
 .../adapter-sample-preview.component.ts            |  36 +++
 .../adapter-script-editor.component.html           | 134 +++++++++++
 .../adapter-script-editor.component.ts             |  42 ++++
 ui/src/app/connect/connect.module.ts               |   6 +
 9 files changed, 425 insertions(+), 232 deletions(-)

diff --git 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.html
 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.html
index 530514c586..2aa96b51ba 100644
--- 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.html
+++ 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.html
@@ -17,246 +17,45 @@
 -->
 <div fxFlex="100" fxLayout="column">
     <div fxFlex="100" fxLayout="column">
-        <sp-basic-inner-panel
-            [panelTitle]="'Transformation' | translate"
-            outerMargin="20px 0px"
-        >
-            @if (loadingAvailableScriptsError()) {
-                <sp-alert-banner
-                    type="error"
-                    [title]="'Error loading available script languages'"
-                    [description]="loadingAvailableScriptsError().cause"
-                >
-                </sp-alert-banner>
-            }
-
-            <div
-                header
-                fxLayoutAlign="end center"
-                fxFlex="100"
-                fxLayoutGap="5px"
-            >
-                @if (scriptActive()) {
-                    @if (selectedScriptMetadata()) {
-                        <button
-                            mat-button
-                            [matMenuTriggerFor]="langMenu"
-                            aria-label="Select template language"
-                        >
-                            {{ selectedScriptMetadata().name | titlecase }}
-                            <mat-icon>arrow_drop_down</mat-icon>
-                        </button>
-
-                        <mat-menu #langMenu="matMenu">
-                            @for (
-                                script of availableScripts();
-                                track script.language
-                            ) {
-                                <button
-                                    mat-menu-item
-                                    (click)="onLanguageChange(script)"
-                                >
-                                    <span>{{ script.name | titlecase }}</span>
-                                    @if (
-                                        script.language ===
-                                        selectedScriptMetadata().language
-                                    ) {
-                                        <mat-icon class="ms-auto"
-                                            >check
-                                        </mat-icon>
-                                    }
-                                </button>
-                            }
-                        </mat-menu>
-                    }
-                    <button
-                        mat-button
-                        data-cy="use-script-template"
-                        (click)="openSelectScriptTemplateDialog()"
-                    >
-                        <mat-icon>article</mat-icon>
-                        <span>{{ 'Use template' | translate }}</span>
-                    </button>
-                    <button
-                        mat-button
-                        data-cy="reset-script"
-                        (click)="resetScript()"
-                    >
-                        <mat-icon>settings_backup_restore</mat-icon>
-                        <span>{{ 'Reset script' | translate }}</span>
-                    </button>
-                }
-
-                <mat-slide-toggle
-                    data-cy="toggle-script-active"
-                    [ngModel]="scriptActive()"
-                    (ngModelChange)="toggleScriptActive()"
-                >
-                    @if (scriptActive()) {
-                        {{ 'Disable script' | translate }}
-                    } @else {
-                        {{ 'Enable script' | translate }}
-                    }
-                </mat-slide-toggle>
-            </div>
-
-            @if (scriptActive()) {
-                <div class="code-editor-outer">
-                    <ngx-codemirror
-                        class="code-editor"
-                        [ngModel]="script()"
-                        (ngModelChange)="onCodeChange($event)"
-                        [options]="editorOptions"
-                        data-cy="configure-schema-script-editor"
-                    ></ngx-codemirror>
-                </div>
-                <div fxLayoutGap="10px">
-                    <button
-                        class="mt-sm"
-                        mat-flat-button
-                        matTooltip="Run script"
-                        data-cy="configure-schema-run-script-button"
-                        (click)="runScript()"
-                    >
-                        <mat-icon>play_circle_filled</mat-icon>
-                        <span>Run script</span>
-                    </button>
-                    <button
-                        class="mat-basic mt-sm"
-                        mat-flat-button
-                        matTooltip="Run script"
-                        data-cy="add-script-template-button"
-                        (click)="openCreateScriptTemplateDialog()"
-                    >
-                        <mat-icon>play_circle_filled</mat-icon>
-                        <span>Create script template</span>
-                    </button>
-                </div>
-            } @else {
-                <sp-alert-banner
-                    type="info"
-                    [title]="'Enable transformation' | translate"
-                    [description]="
-                        'Enable script-based editing and add custom scripts 
which transform the structure or values of your input data.'
-                            | translate
-                    "
-                >
-                </sp-alert-banner>
-            }
-        </sp-basic-inner-panel>
+        <sp-adapter-script-editor
+            [scriptActive]="scriptActive()"
+            [selectedScriptMetadata]="selectedScriptMetadata()"
+            [availableScripts]="availableScripts()"
+            [loadingAvailableScriptsError]="loadingAvailableScriptsError()"
+            [script]="script()"
+            [editorOptions]="editorOptions"
+            (codeChange)="onCodeChange($event)"
+            (languageChange)="onLanguageChange($event)"
+            (selectTemplate)="openSelectScriptTemplateDialog()"
+            (resetScript)="resetScript()"
+            (toggleScriptActive)="toggleScriptActive()"
+            (runScript)="runScript()"
+            (createTemplate)="openCreateScriptTemplateDialog()"
+        ></sp-adapter-script-editor>
     </div>
 
     <div fxFlex="100" fxLayout="row" fxLayoutGap="15px">
         <div fxFlex="50" fxLayout="column">
-            <sp-basic-inner-panel
-                innerPadding="0"
-                [showTitle]="true"
-                [panelTitle]="'Original (Parsed)' | translate"
-            >
-                <div header fxLayoutAlign="end center" fxFlex="100">
-                    <button
-                        data-cy="connect-get-new-sample-button"
-                        mat-button
-                        (click)="getSampleEvent()"
-                    >
-                        <mat-icon>refresh</mat-icon>
-                        <span>{{ 'Get new sample' | translate }}</span>
-                    </button>
-                    <mat-button-toggle-group
-                        [(value)]="sourceViewMode"
-                        [hideSingleSelectionIndicator]="true"
-                    >
-                        <mat-button-toggle value="tree"
-                            >{{ 'Tree' | translate }}
-                        </mat-button-toggle>
-                        <mat-button-toggle value="raw"
-                            >{{ 'Raw' | translate }}
-                        </mat-button-toggle>
-                    </mat-button-toggle-group>
-                </div>
-
-                @if (isSampleLoading()) {
-                    <div
-                        fxFlex="100"
-                        fxLayoutAlign="center center"
-                        fxLayout="column"
-                        class="m-lg"
-                    >
-                        <mat-spinner [diameter]="25"></mat-spinner>
-                        <h5>{{ 'Loading' | translate }}</h5>
-                    </div>
-                } @else {
-                    @let error = sampleErrorMessage();
-
-                    @if (error) {
-                        <sp-exception-message
-                            [message]="error"
-                            [showDetails]="true"
-                        ></sp-exception-message>
-                    } @else {
-                        <sp-show-field-status-infos
-                            [fieldStatusInfos]="fieldStatusInfos()"
-                        ></sp-show-field-status-infos>
-                        <sp-adapter-event-preview
-                            dataCy="configure-schema-event-preview-original"
-                            [mode]="sourceViewMode()"
-                            [value]="input()"
-                        ></sp-adapter-event-preview>
-                    }
-                }
-            </sp-basic-inner-panel>
+            <sp-adapter-sample-preview
+                [isSampleLoading]="isSampleLoading()"
+                [sampleErrorMessage]="sampleErrorMessage()"
+                [fieldStatusInfos]="fieldStatusInfos()"
+                [input]="input()"
+                [sourceViewMode]="sourceViewMode()"
+                (sourceViewModeChange)="setSourceViewMode($event)"
+                (getSample)="getSampleEvent()"
+            ></sp-adapter-sample-preview>
         </div>
 
         @if (scriptActive()) {
             <div fxFlex="50" fxLayout="column">
-                <sp-basic-inner-panel
-                    [showTitle]="true"
-                    innerPadding="0"
-                    [panelTitle]="'Result' | translate"
-                    fxFlex="100"
-                    data-cy="connect-schema-update-preview"
-                >
-                    <div header fxFlex="100" fxLayoutAlign="end center">
-                        <mat-button-toggle-group
-                            [(value)]="resultViewMode"
-                            [hideSingleSelectionIndicator]="true"
-                        >
-                            <mat-button-toggle value="tree"
-                                >{{ 'Tree' | translate }}
-                            </mat-button-toggle>
-                            <mat-button-toggle value="raw"
-                                >{{ 'Raw' | translate }}
-                            </mat-button-toggle>
-                        </mat-button-toggle-group>
-                    </div>
-                    @if (isRunningScript()) {
-                        <div class="m-lg">
-                            <div
-                                fxFlex="100"
-                                fxLayoutAlign="center center"
-                                fxLayout="column"
-                            >
-                                <mat-spinner [diameter]="25"></mat-spinner>
-                                <h5>{{ 'Loading' | translate }}</h5>
-                            </div>
-                        </div>
-                    } @else {
-                        @let error = scriptError();
-                        @if (error) {
-                            <sp-exception-message
-                                class="p-xs"
-                                [message]="error"
-                                [showDetails]="true"
-                            ></sp-exception-message>
-                        } @else {
-                            <sp-adapter-event-preview
-                                dataCy="configure-schema-event-preview-result"
-                                [mode]="resultViewMode()"
-                                [value]="output()"
-                            ></sp-adapter-event-preview>
-                        }
-                    }
-                </sp-basic-inner-panel>
+                <sp-adapter-result-preview
+                    [isRunningScript]="isRunningScript()"
+                    [scriptError]="scriptError()"
+                    [output]="output()"
+                    [resultViewMode]="resultViewMode()"
+                    (resultViewModeChange)="setResultViewMode($event)"
+                ></sp-adapter-result-preview>
             </div>
         }
     </div>
diff --git 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.ts
 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.ts
index b4825aded8..7f29649338 100644
--- 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.ts
+++ 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/configure-schema.component.ts
@@ -171,6 +171,14 @@ export class ConfigureSchemaComponent implements OnInit {
         });
     }
 
+    setSourceViewMode(mode: Mode) {
+        this.sourceViewMode.set(mode);
+    }
+
+    setResultViewMode(mode: Mode) {
+        this.resultViewMode.set(mode);
+    }
+
     resetScript(): void {
         this.stateService.resetScriptToInitial();
         this.runScript();
diff --git 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/result-preview/adapter-result-preview.component.html
 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/result-preview/adapter-result-preview.component.html
new file mode 100644
index 0000000000..3058f8ad06
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/result-preview/adapter-result-preview.component.html
@@ -0,0 +1,61 @@
+<!--
+~ 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
+~
+~ 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.
+~
+-->
+<sp-basic-inner-panel
+    [showTitle]="true"
+    innerPadding="0"
+    [panelTitle]="'Result' | translate"
+    fxFlex="100"
+    data-cy="connect-schema-update-preview"
+>
+    <div header fxFlex="100" fxLayoutAlign="end center">
+        <mat-button-toggle-group
+            [value]="resultViewMode"
+            [hideSingleSelectionIndicator]="true"
+            (valueChange)="resultViewModeChange.emit($event)"
+        >
+            <mat-button-toggle value="tree"
+                >{{ 'Tree' | translate }}
+            </mat-button-toggle>
+            <mat-button-toggle value="raw"
+                >{{ 'Raw' | translate }}
+            </mat-button-toggle>
+        </mat-button-toggle-group>
+    </div>
+    @if (isRunningScript) {
+        <div class="m-lg">
+            <div fxFlex="100" fxLayoutAlign="center center" fxLayout="column">
+                <mat-spinner [diameter]="25"></mat-spinner>
+                <h5>{{ 'Loading' | translate }}</h5>
+            </div>
+        </div>
+    } @else {
+        @if (scriptError) {
+            <sp-exception-message
+                class="p-xs"
+                [message]="scriptError"
+                [showDetails]="true"
+            ></sp-exception-message>
+        } @else {
+            <sp-adapter-event-preview
+                dataCy="configure-schema-event-preview-result"
+                [mode]="resultViewMode"
+                [value]="output"
+            ></sp-adapter-event-preview>
+        }
+    }
+</sp-basic-inner-panel>
diff --git 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/result-preview/adapter-result-preview.component.ts
 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/result-preview/adapter-result-preview.component.ts
new file mode 100644
index 0000000000..4ae85a4bae
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/result-preview/adapter-result-preview.component.ts
@@ -0,0 +1,34 @@
+/*
+ * 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
+ *
+ * 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 { Component, EventEmitter, Input, Output } from '@angular/core';
+import { Mode } from 
'../../adapter-event-preview/adapter-event-preview.component';
+
+@Component({
+    selector: 'sp-adapter-result-preview',
+    standalone: false,
+    templateUrl: './adapter-result-preview.component.html',
+})
+export class AdapterResultPreviewComponent {
+    @Input() isRunningScript = false;
+    @Input() scriptError: any;
+    @Input() output: any;
+    @Input() resultViewMode: Mode = 'raw';
+
+    @Output() resultViewModeChange = new EventEmitter<Mode>();
+}
diff --git 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/sample-preview/adapter-sample-preview.component.html
 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/sample-preview/adapter-sample-preview.component.html
new file mode 100644
index 0000000000..ca0aafaca1
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/sample-preview/adapter-sample-preview.component.html
@@ -0,0 +1,73 @@
+<!--
+~ 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
+~
+~ 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.
+~
+-->
+<sp-basic-inner-panel
+    innerPadding="0"
+    [showTitle]="true"
+    [panelTitle]="'Original (Parsed)' | translate"
+>
+    <div header fxLayoutAlign="end center" fxFlex="100">
+        <button
+            data-cy="connect-get-new-sample-button"
+            mat-button
+            (click)="getSample.emit()"
+        >
+            <mat-icon>refresh</mat-icon>
+            <span>{{ 'Get new sample' | translate }}</span>
+        </button>
+        <mat-button-toggle-group
+            [value]="sourceViewMode"
+            [hideSingleSelectionIndicator]="true"
+            (valueChange)="sourceViewModeChange.emit($event)"
+        >
+            <mat-button-toggle value="tree"
+                >{{ 'Tree' | translate }}
+            </mat-button-toggle>
+            <mat-button-toggle value="raw"
+                >{{ 'Raw' | translate }}
+            </mat-button-toggle>
+        </mat-button-toggle-group>
+    </div>
+
+    @if (isSampleLoading) {
+        <div
+            fxFlex="100"
+            fxLayoutAlign="center center"
+            fxLayout="column"
+            class="m-lg"
+        >
+            <mat-spinner [diameter]="25"></mat-spinner>
+            <h5>{{ 'Loading' | translate }}</h5>
+        </div>
+    } @else {
+        @if (sampleErrorMessage) {
+            <sp-exception-message
+                [message]="sampleErrorMessage"
+                [showDetails]="true"
+            ></sp-exception-message>
+        } @else {
+            <sp-show-field-status-infos
+                [fieldStatusInfos]="fieldStatusInfos"
+            ></sp-show-field-status-infos>
+            <sp-adapter-event-preview
+                dataCy="configure-schema-event-preview-original"
+                [mode]="sourceViewMode"
+                [value]="input"
+            ></sp-adapter-event-preview>
+        }
+    }
+</sp-basic-inner-panel>
diff --git 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/sample-preview/adapter-sample-preview.component.ts
 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/sample-preview/adapter-sample-preview.component.ts
new file mode 100644
index 0000000000..7853d58a6f
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/sample-preview/adapter-sample-preview.component.ts
@@ -0,0 +1,36 @@
+/*
+ * 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
+ *
+ * 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 { Component, EventEmitter, Input, Output } from '@angular/core';
+import { Mode } from 
'../../adapter-event-preview/adapter-event-preview.component';
+
+@Component({
+    selector: 'sp-adapter-sample-preview',
+    standalone: false,
+    templateUrl: './adapter-sample-preview.component.html',
+})
+export class AdapterSamplePreviewComponent {
+    @Input() isSampleLoading = false;
+    @Input() sampleErrorMessage: any;
+    @Input() fieldStatusInfos: any;
+    @Input() input: any;
+    @Input() sourceViewMode: Mode = 'raw';
+
+    @Output() sourceViewModeChange = new EventEmitter<Mode>();
+    @Output() getSample = new EventEmitter<void>();
+}
diff --git 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/script-editor/adapter-script-editor.component.html
 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/script-editor/adapter-script-editor.component.html
new file mode 100644
index 0000000000..8bf4189031
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/script-editor/adapter-script-editor.component.html
@@ -0,0 +1,134 @@
+<!--
+~ 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
+~
+~ 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.
+~
+-->
+<sp-basic-inner-panel
+    [panelTitle]="'Transformation' | translate"
+    outerMargin="20px 0px"
+>
+    @if (loadingAvailableScriptsError) {
+        <sp-alert-banner
+            type="error"
+            [title]="'Error loading available script languages'"
+            [description]="loadingAvailableScriptsError.cause"
+        >
+        </sp-alert-banner>
+    }
+
+    <div header fxLayoutAlign="end center" fxFlex="100" fxLayoutGap="5px">
+        @if (scriptActive) {
+            @if (selectedScriptMetadata) {
+                <button
+                    mat-button
+                    [matMenuTriggerFor]="langMenu"
+                    aria-label="Select template language"
+                >
+                    {{ selectedScriptMetadata.name | titlecase }}
+                    <mat-icon>arrow_drop_down</mat-icon>
+                </button>
+
+                <mat-menu #langMenu="matMenu">
+                    @for (script of availableScripts; track script.language) {
+                        <button
+                            mat-menu-item
+                            (click)="languageChange.emit(script)"
+                        >
+                            <span>{{ script.name | titlecase }}</span>
+                            @if (
+                                script.language ===
+                                selectedScriptMetadata.language
+                            ) {
+                                <mat-icon class="ms-auto">check</mat-icon>
+                            }
+                        </button>
+                    }
+                </mat-menu>
+            }
+            <button
+                mat-button
+                data-cy="use-script-template"
+                (click)="selectTemplate.emit()"
+            >
+                <mat-icon>article</mat-icon>
+                <span>{{ 'Use template' | translate }}</span>
+            </button>
+            <button
+                mat-button
+                data-cy="reset-script"
+                (click)="resetScript.emit()"
+            >
+                <mat-icon>settings_backup_restore</mat-icon>
+                <span>{{ 'Reset script' | translate }}</span>
+            </button>
+        }
+
+        <mat-slide-toggle
+            data-cy="toggle-script-active"
+            [ngModel]="scriptActive"
+            (ngModelChange)="toggleScriptActive.emit()"
+        >
+            @if (scriptActive) {
+                {{ 'Disable script' | translate }}
+            } @else {
+                {{ 'Enable script' | translate }}
+            }
+        </mat-slide-toggle>
+    </div>
+
+    @if (scriptActive) {
+        <div class="code-editor-outer">
+            <ngx-codemirror
+                class="code-editor"
+                [ngModel]="script"
+                (ngModelChange)="codeChange.emit($event)"
+                [options]="editorOptions"
+                data-cy="configure-schema-script-editor"
+            ></ngx-codemirror>
+        </div>
+        <div fxLayoutGap="10px">
+            <button
+                class="mt-sm"
+                mat-flat-button
+                matTooltip="Run script"
+                data-cy="configure-schema-run-script-button"
+                (click)="runScript.emit()"
+            >
+                <mat-icon>play_circle_filled</mat-icon>
+                <span>Run script</span>
+            </button>
+            <button
+                class="mat-basic mt-sm"
+                mat-flat-button
+                matTooltip="Run script"
+                data-cy="add-script-template-button"
+                (click)="createTemplate.emit()"
+            >
+                <mat-icon>play_circle_filled</mat-icon>
+                <span>Create script template</span>
+            </button>
+        </div>
+    } @else {
+        <sp-alert-banner
+            type="info"
+            [title]="'Enable transformation' | translate"
+            [description]="
+                'Enable script-based editing and add custom scripts which 
transform the structure or values of your input data.'
+                    | translate
+            "
+        >
+        </sp-alert-banner>
+    }
+</sp-basic-inner-panel>
diff --git 
a/ui/src/app/connect/components/adapter-configuration/configure-schema/script-editor/adapter-script-editor.component.ts
 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/script-editor/adapter-script-editor.component.ts
new file mode 100644
index 0000000000..bafe5f5655
--- /dev/null
+++ 
b/ui/src/app/connect/components/adapter-configuration/configure-schema/script-editor/adapter-script-editor.component.ts
@@ -0,0 +1,42 @@
+/*
+ * 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
+ *
+ * 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 { Component, EventEmitter, Input, Output } from '@angular/core';
+import { ScriptMetadata } from '@streampipes/platform-services';
+
+@Component({
+    selector: 'sp-adapter-script-editor',
+    standalone: false,
+    templateUrl: './adapter-script-editor.component.html',
+})
+export class AdapterScriptEditorComponent {
+    @Input() scriptActive = false;
+    @Input() selectedScriptMetadata: ScriptMetadata;
+    @Input() availableScripts: ScriptMetadata[] = [];
+    @Input() loadingAvailableScriptsError: any;
+    @Input() script = '';
+    @Input() editorOptions: any;
+
+    @Output() codeChange = new EventEmitter<string>();
+    @Output() languageChange = new EventEmitter<ScriptMetadata>();
+    @Output() selectTemplate = new EventEmitter<void>();
+    @Output() resetScript = new EventEmitter<void>();
+    @Output() toggleScriptActive = new EventEmitter<void>();
+    @Output() runScript = new EventEmitter<void>();
+    @Output() createTemplate = new EventEmitter<void>();
+}
diff --git a/ui/src/app/connect/connect.module.ts 
b/ui/src/app/connect/connect.module.ts
index 54724a5269..8600aa21df 100644
--- a/ui/src/app/connect/connect.module.ts
+++ b/ui/src/app/connect/connect.module.ts
@@ -110,6 +110,9 @@ import { AdapterEventPreviewComponent } from 
'./components/adapter-configuration
 import { AdapterEventPreviewNodeComponent } from 
'./components/adapter-configuration/adapter-event-preview/adapter-event-preview-node/adapter-event-preview-node.component';
 import { EventPropertyScopeComponent } from 
'./components/adapter-configuration/configure-fields/event-property-row/event-property-scope/event-property-scope.component';
 import { ShowFieldStatusInfosComponent } from 
'./components/adapter-configuration/configure-schema/show-field-status-infos/show-field-status-infos.component';
+import { AdapterScriptEditorComponent } from 
'./components/adapter-configuration/configure-schema/script-editor/adapter-script-editor.component';
+import { AdapterSamplePreviewComponent } from 
'./components/adapter-configuration/configure-schema/sample-preview/adapter-sample-preview.component';
+import { AdapterResultPreviewComponent } from 
'./components/adapter-configuration/configure-schema/result-preview/adapter-result-preview.component';
 
 @NgModule({
     imports: [
@@ -256,6 +259,9 @@ import { ShowFieldStatusInfosComponent } from 
'./components/adapter-configuratio
         AdapterEventPreviewNodeComponent,
         EventPropertyScopeComponent,
         ShowFieldStatusInfosComponent,
+        AdapterScriptEditorComponent,
+        AdapterSamplePreviewComponent,
+        AdapterResultPreviewComponent,
     ],
     providers: [TimestampPipe],
     schemas: [CUSTOM_ELEMENTS_SCHEMA],

Reply via email to