mirror of
https://github.com/jwetzell/showbridge-webui.git
synced 2026-09-04 21:09:00 +00:00
flatter layout
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
|
import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
|
||||||
import { provideRouter } from '@angular/router';
|
import { provideRouter } from '@angular/router';
|
||||||
|
import { appRoutes } from './app.routes';
|
||||||
|
|
||||||
export const appConfig: ApplicationConfig = {
|
export const appConfig: ApplicationConfig = {
|
||||||
providers: [provideBrowserGlobalErrorListeners()],
|
providers: [
|
||||||
|
provideBrowserGlobalErrorListeners(),
|
||||||
|
provideRouter(appRoutes),
|
||||||
|
],
|
||||||
};
|
};
|
||||||
|
|||||||
+4
-3
@@ -18,13 +18,14 @@
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
<div class="flex-grow h-full overflow-hidden">
|
<div class="flex-grow h-full overflow-y-auto">
|
||||||
@if (configService.currentlyShownConfig() && schemaService.schemasLoaded()) {
|
<router-outlet></router-outlet>
|
||||||
|
<!-- @if (configService.currentlyShownConfig() && schemaService.schemasLoaded()) {
|
||||||
<app-config [(config)]="configService.currentlyShownConfig"></app-config>
|
<app-config [(config)]="configService.currentlyShownConfig"></app-config>
|
||||||
} @else {
|
} @else {
|
||||||
<div class="flex items-center justify-center mt-28">
|
<div class="flex items-center justify-center mt-28">
|
||||||
<mat-spinner></mat-spinner>
|
<mat-spinner></mat-spinner>
|
||||||
</div>
|
</div>
|
||||||
}
|
} -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import { Routes } from '@angular/router';
|
||||||
|
import { App } from './app';
|
||||||
|
|
||||||
|
export const appRoutes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
redirectTo: 'config',
|
||||||
|
pathMatch: 'full',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'config',
|
||||||
|
loadComponent: () => import('./config/config.component').then((m) => m.ConfigComponent),
|
||||||
|
},
|
||||||
|
];
|
||||||
+3
-4
@@ -13,28 +13,27 @@ import { SchemaService } from '../services/schema.service';
|
|||||||
import { SettingsService } from '../services/settings.service';
|
import { SettingsService } from '../services/settings.service';
|
||||||
import { ConfigComponent } from './config/config.component';
|
import { ConfigComponent } from './config/config.component';
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
|
import { RouterOutlet } from '@angular/router';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
imports: [
|
imports: [
|
||||||
ConfigComponent,
|
|
||||||
MatToolbarModule,
|
MatToolbarModule,
|
||||||
MatProgressSpinnerModule,
|
MatProgressSpinnerModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
TimeagoModule,
|
TimeagoModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
],
|
RouterOutlet
|
||||||
|
],
|
||||||
templateUrl: './app.html',
|
templateUrl: './app.html',
|
||||||
styleUrl: './app.css',
|
styleUrl: './app.css',
|
||||||
})
|
})
|
||||||
export class App {
|
export class App {
|
||||||
public schemaService = inject(SchemaService);
|
public schemaService = inject(SchemaService);
|
||||||
public configService = inject(ConfigService);
|
public configService = inject(ConfigService);
|
||||||
private settingsService = inject(SettingsService);
|
|
||||||
|
|
||||||
private snackBar = inject(MatSnackBar);
|
private snackBar = inject(MatSnackBar);
|
||||||
private dialog = inject(MatDialog);
|
|
||||||
constructor() {
|
constructor() {
|
||||||
effect(() => {
|
effect(() => {
|
||||||
if (this.schemaService.schemasLoaded()) {
|
if (this.schemaService.schemasLoaded()) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div cdkDropList (cdkDropListDropped)="dropItem($event)" [cdkDropListData]="arrayValue">
|
<div cdkDropList (cdkDropListDropped)="dropItem($event)" [cdkDropListData]="arrayValue">
|
||||||
@for (item of arrayValue; track trackByIndex(i, item); let i = $index) {
|
@for (item of arrayValue; track trackByIndex(i, item); let i = $index) {
|
||||||
<div cdkDrag class="flex my-2 mr-2 items-center">
|
<div cdkDrag class="flex my-2 mr-2 items-center">
|
||||||
<label for="item-{{ i }}" class="text-gray-300 mr-1 hover:cursor-move" cdkDragHandle
|
<label for="item-{{ i }}" class="text-white mr-1 hover:cursor-move" cdkDragHandle
|
||||||
>{{ i }}:</label
|
>{{ i }}:</label
|
||||||
>
|
>
|
||||||
<!-- @if (paramInfo?.schema.items.type === 'object') {
|
<!-- @if (paramInfo?.schema.items.type === 'object') {
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
<!-- TODO(jwetzell): add input validation using info from schema -->
|
<!-- TODO(jwetzell): add input validation using info from schema -->
|
||||||
<input
|
<input
|
||||||
id="item-{{ i }}"
|
id="item-{{ i }}"
|
||||||
class="pl-1 border-2 border-gray-200 border-solid rounded-sm text-gray-200"
|
class="pl-1 border-2 border-gray-200 border-solid rounded-sm text-white"
|
||||||
[(ngModel)]="arrayValue[i]"
|
[(ngModel)]="arrayValue[i]"
|
||||||
[placeholder]="paramInfo?.placeholder"
|
[placeholder]="paramInfo?.placeholder"
|
||||||
[ngModelOptions]="{ standalone: true }"
|
[ngModelOptions]="{ standalone: true }"
|
||||||
|
|||||||
@@ -1,78 +1,4 @@
|
|||||||
@if (config()) {
|
@if (config() && schemaService.schemasLoaded()) {
|
||||||
<div class="flex h-full flex-row p-2 gap-1.5">
|
<app-module-list [modules]="config()?.modules" (modulesChange)="modulesUpdated($event)"></app-module-list>
|
||||||
<div class="flex flex-col min-w-1/6 border-2 rounded-lg border-gray-500">
|
<app-route-list [routes]="config()?.routes" [moduleIds]="moduleIds()" (routesChange)="routesUpdated($event)"></app-route-list>
|
||||||
<div class="flex items-center">
|
}
|
||||||
@if (schemaService.moduleTypes.length > 0) {
|
|
||||||
<div
|
|
||||||
matTooltip="Add Module"
|
|
||||||
class="flex items-center justify-center w-10 h-10 rounded-full bg-transparent hover:bg-gray-700 hover:cursor-pointer text-blue-400 border-blue-400 border-2 m-2"
|
|
||||||
[matMenuTriggerFor]="addModuleMenu"
|
|
||||||
>
|
|
||||||
<mat-icon>add</mat-icon>
|
|
||||||
</div>
|
|
||||||
<mat-menu #addModuleMenu="matMenu">
|
|
||||||
@for (moduleType of schemaService.moduleTypes; track moduleType) {
|
|
||||||
<button mat-menu-item (click)="addModule(moduleType.type)">
|
|
||||||
<span>{{ moduleType.name }}</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</mat-menu>
|
|
||||||
}
|
|
||||||
<div class="text-2xl text-white flex-grow text-center">Modules</div>
|
|
||||||
<div class="w-10 h-10 m-2"></div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-grow h-full overflow-x-hidden overflow-y-auto gap-1.5">
|
|
||||||
@for (module of modules(); track module; let i = $index) {
|
|
||||||
<div>
|
|
||||||
<app-module
|
|
||||||
[path]="`modules/${i}`"
|
|
||||||
(moduleChange)="moduleUpdated(i, $event)"
|
|
||||||
[module]="module"
|
|
||||||
(delete)="deleteModule(i)"
|
|
||||||
></app-module>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col flex-grow border-2 border-gray-500 rounded-lg">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div
|
|
||||||
matTooltip="Add Route"
|
|
||||||
class="flex items-center justify-center w-10 h-10 rounded-full bg-transparent hover:bg-gray-700 hover:cursor-pointer text-blue-400 border-blue-400 border-2 m-2"
|
|
||||||
(click)="addRoute()"
|
|
||||||
>
|
|
||||||
<mat-icon>add</mat-icon>
|
|
||||||
</div>
|
|
||||||
<div class="text-2xl text-white text-center flex-grow">Routes</div>
|
|
||||||
<div class="w-10 h-10 m-2"></div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="flex-grow h-full overflow-x-hidden overflow-y-auto flex flex-row flex-wrap gap-1.5 content-baselinerounded-sm"
|
|
||||||
>
|
|
||||||
@for (route of routes(); track route; let i = $index) {
|
|
||||||
<div>
|
|
||||||
<app-route
|
|
||||||
[path]="`routes/${i}`"
|
|
||||||
(routeChange)="routeUpdated(i, $event)"
|
|
||||||
[route]="route"
|
|
||||||
[moduleIds]="moduleIds()"
|
|
||||||
(delete)="deleteRoute(i)"
|
|
||||||
></app-route>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
<ng-template #addModuleMenu>
|
|
||||||
@if (schemaService.moduleTypes.length > 0) {
|
|
||||||
<div cdkMenu class="context-menu">
|
|
||||||
@for (moduleType of schemaService.moduleTypes; track moduleType) {
|
|
||||||
<button cdkMenuItem class="context-menu-item" (click)="addModule(moduleType.type)">
|
|
||||||
<span>{{ moduleType.name }}</span>
|
|
||||||
</button>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</ng-template>
|
|
||||||
@@ -5,25 +5,26 @@ import { MatMenuModule } from '@angular/material/menu';
|
|||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
import { Config, ModuleConfiguration, RouteConfiguration } from '../../models/config.models';
|
import { Config, ModuleConfiguration, RouteConfiguration } from '../../models/config.models';
|
||||||
import { SchemaService } from '../../services/schema.service';
|
import { SchemaService } from '../../services/schema.service';
|
||||||
import { ModuleComponent } from '../module/module.component';
|
|
||||||
import { RouteComponent } from '../route/route.component';
|
|
||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
import { ModuleListComponent } from '../module-list/module-list.component';
|
||||||
|
import { RouteListComponent } from '../route-list.component/route-list.component';
|
||||||
|
import { ConfigService } from '../../services/config.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-config',
|
selector: 'app-config',
|
||||||
imports: [
|
imports: [
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
MatIconModule,
|
MatIconModule,
|
||||||
ModuleComponent,
|
|
||||||
RouteComponent,
|
|
||||||
MatButtonModule,
|
MatButtonModule,
|
||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
|
ModuleListComponent,
|
||||||
|
RouteListComponent,
|
||||||
],
|
],
|
||||||
templateUrl: './config.component.html',
|
templateUrl: './config.component.html',
|
||||||
styleUrl: './config.component.css',
|
styleUrl: './config.component.css',
|
||||||
})
|
})
|
||||||
export class ConfigComponent {
|
export class ConfigComponent {
|
||||||
config = model<Config>();
|
config = computed<Config | undefined>(() => this.configService.currentlyShownConfig());
|
||||||
|
|
||||||
modules = computed(() => this.config()?.modules ?? []);
|
modules = computed(() => this.config()?.modules ?? []);
|
||||||
routes = computed(() => this.config()?.routes ?? []);
|
routes = computed(() => this.config()?.routes ?? []);
|
||||||
@@ -36,109 +37,35 @@ export class ConfigComponent {
|
|||||||
return [];
|
return [];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
public configService = inject(ConfigService);
|
||||||
public schemaService = inject(SchemaService);
|
public schemaService = inject(SchemaService);
|
||||||
|
|
||||||
private snackBar = inject(MatSnackBar);
|
modulesUpdated(modules: ModuleConfiguration[] | undefined) {
|
||||||
|
if (modules === undefined) {
|
||||||
deleteModule(index: number) {
|
console.error('modules is undefined, not updating');
|
||||||
this.config.update((config) => {
|
|
||||||
if (config && config.modules) {
|
|
||||||
config?.modules?.splice(index, 1);
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
modules: config.modules,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
this.snackBar.open('Module Removed', 'Dismiss', {
|
|
||||||
duration: 3000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteRoute(index: number) {
|
|
||||||
this.config.update((config) => {
|
|
||||||
if (config && config.routes) {
|
|
||||||
config?.routes?.splice(index, 1);
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
routes: config.routes,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
this.snackBar.open('Route Removed', 'Dismiss', {
|
|
||||||
duration: 3000,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
moduleUpdated(index: number, module: ModuleConfiguration | undefined) {
|
|
||||||
if (module === undefined) {
|
|
||||||
console.error('module is undefined, not updating');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.config.update((config) => {
|
this.configService.currentlyShownConfig.update((config) => {
|
||||||
if (config && config.modules) {
|
if (config) {
|
||||||
config.modules[index].id = module.id;
|
|
||||||
config.modules[index].type = module.type;
|
|
||||||
if (module.params !== undefined) {
|
|
||||||
config.modules[index].params = module.params;
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
...config,
|
...config,
|
||||||
modules: config.modules,
|
modules: modules,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
routeUpdated(index: number, route: RouteConfiguration | undefined) {
|
routesUpdated(routes: RouteConfiguration[] | undefined) {
|
||||||
if (route === undefined) {
|
if (routes === undefined) {
|
||||||
console.error('route is undefined, not updating');
|
console.error('routes is undefined, not updating');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.config.update((config) => {
|
this.configService.currentlyShownConfig.update((config) => {
|
||||||
if (config && config.routes) {
|
|
||||||
config.routes[index].input = route.input;
|
|
||||||
config.routes[index].output = route.output;
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
routes: config.routes,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addModule(moduleType: string) {
|
|
||||||
const moduleTemplate = this.schemaService.getSkeletonForModule(moduleType);
|
|
||||||
this.config.update((config) => {
|
|
||||||
if (config) {
|
if (config) {
|
||||||
if (!config.modules) {
|
|
||||||
config.modules = [];
|
|
||||||
}
|
|
||||||
config.modules?.push(moduleTemplate);
|
|
||||||
return {
|
return {
|
||||||
...config,
|
...config,
|
||||||
modules: config.modules,
|
routes: routes,
|
||||||
};
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
addRoute() {
|
|
||||||
const routeTemplate = this.schemaService.getSkeletonForRoute();
|
|
||||||
this.config.update((config) => {
|
|
||||||
if (config) {
|
|
||||||
if (!config.routes) {
|
|
||||||
config.routes = [];
|
|
||||||
}
|
|
||||||
config.routes?.push(routeTemplate);
|
|
||||||
return {
|
|
||||||
...config,
|
|
||||||
routes: config.routes,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="flex items-center">
|
||||||
|
@if (schemaService.moduleTypes.length > 0) {
|
||||||
|
<div
|
||||||
|
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"
|
||||||
|
[matMenuTriggerFor]="addModuleMenu"
|
||||||
|
>
|
||||||
|
<mat-icon>add</mat-icon>
|
||||||
|
</div>
|
||||||
|
<mat-menu #addModuleMenu="matMenu">
|
||||||
|
@for (moduleType of schemaService.moduleTypes; track moduleType) {
|
||||||
|
<button mat-menu-item (click)="addModule(moduleType.type)">
|
||||||
|
<span>{{ moduleType.name }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</mat-menu>
|
||||||
|
}
|
||||||
|
<div class="text-white">Modules</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-grow overflow-x-hidden overflow-y-auto gap-1.5">
|
||||||
|
@for (module of modules(); track module; let i = $index) {
|
||||||
|
<div class="m-2">
|
||||||
|
<app-module
|
||||||
|
[path]="`modules/${i}`"
|
||||||
|
(moduleChange)="moduleUpdated(i, $event)"
|
||||||
|
[module]="module"
|
||||||
|
(delete)="deleteModule(i)"
|
||||||
|
></app-module>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-template #addModuleMenu>
|
||||||
|
@if (schemaService.moduleTypes.length > 0) {
|
||||||
|
<div cdkMenu class="context-menu">
|
||||||
|
@for (moduleType of schemaService.moduleTypes; track moduleType) {
|
||||||
|
<button cdkMenuItem class="context-menu-item" (click)="addModule(moduleType.type)">
|
||||||
|
<span>{{ moduleType.name }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</ng-template>
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
import { Component, inject, model } from '@angular/core';
|
||||||
|
import { ModuleComponent } from '../module/module.component';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { ModuleConfiguration } from '../../models/config.models';
|
||||||
|
import { SchemaService } from '../../services/schema.service';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
import { RouteComponent } from '../route/route.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-module-list',
|
||||||
|
imports: [
|
||||||
|
MatMenuModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatTooltipModule,
|
||||||
|
ModuleComponent
|
||||||
|
],
|
||||||
|
templateUrl: './module-list.component.html',
|
||||||
|
styleUrl: './module-list.component.css',
|
||||||
|
})
|
||||||
|
export class ModuleListComponent {
|
||||||
|
modules = model<ModuleConfiguration[]>();
|
||||||
|
public schemaService = inject(SchemaService);
|
||||||
|
|
||||||
|
private snackBar = inject(MatSnackBar);
|
||||||
|
|
||||||
|
moduleUpdated(index: number, module: ModuleConfiguration | undefined) {
|
||||||
|
if (module === undefined) {
|
||||||
|
console.error('module is undefined, not updating');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.modules.update((modules) => {
|
||||||
|
if (modules) {
|
||||||
|
modules[index].id = module.id;
|
||||||
|
modules[index].type = module.type;
|
||||||
|
if (module.params !== undefined) {
|
||||||
|
modules[index].params = module.params;
|
||||||
|
}
|
||||||
|
return [...modules];
|
||||||
|
}
|
||||||
|
return modules;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addModule(moduleType: string) {
|
||||||
|
const moduleTemplate = this.schemaService.getSkeletonForModule(moduleType);
|
||||||
|
this.modules.update((modules) => {
|
||||||
|
if (modules) {
|
||||||
|
if (!modules) {
|
||||||
|
modules = [];
|
||||||
|
}
|
||||||
|
modules?.push(moduleTemplate);
|
||||||
|
return [...modules];
|
||||||
|
}
|
||||||
|
return modules;
|
||||||
|
});
|
||||||
|
this.snackBar.open('Module Added', 'Dismiss', {
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteModule(index: number) {
|
||||||
|
this.modules.update((modules) => {
|
||||||
|
if (modules) {
|
||||||
|
modules?.splice(index, 1);
|
||||||
|
return [...modules];
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
});
|
||||||
|
this.snackBar.open('Module Removed', 'Dismiss', {
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
@if (module() && schema()) {
|
@if (module() && schema()) {
|
||||||
<div class="flex items-start m-2 w-fit">
|
|
||||||
<div
|
<div
|
||||||
class="flex flex-col bg-gray-800 border-2 {{
|
class="flex flex-col bg-gray-800 border-2 {{
|
||||||
isInError() ? 'border-red-500' : 'border-gray-200'
|
isInError() ? 'border-red-500' : 'border-gray-600'
|
||||||
}} border-solid w-fit h-full"
|
}} border-solid w-full h-full"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-center bg-gray-600">
|
<div class="flex items-center justify-center border-gray-600 border-b-2">
|
||||||
<div class="flex-grow ml-1 mr-3 text-gray-200">
|
<div class="flex-grow ml-1 mr-3 text-white">
|
||||||
{{ schema().title }}
|
{{ schema().title || module()?.type }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-center" (click)="delete.emit()">
|
<div class="flex items-center justify-center" (click)="delete.emit()">
|
||||||
<mat-icon class="!text-red-500">close</mat-icon>
|
<mat-icon class="!text-red-500">close</mat-icon>
|
||||||
@@ -17,13 +16,18 @@
|
|||||||
<form [formGroup]="formGroup" class="h-full">
|
<form [formGroup]="formGroup" class="h-full">
|
||||||
<div class="m-2">
|
<div class="m-2">
|
||||||
<div class="flex items-center m-1">
|
<div class="flex items-center m-1">
|
||||||
<label class="mr-2 text-gray-300"> id: </label>
|
<label class="mr-2 text-white"> id: </label>
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[placeholder]="'module-1'"
|
[placeholder]="'module-1'"
|
||||||
[formControlName]="'id'"
|
[formControlName]="'id'"
|
||||||
/>
|
/>
|
||||||
|
<mat-icon class="!text-white" matTooltip="String">abc</mat-icon>
|
||||||
|
@if (!formGroup.controls['id'].valid) {
|
||||||
|
<!-- TODO(jwetzell): better error displaying -->
|
||||||
|
<div class="ml-2 text-red-500">{{ formGroup.controls['id'].errors | json }}</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<app-params-form
|
<app-params-form
|
||||||
[paramsSchema]="schema()?.properties?.params"
|
[paramsSchema]="schema()?.properties?.params"
|
||||||
@@ -34,5 +38,4 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import { Component, computed, inject, input, model, output } from '@angular/core';
|
import { Component, computed, inject, input, model, output } from '@angular/core';
|
||||||
import { FormControl, FormGroup, ReactiveFormsModule } 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';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { ModuleConfiguration } from '../../models/config.models';
|
import { ModuleConfiguration } from '../../models/config.models';
|
||||||
import { SchemaService } from '../../services/schema.service';
|
import { SchemaService } from '../../services/schema.service';
|
||||||
import { ParamsFormComponent } from '../params-form/params-form.component';
|
import { ParamsFormComponent } from '../params-form/params-form.component';
|
||||||
|
import { JsonPipe } from '@angular/common';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-module',
|
selector: 'app-module',
|
||||||
@@ -15,6 +17,8 @@ import { ParamsFormComponent } from '../params-form/params-form.component';
|
|||||||
ParamsFormComponent,
|
ParamsFormComponent,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
|
MatTooltipModule,
|
||||||
|
JsonPipe,
|
||||||
],
|
],
|
||||||
templateUrl: './module.component.html',
|
templateUrl: './module.component.html',
|
||||||
styleUrl: './module.component.css',
|
styleUrl: './module.component.css',
|
||||||
@@ -34,7 +38,7 @@ export class ModuleComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
formGroup: FormGroup = new FormGroup({
|
formGroup: FormGroup = new FormGroup({
|
||||||
id: new FormControl(''),
|
id: new FormControl('', [Validators.required]),
|
||||||
type: new FormControl(''),
|
type: new FormControl(''),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
@if (paramsSchema && paramsFormInfo) {
|
@if (paramsSchema && paramsFormInfo) {
|
||||||
@if (paramsOptions.length > 1) {
|
@if (paramsOptions.length > 1) {
|
||||||
<mat-tab-group
|
<mat-tab-group
|
||||||
|
dynamicHeight
|
||||||
[selectedIndex]="paramsOptionsSelectedIndex"
|
[selectedIndex]="paramsOptionsSelectedIndex"
|
||||||
(selectedTabChange)="paramsOptionsTabSelected($event)"
|
(selectedTabChange)="paramsOptionsTabSelected($event)"
|
||||||
>
|
>
|
||||||
@@ -14,7 +15,7 @@
|
|||||||
@for (key of paramKeys(); track key) {
|
@for (key of paramKeys(); track key) {
|
||||||
<div class="flex items-center m-1">
|
<div class="flex items-center m-1">
|
||||||
@if (getParamInfo(key); as paramInfo) {
|
@if (getParamInfo(key); as paramInfo) {
|
||||||
<label class="mr-2 text-gray-300"> {{ paramInfo.display }}: </label>
|
<label class="mr-2 text-white"> {{ paramInfo.display }}: </label>
|
||||||
@switch (paramInfo.type) {
|
@switch (paramInfo.type) {
|
||||||
@case ('boolean') {
|
@case ('boolean') {
|
||||||
<input type="checkbox" [formControlName]="paramInfo.key" />
|
<input type="checkbox" [formControlName]="paramInfo.key" />
|
||||||
@@ -24,12 +25,12 @@
|
|||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
[placeholder]="paramInfo.placeholder"
|
[placeholder]="paramInfo.placeholder"
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[formControlName]="paramInfo.key"
|
[formControlName]="paramInfo.key"
|
||||||
/>
|
/>
|
||||||
} @else {
|
} @else {
|
||||||
<select
|
<select
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[formControlName]="paramInfo.key"
|
[formControlName]="paramInfo.key"
|
||||||
>
|
>
|
||||||
@for (option of paramInfo.options; track option) {
|
@for (option of paramInfo.options; track option) {
|
||||||
@@ -39,19 +40,19 @@
|
|||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
}
|
}
|
||||||
<mat-icon class="!text-gray-200">123</mat-icon>
|
<mat-icon class="!text-white">123</mat-icon>
|
||||||
}
|
}
|
||||||
@case ('integer') {
|
@case ('integer') {
|
||||||
@if (!paramInfo.options) {
|
@if (!paramInfo.options) {
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number"
|
||||||
[placeholder]="paramInfo.placeholder"
|
[placeholder]="paramInfo.placeholder"
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[formControlName]="paramInfo.key"
|
[formControlName]="paramInfo.key"
|
||||||
/>
|
/>
|
||||||
} @else {
|
} @else {
|
||||||
<select
|
<select
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[formControlName]="paramInfo.key"
|
[formControlName]="paramInfo.key"
|
||||||
>
|
>
|
||||||
@for (option of paramInfo.options; track option) {
|
@for (option of paramInfo.options; track option) {
|
||||||
@@ -61,19 +62,19 @@
|
|||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
}
|
}
|
||||||
<mat-icon class="!text-gray-200" matTooltip="Number">123</mat-icon>
|
<mat-icon class="!text-white" matTooltip="Number">123</mat-icon>
|
||||||
}
|
}
|
||||||
@case ('string') {
|
@case ('string') {
|
||||||
@if (!paramInfo.options) {
|
@if (!paramInfo.options) {
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[placeholder]="paramInfo.placeholder"
|
[placeholder]="paramInfo.placeholder"
|
||||||
[formControlName]="paramInfo.key"
|
[formControlName]="paramInfo.key"
|
||||||
/>
|
/>
|
||||||
} @else {
|
} @else {
|
||||||
<select
|
<select
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[formControlName]="paramInfo.key"
|
[formControlName]="paramInfo.key"
|
||||||
>
|
>
|
||||||
@for (option of paramInfo.options; track option) {
|
@for (option of paramInfo.options; track option) {
|
||||||
@@ -83,42 +84,44 @@
|
|||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
}
|
}
|
||||||
<mat-icon class="!text-gray-200" matTooltip="String">abc</mat-icon>
|
<mat-icon class="!text-white" matTooltip="String">abc</mat-icon>
|
||||||
}
|
}
|
||||||
@case ('array') {
|
@case ('array') {
|
||||||
<app-array-form
|
<app-array-form
|
||||||
[paramFormControl]="paramsFormInfo.formGroup.get(paramInfo.key)"
|
[paramFormControl]="paramsFormInfo.formGroup.get(paramInfo.key)"
|
||||||
[paramInfo]="paramInfo"
|
[paramInfo]="paramInfo"
|
||||||
></app-array-form>
|
></app-array-form>
|
||||||
<mat-icon class="!text-gray-200" matTooltip="Item list">data_array</mat-icon>
|
<mat-icon class="!text-white" matTooltip="Item list">data_array</mat-icon>
|
||||||
}
|
}
|
||||||
@case ('object') {
|
@case ('object') {
|
||||||
<!-- TODO(jwetzell): figure out how to display objects-->
|
<!-- TODO(jwetzell): figure out how to display objects-->
|
||||||
<input
|
<input
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[formControlName]="paramInfo.key"
|
[formControlName]="paramInfo.key"
|
||||||
[placeholder]="paramInfo.placeholder"
|
[placeholder]="paramInfo.placeholder"
|
||||||
/>
|
/>
|
||||||
<mat-icon class="!text-gray-200" matTooltip="JSON">data_object</mat-icon>
|
<mat-icon class="!text-white" matTooltip="JSON">data_object</mat-icon>
|
||||||
}
|
}
|
||||||
@default {
|
@default {
|
||||||
<input
|
<input
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm"
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm"
|
||||||
[formControlName]="paramInfo.key"
|
[formControlName]="paramInfo.key"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@if (paramInfo.hint) {
|
||||||
|
<div class="flex items-center justify-center">
|
||||||
|
<mat-icon [matTooltip]="paramInfo.hint" class="ml-2 !text-white">
|
||||||
|
help_outline
|
||||||
|
</mat-icon>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
@if (!paramsFormInfo.formGroup.controls[key].valid) {
|
@if (!paramsFormInfo.formGroup.controls[key].valid) {
|
||||||
<!-- TODO(jwetzell): better error displaying -->
|
<!-- TODO(jwetzell): better error displaying -->
|
||||||
<div class="ml-2 text-red-500">
|
<div class="ml-2 text-red-500">
|
||||||
{{ paramsFormInfo.formGroup.controls[key].errors | json }}
|
{{ paramsFormInfo.formGroup.controls[key].errors | json }}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div class="flex items-center justify-center">
|
|
||||||
<mat-icon [matTooltip]="paramInfo.hint" class="ml-2 !text-gray-200">
|
|
||||||
help_outline
|
|
||||||
</mat-icon>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
<div class="flex items-start m-2 w-fit">
|
<div class="flex items-start m-2 w-fit">
|
||||||
<div
|
<div
|
||||||
class="flex flex-col bg-gray-800 border-2 {{
|
class="flex flex-col bg-gray-800 border-2 {{
|
||||||
isInError() ? 'border-red-500' : 'border-gray-200'
|
isInError() ? 'border-red-500' : 'border-gray-600'
|
||||||
}} border-solid w-fit h-full"
|
}} border-solid w-fit h-full"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-center bg-gray-600">
|
<div class="flex items-center justify-center border-gray-600 border-b-2">
|
||||||
<div class="flex-grow ml-1 mr-3 text-gray-200">
|
<div class="flex-grow ml-1 mr-3 text-white">
|
||||||
{{ processor()?.type }}
|
{{ schema()?.title || processor()?.type }}
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-center" (click)="delete.emit()">
|
<div class="flex items-center justify-center" (click)="delete.emit()">
|
||||||
<mat-icon class="!text-red-500">close</mat-icon>
|
<mat-icon class="!text-red-500">close</mat-icon>
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div
|
||||||
|
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"
|
||||||
|
(click)="addRoute()"
|
||||||
|
>
|
||||||
|
<mat-icon>add</mat-icon>
|
||||||
|
</div>
|
||||||
|
<div class="text-white">Routes</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex-grow overflow-x-hidden overflow-y-auto gap-1.5">
|
||||||
|
@for (route of routes(); track route; let i = $index) {
|
||||||
|
<div class="m-2">
|
||||||
|
<app-route
|
||||||
|
[path]="`routes/${i}`"
|
||||||
|
(routeChange)="routeUpdated(i, $event)"
|
||||||
|
[route]="route"
|
||||||
|
[moduleIds]="moduleIds() || []"
|
||||||
|
(delete)="deleteRoute(i)"
|
||||||
|
></app-route>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
import { Component, inject, input, model } from '@angular/core';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { ModuleConfiguration, RouteConfiguration } from '../../models/config.models';
|
||||||
|
import { SchemaService } from '../../services/schema.service';
|
||||||
|
import { RouteComponent } from '../route/route.component';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-route-list',
|
||||||
|
imports: [
|
||||||
|
RouteComponent,
|
||||||
|
MatMenuModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatButtonModule,
|
||||||
|
MatTooltipModule,
|
||||||
|
],
|
||||||
|
templateUrl: './route-list.component.html',
|
||||||
|
styleUrl: './route-list.component.css',
|
||||||
|
})
|
||||||
|
export class RouteListComponent {
|
||||||
|
|
||||||
|
routes = model<RouteConfiguration[]>();
|
||||||
|
moduleIds = input<string[]>();
|
||||||
|
public schemaService = inject(SchemaService);
|
||||||
|
|
||||||
|
private snackBar = inject(MatSnackBar);
|
||||||
|
|
||||||
|
deleteRoute(index: number) {
|
||||||
|
this.routes.update((routes) => {
|
||||||
|
if (routes) {
|
||||||
|
routes?.splice(index, 1);
|
||||||
|
return [...routes];
|
||||||
|
}
|
||||||
|
return routes;
|
||||||
|
});
|
||||||
|
this.snackBar.open('Route Removed', 'Dismiss', {
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
routeUpdated(index: number, route: RouteConfiguration | undefined) {
|
||||||
|
if (route === undefined) {
|
||||||
|
console.error('route is undefined, not updating');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.routes.update((routes) => {
|
||||||
|
if (routes) {
|
||||||
|
routes[index].input = route.input;
|
||||||
|
routes[index].output = route.output;
|
||||||
|
return [...routes];
|
||||||
|
}
|
||||||
|
return routes;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
addRoute() {
|
||||||
|
const routeTemplate = this.schemaService.getSkeletonForRoute();
|
||||||
|
this.routes.update((routes) => {
|
||||||
|
if (!routes) {
|
||||||
|
routes = [];
|
||||||
|
}
|
||||||
|
routes?.push(routeTemplate);
|
||||||
|
return [...routes];
|
||||||
|
});
|
||||||
|
this.snackBar.open('Route Added', 'Dismiss', {
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,77 +1,76 @@
|
|||||||
@if (route()) {
|
@if (route()) {
|
||||||
<div class="flex items-start m-2 w-fit">
|
<!-- <div class="flex items-start m-2 w-fit border-2 border-red-500"> -->
|
||||||
<div
|
<div
|
||||||
class="flex flex-col bg-gray-800 border-2 {{
|
class="flex flex-col bg-gray-800 border-2 {{
|
||||||
isInError() ? 'border-red-500' : 'border-gray-200'
|
isInError() ? 'border-red-500' : 'border-gray-600'
|
||||||
}} border-solid w-fit h-full mr-2"
|
}} border-solid w-full h-full"
|
||||||
>
|
>
|
||||||
<div class="flex items-center justify-end bg-gray-600">
|
<div class="flex items-center justify-end border-gray-600 border-b-2">
|
||||||
<div class="flex items-center justify-center" (click)="delete.emit()">
|
<div class="flex-grow text-left ml-2 text-white">Route {{ index() }}</div>
|
||||||
<mat-icon class="!text-red-500">close</mat-icon>
|
<div class="flex items-center justify-center hover:bg-gray-700" (click)="delete.emit()">
|
||||||
</div>
|
<mat-icon class="!text-red-500">close</mat-icon>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<form [formGroup]="formGroup">
|
||||||
|
<div class="m-2">
|
||||||
|
<div class="flex items-center m-1">
|
||||||
|
<label class="mr-2 text-white"> input: </label>
|
||||||
|
<select
|
||||||
|
class="pl-1 border-2 border-gray-200 text-white border-solid rounded-sm w-full"
|
||||||
|
formControlName="input"
|
||||||
|
>
|
||||||
|
@for (option of moduleIds(); track option) {
|
||||||
|
<option [value]="option">
|
||||||
|
{{ option }}
|
||||||
|
</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
|
@if (!formGroup.controls['input'].valid) {
|
||||||
|
<!-- TODO(jwetzell): better error displaying -->
|
||||||
|
<div class="ml-2 text-red-500">{{ formGroup.controls['input'].errors | json }}</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<div>
|
<div>
|
||||||
<form [formGroup]="formGroup" class="h-full">
|
<div class="flex items-center">
|
||||||
<div class="m-2">
|
@if (schemaService.processorTypes.length > 0) {
|
||||||
<div class="flex items-center m-1">
|
<div
|
||||||
<label class="mr-2 text-gray-300"> input: </label>
|
matTooltip="Add Processor"
|
||||||
<select
|
class="flex items-center justify-center w-10 h-10 bg-transparent hover:bg-gray-700 hover:cursor-pointer text-blue-400"
|
||||||
class="pl-1 border-2 border-gray-200 text-gray-200 border-solid rounded-sm w-full"
|
[matMenuTriggerFor]="addProcessorMenu"
|
||||||
formControlName="input"
|
>
|
||||||
>
|
<mat-icon>add</mat-icon>
|
||||||
@for (option of moduleIds(); track option) {
|
|
||||||
<option [value]="option">
|
|
||||||
{{ option }}
|
|
||||||
</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
@if (!formGroup.controls['input'].valid) {
|
|
||||||
<!-- TODO(jwetzell): better error displaying -->
|
|
||||||
<div class="ml-2 text-red-500">{{ formGroup.controls['input'].errors | json }}</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<mat-menu #addProcessorMenu="matMenu">
|
||||||
</form>
|
@for (processorType of schemaService.processorTypes; track processorType) {
|
||||||
<div>
|
<button mat-menu-item (click)="addProcessor(processorType.type)">
|
||||||
<div class="text-md text-gray-300 text-center">Processors</div>
|
<span>{{ processorType.name }}</span>
|
||||||
<div class="border-2 border-gray-500 m-2 rounded-sm">
|
</button>
|
||||||
@if (processors() === undefined || processors()?.length === 0) {
|
|
||||||
<div class="w-full h-6"></div>
|
|
||||||
} @else {
|
|
||||||
@for (processor of processors(); track processor; let i = $index) {
|
|
||||||
<div cdkDrag>
|
|
||||||
<app-processor
|
|
||||||
[path]="path() + '/processors/' + i"
|
|
||||||
(processorChange)="processorUpdated(i, $event)"
|
|
||||||
[processor]="processor"
|
|
||||||
(delete)="deleteProcessor(i)"
|
|
||||||
></app-processor>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
}
|
</mat-menu>
|
||||||
</div>
|
}
|
||||||
|
<div class="text-md text-white text-center">Processors</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
@if (processors() !== undefined && processors()!.length > 0) {
|
||||||
<div class="flex mb-2">
|
<div class="border-2 border-gray-500 m-2">
|
||||||
@if (schemaService.moduleTypes.length > 0) {
|
@for (processor of processors(); track processor; let i = $index) {
|
||||||
<div
|
<div cdkDrag>
|
||||||
matTooltip="Add Module"
|
<app-processor
|
||||||
class="flex items-center justify-center w-full h-10 rounded-lg bg-gray-200 hover:cursor-pointer hover:bg-gray-300 m-2"
|
[path]="path() + '/processors/' + i"
|
||||||
[matMenuTriggerFor]="addProcessorMenu"
|
(processorChange)="processorUpdated(i, $event)"
|
||||||
>
|
[processor]="processor"
|
||||||
<mat-icon>add</mat-icon>
|
(delete)="deleteProcessor(i)"
|
||||||
</div>
|
></app-processor>
|
||||||
<mat-menu #addProcessorMenu="matMenu">
|
</div>
|
||||||
@for (processorType of schemaService.processorTypes; track processorType) {
|
|
||||||
<button mat-menu-item (click)="addProcessor(processorType.type)">
|
|
||||||
<span>{{ processorType.type }}</span>
|
|
||||||
</button>
|
|
||||||
}
|
}
|
||||||
</mat-menu>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- </div> -->
|
||||||
|
|
||||||
<ng-template #addProcessorMenu>
|
<ng-template #addProcessorMenu>
|
||||||
@if (schemaService.processorTypes.length > 0) {
|
@if (schemaService.processorTypes.length > 0) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { SchemaService } from '../../services/schema.service';
|
|||||||
import { JsonPipe } from '@angular/common';
|
import { JsonPipe } from '@angular/common';
|
||||||
import { ProcessorComponent } from '../processor/processor.component';
|
import { ProcessorComponent } from '../processor/processor.component';
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-route',
|
selector: 'app-route',
|
||||||
@@ -18,12 +19,24 @@ import { MatSnackBar } from '@angular/material/snack-bar';
|
|||||||
MatMenuModule,
|
MatMenuModule,
|
||||||
JsonPipe,
|
JsonPipe,
|
||||||
ProcessorComponent,
|
ProcessorComponent,
|
||||||
|
MatTooltipModule,
|
||||||
],
|
],
|
||||||
templateUrl: './route.component.html',
|
templateUrl: './route.component.html',
|
||||||
styleUrl: './route.component.css',
|
styleUrl: './route.component.css',
|
||||||
})
|
})
|
||||||
export class RouteComponent {
|
export class RouteComponent {
|
||||||
path = input<string>('');
|
path = input<string>('');
|
||||||
|
|
||||||
|
index = computed(() => {
|
||||||
|
const path = this.path();
|
||||||
|
if (path) {
|
||||||
|
const parts = path.split('/');
|
||||||
|
const lastPart = parts[parts.length - 1];
|
||||||
|
return parseInt(lastPart, 10);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
|
||||||
route = model<RouteConfiguration>();
|
route = model<RouteConfiguration>();
|
||||||
moduleIds = input<string[]>([]);
|
moduleIds = input<string[]>([]);
|
||||||
delete = output<void>();
|
delete = output<void>();
|
||||||
@@ -85,6 +98,9 @@ export class RouteComponent {
|
|||||||
}
|
}
|
||||||
return route;
|
return route;
|
||||||
});
|
});
|
||||||
|
this.snackBar.open('Processor Added', 'Dismiss', {
|
||||||
|
duration: 3000,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
processorUpdated(index: number, processor: ProcessorConfiguration | undefined) {
|
processorUpdated(index: number, processor: ProcessorConfiguration | undefined) {
|
||||||
|
|||||||
@@ -225,12 +225,12 @@ export class SchemaService {
|
|||||||
.filter((definition) => definition.properties?.type?.const !== undefined)
|
.filter((definition) => definition.properties?.type?.const !== undefined)
|
||||||
.map((definition) => {
|
.map((definition) => {
|
||||||
return {
|
return {
|
||||||
name: definition['title'],
|
name: definition['title'] || definition.properties?.type?.const,
|
||||||
type: definition.properties?.type?.const,
|
type: definition.properties?.type?.const,
|
||||||
schema: definition,
|
schema: definition,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
['name'],
|
['type'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,12 +247,12 @@ export class SchemaService {
|
|||||||
.filter((definition) => definition.properties?.type?.const !== undefined)
|
.filter((definition) => definition.properties?.type?.const !== undefined)
|
||||||
.map((definition) => {
|
.map((definition) => {
|
||||||
return {
|
return {
|
||||||
name: definition['title'],
|
name: definition['title'] || definition.properties?.type?.const,
|
||||||
type: definition.properties?.type?.const,
|
type: definition.properties?.type?.const,
|
||||||
schema: definition,
|
schema: definition,
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
['name'],
|
['type'],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user