n8n-editor-ui
Version:
Workflow Editor UI for n8n
472 lines (471 loc) • 22.2 kB
JavaScript
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/InsightsPaywall-Cgjhc58I.js","assets/_plugin-vue_export-helper-BwBpWJRZ.js","assets/src-DgvumQTi.js","assets/preload-helper-CR0ecmWK.js","assets/truncate-B1HVeveJ.js","assets/_MapCache-ficiegRb.js","assets/vue.runtime.esm-bundler-tP5dCd7J.js","assets/chunk-6z4oVpB-.js","assets/CalendarDate-zWqgZMlk.js","assets/sanitize-html-Cc45ZKm8.js","assets/empty-BuGRxzl4.js","assets/path-browserify-BtCDmZ3_.js","assets/en-CF30SCh2.js","assets/src-CMoPZtHv.css","assets/constants-BbpucWL4.js","assets/merge-k8vSyyXH.js","assets/builder.store-sBTWwxRU.js","assets/_baseOrderBy-B_6CV8x6.js","assets/dateformat-CM9k0--B.js","assets/useDebounce-Bnb8W2LR.js","assets/versions.store-BwdT833-.js","assets/usePageRedirectionHelper-fGNB6ZKK.js","assets/InsightsPaywall-CE5W3W4m.css","assets/InsightsChartTotal-CLtcCYXo.js","assets/chart-CE3HWIkr.js","assets/dist-DP_8je0B.js","assets/smartDecimal-DK6-_VSq.js","assets/chartjs.utils-CeXvwL6J.js","assets/insights.constants-C8GITe6H.js","assets/InsightsChartFailed-DBcygly6.js","assets/InsightsChartFailureRate-CY3HP65L.js","assets/insights.utils-B7OXsqrQ.js","assets/InsightsChartTimeSaved-DAfnPiRJ.js","assets/InsightsChartAverageRuntime-gpxjFP2f.js","assets/InsightsTableWorkflows-D-DIwl3G.js","assets/InsightsTableWorkflows-D20Yb7ZW.css"])))=>i.map(i=>d[i]);
import { C as computed, Cn as toDisplayString, D as createElementBlock, E as createCommentVNode, Gt as unref, It as ref, M as createVNode, N as defineAsyncComponent, P as defineComponent, T as createBlock, Z as onMounted, _ as Fragment, _t as watch, bt as withCtx, ct as resolveDynamicComponent, et as openBlock, ft as useModel, it as renderList, j as createTextVNode, q as onBeforeMount, vn as normalizeClass, w as createBaseVNode, zt as shallowRef } from "./vue.runtime.esm-bundler-tP5dCd7J.js";
import { _t as useI18n } from "./_MapCache-ficiegRb.js";
import { Cn as N8nSpinner_default, Sn as N8nButton_default, o as DateRangePicker_default, wn as N8nIcon_default, xn as N8nText_default, yn as N8nHeading_default } from "./src-DgvumQTi.js";
import "./en-CF30SCh2.js";
import { t as __vitePreload } from "./preload-helper-CR0ecmWK.js";
import { t as __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BwBpWJRZ.js";
import { v as useRoute } from "./truncate-B1HVeveJ.js";
import { O as useTelemetry, Xn as useProjectsStore, Yn as useDocumentTitle } from "./builder.store-sBTWwxRU.js";
import "./empty-BuGRxzl4.js";
import { t as ElDialog } from "./dialog-D5O6wJX0.js";
import "./sanitize-html-Cc45ZKm8.js";
import { h as $14e0f24ef4ac5c92$export$d0bdf45af03a6ea3, i as $11d87f3f76e88657$export$b21e0b124e224484, l as $14e0f24ef4ac5c92$export$629b0a497aa65267, m as $14e0f24ef4ac5c92$export$aa8b41735afcabd2, s as $14e0f24ef4ac5c92$export$461939dd4422153 } from "./CalendarDate-zWqgZMlk.js";
import "./path-browserify-BtCDmZ3_.js";
import "./constants-BbpucWL4.js";
import "./merge-k8vSyyXH.js";
import "./_baseOrderBy-B_6CV8x6.js";
import "./dateformat-CM9k0--B.js";
import "./useDebounce-Bnb8W2LR.js";
import "./versions.store-BwdT833-.js";
import { t as usePageRedirectionHelper } from "./usePageRedirectionHelper-fGNB6ZKK.js";
import "./ProjectIcon-A2WPT9dM.js";
import "./orderBy-EuatZUAl.js";
import { t as ProjectSharing_default } from "./ProjectSharing-IDL3ExN3.js";
import { t as useInsightsStore } from "./insights.store-BBo4cRMD.js";
import { s as INSIGHT_TYPES } from "./insights.constants-C8GITe6H.js";
import { i as timeRangeMappings, r as getTimeRangeLabels, t as formatDateRange } from "./insights.utils-B7OXsqrQ.js";
import "./smartDecimal-DK6-_VSq.js";
import { t as InsightsSummary_default } from "./InsightsSummary-C8OjRO2B.js";
var _hoisted_1$1 = { class: "perks-list" };
var InsightsUpgradeModal_default = /* @__PURE__ */ __plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
__name: "InsightsUpgradeModal",
props: {
"modelValue": { type: Boolean },
"modelModifiers": {}
},
emits: ["update:modelValue"],
setup(__props) {
const model = useModel(__props, "modelValue");
const i18n = useI18n();
function goToUpgrade() {
model.value = false;
usePageRedirectionHelper().goToUpgrade("insights", "upgrade-insights");
}
const perks = computed(() => [...Array(3).keys()].map((index) => i18n.baseText(`insights.upgradeModal.perks.${index}`)));
return (_ctx, _cache) => {
return openBlock(), createBlock(unref(ElDialog), {
modelValue: model.value,
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => model.value = $event),
title: unref(i18n).baseText("insights.upgradeModal.title"),
width: "500"
}, {
footer: withCtx(() => [createBaseVNode("div", null, [createVNode(unref(N8nButton_default), {
type: "secondary",
onClick: _cache[0] || (_cache[0] = ($event) => model.value = false)
}, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("insights.upgradeModal.button.dismiss")), 1)]),
_: 1
}), createVNode(unref(N8nButton_default), {
type: "primary",
onClick: goToUpgrade
}, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("generic.upgrade")), 1)]),
_: 1
})])]),
default: withCtx(() => [createBaseVNode("div", null, [createVNode(unref(N8nText_default), {
tag: "p",
class: "mb-s"
}, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("insights.upgradeModal.content")), 1)]),
_: 1
}), createBaseVNode("ul", _hoisted_1$1, [(openBlock(true), createElementBlock(Fragment, null, renderList(perks.value, (perk) => {
return openBlock(), createBlock(unref(N8nText_default), {
key: perk,
color: "text-dark",
tag: "li"
}, {
default: withCtx(() => [_cache[2] || (_cache[2] = createBaseVNode("svg", {
xmlns: "http://www.w3.org/2000/svg",
viewBox: "0 0 16 16",
width: "16px",
height: "16px"
}, [createBaseVNode("path", {
d: "M 16 8 C 16 12.418 12.418 16 8 16 C 3.582 16 0 12.418 0 8 C 0 3.582 3.582 0 8 0 C 12.418 0 16 3.582 16 8 Z M 3.97 9.03 L 5.97 11.03 L 6.5 11.561 L 7.03 11.03 L 12.53 5.53 L 11.47 4.47 L 6.5 9.439 L 5.03 7.97 L 3.97 9.03 Z",
fill: "currentColor"
})], -1)), createTextVNode(" " + toDisplayString(perk), 1)]),
_: 2
}, 1024);
}), 128))])])]),
_: 1
}, 8, ["modelValue", "title"]);
};
}
}), [["__scopeId", "data-v-528a05c4"]]);
var InsightsDataRangePicker_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "InsightsDataRangePicker",
props: {
maxValue: {},
minValue: {},
modelValue: {},
presets: {}
},
emits: [
"update:modelValue",
"update:placeholder",
"update:startValue",
"update:open"
],
setup(__props, { emit: __emit }) {
const props = __props;
const emit = __emit;
const telemetry = useTelemetry();
const upgradeModal = ref(false);
function showUpgradeModal() {
upgradeModal.value = true;
}
const actionType = ref("custom");
function getDaysDiff({ start, end }) {
if (!start) return 0;
if (!end) return 0;
return end.compare(start);
}
function isBeforeOrSame(dateToCompare, referenceDate) {
return dateToCompare.compare(referenceDate) <= 0;
}
function isAfterOrSame(dateToCompare, referenceDate) {
return dateToCompare.compare(referenceDate) >= 0;
}
function isEqual(dateToCompare, referenceDate) {
if (!dateToCompare || !referenceDate) return false;
return dateToCompare.compare(referenceDate) === 0;
}
function isValidDateRange({ start, end }) {
if (!start) return false;
if (!end) return false;
return isBeforeOrSame(end, props.maxValue) && isAfterOrSame(start, props.minValue);
}
const range = shallowRef({
start: props.modelValue.start?.copy(),
end: props.modelValue.end?.copy()
});
function syncWithParentValue() {
if (!isEqual(range.value?.start, props.modelValue.start) || !isEqual(range.value?.end, props.modelValue.end)) range.value = {
start: props.modelValue.start?.copy(),
end: props.modelValue.end?.copy()
};
}
function syncData(isOpen) {
if (isOpen) {
syncWithParentValue();
return;
}
const normalizedRange = {
start: range.value?.start?.copy(),
end: range.value?.end?.copy() ?? range.value?.start?.copy()
};
if (!isValidDateRange(normalizedRange)) {
console.error("Invalid date range selected", normalizedRange);
syncWithParentValue();
return;
}
if (isEqual(normalizedRange.start, props.modelValue.start) && isEqual(normalizedRange.end, props.modelValue.end)) return;
emit("update:modelValue", normalizedRange);
const trackData = {
start_date: normalizedRange.start?.toDate($14e0f24ef4ac5c92$export$aa8b41735afcabd2()).toISOString(),
end_date: normalizedRange.end?.toDate($14e0f24ef4ac5c92$export$aa8b41735afcabd2()).toISOString(),
range_length_days: getDaysDiff(normalizedRange),
type: actionType.value
};
telemetry.track("User updated insights time range", trackData);
}
const open = ref(false);
watch(open, (opened) => {
syncData(opened);
actionType.value = "custom";
});
function setPresetRange(days) {
range.value = {
start: props.maxValue.copy().subtract({ days }),
end: props.maxValue.copy()
};
actionType.value = "preset";
open.value = false;
}
const formattedRange = computed(() => {
const { start, end } = props.modelValue;
if (!start) return "Select range";
return formatDateRange({
start,
end
});
});
function isActiveRange(presetValue) {
if (!$14e0f24ef4ac5c92$export$629b0a497aa65267(props.modelValue.end, $14e0f24ef4ac5c92$export$aa8b41735afcabd2())) return false;
return props.modelValue.end.compare(props.modelValue.start) === presetValue;
}
return (_ctx, _cache) => {
return openBlock(), createElementBlock(Fragment, null, [createVNode(unref(DateRangePicker_default), {
modelValue: range.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => range.value = $event),
open: open.value,
"onUpdate:open": _cache[1] || (_cache[1] = ($event) => open.value = $event),
"max-value": _ctx.maxValue,
"min-value": _ctx.minValue
}, {
trigger: withCtx(() => [createVNode(unref(N8nButton_default), {
icon: "calendar",
type: "secondary"
}, {
default: withCtx(() => [createTextVNode(toDisplayString(formattedRange.value), 1)]),
_: 1
})]),
presets: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.presets, (preset) => {
return openBlock(), createBlock(unref(N8nButton_default), {
key: preset.value,
class: normalizeClass(_ctx.$style.PresetButton),
type: isActiveRange(preset.value) ? "primary" : "secondary",
size: "small",
onClick: ($event) => preset.disabled ? showUpgradeModal() : setPresetRange(preset.value)
}, {
default: withCtx(() => [createTextVNode(toDisplayString(preset.label) + " ", 1), preset.disabled ? (openBlock(), createBlock(unref(N8nIcon_default), {
key: 0,
icon: "lock",
class: normalizeClass(_ctx.$style.LockIcon)
}, null, 8, ["class"])) : createCommentVNode("", true)]),
_: 2
}, 1032, [
"class",
"type",
"onClick"
]);
}), 128))]),
_: 1
}, 8, [
"modelValue",
"open",
"max-value",
"min-value"
]), createVNode(InsightsUpgradeModal_default, {
modelValue: upgradeModal.value,
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => upgradeModal.value = $event)
}, null, 8, ["modelValue"])], 64);
};
}
});
var InsightsDataRangePicker_vue_vue_type_style_index_0_lang_module_default = {
PresetButton: "_PresetButton_1waws_2",
LockIcon: "_LockIcon_1waws_7"
};
var InsightsDataRangePicker_default = /* @__PURE__ */ __plugin_vue_export_helper_default(InsightsDataRangePicker_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": InsightsDataRangePicker_vue_vue_type_style_index_0_lang_module_default }]]);
var _hoisted_1 = {
class: "mt-s",
style: {
"display": "flex",
"gap": "12px",
"align-items": "center"
}
};
var InsightsDashboard_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "InsightsDashboard",
props: { insightType: {} },
setup(__props) {
const InsightsPaywall = defineAsyncComponent(async () => await __vitePreload(() => import("./InsightsPaywall-Cgjhc58I.js"), __vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22])));
const InsightsChartTotal = defineAsyncComponent(async () => await __vitePreload(() => import("./InsightsChartTotal-CLtcCYXo.js"), __vite__mapDeps([23,5,6,7,24,18,15,25,26,27,28])));
const InsightsChartFailed = defineAsyncComponent(async () => await __vitePreload(() => import("./InsightsChartFailed-DBcygly6.js"), __vite__mapDeps([29,5,6,7,24,18,15,25,26,27,28])));
const InsightsChartFailureRate = defineAsyncComponent(async () => await __vitePreload(() => import("./InsightsChartFailureRate-CY3HP65L.js"), __vite__mapDeps([30,8,5,6,7,24,18,15,25,26,27,28,31])));
const InsightsChartTimeSaved = defineAsyncComponent(async () => await __vitePreload(() => import("./InsightsChartTimeSaved-DAfnPiRJ.js"), __vite__mapDeps([32,8,5,6,7,24,18,15,25,26,27,28,31])));
const InsightsChartAverageRuntime = defineAsyncComponent(async () => await __vitePreload(() => import("./InsightsChartAverageRuntime-gpxjFP2f.js"), __vite__mapDeps([33,8,5,6,7,24,18,15,25,26,27,28,31])));
const InsightsTableWorkflows = defineAsyncComponent(async () => await __vitePreload(() => import("./InsightsTableWorkflows-D-DIwl3G.js"), __vite__mapDeps([34,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,26,28,31,35])));
const props = __props;
const route = useRoute();
const i18n = useI18n();
const insightsStore = useInsightsStore();
const projectsStore = useProjectsStore();
const isTimeSavedRoute = computed(() => route.params.insightType === INSIGHT_TYPES.TIME_SAVED);
const chartComponents = computed(() => ({
total: InsightsChartTotal,
failed: InsightsChartFailed,
failureRate: InsightsChartFailureRate,
timeSaved: InsightsChartTimeSaved,
averageRunTime: InsightsChartAverageRuntime
}));
const transformFilter = ({ id, desc }) => {
return `${id}:${desc ? "desc" : "asc"}`;
};
const sortTableBy = ref([{
id: props.insightType,
desc: true
}]);
const granularity = computed(() => {
const { start, end } = range.value;
if (!start || !end) return "day";
const comparison = end.compare(start);
if (comparison <= 0) return "hour";
if (comparison <= 30) return "day";
return "week";
});
const selectedProject = ref(null);
const maxDate = $14e0f24ef4ac5c92$export$d0bdf45af03a6ea3($14e0f24ef4ac5c92$export$aa8b41735afcabd2());
const maxLicensedDate = insightsStore.dateRanges.toReversed().find((dateRange) => dateRange.licensed)?.key ?? "week";
const timeRangeLabels = getTimeRangeLabels();
const presets = computed(() => insightsStore.dateRanges.map((item) => {
return {
value: timeRangeMappings[item.key],
label: timeRangeLabels[item.key],
disabled: !item.licensed
};
}));
const maximumValue = shallowRef(maxDate.copy());
const minimumValue = shallowRef(maxDate.copy().subtract({ days: timeRangeMappings[maxLicensedDate] }));
const range = shallowRef({
start: maxDate.copy().subtract({ days: 7 }),
end: maxDate.copy()
});
const getFilteredRange = () => {
const timezone = $14e0f24ef4ac5c92$export$aa8b41735afcabd2();
return {
startDate: $11d87f3f76e88657$export$b21e0b124e224484(range.value.start, $14e0f24ef4ac5c92$export$461939dd4422153(timezone)).toDate(timezone),
endDate: $11d87f3f76e88657$export$b21e0b124e224484(range.value.end, $14e0f24ef4ac5c92$export$461939dd4422153(timezone)).toDate(timezone)
};
};
const fetchPaginatedTableData = ({ page = 0, itemsPerPage = 25, sortBy, projectId = selectedProject.value?.id }) => {
const skip = page * itemsPerPage;
const take = itemsPerPage;
const sortKey = sortBy.length ? transformFilter(sortBy[0]) : void 0;
const { startDate, endDate } = getFilteredRange();
insightsStore.table.execute(0, {
skip,
take,
sortBy: sortKey,
startDate,
endDate,
projectId
});
};
watch(() => [
props.insightType,
selectedProject.value,
range.value
], () => {
sortTableBy.value = [{
id: props.insightType,
desc: true
}];
const { startDate, endDate } = getFilteredRange();
if (insightsStore.isSummaryEnabled) insightsStore.summary.execute(0, {
startDate,
endDate,
projectId: selectedProject.value?.id
});
insightsStore.charts.execute(0, {
startDate,
endDate,
projectId: selectedProject.value?.id
});
if (insightsStore.isDashboardEnabled) fetchPaginatedTableData({
sortBy: sortTableBy.value,
projectId: selectedProject.value?.id
});
}, { immediate: true });
onMounted(() => {
useDocumentTitle().set(i18n.baseText("insights.heading"));
});
onBeforeMount(async () => {
await projectsStore.getAvailableProjects();
});
const emailPattern = /^<([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})>$/;
const projects = computed(() => projectsStore.availableProjects.filter((project) => project.name && !emailPattern.test(project.name.trim())));
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", { class: normalizeClass(_ctx.$style.insightsView) }, [createBaseVNode("div", { class: normalizeClass(_ctx.$style.insightsContainer) }, [
createVNode(unref(N8nHeading_default), {
bold: "",
tag: "h2",
size: "xlarge"
}, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("insights.dashboard.title")), 1)]),
_: 1
}),
createBaseVNode("div", _hoisted_1, [createVNode(ProjectSharing_default, {
modelValue: selectedProject.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedProject.value = $event),
projects: projects.value,
placeholder: unref(i18n).baseText("insights.dashboard.search.placeholder"),
"empty-options-text": unref(i18n).baseText("projects.sharing.noMatchingProjects"),
size: "mini",
class: normalizeClass(_ctx.$style.projectSelect),
clearable: "",
onClear: _cache[1] || (_cache[1] = ($event) => selectedProject.value = null)
}, null, 8, [
"modelValue",
"projects",
"placeholder",
"empty-options-text",
"class"
]), createVNode(InsightsDataRangePicker_default, {
modelValue: range.value,
"onUpdate:modelValue": _cache[2] || (_cache[2] = ($event) => range.value = $event),
"max-value": maximumValue.value,
"min-value": minimumValue.value,
presets: presets.value
}, null, 8, [
"modelValue",
"max-value",
"min-value",
"presets"
])]),
unref(insightsStore).isSummaryEnabled ? (openBlock(), createBlock(InsightsSummary_default, {
key: 0,
summary: unref(insightsStore).summary.state,
loading: unref(insightsStore).summary.isLoading,
"start-date": range.value.start,
"end-date": range.value.end,
class: normalizeClass(_ctx.$style.insightsBanner)
}, null, 8, [
"summary",
"loading",
"start-date",
"end-date",
"class"
])) : createCommentVNode("", true),
createBaseVNode("div", { class: normalizeClass(_ctx.$style.insightsContent) }, [unref(insightsStore).isDashboardEnabled || isTimeSavedRoute.value ? (openBlock(), createElementBlock("div", {
key: 0,
class: normalizeClass(_ctx.$style.insightsContentWrapper)
}, [
createBaseVNode("div", { class: normalizeClass([_ctx.$style.dataLoader, { [_ctx.$style.isDataLoading]: unref(insightsStore).charts.isLoading || unref(insightsStore).table.isLoading }]) }, [createVNode(unref(N8nSpinner_default)), createBaseVNode("span", null, toDisplayString(unref(i18n).baseText("insights.chart.loading")), 1)], 2),
createBaseVNode("div", { class: normalizeClass(_ctx.$style.insightsChartWrapper) }, [createTextVNode(toDisplayString(granularity.value) + " ", 1), (openBlock(), createBlock(resolveDynamicComponent(chartComponents.value[props.insightType]), {
type: props.insightType,
data: unref(insightsStore).charts.state,
granularity: granularity.value,
"start-date": range.value.start.toString(),
"end-date": range.value.end.toString()
}, null, 8, [
"type",
"data",
"granularity",
"start-date",
"end-date"
]))], 2),
createBaseVNode("div", { class: normalizeClass(_ctx.$style.insightsTableWrapper) }, [createVNode(unref(InsightsTableWorkflows), {
"sort-by": sortTableBy.value,
"onUpdate:sortBy": _cache[3] || (_cache[3] = ($event) => sortTableBy.value = $event),
data: unref(insightsStore).table.state,
loading: unref(insightsStore).table.isLoading,
"is-dashboard-enabled": unref(insightsStore).isDashboardEnabled,
"onUpdate:options": fetchPaginatedTableData
}, null, 8, [
"sort-by",
"data",
"loading",
"is-dashboard-enabled"
])], 2)
], 2)) : (openBlock(), createBlock(unref(InsightsPaywall), { key: 1 }))], 2)
], 2)], 2);
};
}
});
var InsightsDashboard_vue_vue_type_style_index_0_lang_module_default = {
insightsView: "_insightsView_ttte2_123",
insightsContainer: "_insightsContainer_ttte2_131",
insightsBanner: "_insightsBanner_ttte2_138",
insightsContent: "_insightsContent_ttte2_146",
insightsContentWrapper: "_insightsContentWrapper_ttte2_155",
insightsChartWrapper: "_insightsChartWrapper_ttte2_160",
insightsTableWrapper: "_insightsTableWrapper_ttte2_167",
dataLoader: "_dataLoader_ttte2_173",
isDataLoading: "_isDataLoading_ttte2_186",
projectSelect: "_projectSelect_ttte2_208",
PresetButton: "_PresetButton_ttte2_215"
};
var InsightsDashboard_default = /* @__PURE__ */ __plugin_vue_export_helper_default(InsightsDashboard_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": InsightsDashboard_vue_vue_type_style_index_0_lang_module_default }]]);
export { InsightsDashboard_default as default };