mirror of
https://github.com/n8n-io/n8n.git
synced 2026-08-28 17:22:01 +08:00
feat(editor): Show private credential icon on execution list runs (#32957)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -53,7 +53,7 @@ Auto-generated from the PostgreSQL migrations in @n8n/db. Do not edit by hand.
|
||||
| [public.execution_annotation_tags](public.execution_annotation_tags.md) | 2 | | BASE TABLE |
|
||||
| [public.execution_annotations](public.execution_annotations.md) | 6 | | BASE TABLE |
|
||||
| [public.execution_data](public.execution_data.md) | 4 | | BASE TABLE |
|
||||
| [public.execution_entity](public.execution_entity.md) | 18 | | BASE TABLE |
|
||||
| [public.execution_entity](public.execution_entity.md) | 19 | | BASE TABLE |
|
||||
| [public.execution_metadata](public.execution_metadata.md) | 4 | | BASE TABLE |
|
||||
| [public.folder](public.folder.md) | 6 | | BASE TABLE |
|
||||
| [public.folder_tag](public.folder_tag.md) | 2 | | BASE TABLE |
|
||||
@@ -750,6 +750,7 @@ erDiagram
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
json tracingContext
|
||||
boolean usedPrivateCredentials
|
||||
timestamp_3__with_time_zone waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -113,6 +113,7 @@ erDiagram
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
json tracingContext
|
||||
boolean usedPrivateCredentials
|
||||
timestamp_3__with_time_zone waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -61,6 +61,7 @@ erDiagram
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
json tracingContext
|
||||
boolean usedPrivateCredentials
|
||||
timestamp_3__with_time_zone waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -54,6 +54,7 @@ erDiagram
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
json tracingContext
|
||||
boolean usedPrivateCredentials
|
||||
timestamp_3__with_time_zone waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
| stoppedAt | timestamp(3) with time zone | | true | | | |
|
||||
| storedAt | varchar(2) | 'db'::character varying | false | | | |
|
||||
| tracingContext | json | | true | | | |
|
||||
| usedPrivateCredentials | boolean | false | false | | | Whether this execution ran with at least one dynamically-resolved private credential. |
|
||||
| waitTill | timestamp(3) with time zone | | true | | | |
|
||||
| workflowId | varchar(36) | | false | | [public.workflow_entity](public.workflow_entity.md) | |
|
||||
| workflowVersionId | varchar(36) | NULL::character varying | true | | | Version id of the workflow run by this execution; denormalized from the data bundle. |
|
||||
@@ -36,6 +37,7 @@
|
||||
| execution_entity_mode_not_null | n | NOT NULL mode |
|
||||
| execution_entity_status_not_null | n | NOT NULL status |
|
||||
| execution_entity_storedAt_not_null | n | NOT NULL "storedAt" |
|
||||
| execution_entity_usedPrivateCredentials_not_null | n | NOT NULL "usedPrivateCredentials" |
|
||||
| execution_entity_workflowId_not_null | n | NOT NULL "workflowId" |
|
||||
| fk_execution_entity_workflow_id | FOREIGN KEY | FOREIGN KEY ("workflowId") REFERENCES workflow_entity(id) ON DELETE CASCADE |
|
||||
| pk_e3e63bbf986767844bbe1166d4e | PRIMARY KEY | PRIMARY KEY (id) |
|
||||
@@ -80,6 +82,7 @@ erDiagram
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
json tracingContext
|
||||
boolean usedPrivateCredentials
|
||||
timestamp_3__with_time_zone waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -56,6 +56,7 @@ erDiagram
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
json tracingContext
|
||||
boolean usedPrivateCredentials
|
||||
timestamp_3__with_time_zone waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -79,6 +79,7 @@ erDiagram
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
json tracingContext
|
||||
boolean usedPrivateCredentials
|
||||
timestamp_3__with_time_zone waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -202,6 +202,7 @@ erDiagram
|
||||
timestamp_3__with_time_zone stoppedAt
|
||||
varchar_2_ storedAt
|
||||
json tracingContext
|
||||
boolean usedPrivateCredentials
|
||||
timestamp_3__with_time_zone waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -53,7 +53,7 @@ Auto-generated from the SQLite migrations in @n8n/db. Do not edit by hand.
|
||||
| [execution_annotation_tags](execution_annotation_tags.md) | 2 | | table |
|
||||
| [execution_annotations](execution_annotations.md) | 6 | | table |
|
||||
| [execution_data](execution_data.md) | 4 | | table |
|
||||
| [execution_entity](execution_entity.md) | 18 | | table |
|
||||
| [execution_entity](execution_entity.md) | 19 | | table |
|
||||
| [execution_metadata](execution_metadata.md) | 4 | | table |
|
||||
| [folder](folder.md) | 6 | | table |
|
||||
| [folder_tag](folder_tag.md) | 2 | | table |
|
||||
@@ -738,6 +738,7 @@ erDiagram
|
||||
datetime stoppedAt
|
||||
varchar_2_ storedAt
|
||||
TEXT tracingContext
|
||||
BOOLEAN usedPrivateCredentials
|
||||
datetime waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -117,6 +117,7 @@ erDiagram
|
||||
datetime stoppedAt
|
||||
varchar_2_ storedAt
|
||||
TEXT tracingContext
|
||||
BOOLEAN usedPrivateCredentials
|
||||
datetime waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -67,6 +67,7 @@ erDiagram
|
||||
datetime stoppedAt
|
||||
varchar_2_ storedAt
|
||||
TEXT tracingContext
|
||||
BOOLEAN usedPrivateCredentials
|
||||
datetime waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -68,6 +68,7 @@ erDiagram
|
||||
datetime stoppedAt
|
||||
varchar_2_ storedAt
|
||||
TEXT tracingContext
|
||||
BOOLEAN usedPrivateCredentials
|
||||
datetime waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<summary><strong>Table Definition</strong></summary>
|
||||
|
||||
```sql
|
||||
CREATE TABLE "execution_entity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "workflowId" varchar(36) NOT NULL, "finished" boolean NOT NULL, "mode" varchar NOT NULL, "retryOf" varchar, "retrySuccessId" varchar, "startedAt" datetime, "stoppedAt" datetime, "waitTill" datetime, "status" varchar NOT NULL, "deletedAt" datetime(3), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "storedAt" varchar(2) NOT NULL DEFAULT ('db'), "tracingContext" text, "deduplicationKey" varchar(255), "jsonSizeBytes" bigint NOT NULL DEFAULT (0), "workflowVersionId" varchar(36) DEFAULT (NULL), "binaryDataSizeBytes" bigint NOT NULL DEFAULT (0), CONSTRAINT "CHK_execution_entity_storedAt" CHECK ("storedAt" IN ('db', 'fs', 's3', 'az')), CONSTRAINT "FK_c4d999a5e90784e8caccf5589de" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)
|
||||
CREATE TABLE "execution_entity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "workflowId" varchar(36) NOT NULL, "finished" boolean NOT NULL, "mode" varchar NOT NULL, "retryOf" varchar, "retrySuccessId" varchar, "startedAt" datetime, "stoppedAt" datetime, "waitTill" datetime, "status" varchar NOT NULL, "deletedAt" datetime(3), "createdAt" datetime(3) NOT NULL DEFAULT (STRFTIME('%Y-%m-%d %H:%M:%f', 'NOW')), "storedAt" varchar(2) NOT NULL DEFAULT ('db'), "tracingContext" text, "deduplicationKey" varchar(255), "jsonSizeBytes" bigint NOT NULL DEFAULT (0), "workflowVersionId" varchar(36) DEFAULT (NULL), "binaryDataSizeBytes" bigint NOT NULL DEFAULT (0), "usedPrivateCredentials" BOOLEAN NOT NULL DEFAULT FALSE, CONSTRAINT "CHK_execution_entity_storedAt" CHECK ("storedAt" IN ('db', 'fs', 's3', 'az')), CONSTRAINT "FK_c4d999a5e90784e8caccf5589de" FOREIGN KEY ("workflowId") REFERENCES "workflow_entity" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -30,6 +30,7 @@ CREATE TABLE "execution_entity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL
|
||||
| stoppedAt | datetime | | true | | | |
|
||||
| storedAt | varchar(2) | 'db' | false | | | |
|
||||
| tracingContext | TEXT | | true | | | |
|
||||
| usedPrivateCredentials | BOOLEAN | FALSE | false | | | |
|
||||
| waitTill | datetime | | true | | | |
|
||||
| workflowId | varchar(36) | | false | | [workflow_entity](workflow_entity.md) | |
|
||||
| workflowVersionId | varchar(36) | NULL | true | | | |
|
||||
@@ -80,6 +81,7 @@ erDiagram
|
||||
datetime stoppedAt
|
||||
varchar_2_ storedAt
|
||||
TEXT tracingContext
|
||||
BOOLEAN usedPrivateCredentials
|
||||
datetime waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -62,6 +62,7 @@ erDiagram
|
||||
datetime stoppedAt
|
||||
varchar_2_ storedAt
|
||||
TEXT tracingContext
|
||||
BOOLEAN usedPrivateCredentials
|
||||
datetime waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -94,6 +94,7 @@ erDiagram
|
||||
datetime stoppedAt
|
||||
varchar_2_ storedAt
|
||||
TEXT tracingContext
|
||||
BOOLEAN usedPrivateCredentials
|
||||
datetime waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -201,6 +201,7 @@ erDiagram
|
||||
datetime stoppedAt
|
||||
varchar_2_ storedAt
|
||||
TEXT tracingContext
|
||||
BOOLEAN usedPrivateCredentials
|
||||
datetime waitTill
|
||||
varchar_36_ workflowId FK
|
||||
varchar_36_ workflowVersionId
|
||||
|
||||
@@ -127,6 +127,9 @@ export class ExecutionEntity {
|
||||
@Column({ type: 'varchar', length: 36, nullable: true })
|
||||
workflowVersionId: string | null;
|
||||
|
||||
@Column({ default: false })
|
||||
usedPrivateCredentials: boolean;
|
||||
|
||||
@OneToMany('ExecutionMetadata', 'execution')
|
||||
metadata: ExecutionMetadata[];
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ export interface IExecutionBase {
|
||||
jsonSizeBytes?: number; // see `ExecutionEntity.jsonSizeBytes`
|
||||
binaryDataSizeBytes?: number; // see `ExecutionEntity.binaryDataSizeBytes`
|
||||
workflowVersionId?: string | null; // see `ExecutionEntity.workflowVersionId`
|
||||
usedPrivateCredentials?: boolean; // see `ExecutionEntity.usedPrivateCredentials`
|
||||
}
|
||||
|
||||
// Required by PublicUser
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import type { MigrationContext, ReversibleMigration } from '../migration-types';
|
||||
|
||||
export class AddUsedPrivateCredentialsToExecutionEntity1784000000041
|
||||
implements ReversibleMigration
|
||||
{
|
||||
async up({ escape, runQuery, isPostgres }: MigrationContext) {
|
||||
const tableName = escape.tableName('execution_entity');
|
||||
const column = escape.columnName('usedPrivateCredentials');
|
||||
|
||||
await runQuery(`ALTER TABLE ${tableName} ADD COLUMN ${column} BOOLEAN NOT NULL DEFAULT FALSE`);
|
||||
|
||||
if (isPostgres) {
|
||||
await runQuery(
|
||||
`COMMENT ON COLUMN ${tableName}.${column} IS 'Whether this execution ran with at least one dynamically-resolved private credential.'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async down({ escape, runQuery }: MigrationContext) {
|
||||
const tableName = escape.tableName('execution_entity');
|
||||
const column = escape.columnName('usedPrivateCredentials');
|
||||
|
||||
await runQuery(`ALTER TABLE ${tableName} DROP COLUMN ${column}`);
|
||||
}
|
||||
}
|
||||
@@ -214,6 +214,7 @@ import { DropAgentDescriptionFromAgents1784000000037 } from '../common/178400000
|
||||
import { SetChatHubEnabledFromUsage1784000000038 } from '../common/1784000000038-SetChatHubEnabledFromUsage';
|
||||
import { DropAgentExecutionFallbackColumns1784000000039 } from '../common/1784000000039-DropAgentExecutionFallbackColumns';
|
||||
import { CreateWorkflowPublicationTriggerStatusTable1784000000040 } from '../common/1784000000040-CreateWorkflowPublicationTriggerStatusTable';
|
||||
import { AddUsedPrivateCredentialsToExecutionEntity1784000000041 } from '../common/1784000000041-AddUsedPrivateCredentialsToExecutionEntity';
|
||||
import type { Migration } from '../migration-types';
|
||||
|
||||
export const postgresMigrations: Migration[] = [
|
||||
@@ -433,4 +434,5 @@ export const postgresMigrations: Migration[] = [
|
||||
SetChatHubEnabledFromUsage1784000000038,
|
||||
DropAgentExecutionFallbackColumns1784000000039,
|
||||
CreateWorkflowPublicationTriggerStatusTable1784000000040,
|
||||
AddUsedPrivateCredentialsToExecutionEntity1784000000041,
|
||||
];
|
||||
|
||||
@@ -207,6 +207,7 @@ import { CreateInstanceAiThreadGrantTable1784000000036 } from '../common/1784000
|
||||
import { SetChatHubEnabledFromUsage1784000000038 } from '../common/1784000000038-SetChatHubEnabledFromUsage';
|
||||
import { DropAgentExecutionFallbackColumns1784000000039 } from '../common/1784000000039-DropAgentExecutionFallbackColumns';
|
||||
import { CreateWorkflowPublicationTriggerStatusTable1784000000040 } from '../common/1784000000040-CreateWorkflowPublicationTriggerStatusTable';
|
||||
import { AddUsedPrivateCredentialsToExecutionEntity1784000000041 } from '../common/1784000000041-AddUsedPrivateCredentialsToExecutionEntity';
|
||||
|
||||
const sqliteMigrations: Migration[] = [
|
||||
InitialMigration1588102412422,
|
||||
@@ -417,6 +418,7 @@ const sqliteMigrations: Migration[] = [
|
||||
SetChatHubEnabledFromUsage1784000000038,
|
||||
DropAgentExecutionFallbackColumns1784000000039,
|
||||
CreateWorkflowPublicationTriggerStatusTable1784000000040,
|
||||
AddUsedPrivateCredentialsToExecutionEntity1784000000041,
|
||||
];
|
||||
|
||||
export { sqliteMigrations };
|
||||
|
||||
@@ -753,6 +753,7 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
|
||||
createdAt: true,
|
||||
startedAt: true,
|
||||
stoppedAt: true,
|
||||
usedPrivateCredentials: true,
|
||||
};
|
||||
|
||||
private annotationFields = {
|
||||
@@ -833,6 +834,7 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
|
||||
waitTill?: Date | string | null;
|
||||
jsonSizeBytes?: number | string;
|
||||
binaryDataSizeBytes?: number | string;
|
||||
usedPrivateCredentials?: boolean | number;
|
||||
}): ExecutionSummary {
|
||||
execution.id = execution.id.toString();
|
||||
|
||||
@@ -846,6 +848,11 @@ export class ExecutionRepository extends Repository<ExecutionEntity> {
|
||||
execution.binaryDataSizeBytes = Number(execution.binaryDataSizeBytes);
|
||||
}
|
||||
|
||||
// SQLite returns 0/1 for booleans; coerce to a proper boolean.
|
||||
if (typeof execution.usedPrivateCredentials === 'number') {
|
||||
execution.usedPrivateCredentials = execution.usedPrivateCredentials !== 0;
|
||||
}
|
||||
|
||||
const normalizeDateString = (date: string) => {
|
||||
if (date.includes(' ')) return date.replace(' ', 'T') + 'Z';
|
||||
return date;
|
||||
|
||||
@@ -45,6 +45,7 @@ import {
|
||||
updateExistingExecution,
|
||||
updateExistingExecutionMetadata,
|
||||
} from './shared/shared-hook-functions';
|
||||
|
||||
import { type ExecutionSaveSettings, toSaveSettings } from './to-save-settings';
|
||||
|
||||
@Service()
|
||||
@@ -603,6 +604,14 @@ function hookFunctionsSave(
|
||||
fullExecutionData.data.pushRef = pushRef;
|
||||
}
|
||||
|
||||
fullExecutionData.usedPrivateCredentials = Object.values(
|
||||
fullRunData.data?.resultData?.runData ?? {},
|
||||
).some((taskDataList) =>
|
||||
taskDataList.some(
|
||||
(t) => t.usedDynamicCredentials === true || t.attemptedDynamicCredentials === true,
|
||||
),
|
||||
);
|
||||
|
||||
await updateExistingExecution({
|
||||
executionId: this.executionId,
|
||||
workflowId: this.workflowData.id,
|
||||
@@ -685,6 +694,14 @@ function hookFunctionsSaveWorker(
|
||||
fullExecutionData.data.pushRef = pushRef;
|
||||
}
|
||||
|
||||
fullExecutionData.usedPrivateCredentials = Object.values(
|
||||
fullRunData.data?.resultData?.runData ?? {},
|
||||
).some((taskDataList) =>
|
||||
taskDataList.some(
|
||||
(t) => t.usedDynamicCredentials === true || t.attemptedDynamicCredentials === true,
|
||||
),
|
||||
);
|
||||
|
||||
// In scaling mode, worker saves execution without metadata
|
||||
// Main process will save metadata after deletion decisions to avoid FK violations
|
||||
await updateExistingExecution({
|
||||
|
||||
@@ -100,6 +100,7 @@ describe('ExecutionService', () => {
|
||||
workflowVersionId: null,
|
||||
jsonSizeBytes: 0,
|
||||
binaryDataSizeBytes: 0,
|
||||
usedPrivateCredentials: false,
|
||||
annotation: {
|
||||
tags: expect.arrayContaining([]),
|
||||
vote: null,
|
||||
@@ -966,6 +967,7 @@ describe('ExecutionService', () => {
|
||||
workflowVersionId: null,
|
||||
jsonSizeBytes: 0,
|
||||
binaryDataSizeBytes: 0,
|
||||
usedPrivateCredentials: false,
|
||||
};
|
||||
|
||||
afterEach(async () => {
|
||||
|
||||
@@ -1314,6 +1314,7 @@
|
||||
"error.entityUnAuthorized.title": "You need access",
|
||||
"error.entityUnAuthorized.content": "You don't have permission to view this {entity}. Please contact the person who shared this link to request access.",
|
||||
"executions.ExecutionStatus": "Execution status",
|
||||
"executions.privateCredential.tooltip": "This execution ran using end-user credentials",
|
||||
"executions.concurrency.docsLink": "https://docs.n8n.io/hosting/scaling/concurrency-control/",
|
||||
"executionDetails.additionalActions": "Additional Actions",
|
||||
"executionDetails.confirmMessage.confirmButtonText": "Yes, delete",
|
||||
|
||||
+20
-1
@@ -23,6 +23,7 @@ import {
|
||||
N8nText,
|
||||
N8nTooltip,
|
||||
} from '@n8n/design-system';
|
||||
import PrivateCredentialIcon from '@/features/resolvers/components/PrivateCredentialIcon.vue';
|
||||
type Command = 'retrySaved' | 'retryOriginal' | 'delete';
|
||||
|
||||
const emit = defineEmits<{
|
||||
@@ -274,13 +275,18 @@ async function handleActionItemClick(commandData: Command) {
|
||||
</small>
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<td :class="$style.modeCell">
|
||||
<N8nTooltip v-if="execution.mode === 'manual'" content="Manual Execution" placement="top">
|
||||
<N8nIcon icon="flask-conical" />
|
||||
</N8nTooltip>
|
||||
<N8nTooltip v-else-if="execution.mode === 'chat'" content="Chat Execution" placement="top">
|
||||
<N8nIcon icon="messages-square" />
|
||||
</N8nTooltip>
|
||||
<PrivateCredentialIcon
|
||||
v-if="execution.usedPrivateCredentials"
|
||||
data-test-id="global-execution-private-credential"
|
||||
:tooltip-text="locale.baseText('executions.privateCredential.tooltip')"
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<N8nButton
|
||||
@@ -338,6 +344,19 @@ async function handleActionItemClick(commandData: Command) {
|
||||
</template>
|
||||
|
||||
<style lang="scss" module>
|
||||
.modeCell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing--2xs);
|
||||
|
||||
/* Normalize icon wrappers so SVG baseline doesn't shift relative to tooltip spans */
|
||||
:deep(svg),
|
||||
:deep(span) {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
tr.dangerBg {
|
||||
background-color: rgba(215, 56, 58, 0.1);
|
||||
}
|
||||
|
||||
+16
-5
@@ -11,7 +11,7 @@ import { useI18n } from '@n8n/i18n';
|
||||
import type { PermissionsRecord } from '@n8n/permissions';
|
||||
import { useSettingsStore } from '@/app/stores/settings.store';
|
||||
import { toDayMonth, toTime } from '@/app/utils/formatters/dateFormatter';
|
||||
|
||||
import PrivateCredentialIcon from '@/features/resolvers/components/PrivateCredentialIcon.vue';
|
||||
import {
|
||||
N8nActionDropdown,
|
||||
N8nIcon,
|
||||
@@ -44,6 +44,8 @@ const isAdvancedExecutionFilterEnabled = computed(
|
||||
const isAnnotationEnabled = computed(() => isAdvancedExecutionFilterEnabled.value);
|
||||
|
||||
const workflowId = useInjectWorkflowId();
|
||||
|
||||
const hasPrivateCredentials = computed(() => props.execution.usedPrivateCredentials === true);
|
||||
const retryExecutionActions = computed(() => [
|
||||
{
|
||||
id: 'current-workflow',
|
||||
@@ -169,6 +171,12 @@ function onRetryMenuItemSelect(action: string): void {
|
||||
data-test-id="retry-execution-button"
|
||||
@select="onRetryMenuItemSelect"
|
||||
/>
|
||||
<PrivateCredentialIcon
|
||||
v-if="hasPrivateCredentials"
|
||||
:class="$style.icon"
|
||||
:tooltip-text="locale.baseText('executions.privateCredential.tooltip')"
|
||||
data-test-id="execution-card-private-credential"
|
||||
/>
|
||||
<N8nTooltip v-if="execution.mode === 'manual'" placement="top">
|
||||
<template #content>
|
||||
<span>{{ locale.baseText('executionsList.test') }}</span>
|
||||
@@ -322,10 +330,17 @@ function onRetryMenuItemSelect(action: string): void {
|
||||
.icons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
gap: var(--spacing--2xs);
|
||||
min-width: calc(2 * var(--font-size--sm) + var(--spacing--2xs));
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: var(--font-size--sm);
|
||||
width: var(--font-size--sm);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&.retry {
|
||||
svg {
|
||||
@@ -337,10 +352,6 @@ function onRetryMenuItemSelect(action: string): void {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
& + & {
|
||||
margin-left: var(--spacing--2xs);
|
||||
}
|
||||
}
|
||||
|
||||
.showGap {
|
||||
|
||||
+4
-2
@@ -4,6 +4,8 @@ import { computed } from 'vue';
|
||||
import { N8nIcon, N8nTooltip } from '@n8n/design-system';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
|
||||
defineOptions({ inheritAttrs: false });
|
||||
|
||||
interface Props {
|
||||
tooltip?: boolean;
|
||||
tooltipText?: string;
|
||||
@@ -20,8 +22,8 @@ const content = computed(() => props.tooltipText ?? i18n.baseText('credentials.p
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<N8nTooltip :disabled="!tooltip" placement="top">
|
||||
<N8nTooltip as-child :disabled="!tooltip" placement="top">
|
||||
<template #content>{{ content }}</template>
|
||||
<N8nIcon data-test-id="private-credential-icon" icon="user-round-key" size="small" />
|
||||
<N8nIcon v-bind="$attrs" data-test-id="private-credential-icon" icon="user-round-key" />
|
||||
</N8nTooltip>
|
||||
</template>
|
||||
|
||||
@@ -3736,6 +3736,7 @@ export interface ExecutionSummary {
|
||||
nodeExecutionStatus?: {
|
||||
[key: string]: IExecutionSummaryNodeExecutionResult;
|
||||
};
|
||||
usedPrivateCredentials?: boolean;
|
||||
annotation?: {
|
||||
vote: AnnotationVote;
|
||||
tags: Array<{
|
||||
|
||||
Reference in New Issue
Block a user