mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Show used credentials info when moving workflow between projects
This commit is contained in:
parent
be2dcffc94
commit
32c6768271
|
@ -1,6 +1,6 @@
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, computed, onMounted, h } from 'vue';
|
import { ref, computed, onMounted, h } from 'vue';
|
||||||
import type { ICredentialsResponse, IWorkflowDb } from '@/Interface';
|
import type { ICredentialsResponse, IUsedCredential, IWorkflowDb } from '@/Interface';
|
||||||
import { useI18n } from '@/composables/useI18n';
|
import { useI18n } from '@/composables/useI18n';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { useProjectsStore } from '@/stores/projects.store';
|
import { useProjectsStore } from '@/stores/projects.store';
|
||||||
|
@ -13,6 +13,7 @@ import ProjectMoveSuccessToastMessage from '@/components/Projects/ProjectMoveSuc
|
||||||
import { useToast } from '@/composables/useToast';
|
import { useToast } from '@/composables/useToast';
|
||||||
import { getResourcePermissions } from '@/permissions';
|
import { getResourcePermissions } from '@/permissions';
|
||||||
import { sortByProperty } from '@/utils/sortUtils';
|
import { sortByProperty } from '@/utils/sortUtils';
|
||||||
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
modalName: string;
|
modalName: string;
|
||||||
|
@ -27,10 +28,13 @@ const i18n = useI18n();
|
||||||
const uiStore = useUIStore();
|
const uiStore = useUIStore();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const projectsStore = useProjectsStore();
|
const projectsStore = useProjectsStore();
|
||||||
|
const workflowsStore = useWorkflowsStore();
|
||||||
const telemetry = useTelemetry();
|
const telemetry = useTelemetry();
|
||||||
|
|
||||||
const filter = ref('');
|
const filter = ref('');
|
||||||
const projectId = ref<string | null>(null);
|
const projectId = ref<string | null>(null);
|
||||||
|
const usedCredentials = ref<IUsedCredential[]>([]);
|
||||||
|
const shareUsedCredentials = ref(false);
|
||||||
const processedName = computed(
|
const processedName = computed(
|
||||||
() => processProjectName(props.data.resource.homeProject?.name ?? '') ?? '',
|
() => processProjectName(props.data.resource.homeProject?.name ?? '') ?? '',
|
||||||
);
|
);
|
||||||
|
@ -49,6 +53,7 @@ const selectedProject = computed(() =>
|
||||||
availableProjects.value.find((p) => p.id === projectId.value),
|
availableProjects.value.find((p) => p.id === projectId.value),
|
||||||
);
|
);
|
||||||
const isResourceInTeamProject = computed(() => isHomeProjectTeam(props.data.resource));
|
const isResourceInTeamProject = computed(() => isHomeProjectTeam(props.data.resource));
|
||||||
|
const isResourceWorkflow = computed(() => props.data.resourceType === ResourceType.Workflow);
|
||||||
|
|
||||||
const isHomeProjectTeam = (resource: IWorkflowDb | ICredentialsResponse) =>
|
const isHomeProjectTeam = (resource: IWorkflowDb | ICredentialsResponse) =>
|
||||||
resource.homeProject?.type === ProjectTypes.Team;
|
resource.homeProject?.type === ProjectTypes.Team;
|
||||||
|
@ -90,10 +95,7 @@ const moveResource = async () => {
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
message: h(ProjectMoveSuccessToastMessage, {
|
message: h(ProjectMoveSuccessToastMessage, {
|
||||||
routeName:
|
routeName: isResourceWorkflow.value ? VIEWS.PROJECTS_WORKFLOWS : VIEWS.PROJECTS_CREDENTIALS,
|
||||||
props.data.resourceType === ResourceType.Workflow
|
|
||||||
? VIEWS.PROJECTS_WORKFLOWS
|
|
||||||
: VIEWS.PROJECTS_CREDENTIALS,
|
|
||||||
resource: props.data.resource,
|
resource: props.data.resource,
|
||||||
resourceType: props.data.resourceType,
|
resourceType: props.data.resourceType,
|
||||||
resourceTypeLabel: props.data.resourceTypeLabel,
|
resourceTypeLabel: props.data.resourceTypeLabel,
|
||||||
|
@ -115,11 +117,16 @@ const moveResource = async () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
telemetry.track(`User clicked to move a ${props.data.resourceType}`, {
|
telemetry.track(`User clicked to move a ${props.data.resourceType}`, {
|
||||||
[`${props.data.resourceType}_id`]: props.data.resource.id,
|
[`${props.data.resourceType}_id`]: props.data.resource.id,
|
||||||
project_from_type: projectsStore.currentProject?.type ?? projectsStore.personalProject?.type,
|
project_from_type: projectsStore.currentProject?.type ?? projectsStore.personalProject?.type,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (isResourceWorkflow.value) {
|
||||||
|
const data = await workflowsStore.fetchWorkflow(props.data.resource.id);
|
||||||
|
usedCredentials.value = data.usedCredentials ?? [];
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
@ -184,8 +191,10 @@ onMounted(() => {
|
||||||
>
|
>
|
||||||
<template #resourceTypeLabel>{{ props.data.resourceTypeLabel }}</template>
|
<template #resourceTypeLabel>{{ props.data.resourceTypeLabel }}</template>
|
||||||
</i18n-t>
|
</i18n-t>
|
||||||
<span v-if="props.data.resource.sharedWithProjects?.length ?? 0 > 0">
|
<span
|
||||||
<br />
|
v-if="props.data.resource.sharedWithProjects?.length ?? 0 > 0"
|
||||||
|
:class="$style.textBlock"
|
||||||
|
>
|
||||||
{{
|
{{
|
||||||
i18n.baseText('projects.move.resource.modal.message.sharingInfo', {
|
i18n.baseText('projects.move.resource.modal.message.sharingInfo', {
|
||||||
adjustToNumber: props.data.resource.sharedWithProjects?.length,
|
adjustToNumber: props.data.resource.sharedWithProjects?.length,
|
||||||
|
@ -195,6 +204,43 @@ onMounted(() => {
|
||||||
})
|
})
|
||||||
}}</span
|
}}</span
|
||||||
>
|
>
|
||||||
|
<N8nCheckbox
|
||||||
|
v-if="usedCredentials.length"
|
||||||
|
v-model="shareUsedCredentials"
|
||||||
|
:class="$style.textBlock"
|
||||||
|
>
|
||||||
|
<i18n-t keypath="projects.move.resource.modal.message.usedCredentials">
|
||||||
|
<template #usedCredentials>
|
||||||
|
<N8nTooltip placement="top">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
i18n.baseText('projects.move.resource.modal.message.usedCredentials.number', {
|
||||||
|
adjustToNumber: usedCredentials.length,
|
||||||
|
interpolate: { number: usedCredentials.length },
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
<template #content>
|
||||||
|
<ul>
|
||||||
|
<li v-for="credential in usedCredentials" :key="credential.id">
|
||||||
|
<router-link
|
||||||
|
target="_blank"
|
||||||
|
:to="{
|
||||||
|
name: projectsStore.currentProjectId
|
||||||
|
? VIEWS.PROJECTS_CREDENTIALS
|
||||||
|
: VIEWS.CREDENTIALS,
|
||||||
|
params: { credentialId: credential.id },
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ credential.name }}
|
||||||
|
</router-link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</template>
|
||||||
|
</N8nTooltip>
|
||||||
|
</template>
|
||||||
|
</i18n-t>
|
||||||
|
</N8nCheckbox>
|
||||||
</N8nText>
|
</N8nText>
|
||||||
</div>
|
</div>
|
||||||
<N8nText v-else>{{
|
<N8nText v-else>{{
|
||||||
|
@ -225,4 +271,9 @@ onMounted(() => {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.textBlock {
|
||||||
|
display: block;
|
||||||
|
margin-top: var(--spacing-s);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2606,6 +2606,8 @@
|
||||||
"projects.move.resource.modal.message.note": "Note",
|
"projects.move.resource.modal.message.note": "Note",
|
||||||
"projects.move.resource.modal.message.sharingNote": "{note}: Moving will remove any existing sharing for this {resourceTypeLabel}.",
|
"projects.move.resource.modal.message.sharingNote": "{note}: Moving will remove any existing sharing for this {resourceTypeLabel}.",
|
||||||
"projects.move.resource.modal.message.sharingInfo": "(Currently shared with {numberOfProjects} project) | (Currently shared with {numberOfProjects} projects)",
|
"projects.move.resource.modal.message.sharingInfo": "(Currently shared with {numberOfProjects} project) | (Currently shared with {numberOfProjects} projects)",
|
||||||
|
"projects.move.resource.modal.message.usedCredentials": "Also share the {usedCredentials} used by this workflow to ensure it will continue to run correctly",
|
||||||
|
"projects.move.resource.modal.message.usedCredentials.number": "{number} credential | {number} credentials",
|
||||||
"projects.move.resource.modal.message.noProjects": "Currently there are not any projects or users available for you to move this {resourceTypeLabel} to.",
|
"projects.move.resource.modal.message.noProjects": "Currently there are not any projects or users available for you to move this {resourceTypeLabel} to.",
|
||||||
"projects.move.resource.modal.button": "Move {resourceTypeLabel}",
|
"projects.move.resource.modal.button": "Move {resourceTypeLabel}",
|
||||||
"projects.move.resource.modal.selectPlaceholder": "Select project or user...",
|
"projects.move.resource.modal.selectPlaceholder": "Select project or user...",
|
||||||
|
|
Loading…
Reference in a new issue