Skip to content

Commit 7e212ef

Browse files
committed
update sidebar taskbar when editing composition
1 parent 536a475 commit 7e212ef

File tree

2 files changed

+168
-115
lines changed

2 files changed

+168
-115
lines changed

libs/app-canvas/src/app/components/node-sidebar-menu.tsx

Lines changed: 136 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -143,112 +143,7 @@ export class NodeSidebarMenuComponent extends Component<
143143
this.apikeysButton
144144
);
145145
this.rootElement.append(this.element);
146-
let taskbar: HTMLElement | null = null;
147-
let taskbarContainer: HTMLElement | null = null;
148-
149-
const categorizedNodeTasks = new Map<
150-
string,
151-
{ label: string; nodeType: string }[]
152-
>();
153-
const nodeTasks = getNodeFactoryNames();
154-
nodeTasks.forEach((nodeTask) => {
155-
const factory = this.getNodeFactory(nodeTask);
156-
let categoryName = 'Default';
157-
if (factory) {
158-
const node = factory(this.props.canvasUpdated);
159-
categoryName = node.category || 'uncategorized';
160-
if (node.useInCompositionOnly) {
161-
return;
162-
}
163-
}
164-
const label = canvasNodeTaskRegistryLabels[nodeTask] || nodeTask;
165-
const category = categorizedNodeTasks.get(categoryName);
166-
if (category) {
167-
category.push({
168-
label,
169-
nodeType: nodeTask,
170-
});
171-
} else {
172-
categorizedNodeTasks.set(categoryName, [
173-
{
174-
label,
175-
nodeType: nodeTask,
176-
},
177-
]);
178-
}
179-
});
180-
// sort the categories case-insensitive
181-
const sortedCategories = Array.from(categorizedNodeTasks.keys()).sort(
182-
(a, b) => {
183-
return a.localeCompare(b);
184-
}
185-
);
186-
187-
// sort the tasks within the categories
188-
sortedCategories.forEach((categoryName) => {
189-
const category = categorizedNodeTasks.get(categoryName);
190-
if (category) {
191-
category.sort((a, b) => {
192-
return a.label.localeCompare(b.label);
193-
});
194-
}
195-
});
196-
197-
renderElement(
198-
<div
199-
class={`taskbar-container transition-transform z-[20050] hidden md:flex flex-col absolute left-0 top-[58px] max-h-[calc(100vh-108px)] bg-slate-700 p-4 rounded-l-lg overflow-y-scroll`}
200-
getElement={(element: HTMLElement) => {
201-
taskbarContainer = element;
202-
}}
203-
>
204-
<div
205-
class={`overflow-visible flex flex-col `}
206-
getElement={(element: HTMLElement) => {
207-
taskbar = element;
208-
sortedCategories.forEach((categoryName) => {
209-
const category = categorizedNodeTasks.get(categoryName);
210-
if (categoryName === 'deprecated') {
211-
return;
212-
}
213-
renderElement(
214-
<h2 class={`text-white py-2`}>{categoryName}</h2>,
215-
taskbar
216-
);
217-
218-
category?.forEach((nodeTask) => {
219-
const label =
220-
canvasNodeTaskRegistryLabels[nodeTask.nodeType] ||
221-
nodeTask.nodeType;
222-
223-
renderElement(
224-
<div
225-
class={`cursor-pointer border border-white border-solid rounded px-4 py-2 mb-2 text-white max-w-[150px] whitespace-nowrap overflow-hidden text-ellipsis`}
226-
pointerdown={(event: PointerEvent) => {
227-
this.startDragNode(
228-
event,
229-
taskbar,
230-
taskbarContainer,
231-
nodeTask.nodeType
232-
);
233-
}}
234-
title={label}
235-
>
236-
{label}
237-
</div>,
238-
taskbar
239-
);
240-
});
241-
});
242-
}}
243-
></div>
244-
</div>,
245-
this.rootElement
246-
);
247-
this.rootElement.addEventListener('pointerup', (_event) => {
248-
if (taskbarContainer) {
249-
taskbarContainer.classList.remove('-translate-x-[100%]');
250-
}
251-
});
146+
this.initNodeTaskbar();
252147
}
253148
}
254149
this.isMounted = true;
@@ -262,16 +157,147 @@ export class NodeSidebarMenuComponent extends Component<
262157
this.isMounted = false;
263158
}
264159

160+
private taskbarContainer: HTMLElement | null = null;
161+
initNodeTaskbar = (isInComposition?: boolean, compositionId?: string) => {
162+
if (!this.rootElement) {
163+
return;
164+
}
165+
let taskbar: HTMLElement | null = null;
166+
167+
if (this.taskbarContainer) {
168+
this.taskbarContainer.remove();
169+
this.taskbarContainer = null;
170+
}
171+
172+
const categorizedNodeTasks = new Map<
173+
string,
174+
{ label: string; nodeType: string }[]
175+
>();
176+
const nodeTasks = getNodeFactoryNames();
177+
nodeTasks.forEach((nodeTask) => {
178+
const factory = this.getNodeFactory(nodeTask);
179+
let categoryName = 'Default';
180+
if (factory) {
181+
const node = factory(this.props.canvasUpdated);
182+
183+
if (node.isContained) {
184+
return;
185+
}
186+
if (node.hideFromNodeTypeSelector) {
187+
if (
188+
!isInComposition ||
189+
(isInComposition && !node.useInCompositionOnly)
190+
) {
191+
return;
192+
}
193+
}
194+
if (
195+
isInComposition &&
196+
nodeTask === `composition-${compositionId}` &&
197+
compositionId
198+
) {
199+
return;
200+
}
201+
202+
categoryName = node.category || 'uncategorized';
203+
// if (node.useInCompositionOnly) {
204+
// return;
205+
// }
206+
}
207+
const label = canvasNodeTaskRegistryLabels[nodeTask] || nodeTask;
208+
const category = categorizedNodeTasks.get(categoryName);
209+
if (category) {
210+
category.push({
211+
label,
212+
nodeType: nodeTask,
213+
});
214+
} else {
215+
categorizedNodeTasks.set(categoryName, [
216+
{
217+
label,
218+
nodeType: nodeTask,
219+
},
220+
]);
221+
}
222+
});
223+
// sort the categories case-insensitive
224+
const sortedCategories = Array.from(categorizedNodeTasks.keys()).sort(
225+
(a, b) => {
226+
return a.localeCompare(b);
227+
}
228+
);
229+
230+
// sort the tasks within the categories
231+
sortedCategories.forEach((categoryName) => {
232+
const category = categorizedNodeTasks.get(categoryName);
233+
if (category) {
234+
category.sort((a, b) => {
235+
return a.label.localeCompare(b.label);
236+
});
237+
}
238+
});
239+
240+
renderElement(
241+
<div
242+
class={`taskbar-container transition-transform z-[20050] hidden md:flex flex-col absolute left-0 top-[58px] max-h-[calc(100vh-108px)] bg-slate-700 p-4 rounded-l-lg overflow-y-scroll`}
243+
getElement={(element: HTMLElement) => {
244+
this.taskbarContainer = element;
245+
}}
246+
>
247+
<div
248+
class={`overflow-visible flex flex-col `}
249+
getElement={(element: HTMLElement) => {
250+
taskbar = element;
251+
sortedCategories.forEach((categoryName) => {
252+
const category = categorizedNodeTasks.get(categoryName);
253+
if (categoryName === 'deprecated') {
254+
return;
255+
}
256+
renderElement(
257+
<h2 class={`text-white py-2`}>{categoryName}</h2>,
258+
taskbar
259+
);
260+
261+
category?.forEach((nodeTask) => {
262+
const label =
263+
canvasNodeTaskRegistryLabels[nodeTask.nodeType] ||
264+
nodeTask.nodeType;
265+
266+
renderElement(
267+
<div
268+
class={`cursor-pointer border border-white border-solid rounded px-4 py-2 mb-2 text-white max-w-[150px] whitespace-nowrap overflow-hidden text-ellipsis`}
269+
pointerdown={(event: PointerEvent) => {
270+
this.startDragNode(event, taskbar, nodeTask.nodeType);
271+
}}
272+
title={label}
273+
>
274+
{label}
275+
</div>,
276+
taskbar
277+
);
278+
});
279+
});
280+
}}
281+
></div>
282+
</div>,
283+
this.rootElement
284+
);
285+
this.rootElement.addEventListener('pointerup', (_event) => {
286+
if (this.taskbarContainer) {
287+
this.taskbarContainer.classList.remove('-translate-x-[100%]');
288+
}
289+
});
290+
};
291+
265292
startDragNode = (
266293
event: PointerEvent,
267294
taskbar: HTMLElement | null,
268-
taskbarContainer: HTMLElement | null,
269295
nodeType: string
270296
) => {
271297
const factory = this.getNodeFactory(nodeType);
272298
const canvasApp = this.props.getCanvasApp();
273299

274-
if (factory && canvasApp && taskbar && taskbarContainer) {
300+
if (factory && canvasApp && taskbar && this.taskbarContainer) {
275301
const { pointerXPos, pointerYPos, rootX, rootY } = getPointerPos(
276302
canvasApp.canvas.domElement as HTMLElement,
277303
canvasApp.rootElement,
@@ -282,7 +308,7 @@ export class NodeSidebarMenuComponent extends Component<
282308
pointerYPos - (window?.visualViewport?.offsetTop ?? 0)
283309
);
284310

285-
taskbarContainer.classList.add('-translate-x-[100%]');
311+
this.taskbarContainer.classList.add('-translate-x-[100%]');
286312
const nodeTask = factory(this.props.canvasUpdated, canvasApp.theme);
287313
const nodeInfo = undefined;
288314
const node = nodeTask.createVisualNode(
@@ -607,7 +633,7 @@ export class NodeSidebarMenuComponent extends Component<
607633
export const NodeSidebarMenuComponents = (
608634
props: AppNavComponentsProps<NodeInfo>
609635
) => {
610-
new NodeSidebarMenuComponent(null, {
636+
return new NodeSidebarMenuComponent(null, {
611637
initializeNodes: props.initializeNodes,
612638
storageProvider: props.storageProvider,
613639
clearCanvas: props.clearCanvas,

libs/app-canvas/src/app/flow-app.element.tsx

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ import {
7979
serializeCompositions,
8080
serializeElementsMap,
8181
} from './storage/serialize-canvas';
82-
import { NodeSidebarMenuComponents } from './components/node-sidebar-menu';
82+
import {
83+
NodeSidebarMenuComponent,
84+
NodeSidebarMenuComponents,
85+
} from './components/node-sidebar-menu';
8386
import { AppElement } from './app.element';
8487
import {
8588
executeCommand,
@@ -196,6 +199,7 @@ export class FlowAppElement extends AppElement<NodeInfo> {
196199
speedMeterElement: IDOMElement | undefined = undefined;
197200
selectNodeType: IDOMElement | undefined = undefined;
198201
mediaLibary: MediaLibrary | undefined = undefined;
202+
nodeSidebarMenu: NodeSidebarMenuComponent | undefined = undefined;
199203
canvasUpdated:
200204
| ((
201205
shouldClearExecutionHistory?: boolean,
@@ -895,7 +899,7 @@ export class FlowAppElement extends AppElement<NodeInfo> {
895899
);
896900

897901
if (!isReadOnly) {
898-
NodeSidebarMenuComponents({
902+
this.nodeSidebarMenu = NodeSidebarMenuComponents({
899903
clearCanvas: this.clearCanvas,
900904
getNodeFactory: getNodeTaskFactory,
901905
initializeNodes: initializeNodes,
@@ -981,7 +985,7 @@ export class FlowAppElement extends AppElement<NodeInfo> {
981985
this.isStoring = false;
982986
canvasUpdated();
983987
},
984-
}) as unknown as HTMLElement;
988+
});
985989

986990
registerCommands<NodeInfo>({
987991
rootElement: this.rootElement,
@@ -2152,12 +2156,24 @@ export class FlowAppElement extends AppElement<NodeInfo> {
21522156
connection: IConnectionNodeComponent<NodeInfo>;
21532157
}[]
21542158
) => {
2159+
//this.nodeSidebarMenu
21552160
return this.onAddComposition(
21562161
composition,
21572162
connections,
21582163
registerComposition,
21592164
getNodeTaskFactory,
2160-
setupTasksInDropdown,
2165+
(
2166+
selectNodeTypeHTMLElement: HTMLSelectElement,
2167+
isInComposition?: boolean,
2168+
compositionId?: string
2169+
) => {
2170+
setupTasksInDropdown(
2171+
selectNodeTypeHTMLElement,
2172+
isInComposition,
2173+
compositionId
2174+
);
2175+
this.nodeSidebarMenu?.initNodeTaskbar(isInComposition, compositionId);
2176+
},
21612177
this.selectNodeType?.domElement as HTMLSelectElement
21622178
);
21632179
};
@@ -2167,7 +2183,18 @@ export class FlowAppElement extends AppElement<NodeInfo> {
21672183
this.editComposition(
21682184
getNodeTaskFactory,
21692185
this.canvasUpdated,
2170-
setupTasksInDropdown,
2186+
(
2187+
selectNodeTypeHTMLElement: HTMLSelectElement,
2188+
isInComposition?: boolean,
2189+
compositionId?: string
2190+
) => {
2191+
setupTasksInDropdown(
2192+
selectNodeTypeHTMLElement,
2193+
isInComposition,
2194+
compositionId
2195+
);
2196+
this.nodeSidebarMenu?.initNodeTaskbar(isInComposition, compositionId);
2197+
},
21712198
this.selectNodeType?.domElement as HTMLSelectElement
21722199
);
21732200
}

0 commit comments

Comments
 (0)