mirror of
https://github.com/jwetzell/showbridge-webui.git
synced 2026-09-03 20:38:58 +00:00
allow processors to be moved across routes
This commit is contained in:
+1
-1
@@ -57,7 +57,7 @@
|
|||||||
<app-route-list
|
<app-route-list
|
||||||
[routes]="config()?.routes"
|
[routes]="config()?.routes"
|
||||||
[moduleIds]="moduleIds()"
|
[moduleIds]="moduleIds()"
|
||||||
(routesChange)="routesUpdated($event)"
|
(updated)="routesUpdated($event)"
|
||||||
></app-route-list>
|
></app-route-list>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-1/2 overflow-y-hidden">
|
<div class="w-1/2 overflow-y-hidden">
|
||||||
|
|||||||
@@ -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, model, output } from '@angular/core';
|
import { Component, computed, inject, input, output } 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';
|
||||||
@@ -21,7 +21,7 @@ import { ParamsFormComponent } from '../params-form/params-form';
|
|||||||
})
|
})
|
||||||
export class ProcessorComponent {
|
export class ProcessorComponent {
|
||||||
path = input<string>('');
|
path = input<string>('');
|
||||||
processor = model<ProcessorConfig>();
|
processor = input<ProcessorConfig>();
|
||||||
delete = output<void>();
|
delete = output<void>();
|
||||||
|
|
||||||
inDragList = input<boolean>(false);
|
inDragList = input<boolean>(false);
|
||||||
@@ -34,6 +34,8 @@ export class ProcessorComponent {
|
|||||||
: undefined;
|
: undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
updated = output<ProcessorConfig>();
|
||||||
|
|
||||||
hasParams = computed(() => {
|
hasParams = computed(() => {
|
||||||
const schema = this.schema();
|
const schema = this.schema();
|
||||||
return (
|
return (
|
||||||
@@ -45,20 +47,20 @@ export class ProcessorComponent {
|
|||||||
private schemaService = inject(SchemaService);
|
private schemaService = inject(SchemaService);
|
||||||
|
|
||||||
paramsUpdated(params: any) {
|
paramsUpdated(params: any) {
|
||||||
this.processor.update((processor) => {
|
console.log('Params updated:', params);
|
||||||
if (processor !== undefined) {
|
const currentProcessor = this.processor();
|
||||||
if (params !== undefined) {
|
if (currentProcessor !== undefined) {
|
||||||
return {
|
if (params !== undefined) {
|
||||||
...processor,
|
this.updated.emit({
|
||||||
params: params,
|
...currentProcessor,
|
||||||
};
|
params: params,
|
||||||
}
|
});
|
||||||
return {
|
} else {
|
||||||
...processor,
|
this.updated.emit({
|
||||||
};
|
...currentProcessor,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return undefined;
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteMe() {
|
deleteMe() {
|
||||||
|
|||||||
@@ -14,10 +14,11 @@
|
|||||||
<div class="m-2">
|
<div class="m-2">
|
||||||
<app-route
|
<app-route
|
||||||
[path]="`routes/${i}`"
|
[path]="`routes/${i}`"
|
||||||
(routeChange)="routeUpdated(i, $event)"
|
(updated)="routeUpdated(i, $event)"
|
||||||
[route]="route"
|
[route]="route"
|
||||||
[moduleIds]="moduleIds() || []"
|
[moduleIds]="moduleIds() || []"
|
||||||
(delete)="deleteRoute(i)"
|
(delete)="deleteRoute(i)"
|
||||||
|
(moveProcessor)="moveProcessorBetweenRoutes($event)"
|
||||||
></app-route>
|
></app-route>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import { Component, inject, input, model } from '@angular/core';
|
import { transferArrayItem } from '@angular/cdk/drag-drop';
|
||||||
|
import { Component, inject, input, output } 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';
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
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 { RouteConfig } from '../../models/config';
|
import { RouteConfig } from '../../models/config';
|
||||||
import { SchemaService } from '../../services/schema';
|
import { SchemaService } from '../../services/schema';
|
||||||
import { RouteComponent } from '../route/route';
|
import { RouteComponent } from '../route/route';
|
||||||
@@ -15,20 +17,21 @@ import { RouteComponent } from '../route/route';
|
|||||||
styleUrl: './route-list.css',
|
styleUrl: './route-list.css',
|
||||||
})
|
})
|
||||||
export class RouteListComponent {
|
export class RouteListComponent {
|
||||||
routes = model<RouteConfig[]>();
|
routes = input<RouteConfig[]>();
|
||||||
moduleIds = input<string[]>();
|
moduleIds = input<string[]>();
|
||||||
|
updated = output<RouteConfig[]>();
|
||||||
public schemaService = inject(SchemaService);
|
public schemaService = inject(SchemaService);
|
||||||
|
|
||||||
private snackBar = inject(MatSnackBar);
|
private snackBar = inject(MatSnackBar);
|
||||||
|
|
||||||
deleteRoute(index: number) {
|
deleteRoute(index: number) {
|
||||||
this.routes.update((routes) => {
|
const currentRoutes = this.routes();
|
||||||
if (routes) {
|
if (currentRoutes === undefined) {
|
||||||
routes?.splice(index, 1);
|
console.error('routes is undefined, cannot delete');
|
||||||
return [...routes];
|
return;
|
||||||
}
|
}
|
||||||
return routes;
|
currentRoutes.splice(index, 1);
|
||||||
});
|
this.updated.emit(cloneDeep(currentRoutes));
|
||||||
this.snackBar.open('Route Removed', 'Dismiss', {
|
this.snackBar.open('Route Removed', 'Dismiss', {
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
});
|
});
|
||||||
@@ -39,29 +42,65 @@ export class RouteListComponent {
|
|||||||
console.error('route is undefined, not updating');
|
console.error('route is undefined, not updating');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.routes.update((routes) => {
|
const currentRoutes = this.routes();
|
||||||
if (routes) {
|
if (currentRoutes === undefined) {
|
||||||
routes[index].input = route.input;
|
console.error('routes is undefined, cannot update');
|
||||||
if (route.processors) {
|
return;
|
||||||
routes[index].processors = [...route.processors];
|
}
|
||||||
}
|
currentRoutes[index] = cloneDeep(route);
|
||||||
return [...routes];
|
this.updated.emit(cloneDeep(currentRoutes));
|
||||||
}
|
|
||||||
return routes;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addRoute() {
|
addRoute() {
|
||||||
const routeTemplate = this.schemaService.getSkeletonForRoute();
|
const routeTemplate = this.schemaService.getSkeletonForRoute();
|
||||||
this.routes.update((routes) => {
|
const currentRoutes = this.routes() || [];
|
||||||
if (!routes) {
|
if (currentRoutes === undefined) {
|
||||||
routes = [];
|
console.error('routes is undefined, cannot update');
|
||||||
}
|
return;
|
||||||
routes?.push(routeTemplate);
|
}
|
||||||
return [...routes];
|
currentRoutes.push(routeTemplate);
|
||||||
});
|
this.updated.emit(cloneDeep(currentRoutes));
|
||||||
this.snackBar.open('Route Added', 'Dismiss', {
|
this.snackBar.open('Route Added', 'Dismiss', {
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
moveProcessorBetweenRoutes(event: {
|
||||||
|
fromRouteIndex: number;
|
||||||
|
toRouteIndex: number;
|
||||||
|
fromProcessorIndex: number;
|
||||||
|
toProcessorIndex: number;
|
||||||
|
}) {
|
||||||
|
if (event.fromRouteIndex === event.toRouteIndex) {
|
||||||
|
console.error(
|
||||||
|
'this should be handled by the route component, not moving processor between routes',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const routes = this.routes();
|
||||||
|
if (routes === undefined) {
|
||||||
|
console.error('routes is undefined, cannot move processor');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fromRoute = routes[event.fromRouteIndex];
|
||||||
|
const toRoute = routes[event.toRouteIndex];
|
||||||
|
if (fromRoute === undefined || toRoute === undefined) {
|
||||||
|
console.error('fromRoute or toRoute is undefined, cannot move processor');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const fromProcessors = fromRoute.processors;
|
||||||
|
const toProcessors = toRoute.processors;
|
||||||
|
if (fromProcessors === undefined || toProcessors === undefined) {
|
||||||
|
console.error('fromProcessors or toProcessors is undefined, cannot move processor');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
transferArrayItem(
|
||||||
|
fromProcessors,
|
||||||
|
toProcessors,
|
||||||
|
event.fromProcessorIndex,
|
||||||
|
event.toProcessorIndex,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.updated.emit(cloneDeep(routes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,6 +66,8 @@
|
|||||||
<div
|
<div
|
||||||
class="border-2 border-gray-500 m-2"
|
class="border-2 border-gray-500 m-2"
|
||||||
cdkDropList
|
cdkDropList
|
||||||
|
[id]="listsService.registerProcessorList(path() + '/processors')"
|
||||||
|
[cdkDropListConnectedTo]="listsService.processorListIds"
|
||||||
(cdkDropListDropped)="drop($event)"
|
(cdkDropListDropped)="drop($event)"
|
||||||
[cdkDropListData]="route()?.processors"
|
[cdkDropListData]="route()?.processors"
|
||||||
>
|
>
|
||||||
@@ -73,7 +75,7 @@
|
|||||||
<div cdkDrag>
|
<div cdkDrag>
|
||||||
<app-processor
|
<app-processor
|
||||||
[path]="path() + '/processors/' + i"
|
[path]="path() + '/processors/' + i"
|
||||||
(processorChange)="processorUpdated(i, $event)"
|
(updated)="processorUpdated(i, $event)"
|
||||||
[processor]="processor"
|
[processor]="processor"
|
||||||
(delete)="deleteProcessor(i)"
|
(delete)="deleteProcessor(i)"
|
||||||
[inDragList]="true"
|
[inDragList]="true"
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
import { CdkDrag, CdkDragDrop, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
import { JsonPipe } from '@angular/common';
|
import { JsonPipe } from '@angular/common';
|
||||||
import { Component, computed, inject, input, model, output, signal } from '@angular/core';
|
import { Component, computed, inject, input, output, signal } 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';
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
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 { debounceTime, tap } from 'rxjs';
|
import { debounceTime, tap } from 'rxjs';
|
||||||
import { ProcessorConfig, RouteConfig } from '../../models/config';
|
import { ProcessorConfig, RouteConfig } from '../../models/config';
|
||||||
import { ConfigService } from '../../services/config';
|
import { ConfigService } from '../../services/config';
|
||||||
@@ -44,9 +45,16 @@ export class RouteComponent {
|
|||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
route = model<RouteConfig>();
|
route = input<RouteConfig>();
|
||||||
moduleIds = input<string[]>([]);
|
moduleIds = input<string[]>([]);
|
||||||
delete = output<void>();
|
delete = output<void>();
|
||||||
|
updated = output<RouteConfig>();
|
||||||
|
moveProcessor = output<{
|
||||||
|
fromRouteIndex: number;
|
||||||
|
toRouteIndex: number;
|
||||||
|
fromProcessorIndex: number;
|
||||||
|
toProcessorIndex: number;
|
||||||
|
}>();
|
||||||
|
|
||||||
processors = computed(() => {
|
processors = computed(() => {
|
||||||
const route = this.route();
|
const route = this.route();
|
||||||
@@ -83,15 +91,14 @@ export class RouteComponent {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.formGroup.valueChanges.subscribe((value) => {
|
this.formGroup.valueChanges.subscribe((value) => {
|
||||||
this.route.update((route) => {
|
const currentRoute = this.route();
|
||||||
if (route) {
|
if (currentRoute === undefined) {
|
||||||
route.input = value.input;
|
console.error('route is undefined, not updating');
|
||||||
return {
|
return;
|
||||||
...route,
|
}
|
||||||
input: route.input,
|
this.updated.emit({
|
||||||
};
|
...currentRoute,
|
||||||
}
|
input: value.input,
|
||||||
return undefined;
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -120,18 +127,18 @@ export class RouteComponent {
|
|||||||
|
|
||||||
addProcessor(processorType: string) {
|
addProcessor(processorType: string) {
|
||||||
const processorTemplate = this.schemaService.getSkeletonForProcessor(processorType);
|
const processorTemplate = this.schemaService.getSkeletonForProcessor(processorType);
|
||||||
this.route.update((route) => {
|
const currentRoute = this.route();
|
||||||
if (route) {
|
if (currentRoute === undefined) {
|
||||||
const processors = route.processors || [];
|
console.error('route is undefined, not updating');
|
||||||
|
return;
|
||||||
processors.push(processorTemplate);
|
}
|
||||||
return {
|
const processors = currentRoute.processors || [];
|
||||||
...route,
|
processors.push(processorTemplate);
|
||||||
processors: [...processors],
|
this.updated.emit({
|
||||||
};
|
...currentRoute,
|
||||||
}
|
processors: cloneDeep(processors),
|
||||||
return route;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.snackBar.open('Processor Added', 'Dismiss', {
|
this.snackBar.open('Processor Added', 'Dismiss', {
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
});
|
});
|
||||||
@@ -142,53 +149,75 @@ export class RouteComponent {
|
|||||||
console.error('processor is undefined, not updating');
|
console.error('processor is undefined, not updating');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.route.update((route) => {
|
const currentRoute = this.route();
|
||||||
if (route && route.processors) {
|
if (currentRoute === undefined) {
|
||||||
route.processors[index].type = processor.type;
|
console.error('route is undefined, not updating');
|
||||||
if (processor.params !== undefined) {
|
return;
|
||||||
route.processors[index].params = processor.params;
|
}
|
||||||
}
|
if (currentRoute.processors === undefined) {
|
||||||
return {
|
console.error('route processors is undefined, not updating');
|
||||||
...route,
|
return;
|
||||||
processors: [...route.processors],
|
}
|
||||||
};
|
currentRoute.processors[index].type = processor.type;
|
||||||
}
|
if (processor.params !== undefined) {
|
||||||
return route;
|
currentRoute.processors[index].params = processor.params;
|
||||||
|
}
|
||||||
|
this.updated.emit({
|
||||||
|
...currentRoute,
|
||||||
|
processors: cloneDeep(currentRoute.processors),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
deleteProcessor(index: number) {
|
deleteProcessor(index: number) {
|
||||||
this.route.update((route) => {
|
const currentRoute = this.route();
|
||||||
if (route && route.processors) {
|
if (currentRoute === undefined) {
|
||||||
route?.processors?.splice(index, 1);
|
console.error('route is undefined, not updating');
|
||||||
return {
|
return;
|
||||||
...route,
|
}
|
||||||
processors: [...route.processors],
|
if (currentRoute.processors === undefined) {
|
||||||
};
|
console.error('route processors is undefined, not updating');
|
||||||
}
|
return;
|
||||||
return route;
|
}
|
||||||
|
currentRoute.processors.splice(index, 1);
|
||||||
|
|
||||||
|
this.updated.emit({
|
||||||
|
...currentRoute,
|
||||||
|
processors: cloneDeep(currentRoute.processors),
|
||||||
});
|
});
|
||||||
|
|
||||||
this.snackBar.open('Processor Removed', 'Dismiss', {
|
this.snackBar.open('Processor Removed', 'Dismiss', {
|
||||||
duration: 3000,
|
duration: 3000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(event: CdkDragDrop<ProcessorConfig[] | undefined>) {
|
drop(event: CdkDragDrop<ProcessorConfig[] | undefined>) {
|
||||||
// TODO(jwetzell): support moving between routes
|
|
||||||
if (event.previousContainer === event.container) {
|
if (event.previousContainer === event.container) {
|
||||||
const processors = this.route()?.processors;
|
const currentRoute = this.route();
|
||||||
if (processors !== undefined) {
|
if (currentRoute === undefined) {
|
||||||
moveItemInArray(processors, event.previousIndex, event.currentIndex);
|
console.error('route is undefined, not updating');
|
||||||
this.route.update((route) => {
|
return;
|
||||||
if (route) {
|
|
||||||
return {
|
|
||||||
...route,
|
|
||||||
processors: [...processors],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return route;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
const processors = currentRoute.processors;
|
||||||
|
if (processors === undefined) {
|
||||||
|
console.error('route processors is undefined, cannot move processor');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
moveItemInArray(processors, event.previousIndex, event.currentIndex);
|
||||||
|
this.updated.emit({
|
||||||
|
...currentRoute,
|
||||||
|
processors: cloneDeep(processors),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const fromRouteIndex = parseInt(event.previousContainer.id.split('.')[1], 10);
|
||||||
|
const toRouteIndex = parseInt(event.container.id.split('.')[1], 10);
|
||||||
|
const fromProcessorIndex = event.previousIndex;
|
||||||
|
const toProcessorIndex = event.currentIndex;
|
||||||
|
this.moveProcessor.emit({
|
||||||
|
fromRouteIndex,
|
||||||
|
toRouteIndex,
|
||||||
|
fromProcessorIndex,
|
||||||
|
toProcessorIndex,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user