mirror of
https://github.com/jwetzell/showbridge-webui.git
synced 2026-08-24 15:39:00 +00:00
Compare commits
41 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 283b28e8c1 | |||
| cb4e011fea | |||
| 08af66c378 | |||
| bb76c3b561 | |||
| 8f9d2352c8 | |||
| 95b109de8f | |||
| 53ec3b222a | |||
| a09824ca03 | |||
| f9695c19d6 | |||
| 2396657fc8 | |||
| 83469cc9f2 | |||
| 18e1000da5 | |||
| 17536deff1 | |||
| 450c5d934d | |||
| 088f278bb7 | |||
| 8db22220dd | |||
| d72fc9726a | |||
| 0b86856a71 | |||
| 2ed2418ae1 | |||
| 2576e4902d | |||
| fa2baa71f4 | |||
| 3956290d3d | |||
| a00efa0c5c | |||
| e309df8fe5 | |||
| 6323dd1724 | |||
| 0aa3b23362 | |||
| ac2ced53bf | |||
| b9950c64e7 | |||
| 31f42e696d | |||
| 947fd14364 | |||
| 0a738b5c01 | |||
| 876f41f3c6 | |||
| 903653e4b3 | |||
| 785c1b882c | |||
| 4b1bd29487 | |||
| 70d5578713 | |||
| fca57b0302 | |||
| 69599e688c | |||
| 5e22cbfbdd | |||
| 26631d3bc2 | |||
| 0fc02a46d1 |
@@ -9,10 +9,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository
|
- name: Check out repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out repository
|
- name: Check out repository
|
||||||
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
|
|
||||||
- name: Set up Node.js
|
- name: Set up Node.js
|
||||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
|
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
cache: 'npm'
|
cache: 'npm'
|
||||||
|
|||||||
+15
-3
@@ -1,8 +1,20 @@
|
|||||||
import { test } from '@playwright/test';
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
test('add module', async ({ page }) => {
|
test('add module', async ({ page }) => {
|
||||||
await page.goto('/');
|
await page.goto('/');
|
||||||
await page.locator('app-module-list').getByText('add').click();
|
await page.getByRole('button', { name: 'Add Module' }).click();
|
||||||
await page.getByRole('menuitem', { name: 'HTTP Server' }).click();
|
await page.getByRole('menuitem', { name: 'HTTP Server' }).click();
|
||||||
// TODO(jwetzell): test that the module gets added
|
const module = page.locator('#modules\\.0');
|
||||||
|
await expect(module).toBeVisible();
|
||||||
|
await expect(module).toContainText('HTTP Server');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('remove module', async ({ page }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await page.getByRole('button', { name: 'Add Module' }).click();
|
||||||
|
await page.getByRole('menuitem', { name: 'HTTP Server' }).click();
|
||||||
|
const module = page.locator('#modules\\.0');
|
||||||
|
await expect(module).toBeVisible();
|
||||||
|
await module.getByRole('button', { name: 'Delete Module' }).click();
|
||||||
|
await expect(module).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
|
||||||
|
test('add route', async ({ page }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await page.getByRole('button', { name: 'Add Route' }).click();
|
||||||
|
await page.getByRole('menuitem', { name: 'HTTP Server' }).click();
|
||||||
|
const route = page.locator('#routes\\.0');
|
||||||
|
await expect(route).toBeVisible();
|
||||||
|
await expect(route).toContainText('Route 0');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('remove route', async ({ page }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await page.getByRole('button', { name: 'Add Route' }).click();
|
||||||
|
const route = page.locator('#routes\\.0');
|
||||||
|
await expect(route).toBeVisible();
|
||||||
|
await route.getByRole('button', { name: 'Delete Route' }).click();
|
||||||
|
await expect(route).not.toBeVisible();
|
||||||
|
});
|
||||||
Generated
+2789
-3476
File diff suppressed because it is too large
Load Diff
+20
-21
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@showbridge/webui",
|
"name": "@showbridge/webui",
|
||||||
"version": "0.14.0",
|
"version": "0.14.4",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ng": "ng",
|
"ng": "ng",
|
||||||
"start": "ng serve",
|
"start": "ng serve",
|
||||||
@@ -28,35 +28,34 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"packageManager": "npm@11.6.2",
|
"packageManager": "npm@11.6.2",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/cdk": "21.2.11",
|
"@angular/cdk": "22.1.0",
|
||||||
"@angular/common": "21.2.13",
|
"@angular/common": "22.1.0",
|
||||||
"@angular/compiler": "21.2.13",
|
"@angular/compiler": "22.1.0",
|
||||||
"@angular/core": "21.2.13",
|
"@angular/core": "22.1.0",
|
||||||
"@angular/forms": "21.2.13",
|
"@angular/forms": "22.1.0",
|
||||||
"@angular/material": "21.2.11",
|
"@angular/material": "22.1.0",
|
||||||
"@angular/platform-browser": "21.2.13",
|
"@angular/platform-browser": "22.1.0",
|
||||||
"@angular/router": "21.2.13",
|
"@angular/router": "22.1.0",
|
||||||
"ajv": "8.20.0",
|
"ajv": "8.20.0",
|
||||||
"js-yaml": "4.1.1",
|
"js-yaml": "5.2.3",
|
||||||
"lodash-es": "4.18.1",
|
"lodash-es": "4.18.1",
|
||||||
"rxjs": "7.8.2",
|
"rxjs": "7.8.2",
|
||||||
"tslib": "2.8.1"
|
"tslib": "2.8.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@angular/build": "21.2.11",
|
"@angular/build": "22.1.2",
|
||||||
"@angular/cli": "21.2.11",
|
"@angular/cli": "22.1.2",
|
||||||
"@angular/compiler-cli": "21.2.13",
|
"@angular/compiler-cli": "22.1.0",
|
||||||
"@angular/material": "21.2.11",
|
|
||||||
"@playwright/test": "1.60.0",
|
"@playwright/test": "1.60.0",
|
||||||
"@tailwindcss/postcss": "4.3.0",
|
"@tailwindcss/postcss": "4.3.3",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "4.0.9",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "4.17.12",
|
||||||
"jsdom": "29.1.1",
|
"jsdom": "29.1.1",
|
||||||
"playwright-ng-schematics": "^21.1.0",
|
"playwright-ng-schematics": "22.0.3",
|
||||||
"postcss": "8.5.14",
|
"postcss": "8.5.25",
|
||||||
"prettier": "3.8.3",
|
"prettier": "3.9.6",
|
||||||
"tailwindcss": "4.3.0",
|
"tailwindcss": "4.3.3",
|
||||||
"typescript": "5.9.3",
|
"typescript": "6.0.3",
|
||||||
"vitest": "4.1.6"
|
"vitest": "4.1.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,9 +24,13 @@ export default defineConfig({
|
|||||||
webServer: [
|
webServer: [
|
||||||
{
|
{
|
||||||
name: 'showbridge',
|
name: 'showbridge',
|
||||||
command: 'showbridge --config config.yaml',
|
command: 'showbridge --config config.test.yaml',
|
||||||
url: 'http://localhost:8080/health',
|
url: 'http://localhost:8080/health',
|
||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
|
gracefulShutdown: {
|
||||||
|
signal: 'SIGTERM',
|
||||||
|
timeout: 5000,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
@@ -36,6 +40,7 @@ export default defineConfig({
|
|||||||
|
|
||||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
trace: 'on-first-retry',
|
trace: 'on-first-retry',
|
||||||
|
video: 'retain-on-failure',
|
||||||
},
|
},
|
||||||
/* Configure projects for major browsers */
|
/* Configure projects for major browsers */
|
||||||
projects: [
|
projects: [
|
||||||
|
|||||||
+2
-1
@@ -1,4 +1,4 @@
|
|||||||
import { Component, computed, effect, inject } from '@angular/core';
|
import { Component, computed, effect, inject, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
@@ -29,6 +29,7 @@ import { SettingsService } from './services/settings';
|
|||||||
ConfigPreviewComponent,
|
ConfigPreviewComponent,
|
||||||
],
|
],
|
||||||
templateUrl: './app.html',
|
templateUrl: './app.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
styleUrl: './app.css',
|
styleUrl: './app.css',
|
||||||
})
|
})
|
||||||
export class App {
|
export class App {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
import { Component, inject, Input, OnInit } from '@angular/core';
|
import { Component, inject, Input, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { ParamInfo } from '../../models/form';
|
import { ParamInfo } from '../../models/form';
|
||||||
@@ -12,6 +12,7 @@ import { parseStringToArray } from '../../utils/params';
|
|||||||
templateUrl: './array-form.html',
|
templateUrl: './array-form.html',
|
||||||
styleUrl: './array-form.css',
|
styleUrl: './array-form.css',
|
||||||
imports: [MatIconModule, FormsModule, CdkDrag, CdkDropList],
|
imports: [MatIconModule, FormsModule, CdkDrag, CdkDropList],
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
standalone: true,
|
standalone: true,
|
||||||
})
|
})
|
||||||
export class ArrayFormComponent implements OnInit {
|
export class ArrayFormComponent implements OnInit {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Component, computed, input } from '@angular/core';
|
import { Component, computed, input, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
@@ -9,6 +9,7 @@ import { Config } from '../../models/config';
|
|||||||
selector: 'app-config-preview',
|
selector: 'app-config-preview',
|
||||||
imports: [MatIconModule, MatButtonModule, MatTooltipModule],
|
imports: [MatIconModule, MatButtonModule, MatTooltipModule],
|
||||||
templateUrl: './config-preview.html',
|
templateUrl: './config-preview.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
styleUrl: './config-preview.css',
|
styleUrl: './config-preview.css',
|
||||||
})
|
})
|
||||||
export class ConfigPreviewComponent {
|
export class ConfigPreviewComponent {
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
matTooltip="Add Module"
|
matTooltip="Add Module"
|
||||||
class="flex items-center justify-center w-10 h-10 bg-transparent hover:bg-gray-700 hover:cursor-pointer text-blue-400"
|
class="flex items-center justify-center w-10 h-10 bg-transparent hover:bg-gray-700 hover:cursor-pointer text-blue-400"
|
||||||
[matMenuTriggerFor]="addModuleMenu"
|
[matMenuTriggerFor]="addModuleMenu"
|
||||||
|
role="button"
|
||||||
|
aria-label="Add Module"
|
||||||
>
|
>
|
||||||
<mat-icon>add</mat-icon>
|
<mat-icon>add</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -27,6 +29,7 @@
|
|||||||
@for (module of modules(); track module.id; let i = $index) {
|
@for (module of modules(); track module.id; let i = $index) {
|
||||||
<div class="m-2" cdkDrag>
|
<div class="m-2" cdkDrag>
|
||||||
<app-module
|
<app-module
|
||||||
|
[id]="listService.pathToId(`modules/${i}`)"
|
||||||
[path]="`modules/${i}`"
|
[path]="`modules/${i}`"
|
||||||
[module]="module"
|
[module]="module"
|
||||||
(updated)="moduleUpdated(i, $event)"
|
(updated)="moduleUpdated(i, $event)"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
import { Component, inject, input, output } from '@angular/core';
|
import { Component, inject, input, output, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
@@ -7,6 +7,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
|||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
import { ModuleConfig } from '../../models/config';
|
import { ModuleConfig } from '../../models/config';
|
||||||
|
import { ListsService } from '../../services/lists';
|
||||||
import { SchemaService } from '../../services/schema';
|
import { SchemaService } from '../../services/schema';
|
||||||
import { ModuleComponent } from '../module/module';
|
import { ModuleComponent } from '../module/module';
|
||||||
|
|
||||||
@@ -22,12 +23,14 @@ import { ModuleComponent } from '../module/module';
|
|||||||
CdkDropList,
|
CdkDropList,
|
||||||
],
|
],
|
||||||
templateUrl: './module-list.html',
|
templateUrl: './module-list.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
styleUrl: './module-list.css',
|
styleUrl: './module-list.css',
|
||||||
})
|
})
|
||||||
export class ModuleListComponent {
|
export class ModuleListComponent {
|
||||||
modules = input<ModuleConfig[]>();
|
modules = input<ModuleConfig[]>();
|
||||||
updated = output<ModuleConfig[]>();
|
updated = output<ModuleConfig[]>();
|
||||||
public schemaService = inject(SchemaService);
|
public schemaService = inject(SchemaService);
|
||||||
|
public listService = inject(ListsService);
|
||||||
|
|
||||||
private snackBar = inject(MatSnackBar);
|
private snackBar = inject(MatSnackBar);
|
||||||
|
|
||||||
@@ -73,7 +76,6 @@ export class ModuleListComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drop(event: CdkDragDrop<ModuleConfig[] | undefined>) {
|
drop(event: CdkDragDrop<ModuleConfig[] | undefined>) {
|
||||||
console.log('Drop event:', event);
|
|
||||||
if (event.previousContainer === event.container) {
|
if (event.previousContainer === event.container) {
|
||||||
const currentModules = this.modules();
|
const currentModules = this.modules();
|
||||||
if (currentModules === undefined) {
|
if (currentModules === undefined) {
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
<div
|
<div
|
||||||
class="flex items-center justify-center hover:bg-gray-700 hover:cursor-pointer"
|
class="flex items-center justify-center hover:bg-gray-700 hover:cursor-pointer"
|
||||||
(click)="delete.emit()"
|
(click)="delete.emit()"
|
||||||
|
role="button"
|
||||||
|
aria-label="Delete Module"
|
||||||
>
|
>
|
||||||
<mat-icon class="text-red-500!">close</mat-icon>
|
<mat-icon class="text-red-500!">close</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import { CdkDragHandle, CdkDragPlaceholder, CdkDragPreview } from '@angular/cdk/drag-drop';
|
import { CdkDragHandle, CdkDragPlaceholder, CdkDragPreview } from '@angular/cdk/drag-drop';
|
||||||
import { JsonPipe } from '@angular/common';
|
import { JsonPipe } from '@angular/common';
|
||||||
import { Component, computed, inject, input, output, signal } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
computed,
|
||||||
|
inject,
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
signal,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
} from '@angular/core';
|
||||||
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
@@ -29,6 +37,7 @@ import { ParamsFormComponent } from '../params-form/params-form';
|
|||||||
CdkDragPlaceholder,
|
CdkDragPlaceholder,
|
||||||
],
|
],
|
||||||
templateUrl: './module.html',
|
templateUrl: './module.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
styleUrl: './module.css',
|
styleUrl: './module.css',
|
||||||
})
|
})
|
||||||
export class ModuleComponent {
|
export class ModuleComponent {
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
import { JsonPipe } from '@angular/common';
|
import { JsonPipe } from '@angular/common';
|
||||||
import { Component, effect, input, OnDestroy, output } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
effect,
|
||||||
|
input,
|
||||||
|
OnDestroy,
|
||||||
|
output,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
} from '@angular/core';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
@@ -26,6 +33,7 @@ import { ArrayFormComponent } from '../array-form/array-form';
|
|||||||
ArrayFormComponent,
|
ArrayFormComponent,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
],
|
],
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
standalone: true,
|
standalone: true,
|
||||||
})
|
})
|
||||||
export class ParamsFormComponent implements OnDestroy {
|
export class ParamsFormComponent implements OnDestroy {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { CdkDragHandle, CdkDragPlaceholder, CdkDragPreview } from '@angular/cdk/drag-drop';
|
import { CdkDragHandle, CdkDragPlaceholder, CdkDragPreview } from '@angular/cdk/drag-drop';
|
||||||
import { Component, computed, inject, input, output } from '@angular/core';
|
import { Component, computed, inject, input, output, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { ReactiveFormsModule } from '@angular/forms';
|
import { ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { ProcessorConfig } from '../../models/config';
|
import { ProcessorConfig } from '../../models/config';
|
||||||
@@ -17,6 +17,7 @@ import { ParamsFormComponent } from '../params-form/params-form';
|
|||||||
CdkDragPlaceholder,
|
CdkDragPlaceholder,
|
||||||
],
|
],
|
||||||
templateUrl: './processor.html',
|
templateUrl: './processor.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
styleUrl: './processor.css',
|
styleUrl: './processor.css',
|
||||||
})
|
})
|
||||||
export class ProcessorComponent {
|
export class ProcessorComponent {
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
matTooltip="Add Route"
|
matTooltip="Add Route"
|
||||||
class="flex items-center justify-center w-10 h-10 bg-transparent hover:bg-gray-700 hover:cursor-pointer text-blue-400"
|
class="flex items-center justify-center w-10 h-10 bg-transparent hover:bg-gray-700 hover:cursor-pointer text-blue-400"
|
||||||
(click)="addRoute()"
|
(click)="addRoute()"
|
||||||
|
role="button"
|
||||||
|
aria-label="Add Route"
|
||||||
>
|
>
|
||||||
<mat-icon>add</mat-icon>
|
<mat-icon>add</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -15,9 +17,10 @@
|
|||||||
(cdkDropListDropped)="drop($event)"
|
(cdkDropListDropped)="drop($event)"
|
||||||
[cdkDropListData]="routes()"
|
[cdkDropListData]="routes()"
|
||||||
>
|
>
|
||||||
@for (route of routes(); track route; let i = $index) {
|
@for (route of routes(); track $index + (route.input || ''); let i = $index) {
|
||||||
<div class="m-2" cdkDrag>
|
<div class="m-2" cdkDrag>
|
||||||
<app-route
|
<app-route
|
||||||
|
[id]="listService.pathToId(`routes/${i}`)"
|
||||||
[path]="`routes/${i}`"
|
[path]="`routes/${i}`"
|
||||||
(updated)="routeUpdated(i, $event)"
|
(updated)="routeUpdated(i, $event)"
|
||||||
[route]="route"
|
[route]="route"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
moveItemInArray,
|
moveItemInArray,
|
||||||
transferArrayItem,
|
transferArrayItem,
|
||||||
} from '@angular/cdk/drag-drop';
|
} from '@angular/cdk/drag-drop';
|
||||||
import { Component, inject, input, output } from '@angular/core';
|
import { Component, inject, input, output, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
@@ -14,6 +14,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
|||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
import { cloneDeep } from 'lodash-es';
|
import { cloneDeep } from 'lodash-es';
|
||||||
import { RouteConfig } from '../../models/config';
|
import { RouteConfig } from '../../models/config';
|
||||||
|
import { ListsService } from '../../services/lists';
|
||||||
import { SchemaService } from '../../services/schema';
|
import { SchemaService } from '../../services/schema';
|
||||||
import { RouteComponent } from '../route/route';
|
import { RouteComponent } from '../route/route';
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ import { RouteComponent } from '../route/route';
|
|||||||
A11yModule,
|
A11yModule,
|
||||||
],
|
],
|
||||||
templateUrl: './route-list.html',
|
templateUrl: './route-list.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
styleUrl: './route-list.css',
|
styleUrl: './route-list.css',
|
||||||
})
|
})
|
||||||
export class RouteListComponent {
|
export class RouteListComponent {
|
||||||
@@ -37,6 +39,7 @@ export class RouteListComponent {
|
|||||||
moduleIds = input<string[]>();
|
moduleIds = input<string[]>();
|
||||||
updated = output<RouteConfig[]>();
|
updated = output<RouteConfig[]>();
|
||||||
public schemaService = inject(SchemaService);
|
public schemaService = inject(SchemaService);
|
||||||
|
public listService = inject(ListsService);
|
||||||
|
|
||||||
private snackBar = inject(MatSnackBar);
|
private snackBar = inject(MatSnackBar);
|
||||||
|
|
||||||
@@ -121,7 +124,6 @@ export class RouteListComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
drop(event: CdkDragDrop<RouteConfig[] | undefined>) {
|
drop(event: CdkDragDrop<RouteConfig[] | undefined>) {
|
||||||
console.log('Drop event:', event);
|
|
||||||
if (event.previousContainer === event.container) {
|
if (event.previousContainer === event.container) {
|
||||||
const currentRoutes = this.routes();
|
const currentRoutes = this.routes();
|
||||||
if (currentRoutes === undefined) {
|
if (currentRoutes === undefined) {
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
<div
|
<div
|
||||||
class="flex items-center justify-center hover:bg-gray-700 hover:cursor-pointer"
|
class="flex items-center justify-center hover:bg-gray-700 hover:cursor-pointer"
|
||||||
(click)="delete.emit()"
|
(click)="delete.emit()"
|
||||||
|
role="button"
|
||||||
|
aria-label="Delete Route"
|
||||||
>
|
>
|
||||||
<mat-icon class="text-red-500!">close</mat-icon>
|
<mat-icon class="text-red-500!">close</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,7 +81,7 @@
|
|||||||
(cdkDropListDropped)="drop($event)"
|
(cdkDropListDropped)="drop($event)"
|
||||||
[cdkDropListData]="route()?.processors"
|
[cdkDropListData]="route()?.processors"
|
||||||
>
|
>
|
||||||
@for (processor of processors(); track processor; let i = $index) {
|
@for (processor of processors(); track $index + processor.type; let i = $index) {
|
||||||
<div cdkDrag>
|
<div cdkDrag>
|
||||||
<app-processor
|
<app-processor
|
||||||
[path]="path() + '/processors/' + i"
|
[path]="path() + '/processors/' + i"
|
||||||
@@ -235,7 +237,7 @@
|
|||||||
(cdkDropListDropped)="drop($event)"
|
(cdkDropListDropped)="drop($event)"
|
||||||
[cdkDropListData]="route()?.processors"
|
[cdkDropListData]="route()?.processors"
|
||||||
>
|
>
|
||||||
@for (processor of processors(); track processor; let i = $index) {
|
@for (processor of processors(); track $index + processor.type; let i = $index) {
|
||||||
<div cdkDrag>
|
<div cdkDrag>
|
||||||
<app-processor
|
<app-processor
|
||||||
[path]="path() + '/processors/' + i"
|
[path]="path() + '/processors/' + i"
|
||||||
|
|||||||
@@ -1,13 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
CdkDrag,
|
CdkDrag,
|
||||||
CdkDragDrop,
|
CdkDragDrop,
|
||||||
|
CdkDragHandle,
|
||||||
CdkDragPlaceholder,
|
CdkDragPlaceholder,
|
||||||
CdkDragPreview,
|
CdkDragPreview,
|
||||||
CdkDropList,
|
CdkDropList,
|
||||||
moveItemInArray,
|
moveItemInArray,
|
||||||
} from '@angular/cdk/drag-drop';
|
} from '@angular/cdk/drag-drop';
|
||||||
import { JsonPipe } from '@angular/common';
|
import { JsonPipe } from '@angular/common';
|
||||||
import { Component, computed, inject, input, output, signal } from '@angular/core';
|
import {
|
||||||
|
Component,
|
||||||
|
computed,
|
||||||
|
inject,
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
signal,
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
} from '@angular/core';
|
||||||
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
@@ -34,11 +43,13 @@ import { ProcessorComponent } from '../processor/processor';
|
|||||||
ProcessorComponent,
|
ProcessorComponent,
|
||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
CdkDrag,
|
CdkDrag,
|
||||||
|
CdkDragHandle,
|
||||||
CdkDropList,
|
CdkDropList,
|
||||||
CdkDragPreview,
|
CdkDragPreview,
|
||||||
CdkDragPlaceholder,
|
CdkDragPlaceholder,
|
||||||
],
|
],
|
||||||
templateUrl: './route.html',
|
templateUrl: './route.html',
|
||||||
|
changeDetection: ChangeDetectionStrategy.Eager,
|
||||||
styleUrl: './route.css',
|
styleUrl: './route.css',
|
||||||
})
|
})
|
||||||
export class RouteComponent {
|
export class RouteComponent {
|
||||||
|
|||||||
+15
-21
@@ -17,17 +17,18 @@ import { SettingsService } from './settings';
|
|||||||
})
|
})
|
||||||
export class ConfigService {
|
export class ConfigService {
|
||||||
pendingConfigIsValid = computed(() => {
|
pendingConfigIsValid = computed(() => {
|
||||||
const config = this.currentlyShownConfig();
|
const config = this._currentlyShownConfig();
|
||||||
if (config === undefined) {
|
if (config === undefined) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.schemaService.validate(this.schemaService.configSchemaId, config);
|
return this.schemaService.validate(this.schemaService.configSchemaId, config);
|
||||||
});
|
});
|
||||||
currentlyShownConfig = signal<Config | undefined>(undefined);
|
private runningConfig = signal<Config | undefined>(undefined);
|
||||||
runningConfig = signal<Config | undefined>(undefined);
|
private _currentlyShownConfig = signal<Config | undefined>(undefined);
|
||||||
|
readonly currentlyShownConfig = this._currentlyShownConfig.asReadonly();
|
||||||
|
|
||||||
configIsDirty = computed(() => {
|
configIsDirty = computed(() => {
|
||||||
const currentlyShown = this.currentlyShownConfig();
|
const currentlyShown = this._currentlyShownConfig();
|
||||||
const running = this.runningConfig();
|
const running = this.runningConfig();
|
||||||
if (currentlyShown === undefined || running === undefined) {
|
if (currentlyShown === undefined || running === undefined) {
|
||||||
return false;
|
return false;
|
||||||
@@ -44,7 +45,7 @@ export class ConfigService {
|
|||||||
|
|
||||||
constructor(private schemaService: SchemaService) {
|
constructor(private schemaService: SchemaService) {
|
||||||
effect(() => {
|
effect(() => {
|
||||||
console.log('config state changed', this.currentlyShownConfig());
|
console.log('config state changed', this._currentlyShownConfig());
|
||||||
});
|
});
|
||||||
|
|
||||||
effect(() => {
|
effect(() => {
|
||||||
@@ -124,36 +125,29 @@ export class ConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateCurrentlyShownConfig(config: Config) {
|
updateCurrentlyShownConfig(config: Config) {
|
||||||
if (isEqual(config, this.currentlyShownConfig())) {
|
this._currentlyShownConfig.set(cloneDeep(config));
|
||||||
// NOTE(jwetzell): no update
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.currentlyShownConfig.set(cloneDeep(config));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateModules(modules: ModuleConfig[]) {
|
updateModules(modules: ModuleConfig[]) {
|
||||||
const currentConfig = this.currentlyShownConfig();
|
var newConfig = cloneDeep(this._currentlyShownConfig());
|
||||||
if (!currentConfig) {
|
if (!newConfig) {
|
||||||
console.error('No currently shown config to update modules on');
|
console.error('No currently shown config to update modules on');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
newConfig.modules = cloneDeep(modules);
|
||||||
|
|
||||||
this.currentlyShownConfig.set({
|
this.updateCurrentlyShownConfig(newConfig);
|
||||||
...currentConfig,
|
|
||||||
modules: modules,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRoutes(routes: RouteConfig[]) {
|
updateRoutes(routes: RouteConfig[]) {
|
||||||
const currentConfig = this.currentlyShownConfig();
|
const currentConfig = this._currentlyShownConfig();
|
||||||
if (!currentConfig) {
|
if (!currentConfig) {
|
||||||
console.error('No currently shown config to update routes on');
|
console.error('No currently shown config to update routes on');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentlyShownConfig.set({
|
currentConfig.routes = cloneDeep(routes);
|
||||||
...currentConfig,
|
|
||||||
routes: routes,
|
this.updateCurrentlyShownConfig(currentConfig);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-1
@@ -7,5 +7,13 @@
|
|||||||
"types": []
|
"types": []
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.ts"],
|
"include": ["src/**/*.ts"],
|
||||||
"exclude": ["src/**/*.spec.ts"]
|
"exclude": ["src/**/*.spec.ts"],
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"extendedDiagnostics": {
|
||||||
|
"checks": {
|
||||||
|
"nullishCoalescingNotNullable": "suppress",
|
||||||
|
"optionalChainNotNullable": "suppress"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user