From 13b8094df71223d2a81fcd50344457d48979e877 Mon Sep 17 00:00:00 2001 From: Eugene Molodkin Date: Wed, 24 Jul 2024 16:39:43 +0200 Subject: [PATCH 1/4] wip: Add info boxes to AI subcategories --- .../Node/NodeCreator/Modes/NodesMode.vue | 2 ++ .../NodeCreator/composables/useViewStacks.ts | 1 + .../components/Node/NodeCreator/viewsData.ts | 21 +++++++++++++++++++ .../src/plugins/i18n/locales/en.json | 3 +++ 4 files changed, 27 insertions(+) diff --git a/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue b/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue index 94d611b4c8d48..e2f4839a2f336 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue +++ b/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue @@ -56,10 +56,12 @@ function onSelected(item: INodeCreateElement) { if (item.type === 'subcategory') { const subcategoryKey = camelCase(item.properties.title); const title = i18n.baseText(`nodeCreator.subcategoryNames.${subcategoryKey}` as BaseTextKey); + const info = i18n.baseText(`nodeCreator.subcategoryInfos.${subcategoryKey}` as BaseTextKey); pushViewStack({ subcategory: item.key, title, + info, mode: 'nodes', ...(item.properties.icon ? { diff --git a/packages/editor-ui/src/components/Node/NodeCreator/composables/useViewStacks.ts b/packages/editor-ui/src/components/Node/NodeCreator/composables/useViewStacks.ts index b67869204d39a..a237d26164b41 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/composables/useViewStacks.ts +++ b/packages/editor-ui/src/components/Node/NodeCreator/composables/useViewStacks.ts @@ -300,6 +300,7 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => { await nextTick(); pushViewStack({ title: relatedAIView?.properties.title, + info: relatedAIView?.properties.info, rootView: AI_OTHERS_NODE_CREATOR_VIEW, mode: 'nodes', items: nodeCreatorStore.allNodeCreatorNodes, diff --git a/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts b/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts index 53ceb525b51ff..6ba5b3c1a2ef7 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts +++ b/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts @@ -61,6 +61,8 @@ import type { SimplifiedNodeType } from '@/Interface'; import type { INodeTypeDescription, Themed } from 'n8n-workflow'; import { NodeConnectionType } from 'n8n-workflow'; import { useTemplatesStore } from '@/stores/templates.store'; +import type { BaseTextKey } from '@/plugins/i18n'; +import { camelCase } from 'lodash-es'; export interface NodeViewItemSection { key: string; @@ -78,6 +80,7 @@ export interface NodeViewItem { iconProps?: { color?: string; }; + info?: string; url?: string; connectionType?: NodeConnectionType; panelClass?: string; @@ -185,6 +188,15 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { }; } + function getSubcategoryInfo(subcategory: string) { + const localeKey = `nodeCreator.aiPanel.${camelCase(subcategory)}` as BaseTextKey; + if (i18n.exists(localeKey)) { + return i18n.baseText(localeKey); + } + + return undefined; + } + return { value: AI_OTHERS_NODE_CREATOR_VIEW, title: i18n.baseText('nodeCreator.aiPanel.aiOtherNodes'), @@ -195,6 +207,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { type: 'subcategory', properties: { title: AI_CATEGORY_DOCUMENT_LOADERS, + info: getSubcategoryInfo(AI_CATEGORY_DOCUMENT_LOADERS), icon: 'file-import', ...getAISubcategoryProperties(NodeConnectionType.AiDocument), }, @@ -204,6 +217,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { type: 'subcategory', properties: { title: AI_CATEGORY_LANGUAGE_MODELS, + info: getSubcategoryInfo(AI_CATEGORY_LANGUAGE_MODELS), icon: 'language', ...getAISubcategoryProperties(NodeConnectionType.AiLanguageModel), }, @@ -213,6 +227,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { type: 'subcategory', properties: { title: AI_CATEGORY_MEMORY, + info: getSubcategoryInfo(AI_CATEGORY_MEMORY), icon: 'brain', ...getAISubcategoryProperties(NodeConnectionType.AiMemory), }, @@ -222,6 +237,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { type: 'subcategory', properties: { title: AI_CATEGORY_OUTPUTPARSER, + info: getSubcategoryInfo(AI_CATEGORY_OUTPUTPARSER), icon: 'list', ...getAISubcategoryProperties(NodeConnectionType.AiOutputParser), }, @@ -231,6 +247,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { type: 'subcategory', properties: { title: AI_CATEGORY_RETRIEVERS, + info: getSubcategoryInfo(AI_CATEGORY_RETRIEVERS), icon: 'search', ...getAISubcategoryProperties(NodeConnectionType.AiRetriever), }, @@ -240,6 +257,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { type: 'subcategory', properties: { title: AI_CATEGORY_TEXT_SPLITTERS, + info: getSubcategoryInfo(AI_CATEGORY_TEXT_SPLITTERS), icon: 'grip-lines-vertical', ...getAISubcategoryProperties(NodeConnectionType.AiTextSplitter), }, @@ -250,6 +268,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { category: CORE_NODES_CATEGORY, properties: { title: AI_CATEGORY_TOOLS, + info: getSubcategoryInfo(AI_CATEGORY_TOOLS), icon: 'tools', ...getAISubcategoryProperties(NodeConnectionType.AiTool), sections: [ @@ -266,6 +285,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { type: 'subcategory', properties: { title: AI_CATEGORY_EMBEDDING, + info: getSubcategoryInfo(AI_CATEGORY_EMBEDDING), icon: 'vector-square', ...getAISubcategoryProperties(NodeConnectionType.AiEmbedding), }, @@ -275,6 +295,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { type: 'subcategory', properties: { title: AI_CATEGORY_VECTOR_STORES, + info: getSubcategoryInfo(AI_CATEGORY_VECTOR_STORES), icon: 'project-diagram', ...getAISubcategoryProperties(NodeConnectionType.AiVectorStore), }, diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index 56af9fcade8cf..7864946921152 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -1018,6 +1018,9 @@ "nodeCreator.subcategoryDescriptions.tools": "Utility components providing various functionalities.", "nodeCreator.subcategoryDescriptions.vectorStores": "Handles storage and retrieval of vector representations.", "nodeCreator.subcategoryDescriptions.miscellaneous": "Other AI related nodes.", + "nodeCreator.subcategoryInfos.languageModels": "Chat models are designed for interactive conversations and follow instructions well, while text completion models focus on generating continuations of a given text input.", + "nodeCreator.subcategoryInfos.memory": "Memory allows an AI model to remember and reference past interactions with it.", + "nodeCreator.subcategoryInfos.vectorStores": "Vector stores allow an AI model to reference relevant pieces of documents, useful for question answering and document search", "nodeCreator.subcategoryNames.appTriggerNodes": "On app event", "nodeCreator.subcategoryNames.appRegularNodes": "Action in an app", "nodeCreator.subcategoryNames.dataTransformation": "Data transformation", From 8172ada1bd2ec1888cc423c46f8954c420ecd346 Mon Sep 17 00:00:00 2001 From: Eugene Molodkin Date: Thu, 25 Jul 2024 12:24:58 +0200 Subject: [PATCH 2/4] wip: fix the issue when info locale string does not exist, hide info box when node creator is opened with filter --- .../components/Node/NodeCreator/Modes/NodesMode.vue | 10 +++++++--- .../Node/NodeCreator/composables/useViewStacks.ts | 8 +++++++- .../src/components/Node/NodeCreator/viewsData.ts | 12 +++++++----- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue b/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue index e2f4839a2f336..2ffcd77fed45f 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue +++ b/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue @@ -56,13 +56,17 @@ function onSelected(item: INodeCreateElement) { if (item.type === 'subcategory') { const subcategoryKey = camelCase(item.properties.title); const title = i18n.baseText(`nodeCreator.subcategoryNames.${subcategoryKey}` as BaseTextKey); - const info = i18n.baseText(`nodeCreator.subcategoryInfos.${subcategoryKey}` as BaseTextKey); + + // If the info message exists in locale, add it to the info field of the view + const infoKey: BaseTextKey = `nodeCreator.subcategoryInfos.${subcategoryKey}`; + const info = i18n.baseText(infoKey); + const extendedInfo = info !== infoKey ? { info } : {}; pushViewStack({ subcategory: item.key, - title, - info, mode: 'nodes', + title, + ...extendedInfo, ...(item.properties.icon ? { nodeIcon: { diff --git a/packages/editor-ui/src/components/Node/NodeCreator/composables/useViewStacks.ts b/packages/editor-ui/src/components/Node/NodeCreator/composables/useViewStacks.ts index a237d26164b41..891c360e2cc13 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/composables/useViewStacks.ts +++ b/packages/editor-ui/src/components/Node/NodeCreator/composables/useViewStacks.ts @@ -297,10 +297,16 @@ export const useViewStacks = defineStore('nodeCreatorViewStacks', () => { ); } + // Only add info field if the view does not have any filters (e.g. + let extendedInfo = {}; + if (!filter?.nodes?.length && relatedAIView?.properties.info) { + extendedInfo = { info: relatedAIView?.properties.info }; + } + await nextTick(); pushViewStack({ title: relatedAIView?.properties.title, - info: relatedAIView?.properties.info, + ...extendedInfo, rootView: AI_OTHERS_NODE_CREATOR_VIEW, mode: 'nodes', items: nodeCreatorStore.allNodeCreatorNodes, diff --git a/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts b/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts index 6ba5b3c1a2ef7..814d57c757123 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts +++ b/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts @@ -189,12 +189,14 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { } function getSubcategoryInfo(subcategory: string) { - const localeKey = `nodeCreator.aiPanel.${camelCase(subcategory)}` as BaseTextKey; - if (i18n.exists(localeKey)) { - return i18n.baseText(localeKey); - } + const localeKey: BaseTextKey = `nodeCreator.subcategoryInfos.${camelCase(subcategory)}`; - return undefined; + const info = i18n.baseText(localeKey); + + // Return undefined if the locale key is not found + if (info === localeKey) return undefined; + + return info; } return { From 4e041f3f6671267736bd841afea1a211a9a4e45f Mon Sep 17 00:00:00 2001 From: Eugene Molodkin Date: Thu, 25 Jul 2024 13:07:12 +0200 Subject: [PATCH 3/4] wip: Fix type errors --- .../src/components/Node/NodeCreator/Modes/NodesMode.vue | 2 +- packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue b/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue index 2ffcd77fed45f..1f163232ed1b9 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue +++ b/packages/editor-ui/src/components/Node/NodeCreator/Modes/NodesMode.vue @@ -58,7 +58,7 @@ function onSelected(item: INodeCreateElement) { const title = i18n.baseText(`nodeCreator.subcategoryNames.${subcategoryKey}` as BaseTextKey); // If the info message exists in locale, add it to the info field of the view - const infoKey: BaseTextKey = `nodeCreator.subcategoryInfos.${subcategoryKey}`; + const infoKey = `nodeCreator.subcategoryInfos.${subcategoryKey}` as BaseTextKey; const info = i18n.baseText(infoKey); const extendedInfo = info !== infoKey ? { info } : {}; diff --git a/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts b/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts index 814d57c757123..ba9cb59c3aa05 100644 --- a/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts +++ b/packages/editor-ui/src/components/Node/NodeCreator/viewsData.ts @@ -189,7 +189,7 @@ export function AINodesView(_nodes: SimplifiedNodeType[]): NodeView { } function getSubcategoryInfo(subcategory: string) { - const localeKey: BaseTextKey = `nodeCreator.subcategoryInfos.${camelCase(subcategory)}`; + const localeKey = `nodeCreator.subcategoryInfos.${camelCase(subcategory)}` as BaseTextKey; const info = i18n.baseText(localeKey); From 70bdbbc2a353d05251e3e103f2bc98e6dc9682ec Mon Sep 17 00:00:00 2001 From: Eugene Molodkin Date: Thu, 25 Jul 2024 14:29:46 +0200 Subject: [PATCH 4/4] wip: Remove final dots --- packages/editor-ui/src/plugins/i18n/locales/en.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/editor-ui/src/plugins/i18n/locales/en.json b/packages/editor-ui/src/plugins/i18n/locales/en.json index 7864946921152..8d00e109e50ae 100644 --- a/packages/editor-ui/src/plugins/i18n/locales/en.json +++ b/packages/editor-ui/src/plugins/i18n/locales/en.json @@ -1018,8 +1018,8 @@ "nodeCreator.subcategoryDescriptions.tools": "Utility components providing various functionalities.", "nodeCreator.subcategoryDescriptions.vectorStores": "Handles storage and retrieval of vector representations.", "nodeCreator.subcategoryDescriptions.miscellaneous": "Other AI related nodes.", - "nodeCreator.subcategoryInfos.languageModels": "Chat models are designed for interactive conversations and follow instructions well, while text completion models focus on generating continuations of a given text input.", - "nodeCreator.subcategoryInfos.memory": "Memory allows an AI model to remember and reference past interactions with it.", + "nodeCreator.subcategoryInfos.languageModels": "Chat models are designed for interactive conversations and follow instructions well, while text completion models focus on generating continuations of a given text input", + "nodeCreator.subcategoryInfos.memory": "Memory allows an AI model to remember and reference past interactions with it", "nodeCreator.subcategoryInfos.vectorStores": "Vector stores allow an AI model to reference relevant pieces of documents, useful for question answering and document search", "nodeCreator.subcategoryNames.appTriggerNodes": "On app event", "nodeCreator.subcategoryNames.appRegularNodes": "Action in an app",