n8n-editor-ui
Version:
Workflow Editor UI for n8n
1,229 lines (1,228 loc) • 44.2 kB
JavaScript
import { o as __toESM, t as __commonJSMin } from "./chunk-6z4oVpB-.js";
import { C as computed, Cn as toDisplayString, D as createElementBlock, E as createCommentVNode, G as nextTick, Gt as unref, It as ref, M as createVNode, P as defineComponent, T as createBlock, W as mergeProps, Z as onMounted, _ as Fragment, _t as watch, at as renderSlot, bn as normalizeStyle, bt as withCtx, et as openBlock, it as renderList, j as createTextVNode, k as createSlots, p as vShow, q as onBeforeMount, st as resolveDirective, vn as normalizeClass, w as createBaseVNode, xt as withDirectives } from "./vue.runtime.esm-bundler-tP5dCd7J.js";
import { _t as useI18n, c as require_isObject } from "./_MapCache-ficiegRb.js";
import { Lt as ElCheckbox, Sn as N8nButton_default, at as N8nLoading_default, et as N8nCard_default, wn as N8nIcon_default, xn as N8nText_default, yn as N8nHeading_default, yt as N8nInput_default } from "./src-DgvumQTi.js";
import "./en-CF30SCh2.js";
import "./preload-helper-CR0ecmWK.js";
import { t as __plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BwBpWJRZ.js";
import { _ as onBeforeRouteLeave, v as useRoute, y as useRouter } from "./truncate-B1HVeveJ.js";
import { Dr as useUsersStore, O as useTelemetry, Yn as useDocumentTitle, c as useTemplatesStore, gs as useSettingsStore, v as useToast } from "./builder.store-sBTWwxRU.js";
import "./empty-BuGRxzl4.js";
import "./sanitize-html-Cc45ZKm8.js";
import "./CalendarDate-zWqgZMlk.js";
import "./path-browserify-BtCDmZ3_.js";
import { Ro as VIEWS, u as CREATOR_HUB_URL } from "./constants-BbpucWL4.js";
import "./merge-k8vSyyXH.js";
import "./_baseOrderBy-B_6CV8x6.js";
import "./dateformat-CM9k0--B.js";
import { n as require_debounce, t as useDebounce } from "./useDebounce-Bnb8W2LR.js";
import "./nodeIcon-DI2Acud1.js";
import "./NodeIcon-BVhrZNYI.js";
import "./TimeAgo-CWvYoS88.js";
import { t as require_orderBy } from "./orderBy-EuatZUAl.js";
import { t as TemplatesView_default } from "./TemplatesView-oCiQur38.js";
import { n as NodeList_default, t as TemplateList_default } from "./TemplateList-Bhr0TAFO.js";
var _hoisted_1$3 = ["textContent"];
var CollectionWorkflowCard_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "CollectionWorkflowCard",
props: {
loading: { type: Boolean },
title: {}
},
setup(__props) {
return (_ctx, _cache) => {
return openBlock(), createBlock(unref(N8nCard_default), mergeProps({ class: _ctx.$style.card }, _ctx.$attrs), createSlots({
default: withCtx(() => [createVNode(unref(N8nLoading_default), {
loading: _ctx.loading,
rows: 3,
variant: "p"
}, null, 8, ["loading"])]),
_: 2
}, [!_ctx.loading && _ctx.title ? {
name: "header",
fn: withCtx(() => [createBaseVNode("span", {
class: normalizeClass(_ctx.$style.title),
textContent: toDisplayString(_ctx.title)
}, null, 10, _hoisted_1$3)]),
key: "0"
} : void 0, !_ctx.loading ? {
name: "footer",
fn: withCtx(() => [renderSlot(_ctx.$slots, "footer")]),
key: "1"
} : void 0]), 1040, ["class"]);
};
}
});
var CollectionWorkflowCard_vue_vue_type_style_index_0_lang_module_default = {
card: "_card_1goyo_123",
title: "_title_1goyo_139"
};
var CollectionWorkflowCard_default = /* @__PURE__ */ __plugin_vue_export_helper_default(CollectionWorkflowCard_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": CollectionWorkflowCard_vue_vue_type_style_index_0_lang_module_default }]]);
var TemplatesInfoCard_default = /* @__PURE__ */ defineComponent({
__name: "TemplatesInfoCard",
props: {
collection: {},
loading: {
type: Boolean,
default: false
},
showItemCount: {
type: Boolean,
default: true
},
width: {}
},
setup(__props) {
const i18n = useI18n();
return (_ctx, _cache) => {
return openBlock(), createBlock(CollectionWorkflowCard_default, {
loading: _ctx.loading,
title: _ctx.collection.name,
style: normalizeStyle({ width: _ctx.width })
}, {
footer: withCtx(() => [createBaseVNode("span", null, [withDirectives(createVNode(unref(N8nText_default), {
size: "small",
color: "text-light"
}, {
default: withCtx(() => [createTextVNode(toDisplayString(_ctx.collection.workflows.length) + " " + toDisplayString(unref(i18n).baseText("templates.workflows")), 1)]),
_: 1
}, 512), [[vShow, _ctx.showItemCount]])]), createVNode(NodeList_default, {
nodes: _ctx.collection.nodes,
"show-more": false
}, null, 8, ["nodes"])]),
_: 1
}, 8, [
"loading",
"title",
"style"
]);
};
}
});
var handlers_default = { methods: {
handleMouseDown(e) {
this.isMouseDown = true;
if (e.type.indexOf("touch") !== -1) {
this.dragStartX = e.touches[0].clientX;
this.dragStartY = e.touches[0].clientY;
}
if (e.type.indexOf("mouse") !== -1) {
this.dragStartX = e.clientX;
this.dragStartY = e.clientY;
}
},
handleMouseMove(e) {
let positionX;
let positionY;
if (e.type.indexOf("touch") !== -1) {
positionX = e.touches[0].clientX;
positionY = e.touches[0].clientY;
}
if (e.type.indexOf("mouse") !== -1) {
positionX = e.clientX;
positionY = e.clientY;
}
if (Math.abs(positionX - this.dragStartX) > 3 * Math.abs(positionY - this.dragStartY)) {
this.disableScroll();
this.dragDistance = positionX - this.dragStartX;
}
},
handleMouseUp() {
this.isMouseDown = false;
this.enableScroll();
},
handleMouseOver(element) {
if (this.settings.autoplay) {
if (element === "dot" && this.settings.pauseOnDotsHover || element === "track" && this.settings.pauseOnHover) this.isAutoplayPaused = true;
}
},
handleMouseOut(element) {
if (this.settings.autoplay) {
if (element === "dot" && this.settings.pauseOnDotsHover || element === "track" && this.settings.pauseOnHover) this.isAutoplayPaused = false;
}
}
} };
var helpers_default = { methods: {
getWidth() {
if (this.isSSR) return false;
this.widthWindow = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
this.widthContainer = this.$refs.list.clientWidth;
},
htmlCollectionToArray(collection) {
return Array.prototype.slice.call(collection, 0);
}
} };
var methods_default = { methods: {
clearAutoPlayPause() {
clearTimeout(this.autoplayTimeout);
this.autoplayRemaining = null;
},
disableAutoPlay() {
clearInterval(this.autoplayInterval);
this.autoplayInterval = null;
},
disableScroll() {
document.ontouchmove = (e) => e.preventDefault();
},
enableScroll() {
document.ontouchmove = () => true;
},
restartAutoPlay() {
this.disableAutoPlay();
this.toggleAutoPlay();
},
toggleAutoPlay() {
const enabled = !this.settings.unagile && this.settings.autoplay;
if (!this.autoplayInterval && enabled) this.autoplayInterval = setInterval(() => {
if (!document.hidden) if (!this.canGoToNext) this.disableAutoPlay();
else this.goToNext();
}, this.settings.autoplaySpeed);
else this.disableAutoPlay();
},
toggleFade() {
const enabled = !this.settings.unagile && this.settings.fade;
for (let i = 0; i < this.countSlides; i++) {
this.slides[i].style.transition = enabled ? "opacity " + this.settings.timing + " " + this.settings.speed + "ms" : "none";
this.slides[i].style.transform = enabled ? `translate(-${i * this.widthSlide}px)` : "none";
}
}
} };
var preparations_default = { methods: {
prepareSlides() {
this.slides = this.htmlCollectionToArray(this.$refs.slides.children);
if (this.slidesCloned) {
this.slidesClonedBefore = this.htmlCollectionToArray(this.$refs.slidesClonedBefore.children);
this.slidesClonedAfter = this.htmlCollectionToArray(this.$refs.slidesClonedAfter.children);
}
for (const slide of this.slidesAll) slide.classList.add("agile__slide");
},
prepareSlidesClasses() {
if (this.currentSlide === null) return false;
for (let i = 0; i < this.countSlides; i++) {
this.slides[i].classList.remove("agile__slide--active");
this.slides[i].classList.remove("agile__slide--current");
}
setTimeout(() => this.slides[this.currentSlide].classList.add("agile__slide--active"), this.changeDelay);
let start = this.slidesCloned ? this.countSlides + this.currentSlide : this.currentSlide;
if (this.centerMode) start -= Math.floor(this.settings.slidesToShow / 2) - +(this.settings.slidesToShow % 2 === 0);
for (let i = Math.max(start, 0); i < Math.min(start + this.settings.slidesToShow, this.countSlides); i++) this.slidesAll[i].classList.add("agile__slide--current");
},
prepareCarousel() {
if (this.settings.unagile) this.translateX = 0;
else {
if (this.currentSlide === null && this.countSlides) this.currentSlide = this.settings.initialSlide;
if (this.currentSlide > this.countSlides) this.currentSlide = this.countSlides - 1;
this.goTo(this.currentSlide, false, false);
}
}
} };
var import_orderBy = /* @__PURE__ */ __toESM(require_orderBy());
var settings_default = {
props: {
asNavFor: {
type: Array,
default: function() {
return [];
}
},
autoplay: {
type: Boolean,
default: false
},
autoplaySpeed: {
type: Number,
default: 3e3
},
centerMode: {
type: Boolean,
default: false
},
centerPadding: {
type: String,
default: "15%"
},
changeDelay: {
type: Number,
default: 0
},
dots: {
type: Boolean,
default: true
},
fade: {
type: Boolean,
default: false
},
infinite: {
type: Boolean,
default: true
},
initialSlide: {
type: Number,
default: 0
},
mobileFirst: {
type: Boolean,
default: true
},
navButtons: {
type: Boolean,
default: true
},
options: {
type: Object,
default: () => null
},
pauseOnDotsHover: {
type: Boolean,
default: false
},
pauseOnHover: {
type: Boolean,
default: true
},
responsive: {
type: Array,
default: () => null
},
rtl: {
type: Boolean,
default: false
},
slidesToScroll: {
type: Number,
default: 1
},
slidesToShow: {
type: Number,
default: 1
},
speed: {
type: Number,
default: 300
},
swipeDistance: {
type: Number,
default: 50
},
throttleDelay: {
type: Number,
default: 500
},
timing: {
type: String,
default: "ease",
validator: (value) => {
return [
"ease",
"linear",
"ease-in",
"ease-out",
"ease-in-out"
].indexOf(value) !== -1;
}
},
unagile: {
type: Boolean,
default: false
}
},
computed: {
initialSettings: function() {
let { options,...initialSettings } = this.$props;
if (options) initialSettings = {
...initialSettings,
...options
};
if (initialSettings.responsive) initialSettings.responsive = (0, import_orderBy.default)(initialSettings.responsive, "breakpoint");
return initialSettings;
},
settings: function() {
const { responsive,...settings } = this.initialSettings;
if (responsive) responsive.forEach((option) => {
if (settings.mobileFirst ? option.breakpoint < this.widthWindow : option.breakpoint > this.widthWindow) for (const key in option.settings) settings[key] = option.settings[key];
});
return settings;
}
}
};
var import_throttle = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
var debounce = require_debounce(), isObject = require_isObject();
var FUNC_ERROR_TEXT = "Expected a function";
function throttle$1(func, wait, options) {
var leading = true, trailing = true;
if (typeof func != "function") throw new TypeError(FUNC_ERROR_TEXT);
if (isObject(options)) {
leading = "leading" in options ? !!options.leading : leading;
trailing = "trailing" in options ? !!options.trailing : trailing;
}
return debounce(func, wait, {
"leading": leading,
"maxWait": wait,
"trailing": trailing
});
}
module.exports = throttle$1;
})))());
var _sfc_main = {
name: "agile",
mixins: [
handlers_default,
helpers_default,
methods_default,
preparations_default,
settings_default,
{ created() {
this.goTo = (0, import_throttle.default)(this.goTo, this.throttleDelay);
this.getWidth = (0, import_throttle.default)(this.getWidth, 500);
} },
{ watch: {
currentBreakpoint() {
this.$emit("breakpoint", { breakpoint: this.currentBreakpoint });
},
currentSlide() {
this.prepareSlidesClasses();
this.autoplayStartTimestamp = this.settings.autoplay ? +/* @__PURE__ */ new Date() : null;
this.$emit("after-change", { currentSlide: this.currentSlide });
},
dragDistance() {
if (this.isMouseDown) {
const { rtl } = this.settings;
const dragDistance = this.dragDistance * (rtl ? -1 : 1);
if (dragDistance > this.swipeDistance && this.canGoToPrev) {
this.goToPrev();
this.handleMouseUp();
}
if (dragDistance < -1 * this.swipeDistance && this.canGoToNext) {
this.goToNext();
this.handleMouseUp();
}
}
},
isAutoplayPaused(nevValue) {
if (nevValue) {
this.remaining = this.settings.autoplaySpeed - (+/* @__PURE__ */ new Date() - this.autoplayStartTimestamp);
this.disableAutoPlay();
this.clearAutoPlayPause();
} else this.autoplayTimeout = setTimeout(() => {
this.clearAutoPlayPause();
this.goToNext();
this.toggleAutoPlay();
}, this.remaining);
},
"settings.autoplay"() {
this.toggleAutoPlay();
},
"settings.fade"() {
this.toggleFade();
},
"settings.unagile"() {},
widthSlide() {
for (let i = 0; i < this.countSlidesAll; i++) this.slidesAll[i].style.width = `${this.widthSlide}${this.widthSlide !== "auto" ? "px" : ""}`;
},
widthWindow(newValue, oldValue) {
if (oldValue) {
this.prepareCarousel();
this.toggleFade();
}
}
} }
],
emits: [
"before-change",
"after-change",
"breakpoint"
],
data() {
return {
autoplayInterval: null,
autoplayRemaining: null,
autoplayStartTimestamp: null,
autoplayTimeout: null,
currentSlide: null,
dragDistance: 0,
dragStartX: 0,
dragStartY: 0,
isAutoplayPaused: false,
isMouseDown: false,
slides: [],
slidesClonedAfter: [],
slidesClonedBefore: [],
isSSR: typeof window === "undefined",
transitionDelay: 0,
translateX: 0,
widthWindow: 0,
widthContainer: 0
};
},
computed: {
breakpoints: function() {
return !this.initialSettings.responsive ? [] : this.initialSettings.responsive.map((item$1) => item$1.breakpoint);
},
canGoToPrev: function() {
return this.settings.infinite || this.currentSlide > 0;
},
canGoToNext: function() {
return this.settings.infinite || this.currentSlide < this.countSlides - 1;
},
countSlides: function() {
return this.isSSR ? this.htmlCollectionToArray(this.$slots.default).length : this.slides.length;
},
countSlidesAll: function() {
return this.slidesAll.length;
},
currentBreakpoint: function() {
const breakpoints = this.breakpoints.map((item$1) => item$1).reverse();
return this.initialSettings.mobileFirst ? breakpoints.find((item$1) => item$1 < this.widthWindow) || 0 : breakpoints.find((item$1) => item$1 > this.widthWindow) || null;
},
marginX: function() {
if (this.settings.unagile) return 0;
let marginX = this.slidesCloned ? this.countSlides * this.widthSlide : 0;
if (this.settings.centerMode) marginX -= (Math.floor(this.settings.slidesToShow / 2) - +(this.settings.slidesToShow % 2 === 0)) * this.widthSlide;
return this.settings.rtl ? marginX : -1 * marginX;
},
slidesCloned: function() {
return !this.settings.unagile && !this.settings.fade && this.settings.infinite;
},
slidesAll: function() {
return this.slidesCloned ? [
...this.slidesClonedBefore,
...this.slides,
...this.slidesClonedAfter
] : this.slides;
},
widthSlide: function() {
return !this.settings.unagile ? this.widthContainer / this.settings.slidesToShow : "auto";
}
},
mounted() {
window.addEventListener("resize", this.getWidth);
this.$refs.track.addEventListener("touchstart", this.handleMouseDown);
this.$refs.track.addEventListener("touchend", this.handleMouseUp);
this.$refs.track.addEventListener("touchmove", this.handleMouseMove);
this.$refs.track.addEventListener("mousedown", this.handleMouseDown);
this.$refs.track.addEventListener("mouseup", this.handleMouseUp);
this.$refs.track.addEventListener("mousemove", this.handleMouseMove);
this.isSSR = false;
this.reload();
},
beforeUnmount() {
this.destroy();
},
methods: {
destroy() {
window.removeEventListener("resize", this.getWidth);
this.$refs.track.removeEventListener("touchstart", this.handleMouseDown);
this.$refs.track.removeEventListener("touchend", this.handleMouseUp);
this.$refs.track.removeEventListener("touchmove", this.handleMouseMove);
this.$refs.track.removeEventListener("mousedown", this.handleMouseDown);
this.$refs.track.removeEventListener("mouseup", this.handleMouseUp);
this.$refs.track.removeEventListener("mousemove", this.handleMouseMove);
this.disableAutoPlay();
},
getCurrentBreakpoint() {
return this.currentBreakpoint;
},
getCurrentSettings() {
return this.settings;
},
getCurrentSlide() {
return this.currentSlide;
},
getInitialSettings() {
return this.initialSettings;
},
goTo(n, transition = true, asNav = false) {
if (this.settings.unagile) return false;
if (!asNav) this.settings.asNavFor.forEach((carousel) => {
if (carousel) carousel.goTo(n, transition, true);
});
let slideNextReal = n;
if (transition) {
if (this.settings.infinite && n < 0) slideNextReal = this.countSlides - 1;
else if (n >= this.countSlides) slideNextReal = 0;
this.$emit("before-change", {
currentSlide: this.currentSlide,
nextSlide: slideNextReal
});
this.currentSlide = slideNextReal;
if (n !== slideNextReal) setTimeout(() => {
this.goTo(slideNextReal, false);
}, this.settings.speed);
}
const translateX = !this.settings.fade ? n * this.widthSlide * this.settings.slidesToScroll : 0;
this.transitionDelay = transition ? this.speed : 0;
if (this.infinite || this.currentSlide + this.slidesToShow <= this.countSlides) this.translateX = this.settings.rtl ? translateX : -1 * translateX;
},
goToNext() {
if (this.canGoToNext) this.goTo(this.currentSlide + 1);
},
goToPrev() {
if (this.canGoToPrev) this.goTo(this.currentSlide - 1);
},
reload() {
this.getWidth();
this.prepareSlides();
this.prepareCarousel();
this.toggleFade();
this.toggleAutoPlay();
}
}
};
var _hoisted_1$2 = {
ref: "list",
class: "agile__list"
};
var _hoisted_2$1 = {
ref: "slidesClonedBefore",
class: "agile__slides agile__slides--cloned"
};
var _hoisted_3 = {
ref: "slides",
class: "agile__slides agile__slides--regular"
};
var _hoisted_4 = {
ref: "slidesClonedAfter",
class: "agile__slides agile__slides--cloned"
};
var _hoisted_5 = {
key: 0,
class: "agile__caption"
};
var _hoisted_6 = {
key: 1,
class: "agile__actions"
};
var _hoisted_7 = ["disabled"];
var _hoisted_8 = {
key: 1,
ref: "dots",
class: "agile__dots"
};
var _hoisted_9 = ["onClick"];
var _hoisted_10 = ["disabled"];
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return openBlock(), createElementBlock("div", {
class: normalizeClass([{
"agile--ssr": $data.isSSR,
"agile--auto-play": _ctx.settings.autoplay,
"agile--disabled": _ctx.settings.unagile,
"agile--fade": _ctx.settings.fade && !_ctx.settings.unagile,
"agile--rtl": _ctx.settings.rtl,
"agile--no-nav-buttons": !_ctx.settings.navButtons
}, "agile"]),
onTouchstart: () => {}
}, [
createBaseVNode("div", _hoisted_1$2, [createBaseVNode("div", {
ref: "track",
style: normalizeStyle({
transform: `translate(${$data.translateX + $options.marginX}px)`,
transition: `transform ${_ctx.settings.timing} ${$data.transitionDelay}ms`
}),
class: "agile__track",
onMouseout: _cache[0] || (_cache[0] = ($event) => _ctx.handleMouseOut("track")),
onMouseover: _cache[1] || (_cache[1] = ($event) => _ctx.handleMouseOver("track"))
}, [
withDirectives(createBaseVNode("div", _hoisted_2$1, [renderSlot(_ctx.$slots, "default")], 512), [[vShow, $options.slidesCloned]]),
createBaseVNode("div", _hoisted_3, [renderSlot(_ctx.$slots, "default")], 512),
withDirectives(createBaseVNode("div", _hoisted_4, [renderSlot(_ctx.$slots, "default")], 512), [[vShow, $options.slidesCloned]])
], 36)], 512),
_ctx.$slots.caption ? (openBlock(), createElementBlock("div", _hoisted_5, [renderSlot(_ctx.$slots, "caption")])) : createCommentVNode("", true),
!_ctx.settings.unagile && (_ctx.settings.navButtons || _ctx.settings.dots) ? (openBlock(), createElementBlock("div", _hoisted_6, [
_ctx.settings.navButtons && !_ctx.settings.unagile ? (openBlock(), createElementBlock("button", {
key: 0,
ref: "prevButton",
disabled: !$options.canGoToPrev,
"aria-label": "Previous",
class: "agile__nav-button agile__nav-button--prev",
type: "button",
onClick: _cache[2] || (_cache[2] = ($event) => ($options.goToPrev(), _ctx.restartAutoPlay()))
}, [renderSlot(_ctx.$slots, "prevButton", {}, () => [_cache[6] || (_cache[6] = createTextVNode(" ← "))])], 8, _hoisted_7)) : createCommentVNode("", true),
_ctx.settings.dots && !_ctx.settings.unagile ? (openBlock(), createElementBlock("ul", _hoisted_8, [(openBlock(true), createElementBlock(Fragment, null, renderList($options.countSlides, (n) => {
return openBlock(), createElementBlock("li", {
key: n,
class: normalizeClass([{ "agile__dot--current": n - 1 === $data.currentSlide }, "agile__dot"]),
onMouseout: _cache[3] || (_cache[3] = ($event) => _ctx.handleMouseOut("dot")),
onMouseover: _cache[4] || (_cache[4] = ($event) => _ctx.handleMouseOver("dot"))
}, [createBaseVNode("button", {
type: "button",
onClick: ($event) => ($options.goTo(n - 1), _ctx.restartAutoPlay())
}, toDisplayString(n), 9, _hoisted_9)], 34);
}), 128))], 512)) : createCommentVNode("", true),
_ctx.settings.navButtons && !_ctx.settings.unagile ? (openBlock(), createElementBlock("button", {
key: 2,
ref: "nextButton",
disabled: !$options.canGoToNext,
"aria-label": "Next",
class: "agile__nav-button agile__nav-button--next",
type: "button",
onClick: _cache[5] || (_cache[5] = ($event) => ($options.goToNext(), _ctx.restartAutoPlay()))
}, [renderSlot(_ctx.$slots, "nextButton", {}, () => [_cache[7] || (_cache[7] = createTextVNode(" → "))])], 8, _hoisted_10)) : createCommentVNode("", true)
])) : createCommentVNode("", true)
], 34);
}
var Agile_default = /* @__PURE__ */ __plugin_vue_export_helper_default(_sfc_main, [["render", _sfc_render]]);
var TemplatesInfoCarousel_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "TemplatesInfoCarousel",
props: {
collections: {},
loading: {
type: Boolean,
default: false
},
showItemCount: {
type: Boolean,
default: true
},
showNavigation: {
type: Boolean,
default: true
},
cardsWidth: { default: "240px" }
},
emits: ["openCollection"],
setup(__props, { emit: __emit }) {
const props = __props;
const emit = __emit;
const carouselScrollPosition = ref(0);
const cardWidth = ref(parseInt(props.cardsWidth, 10));
const scrollEnd = ref(false);
const listElement = ref(null);
const sliderRef = ref(null);
const updateCarouselScroll = () => {
if (listElement.value) {
carouselScrollPosition.value = Number(listElement.value.scrollLeft.toFixed());
const width = listElement.value.clientWidth;
const scrollWidth = listElement.value.scrollWidth;
const scrollLeft$1 = carouselScrollPosition.value;
scrollEnd.value = scrollWidth - width <= scrollLeft$1 + 7;
}
};
const onCardClick = (event, id) => {
emit("openCollection", {
event,
id
});
};
const scrollLeft = () => {
if (listElement.value) listElement.value.scrollBy({
left: -(cardWidth.value * 2),
top: 0,
behavior: "smooth"
});
};
const scrollRight = () => {
if (listElement.value) listElement.value.scrollBy({
left: cardWidth.value * 2,
top: 0,
behavior: "smooth"
});
};
watch(() => props.collections, () => {
setTimeout(() => {
updateCarouselScroll();
}, 0);
});
watch(() => props.loading, () => {
setTimeout(() => {
updateCarouselScroll();
}, 0);
});
onMounted(async () => {
await nextTick();
if (!sliderRef.value) return;
listElement.value = sliderRef.value.$el.querySelector(".agile__list");
if (listElement.value) listElement.value.addEventListener("scroll", updateCarouselScroll);
});
onBeforeMount(() => {
if (sliderRef.value) sliderRef.value.destroy();
window.addEventListener("scroll", updateCarouselScroll);
});
return (_ctx, _cache) => {
return withDirectives((openBlock(), createElementBlock("div", { class: normalizeClass(_ctx.$style.container) }, [
createVNode(unref(Agile_default), {
ref_key: "sliderRef",
ref: sliderRef,
dots: false,
"nav-buttons": false,
infinite: false,
"slides-to-show": 4,
onAfterChange: updateCarouselScroll
}, {
default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.loading ? 4 : 0, (n) => {
return openBlock(), createBlock(CollectionWorkflowCard_default, {
key: `loading-${n}`,
loading: _ctx.loading
}, null, 8, ["loading"]);
}), 128)), (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.loading ? [] : _ctx.collections, (collection) => {
return openBlock(), createBlock(TemplatesInfoCard_default, {
key: collection.id,
"data-test-id": "templates-info-card",
collection,
"show-item-count": _ctx.showItemCount,
width: _ctx.cardsWidth,
onClick: (e) => onCardClick(e, collection.id)
}, null, 8, [
"collection",
"show-item-count",
"width",
"onClick"
]);
}), 128))]),
_: 1
}, 512),
withDirectives(createBaseVNode("button", {
class: normalizeClass({ [_ctx.$style.leftButton]: true }),
onClick: scrollLeft
}, [createVNode(unref(N8nIcon_default), { icon: "chevron-left" })], 2), [[vShow, _ctx.showNavigation && carouselScrollPosition.value > 0]]),
withDirectives(createBaseVNode("button", {
class: normalizeClass({ [_ctx.$style.rightButton]: true }),
onClick: scrollRight
}, [createVNode(unref(N8nIcon_default), { icon: "chevron-right" })], 2), [[vShow, _ctx.showNavigation && !scrollEnd.value]])
], 2)), [[vShow, _ctx.loading || _ctx.collections.length]]);
};
}
});
var TemplatesInfoCarousel_vue_vue_type_style_index_0_lang_module_default = {
container: "_container_3t1vn_123",
button: "_button_3t1vn_127",
leftButton: "_leftButton_3t1vn_148 _button_3t1vn_127",
rightButton: "_rightButton_3t1vn_157 _button_3t1vn_127"
};
var TemplatesInfoCarousel_default = /* @__PURE__ */ __plugin_vue_export_helper_default(TemplatesInfoCarousel_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": TemplatesInfoCarousel_vue_vue_type_style_index_0_lang_module_default }]]);
var _hoisted_1$1 = ["textContent"];
var _hoisted_2 = ["data-test-id"];
var TemplateFilters_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "TemplateFilters",
props: {
categories: { default: () => [] },
sortOnPopulate: {
type: Boolean,
default: false
},
expandLimit: { default: 12 },
loading: {
type: Boolean,
default: false
},
selected: { default: () => [] }
},
emits: [
"clearAll",
"select",
"clear"
],
setup(__props, { emit: __emit }) {
const props = __props;
const emit = __emit;
const i18n = useI18n();
const collapsed = ref(true);
const sortedCategories = ref([]);
const allSelected = computed(() => {
return props.selected.length === 0;
});
function sortCategories() {
if (!props.sortOnPopulate) sortedCategories.value = props.categories;
else {
const selected = props.selected || [];
const selectedCategories = props.categories.filter((cat) => selected.includes(cat));
const notSelectedCategories = props.categories.filter((cat) => !selected.includes(cat));
sortedCategories.value = selectedCategories.concat(notSelectedCategories);
}
}
function collapseAction() {
collapsed.value = false;
}
function handleCheckboxChanged(value, selectedCategory) {
if (value) emit("select", selectedCategory);
else emit("clear", selectedCategory);
}
function isSelected(category) {
return props.selected.includes(category);
}
function resetCategories() {
emit("clearAll");
}
watch(() => props.sortOnPopulate, (value) => {
if (value) sortCategories();
}, { immediate: true });
watch(() => props.categories, (categories$1) => {
if (categories$1.length > 0) sortCategories();
}, { immediate: true });
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
class: normalizeClass([_ctx.$style.filters, "template-filters"]),
"data-test-id": "templates-filter-container"
}, [
createBaseVNode("div", {
class: normalizeClass(_ctx.$style.title),
textContent: toDisplayString(unref(i18n).baseText("templates.categoriesHeading"))
}, null, 10, _hoisted_1$1),
_ctx.loading ? (openBlock(), createElementBlock("div", {
key: 0,
class: normalizeClass(_ctx.$style.list)
}, [createVNode(unref(N8nLoading_default), {
loading: _ctx.loading,
rows: _ctx.expandLimit
}, null, 8, ["loading", "rows"])], 2)) : createCommentVNode("", true),
!_ctx.loading ? (openBlock(), createElementBlock("ul", {
key: 1,
class: normalizeClass(_ctx.$style.categories)
}, [createBaseVNode("li", {
class: normalizeClass(_ctx.$style.item),
"data-test-id": "template-filter-all-categories"
}, [createVNode(unref(ElCheckbox), {
"model-value": allSelected.value,
"onUpdate:modelValue": _cache[0] || (_cache[0] = () => resetCategories())
}, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("templates.allCategories")), 1)]),
_: 1
}, 8, ["model-value"])], 2), (openBlock(true), createElementBlock(Fragment, null, renderList(collapsed.value ? sortedCategories.value.slice(0, _ctx.expandLimit) : sortedCategories.value, (category, index) => {
return openBlock(), createElementBlock("li", {
key: index,
class: normalizeClass(_ctx.$style.item),
"data-test-id": `template-filter-${category.name.toLowerCase().replaceAll(" ", "-")}`
}, [createVNode(unref(ElCheckbox), {
"model-value": isSelected(category),
"onUpdate:modelValue": (value) => handleCheckboxChanged(typeof value === "boolean" ? value : Boolean(value), category)
}, {
default: withCtx(() => [createTextVNode(toDisplayString(category.name), 1)]),
_: 2
}, 1032, ["model-value", "onUpdate:modelValue"])], 10, _hoisted_2);
}), 128))], 2)) : createCommentVNode("", true),
sortedCategories.value.length > _ctx.expandLimit && collapsed.value && !_ctx.loading ? (openBlock(), createElementBlock("div", {
key: 2,
class: normalizeClass(_ctx.$style.button),
"data-test-id": "expand-categories-button",
onClick: collapseAction
}, [createVNode(unref(N8nText_default), {
size: "small",
color: "primary"
}, {
default: withCtx(() => [createTextVNode(" + " + toDisplayString(`${sortedCategories.value.length - _ctx.expandLimit} more`), 1)]),
_: 1
})], 2)) : createCommentVNode("", true)
], 2);
};
}
});
var TemplateFilters_vue_vue_type_style_index_0_lang_module_default = {
title: "_title_jr0i7_123",
categories: "_categories_jr0i7_128",
item: "_item_jr0i7_133",
button: "_button_jr0i7_140"
};
var TemplateFilters_default = /* @__PURE__ */ __plugin_vue_export_helper_default(TemplateFilters_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": TemplateFilters_vue_vue_type_style_index_0_lang_module_default }]]);
var _hoisted_1 = ["textContent"];
var TemplatesSearchView_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
__name: "TemplatesSearchView",
setup(__props) {
const areCategoriesPrepopulated = ref(false);
const categories$1 = ref([]);
const loadingCategories = ref(true);
const loadingCollections = ref(true);
const loadingWorkflows = ref(true);
const search$1 = ref("");
const searchEventToTrack = ref(null);
const errorLoadingWorkflows = ref(false);
const { callDebounced } = useDebounce();
const toast = useToast();
const documentTitle = useDocumentTitle();
const settingsStore = useSettingsStore();
const templatesStore = useTemplatesStore();
const usersStore = useUsersStore();
const i18n = useI18n();
const route = useRoute();
const router = useRouter();
const telemetry = useTelemetry();
const createQueryObject = (categoryId) => {
return {
categories: categories$1.value.map((category) => categoryId === "name" ? category.name : String(category.id)),
search: search$1.value
};
};
const totalWorkflows = computed(() => templatesStore.getSearchedWorkflowsTotal(createQueryObject("name")));
const workflows = computed(() => templatesStore.getSearchedWorkflows(createQueryObject("name")) ?? []);
const collections = computed(() => templatesStore.getSearchedCollections(createQueryObject("id")) ?? []);
const endOfSearchMessage = computed(() => {
if (loadingWorkflows.value) return null;
if (!loadingCollections.value && workflows.value.length === 0 && collections.value.length === 0) {
if (!settingsStore.isTemplatesEndpointReachable && errorLoadingWorkflows.value) return i18n.baseText("templates.connectionWarning");
return i18n.baseText("templates.noSearchResults");
}
return null;
});
const updateQueryParam = (search$2, category) => {
const query = Object.assign({}, route.query);
if (category.length) query.categories = category;
else delete query.categories;
if (search$2.length) query.search = search$2;
else delete query.search;
router.replace({ query });
};
const updateSearch = () => {
updateQueryParam(search$1.value, categories$1.value.map((category) => category.id).join(","));
loadWorkflowsAndCollections(false);
};
const loadWorkflows = async () => {
try {
loadingWorkflows.value = true;
await templatesStore.getWorkflows({
search: search$1.value,
categories: categories$1.value.map((category) => category.name)
});
errorLoadingWorkflows.value = false;
} catch (e) {
errorLoadingWorkflows.value = true;
}
loadingWorkflows.value = false;
};
const loadCollections = async () => {
try {
loadingCollections.value = true;
await templatesStore.getCollections({
categories: categories$1.value.map((category) => String(category.id)),
search: search$1.value
});
} catch (e) {}
loadingCollections.value = false;
};
const updateSearchTracking = (search$2, categories$2) => {
if (!search$2) return;
if (searchEventToTrack.value && searchEventToTrack.value.search_string.length > search$2.length) return;
searchEventToTrack.value = {
search_string: search$2,
workflow_results_count: workflows.value.length,
collection_results_count: collections.value.length,
categories_applied: categories$2.map((categoryId) => templatesStore.getCategoryById(categoryId.toString())),
wf_template_repo_session_id: templatesStore.currentSessionId
};
};
const trackCategories = () => {
if (categories$1.value.length) telemetry.track("User changed template filters", {
search_string: search$1.value,
categories_applied: categories$1.value,
wf_template_repo_session_id: templatesStore.currentSessionId
});
};
const loadWorkflowsAndCollections = async (initialLoad) => {
const _categories = [...categories$1.value];
const _search = search$1.value;
await Promise.all([loadWorkflows(), loadCollections()]);
if (!initialLoad) updateSearchTracking(_search, _categories.map((category) => category.id));
};
const navigateTo = (e, page, id) => {
if (e.metaKey || e.ctrlKey) {
const route$1 = router.resolve({
name: page,
params: { id }
});
window.open(route$1.href, "_blank");
return;
} else router.push({
name: page,
params: { id }
});
};
const onOpenCollection = ({ event, id }) => {
navigateTo(event, VIEWS.COLLECTION, id);
};
const onOpenTemplate = ({ event, id }) => {
navigateTo(event, VIEWS.TEMPLATE, id);
};
const trackSearch = () => {
if (searchEventToTrack.value) {
telemetry.track("User searched workflow templates", searchEventToTrack.value);
searchEventToTrack.value = null;
}
};
const onSearchInput = (searchText) => {
loadingWorkflows.value = true;
loadingCollections.value = true;
search$1.value = searchText;
callDebounced(updateSearch, {
debounceTime: 500,
trailing: true
});
if (searchText.length === 0) trackSearch();
};
const onCategorySelected = (selected) => {
categories$1.value = categories$1.value.concat(selected);
updateSearch();
trackCategories();
};
const onCategoryUnselected = (selected) => {
categories$1.value = categories$1.value.filter((category) => category.id !== selected.id);
updateSearch();
trackCategories();
};
const onCategoriesCleared = () => {
categories$1.value = [];
updateSearch();
};
const onLoadMore = async () => {
if (workflows.value.length >= totalWorkflows.value) return;
try {
loadingWorkflows.value = true;
await templatesStore.getMoreWorkflows({
categories: categories$1.value.map((category) => category.name),
search: search$1.value
});
} catch (e) {
toast.showMessage({
title: "Error",
message: "Could not load more workflows",
type: "error"
});
} finally {
loadingWorkflows.value = false;
}
};
const loadCategories = async () => {
try {
await templatesStore.getCategories();
} catch (e) {}
loadingCategories.value = false;
};
const scrollTo = (position, behavior = "smooth") => {
setTimeout(() => {
const contentArea = document.getElementById("content");
if (contentArea) contentArea.scrollTo({
top: position,
behavior
});
}, 0);
};
const restoreSearchFromRoute = () => {
let shouldUpdateSearch = false;
if (route.query.search && typeof route.query.search === "string") {
search$1.value = route.query.search;
shouldUpdateSearch = true;
}
if (typeof route.query.categories === "string" && route.query.categories.length) {
const categoriesFromURL = route.query.categories.split(",");
categories$1.value = templatesStore.allCategories.filter((category) => categoriesFromURL.includes(category.id.toString()));
shouldUpdateSearch = true;
}
if (shouldUpdateSearch) {
updateSearch();
trackCategories();
areCategoriesPrepopulated.value = true;
}
};
onMounted(async () => {
documentTitle.set("Templates");
await loadCategories();
loadWorkflowsAndCollections(true);
usersStore.showPersonalizationSurvey();
restoreSearchFromRoute();
if (settingsStore.isTemplatesEnabled) settingsStore.testTemplatesEndpoint().catch(() => {});
setTimeout(() => {
const scrollOffset = route.meta?.scrollOffset;
if (typeof scrollOffset === "number" && scrollOffset > 0) scrollTo(scrollOffset, "auto");
}, 100);
});
onBeforeRouteLeave((_to, _from, next) => {
const contentArea = document.getElementById("content");
if (contentArea) route.meta?.setScrollPosition?.(contentArea.scrollTop);
trackSearch();
next();
});
watch(workflows, (newWorkflows) => {
if (newWorkflows.length === 0) window.scrollTo(0, 0);
});
return (_ctx, _cache) => {
const _directive_n8n_html = resolveDirective("n8n-html");
return openBlock(), createBlock(TemplatesView_default, null, {
header: withCtx(() => [createBaseVNode("div", { class: normalizeClass(_ctx.$style.wrapper) }, [createBaseVNode("div", { class: normalizeClass(_ctx.$style.title) }, [createVNode(unref(N8nHeading_default), {
tag: "h1",
size: "2xlarge"
}, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("templates.heading")), 1)]),
_: 1
})], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.button) }, [createVNode(unref(N8nButton_default), {
size: "large",
type: "secondary",
element: "a",
href: unref(CREATOR_HUB_URL),
label: unref(i18n).baseText("templates.shareWorkflow"),
target: "_blank"
}, null, 8, ["href", "label"])], 2)], 2)]),
content: withCtx(() => [createBaseVNode("div", { class: normalizeClass(_ctx.$style.contentWrapper) }, [createBaseVNode("div", { class: normalizeClass(_ctx.$style.filters) }, [createVNode(TemplateFilters_default, {
categories: unref(templatesStore).allCategories,
"sort-on-populate": areCategoriesPrepopulated.value,
selected: categories$1.value,
loading: loadingCategories.value,
onClear: onCategoryUnselected,
onClearAll: onCategoriesCleared,
onSelect: onCategorySelected
}, null, 8, [
"categories",
"sort-on-populate",
"selected",
"loading"
])], 2), createBaseVNode("div", { class: normalizeClass(_ctx.$style.search) }, [
createVNode(unref(N8nInput_default), {
"model-value": search$1.value,
placeholder: unref(i18n).baseText("templates.searchPlaceholder"),
clearable: "",
"data-test-id": "template-search-input",
"onUpdate:modelValue": onSearchInput,
onBlur: trackSearch
}, {
prefix: withCtx(() => [createVNode(unref(N8nIcon_default), { icon: "search" })]),
_: 1
}, 8, ["model-value", "placeholder"]),
withDirectives(createBaseVNode("div", { class: normalizeClass(_ctx.$style.carouselContainer) }, [createBaseVNode("div", { class: normalizeClass(_ctx.$style.header) }, [createVNode(unref(N8nHeading_default), {
bold: true,
size: "medium",
color: "text-light"
}, {
default: withCtx(() => [createTextVNode(toDisplayString(unref(i18n).baseText("templates.collections")) + " ", 1), !loadingCollections.value ? (openBlock(), createElementBlock("span", {
key: 0,
"data-test-id": "collection-count-label",
textContent: toDisplayString(`(${collections.value.length})`)
}, null, 8, _hoisted_1)) : createCommentVNode("", true)]),
_: 1
})], 2), createVNode(TemplatesInfoCarousel_default, {
collections: collections.value,
loading: loadingCollections.value,
onOpenCollection
}, null, 8, ["collections", "loading"])], 2), [[vShow, collections.value.length || loadingCollections.value]]),
createVNode(TemplateList_default, {
"infinite-scroll-enabled": true,
loading: loadingWorkflows.value,
workflows: workflows.value,
"total-count": totalWorkflows.value,
onLoadMore,
onOpenTemplate
}, null, 8, [
"loading",
"workflows",
"total-count"
]),
endOfSearchMessage.value ? (openBlock(), createElementBlock("div", {
key: 0,
class: normalizeClass(_ctx.$style.endText)
}, [createVNode(unref(N8nText_default), {
size: "medium",
color: "text-base"
}, {
default: withCtx(() => [withDirectives(createBaseVNode("span", null, null, 512), [[_directive_n8n_html, endOfSearchMessage.value]])]),
_: 1
})], 2)) : createCommentVNode("", true)
], 2)], 2)]),
_: 1
});
};
}
});
var TemplatesSearchView_vue_vue_type_style_index_0_lang_module_default = {
wrapper: "_wrapper_xumc9_123",
contentWrapper: "_contentWrapper_xumc9_128",
filters: "_filters_xumc9_138",
search: "_search_xumc9_144",
header: "_header_xumc9_156"
};
var TemplatesSearchView_default = /* @__PURE__ */ __plugin_vue_export_helper_default(TemplatesSearchView_vue_vue_type_script_setup_true_lang_default, [["__cssModules", { "$style": TemplatesSearchView_vue_vue_type_style_index_0_lang_module_default }]]);
export { TemplatesSearchView_default as default };