diff --git a/packages/frontend/@n8n/design-system/package.json b/packages/frontend/@n8n/design-system/package.json
index afbcb36404f..d068042b72f 100644
--- a/packages/frontend/@n8n/design-system/package.json
+++ b/packages/frontend/@n8n/design-system/package.json
@@ -23,7 +23,7 @@
"lint:styles:fix": "stylelint \"src/**/*.{scss,sass,vue}\" --fix --cache"
},
"devDependencies": {
- "@iconify/json": "^2.2.349",
+ "@iconify/json": "^2.2.488",
"@n8n/eslint-config": "workspace:*",
"@n8n/playwright-janitor": "workspace:*",
"@n8n/stylelint-config": "workspace:*",
diff --git a/packages/frontend/@n8n/design-system/src/components/N8nIcon/Icon.stories.ts b/packages/frontend/@n8n/design-system/src/components/N8nIcon/Icon.stories.ts
index d79506c86bb..9a46bb7b9e7 100644
--- a/packages/frontend/@n8n/design-system/src/components/N8nIcon/Icon.stories.ts
+++ b/packages/frontend/@n8n/design-system/src/components/N8nIcon/Icon.stories.ts
@@ -202,6 +202,11 @@ export const AllColors: StoryFn = (args, { argTypes }) => ({
`,
});
+export const UserRoundKey = Template.bind({});
+UserRoundKey.args = {
+ icon: 'user-round-key',
+};
+
export const CommonIcons: StoryFn = (args, { argTypes }) => ({
setup: () => ({ args }),
props: Object.keys(argTypes),
@@ -258,6 +263,10 @@ export const CommonIcons: StoryFn = (args, { argTypes }) => ({
exclamation-triangle
+
+
+ user-round-key
+
`,
});
diff --git a/packages/frontend/@n8n/design-system/src/components/N8nIcon/icons.ts b/packages/frontend/@n8n/design-system/src/components/N8nIcon/icons.ts
index 169840cb64e..ae5b264871f 100644
--- a/packages/frontend/@n8n/design-system/src/components/N8nIcon/icons.ts
+++ b/packages/frontend/@n8n/design-system/src/components/N8nIcon/icons.ts
@@ -260,6 +260,7 @@ import IconLucideUserCheck from '~icons/lucide/user-check';
import IconLucideUserLock from '~icons/lucide/user-lock';
import IconLucideUserPen from '~icons/lucide/user-pen';
import IconLucideUserRound from '~icons/lucide/user-round';
+import IconLucideUserRoundKey from '~icons/lucide/user-round-key';
import IconLucideUsers from '~icons/lucide/users';
import IconLucideVariable from '~icons/lucide/variable';
import IconLucideVault from '~icons/lucide/vault';
@@ -752,6 +753,7 @@ export const updatedIconSet = {
'user-lock': IconLucideUserLock,
'user-pen': IconLucideUserPen,
'user-round': IconLucideUserRound,
+ 'user-round-key': IconLucideUserRoundKey,
users: IconLucideUsers,
vault: IconLucideVault,
video: IconLucideVideo,
diff --git a/packages/frontend/@n8n/i18n/src/locales/en.json b/packages/frontend/@n8n/i18n/src/locales/en.json
index c2aae86c497..4131af8408d 100644
--- a/packages/frontend/@n8n/i18n/src/locales/en.json
+++ b/packages/frontend/@n8n/i18n/src/locales/en.json
@@ -4347,6 +4347,7 @@
"workflows.item.readonly": "Read only",
"workflows.item.archived": "Archived",
"workflows.item.availableInMCP": "Available in MCP",
+ "workflows.privateCredential.tooltip": "Set up and run with your own credentials",
"workflows.dynamic.tooltip": "This workflow resolves credentials at runtime based on who executes it.",
"workflows.dynamic.tooltipTitle": "Private credentials",
"workflows.dependencies.tooltip.workflow": "Click to view resources referenced by this workflow",
diff --git a/packages/frontend/editor-ui/package.json b/packages/frontend/editor-ui/package.json
index 2674a0d1c4b..bc3c72a6842 100644
--- a/packages/frontend/editor-ui/package.json
+++ b/packages/frontend/editor-ui/package.json
@@ -126,7 +126,7 @@
"devDependencies": {
"@codecov/vite-plugin": "^1.9.1",
"@faker-js/faker": "^8.0.2",
- "@iconify/json": "^2.2.349",
+ "@iconify/json": "^2.2.488",
"@n8n/eslint-config": "workspace:*",
"@n8n/playwright-janitor": "workspace:*",
"@n8n/stylelint-config": "workspace:*",
diff --git a/packages/frontend/editor-ui/src/app/components/WorkflowCard.test.ts b/packages/frontend/editor-ui/src/app/components/WorkflowCard.test.ts
index 7f00b27c69e..3858d191872 100644
--- a/packages/frontend/editor-ui/src/app/components/WorkflowCard.test.ts
+++ b/packages/frontend/editor-ui/src/app/components/WorkflowCard.test.ts
@@ -1094,25 +1094,25 @@ describe('WorkflowCard', () => {
expect(queryByTestId('workflow-card-mcp-toggle')).not.toBeInTheDocument();
});
- it('should show dynamic credentials indicator when workflow has resolvable credentials', () => {
+ it('should show private credential indicator when workflow has resolvable credentials', () => {
const data = createWorkflow({
hasResolvableCredentials: true,
});
const { getByTestId } = renderComponent({ props: { data } });
- const indicator = getByTestId('workflow-card-dynamic-credentials');
+ const indicator = getByTestId('workflow-card-private-credential');
expect(indicator).toBeVisible();
});
- it('should hide dynamic credentials indicator when workflow has no resolvable credentials', () => {
+ it('should hide private credential indicator when workflow has no resolvable credentials', () => {
const data = createWorkflow({
hasResolvableCredentials: false,
});
const { queryByTestId } = renderComponent({ props: { data } });
- const indicator = queryByTestId('workflow-card-dynamic-credentials');
+ const indicator = queryByTestId('workflow-card-private-credential');
expect(indicator).toBeNull();
});
diff --git a/packages/frontend/editor-ui/src/app/components/WorkflowCard.vue b/packages/frontend/editor-ui/src/app/components/WorkflowCard.vue
index 71433c397ee..7d37c90f1c3 100644
--- a/packages/frontend/editor-ui/src/app/components/WorkflowCard.vue
+++ b/packages/frontend/editor-ui/src/app/components/WorkflowCard.vue
@@ -50,6 +50,7 @@ import { useMcp } from '@/features/ai/mcpAccess/composables/useMcp';
import { useWorkflowActivate } from '@/app/composables/useWorkflowActivate';
import { createEventBus } from '@n8n/utils/event-bus';
import { usePrivateCredentials } from '@/features/resolvers/composables/usePrivateCredentials';
+import PrivateCredentialIcon from '@/features/resolvers/components/PrivateCredentialIcon.vue';
import { useDependencies } from '@/app/composables/useDependencies';
const WORKFLOW_LIST_ITEM_ACTIONS = {
@@ -618,24 +619,6 @@ const tags = computed(
{{ locale.baseText('workflows.item.readonly') }}
-
-
-
- {{ locale.baseText('workflows.dynamic.tooltipTitle') }}
- {{ locale.baseText('workflows.dynamic.tooltip') }}
-
-
-
-
-
- {{ locale.baseText('credentials.private.badge') }}
-
-
-
@@ -656,6 +639,17 @@ const tags = computed(
+
+ |
+
+
+
+
{
try {
await credentialsStore.fetchCredentialTypes(false);
@@ -41,10 +43,20 @@ onMounted(async () => {
});
// Exclude purpose built credentials for ChatHub
-const selectableCredentialTypes = computed(() =>
+const allSelectableCredentialTypes = computed(() =>
credentialsStore.allCredentialTypes.filter((c) => !c.name.startsWith('chatHub')),
);
+const selectableCredentialTypes = computed(() => {
+ if (!searchQuery.value) return allSelectableCredentialTypes.value;
+ const q = searchQuery.value.toLowerCase();
+ return allSelectableCredentialTypes.value.filter((c) => c.displayName.toLowerCase().includes(q));
+});
+
+function filterCredentials(query: string) {
+ searchQuery.value = query;
+}
+
function onSelect(type: string) {
selected.value = type;
}
@@ -106,6 +118,7 @@ function openCredentialType() {
:placeholder="i18n.baseText('credentialSelectModal.searchForApp')"
size="xlarge"
:model-value="selected"
+ :filter-method="filterCredentials"
data-test-id="new-credential-type-select"
@update:model-value="onSelect"
>
diff --git a/packages/frontend/editor-ui/src/features/resolvers/components/PrivateCredentialIcon.test.ts b/packages/frontend/editor-ui/src/features/resolvers/components/PrivateCredentialIcon.test.ts
new file mode 100644
index 00000000000..304f5e5076e
--- /dev/null
+++ b/packages/frontend/editor-ui/src/features/resolvers/components/PrivateCredentialIcon.test.ts
@@ -0,0 +1,11 @@
+import { createComponentRenderer } from '@/__tests__/render';
+import PrivateCredentialIcon from './PrivateCredentialIcon.vue';
+
+const renderComponent = createComponentRenderer(PrivateCredentialIcon);
+
+describe('PrivateCredentialIcon', () => {
+ it('should render the icon', () => {
+ const { getByTestId } = renderComponent();
+ expect(getByTestId('private-credential-icon')).toBeInTheDocument();
+ });
+});
diff --git a/packages/frontend/editor-ui/src/features/resolvers/components/PrivateCredentialIcon.vue b/packages/frontend/editor-ui/src/features/resolvers/components/PrivateCredentialIcon.vue
new file mode 100644
index 00000000000..2733ad76621
--- /dev/null
+++ b/packages/frontend/editor-ui/src/features/resolvers/components/PrivateCredentialIcon.vue
@@ -0,0 +1,27 @@
+
+
+
+
+ {{ content }}
+
+
+
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d83b0903441..263266e0c73 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -4188,8 +4188,8 @@ importers:
version: 1.0.15
devDependencies:
'@iconify/json':
- specifier: ^2.2.349
- version: 2.2.354
+ specifier: ^2.2.488
+ version: 2.2.488
'@n8n/eslint-config':
specifier: workspace:*
version: link:../../../@n8n/eslint-config
@@ -4853,8 +4853,8 @@ importers:
specifier: ^8.0.2
version: 8.4.1
'@iconify/json':
- specifier: ^2.2.349
- version: 2.2.354
+ specifier: ^2.2.488
+ version: 2.2.488
'@n8n/eslint-config':
specifier: workspace:*
version: link:../../@n8n/eslint-config
@@ -7620,8 +7620,8 @@ packages:
'@iconify-json/mdi@1.1.63':
resolution: {integrity: sha512-b07dRM5LYdwJqd/lm+1+JDNDNSWHvpZ7ujb73oJxx3lmK1J0giDS0BSc4yia0hixNV0Z2q/4GyxAu/A8XqDnbg==}
- '@iconify/json@2.2.354':
- resolution: {integrity: sha512-I7sYXaLfvGw0msuc5p2VdQJ4nthbsqLW8IF9j1jaekUcs/xwGVgs3SHO5lEiFglv0odlkCu26CMbboZMvwkTcw==}
+ '@iconify/json@2.2.488':
+ resolution: {integrity: sha512-W2MfGS0n1GugWhQn7SLgRKNH1JonVsKG/O9vO/htP7j3k1bGt54R1mbN9uaZlQ99uCCu65IR5UgQM66E8Cm+Fw==}
'@iconify/types@2.0.0':
resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==}
@@ -18234,9 +18234,6 @@ packages:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
- pathe@1.1.2:
- resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
-
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
@@ -24875,10 +24872,10 @@ snapshots:
dependencies:
'@iconify/types': 2.0.0
- '@iconify/json@2.2.354':
+ '@iconify/json@2.2.488':
dependencies:
'@iconify/types': 2.0.0
- pathe: 1.1.2
+ pathe: 2.0.3
'@iconify/types@2.0.0': {}
@@ -37338,8 +37335,6 @@ snapshots:
path-type@4.0.0: {}
- pathe@1.1.2: {}
-
pathe@2.0.3: {}
pathval@2.0.0: {}