1563 lines
51 KiB
JavaScript
Executable File
1563 lines
51 KiB
JavaScript
Executable File
import { d as defineComponent, e as createBlock, g as openBlock, s as N8nCard, K as mergeProps, br as createSlots, w as withCtx, j as createBaseVNode, t as toDisplayString, n as normalizeClass, X as renderSlot, i as createVNode, dK as N8nLoading, _ as _export_sfc, ap as normalizeStyle, b2 as withDirectives, p as N8nText, k as createTextVNode, l as unref, c as useI18n, b3 as vShow, eS as orderBy, eT as requireDebounce, eU as requireIsObject, bS as getDefaultExportFromCjs, h as createElementBlock, f as createCommentVNode, F as Fragment, A as renderList, r as ref, a7 as watch, o as onMounted, Y as nextTick, b1 as onBeforeMount, N as N8nIcon, x as computed, a8 as resolveComponent, P as useDebounce, a as useToast, ax as useDocumentTitle, v as useSettingsStore, bk as useTemplatesStore, u as useUsersStore, a2 as useRoute, b as useRouter, dn as onBeforeRouteLeave, cc as resolveDirective, cZ as N8nInput, m as N8nHeading, q as N8nButton, eV as CREATOR_HUB_URL, V as VIEWS, al as useTelemetry } from "./index--OJ5nhDf.js";
|
|
import { N as NodeList, T as TemplateList } from "./TemplateList-CV9csLUI.js";
|
|
import { T as TemplatesView } from "./TemplatesView-CXSlz1M1.js";
|
|
const _hoisted_1$3 = ["textContent"];
|
|
const _sfc_main$5 = /* @__PURE__ */ defineComponent({
|
|
__name: "CollectionWorkflowCard",
|
|
props: {
|
|
loading: { type: Boolean },
|
|
title: {}
|
|
},
|
|
setup(__props) {
|
|
return (_ctx, _cache) => {
|
|
const _component_n8n_loading = N8nLoading;
|
|
const _component_n8n_card = N8nCard;
|
|
return openBlock(), createBlock(_component_n8n_card, mergeProps({
|
|
class: _ctx.$style.card
|
|
}, _ctx.$attrs), createSlots({
|
|
default: withCtx(() => [
|
|
createVNode(_component_n8n_loading, {
|
|
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"]);
|
|
};
|
|
}
|
|
});
|
|
const card = "_card_p9uhf_123";
|
|
const title$1 = "_title_p9uhf_139";
|
|
const style0$3 = {
|
|
card,
|
|
title: title$1
|
|
};
|
|
const cssModules$3 = {
|
|
"$style": style0$3
|
|
};
|
|
const Card = /* @__PURE__ */ _export_sfc(_sfc_main$5, [["__cssModules", cssModules$3]]);
|
|
const _sfc_main$4 = /* @__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) => {
|
|
const _component_n8n_text = N8nText;
|
|
return openBlock(), createBlock(Card, {
|
|
loading: _ctx.loading,
|
|
title: _ctx.collection.name,
|
|
style: normalizeStyle({ width: _ctx.width })
|
|
}, {
|
|
footer: withCtx(() => [
|
|
createBaseVNode("span", null, [
|
|
withDirectives(createVNode(_component_n8n_text, {
|
|
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, {
|
|
nodes: _ctx.collection.nodes,
|
|
"show-more": false
|
|
}, null, 8, ["nodes"])
|
|
]),
|
|
_: 1
|
|
}, 8, ["loading", "title", "style"]);
|
|
};
|
|
}
|
|
});
|
|
const mixin$6 = {
|
|
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;
|
|
}
|
|
const dragDistanceX = Math.abs(positionX - this.dragStartX);
|
|
const dragDistanceY = Math.abs(positionY - this.dragStartY);
|
|
if (dragDistanceX > 3 * dragDistanceY) {
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const mixin$5 = {
|
|
methods: {
|
|
/**
|
|
* Set window & container width
|
|
*/
|
|
getWidth() {
|
|
if (this.isSSR) {
|
|
return false;
|
|
}
|
|
this.widthWindow = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
|
this.widthContainer = this.$refs.list.clientWidth;
|
|
},
|
|
/**
|
|
* Convert HTML Collection to JS Array
|
|
*/
|
|
htmlCollectionToArray(collection) {
|
|
return Array.prototype.slice.call(collection, 0);
|
|
}
|
|
}
|
|
};
|
|
const mixin$4 = {
|
|
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";
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const mixin$3 = {
|
|
methods: {
|
|
/**
|
|
* Prepare slides classes and styles
|
|
*/
|
|
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");
|
|
}
|
|
},
|
|
/**
|
|
* Prepare slides active/current classes
|
|
*/
|
|
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");
|
|
}
|
|
},
|
|
/**
|
|
* Prepare carousel styles
|
|
*/
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const mixin$2 = {
|
|
props: {
|
|
/**
|
|
* Set the carousel to be the navigation of other carousels
|
|
*/
|
|
asNavFor: {
|
|
type: Array,
|
|
default: function() {
|
|
return [];
|
|
}
|
|
},
|
|
/**
|
|
* Enable autoplay
|
|
*/
|
|
autoplay: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* Autoplay interval in milliseconds
|
|
*/
|
|
autoplaySpeed: {
|
|
type: Number,
|
|
default: 3e3
|
|
},
|
|
/**
|
|
* Enable centered view when slidesToShow > 1
|
|
*/
|
|
centerMode: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* Slides padding in center mode
|
|
*/
|
|
centerPadding: {
|
|
type: String,
|
|
default: "15%"
|
|
},
|
|
/**
|
|
* Slide change delay in milliseconds
|
|
*/
|
|
changeDelay: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
/**
|
|
* Enable dot indicators/pagination
|
|
*/
|
|
dots: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
/**
|
|
* Enable fade effect
|
|
*/
|
|
fade: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* Infinite loop sliding
|
|
*/
|
|
infinite: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
/**
|
|
* Index of slide to start on
|
|
*/
|
|
initialSlide: {
|
|
type: Number,
|
|
default: 0
|
|
},
|
|
/**
|
|
* Enable mobile first calculation for responsive settings
|
|
*/
|
|
mobileFirst: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
/**
|
|
* Enable prev/next navigation buttons
|
|
*/
|
|
navButtons: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
/**
|
|
* All settings as one object
|
|
*/
|
|
options: {
|
|
type: Object,
|
|
default: () => null
|
|
},
|
|
/**
|
|
* Pause autoplay when a dot is hovered
|
|
*/
|
|
pauseOnDotsHover: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* Pause autoplay when a slide is hovered
|
|
*/
|
|
pauseOnHover: {
|
|
type: Boolean,
|
|
default: true
|
|
},
|
|
/**
|
|
* Object containing breakpoints and settings objects
|
|
*/
|
|
responsive: {
|
|
type: Array,
|
|
default: () => null
|
|
},
|
|
/**
|
|
* Enable right-to-left mode
|
|
*/
|
|
rtl: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
/**
|
|
* Number of slides to scroll
|
|
*/
|
|
slidesToScroll: {
|
|
type: Number,
|
|
default: 1
|
|
},
|
|
/**
|
|
* Number of slides to show
|
|
*/
|
|
slidesToShow: {
|
|
type: Number,
|
|
default: 1
|
|
},
|
|
/**
|
|
* Slide animation speed in milliseconds
|
|
*/
|
|
speed: {
|
|
type: Number,
|
|
default: 300
|
|
},
|
|
/**
|
|
* Swipe distance
|
|
*/
|
|
swipeDistance: {
|
|
type: Number,
|
|
default: 50
|
|
},
|
|
/**
|
|
* Throttle delay in milliseconds
|
|
*/
|
|
throttleDelay: {
|
|
type: Number,
|
|
default: 500
|
|
},
|
|
/**
|
|
* Transition timing function
|
|
* Available: ease, linear, ease-in, ease-out, ease-in-out
|
|
*/
|
|
timing: {
|
|
type: String,
|
|
default: "ease",
|
|
validator: (value) => {
|
|
return ["ease", "linear", "ease-in", "ease-out", "ease-in-out"].indexOf(value) !== -1;
|
|
}
|
|
},
|
|
/**
|
|
* Disable Agile carousel
|
|
*/
|
|
unagile: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
computed: {
|
|
// Initial settings based on props and options object
|
|
initialSettings: function() {
|
|
let { options, ...initialSettings } = this.$props;
|
|
if (options) {
|
|
initialSettings = { ...initialSettings, ...options };
|
|
}
|
|
if (initialSettings.responsive) {
|
|
initialSettings.responsive = orderBy(initialSettings.responsive, "breakpoint");
|
|
}
|
|
return initialSettings;
|
|
},
|
|
// Settings for current breakpoint
|
|
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 throttle_1;
|
|
var hasRequiredThrottle;
|
|
function requireThrottle() {
|
|
if (hasRequiredThrottle) return throttle_1;
|
|
hasRequiredThrottle = 1;
|
|
var debounce = requireDebounce(), isObject = requireIsObject();
|
|
var FUNC_ERROR_TEXT = "Expected a function";
|
|
function throttle2(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
|
|
});
|
|
}
|
|
throttle_1 = throttle2;
|
|
return throttle_1;
|
|
}
|
|
var throttleExports = requireThrottle();
|
|
const throttle = /* @__PURE__ */ getDefaultExportFromCjs(throttleExports);
|
|
const mixin$1 = {
|
|
created() {
|
|
this.goTo = throttle(this.goTo, this.throttleDelay);
|
|
this.getWidth = throttle(this.getWidth, 500);
|
|
}
|
|
};
|
|
const mixin = {
|
|
watch: {
|
|
// Recalculate settings
|
|
currentBreakpoint() {
|
|
this.$emit("breakpoint", { breakpoint: this.currentBreakpoint });
|
|
},
|
|
// Watch current slide change
|
|
currentSlide() {
|
|
this.prepareSlidesClasses();
|
|
this.autoplayStartTimestamp = this.settings.autoplay ? +/* @__PURE__ */ new Date() : null;
|
|
this.$emit("after-change", { currentSlide: this.currentSlide });
|
|
},
|
|
// Watch drag distance change
|
|
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" : ""}`;
|
|
}
|
|
},
|
|
// Watch window width change
|
|
widthWindow(newValue, oldValue) {
|
|
if (oldValue) {
|
|
this.prepareCarousel();
|
|
this.toggleFade();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const _sfc_main$3 = {
|
|
name: "agile",
|
|
mixins: [mixin$6, mixin$5, mixin$4, mixin$3, mixin$2, mixin$1, mixin],
|
|
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((item2) => item2.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((item2) => item2).reverse();
|
|
return this.initialSettings.mobileFirst ? breakpoints.find((item2) => item2 < this.widthWindow) || 0 : breakpoints.find((item2) => item2 > 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();
|
|
},
|
|
// Vue 3
|
|
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();
|
|
},
|
|
// Return current breakpoint
|
|
getCurrentBreakpoint() {
|
|
return this.currentBreakpoint;
|
|
},
|
|
// Return settings for current breakpoint
|
|
getCurrentSettings() {
|
|
return this.settings;
|
|
},
|
|
// Return current slide index
|
|
getCurrentSlide() {
|
|
return this.currentSlide;
|
|
},
|
|
// Return initial settings
|
|
getInitialSettings() {
|
|
return this.initialSettings;
|
|
},
|
|
// Go to slide
|
|
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;
|
|
}
|
|
},
|
|
// Go to next slide
|
|
goToNext() {
|
|
if (this.canGoToNext) {
|
|
this.goTo(this.currentSlide + 1);
|
|
}
|
|
},
|
|
// Go to previous slide
|
|
goToPrev() {
|
|
if (this.canGoToPrev) {
|
|
this.goTo(this.currentSlide - 1);
|
|
}
|
|
},
|
|
// Reload carousel
|
|
reload() {
|
|
this.getWidth();
|
|
this.prepareSlides();
|
|
this.prepareCarousel();
|
|
this.toggleFade();
|
|
this.toggleAutoPlay();
|
|
}
|
|
}
|
|
};
|
|
const _hoisted_1$2 = {
|
|
ref: "list",
|
|
class: "agile__list"
|
|
};
|
|
const _hoisted_2$1 = {
|
|
ref: "slidesClonedBefore",
|
|
class: "agile__slides agile__slides--cloned"
|
|
};
|
|
const _hoisted_3 = {
|
|
ref: "slides",
|
|
class: "agile__slides agile__slides--regular"
|
|
};
|
|
const _hoisted_4 = {
|
|
ref: "slidesClonedAfter",
|
|
class: "agile__slides agile__slides--cloned"
|
|
};
|
|
const _hoisted_5 = {
|
|
key: 0,
|
|
class: "agile__caption"
|
|
};
|
|
const _hoisted_6 = {
|
|
key: 1,
|
|
class: "agile__actions"
|
|
};
|
|
const _hoisted_7 = ["disabled"];
|
|
const _hoisted_8 = {
|
|
key: 1,
|
|
ref: "dots",
|
|
class: "agile__dots"
|
|
};
|
|
const _hoisted_9 = ["onClick"];
|
|
const _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);
|
|
}
|
|
const VueAgile = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["render", _sfc_render]]);
|
|
const _sfc_main$2 = /* @__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 scrollLeft2 = carouselScrollPosition.value;
|
|
scrollEnd.value = scrollWidth - width <= scrollLeft2 + 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) => {
|
|
const _component_n8n_icon = N8nIcon;
|
|
return withDirectives((openBlock(), createElementBlock("div", {
|
|
class: normalizeClass(_ctx.$style.container)
|
|
}, [
|
|
createVNode(unref(VueAgile), {
|
|
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(Card, {
|
|
key: `loading-${n}`,
|
|
loading: _ctx.loading
|
|
}, null, 8, ["loading"]);
|
|
}), 128)),
|
|
(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.loading ? [] : _ctx.collections, (collection) => {
|
|
return openBlock(), createBlock(_sfc_main$4, {
|
|
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(_component_n8n_icon, { icon: "chevron-left" })
|
|
], 2), [
|
|
[vShow, _ctx.showNavigation && carouselScrollPosition.value > 0]
|
|
]),
|
|
withDirectives(createBaseVNode("button", {
|
|
class: normalizeClass({ [_ctx.$style.rightButton]: true }),
|
|
onClick: scrollRight
|
|
}, [
|
|
createVNode(_component_n8n_icon, { icon: "chevron-right" })
|
|
], 2), [
|
|
[vShow, _ctx.showNavigation && !scrollEnd.value]
|
|
])
|
|
], 2)), [
|
|
[vShow, _ctx.loading || _ctx.collections.length]
|
|
]);
|
|
};
|
|
}
|
|
});
|
|
const container = "_container_1rskb_123";
|
|
const button$1 = "_button_1rskb_127";
|
|
const leftButton = "_leftButton_1rskb_148 _button_1rskb_127";
|
|
const rightButton = "_rightButton_1rskb_157 _button_1rskb_127";
|
|
const style0$2 = {
|
|
container,
|
|
button: button$1,
|
|
leftButton,
|
|
rightButton
|
|
};
|
|
const cssModules$2 = {
|
|
"$style": style0$2
|
|
};
|
|
const TemplatesInfoCarousel = /* @__PURE__ */ _export_sfc(_sfc_main$2, [["__cssModules", cssModules$2]]);
|
|
const _hoisted_1$1 = ["textContent"];
|
|
const _hoisted_2 = ["data-test-id"];
|
|
const _sfc_main$1 = /* @__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,
|
|
(categories2) => {
|
|
if (categories2.length > 0) {
|
|
sortCategories();
|
|
}
|
|
},
|
|
{
|
|
immediate: true
|
|
}
|
|
);
|
|
return (_ctx, _cache) => {
|
|
const _component_n8n_loading = N8nLoading;
|
|
const _component_el_checkbox = resolveComponent("el-checkbox");
|
|
const _component_n8n_text = N8nText;
|
|
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(_component_n8n_loading, {
|
|
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(_component_el_checkbox, {
|
|
"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(_component_el_checkbox, {
|
|
"model-value": isSelected(category),
|
|
"onUpdate:modelValue": (value) => handleCheckboxChanged(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(_component_n8n_text, {
|
|
size: "small",
|
|
color: "primary"
|
|
}, {
|
|
default: withCtx(() => [
|
|
createTextVNode(" + " + toDisplayString(`${sortedCategories.value.length - _ctx.expandLimit} more`), 1)
|
|
]),
|
|
_: 1
|
|
})
|
|
], 2)) : createCommentVNode("", true)
|
|
], 2);
|
|
};
|
|
}
|
|
});
|
|
const title = "_title_gndmi_123";
|
|
const categories = "_categories_gndmi_128";
|
|
const item = "_item_gndmi_133";
|
|
const button = "_button_gndmi_140";
|
|
const style0$1 = {
|
|
title,
|
|
categories,
|
|
item,
|
|
button
|
|
};
|
|
const cssModules$1 = {
|
|
"$style": style0$1
|
|
};
|
|
const TemplateFilters = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__cssModules", cssModules$1]]);
|
|
const _hoisted_1 = ["textContent"];
|
|
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
__name: "TemplatesSearchView",
|
|
setup(__props) {
|
|
const areCategoriesPrepopulated = ref(false);
|
|
const categories2 = ref([]);
|
|
const loadingCategories = ref(true);
|
|
const loadingCollections = ref(true);
|
|
const loadingWorkflows = ref(true);
|
|
const search2 = 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: categories2.value.map(
|
|
(category) => categoryId === "name" ? category.name : String(category.id)
|
|
),
|
|
search: search2.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 = (search22, category) => {
|
|
const query = Object.assign({}, route.query);
|
|
if (category.length) {
|
|
query.categories = category;
|
|
} else {
|
|
delete query.categories;
|
|
}
|
|
if (search22.length) {
|
|
query.search = search22;
|
|
} else {
|
|
delete query.search;
|
|
}
|
|
void router.replace({ query });
|
|
};
|
|
const updateSearch = () => {
|
|
updateQueryParam(search2.value, categories2.value.map((category) => category.id).join(","));
|
|
void loadWorkflowsAndCollections(false);
|
|
};
|
|
const loadWorkflows = async () => {
|
|
try {
|
|
loadingWorkflows.value = true;
|
|
await templatesStore.getWorkflows({
|
|
search: search2.value,
|
|
categories: categories2.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: categories2.value.map((category) => String(category.id)),
|
|
search: search2.value
|
|
});
|
|
} catch (e) {
|
|
}
|
|
loadingCollections.value = false;
|
|
};
|
|
const updateSearchTracking = (search22, categories22) => {
|
|
if (!search22) {
|
|
return;
|
|
}
|
|
if (searchEventToTrack.value && searchEventToTrack.value.search_string.length > search22.length) {
|
|
return;
|
|
}
|
|
searchEventToTrack.value = {
|
|
search_string: search22,
|
|
workflow_results_count: workflows.value.length,
|
|
collection_results_count: collections.value.length,
|
|
categories_applied: categories22.map(
|
|
(categoryId) => templatesStore.getCategoryById(categoryId.toString())
|
|
),
|
|
wf_template_repo_session_id: templatesStore.currentSessionId
|
|
};
|
|
};
|
|
const trackCategories = () => {
|
|
if (categories2.value.length) {
|
|
telemetry.track("User changed template filters", {
|
|
search_string: search2.value,
|
|
categories_applied: categories2.value,
|
|
wf_template_repo_session_id: templatesStore.currentSessionId
|
|
});
|
|
}
|
|
};
|
|
const loadWorkflowsAndCollections = async (initialLoad) => {
|
|
const _categories = [...categories2.value];
|
|
const _search = search2.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 route2 = router.resolve({ name: page, params: { id } });
|
|
window.open(route2.href, "_blank");
|
|
return;
|
|
} else {
|
|
void 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;
|
|
search2.value = searchText;
|
|
void callDebounced(updateSearch, {
|
|
debounceTime: 500,
|
|
trailing: true
|
|
});
|
|
if (searchText.length === 0) {
|
|
trackSearch();
|
|
}
|
|
};
|
|
const onCategorySelected = (selected) => {
|
|
categories2.value = categories2.value.concat(selected);
|
|
updateSearch();
|
|
trackCategories();
|
|
};
|
|
const onCategoryUnselected = (selected) => {
|
|
categories2.value = categories2.value.filter((category) => category.id !== selected.id);
|
|
updateSearch();
|
|
trackCategories();
|
|
};
|
|
const onCategoriesCleared = () => {
|
|
categories2.value = [];
|
|
updateSearch();
|
|
};
|
|
const onLoadMore = async () => {
|
|
if (workflows.value.length >= totalWorkflows.value) {
|
|
return;
|
|
}
|
|
try {
|
|
loadingWorkflows.value = true;
|
|
await templatesStore.getMoreWorkflows({
|
|
categories: categories2.value.map((category) => category.name),
|
|
search: search2.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") {
|
|
search2.value = route.query.search;
|
|
shouldUpdateSearch = true;
|
|
}
|
|
if (typeof route.query.categories === "string" && route.query.categories.length) {
|
|
const categoriesFromURL = route.query.categories.split(",");
|
|
categories2.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();
|
|
void loadWorkflowsAndCollections(true);
|
|
void 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 _component_n8n_heading = N8nHeading;
|
|
const _component_n8n_button = N8nButton;
|
|
const _component_n8n_icon = N8nIcon;
|
|
const _component_n8n_input = N8nInput;
|
|
const _component_n8n_text = N8nText;
|
|
const _directive_n8n_html = resolveDirective("n8n-html");
|
|
return openBlock(), createBlock(TemplatesView, null, {
|
|
header: withCtx(() => [
|
|
createBaseVNode("div", {
|
|
class: normalizeClass(_ctx.$style.wrapper)
|
|
}, [
|
|
createBaseVNode("div", {
|
|
class: normalizeClass(_ctx.$style.title)
|
|
}, [
|
|
createVNode(_component_n8n_heading, {
|
|
tag: "h1",
|
|
size: "2xlarge"
|
|
}, {
|
|
default: withCtx(() => [
|
|
createTextVNode(toDisplayString(unref(i18n).baseText("templates.heading")), 1)
|
|
]),
|
|
_: 1
|
|
})
|
|
], 2),
|
|
createBaseVNode("div", {
|
|
class: normalizeClass(_ctx.$style.button)
|
|
}, [
|
|
createVNode(_component_n8n_button, {
|
|
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, {
|
|
categories: unref(templatesStore).allCategories,
|
|
"sort-on-populate": areCategoriesPrepopulated.value,
|
|
selected: categories2.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(_component_n8n_input, {
|
|
"model-value": search2.value,
|
|
placeholder: unref(i18n).baseText("templates.searchPlaceholder"),
|
|
clearable: "",
|
|
"data-test-id": "template-search-input",
|
|
"onUpdate:modelValue": onSearchInput,
|
|
onBlur: trackSearch
|
|
}, {
|
|
prefix: withCtx(() => [
|
|
createVNode(_component_n8n_icon, { icon: "search" })
|
|
]),
|
|
_: 1
|
|
}, 8, ["model-value", "placeholder"]),
|
|
withDirectives(createBaseVNode("div", {
|
|
class: normalizeClass(_ctx.$style.carouselContainer)
|
|
}, [
|
|
createBaseVNode("div", {
|
|
class: normalizeClass(_ctx.$style.header)
|
|
}, [
|
|
createVNode(_component_n8n_heading, {
|
|
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, {
|
|
collections: collections.value,
|
|
loading: loadingCollections.value,
|
|
onOpenCollection
|
|
}, null, 8, ["collections", "loading"])
|
|
], 2), [
|
|
[vShow, collections.value.length || loadingCollections.value]
|
|
]),
|
|
createVNode(TemplateList, {
|
|
"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(_component_n8n_text, {
|
|
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
|
|
});
|
|
};
|
|
}
|
|
});
|
|
const wrapper = "_wrapper_15fkc_123";
|
|
const contentWrapper = "_contentWrapper_15fkc_128";
|
|
const filters = "_filters_15fkc_138";
|
|
const search = "_search_15fkc_144";
|
|
const header = "_header_15fkc_156";
|
|
const style0 = {
|
|
wrapper,
|
|
contentWrapper,
|
|
filters,
|
|
search,
|
|
header
|
|
};
|
|
const cssModules = {
|
|
"$style": style0
|
|
};
|
|
const TemplatesSearchView = /* @__PURE__ */ _export_sfc(_sfc_main, [["__cssModules", cssModules]]);
|
|
export {
|
|
TemplatesSearchView as default
|
|
};
|