feat(editor): Add sections to create node panel (#7831)

This PR sets the stage for the node creator to handle sections within
subcategories. No visible changes result from this PR; the next PR will
define sections and assign nodes accordingly.

Sections are configurable in
`packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts`:
```
{
	type: 'subcategory',
	key: FILES_SUBCATEGORY,
	category: CORE_NODES_CATEGORY,
	properties: {
		title: FILES_SUBCATEGORY,
		icon: 'file-alt',
		sections: [
			{
				key: 'popular',
				title: i18n.baseText('nodeCreator.sectionNames.popular'),
				items: ['n8n-nodes-base.readBinaryFiles', 'n8n-nodes-base.compression'],
			},
		],
	},
},
```

For example:
<img width="302" alt="image"
src="https://github.com/n8n-io/n8n/assets/8850410/74470c07-f4ea-4306-bd4a-8d33bd769b86">

---------

Co-authored-by: Michael Kret <michael.k@radency.com>
This commit is contained in:
Elias Meire
2023-12-04 10:02:07 +01:00
committed by GitHub
parent 485a0c73cb
commit 39fa8d21bb
12 changed files with 271 additions and 80 deletions

View File

@@ -4,10 +4,14 @@ import type {
SubcategorizedNodeTypes,
SimplifiedNodeType,
INodeCreateElement,
SectionCreateElement,
} from '@/Interface';
import { AI_SUBCATEGORY, CORE_NODES_CATEGORY, DEFAULT_SUBCATEGORY } from '@/constants';
import { v4 as uuidv4 } from 'uuid';
import { sublimeSearch } from '@/utils/sortUtils';
import { i18n } from '@/plugins/i18n';
import type { NodeViewItemSection } from './viewsData';
export function transformNodeType(
node: SimplifiedNodeType,
@@ -75,3 +79,42 @@ export function searchNodes(searchFilter: string, items: INodeCreateElement[]) {
return result;
}
export function flattenCreateElements(items: INodeCreateElement[]): INodeCreateElement[] {
return items.map((item) => (item.type === 'section' ? item.children : item)).flat();
}
export function groupItemsInSections(
items: INodeCreateElement[],
sections: NodeViewItemSection[],
): INodeCreateElement[] {
const itemsBySection = items.reduce((acc: Record<string, INodeCreateElement[]>, item) => {
const section = sections.find((s) => s.items.includes(item.key));
const key = section?.key ?? 'other';
acc[key] = [...(acc[key] ?? []), item];
return acc;
}, {});
const result: SectionCreateElement[] = sections
.map(
(section): SectionCreateElement => ({
type: 'section',
key: section.key,
title: section.title,
children: itemsBySection[section.key],
}),
)
.concat({
type: 'section',
key: 'other',
title: i18n.baseText('nodeCreator.sectionNames.other'),
children: itemsBySection.other,
})
.filter((section) => section.children);
if (result.length <= 1) {
return items;
}
return result;
}