mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor(editor): Fix TypeScript issues in views (no-changelog) (#9573)
This commit is contained in:
parent
327794127e
commit
e23420d89d
|
@ -250,7 +250,7 @@ export interface IWorkflowData {
|
||||||
export interface IWorkflowDataUpdate {
|
export interface IWorkflowDataUpdate {
|
||||||
id?: string;
|
id?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
nodes?: INode[];
|
nodes?: Array<INode | IWorkflowTemplateNode>;
|
||||||
connections?: IConnections;
|
connections?: IConnections;
|
||||||
settings?: IWorkflowSettings;
|
settings?: IWorkflowSettings;
|
||||||
active?: boolean;
|
active?: boolean;
|
||||||
|
@ -363,6 +363,7 @@ export interface ICredentialsResponse extends ICredentialsEncrypted {
|
||||||
homeProject?: ProjectSharingData;
|
homeProject?: ProjectSharingData;
|
||||||
currentUserHasAccess?: boolean;
|
currentUserHasAccess?: boolean;
|
||||||
scopes?: Scope[];
|
scopes?: Scope[];
|
||||||
|
ownedBy?: Pick<IUserResponse, 'id' | 'firstName' | 'lastName' | 'email'>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICredentialsBase {
|
export interface ICredentialsBase {
|
||||||
|
|
|
@ -64,7 +64,7 @@ export default function useCanvasMouseSelect() {
|
||||||
selectActive.value = false;
|
selectActive.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getSelectionBox(event: MouseEvent) {
|
function _getSelectionBox(event: MouseEvent | TouchEvent) {
|
||||||
const [x, y] = getMousePositionWithinNodeView(event);
|
const [x, y] = getMousePositionWithinNodeView(event);
|
||||||
return {
|
return {
|
||||||
x: Math.min(x, selectBox.value.x),
|
x: Math.min(x, selectBox.value.x),
|
||||||
|
@ -74,7 +74,7 @@ export default function useCanvasMouseSelect() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getNodesInSelection(event: MouseEvent): INodeUi[] {
|
function _getNodesInSelection(event: MouseEvent | TouchEvent): INodeUi[] {
|
||||||
const returnNodes: INodeUi[] = [];
|
const returnNodes: INodeUi[] = [];
|
||||||
const selectionBox = _getSelectionBox(event);
|
const selectionBox = _getSelectionBox(event);
|
||||||
|
|
||||||
|
@ -128,9 +128,9 @@ export default function useCanvasMouseSelect() {
|
||||||
_updateSelectBox(e);
|
_updateSelectBox(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
function mouseUpMouseSelect(e: MouseEvent) {
|
function mouseUpMouseSelect(e: MouseEvent | TouchEvent) {
|
||||||
// Ignore right-click
|
// Ignore right-click
|
||||||
if (e.button === 2 || isContextMenuOpen.value) return;
|
if (('button' in e && e.button === 2) || isContextMenuOpen.value) return;
|
||||||
|
|
||||||
if (!selectActive.value) {
|
if (!selectActive.value) {
|
||||||
if (isTouchDevice && e.target instanceof HTMLElement) {
|
if (isTouchDevice && e.target instanceof HTMLElement) {
|
||||||
|
|
|
@ -212,7 +212,7 @@ export const useUIStore = defineStore(STORES.UI, {
|
||||||
const settingsStore = useSettingsStore();
|
const settingsStore = useSettingsStore();
|
||||||
const deploymentType = settingsStore.deploymentType;
|
const deploymentType = settingsStore.deploymentType;
|
||||||
|
|
||||||
let contextKey = '';
|
let contextKey: '' | '.cloud' | '.desktop' = '';
|
||||||
if (deploymentType === 'cloud') {
|
if (deploymentType === 'cloud') {
|
||||||
contextKey = '.cloud';
|
contextKey = '.cloud';
|
||||||
} else if (deploymentType === 'desktop_mac' || deploymentType === 'desktop_win') {
|
} else if (deploymentType === 'desktop_mac' || deploymentType === 'desktop_win') {
|
||||||
|
@ -266,7 +266,7 @@ export const useUIStore = defineStore(STORES.UI, {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
} as const;
|
||||||
},
|
},
|
||||||
getLastSelectedNode(): INodeUi | null {
|
getLastSelectedNode(): INodeUi | null {
|
||||||
const workflowsStore = useWorkflowsStore();
|
const workflowsStore = useWorkflowsStore();
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { NodeConnectionType } from 'n8n-workflow';
|
||||||
import type { BrowserJsPlumbInstance } from '@jsplumb/browser-ui';
|
import type { BrowserJsPlumbInstance } from '@jsplumb/browser-ui';
|
||||||
import { EVENT_CONNECTION_MOUSEOUT, EVENT_CONNECTION_MOUSEOVER } from '@jsplumb/browser-ui';
|
import { EVENT_CONNECTION_MOUSEOUT, EVENT_CONNECTION_MOUSEOVER } from '@jsplumb/browser-ui';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
|
import type { StyleValue } from 'vue';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Canvas constants and functions.
|
Canvas constants and functions.
|
||||||
|
@ -609,7 +610,7 @@ export const getBackgroundStyles = (
|
||||||
scale: number,
|
scale: number,
|
||||||
offsetPosition: XYPosition,
|
offsetPosition: XYPosition,
|
||||||
executionPreview: boolean,
|
executionPreview: boolean,
|
||||||
) => {
|
): StyleValue => {
|
||||||
const squareSize = GRID_SIZE * scale;
|
const squareSize = GRID_SIZE * scale;
|
||||||
const dotSize = 1 * scale;
|
const dotSize = 1 * scale;
|
||||||
const dotPosition = (GRID_SIZE / 2) * scale;
|
const dotPosition = (GRID_SIZE / 2) * scale;
|
||||||
|
@ -623,7 +624,7 @@ export const getBackgroundStyles = (
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const styles: object = {
|
const styles: StyleValue = {
|
||||||
'background-size': `${squareSize}px ${squareSize}px`,
|
'background-size': `${squareSize}px ${squareSize}px`,
|
||||||
'background-position': `left ${offsetPosition[0]}px top ${offsetPosition[1]}px`,
|
'background-position': `left ${offsetPosition[0]}px top ${offsetPosition[1]}px`,
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,10 +22,11 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { type PropType, defineComponent } from 'vue';
|
||||||
|
|
||||||
import Logo from '@/components/Logo.vue';
|
import Logo from '@/components/Logo.vue';
|
||||||
import SSOLogin from '@/components/SSOLogin.vue';
|
import SSOLogin from '@/components/SSOLogin.vue';
|
||||||
|
import type { IFormBoxConfig } from '@/Interface';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'AuthView',
|
name: 'AuthView',
|
||||||
|
@ -34,7 +35,9 @@ export default defineComponent({
|
||||||
SSOLogin,
|
SSOLogin,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
form: {},
|
form: {
|
||||||
|
type: Object as PropType<IFormBoxConfig>,
|
||||||
|
},
|
||||||
formLoading: {
|
formLoading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
|
|
|
@ -18,20 +18,22 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import type { BaseTextKey } from '@/plugins/i18n';
|
||||||
|
import { type PropType, defineComponent } from 'vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ErrorView',
|
name: 'ErrorView',
|
||||||
props: {
|
props: {
|
||||||
messageKey: {
|
messageKey: {
|
||||||
type: String,
|
type: String as PropType<BaseTextKey>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
errorCode: {
|
errorCode: {
|
||||||
type: Number,
|
type: Number,
|
||||||
},
|
},
|
||||||
redirectTextKey: {
|
redirectTextKey: {
|
||||||
type: String,
|
type: String as PropType<BaseTextKey>,
|
||||||
|
required: true,
|
||||||
},
|
},
|
||||||
redirectPage: {
|
redirectPage: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<n8n-heading size="2xlarge">
|
<n8n-heading size="2xlarge">
|
||||||
{{ $locale.baseText('settings.api') }}
|
{{ $locale.baseText('settings.api') }}
|
||||||
<span :style="{ fontSize: 'var(--font-size-s)', color: 'var(--color-text-light)' }">
|
<span :style="{ fontSize: 'var(--font-size-s)', color: 'var(--color-text-light)' }">
|
||||||
({{ $locale.baseText('beta') }})
|
({{ $locale.baseText('generic.beta') }})
|
||||||
</span>
|
</span>
|
||||||
</n8n-heading>
|
</n8n-heading>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<n8n-heading size="2xlarge">{{
|
<n8n-heading size="2xlarge">{{
|
||||||
i18n.baseText('settings.personal.personalSettings')
|
i18n.baseText('settings.personal.personalSettings')
|
||||||
}}</n8n-heading>
|
}}</n8n-heading>
|
||||||
<div :class="$style.user">
|
<div v-if="currentUser" :class="$style.user">
|
||||||
<span :class="$style.username" data-test-id="current-user-name">
|
<span :class="$style.username" data-test-id="current-user-name">
|
||||||
<n8n-text color="text-light">{{ currentUser.fullName }}</n8n-text>
|
<n8n-text color="text-light">{{ currentUser.fullName }}</n8n-text>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -219,7 +219,7 @@ const onSelectSshKeyType = async (sshKeyType: TupleToUnion<SshKeyTypes>) => {
|
||||||
:validation-rules="repoUrlValidationRules"
|
:validation-rules="repoUrlValidationRules"
|
||||||
:disabled="isConnected"
|
:disabled="isConnected"
|
||||||
:placeholder="locale.baseText('settings.sourceControl.repoUrlPlaceholder')"
|
:placeholder="locale.baseText('settings.sourceControl.repoUrlPlaceholder')"
|
||||||
@validate="(value) => onValidate('repoUrl', value)"
|
@validate="(value: boolean) => onValidate('repoUrl', value)"
|
||||||
/>
|
/>
|
||||||
<n8n-button
|
<n8n-button
|
||||||
v-if="isConnected"
|
v-if="isConnected"
|
||||||
|
@ -248,7 +248,7 @@ const onSelectSshKeyType = async (sshKeyType: TupleToUnion<SshKeyTypes>) => {
|
||||||
:validation-rules="keyGeneratorTypeValidationRules"
|
:validation-rules="keyGeneratorTypeValidationRules"
|
||||||
:options="sourceControlStore.sshKeyTypesWithLabel"
|
:options="sourceControlStore.sshKeyTypesWithLabel"
|
||||||
:model-value="sourceControlStore.preferences.keyGeneratorType"
|
:model-value="sourceControlStore.preferences.keyGeneratorType"
|
||||||
@validate="(value) => onValidate('keyGeneratorType', value)"
|
@validate="(value: boolean) => onValidate('keyGeneratorType', value)"
|
||||||
@update:model-value="onSelectSshKeyType"
|
@update:model-value="onSelectSshKeyType"
|
||||||
/>
|
/>
|
||||||
<CopyInput
|
<CopyInput
|
||||||
|
@ -309,7 +309,7 @@ const onSelectSshKeyType = async (sshKeyType: TupleToUnion<SshKeyTypes>) => {
|
||||||
:validation-rules="branchNameValidationRules"
|
:validation-rules="branchNameValidationRules"
|
||||||
:options="branchNameOptions"
|
:options="branchNameOptions"
|
||||||
:model-value="sourceControlStore.preferences.branchName"
|
:model-value="sourceControlStore.preferences.branchName"
|
||||||
@validate="(value) => onValidate('branchName', value)"
|
@validate="(value: boolean) => onValidate('branchName', value)"
|
||||||
@update:model-value="onSelect"
|
@update:model-value="onSelect"
|
||||||
/>
|
/>
|
||||||
<n8n-tooltip placement="top">
|
<n8n-tooltip placement="top">
|
||||||
|
|
|
@ -84,7 +84,7 @@ import { defineComponent } from 'vue';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { EnterpriseEditionFeature, INVITE_USER_MODAL_KEY, VIEWS, ROLE } from '@/constants';
|
import { EnterpriseEditionFeature, INVITE_USER_MODAL_KEY, VIEWS, ROLE } from '@/constants';
|
||||||
|
|
||||||
import type { IUser, IUserListAction, InvitableRoleName } from '@/Interface';
|
import type { IRole, IUser, IUserListAction, InvitableRoleName } from '@/Interface';
|
||||||
import { useToast } from '@/composables/useToast';
|
import { useToast } from '@/composables/useToast';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { useSettingsStore } from '@/stores/settings.store';
|
import { useSettingsStore } from '@/stores/settings.store';
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import type { Route } from 'vue-router';
|
import type { RouteLocationPathRaw } from 'vue-router';
|
||||||
|
|
||||||
import { VIEWS } from '@/constants';
|
import { VIEWS } from '@/constants';
|
||||||
import SettingsSidebar from '@/components/SettingsSidebar.vue';
|
import SettingsSidebar from '@/components/SettingsSidebar.vue';
|
||||||
|
@ -32,7 +32,7 @@ const SettingsView = defineComponent({
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
previousRoute: null as Route | null,
|
previousRoute: null as RouteLocationPathRaw | null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -101,9 +101,9 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useUIStore, useUsersStore),
|
...mapStores(useUIStore, useUsersStore),
|
||||||
inviteMessage(): null | string {
|
inviteMessage(): string {
|
||||||
if (!this.inviter) {
|
if (!this.inviter) {
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.$locale.baseText('settings.signup.signUpInviterInfo', {
|
return this.$locale.baseText('settings.signup.signUpInviterInfo', {
|
||||||
|
|
|
@ -53,15 +53,18 @@ const canRender = ref(true);
|
||||||
const isListLoading = ref(true);
|
const isListLoading = ref(true);
|
||||||
const requestNumberOfItems = ref(20);
|
const requestNumberOfItems = ref(20);
|
||||||
const lastReceivedItemsLength = ref(0);
|
const lastReceivedItemsLength = ref(0);
|
||||||
const editorRoute = computed(() => ({
|
|
||||||
name: VIEWS.WORKFLOW,
|
|
||||||
params: {
|
|
||||||
name: route.params.workflowId,
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
const activeWorkflow = ref<IWorkflowDb | null>(null);
|
const activeWorkflow = ref<IWorkflowDb | null>(null);
|
||||||
const workflowHistory = ref<WorkflowHistory[]>([]);
|
const workflowHistory = ref<WorkflowHistory[]>([]);
|
||||||
const activeWorkflowVersion = ref<WorkflowVersion | null>(null);
|
const activeWorkflowVersion = ref<WorkflowVersion | null>(null);
|
||||||
|
|
||||||
|
const workflowId = computed(() => normalizeSingleRouteParam('workflowId'));
|
||||||
|
const versionId = computed(() => normalizeSingleRouteParam('versionId'));
|
||||||
|
const editorRoute = computed(() => ({
|
||||||
|
name: VIEWS.WORKFLOW,
|
||||||
|
params: {
|
||||||
|
name: workflowId.value,
|
||||||
|
},
|
||||||
|
}));
|
||||||
const actions = computed<UserAction[]>(() =>
|
const actions = computed<UserAction[]>(() =>
|
||||||
workflowHistoryActionTypes.map((value) => ({
|
workflowHistoryActionTypes.map((value) => ({
|
||||||
label: i18n.baseText(`workflowHistory.item.actions.${value}`),
|
label: i18n.baseText(`workflowHistory.item.actions.${value}`),
|
||||||
|
@ -70,23 +73,18 @@ const actions = computed<UserAction[]>(() =>
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
const isFirstItemShown = computed(
|
const isFirstItemShown = computed(() => workflowHistory.value[0]?.versionId === versionId.value);
|
||||||
() => workflowHistory.value[0]?.versionId === route.params.versionId,
|
|
||||||
);
|
|
||||||
const evaluatedPruneTime = computed(() => Math.floor(workflowHistoryStore.evaluatedPruneTime / 24));
|
const evaluatedPruneTime = computed(() => Math.floor(workflowHistoryStore.evaluatedPruneTime / 24));
|
||||||
|
|
||||||
const sendTelemetry = (event: string) => {
|
const sendTelemetry = (event: string) => {
|
||||||
telemetry.track(event, {
|
telemetry.track(event, {
|
||||||
instance_id: useRootStore().instanceId,
|
instance_id: useRootStore().instanceId,
|
||||||
workflow_id: route.params.workflowId,
|
workflow_id: workflowId.value,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadMore = async (queryParams: WorkflowHistoryRequestParams) => {
|
const loadMore = async (queryParams: WorkflowHistoryRequestParams) => {
|
||||||
const history = await workflowHistoryStore.getWorkflowHistory(
|
const history = await workflowHistoryStore.getWorkflowHistory(workflowId.value, queryParams);
|
||||||
route.params.workflowId,
|
|
||||||
queryParams,
|
|
||||||
);
|
|
||||||
lastReceivedItemsLength.value = history.length;
|
lastReceivedItemsLength.value = history.length;
|
||||||
workflowHistory.value = workflowHistory.value.concat(history);
|
workflowHistory.value = workflowHistory.value.concat(history);
|
||||||
};
|
};
|
||||||
|
@ -95,17 +93,17 @@ onBeforeMount(async () => {
|
||||||
sendTelemetry('User opened workflow history');
|
sendTelemetry('User opened workflow history');
|
||||||
try {
|
try {
|
||||||
const [workflow] = await Promise.all([
|
const [workflow] = await Promise.all([
|
||||||
workflowsStore.fetchWorkflow(route.params.workflowId),
|
workflowsStore.fetchWorkflow(workflowId.value),
|
||||||
loadMore({ take: requestNumberOfItems.value }),
|
loadMore({ take: requestNumberOfItems.value }),
|
||||||
]);
|
]);
|
||||||
activeWorkflow.value = workflow;
|
activeWorkflow.value = workflow;
|
||||||
isListLoading.value = false;
|
isListLoading.value = false;
|
||||||
|
|
||||||
if (!route.params.versionId && workflowHistory.value.length) {
|
if (!versionId.value && workflowHistory.value.length) {
|
||||||
await router.replace({
|
await router.replace({
|
||||||
name: VIEWS.WORKFLOW_HISTORY,
|
name: VIEWS.WORKFLOW_HISTORY,
|
||||||
params: {
|
params: {
|
||||||
workflowId: route.params.workflowId,
|
workflowId: workflowId.value,
|
||||||
versionId: workflowHistory.value[0].versionId,
|
versionId: workflowHistory.value[0].versionId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -116,11 +114,17 @@ onBeforeMount(async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const normalizeSingleRouteParam = (name: string): string => {
|
||||||
|
const param = route.params[name];
|
||||||
|
if (typeof param === 'string') return param;
|
||||||
|
return param?.[0] ?? '';
|
||||||
|
};
|
||||||
|
|
||||||
const openInNewTab = (id: WorkflowVersionId) => {
|
const openInNewTab = (id: WorkflowVersionId) => {
|
||||||
const { href } = router.resolve({
|
const { href } = router.resolve({
|
||||||
name: VIEWS.WORKFLOW_HISTORY,
|
name: VIEWS.WORKFLOW_HISTORY,
|
||||||
params: {
|
params: {
|
||||||
workflowId: route.params.workflowId,
|
workflowId: workflowId.value,
|
||||||
versionId: id,
|
versionId: id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -183,7 +187,7 @@ const cloneWorkflowVersion = async (
|
||||||
data: { formattedCreatedAt: string },
|
data: { formattedCreatedAt: string },
|
||||||
) => {
|
) => {
|
||||||
const clonedWorkflow = await workflowHistoryStore.cloneIntoNewWorkflow(
|
const clonedWorkflow = await workflowHistoryStore.cloneIntoNewWorkflow(
|
||||||
route.params.workflowId,
|
workflowId.value,
|
||||||
id,
|
id,
|
||||||
data,
|
data,
|
||||||
);
|
);
|
||||||
|
@ -210,17 +214,17 @@ const restoreWorkflowVersion = async (
|
||||||
id: WorkflowVersionId,
|
id: WorkflowVersionId,
|
||||||
data: { formattedCreatedAt: string },
|
data: { formattedCreatedAt: string },
|
||||||
) => {
|
) => {
|
||||||
const workflow = await workflowsStore.fetchWorkflow(route.params.workflowId);
|
const workflow = await workflowsStore.fetchWorkflow(workflowId.value);
|
||||||
const modalAction = await openRestorationModal(workflow.active, data.formattedCreatedAt);
|
const modalAction = await openRestorationModal(workflow.active, data.formattedCreatedAt);
|
||||||
if (modalAction === WorkflowHistoryVersionRestoreModalActions.cancel) {
|
if (modalAction === WorkflowHistoryVersionRestoreModalActions.cancel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
activeWorkflow.value = await workflowHistoryStore.restoreWorkflow(
|
activeWorkflow.value = await workflowHistoryStore.restoreWorkflow(
|
||||||
route.params.workflowId,
|
workflowId.value,
|
||||||
id,
|
id,
|
||||||
modalAction === WorkflowHistoryVersionRestoreModalActions.deactivateAndRestore,
|
modalAction === WorkflowHistoryVersionRestoreModalActions.deactivateAndRestore,
|
||||||
);
|
);
|
||||||
const history = await workflowHistoryStore.getWorkflowHistory(route.params.workflowId, {
|
const history = await workflowHistoryStore.getWorkflowHistory(workflowId.value, {
|
||||||
take: 1,
|
take: 1,
|
||||||
});
|
});
|
||||||
workflowHistory.value = history.concat(workflowHistory.value);
|
workflowHistory.value = history.concat(workflowHistory.value);
|
||||||
|
@ -246,7 +250,7 @@ const onAction = async ({
|
||||||
sendTelemetry('User opened version in new tab');
|
sendTelemetry('User opened version in new tab');
|
||||||
break;
|
break;
|
||||||
case WORKFLOW_HISTORY_ACTIONS.DOWNLOAD:
|
case WORKFLOW_HISTORY_ACTIONS.DOWNLOAD:
|
||||||
await workflowHistoryStore.downloadVersion(route.params.workflowId, id, data);
|
await workflowHistoryStore.downloadVersion(workflowId.value, id, data);
|
||||||
sendTelemetry('User downloaded version');
|
sendTelemetry('User downloaded version');
|
||||||
break;
|
break;
|
||||||
case WORKFLOW_HISTORY_ACTIONS.CLONE:
|
case WORKFLOW_HISTORY_ACTIONS.CLONE:
|
||||||
|
@ -278,7 +282,7 @@ const onPreview = async ({ event, id }: { event: MouseEvent; id: WorkflowVersion
|
||||||
await router.push({
|
await router.push({
|
||||||
name: VIEWS.WORKFLOW_HISTORY,
|
name: VIEWS.WORKFLOW_HISTORY,
|
||||||
params: {
|
params: {
|
||||||
workflowId: route.params.workflowId,
|
workflowId: workflowId.value,
|
||||||
versionId: id,
|
versionId: id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -290,24 +294,24 @@ const onUpgrade = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
watchEffect(async () => {
|
watchEffect(async () => {
|
||||||
if (!route.params.versionId) {
|
if (!versionId.value) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
activeWorkflowVersion.value = await workflowHistoryStore.getWorkflowVersion(
|
activeWorkflowVersion.value = await workflowHistoryStore.getWorkflowVersion(
|
||||||
route.params.workflowId,
|
workflowId.value,
|
||||||
route.params.versionId,
|
versionId.value,
|
||||||
);
|
);
|
||||||
sendTelemetry('User selected version');
|
sendTelemetry('User selected version');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toast.showError(
|
toast.showError(
|
||||||
new Error(`${error.message} "${route.params.versionId}" `),
|
new Error(`${error.message} "${versionId.value}" `),
|
||||||
i18n.baseText('workflowHistory.title'),
|
i18n.baseText('workflowHistory.title'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
activeWorkflow.value = await workflowsStore.fetchWorkflow(route.params.workflowId);
|
activeWorkflow.value = await workflowsStore.fetchWorkflow(workflowId.value);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
canRender.value = false;
|
canRender.value = false;
|
||||||
toast.showError(error, i18n.baseText('workflowHistory.title'));
|
toast.showError(error, i18n.baseText('workflowHistory.title'));
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { useRoute, useRouter } from 'vue-router';
|
||||||
|
|
||||||
const loadingService = useLoadingService();
|
const loadingService = useLoadingService();
|
||||||
const templateStore = useTemplatesStore();
|
const templateStore = useTemplatesStore();
|
||||||
const workfowStore = useWorkflowsStore();
|
const workflowsStore = useWorkflowsStore();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
|
@ -26,7 +26,7 @@ const openWorkflowTemplate = async (templateId: string) => {
|
||||||
interpolate: { name: template.name },
|
interpolate: { name: template.name },
|
||||||
});
|
});
|
||||||
|
|
||||||
const workflow = await workfowStore.createNewWorkflow({
|
const workflow = await workflowsStore.createNewWorkflow({
|
||||||
name,
|
name,
|
||||||
connections: template.workflow.connections,
|
connections: template.workflow.connections,
|
||||||
nodes: template.workflow.nodes,
|
nodes: template.workflow.nodes,
|
||||||
|
|
|
@ -67,12 +67,11 @@
|
||||||
<div class="text-center mt-s">
|
<div class="text-center mt-s">
|
||||||
<n8n-heading tag="h2" size="xlarge" class="mb-2xs">
|
<n8n-heading tag="h2" size="xlarge" class="mb-2xs">
|
||||||
{{
|
{{
|
||||||
$locale.baseText(
|
currentUser.firstName
|
||||||
currentUser.firstName
|
? $locale.baseText('workflows.empty.heading', {
|
||||||
? 'workflows.empty.heading'
|
interpolate: { name: currentUser.firstName },
|
||||||
: 'workflows.empty.heading.userNotSetup',
|
})
|
||||||
{ interpolate: { name: currentUser.firstName } },
|
: $locale.baseText('workflows.empty.heading.userNotSetup')
|
||||||
)
|
|
||||||
}}
|
}}
|
||||||
</n8n-heading>
|
</n8n-heading>
|
||||||
<n8n-text size="large" color="text-base">
|
<n8n-text size="large" color="text-base">
|
||||||
|
@ -178,13 +177,13 @@ import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||||
import { useTagsStore } from '@/stores/tags.store';
|
import { useTagsStore } from '@/stores/tags.store';
|
||||||
import { useProjectsStore } from '@/features/projects/projects.store';
|
import { useProjectsStore } from '@/features/projects/projects.store';
|
||||||
import ProjectTabs from '@/features/projects/components/ProjectTabs.vue';
|
import ProjectTabs from '@/features/projects/components/ProjectTabs.vue';
|
||||||
|
import { useTemplatesStore } from '@/stores/templates.store';
|
||||||
|
|
||||||
type IResourcesListLayoutInstance = InstanceType<typeof ResourcesListLayout>;
|
type IResourcesListLayoutInstance = InstanceType<typeof ResourcesListLayout>;
|
||||||
|
|
||||||
interface Filters {
|
interface Filters {
|
||||||
search: string;
|
search: string;
|
||||||
ownedBy: string;
|
homeProject: string;
|
||||||
sharedWith: string;
|
|
||||||
status: string | boolean;
|
status: string | boolean;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
}
|
}
|
||||||
|
@ -210,9 +209,9 @@ const WorkflowsView = defineComponent({
|
||||||
filters: {
|
filters: {
|
||||||
search: '',
|
search: '',
|
||||||
homeProject: '',
|
homeProject: '',
|
||||||
status: StatusFilter.ALL as string | boolean,
|
status: StatusFilter.ALL,
|
||||||
tags: [] as string[],
|
tags: [],
|
||||||
},
|
} as Filters,
|
||||||
sourceControlStoreUnsubscribe: () => {},
|
sourceControlStoreUnsubscribe: () => {},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -225,6 +224,7 @@ const WorkflowsView = defineComponent({
|
||||||
useSourceControlStore,
|
useSourceControlStore,
|
||||||
useTagsStore,
|
useTagsStore,
|
||||||
useProjectsStore,
|
useProjectsStore,
|
||||||
|
useTemplatesStore,
|
||||||
),
|
),
|
||||||
readOnlyEnv(): boolean {
|
readOnlyEnv(): boolean {
|
||||||
return this.sourceControlStore.preferences.branchReadOnly;
|
return this.sourceControlStore.preferences.branchReadOnly;
|
||||||
|
@ -258,10 +258,18 @@ const WorkflowsView = defineComponent({
|
||||||
return this.uiStore.suggestedTemplates;
|
return this.uiStore.suggestedTemplates;
|
||||||
},
|
},
|
||||||
userRole() {
|
userRole() {
|
||||||
const userRole: string | undefined =
|
const role = this.usersStore.currentUserCloudInfo?.role;
|
||||||
this.usersStore.currentUserCloudInfo?.role ??
|
|
||||||
this.usersStore.currentUser?.personalizationAnswers?.role;
|
if (role) {
|
||||||
return userRole;
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
const answers = this.usersStore.currentUser?.personalizationAnswers;
|
||||||
|
if (answers && 'role' in answers) {
|
||||||
|
return answers.role;
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
},
|
},
|
||||||
isSalesUser() {
|
isSalesUser() {
|
||||||
if (!this.userRole) {
|
if (!this.userRole) {
|
||||||
|
|
Loading…
Reference in a new issue