mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat: Add share button to workflows list (#4681)
* feat: Add share button to workflows list * fix: take empty workflow into account when sharing
This commit is contained in:
parent
b5b44d1b59
commit
a356d7bdba
|
@ -241,7 +241,7 @@ export default mixins(workflowHelpers, titleChange).extend({
|
||||||
if (saved) await this.settingsStore.fetchPromptsData();
|
if (saved) await this.settingsStore.fetchPromptsData();
|
||||||
},
|
},
|
||||||
onShareButtonClick() {
|
onShareButtonClick() {
|
||||||
this.uiStore.openModal(WORKFLOW_SHARE_MODAL_KEY);
|
this.uiStore.openModalWithData({ name: WORKFLOW_SHARE_MODAL_KEY, data: { id: this.currentWorkflowId } });
|
||||||
},
|
},
|
||||||
onTagsEditEnable() {
|
onTagsEditEnable() {
|
||||||
this.$data.appliedTagIds = this.currentWorkflowTagIds;
|
this.$data.appliedTagIds = this.currentWorkflowTagIds;
|
||||||
|
|
|
@ -83,7 +83,13 @@
|
||||||
</ModalRoot>
|
</ModalRoot>
|
||||||
|
|
||||||
<ModalRoot :name="WORKFLOW_SHARE_MODAL_KEY">
|
<ModalRoot :name="WORKFLOW_SHARE_MODAL_KEY">
|
||||||
<WorkflowShareModal />
|
<template #default="{ modalName, active, data }">
|
||||||
|
<WorkflowShareModal
|
||||||
|
:data="data"
|
||||||
|
:isActive="active"
|
||||||
|
:modalName="modalName"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
</ModalRoot>
|
</ModalRoot>
|
||||||
|
|
||||||
<ModalRoot :name="ONBOARDING_CALL_SIGNUP_MODAL_KEY">
|
<ModalRoot :name="ONBOARDING_CALL_SIGNUP_MODAL_KEY">
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import mixins from 'vue-typed-mixins';
|
import mixins from 'vue-typed-mixins';
|
||||||
import {IWorkflowDb, IUser, ITag} from "@/Interface";
|
import {IWorkflowDb, IUser, ITag} from "@/Interface";
|
||||||
import {DUPLICATE_MODAL_KEY, EnterpriseEditionFeature, VIEWS} from '@/constants';
|
import {DUPLICATE_MODAL_KEY, EnterpriseEditionFeature, VIEWS, WORKFLOW_SHARE_MODAL_KEY} from '@/constants';
|
||||||
import {showMessage} from "@/components/mixins/showMessage";
|
import {showMessage} from "@/components/mixins/showMessage";
|
||||||
import {getWorkflowPermissions, IPermissions} from "@/permissions";
|
import {getWorkflowPermissions, IPermissions} from "@/permissions";
|
||||||
import dateformat from "dateformat";
|
import dateformat from "dateformat";
|
||||||
|
@ -74,6 +74,7 @@ import { useWorkflowsStore } from '@/stores/workflows';
|
||||||
|
|
||||||
export const WORKFLOW_LIST_ITEM_ACTIONS = {
|
export const WORKFLOW_LIST_ITEM_ACTIONS = {
|
||||||
OPEN: 'open',
|
OPEN: 'open',
|
||||||
|
SHARE: 'share',
|
||||||
DUPLICATE: 'duplicate',
|
DUPLICATE: 'duplicate',
|
||||||
DELETE: 'delete',
|
DELETE: 'delete',
|
||||||
};
|
};
|
||||||
|
@ -131,6 +132,10 @@ export default mixins(
|
||||||
label: this.$locale.baseText('workflows.item.open'),
|
label: this.$locale.baseText('workflows.item.open'),
|
||||||
value: WORKFLOW_LIST_ITEM_ACTIONS.OPEN,
|
value: WORKFLOW_LIST_ITEM_ACTIONS.OPEN,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: this.$locale.baseText('workflows.item.share'),
|
||||||
|
value: WORKFLOW_LIST_ITEM_ACTIONS.SHARE,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: this.$locale.baseText('workflows.item.duplicate'),
|
label: this.$locale.baseText('workflows.item.duplicate'),
|
||||||
value: WORKFLOW_LIST_ITEM_ACTIONS.DUPLICATE,
|
value: WORKFLOW_LIST_ITEM_ACTIONS.DUPLICATE,
|
||||||
|
@ -183,6 +188,8 @@ export default mixins(
|
||||||
tags: (this.data.tags || []).map((tag: ITag) => tag.id),
|
tags: (this.data.tags || []).map((tag: ITag) => tag.id),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
} else if (action === WORKFLOW_LIST_ITEM_ACTIONS.SHARE) {
|
||||||
|
this.uiStore.openModalWithData({ name: WORKFLOW_SHARE_MODAL_KEY, data: { id: this.data.id } });
|
||||||
} else if (action === WORKFLOW_LIST_ITEM_ACTIONS.DELETE) {
|
} else if (action === WORKFLOW_LIST_ITEM_ACTIONS.DELETE) {
|
||||||
const deleteConfirmed = await this.confirmMessage(
|
const deleteConfirmed = await this.confirmMessage(
|
||||||
this.$locale.baseText(
|
this.$locale.baseText(
|
||||||
|
|
|
@ -120,14 +120,23 @@ export default mixins(
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
},
|
},
|
||||||
|
props: {
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
const workflowsStore = useWorkflowsStore();
|
const workflowsStore = useWorkflowsStore();
|
||||||
|
const workflow = this.data.id === PLACEHOLDER_EMPTY_WORKFLOW_ID
|
||||||
|
? workflowsStore.workflow
|
||||||
|
: workflowsStore.workflowsById[this.data.id];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
WORKFLOW_SHARE_MODAL_KEY,
|
WORKFLOW_SHARE_MODAL_KEY,
|
||||||
loading: false,
|
loading: false,
|
||||||
modalBus: new Vue(),
|
modalBus: new Vue(),
|
||||||
sharedWith: [...(workflowsStore.workflow.sharedWith || [])] as Array<Partial<IUser>>,
|
sharedWith: [...(workflow.sharedWith || [])] as Array<Partial<IUser>>,
|
||||||
EnterpriseEditionFeature,
|
EnterpriseEditionFeature,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -150,7 +159,9 @@ export default mixins(
|
||||||
] as Array<Partial<IUser>>).concat(this.sharedWith || []);
|
] as Array<Partial<IUser>>).concat(this.sharedWith || []);
|
||||||
},
|
},
|
||||||
workflow(): IWorkflowDb {
|
workflow(): IWorkflowDb {
|
||||||
return this.workflowsStore.workflow;
|
return this.data.id === PLACEHOLDER_EMPTY_WORKFLOW_ID
|
||||||
|
? this.workflowsStore.workflow
|
||||||
|
: this.workflowsStore.workflowsById[this.data.id];
|
||||||
},
|
},
|
||||||
currentUser(): IUser | null {
|
currentUser(): IUser | null {
|
||||||
return this.usersStore.currentUser;
|
return this.usersStore.currentUser;
|
||||||
|
@ -221,7 +232,7 @@ export default mixins(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
this.sharedWith = this.sharedWith.filter((sharee: IUser) => {
|
this.sharedWith = this.sharedWith.filter((sharee: Partial<IUser>) => {
|
||||||
return sharee.id !== user.id;
|
return sharee.id !== user.id;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
PLACEHOLDER_EMPTY_WORKFLOW_ID,
|
PLACEHOLDER_EMPTY_WORKFLOW_ID,
|
||||||
START_NODE_TYPE,
|
START_NODE_TYPE,
|
||||||
WEBHOOK_NODE_TYPE,
|
WEBHOOK_NODE_TYPE,
|
||||||
VIEWS,
|
VIEWS, EnterpriseEditionFeature,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -65,6 +65,8 @@ import { IWorkflowSettings } from 'n8n-workflow';
|
||||||
import { useNDVStore } from '@/stores/ndv';
|
import { useNDVStore } from '@/stores/ndv';
|
||||||
import { useTemplatesStore } from '@/stores/templates';
|
import { useTemplatesStore } from '@/stores/templates';
|
||||||
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
import { useNodeTypesStore } from '@/stores/nodeTypes';
|
||||||
|
import useWorkflowsEEStore from "@/stores/workflows.ee";
|
||||||
|
import {useUsersStore} from "@/stores/users";
|
||||||
|
|
||||||
let cachedWorkflowKey: string | null = '';
|
let cachedWorkflowKey: string | null = '';
|
||||||
let cachedWorkflow: Workflow | null = null;
|
let cachedWorkflow: Workflow | null = null;
|
||||||
|
@ -83,6 +85,8 @@ export const workflowHelpers = mixins(
|
||||||
useRootStore,
|
useRootStore,
|
||||||
useTemplatesStore,
|
useTemplatesStore,
|
||||||
useWorkflowsStore,
|
useWorkflowsStore,
|
||||||
|
useWorkflowsEEStore,
|
||||||
|
useUsersStore,
|
||||||
useUIStore,
|
useUIStore,
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
@ -796,6 +800,10 @@ export const workflowHelpers = mixins(
|
||||||
this.workflowsStore.addWorkflow(workflowData);
|
this.workflowsStore.addWorkflow(workflowData);
|
||||||
this.workflowsStore.setWorkflowHash(workflowData.hash);
|
this.workflowsStore.setWorkflowHash(workflowData.hash);
|
||||||
|
|
||||||
|
if (this.settingsStore.isEnterpriseFeatureEnabled(EnterpriseEditionFeature.WorkflowSharing) && this.usersStore.currentUser) {
|
||||||
|
this.workflowsEEStore.setWorkflowOwnedBy({ workflowId: workflowData.id, ownedBy: this.usersStore.currentUser });
|
||||||
|
}
|
||||||
|
|
||||||
if (openInNewWindow) {
|
if (openInNewWindow) {
|
||||||
const routeData = this.$router.resolve({name: VIEWS.WORKFLOW, params: {name: workflowData.id}});
|
const routeData = this.$router.resolve({name: VIEWS.WORKFLOW, params: {name: workflowData.id}});
|
||||||
window.open(routeData.href, '_blank');
|
window.open(routeData.href, '_blank');
|
||||||
|
|
|
@ -1342,6 +1342,7 @@
|
||||||
"workflows.menu.my": "My workflows",
|
"workflows.menu.my": "My workflows",
|
||||||
"workflows.menu.all": "All workflows",
|
"workflows.menu.all": "All workflows",
|
||||||
"workflows.item.open": "Open",
|
"workflows.item.open": "Open",
|
||||||
|
"workflows.item.share": "Share...",
|
||||||
"workflows.item.duplicate": "Duplicate",
|
"workflows.item.duplicate": "Duplicate",
|
||||||
"workflows.item.delete": "Delete",
|
"workflows.item.delete": "Delete",
|
||||||
"workflows.item.updated": "Last updated",
|
"workflows.item.updated": "Last updated",
|
||||||
|
|
Loading…
Reference in a new issue