add basic support for adding processors to routes

This commit is contained in:
Joel Wetzell
2026-02-13 20:35:29 -06:00
parent 7a3b447ed3
commit 6cc183436c
6 changed files with 216 additions and 4 deletions
@@ -0,0 +1,27 @@
@if (processor() && schema()) {
<div class="flex items-start m-2 w-fit">
<div
class="flex flex-col bg-gray-800 border-2 {{
isInError() ? 'border-red-500' : 'border-gray-200'
}} border-solid w-fit h-full"
>
<div class="flex items-center justify-center bg-gray-600">
<div class="flex-grow ml-1 mr-3 text-gray-200">
{{ processor()?.type }}
</div>
<div class="flex items-center justify-center" (click)="delete.emit()">
<mat-icon class="!text-red-500">close</mat-icon>
</div>
</div>
@if (hasParams()) {
<div>
<app-params-form
[paramsSchema]="schema()?.properties?.params"
[data]="params()"
(updated)="paramsUpdated($event)"
></app-params-form>
</div>
}
</div>
</div>
}
+61
View File
@@ -0,0 +1,61 @@
import { Component, computed, inject, input, model, output, signal } from '@angular/core';
import { ProcessorConfiguration } from '../../models/config.models';
import { SchemaService } from '../../services/schema.service';
import { MatIconModule } from '@angular/material/icon';
import { ParamsFormComponent } from '../params-form/params-form.component';
import { ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-processor',
imports: [MatIconModule, ParamsFormComponent, ReactiveFormsModule],
templateUrl: './processor.component.html',
styleUrl: './processor.component.css',
})
export class ProcessorComponent {
path = input<string>('');
processor = model<ProcessorConfiguration>();
delete = output<void>();
params = computed(() => this.processor()!.params);
schema = computed(() => {
return this.processor()?.type
? this.schemaService.getSchemaForProcessorType(this.processor()!.type)
: undefined;
});
hasParams = computed(() => {
const schema = this.schema();
return (
schema !== undefined &&
schema.properties !== undefined &&
schema.properties.params !== undefined
);
});
private schemaService = inject(SchemaService);
paramsUpdated(params: any) {
this.processor.update((processor) => {
if (processor !== undefined) {
processor.params = params;
return {
...processor,
params: processor.params,
};
}
return undefined;
});
}
deleteMe() {
this.delete.emit();
}
isInError(): boolean {
const path = this.path();
if (path) {
return this.schemaService.errorPaths.includes(path);
}
return false;
}
}
+8
View File
@@ -0,0 +1,8 @@
input::placeholder {
color: #d2d2d2;
opacity: 0.5;
}
select {
background-color: #424242;
}
+49
View File
@@ -51,7 +51,56 @@
</div>
</div>
</form>
<div>
<div class="text-md text-gray-300 text-center">Processors</div>
<div class="border-2 border-gray-500 m-2 rounded-sm">
@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>
}
}
</div>
</div>
</div>
<div class="flex mb-2">
@if (schemaService.moduleTypes.length > 0) {
<div
matTooltip="Add Module"
class="flex items-center justify-center w-full h-10 rounded-lg bg-gray-200 hover:cursor-pointer hover:bg-gray-300 m-2"
[matMenuTriggerFor]="addProcessorMenu"
>
<mat-icon>add</mat-icon>
</div>
<mat-menu #addProcessorMenu="matMenu">
@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>
<ng-template #addProcessorMenu>
@if (schemaService.processorTypes.length > 0) {
<div cdkMenu class="context-menu">
@for (processorType of schemaService.processorTypes; track processorType) {
<button cdkMenuItem class="context-menu-item" (click)="addProcessor(processorType.type)">
<span>{{ processorType.name }}</span>
</button>
}
</div>
}
</ng-template>
}
+71 -4
View File
@@ -1,15 +1,24 @@
import { Component, inject, input, model, output } from '@angular/core';
import { Component, computed, inject, input, model, output } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { RouteConfiguration } from '../../models/config.models';
import { ProcessorConfiguration, RouteConfiguration } from '../../models/config.models';
import { SchemaService } from '../../services/schema.service';
import { JsonPipe } from '@angular/common';
import { ProcessorComponent } from '../processor/processor.component';
import { MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-route',
imports: [MatFormFieldModule, MatIconModule, ReactiveFormsModule, MatMenuModule, JsonPipe],
imports: [
MatFormFieldModule,
MatIconModule,
ReactiveFormsModule,
MatMenuModule,
JsonPipe,
ProcessorComponent,
],
templateUrl: './route.component.html',
styleUrl: './route.component.css',
})
@@ -19,12 +28,21 @@ export class RouteComponent {
moduleIds = input<string[]>([]);
delete = output<void>();
processors = computed(() => {
const route = this.route();
if (route) {
return route.processors;
}
return [];
});
formGroup: FormGroup = new FormGroup({
input: new FormControl('', [Validators.required]),
output: new FormControl('', [Validators.required]),
});
private schemaService = inject(SchemaService);
public schemaService = inject(SchemaService);
private snackBar = inject(MatSnackBar);
ngOnInit(): void {
this.formGroup.patchValue({
@@ -55,4 +73,53 @@ export class RouteComponent {
}
return false;
}
addProcessor(processorType: string) {
const processorTemplate = this.schemaService.getSkeletonForProcessor(processorType);
this.route.update((route) => {
if (route) {
if (!route.processors) {
route.processors = [];
}
route.processors?.push(processorTemplate);
return {
...route,
processors: route.processors,
};
}
return route;
});
}
processorUpdated(index: number, processor: ProcessorConfiguration | undefined) {
if (processor === undefined) {
console.error('processor is undefined, not updating');
return;
}
this.route.update((route) => {
if (route && route.processors) {
return {
...route,
processors: route.processors,
};
}
return route;
});
}
deleteProcessor(index: number) {
this.route.update((route) => {
if (route && route.processors) {
route?.processors?.splice(index, 1);
return {
...route,
processors: route.processors,
};
}
return route;
});
this.snackBar.open('Processor Removed', 'Dismiss', {
duration: 3000,
});
}
}