mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
refactor: Migrate genericHelpers
mixin to composable (#8220)
## Summary - Moved out canvas loading handling to canvas store - Tag editable routes via meta to remove router dependency from generic helpers - Replace all occurrences of `genericHelpers` mixin with composable and audit usage - Moved out `isRedirectSafe` and `getRedirectQueryParameter` out of genericHelpers to remove dependency on router Removing the router dependency is important, because `useRouter` and `useRoute` compostables are only available if called from component instance. So if composable is nested within another composable, we wouldn't be able to use these. In this case we'd always need to inject the router and pass it through several composables. That's why I moved the `readonly` logic to router meta and `isRedirectSafe` and `getRedirectQueryParameter` out as they were only used in a single component. --------- Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
This commit is contained in:
parent
f53c482939
commit
184ed8e17d
|
@ -17,14 +17,13 @@ import { BREAKPOINT_SM, BREAKPOINT_MD, BREAKPOINT_LG, BREAKPOINT_XL } from '@/co
|
||||||
* xl >= 1920
|
* xl >= 1920
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { debounceHelper } from '@/mixins/debounce';
|
import { debounceHelper } from '@/mixins/debounce';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { getBannerRowHeight } from '@/utils/htmlUtils';
|
import { getBannerRowHeight } from '@/utils/htmlUtils';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'BreakpointsObserver',
|
name: 'BreakpointsObserver',
|
||||||
mixins: [genericHelpers, debounceHelper],
|
mixins: [debounceHelper],
|
||||||
props: ['valueXS', 'valueXL', 'valueLG', 'valueMD', 'valueSM', 'valueDefault'],
|
props: ['valueXS', 'valueXL', 'valueLG', 'valueMD', 'valueSM', 'valueDefault'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -12,11 +12,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Card',
|
name: 'Card',
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
loading: {
|
loading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -6,11 +6,9 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'ExecutionTime',
|
name: 'ExecutionTime',
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: ['startTime'],
|
props: ['startTime'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -24,7 +22,7 @@ export default defineComponent({
|
||||||
return '...';
|
return '...';
|
||||||
}
|
}
|
||||||
const msPassed = this.nowTime - new Date(this.startTime).getTime();
|
const msPassed = this.nowTime - new Date(this.startTime).getTime();
|
||||||
return this.displayTimer(msPassed);
|
return this.$locale.displayTimer(msPassed);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -46,9 +44,3 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
// .data-display-wrapper {
|
|
||||||
|
|
||||||
// }
|
|
||||||
</style>
|
|
||||||
|
|
|
@ -107,7 +107,7 @@
|
||||||
v-else-if="execution.stoppedAt !== null && execution.stoppedAt !== undefined"
|
v-else-if="execution.stoppedAt !== null && execution.stoppedAt !== undefined"
|
||||||
>
|
>
|
||||||
{{
|
{{
|
||||||
displayTimer(
|
i18n.displayTimer(
|
||||||
new Date(execution.stoppedAt).getTime() -
|
new Date(execution.stoppedAt).getTime() -
|
||||||
new Date(execution.startedAt).getTime(),
|
new Date(execution.startedAt).getTime(),
|
||||||
true,
|
true,
|
||||||
|
@ -288,7 +288,6 @@ import { mapStores } from 'pinia';
|
||||||
import ExecutionTime from '@/components/ExecutionTime.vue';
|
import ExecutionTime from '@/components/ExecutionTime.vue';
|
||||||
import ExecutionFilter from '@/components/ExecutionFilter.vue';
|
import ExecutionFilter from '@/components/ExecutionFilter.vue';
|
||||||
import { MODAL_CONFIRM, VIEWS, WAIT_TIME_UNLIMITED } from '@/constants';
|
import { MODAL_CONFIRM, VIEWS, WAIT_TIME_UNLIMITED } from '@/constants';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { executionHelpers } from '@/mixins/executionsHelpers';
|
import { executionHelpers } from '@/mixins/executionsHelpers';
|
||||||
import { useToast } from '@/composables/useToast';
|
import { useToast } from '@/composables/useToast';
|
||||||
import { useMessage } from '@/composables/useMessage';
|
import { useMessage } from '@/composables/useMessage';
|
||||||
|
@ -318,7 +317,7 @@ export default defineComponent({
|
||||||
ExecutionTime,
|
ExecutionTime,
|
||||||
ExecutionFilter,
|
ExecutionFilter,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers, executionHelpers],
|
mixins: [executionHelpers],
|
||||||
props: {
|
props: {
|
||||||
autoRefreshEnabled: {
|
autoRefreshEnabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
<ExpressionEditorModalInput
|
<ExpressionEditorModalInput
|
||||||
ref="inputFieldExpression"
|
ref="inputFieldExpression"
|
||||||
:model-value="modelValue"
|
:model-value="modelValue"
|
||||||
:is-read-only="isReadOnlyRoute"
|
:is-read-only="isReadOnly"
|
||||||
:path="path"
|
:path="path"
|
||||||
:class="{ 'ph-no-capture': redactValues }"
|
:class="{ 'ph-no-capture': redactValues }"
|
||||||
data-test-id="expression-modal-input"
|
data-test-id="expression-modal-input"
|
||||||
|
@ -87,8 +87,6 @@ import VariableSelector from '@/components/VariableSelector.vue';
|
||||||
|
|
||||||
import type { IVariableItemSelected } from '@/Interface';
|
import type { IVariableItemSelected } from '@/Interface';
|
||||||
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
|
|
||||||
import { EXPRESSIONS_DOCS_URL } from '@/constants';
|
import { EXPRESSIONS_DOCS_URL } from '@/constants';
|
||||||
|
|
||||||
import { debounceHelper } from '@/mixins/debounce';
|
import { debounceHelper } from '@/mixins/debounce';
|
||||||
|
@ -106,10 +104,40 @@ export default defineComponent({
|
||||||
ExpressionEditorModalOutput,
|
ExpressionEditorModalOutput,
|
||||||
VariableSelector,
|
VariableSelector,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers, debounceHelper],
|
mixins: [debounceHelper],
|
||||||
props: ['dialogVisible', 'parameter', 'path', 'modelValue', 'eventSource', 'redactValues'],
|
props: {
|
||||||
|
dialogVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
parameter: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
eventSource: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
redactValues: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
isReadOnly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const externalHooks = useExternalHooks();
|
const externalHooks = useExternalHooks();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
externalHooks,
|
externalHooks,
|
||||||
};
|
};
|
||||||
|
|
|
@ -183,8 +183,8 @@ import type { IPermissions } from '@/permissions';
|
||||||
import { getWorkflowPermissions } from '@/permissions';
|
import { getWorkflowPermissions } from '@/permissions';
|
||||||
import { createEventBus } from 'n8n-design-system/utils';
|
import { createEventBus } from 'n8n-design-system/utils';
|
||||||
import { nodeViewEventBus } from '@/event-bus';
|
import { nodeViewEventBus } from '@/event-bus';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { hasPermission } from '@/rbac/permissions';
|
import { hasPermission } from '@/rbac/permissions';
|
||||||
|
import { useCanvasStore } from '@/stores/canvas.store';
|
||||||
|
|
||||||
const hasChanged = (prev: string[], curr: string[]) => {
|
const hasChanged = (prev: string[], curr: string[]) => {
|
||||||
if (prev.length !== curr.length) {
|
if (prev.length !== curr.length) {
|
||||||
|
@ -208,7 +208,7 @@ export default defineComponent({
|
||||||
BreakpointsObserver,
|
BreakpointsObserver,
|
||||||
CollaborationPane,
|
CollaborationPane,
|
||||||
},
|
},
|
||||||
mixins: [workflowHelpers, genericHelpers],
|
mixins: [workflowHelpers],
|
||||||
props: {
|
props: {
|
||||||
readOnly: {
|
readOnly: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
@ -244,6 +244,7 @@ export default defineComponent({
|
||||||
useWorkflowsStore,
|
useWorkflowsStore,
|
||||||
useUsersStore,
|
useUsersStore,
|
||||||
useSourceControlStore,
|
useSourceControlStore,
|
||||||
|
useCanvasStore,
|
||||||
),
|
),
|
||||||
currentUser(): IUser | null {
|
currentUser(): IUser | null {
|
||||||
return this.usersStore.currentUser;
|
return this.usersStore.currentUser;
|
||||||
|
@ -586,7 +587,7 @@ export default defineComponent({
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WORKFLOW_MENU_ACTIONS.PUSH: {
|
case WORKFLOW_MENU_ACTIONS.PUSH: {
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
try {
|
try {
|
||||||
await this.onSaveButtonClick();
|
await this.onSaveButtonClick();
|
||||||
|
|
||||||
|
@ -610,7 +611,7 @@ export default defineComponent({
|
||||||
this.showError(error, this.$locale.baseText('error'));
|
this.showError(error, this.$locale.baseText('error'));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -104,11 +104,7 @@
|
||||||
import type { CloudPlanAndUsageData, IExecutionResponse, IMenuItem, IVersion } from '@/Interface';
|
import type { CloudPlanAndUsageData, IExecutionResponse, IMenuItem, IVersion } from '@/Interface';
|
||||||
import GiftNotificationIcon from './GiftNotificationIcon.vue';
|
import GiftNotificationIcon from './GiftNotificationIcon.vue';
|
||||||
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { useMessage } from '@/composables/useMessage';
|
import { useMessage } from '@/composables/useMessage';
|
||||||
import { workflowHelpers } from '@/mixins/workflowHelpers';
|
|
||||||
import { workflowRun } from '@/mixins/workflowRun';
|
|
||||||
|
|
||||||
import { ABOUT_MODAL_KEY, VERSIONS_MODAL_KEY, VIEWS } from '@/constants';
|
import { ABOUT_MODAL_KEY, VERSIONS_MODAL_KEY, VIEWS } from '@/constants';
|
||||||
import { userHelpers } from '@/mixins/userHelpers';
|
import { userHelpers } from '@/mixins/userHelpers';
|
||||||
import { debounceHelper } from '@/mixins/debounce';
|
import { debounceHelper } from '@/mixins/debounce';
|
||||||
|
@ -135,15 +131,13 @@ export default defineComponent({
|
||||||
ExecutionsUsage,
|
ExecutionsUsage,
|
||||||
MainSidebarSourceControl,
|
MainSidebarSourceControl,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers, workflowHelpers, workflowRun, userHelpers, debounceHelper],
|
mixins: [userHelpers, debounceHelper],
|
||||||
setup(props, ctx) {
|
setup(props, ctx) {
|
||||||
const externalHooks = useExternalHooks();
|
const externalHooks = useExternalHooks();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
externalHooks,
|
externalHooks,
|
||||||
...useMessage(),
|
...useMessage(),
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
||||||
...workflowRun.setup?.(props, ctx),
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -418,31 +412,31 @@ export default defineComponent({
|
||||||
async handleSelect(key: string) {
|
async handleSelect(key: string) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'workflows': {
|
case 'workflows': {
|
||||||
if (this.$router.currentRoute.name !== VIEWS.WORKFLOWS) {
|
if (this.$router.currentRoute.value.name !== VIEWS.WORKFLOWS) {
|
||||||
this.goToRoute({ name: VIEWS.WORKFLOWS });
|
this.goToRoute({ name: VIEWS.WORKFLOWS });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'templates': {
|
case 'templates': {
|
||||||
if (this.$router.currentRoute.name !== VIEWS.TEMPLATES) {
|
if (this.$router.currentRoute.value.name !== VIEWS.TEMPLATES) {
|
||||||
this.goToRoute({ name: VIEWS.TEMPLATES });
|
this.goToRoute({ name: VIEWS.TEMPLATES });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'credentials': {
|
case 'credentials': {
|
||||||
if (this.$router.currentRoute.name !== VIEWS.CREDENTIALS) {
|
if (this.$router.currentRoute.value.name !== VIEWS.CREDENTIALS) {
|
||||||
this.goToRoute({ name: VIEWS.CREDENTIALS });
|
this.goToRoute({ name: VIEWS.CREDENTIALS });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'variables': {
|
case 'variables': {
|
||||||
if (this.$router.currentRoute.name !== VIEWS.VARIABLES) {
|
if (this.$router.currentRoute.value.name !== VIEWS.VARIABLES) {
|
||||||
this.goToRoute({ name: VIEWS.VARIABLES });
|
this.goToRoute({ name: VIEWS.VARIABLES });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'executions': {
|
case 'executions': {
|
||||||
if (this.$router.currentRoute.name !== VIEWS.EXECUTIONS) {
|
if (this.$router.currentRoute.value.name !== VIEWS.EXECUTIONS) {
|
||||||
this.goToRoute({ name: VIEWS.EXECUTIONS });
|
this.goToRoute({ name: VIEWS.EXECUTIONS });
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -451,7 +445,7 @@ export default defineComponent({
|
||||||
const defaultRoute = this.findFirstAccessibleSettingsRoute();
|
const defaultRoute = this.findFirstAccessibleSettingsRoute();
|
||||||
if (defaultRoute) {
|
if (defaultRoute) {
|
||||||
const route = this.$router.resolve({ name: defaultRoute });
|
const route = this.$router.resolve({ name: defaultRoute });
|
||||||
if (this.$router.currentRoute.name !== defaultRoute) {
|
if (this.$router.currentRoute.value.name !== defaultRoute) {
|
||||||
this.goToRoute(route.path);
|
this.goToRoute(route.path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -463,7 +457,7 @@ export default defineComponent({
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'cloud-admin': {
|
case 'cloud-admin': {
|
||||||
this.cloudPlanStore.redirectToDashboard();
|
void this.cloudPlanStore.redirectToDashboard();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'quickstart':
|
case 'quickstart':
|
||||||
|
@ -494,7 +488,7 @@ export default defineComponent({
|
||||||
|
|
||||||
let defaultSettingsRoute = null;
|
let defaultSettingsRoute = null;
|
||||||
for (const route of settingsRoutes) {
|
for (const route of settingsRoutes) {
|
||||||
if (this.canUserAccessRouteByName(route)) {
|
if (this.canUserAccessRouteByName(route.toString())) {
|
||||||
defaultSettingsRoute = route;
|
defaultSettingsRoute = route;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
color="text-dark"
|
color="text-dark"
|
||||||
data-test-id="credentials-label"
|
data-test-id="credentials-label"
|
||||||
>
|
>
|
||||||
<div v-if="readonly || isReadOnlyRoute">
|
<div v-if="readonly">
|
||||||
<n8n-input
|
<n8n-input
|
||||||
:model-value="getSelectedName(credentialTypeDescription.name)"
|
:model-value="getSelectedName(credentialTypeDescription.name)"
|
||||||
disabled
|
disabled
|
||||||
|
@ -117,7 +117,6 @@ import type {
|
||||||
INodeTypeDescription,
|
INodeTypeDescription,
|
||||||
} from 'n8n-workflow';
|
} from 'n8n-workflow';
|
||||||
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||||
import { useToast } from '@/composables/useToast';
|
import { useToast } from '@/composables/useToast';
|
||||||
|
|
||||||
|
@ -147,7 +146,6 @@ export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
TitledList,
|
TitledList,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
readonly: {
|
readonly: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import NodeIcon from '@/components/NodeIcon.vue';
|
import NodeIcon from '@/components/NodeIcon.vue';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import type { ITemplatesNode } from '@/Interface';
|
import type { ITemplatesNode } from '@/Interface';
|
||||||
import { filterTemplateNodes } from '@/utils/nodeTypesUtils';
|
import { filterTemplateNodes } from '@/utils/nodeTypesUtils';
|
||||||
|
|
||||||
|
@ -24,7 +23,6 @@ export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
NodeIcon,
|
NodeIcon,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
nodes: {
|
nodes: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<RunData
|
<RunData
|
||||||
|
ref="runData"
|
||||||
:node="node"
|
:node="node"
|
||||||
:run-index="runIndex"
|
:run-index="runIndex"
|
||||||
:linked-runs="linkedRuns"
|
:linked-runs="linkedRuns"
|
||||||
|
@ -10,7 +11,6 @@
|
||||||
:executing-message="$locale.baseText('ndv.output.executing')"
|
:executing-message="$locale.baseText('ndv.output.executing')"
|
||||||
:session-id="sessionId"
|
:session-id="sessionId"
|
||||||
:block-u-i="blockUI"
|
:block-u-i="blockUI"
|
||||||
ref="runData"
|
|
||||||
:is-production-execution-preview="isProductionExecutionPreview"
|
:is-production-execution-preview="isProductionExecutionPreview"
|
||||||
:is-pane-active="isPaneActive"
|
:is-pane-active="isPaneActive"
|
||||||
pane-type="output"
|
pane-type="output"
|
||||||
|
|
|
@ -42,8 +42,8 @@
|
||||||
/>
|
/>
|
||||||
<ExpressionParameterInput
|
<ExpressionParameterInput
|
||||||
v-else-if="isValueExpression || forceShowExpression"
|
v-else-if="isValueExpression || forceShowExpression"
|
||||||
:model-value="expressionDisplayValue"
|
|
||||||
ref="inputField"
|
ref="inputField"
|
||||||
|
:model-value="expressionDisplayValue"
|
||||||
:title="displayTitle"
|
:title="displayTitle"
|
||||||
:is-read-only="isReadOnly"
|
:is-read-only="isReadOnly"
|
||||||
:is-single-line="isSingleLine"
|
:is-single-line="isSingleLine"
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
>
|
>
|
||||||
<ResourceLocatorDropdown
|
<ResourceLocatorDropdown
|
||||||
ref="dropdown"
|
ref="dropdown"
|
||||||
|
v-on-click-outside="hideResourceDropdown"
|
||||||
:model-value="modelValue ? modelValue.value : ''"
|
:model-value="modelValue ? modelValue.value : ''"
|
||||||
:show="resourceDropdownVisible"
|
:show="resourceDropdownVisible"
|
||||||
v-on-click-outside="hideResourceDropdown"
|
|
||||||
:filterable="isSearchable"
|
:filterable="isSearchable"
|
||||||
:filter-required="requiresSearchFilter"
|
:filter-required="requiresSearchFilter"
|
||||||
:resources="currentQueryResults"
|
:resources="currentQueryResults"
|
||||||
|
|
|
@ -607,7 +607,6 @@ import BinaryDataDisplay from '@/components/BinaryDataDisplay.vue';
|
||||||
import NodeErrorView from '@/components/Error/NodeErrorView.vue';
|
import NodeErrorView from '@/components/Error/NodeErrorView.vue';
|
||||||
import JsonEditor from '@/components/JsonEditor/JsonEditor.vue';
|
import JsonEditor from '@/components/JsonEditor/JsonEditor.vue';
|
||||||
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import type { PinDataSource } from '@/composables/usePinnedData';
|
import type { PinDataSource } from '@/composables/usePinnedData';
|
||||||
import { usePinnedData } from '@/composables/usePinnedData';
|
import { usePinnedData } from '@/composables/usePinnedData';
|
||||||
import { dataPinningEventBus } from '@/event-bus';
|
import { dataPinningEventBus } from '@/event-bus';
|
||||||
|
@ -621,6 +620,7 @@ import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||||
import { useToast } from '@/composables/useToast';
|
import { useToast } from '@/composables/useToast';
|
||||||
import { isObject } from 'lodash-es';
|
import { isObject } from 'lodash-es';
|
||||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||||
|
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||||
|
|
||||||
const RunDataTable = defineAsyncComponent(async () => import('@/components/RunDataTable.vue'));
|
const RunDataTable = defineAsyncComponent(async () => import('@/components/RunDataTable.vue'));
|
||||||
const RunDataJson = defineAsyncComponent(async () => import('@/components/RunDataJson.vue'));
|
const RunDataJson = defineAsyncComponent(async () => import('@/components/RunDataJson.vue'));
|
||||||
|
@ -644,7 +644,6 @@ export default defineComponent({
|
||||||
RunDataHtml,
|
RunDataHtml,
|
||||||
RunDataSearch,
|
RunDataSearch,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
node: {
|
node: {
|
||||||
type: Object as PropType<INodeUi>,
|
type: Object as PropType<INodeUi>,
|
||||||
|
@ -759,7 +758,10 @@ export default defineComponent({
|
||||||
this.hidePinDataDiscoveryTooltip();
|
this.hidePinDataDiscoveryTooltip();
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useNodeTypesStore, useNDVStore, useWorkflowsStore),
|
...mapStores(useNodeTypesStore, useNDVStore, useWorkflowsStore, useSourceControlStore),
|
||||||
|
isReadOnlyRoute() {
|
||||||
|
return this.$route?.meta?.readOnlyCanvas === true;
|
||||||
|
},
|
||||||
activeNode(): INodeUi | null {
|
activeNode(): INodeUi | null {
|
||||||
return this.ndvStore.activeNode;
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
|
@ -1402,7 +1404,7 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async downloadJsonData() {
|
async downloadJsonData() {
|
||||||
const fileName = this.node!.name.replace(/[^\w\d]/g, '_');
|
const fileName = this.node.name.replace(/[^\w\d]/g, '_');
|
||||||
const blob = new Blob([JSON.stringify(this.rawInputData, null, 2)], {
|
const blob = new Blob([JSON.stringify(this.rawInputData, null, 2)], {
|
||||||
type: 'application/json',
|
type: 'application/json',
|
||||||
});
|
});
|
||||||
|
@ -1413,7 +1415,7 @@ export default defineComponent({
|
||||||
this.binaryDataDisplayVisible = true;
|
this.binaryDataDisplayVisible = true;
|
||||||
|
|
||||||
this.binaryDataDisplayData = {
|
this.binaryDataDisplayData = {
|
||||||
node: this.node!.name,
|
node: this.node.name,
|
||||||
runIndex: this.runIndex,
|
runIndex: this.runIndex,
|
||||||
outputIndex: this.currentOutputIndex,
|
outputIndex: this.currentOutputIndex,
|
||||||
index,
|
index,
|
||||||
|
|
|
@ -41,7 +41,6 @@ import { mapStores, storeToRefs } from 'pinia';
|
||||||
import jp from 'jsonpath';
|
import jp from 'jsonpath';
|
||||||
import type { INodeUi } from '@/Interface';
|
import type { INodeUi } from '@/Interface';
|
||||||
import type { IDataObject } from 'n8n-workflow';
|
import type { IDataObject } from 'n8n-workflow';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { clearJsonKey, convertPath } from '@/utils/typesUtils';
|
import { clearJsonKey, convertPath } from '@/utils/typesUtils';
|
||||||
import { executionDataToJson } from '@/utils/nodeTypesUtils';
|
import { executionDataToJson } from '@/utils/nodeTypesUtils';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
|
@ -51,6 +50,8 @@ import { useToast } from '@/composables/useToast';
|
||||||
import { useI18n } from '@/composables/useI18n';
|
import { useI18n } from '@/composables/useI18n';
|
||||||
import { nonExistingJsonPath } from '@/constants';
|
import { nonExistingJsonPath } from '@/constants';
|
||||||
import { useClipboard } from '@/composables/useClipboard';
|
import { useClipboard } from '@/composables/useClipboard';
|
||||||
|
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||||
|
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||||
import { usePinnedData } from '@/composables/usePinnedData';
|
import { usePinnedData } from '@/composables/usePinnedData';
|
||||||
|
|
||||||
type JsonPathData = {
|
type JsonPathData = {
|
||||||
|
@ -60,7 +61,6 @@ type JsonPathData = {
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'RunDataJsonActions',
|
name: 'RunDataJsonActions',
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
node: {
|
node: {
|
||||||
type: Object as PropType<INodeUi>,
|
type: Object as PropType<INodeUi>,
|
||||||
|
@ -109,7 +109,10 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useNDVStore, useWorkflowsStore),
|
...mapStores(useNodeTypesStore, useNDVStore, useWorkflowsStore, useSourceControlStore),
|
||||||
|
isReadOnlyRoute() {
|
||||||
|
return this.$route?.meta?.readOnlyCanvas === true;
|
||||||
|
},
|
||||||
activeNode(): INodeUi | null {
|
activeNode(): INodeUi | null {
|
||||||
return this.ndvStore.activeNode;
|
return this.ndvStore.activeNode;
|
||||||
},
|
},
|
||||||
|
|
|
@ -48,7 +48,6 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { filterTemplateNodes } from '@/utils/nodeTypesUtils';
|
import { filterTemplateNodes } from '@/utils/nodeTypesUtils';
|
||||||
import { abbreviateNumber } from '@/utils/typesUtils';
|
import { abbreviateNumber } from '@/utils/typesUtils';
|
||||||
import NodeList from './NodeList.vue';
|
import NodeList from './NodeList.vue';
|
||||||
|
@ -60,7 +59,6 @@ export default defineComponent({
|
||||||
TimeAgo,
|
TimeAgo,
|
||||||
NodeList,
|
NodeList,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
lastItem: {
|
lastItem: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -38,12 +38,10 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import type { ITemplatesCategory } from '@/Interface';
|
import type { ITemplatesCategory } from '@/Interface';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'TemplateFilters',
|
name: 'TemplateFilters',
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
sortOnPopulate: {
|
sortOnPopulate: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import TemplateCard from './TemplateCard.vue';
|
import TemplateCard from './TemplateCard.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -42,7 +41,6 @@ export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
TemplateCard,
|
TemplateCard,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
infiniteScrollEnabled: {
|
infiniteScrollEnabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import Card from '@/components/CollectionWorkflowCard.vue';
|
import Card from '@/components/CollectionWorkflowCard.vue';
|
||||||
import NodeList from '@/components/NodeList.vue';
|
import NodeList from '@/components/NodeList.vue';
|
||||||
|
|
||||||
|
@ -24,7 +23,6 @@ export default defineComponent({
|
||||||
Card,
|
Card,
|
||||||
NodeList,
|
NodeList,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
loading: {
|
loading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -44,8 +44,6 @@ import Card from '@/components/CollectionWorkflowCard.vue';
|
||||||
import TemplatesInfoCard from '@/components/TemplatesInfoCard.vue';
|
import TemplatesInfoCard from '@/components/TemplatesInfoCard.vue';
|
||||||
import { VueAgile } from 'vue-agile';
|
import { VueAgile } from 'vue-agile';
|
||||||
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
|
|
||||||
type SliderRef = InstanceType<typeof VueAgile>;
|
type SliderRef = InstanceType<typeof VueAgile>;
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -55,7 +53,6 @@ export default defineComponent({
|
||||||
TemplatesInfoCard,
|
TemplatesInfoCard,
|
||||||
agile: VueAgile,
|
agile: VueAgile,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
collections: {
|
collections: {
|
||||||
type: Array as PropType<ITemplatesCollection[]>,
|
type: Array as PropType<ITemplatesCollection[]>,
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import PushConnectionTracker from '@/components/PushConnectionTracker.vue';
|
import PushConnectionTracker from '@/components/PushConnectionTracker.vue';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { executionHelpers } from '@/mixins/executionsHelpers';
|
import { executionHelpers } from '@/mixins/executionsHelpers';
|
||||||
import { useI18n } from '@/composables/useI18n';
|
import { useI18n } from '@/composables/useI18n';
|
||||||
import { useToast } from '@/composables/useToast';
|
import { useToast } from '@/composables/useToast';
|
||||||
|
@ -39,7 +38,7 @@ export default defineComponent({
|
||||||
name: 'WorkerList',
|
name: 'WorkerList',
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/naming-convention
|
||||||
components: { PushConnectionTracker, WorkerCard },
|
components: { PushConnectionTracker, WorkerCard },
|
||||||
mixins: [pushConnection, genericHelpers, executionHelpers],
|
mixins: [pushConnection, executionHelpers],
|
||||||
props: {
|
props: {
|
||||||
autoRefreshEnabled: {
|
autoRefreshEnabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -355,7 +355,6 @@
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { useToast } from '@/composables/useToast';
|
import { useToast } from '@/composables/useToast';
|
||||||
import type {
|
import type {
|
||||||
ITimeoutHMS,
|
ITimeoutHMS,
|
||||||
|
@ -383,13 +382,13 @@ import { createEventBus } from 'n8n-design-system/utils';
|
||||||
import type { IPermissions } from '@/permissions';
|
import type { IPermissions } from '@/permissions';
|
||||||
import { getWorkflowPermissions } from '@/permissions';
|
import { getWorkflowPermissions } from '@/permissions';
|
||||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||||
|
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'WorkflowSettings',
|
name: 'WorkflowSettings',
|
||||||
components: {
|
components: {
|
||||||
Modal,
|
Modal,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
setup() {
|
setup() {
|
||||||
const externalHooks = useExternalHooks();
|
const externalHooks = useExternalHooks();
|
||||||
|
|
||||||
|
@ -459,9 +458,13 @@ export default defineComponent({
|
||||||
useRootStore,
|
useRootStore,
|
||||||
useUsersStore,
|
useUsersStore,
|
||||||
useSettingsStore,
|
useSettingsStore,
|
||||||
|
useSourceControlStore,
|
||||||
useWorkflowsStore,
|
useWorkflowsStore,
|
||||||
useWorkflowsEEStore,
|
useWorkflowsEEStore,
|
||||||
),
|
),
|
||||||
|
readOnlyEnv(): boolean {
|
||||||
|
return this.sourceControlStore.preferences.branchReadOnly;
|
||||||
|
},
|
||||||
workflowName(): string {
|
workflowName(): string {
|
||||||
return this.workflowsStore.workflowName;
|
return this.workflowsStore.workflowName;
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,18 +5,18 @@ import { BulkCommand, Command } from '@/models/history';
|
||||||
import { useHistoryStore } from '@/stores/history.store';
|
import { useHistoryStore } from '@/stores/history.store';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
|
|
||||||
import { onMounted, onUnmounted, nextTick, getCurrentInstance } from 'vue';
|
import { onMounted, onUnmounted, nextTick } from 'vue';
|
||||||
import { useDebounceHelper } from './useDebounce';
|
import { useDebounceHelper } from './useDebounce';
|
||||||
import { useDeviceSupport } from 'n8n-design-system/composables/useDeviceSupport';
|
import { useDeviceSupport } from 'n8n-design-system/composables/useDeviceSupport';
|
||||||
import { getNodeViewTab } from '@/utils/canvasUtils';
|
import { getNodeViewTab } from '@/utils/canvasUtils';
|
||||||
import type { Route } from 'vue-router';
|
import type { Route } from 'vue-router';
|
||||||
|
import { useTelemetry } from './useTelemetry';
|
||||||
|
|
||||||
const UNDO_REDO_DEBOUNCE_INTERVAL = 100;
|
const UNDO_REDO_DEBOUNCE_INTERVAL = 100;
|
||||||
const ELEMENT_UI_OVERLAY_SELECTOR = '.el-overlay';
|
const ELEMENT_UI_OVERLAY_SELECTOR = '.el-overlay';
|
||||||
|
|
||||||
export function useHistoryHelper(activeRoute: Route) {
|
export function useHistoryHelper(activeRoute: Route) {
|
||||||
const instance = getCurrentInstance();
|
const telemetry = useTelemetry();
|
||||||
const telemetry = instance?.proxy.$telemetry;
|
|
||||||
|
|
||||||
const ndvStore = useNDVStore();
|
const ndvStore = useNDVStore();
|
||||||
const historyStore = useHistoryStore();
|
const historyStore = useHistoryStore();
|
||||||
|
@ -85,9 +85,9 @@ export function useHistoryHelper(activeRoute: Route) {
|
||||||
|
|
||||||
function trackCommand(command: Undoable, type: 'undo' | 'redo'): void {
|
function trackCommand(command: Undoable, type: 'undo' | 'redo'): void {
|
||||||
if (command instanceof Command) {
|
if (command instanceof Command) {
|
||||||
telemetry?.track(`User hit ${type}`, { commands_length: 1, commands: [command.name] });
|
telemetry.track(`User hit ${type}`, { commands_length: 1, commands: [command.name] });
|
||||||
} else if (command instanceof BulkCommand) {
|
} else if (command instanceof BulkCommand) {
|
||||||
telemetry?.track(`User hit ${type}`, {
|
telemetry.track(`User hit ${type}`, {
|
||||||
commands_length: command.commands.length,
|
commands_length: command.commands.length,
|
||||||
commands: command.commands.map((c) => c.name),
|
commands: command.commands.map((c) => c.name),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ref } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useI18n } from '@/composables/useI18n';
|
import { useI18n } from '@/composables/useI18n';
|
||||||
import { ElLoading as Loading } from 'element-plus';
|
import { ElLoading as Loading } from 'element-plus';
|
||||||
|
|
||||||
|
@ -36,8 +36,11 @@ export function useLoadingService() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isLoading = computed(() => loadingService.value !== null);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loadingService,
|
loadingService,
|
||||||
|
isLoading,
|
||||||
startLoading,
|
startLoading,
|
||||||
setLoadingText,
|
setLoadingText,
|
||||||
stopLoading,
|
stopLoading,
|
||||||
|
|
|
@ -544,7 +544,6 @@ export function useNodeHelpers() {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Is this problematic?
|
|
||||||
let data: ITaskDataConnections | undefined = taskData.data;
|
let data: ITaskDataConnections | undefined = taskData.data;
|
||||||
if (paneType === 'input' && taskData.inputOverride) {
|
if (paneType === 'input' && taskData.inputOverride) {
|
||||||
data = taskData.inputOverride!;
|
data = taskData.inputOverride!;
|
||||||
|
|
|
@ -458,6 +458,8 @@ export const enum VIEWS {
|
||||||
WORKER_VIEW = 'WorkerView',
|
WORKER_VIEW = 'WorkerView',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const EDITABLE_CANVAS_VIEWS = [VIEWS.WORKFLOW, VIEWS.NEW_WORKFLOW, VIEWS.EXECUTION_DEBUG];
|
||||||
|
|
||||||
export const enum FAKE_DOOR_FEATURES {
|
export const enum FAKE_DOOR_FEATURES {
|
||||||
ENVIRONMENTS = 'environments',
|
ENVIRONMENTS = 'environments',
|
||||||
LOGGING = 'logging',
|
LOGGING = 'logging',
|
||||||
|
|
|
@ -2,9 +2,8 @@ import { defineComponent } from 'vue';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import { i18n as locale } from '@/plugins/i18n';
|
import { i18n as locale } from '@/plugins/i18n';
|
||||||
import { genericHelpers } from './genericHelpers';
|
|
||||||
import type { IExecutionsSummary } from 'n8n-workflow';
|
import type { IExecutionsSummary } from 'n8n-workflow';
|
||||||
import { convertToDisplayDateComponents } from '@/utils/formatters/dateFormatter';
|
import { convertToDisplayDate } from '@/utils/formatters/dateFormatter';
|
||||||
|
|
||||||
export interface IExecutionUIData {
|
export interface IExecutionUIData {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -14,7 +13,6 @@ export interface IExecutionUIData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const executionHelpers = defineComponent({
|
export const executionHelpers = defineComponent({
|
||||||
mixins: [genericHelpers],
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useWorkflowsStore),
|
...mapStores(useWorkflowsStore),
|
||||||
executionId(): string {
|
executionId(): string {
|
||||||
|
@ -64,7 +62,7 @@ export const executionHelpers = defineComponent({
|
||||||
const stoppedAt = execution.stoppedAt
|
const stoppedAt = execution.stoppedAt
|
||||||
? new Date(execution.stoppedAt).getTime()
|
? new Date(execution.stoppedAt).getTime()
|
||||||
: Date.now();
|
: Date.now();
|
||||||
status.runningTime = this.displayTimer(
|
status.runningTime = this.$locale.displayTimer(
|
||||||
stoppedAt - new Date(execution.startedAt).getTime(),
|
stoppedAt - new Date(execution.startedAt).getTime(),
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
@ -73,7 +71,7 @@ export const executionHelpers = defineComponent({
|
||||||
return status;
|
return status;
|
||||||
},
|
},
|
||||||
formatDate(fullDate: Date | string | number) {
|
formatDate(fullDate: Date | string | number) {
|
||||||
const { date, time } = convertToDisplayDateComponents(fullDate);
|
const { date, time } = convertToDisplayDate(fullDate);
|
||||||
return locale.baseText('executionsList.started', { interpolate: { time, date } });
|
return locale.baseText('executionsList.started', { interpolate: { time, date } });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,89 +0,0 @@
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { mapStores } from 'pinia';
|
|
||||||
import { VIEWS } from '@/constants';
|
|
||||||
import { useToast } from '@/composables/useToast';
|
|
||||||
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
|
||||||
|
|
||||||
export const genericHelpers = defineComponent({
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
...useToast(),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loadingService: null as null | { close: () => void; text: string },
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapStores(useSourceControlStore),
|
|
||||||
isReadOnlyRoute(): boolean {
|
|
||||||
return ![
|
|
||||||
VIEWS.WORKFLOW,
|
|
||||||
VIEWS.NEW_WORKFLOW,
|
|
||||||
VIEWS.LOG_STREAMING_SETTINGS,
|
|
||||||
VIEWS.EXECUTION_DEBUG,
|
|
||||||
].includes(this.$route.name as VIEWS);
|
|
||||||
},
|
|
||||||
readOnlyEnv(): boolean {
|
|
||||||
return this.sourceControlStore.preferences.branchReadOnly;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
displayTimer(msPassed: number, showMs = false): string {
|
|
||||||
if (msPassed < 60000) {
|
|
||||||
if (!showMs) {
|
|
||||||
return `${Math.floor(msPassed / 1000)}${this.$locale.baseText(
|
|
||||||
'genericHelpers.secShort',
|
|
||||||
)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${msPassed / 1000}${this.$locale.baseText('genericHelpers.secShort')}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const secondsPassed = Math.floor(msPassed / 1000);
|
|
||||||
const minutesPassed = Math.floor(secondsPassed / 60);
|
|
||||||
const secondsLeft = (secondsPassed - minutesPassed * 60).toString().padStart(2, '0');
|
|
||||||
|
|
||||||
return `${minutesPassed}:${secondsLeft}${this.$locale.baseText('genericHelpers.minShort')}`;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @note Loading helpers extracted as composable in useLoadingService
|
|
||||||
*/
|
|
||||||
|
|
||||||
startLoading(text?: string) {
|
|
||||||
if (this.loadingService !== null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loadingService = this.$loading({
|
|
||||||
lock: true,
|
|
||||||
text: text || this.$locale.baseText('genericHelpers.loading'),
|
|
||||||
background: 'var(--color-dialog-overlay-background)',
|
|
||||||
});
|
|
||||||
},
|
|
||||||
setLoadingText(text: string) {
|
|
||||||
if (this.loadingService !== null) {
|
|
||||||
this.loadingService.text = text;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stopLoading() {
|
|
||||||
if (this.loadingService !== null) {
|
|
||||||
this.loadingService.close();
|
|
||||||
this.loadingService = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isRedirectSafe() {
|
|
||||||
const redirect = this.getRedirectQueryParameter();
|
|
||||||
return redirect.startsWith('/');
|
|
||||||
},
|
|
||||||
getRedirectQueryParameter() {
|
|
||||||
let redirect = '';
|
|
||||||
if (typeof this.$route.query.redirect === 'string') {
|
|
||||||
redirect = decodeURIComponent(this.$route.query.redirect);
|
|
||||||
}
|
|
||||||
return redirect;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -48,7 +48,6 @@ import type {
|
||||||
import { useMessage } from '@/composables/useMessage';
|
import { useMessage } from '@/composables/useMessage';
|
||||||
import { useToast } from '@/composables/useToast';
|
import { useToast } from '@/composables/useToast';
|
||||||
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
import { useNodeHelpers } from '@/composables/useNodeHelpers';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
|
|
||||||
import { get, isEqual } from 'lodash-es';
|
import { get, isEqual } from 'lodash-es';
|
||||||
|
|
||||||
|
@ -68,6 +67,8 @@ import { v4 as uuid } from 'uuid';
|
||||||
import { useSettingsStore } from '@/stores/settings.store';
|
import { useSettingsStore } from '@/stores/settings.store';
|
||||||
import { getCredentialTypeName, isCredentialOnlyNodeType } from '@/utils/credentialOnlyNodes';
|
import { getCredentialTypeName, isCredentialOnlyNodeType } from '@/utils/credentialOnlyNodes';
|
||||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||||
|
import { useCanvasStore } from '@/stores/canvas.store';
|
||||||
|
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||||
|
|
||||||
export function getParentMainInputNode(workflow: Workflow, node: INode): INode {
|
export function getParentMainInputNode(workflow: Workflow, node: INode): INode {
|
||||||
const nodeType = useNodeTypesStore().getNodeType(node.type);
|
const nodeType = useNodeTypesStore().getNodeType(node.type);
|
||||||
|
@ -475,9 +476,9 @@ export function executeData(
|
||||||
}
|
}
|
||||||
|
|
||||||
export const workflowHelpers = defineComponent({
|
export const workflowHelpers = defineComponent({
|
||||||
mixins: [genericHelpers],
|
|
||||||
setup() {
|
setup() {
|
||||||
const nodeHelpers = useNodeHelpers();
|
const nodeHelpers = useNodeHelpers();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...useToast(),
|
...useToast(),
|
||||||
...useMessage(),
|
...useMessage(),
|
||||||
|
@ -887,12 +888,13 @@ export const workflowHelpers = defineComponent({
|
||||||
redirect = true,
|
redirect = true,
|
||||||
forceSave = false,
|
forceSave = false,
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
if (this.readOnlyEnv) {
|
const readOnlyEnv = useSourceControlStore().preferences.branchReadOnly;
|
||||||
return;
|
if (readOnlyEnv) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isLoading = useCanvasStore().isLoading;
|
||||||
const currentWorkflow = id || this.$route.params.name;
|
const currentWorkflow = id || this.$route.params.name;
|
||||||
const isLoading = this.loadingService !== null;
|
|
||||||
|
|
||||||
if (!currentWorkflow || ['new', PLACEHOLDER_EMPTY_WORKFLOW_ID].includes(currentWorkflow)) {
|
if (!currentWorkflow || ['new', PLACEHOLDER_EMPTY_WORKFLOW_ID].includes(currentWorkflow)) {
|
||||||
return this.saveAsNewWorkflow({ name, tags }, redirect);
|
return this.saveAsNewWorkflow({ name, tags }, redirect);
|
||||||
|
|
|
@ -80,6 +80,22 @@ export class I18nClass {
|
||||||
return this.i18n.te(key) ? this.i18n.t(key).toString() : fallback ?? '';
|
return this.i18n.te(key) ? this.i18n.t(key).toString() : fallback ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
displayTimer(msPassed: number, showMs = false): string {
|
||||||
|
if (msPassed < 60000) {
|
||||||
|
if (!showMs) {
|
||||||
|
return `${Math.floor(msPassed / 1000)}${this.baseText('genericHelpers.secShort')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${msPassed / 1000}${this.baseText('genericHelpers.secShort')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const secondsPassed = Math.floor(msPassed / 1000);
|
||||||
|
const minutesPassed = Math.floor(secondsPassed / 60);
|
||||||
|
const secondsLeft = (secondsPassed - minutesPassed * 60).toString().padStart(2, '0');
|
||||||
|
|
||||||
|
return `${minutesPassed}:${secondsLeft}${this.baseText('genericHelpers.minShort')}`;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a string of header text (a node's name and description),
|
* Render a string of header text (a node's name and description),
|
||||||
* used variously in the nodes panel, under the node icon, etc.
|
* used variously in the nodes panel, under the node icon, etc.
|
||||||
|
|
|
@ -13,7 +13,7 @@ import { useSettingsStore } from '@/stores/settings.store';
|
||||||
import { useTemplatesStore } from '@/stores/templates.store';
|
import { useTemplatesStore } from '@/stores/templates.store';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { useSSOStore } from '@/stores/sso.store';
|
import { useSSOStore } from '@/stores/sso.store';
|
||||||
import { EnterpriseEditionFeature, VIEWS } from '@/constants';
|
import { EnterpriseEditionFeature, VIEWS, EDITABLE_CANVAS_VIEWS } from '@/constants';
|
||||||
import { useTelemetry } from '@/composables/useTelemetry';
|
import { useTelemetry } from '@/composables/useTelemetry';
|
||||||
import { middleware } from '@/rbac/middleware';
|
import { middleware } from '@/rbac/middleware';
|
||||||
import type { RouteConfig, RouterMiddleware } from '@/types/router';
|
import type { RouteConfig, RouterMiddleware } from '@/types/router';
|
||||||
|
@ -755,6 +755,19 @@ export const routes = [
|
||||||
},
|
},
|
||||||
] as Array<RouteRecordRaw & RouteConfig>;
|
] as Array<RouteRecordRaw & RouteConfig>;
|
||||||
|
|
||||||
|
function withCanvasReadOnlyMeta(route: RouteRecordRaw) {
|
||||||
|
if (!route.meta) {
|
||||||
|
route.meta = {};
|
||||||
|
}
|
||||||
|
route.meta.readOnlyCanvas = !EDITABLE_CANVAS_VIEWS.includes((route?.name ?? '') as VIEWS);
|
||||||
|
|
||||||
|
if (route.children) {
|
||||||
|
route.children = route.children.map(withCanvasReadOnlyMeta);
|
||||||
|
}
|
||||||
|
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.DEV ? '/' : window.BASE_PATH ?? '/'),
|
history: createWebHistory(import.meta.env.DEV ? '/' : window.BASE_PATH ?? '/'),
|
||||||
scrollBehavior(to: RouteLocationNormalized & RouteConfig, from, savedPosition) {
|
scrollBehavior(to: RouteLocationNormalized & RouteConfig, from, savedPosition) {
|
||||||
|
@ -764,7 +777,7 @@ const router = createRouter({
|
||||||
to.meta.setScrollPosition(0);
|
to.meta.setScrollPosition(0);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
routes,
|
routes: routes.map(withCanvasReadOnlyMeta),
|
||||||
});
|
});
|
||||||
|
|
||||||
router.beforeEach(async (to: RouteLocationNormalized & RouteConfig, from, next) => {
|
router.beforeEach(async (to: RouteLocationNormalized & RouteConfig, from, next) => {
|
||||||
|
|
|
@ -40,6 +40,7 @@ import {
|
||||||
SIDEBAR_WIDTH_EXPANDED,
|
SIDEBAR_WIDTH_EXPANDED,
|
||||||
} from '@/utils/nodeViewUtils';
|
} from '@/utils/nodeViewUtils';
|
||||||
import type { PointXY } from '@jsplumb/util';
|
import type { PointXY } from '@jsplumb/util';
|
||||||
|
import { useLoadingService } from '@/composables/useLoadingService';
|
||||||
|
|
||||||
export const useCanvasStore = defineStore('canvas', () => {
|
export const useCanvasStore = defineStore('canvas', () => {
|
||||||
const workflowStore = useWorkflowsStore();
|
const workflowStore = useWorkflowsStore();
|
||||||
|
@ -47,6 +48,7 @@ export const useCanvasStore = defineStore('canvas', () => {
|
||||||
const uiStore = useUIStore();
|
const uiStore = useUIStore();
|
||||||
const historyStore = useHistoryStore();
|
const historyStore = useHistoryStore();
|
||||||
const sourceControlStore = useSourceControlStore();
|
const sourceControlStore = useSourceControlStore();
|
||||||
|
const loadingService = useLoadingService();
|
||||||
|
|
||||||
const jsPlumbInstanceRef = ref<BrowserJsPlumbInstance>();
|
const jsPlumbInstanceRef = ref<BrowserJsPlumbInstance>();
|
||||||
const isDragging = ref<boolean>(false);
|
const isDragging = ref<boolean>(false);
|
||||||
|
@ -295,6 +297,10 @@ export const useCanvasStore = defineStore('canvas', () => {
|
||||||
lastSelectedConnection,
|
lastSelectedConnection,
|
||||||
newNodeInsertPosition,
|
newNodeInsertPosition,
|
||||||
jsPlumbInstance,
|
jsPlumbInstance,
|
||||||
|
isLoading: loadingService.isLoading,
|
||||||
|
startLoading: loadingService.startLoading,
|
||||||
|
setLoadingText: loadingService.setLoadingText,
|
||||||
|
stopLoading: loadingService.stopLoading,
|
||||||
setRecenteredCanvasAddButtonPosition,
|
setRecenteredCanvasAddButtonPosition,
|
||||||
getNodesWithPlaceholderNode,
|
getNodesWithPlaceholderNode,
|
||||||
canvasPositionFromPagePosition,
|
canvasPositionFromPagePosition,
|
||||||
|
|
|
@ -46,6 +46,7 @@ export interface RouteConfig {
|
||||||
};
|
};
|
||||||
scrollOffset?: number;
|
scrollOffset?: number;
|
||||||
setScrollPosition?: (position: number) => void;
|
setScrollPosition?: (position: number) => void;
|
||||||
|
readOnlyCanvas?: boolean;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,3 +10,15 @@ export const convertToDisplayDateComponents = (
|
||||||
const [date, time] = formattedDate.split('#');
|
const [date, time] = formattedDate.split('#');
|
||||||
return { date, time };
|
return { date, time };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function convertToDisplayDate(fullDate: Date | string | number): {
|
||||||
|
date: string;
|
||||||
|
time: string;
|
||||||
|
} {
|
||||||
|
const mask = `d mmm${
|
||||||
|
new Date(fullDate).getFullYear() === new Date().getFullYear() ? '' : ', yyyy'
|
||||||
|
}#HH:MM:ss`;
|
||||||
|
const formattedDate = dateformat(fullDate, mask);
|
||||||
|
const [date, time] = formattedDate.split('#');
|
||||||
|
return { date, time };
|
||||||
|
}
|
||||||
|
|
|
@ -69,7 +69,6 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import type { IFormInputs } from '@/Interface';
|
import type { IFormInputs } from '@/Interface';
|
||||||
import Logo from '../components/Logo.vue';
|
import Logo from '../components/Logo.vue';
|
||||||
import {
|
import {
|
||||||
|
@ -92,7 +91,6 @@ export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
Logo,
|
Logo,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
props: {
|
props: {
|
||||||
reportError: Boolean,
|
reportError: Boolean,
|
||||||
},
|
},
|
||||||
|
|
|
@ -49,18 +49,18 @@
|
||||||
:name="nodeData.name"
|
:name="nodeData.name"
|
||||||
:is-read-only="isReadOnlyRoute || readOnlyEnv"
|
:is-read-only="isReadOnlyRoute || readOnlyEnv"
|
||||||
:instance="instance"
|
:instance="instance"
|
||||||
@deselectAllNodes="deselectAllNodes"
|
|
||||||
:is-active="!!activeNode && activeNode.name === nodeData.name"
|
:is-active="!!activeNode && activeNode.name === nodeData.name"
|
||||||
@deselectNode="nodeDeselectedByName"
|
|
||||||
:hide-actions="pullConnActive"
|
:hide-actions="pullConnActive"
|
||||||
@nodeSelected="nodeSelectedByName"
|
|
||||||
:is-production-execution-preview="isProductionExecutionPreview"
|
:is-production-execution-preview="isProductionExecutionPreview"
|
||||||
@runWorkflow="onRunNode"
|
|
||||||
:workflow="currentWorkflowObject"
|
:workflow="currentWorkflowObject"
|
||||||
@moved="onNodeMoved"
|
|
||||||
:disable-pointer-events="!canOpenNDV"
|
:disable-pointer-events="!canOpenNDV"
|
||||||
@run="onNodeRun"
|
|
||||||
:hide-node-issues="hideNodeIssues"
|
:hide-node-issues="hideNodeIssues"
|
||||||
|
@deselectAllNodes="deselectAllNodes"
|
||||||
|
@deselectNode="nodeDeselectedByName"
|
||||||
|
@nodeSelected="nodeSelectedByName"
|
||||||
|
@runWorkflow="onRunNode"
|
||||||
|
@moved="onNodeMoved"
|
||||||
|
@run="onNodeRun"
|
||||||
>
|
>
|
||||||
<template #custom-tooltip>
|
<template #custom-tooltip>
|
||||||
<span
|
<span
|
||||||
|
@ -77,10 +77,10 @@
|
||||||
:instance="instance"
|
:instance="instance"
|
||||||
:is-active="!!activeNode && activeNode.name === stickyData.name"
|
:is-active="!!activeNode && activeNode.name === stickyData.name"
|
||||||
:node-view-scale="nodeViewScale"
|
:node-view-scale="nodeViewScale"
|
||||||
@deselectAllNodes="deselectAllNodes"
|
|
||||||
:grid-size="GRID_SIZE"
|
:grid-size="GRID_SIZE"
|
||||||
@deselectNode="nodeDeselectedByName"
|
|
||||||
:hide-actions="pullConnActive"
|
:hide-actions="pullConnActive"
|
||||||
|
@deselectAllNodes="deselectAllNodes"
|
||||||
|
@deselectNode="nodeDeselectedByName"
|
||||||
@nodeSelected="nodeSelectedByName"
|
@nodeSelected="nodeSelectedByName"
|
||||||
@removeNode="(name) => removeNode(name, true)"
|
@removeNode="(name) => removeNode(name, true)"
|
||||||
/>
|
/>
|
||||||
|
@ -239,7 +239,6 @@ import {
|
||||||
UPDATE_WEBHOOK_ID_NODE_TYPES,
|
UPDATE_WEBHOOK_ID_NODE_TYPES,
|
||||||
TIME,
|
TIME,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { moveNodeWorkflow } from '@/mixins/moveNodeWorkflow';
|
import { moveNodeWorkflow } from '@/mixins/moveNodeWorkflow';
|
||||||
|
|
||||||
import useGlobalLinkActions from '@/composables/useGlobalLinkActions';
|
import useGlobalLinkActions from '@/composables/useGlobalLinkActions';
|
||||||
|
@ -372,6 +371,7 @@ import { useViewStacks } from '@/components/Node/NodeCreator/composables/useView
|
||||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||||
import { useClipboard } from '@/composables/useClipboard';
|
import { useClipboard } from '@/composables/useClipboard';
|
||||||
import { usePinnedData } from '@/composables/usePinnedData';
|
import { usePinnedData } from '@/composables/usePinnedData';
|
||||||
|
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||||
|
|
||||||
interface AddNodeOptions {
|
interface AddNodeOptions {
|
||||||
position?: XYPosition;
|
position?: XYPosition;
|
||||||
|
@ -394,7 +394,7 @@ export default defineComponent({
|
||||||
CanvasControls,
|
CanvasControls,
|
||||||
ContextMenu,
|
ContextMenu,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers, moveNodeWorkflow, workflowHelpers, workflowRun, debounceHelper],
|
mixins: [moveNodeWorkflow, workflowHelpers, workflowRun, debounceHelper],
|
||||||
async beforeRouteLeave(to, from, next) {
|
async beforeRouteLeave(to, from, next) {
|
||||||
if (
|
if (
|
||||||
getNodeViewTab(to) === MAIN_HEADER_TABS.EXECUTIONS ||
|
getNodeViewTab(to) === MAIN_HEADER_TABS.EXECUTIONS ||
|
||||||
|
@ -504,14 +504,14 @@ export default defineComponent({
|
||||||
// When entering this tab:
|
// When entering this tab:
|
||||||
if (currentTab === MAIN_HEADER_TABS.WORKFLOW || isOpeningTemplate) {
|
if (currentTab === MAIN_HEADER_TABS.WORKFLOW || isOpeningTemplate) {
|
||||||
if (workflowChanged || nodeViewNotInitialized || isOpeningTemplate) {
|
if (workflowChanged || nodeViewNotInitialized || isOpeningTemplate) {
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
if (nodeViewNotInitialized) {
|
if (nodeViewNotInitialized) {
|
||||||
const previousDirtyState = this.uiStore.stateIsDirty;
|
const previousDirtyState = this.uiStore.stateIsDirty;
|
||||||
this.resetWorkspace();
|
this.resetWorkspace();
|
||||||
this.uiStore.stateIsDirty = previousDirtyState;
|
this.uiStore.stateIsDirty = previousDirtyState;
|
||||||
}
|
}
|
||||||
await Promise.all([this.loadCredentials(), this.initView()]);
|
await Promise.all([this.loadCredentials(), this.initView()]);
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
if (this.blankRedirect) {
|
if (this.blankRedirect) {
|
||||||
this.blankRedirect = false;
|
this.blankRedirect = false;
|
||||||
}
|
}
|
||||||
|
@ -570,6 +570,7 @@ export default defineComponent({
|
||||||
useExternalSecretsStore,
|
useExternalSecretsStore,
|
||||||
useCollaborationStore,
|
useCollaborationStore,
|
||||||
usePushConnectionStore,
|
usePushConnectionStore,
|
||||||
|
useSourceControlStore,
|
||||||
),
|
),
|
||||||
nativelyNumberSuffixedDefaults(): string[] {
|
nativelyNumberSuffixedDefaults(): string[] {
|
||||||
return this.nodeTypesStore.nativelyNumberSuffixedDefaults;
|
return this.nodeTypesStore.nativelyNumberSuffixedDefaults;
|
||||||
|
@ -587,9 +588,7 @@ export default defineComponent({
|
||||||
return this.$route.name === VIEWS.DEMO;
|
return this.$route.name === VIEWS.DEMO;
|
||||||
},
|
},
|
||||||
showCanvasAddButton(): boolean {
|
showCanvasAddButton(): boolean {
|
||||||
return (
|
return !this.isLoading && !this.containsTrigger && !this.isDemo && !this.readOnlyEnv;
|
||||||
this.loadingService === null && !this.containsTrigger && !this.isDemo && !this.readOnlyEnv
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
lastSelectedNode(): INodeUi | null {
|
lastSelectedNode(): INodeUi | null {
|
||||||
return this.uiStore.getLastSelectedNode;
|
return this.uiStore.getLastSelectedNode;
|
||||||
|
@ -702,11 +701,17 @@ export default defineComponent({
|
||||||
return this.canvasStore.jsPlumbInstance;
|
return this.canvasStore.jsPlumbInstance;
|
||||||
},
|
},
|
||||||
isLoading(): boolean {
|
isLoading(): boolean {
|
||||||
return this.loadingService !== null;
|
return this.canvasStore.isLoading;
|
||||||
},
|
},
|
||||||
currentWorkflowObject(): Workflow {
|
currentWorkflowObject(): Workflow {
|
||||||
return this.workflowsStore.getCurrentWorkflow();
|
return this.workflowsStore.getCurrentWorkflow();
|
||||||
},
|
},
|
||||||
|
readOnlyEnv(): boolean {
|
||||||
|
return this.sourceControlStore.preferences.branchReadOnly;
|
||||||
|
},
|
||||||
|
isReadOnlyRoute() {
|
||||||
|
return this.$route?.meta?.readOnlyCanvas === true;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
@ -756,7 +761,7 @@ export default defineComponent({
|
||||||
|
|
||||||
this.clipboard.onPaste.value = this.onClipboardPasteEvent;
|
this.clipboard.onPaste.value = this.onClipboardPasteEvent;
|
||||||
|
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
const loadPromises = [
|
const loadPromises = [
|
||||||
this.loadActiveWorkflows(),
|
this.loadActiveWorkflows(),
|
||||||
this.loadCredentials(),
|
this.loadCredentials(),
|
||||||
|
@ -799,7 +804,7 @@ export default defineComponent({
|
||||||
this.$locale.baseText('nodeView.showError.mounted2.message') + ':',
|
this.$locale.baseText('nodeView.showError.mounted2.message') + ':',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
void this.usersStore.showPersonalizationSurvey();
|
void this.usersStore.showPersonalizationSurvey();
|
||||||
|
@ -1140,7 +1145,7 @@ export default defineComponent({
|
||||||
this.onToggleNodeCreator({ source, createNodeActive: true });
|
this.onToggleNodeCreator({ source, createNodeActive: true });
|
||||||
},
|
},
|
||||||
async openExecution(executionId: string) {
|
async openExecution(executionId: string) {
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
this.resetWorkspace();
|
this.resetWorkspace();
|
||||||
let data: IExecutionResponse | undefined;
|
let data: IExecutionResponse | undefined;
|
||||||
try {
|
try {
|
||||||
|
@ -1239,7 +1244,7 @@ export default defineComponent({
|
||||||
duration: 0,
|
duration: 0,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
},
|
},
|
||||||
async importWorkflowExact(data: { workflow: IWorkflowDataUpdate }) {
|
async importWorkflowExact(data: { workflow: IWorkflowDataUpdate }) {
|
||||||
if (!data.workflow.nodes || !data.workflow.connections) {
|
if (!data.workflow.nodes || !data.workflow.connections) {
|
||||||
|
@ -1257,8 +1262,8 @@ export default defineComponent({
|
||||||
this.canvasStore.zoomToFit();
|
this.canvasStore.zoomToFit();
|
||||||
},
|
},
|
||||||
async openWorkflowTemplate(templateId: string) {
|
async openWorkflowTemplate(templateId: string) {
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
this.setLoadingText(this.$locale.baseText('nodeView.loadingTemplate'));
|
this.canvasStore.setLoadingText(this.$locale.baseText('nodeView.loadingTemplate'));
|
||||||
this.resetWorkspace();
|
this.resetWorkspace();
|
||||||
|
|
||||||
this.workflowsStore.currentWorkflowExecutions = [];
|
this.workflowsStore.currentWorkflowExecutions = [];
|
||||||
|
@ -1297,10 +1302,10 @@ export default defineComponent({
|
||||||
templateName: data.name,
|
templateName: data.name,
|
||||||
workflow: data.workflow,
|
workflow: data.workflow,
|
||||||
});
|
});
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
},
|
},
|
||||||
async openWorkflow(workflow: IWorkflowDb) {
|
async openWorkflow(workflow: IWorkflowDb) {
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
|
|
||||||
const selectedExecution = this.workflowsStore.activeWorkflowExecution;
|
const selectedExecution = this.workflowsStore.activeWorkflowExecution;
|
||||||
|
|
||||||
|
@ -1354,7 +1359,7 @@ export default defineComponent({
|
||||||
} else {
|
} else {
|
||||||
this.workflowsStore.activeWorkflowExecution = selectedExecution;
|
this.workflowsStore.activeWorkflowExecution = selectedExecution;
|
||||||
}
|
}
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
this.collaborationStore.notifyWorkflowOpened(workflow.id);
|
this.collaborationStore.notifyWorkflowOpened(workflow.id);
|
||||||
},
|
},
|
||||||
touchTap(e: MouseEvent | TouchEvent) {
|
touchTap(e: MouseEvent | TouchEvent) {
|
||||||
|
@ -1997,18 +2002,18 @@ export default defineComponent({
|
||||||
async getWorkflowDataFromUrl(url: string): Promise<IWorkflowDataUpdate | undefined> {
|
async getWorkflowDataFromUrl(url: string): Promise<IWorkflowDataUpdate | undefined> {
|
||||||
let workflowData: IWorkflowDataUpdate;
|
let workflowData: IWorkflowDataUpdate;
|
||||||
|
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
try {
|
try {
|
||||||
workflowData = await this.workflowsStore.getWorkflowFromUrl(url);
|
workflowData = await this.workflowsStore.getWorkflowFromUrl(url);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
this.showError(
|
this.showError(
|
||||||
error,
|
error,
|
||||||
this.$locale.baseText('nodeView.showError.getWorkflowDataFromUrl.title'),
|
this.$locale.baseText('nodeView.showError.getWorkflowDataFromUrl.title'),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
|
|
||||||
return workflowData;
|
return workflowData;
|
||||||
},
|
},
|
||||||
|
@ -3423,7 +3428,7 @@ export default defineComponent({
|
||||||
e.returnValue = true; //Gecko + IE
|
e.returnValue = true; //Gecko + IE
|
||||||
return true; //Gecko + Webkit, Safari, Chrome etc.
|
return true; //Gecko + Webkit, Safari, Chrome etc.
|
||||||
} else {
|
} else {
|
||||||
this.startLoading(this.$locale.baseText('nodeView.redirecting'));
|
this.canvasStore.startLoading(this.$locale.baseText('nodeView.redirecting'));
|
||||||
this.collaborationStore.notifyWorkflowClosed(this.workflowsStore.workflowId);
|
this.collaborationStore.notifyWorkflowClosed(this.workflowsStore.workflowId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3434,7 +3439,7 @@ export default defineComponent({
|
||||||
clearTimeout(this.unloadTimeout);
|
clearTimeout(this.unloadTimeout);
|
||||||
},
|
},
|
||||||
async newWorkflow(): Promise<void> {
|
async newWorkflow(): Promise<void> {
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
this.resetWorkspace();
|
this.resetWorkspace();
|
||||||
this.workflowData = await this.workflowsStore.getNewWorkflowData();
|
this.workflowData = await this.workflowsStore.getNewWorkflowData();
|
||||||
this.workflowsStore.currentWorkflowExecutions = [];
|
this.workflowsStore.currentWorkflowExecutions = [];
|
||||||
|
@ -3446,7 +3451,7 @@ export default defineComponent({
|
||||||
this.uiStore.nodeViewInitialized = true;
|
this.uiStore.nodeViewInitialized = true;
|
||||||
this.historyStore.reset();
|
this.historyStore.reset();
|
||||||
this.workflowsStore.activeWorkflowExecution = null;
|
this.workflowsStore.activeWorkflowExecution = null;
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
},
|
},
|
||||||
async tryToAddWelcomeSticky(): Promise<void> {
|
async tryToAddWelcomeSticky(): Promise<void> {
|
||||||
this.canvasStore.zoomToFit();
|
this.canvasStore.zoomToFit();
|
||||||
|
@ -4574,9 +4579,9 @@ export default defineComponent({
|
||||||
|
|
||||||
if (nodesToBeFetched.length > 0) {
|
if (nodesToBeFetched.length > 0) {
|
||||||
// Only call API if node information is actually missing
|
// Only call API if node information is actually missing
|
||||||
this.startLoading();
|
this.canvasStore.startLoading();
|
||||||
await this.nodeTypesStore.getNodesInformation(nodesToBeFetched);
|
await this.nodeTypesStore.getNodesInformation(nodesToBeFetched);
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async onPostMessageReceived(message: MessageEvent) {
|
async onPostMessageReceived(message: MessageEvent) {
|
||||||
|
@ -4829,7 +4834,7 @@ export default defineComponent({
|
||||||
onPageShow(e: PageTransitionEvent) {
|
onPageShow(e: PageTransitionEvent) {
|
||||||
// Page was restored from the bfcache (back-forward cache)
|
// Page was restored from the bfcache (back-forward cache)
|
||||||
if (e.persisted) {
|
if (e.persisted) {
|
||||||
this.stopLoading();
|
this.canvasStore.stopLoading();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
readOnlyEnvRouteCheck() {
|
readOnlyEnvRouteCheck() {
|
||||||
|
|
|
@ -30,7 +30,6 @@ import { useUsersStore } from '@/stores/users.store';
|
||||||
import { useSettingsStore } from '@/stores/settings.store';
|
import { useSettingsStore } from '@/stores/settings.store';
|
||||||
import { useCloudPlanStore } from '@/stores/cloudPlan.store';
|
import { useCloudPlanStore } from '@/stores/cloudPlan.store';
|
||||||
import { useUIStore } from '@/stores/ui.store';
|
import { useUIStore } from '@/stores/ui.store';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'SigninView',
|
name: 'SigninView',
|
||||||
|
@ -38,7 +37,6 @@ export default defineComponent({
|
||||||
AuthView,
|
AuthView,
|
||||||
MfaView,
|
MfaView,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
...useToast(),
|
...useToast(),
|
||||||
|
@ -116,6 +114,17 @@ export default defineComponent({
|
||||||
async onEmailPasswordSubmitted(form: { email: string; password: string }) {
|
async onEmailPasswordSubmitted(form: { email: string; password: string }) {
|
||||||
await this.login(form);
|
await this.login(form);
|
||||||
},
|
},
|
||||||
|
isRedirectSafe() {
|
||||||
|
const redirect = this.getRedirectQueryParameter();
|
||||||
|
return redirect.startsWith('/');
|
||||||
|
},
|
||||||
|
getRedirectQueryParameter() {
|
||||||
|
let redirect = '';
|
||||||
|
if (typeof this.$route.query?.redirect === 'string') {
|
||||||
|
redirect = decodeURIComponent(this.$route.query?.redirect);
|
||||||
|
}
|
||||||
|
return redirect;
|
||||||
|
},
|
||||||
async login(form: { email: string; password: string; token?: string; recoveryCode?: string }) {
|
async login(form: { email: string; password: string; token?: string; recoveryCode?: string }) {
|
||||||
try {
|
try {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
|
|
@ -84,7 +84,6 @@ import TemplateFilters from '@/components/TemplateFilters.vue';
|
||||||
import TemplateList from '@/components/TemplateList.vue';
|
import TemplateList from '@/components/TemplateList.vue';
|
||||||
import TemplatesView from '@/views/TemplatesView.vue';
|
import TemplatesView from '@/views/TemplatesView.vue';
|
||||||
|
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import type {
|
import type {
|
||||||
ITemplatesCollection,
|
ITemplatesCollection,
|
||||||
ITemplatesWorkflow,
|
ITemplatesWorkflow,
|
||||||
|
@ -118,7 +117,7 @@ export default defineComponent({
|
||||||
TemplateList,
|
TemplateList,
|
||||||
TemplatesView,
|
TemplatesView,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers, debounceHelper],
|
mixins: [debounceHelper],
|
||||||
setup() {
|
setup() {
|
||||||
return {
|
return {
|
||||||
...useToast(),
|
...useToast(),
|
||||||
|
|
|
@ -151,7 +151,6 @@ import { useUsersStore } from '@/stores/users.store';
|
||||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||||
import { useCredentialsStore } from '@/stores/credentials.store';
|
import { useCredentialsStore } from '@/stores/credentials.store';
|
||||||
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
import { useSourceControlStore } from '@/stores/sourceControl.store';
|
||||||
import { genericHelpers } from '@/mixins/genericHelpers';
|
|
||||||
import { useTagsStore } from '@/stores/tags.store';
|
import { useTagsStore } from '@/stores/tags.store';
|
||||||
|
|
||||||
type IResourcesListLayoutInstance = InstanceType<typeof ResourcesListLayout>;
|
type IResourcesListLayoutInstance = InstanceType<typeof ResourcesListLayout>;
|
||||||
|
@ -171,7 +170,6 @@ const WorkflowsView = defineComponent({
|
||||||
SuggestedTemplatesPage,
|
SuggestedTemplatesPage,
|
||||||
SuggestedTemplatesSection,
|
SuggestedTemplatesSection,
|
||||||
},
|
},
|
||||||
mixins: [genericHelpers],
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
|
@ -194,6 +192,9 @@ const WorkflowsView = defineComponent({
|
||||||
useSourceControlStore,
|
useSourceControlStore,
|
||||||
useTagsStore,
|
useTagsStore,
|
||||||
),
|
),
|
||||||
|
readOnlyEnv(): boolean {
|
||||||
|
return this.sourceControlStore.preferences.branchReadOnly;
|
||||||
|
},
|
||||||
currentUser(): IUser {
|
currentUser(): IUser {
|
||||||
return this.usersStore.currentUser || ({} as IUser);
|
return this.usersStore.currentUser || ({} as IUser);
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue