relayout folders

This commit is contained in:
Joel Wetzell
2026-03-07 10:49:13 -06:00
parent f792ca9e85
commit 5f91889c10
32 changed files with 5 additions and 7 deletions
@@ -0,0 +1,8 @@
input::placeholder {
color: #d2d2d2;
opacity: 0.5;
}
select {
background-color: #424242;
}
@@ -0,0 +1,86 @@
@if (route()) {
<!-- <div class="flex items-start m-2 w-fit border-2 border-red-500"> -->
<div
class="flex flex-col bg-gray-800 border-2 {{
isInError() ? 'border-red-500' : 'border-gray-600'
}} border-solid w-full h-full"
>
<div class="flex items-center justify-end border-gray-600 border-b-2">
<div class="flex-grow text-left ml-2 text-white">Route {{ index() }}</div>
<div class="flex items-center justify-center hover:bg-gray-700" (click)="delete.emit()">
<mat-icon class="!text-red-500">close</mat-icon>
</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 class="flex items-center">
@if (schemaService.processorTypes.length > 0) {
<div
matTooltip="Add Processor"
class="flex items-center justify-center w-10 h-10 bg-transparent hover:bg-gray-700 hover:cursor-pointer text-blue-400"
[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.name }}</span>
</button>
}
</mat-menu>
}
<div class="text-md text-white text-center">Processors</div>
</div>
@if (processors() !== undefined && processors()!.length > 0) {
<div class="border-2 border-gray-500 m-2">
@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>
<!-- </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>
}
+141
View File
@@ -0,0 +1,141 @@
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 { 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';
import { MatTooltipModule } from '@angular/material/tooltip';
@Component({
selector: 'app-route',
imports: [
MatFormFieldModule,
MatIconModule,
ReactiveFormsModule,
MatMenuModule,
JsonPipe,
ProcessorComponent,
MatTooltipModule,
],
templateUrl: './route.component.html',
styleUrl: './route.component.css',
})
export class RouteComponent {
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>();
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]),
});
public schemaService = inject(SchemaService);
private snackBar = inject(MatSnackBar);
ngOnInit(): void {
this.formGroup.patchValue({
input: this.route()?.input,
});
this.formGroup.valueChanges.subscribe((value) => {
this.route.update((route) => {
if (route) {
route.input = value.input;
return {
...route,
input: route.input,
};
}
return undefined;
});
});
}
isInError(): boolean {
const path = this.path();
if (path) {
return this.schemaService.errorPaths.includes(path);
}
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;
});
this.snackBar.open('Processor Added', 'Dismiss', {
duration: 3000,
});
}
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) {
route.processors[index].type = processor.type;
if (processor.params !== undefined) {
route.processors[index].params = processor.params;
}
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,
});
}
}