UNPKG

n8n-editor-ui

Version:

Workflow Editor UI for n8n

773 lines 50.5 kB
;
(function () {
  System.register(["./vue.runtime.esm-bundler-legacy--Sn1h8On.js", "./_MapCache-legacy-DlYNX_X1.js", "./src-legacy-uZTNWMC0.js", "./_plugin-vue_export-helper-legacy-DZMI5HPp.js", "./truncate-legacy-BGje52Or.js", "./useTelemetry-legacy-B3pzzkAE.js", "./constants-legacy-TKxWCqvM.js", "./useDebounce-legacy-CqZ-fJEm.js", "./readyToRun.store-legacy-D5fQDMhh.js", "./PageViewLayout-legacy-DaVsi9BM.js", "./ResourceFiltersDropdown-legacy-xoxQ657s.js"], function (_export, _context) {
    "use strict";

    var computed, toDisplayString, createElementBlock, createCommentVNode, nextTick, unref, guardReactiveProps, ref, onBeforeUnmount, createVNode, defineComponent, createBlock, onMounted, Fragment, watch, renderSlot, withCtx, openBlock, renderList, createTextVNode, vShow, useSlots, normalizeClass, createBaseVNode, withDirectives, normalizeProps, useI18n, useLocalStorage, N8nActionBox_default, ElPagination, N8nInfoTip_default, N8nSelect_default, N8nOption_default, N8nDatatable_default, N8nText_default, N8nIcon_default, N8nLoading_default, N8nLink_default, N8nRecycleScroller_default, N8nInput_default, __plugin_vue_export_helper_default, useRoute, useRouter, isResourceSortableByDate, useUsersStore, isSharedResource, isBaseTextKey, useTelemetry, LOCAL_STORAGE_WORKFLOW_LIST_PREFERENCES_KEY, useDebounce, useProjectPages, PageViewLayout_default, ResourceFiltersDropdown_default, __vite_style__, PageViewLayoutList_vue_vue_type_script_setup_true_lang_default, wrapper, overflow, list, body, PageViewLayoutList_vue_vue_type_style_index_0_lang_module_default, cssModules$1, PageViewLayoutList_default, _hoisted_1, _hoisted_2, _hoisted_3, _hoisted_4, ResourcesListLayout_vue_vue_type_script_setup_true_lang_default, filters, search, listWrapper, paginatedListWrapper, listItems, listPagination, datatable, ResourcesListLayout_vue_vue_type_style_index_0_lang_module_default, cssModules, ResourcesListLayout_default;
    //#endregion
    //#region src/app/composables/useN8nLocalStorage.ts
    /**
    * Simple n8n wrapper around vueuse's useLocalStorage.
    * Provides util functions to read and write n8n values to local storage.
    * Currently only used for workflow list user preferences.
    */
    function useN8nLocalStorage() {
      const projectPages = useProjectPages();
      const getProjectKey = projectId => {
        return projectPages.isOverviewSubPage ? "home" : projectId;
      };
      const saveProjectPreferencesToLocalStorage = (projectId, tabKey, preferences) => {
        const projectKey = getProjectKey(projectId);
        if (!projectKey) return;
        const localStorage = useLocalStorage(LOCAL_STORAGE_WORKFLOW_LIST_PREFERENCES_KEY, {});
        if (!localStorage.value[projectKey]) localStorage.value[projectKey] = {};
        localStorage.value[projectKey][tabKey] = {
          ...localStorage.value[projectKey][tabKey],
          ...preferences
        };
      };
      const loadProjectPreferencesFromLocalStorage = (projectId, tabKey) => {
        const projectKey = getProjectKey(projectId);
        if (!projectKey) return {};
        return useLocalStorage("N8N_WORKFLOWS_LIST_PREFERENCES", {}).value[projectKey]?.[tabKey] || {};
      };
      return {
        saveProjectPreferencesToLocalStorage,
        loadProjectPreferencesFromLocalStorage,
        getProjectKey
      };
    }

    //#endregion
    //#region src/app/composables/useResourcesListI18n.ts
    /**
    * Composable for handling i18n in ResourcesListLayout with dynamic resource keys
    * It provides fallback functionality for translation keys
    */
    function useResourcesListI18n(resourceKey) {
      const i18n = useI18n();
      /**
      * Get a translated text with fallback support for dynamic resource keys
      * First tries the specific resource key, then falls back to generic keys
      */
      const getResourceText = (keySuffix, fallbackKeySuffix, interpolate) => {
        const specificKey = `${resourceKey}.${keySuffix}`;
        const genericKey = `resources.${keySuffix}`;
        const fallbackKey = fallbackKeySuffix ? `resources.${fallbackKeySuffix}` : void 0;
        if (isBaseTextKey(specificKey)) return i18n.baseText(specificKey, {
          interpolate
        });
        if (isBaseTextKey(genericKey)) return i18n.baseText(genericKey, {
          interpolate
        });
        if (fallbackKey && isBaseTextKey(fallbackKey)) return i18n.baseText(fallbackKey, {
          interpolate
        });
        return keySuffix.split(".").pop()?.replace(/([A-Z])/g, " $1").trim() || keySuffix;
      };
      return {
        getResourceText
      };
    }

    //#endregion
    //#region src/app/components/layouts/ResourcesListLayout.vue?vue&type=script&setup=true&lang.ts
    return {
      setters: [function (_vueRuntimeEsmBundlerLegacy003Js) {
        computed = _vueRuntimeEsmBundlerLegacy003Js.C;
        toDisplayString = _vueRuntimeEsmBundlerLegacy003Js.Cn;
        createElementBlock = _vueRuntimeEsmBundlerLegacy003Js.D;
        createCommentVNode = _vueRuntimeEsmBundlerLegacy003Js.E;
        nextTick = _vueRuntimeEsmBundlerLegacy003Js.G;
        unref = _vueRuntimeEsmBundlerLegacy003Js.Gt;
        guardReactiveProps = _vueRuntimeEsmBundlerLegacy003Js.I;
        ref = _vueRuntimeEsmBundlerLegacy003Js.It;
        onBeforeUnmount = _vueRuntimeEsmBundlerLegacy003Js.J;
        createVNode = _vueRuntimeEsmBundlerLegacy003Js.M;
        defineComponent = _vueRuntimeEsmBundlerLegacy003Js.P;
        createBlock = _vueRuntimeEsmBundlerLegacy003Js.T;
        onMounted = _vueRuntimeEsmBundlerLegacy003Js.Z;
        Fragment = _vueRuntimeEsmBundlerLegacy003Js._;
        watch = _vueRuntimeEsmBundlerLegacy003Js._t;
        renderSlot = _vueRuntimeEsmBundlerLegacy003Js.at;
        withCtx = _vueRuntimeEsmBundlerLegacy003Js.bt;
        openBlock = _vueRuntimeEsmBundlerLegacy003Js.et;
        renderList = _vueRuntimeEsmBundlerLegacy003Js.it;
        createTextVNode = _vueRuntimeEsmBundlerLegacy003Js.j;
        vShow = _vueRuntimeEsmBundlerLegacy003Js.p;
        useSlots = _vueRuntimeEsmBundlerLegacy003Js.pt;
        normalizeClass = _vueRuntimeEsmBundlerLegacy003Js.vn;
        createBaseVNode = _vueRuntimeEsmBundlerLegacy003Js.w;
        withDirectives = _vueRuntimeEsmBundlerLegacy003Js.xt;
        normalizeProps = _vueRuntimeEsmBundlerLegacy003Js.yn;
      }, function (_MapCacheLegacy005Js) {
        useI18n = _MapCacheLegacy005Js.gt;
        useLocalStorage = _MapCacheLegacy005Js.j;
      }, function (_srcLegacy007Js) {
        N8nActionBox_default = _srcLegacy007Js.Ct;
        ElPagination = _srcLegacy007Js.Dt;
        N8nInfoTip_default = _srcLegacy007Js.F;
        N8nSelect_default = _srcLegacy007Js.G;
        N8nOption_default = _srcLegacy007Js.K;
        N8nDatatable_default = _srcLegacy007Js.U;
        N8nText_default = _srcLegacy007Js.Vn;
        N8nIcon_default = _srcLegacy007Js.Wn;
        N8nLoading_default = _srcLegacy007Js.tt;
        N8nLink_default = _srcLegacy007Js.ut;
        N8nRecycleScroller_default = _srcLegacy007Js.x;
        N8nInput_default = _srcLegacy007Js.yt;
      }, function (_pluginVue_exportHelperLegacy00fJs) {
        __plugin_vue_export_helper_default = _pluginVue_exportHelperLegacy00fJs.t;
      }, function (_truncateLegacy00hJs) {
        useRoute = _truncateLegacy00hJs.v;
        useRouter = _truncateLegacy00hJs.y;
      }, function (_useTelemetryLegacy00HJs) {
        isResourceSortableByDate = _useTelemetryLegacy00HJs.dr;
        useUsersStore = _useTelemetryLegacy00HJs.nr;
        isSharedResource = _useTelemetryLegacy00HJs.pr;
        isBaseTextKey = _useTelemetryLegacy00HJs.rr;
        useTelemetry = _useTelemetryLegacy00HJs.t;
      }, function (_constantsLegacy00TJs) {
        LOCAL_STORAGE_WORKFLOW_LIST_PREFERENCES_KEY = _constantsLegacy00TJs.Ls;
      }, function (_useDebounceLegacy011Js) {
        useDebounce = _useDebounceLegacy011Js.t;
      }, function (_readyToRunStoreLegacy04fJs) {
        useProjectPages = _readyToRunStoreLegacy04fJs.n;
      }, function (_PageViewLayoutLegacy04FJs) {
        PageViewLayout_default = _PageViewLayoutLegacy04FJs.t;
      }, function (_ResourceFiltersDropdownLegacy04RJs) {
        ResourceFiltersDropdown_default = _ResourceFiltersDropdownLegacy04RJs.t;
      }],
      execute: function () {
        __vite_style__ = document.createElement('style');
        __vite_style__.textContent = "/* BEM support Func\n -------------------------- */\n/* Transition\n-------------------------- */\n/* Color\n-------------------------- */\n/* Link\n-------------------------- */\n/* Border\n-------------------------- */\n/* Outline\n-------------------------- */\n/* Box shadow\n-------------------------- */\n/* Fill\n-------------------------- */\n/* Typography\n-------------------------- */\n/* z-index\n-------------------------- */\n/* Disable base\n-------------------------- */\n/* Icon\n-------------------------- */\n/* Checkbox\n-------------------------- */\n/* Radio\n-------------------------- */\n/* Select\n-------------------------- */\n/* Alert\n-------------------------- */\n/* MessageBox\n-------------------------- */\n/* Message\n-------------------------- */\n/* Notification\n-------------------------- */\n/* Input\n-------------------------- */\n/* Cascader\n-------------------------- */\n/* Group\n-------------------------- */\n/* Tab\n-------------------------- */\n/* Button\n-------------------------- */\n/* cascader\n-------------------------- */\n/* Switch\n-------------------------- */\n/* Dialog\n-------------------------- */\n/* Table\n-------------------------- */\n/* Pagination\n-------------------------- */\n/* Popup\n-------------------------- */\n/* Popover\n-------------------------- */\n/* Tooltip\n-------------------------- */\n/* Tag\n-------------------------- */\n/* Tree\n-------------------------- */\n/* Dropdown\n-------------------------- */\n/* Badge\n-------------------------- */\n/* Card\n--------------------------*/\n/* Slider\n--------------------------*/\n/* Steps\n--------------------------*/\n/* Menu\n--------------------------*/\n/* Rate\n--------------------------*/\n/* DatePicker\n--------------------------*/\n/* Loading\n--------------------------*/\n/* Scrollbar\n--------------------------*/\n/* Carousel\n--------------------------*/\n/* Collapse\n--------------------------*/\n/* Transfer\n--------------------------*/\n/* Header\n  --------------------------*/\n/* Footer\n--------------------------*/\n/* Main\n--------------------------*/\n/* Timeline\n--------------------------*/\n/* Backtop\n--------------------------*/\n/* Link\n--------------------------*/\n/* Calendar\n--------------------------*/\n/* Form\n-------------------------- */\n/* Avatar\n--------------------------*/\n/* Break-point\n--------------------------*/\n/* Break-points\n -------------------------- */\n/* Scrollbar\n -------------------------- */\n/* Placeholder\n -------------------------- */\n/* BEM\n -------------------------- */\n._wrapper_hn9dc_123 {\n  display: grid;\n  height: 100%;\n}\n._overflow_hn9dc_128 ._list_hn9dc_128 ._body_hn9dc_128 {\n  overflow: auto;\n}\n._list_hn9dc_128 {\n  display: grid;\n  grid-template-rows: auto 1fr;\n  height: 100%;\n}\n._list_hn9dc_128 ._body_hn9dc_128 {\n  position: relative;\n  height: 100%;\n}/* BEM support Func\n -------------------------- */\n/* Transition\n-------------------------- */\n/* Color\n-------------------------- */\n/* Link\n-------------------------- */\n/* Border\n-------------------------- */\n/* Outline\n-------------------------- */\n/* Box shadow\n-------------------------- */\n/* Fill\n-------------------------- */\n/* Typography\n-------------------------- */\n/* z-index\n-------------------------- */\n/* Disable base\n-------------------------- */\n/* Icon\n-------------------------- */\n/* Checkbox\n-------------------------- */\n/* Radio\n-------------------------- */\n/* Select\n-------------------------- */\n/* Alert\n-------------------------- */\n/* MessageBox\n-------------------------- */\n/* Message\n-------------------------- */\n/* Notification\n-------------------------- */\n/* Input\n-------------------------- */\n/* Cascader\n-------------------------- */\n/* Group\n-------------------------- */\n/* Tab\n-------------------------- */\n/* Button\n-------------------------- */\n/* cascader\n-------------------------- */\n/* Switch\n-------------------------- */\n/* Dialog\n-------------------------- */\n/* Table\n-------------------------- */\n/* Pagination\n-------------------------- */\n/* Popup\n-------------------------- */\n/* Popover\n-------------------------- */\n/* Tooltip\n-------------------------- */\n/* Tag\n-------------------------- */\n/* Tree\n-------------------------- */\n/* Dropdown\n-------------------------- */\n/* Badge\n-------------------------- */\n/* Card\n--------------------------*/\n/* Slider\n--------------------------*/\n/* Steps\n--------------------------*/\n/* Menu\n--------------------------*/\n/* Rate\n--------------------------*/\n/* DatePicker\n--------------------------*/\n/* Loading\n--------------------------*/\n/* Scrollbar\n--------------------------*/\n/* Carousel\n--------------------------*/\n/* Collapse\n--------------------------*/\n/* Transfer\n--------------------------*/\n/* Header\n  --------------------------*/\n/* Footer\n--------------------------*/\n/* Main\n--------------------------*/\n/* Timeline\n--------------------------*/\n/* Backtop\n--------------------------*/\n/* Link\n--------------------------*/\n/* Calendar\n--------------------------*/\n/* Form\n-------------------------- */\n/* Avatar\n--------------------------*/\n/* Break-point\n--------------------------*/\n/* Break-points\n -------------------------- */\n/* Scrollbar\n -------------------------- */\n/* Placeholder\n -------------------------- */\n/* BEM\n -------------------------- */\n._filters-row_lkzqj_123 {\n  display: flex;\n  flex-direction: row;\n  align-items: center;\n  justify-content: space-between;\n  width: 100%;\n  gap: var(--spacing--2xs);\n}\n._filters_lkzqj_123 {\n  display: grid;\n  grid-auto-flow: column;\n  grid-auto-columns: 1fr max-content max-content max-content;\n  gap: var(--spacing--4xs);\n  align-items: center;\n  justify-content: end;\n  width: 100%;\n}\n._filters_lkzqj_123 ._sort-and-filter_lkzqj_141 {\n  display: flex;\n  gap: var(--spacing--4xs);\n  align-items: center;\n}\n@media screen and (max-width: 767px) {\n._filters_lkzqj_123 {\n    grid-auto-flow: row;\n    grid-auto-columns: unset;\n    grid-template-columns: 1fr;\n}\n}\n._search_lkzqj_154 {\n  max-width: 196px;\n  justify-self: end;\n}\n._search_lkzqj_154 input {\n  height: 30px;\n}\n@media screen and (max-width: 991px) {\n._search_lkzqj_154 {\n    max-width: 100%;\n}\n}\n._listWrapper_lkzqj_167 {\n  position: absolute;\n  height: 100%;\n  width: 100%;\n}\n._paginatedListWrapper_lkzqj_173 {\n  display: flex;\n  flex-direction: column;\n  height: 100%;\n  overflow: auto;\n  gap: var(--spacing--md);\n}\n._listItems_lkzqj_181 {\n  overflow-y: auto;\n}\n._listPagination_lkzqj_185 {\n  display: flex;\n  justify-content: flex-end;\n  margin-bottom: var(--spacing--lg);\n}\n._listPagination_lkzqj_185 .el-pagination__sizes {\n  height: 100%;\n  position: relative;\n  top: -1px;\n}\n._listPagination_lkzqj_185 .el-pagination__sizes input {\n  height: 100%;\n  min-height: 28px;\n}\n._listPagination_lkzqj_185 .el-pagination__sizes .el-input__suffix {\n  width: var(--spacing--md);\n}\n._sort-and-filter_lkzqj_141 {\n  white-space: nowrap;\n}\n@media screen and (max-width: 991px) {\n._sort-and-filter_lkzqj_141 {\n    width: 100%;\n}\n}\n._datatable_lkzqj_212 {\n  padding-bottom: var(--spacing--sm);\n}/* BEM support Func\n -------------------------- */\n/* Transition\n-------------------------- */\n/* Color\n-------------------------- */\n/* Link\n-------------------------- */\n/* Border\n-------------------------- */\n/* Outline\n-------------------------- */\n/* Box shadow\n-------------------------- */\n/* Fill\n-------------------------- */\n/* Typography\n-------------------------- */\n/* z-index\n-------------------------- */\n/* Disable base\n-------------------------- */\n/* Icon\n-------------------------- */\n/* Checkbox\n-------------------------- */\n/* Radio\n-------------------------- */\n/* Select\n-------------------------- */\n/* Alert\n-------------------------- */\n/* MessageBox\n-------------------------- */\n/* Message\n-------------------------- */\n/* Notification\n-------------------------- */\n/* Input\n-------------------------- */\n/* Cascader\n-------------------------- */\n/* Group\n-------------------------- */\n/* Tab\n-------------------------- */\n/* Button\n-------------------------- */\n/* cascader\n-------------------------- */\n/* Switch\n-------------------------- */\n/* Dialog\n-------------------------- */\n/* Table\n-------------------------- */\n/* Pagination\n-------------------------- */\n/* Popup\n-------------------------- */\n/* Popover\n-------------------------- */\n/* Tooltip\n-------------------------- */\n/* Tag\n-------------------------- */\n/* Tree\n-------------------------- */\n/* Dropdown\n-------------------------- */\n/* Badge\n-------------------------- */\n/* Card\n--------------------------*/\n/* Slider\n--------------------------*/\n/* Steps\n--------------------------*/\n/* Menu\n--------------------------*/\n/* Rate\n--------------------------*/\n/* DatePicker\n--------------------------*/\n/* Loading\n--------------------------*/\n/* Scrollbar\n--------------------------*/\n/* Carousel\n--------------------------*/\n/* Collapse\n--------------------------*/\n/* Transfer\n--------------------------*/\n/* Header\n  --------------------------*/\n/* Footer\n--------------------------*/\n/* Main\n--------------------------*/\n/* Timeline\n--------------------------*/\n/* Backtop\n--------------------------*/\n/* Link\n--------------------------*/\n/* Calendar\n--------------------------*/\n/* Form\n-------------------------- */\n/* Avatar\n--------------------------*/\n/* Break-point\n--------------------------*/\n/* Break-points\n -------------------------- */\n/* Scrollbar\n -------------------------- */\n/* Placeholder\n -------------------------- */\n/* BEM\n -------------------------- */\n.resource-list-loading[data-v-b3f25b76] {\n  position: relative;\n  height: 0;\n  width: 100%;\n  overflow: hidden;\n  /*\n  Show the loading skeleton only if the loading takes longer than 300ms\n  */\n  animation: 0.01s linear 0.3s forwards changeVisibility-b3f25b76;\n}\n.resource-list-loading[data-v-b3f25b76] .el-skeleton {\n  position: absolute;\n  height: 100%;\n  width: 100%;\n  overflow: hidden;\n}\n.resource-list-loading[data-v-b3f25b76] .el-skeleton > div > div:first-child .el-skeleton__item {\n  height: 42px;\n  margin: 0;\n}\n.resource-list-loading[data-v-b3f25b76] .el-skeleton .el-skeleton__item {\n  height: 69px;\n}\n.resource-list-loading-instant[data-v-b3f25b76] {\n  animation: 0.01s linear 0s forwards changeVisibility-b3f25b76;\n}\n@keyframes changeVisibility-b3f25b76 {\nfrom {\n    height: 0;\n}\nto {\n    height: 100%;\n}\n}/*$vite$:1*/";
        document.head.appendChild(__vite_style__);
        //#region src/app/components/layouts/PageViewLayoutList.vue?vue&type=script&setup=true&lang.ts
        PageViewLayoutList_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */defineComponent({
          __name: "PageViewLayoutList",
          props: {
            overflow: {
              type: Boolean
            }
          },
          setup(__props) {
            return (_ctx, _cache) => {
              return openBlock(), createElementBlock("div", {
                class: normalizeClass({
                  [_ctx.$style.wrapper]: true,
                  [_ctx.$style.overflow]: _ctx.overflow
                })
              }, [createBaseVNode("div", {
                class: normalizeClass(_ctx.$style.list)
              }, [_ctx.$slots.header ? (openBlock(), createElementBlock("div", {
                key: 0,
                class: normalizeClass(_ctx.$style.header)
              }, [renderSlot(_ctx.$slots, "header")], 2)) : createCommentVNode("", true), createBaseVNode("div", {
                class: normalizeClass(_ctx.$style.body)
              }, [renderSlot(_ctx.$slots, "default")], 2)], 2)], 2);
            };
          }
        }); //#endregion
        //#region src/app/components/layouts/PageViewLayoutList.vue?vue&type=style&index=0&lang.module.scss
        wrapper = "_wrapper_hn9dc_123";
        overflow = "_overflow_hn9dc_128";
        list = "_list_hn9dc_128";
        body = "_body_hn9dc_128";
        PageViewLayoutList_vue_vue_type_style_index_0_lang_module_default = {
          wrapper,
          overflow,
          list,
          body
        }; //#endregion
        //#region src/app/components/layouts/PageViewLayoutList.vue
        cssModules$1 = {
          "$style": PageViewLayoutList_vue_vue_type_style_index_0_lang_module_default
        };
        PageViewLayoutList_default = /* @__PURE__ */__plugin_vue_export_helper_default(PageViewLayoutList_vue_vue_type_script_setup_true_lang_default, [["__cssModules", cssModules$1]]);
        _hoisted_1 = {
          key: 0,
          class: "resource-list-loading"
        };
        _hoisted_2 = {
          key: 0
        };
        _hoisted_3 = {
          key: 0,
          class: "mt-xs",
          "data-test-id": "resources-list-filters-applied-info"
        };
        _hoisted_4 = {
          key: 0,
          class: "resource-list-loading resource-list-loading-instant"
        };
        ResourcesListLayout_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */defineComponent({
          __name: "ResourcesListLayout",
          props: {
            resourceKey: {},
            displayName: {
              type: Function,
              default: resource => resource.name || ""
            },
            resources: {},
            disabled: {
              type: Boolean
            },
            initialize: {
              type: Function,
              default: async () => {}
            },
            filters: {
              default: () => ({
                search: "",
                homeProject: ""
              })
            },
            additionalFiltersHandler: {
              type: Function,
              default: void 0
            },
            shareable: {
              type: Boolean,
              default: true
            },
            sortFns: {
              default: () => ({})
            },
            sortOptions: {
              default: () => ["lastUpdated", "lastCreated", "nameAsc", "nameDesc"]
            },
            type: {
              default: "list-full"
            },
            typeProps: {
              default: () => ({
                itemSize: 80
              })
            },
            loading: {
              type: Boolean,
              default: true
            },
            customPageSize: {
              default: 25
            },
            availablePageSizeOptions: {
              default: () => [10, 25, 50, 100]
            },
            totalItems: {
              default: 0
            },
            resourcesRefreshing: {
              type: Boolean,
              default: false
            },
            dontPerformSortingAndFiltering: {
              type: Boolean,
              default: false
            },
            hasEmptyState: {
              type: Boolean,
              default: true
            },
            uiConfig: {
              default: () => ({
                searchEnabled: true,
                showFiltersDropdown: true,
                sortEnabled: true
              })
            }
          },
          emits: ["update:filters", "click:add", "update:pagination-and-sort", "update:search"],
          setup(__props, {
            expose: __expose,
            emit: __emit
          }) {
            const route = useRoute();
            const router = useRouter();
            const {
              callDebounced
            } = useDebounce();
            const usersStore = useUsersStore();
            const telemetry = useTelemetry();
            const n8nLocalStorage = useN8nLocalStorage();
            const props = __props;
            const {
              getResourceText
            } = useResourcesListI18n(props.resourceKey);
            const sortBy = ref(props.sortOptions[0]);
            const hasFilters = ref(false);
            const currentPage = ref(1);
            const rowsPerPage = ref(props.customPageSize);
            const resettingFilters = ref(false);
            const search$1 = ref(null);
            const listWrapperRef = ref(null);
            const listItemsRef = ref(null);
            const preferredPageSize = ref(props.customPageSize);
            const preferredSort = ref(props.sortOptions[0]);
            const emit = __emit;
            useSlots();
            const filtersModel = computed({
              get: () => props.filters,
              set: newValue => emit("update:filters", newValue)
            });
            const showEmptyState = computed(() => {
              return props.hasEmptyState && props.resources.length === 0 && !hasFilters.value && !filtersModel.value.search && !props.resourcesRefreshing;
            });
            const filterKeys = computed(() => {
              return Object.keys(filtersModel.value);
            });
            const filteredAndSortedResources = computed(() => {
              if (props.dontPerformSortingAndFiltering) return props.resources;
              return props.resources.filter(resource => {
                let matches = true;
                if (filtersModel.value.homeProject && isSharedResource(resource)) matches = matches && !!("homeProject" in resource && resource.homeProject && resource.homeProject.id === filtersModel.value.homeProject);
                if (filtersModel.value.search) {
                  const searchString = filtersModel.value.search.toLowerCase();
                  matches = matches && props.displayName(resource).toLowerCase().includes(searchString);
                }
                if (props.additionalFiltersHandler) matches = props.additionalFiltersHandler(resource, filtersModel.value, matches);
                return matches;
              }).sort((a, b) => {
                const sortableByDate = isResourceSortableByDate(a) && isResourceSortableByDate(b);
                switch (sortBy.value) {
                  case "lastUpdated":
                    if (!sortableByDate) return 0;
                    if ("updatedAt" in a && "updatedAt" in b) return props.sortFns.lastUpdated ? props.sortFns.lastUpdated(a, b) : new Date(b.updatedAt ?? "").valueOf() - new Date(a.updatedAt ?? "").valueOf();
                    return 0;
                  case "lastCreated":
                    if (!sortableByDate) return 0;
                    if ("createdAt" in a && "createdAt" in b) return props.sortFns.lastCreated ? props.sortFns.lastCreated(a, b) : new Date(b.createdAt ?? "").valueOf() - new Date(a.createdAt ?? "").valueOf();
                    return 0;
                  case "nameAsc":
                    return props.sortFns.nameAsc ? props.sortFns.nameAsc(a, b) : props.displayName(a).trim().localeCompare(props.displayName(b).trim());
                  case "nameDesc":
                    return props.sortFns.nameDesc ? props.sortFns.nameDesc(a, b) : props.displayName(b).trim().localeCompare(props.displayName(a).trim());
                  default:
                    return props.sortFns[sortBy.value] ? props.sortFns[sortBy.value](a, b) : 0;
                }
              });
            });
            watch(() => props.filters, value => {
              filtersModel.value = value;
              if (hasAppliedFilters()) hasFilters.value = true;
            });
            watch(() => filtersModel.value.homeProject, () => {
              sendFiltersTelemetry("homeProject");
            });
            watch(() => filtersModel.value.tags, () => {
              sendFiltersTelemetry("tags");
            });
            watch(() => filtersModel.value.type, () => {
              sendFiltersTelemetry("type");
            });
            watch(() => filtersModel.value.search, () => callDebounced(sendFiltersTelemetry, {
              debounceTime: 1e3,
              trailing: true
            }, "search"));
            watch(() => filtersModel.value.setupNeeded, () => {
              sendFiltersTelemetry("setupNeeded");
            });
            watch(() => filtersModel.value.incomplete, () => {
              sendFiltersTelemetry("incomplete");
            });
            watch([() => route.params?.projectId, () => route.name], async () => {
              await resetFilters();
              await loadPaginationPreferences();
              await props.initialize();
            });
            onMounted(async () => {
              await loadPaginationPreferences();
              await props.initialize();
              await nextTick();
              if (hasAppliedFilters()) hasFilters.value = true;
              window.addEventListener("keydown", captureSearchHotKey);
            });
            onBeforeUnmount(() => {
              window.removeEventListener("keydown", captureSearchHotKey);
            });
            const captureSearchHotKey = e => {
              if ((e.ctrlKey || e.metaKey) && e.key === "f") {
                e.preventDefault();
                focusSearchInput();
              }
            };
            const focusSearchInput = () => {
              if (search$1.value) search$1.value.focus();
            };
            const isFilterApplied = key => {
              if (key === "search") return false;
              if (typeof props.filters[key] === "boolean") return props.filters[key];
              if (Array.isArray(props.filters[key])) return props.filters[key].length > 0;
              return props.filters[key] !== "";
            };
            const hasOnlyFiltersThatShowMoreResults = computed(() => {
              const activeFilters = filterKeys.value.filter(isFilterApplied);
              const filtersThatShowMoreResults = ["showArchived"];
              return activeFilters.every(filter => {
                return filtersThatShowMoreResults.includes(filter);
              });
            });
            const hasAppliedFilters = () => {
              return !!filterKeys.value.find(isFilterApplied);
            };
            const setRowsPerPage = async numberOfRowsPerPage => {
              rowsPerPage.value = numberOfRowsPerPage;
              await savePaginationPreferences();
              emit("update:pagination-and-sort", {
                pageSize: numberOfRowsPerPage
              });
            };
            const setSorting = async (sort, persistUpdate = true) => {
              sortBy.value = sort;
              if (persistUpdate) {
                await savePaginationPreferences();
                sendSortingTelemetry();
              }
              emit("update:pagination-and-sort", {
                sort
              });
            };
            const setCurrentPage = async (page, persistUpdate = true) => {
              currentPage.value = page;
              if (persistUpdate) await savePaginationPreferences();
              emit("update:pagination-and-sort", {
                page
              });
            };
            const sendFiltersTelemetry = source => {
              if (resettingFilters.value) {
                if (source !== "reset") return;
                setTimeout(() => resettingFilters.value = false, 1500);
              }
              const filters$1 = filtersModel.value;
              const filtersSet = [];
              const filterValues = [];
              Object.keys(filters$1).forEach(key => {
                if (filters$1[key]) {
                  filtersSet.push(key);
                  filterValues.push(key === "search" ? null : filters$1[key]);
                }
              });
              telemetry.track(`User set filters in ${props.resourceKey} list`, {
                filters_set: filtersSet,
                filter_values: filterValues,
                [`${props.resourceKey}_total_in_view`]: props.resources.length,
                [`${props.resourceKey}_after_filtering`]: filteredAndSortedResources.value.length
              });
            };
            const onAddButtonClick = e => {
              emit("click:add", e);
            };
            const onUpdateFilters = e => {
              emit("update:filters", e);
            };
            const resetFilters = async () => {
              Object.keys(filtersModel.value).forEach(key => {
                filtersModel.value[key] = Array.isArray(filtersModel.value[key]) ? [] : "";
              });
              await setCurrentPage(1, false);
              resettingFilters.value = true;
              hasFilters.value = false;
              sendFiltersTelemetry("reset");
              emit("update:filters", filtersModel.value);
            };
            const itemSize = () => {
              if ("itemSize" in props.typeProps) return props.typeProps.itemSize;
              return 0;
            };
            const getColumns = () => {
              if ("columns" in props.typeProps) return props.typeProps.columns;
              return [];
            };
            const sendSortingTelemetry = () => {
              telemetry.track(`User changed sorting in ${props.resourceKey} list`, {
                sorting: sortBy.value
              });
            };
            const onUpdateFiltersLength = length => {
              hasFilters.value = length > 0;
            };
            const onSearch = s => {
              filtersModel.value.search = s;
              emit("update:search", s);
            };
            const findNearestPageSize = size => {
              return props.availablePageSizeOptions.reduce((prev, curr) => Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev);
            };
            /**
            * Saves the current pagination preferences to local storage and updates the URL query parameters.
            */
            const savePaginationPreferences = async () => {
              if (props.type !== "list-paginated") return;
              const currentQuery = {
                ...route.query
              };
              if (currentPage.value !== 1) currentQuery.page = currentPage.value.toString();else delete currentQuery.page;
              if (rowsPerPage.value !== preferredPageSize.value) {
                currentQuery.pageSize = rowsPerPage.value.toString();
                preferredPageSize.value = rowsPerPage.value;
              } else delete currentQuery.pageSize;
              if (sortBy.value !== preferredSort.value) {
                currentQuery.sort = sortBy.value;
                preferredSort.value = sortBy.value;
              } else delete currentQuery.sort;
              n8nLocalStorage.saveProjectPreferencesToLocalStorage(route.params.projectId ?? "", "workflows", {
                sort: sortBy.value,
                pageSize: rowsPerPage.value
              });
              await router.replace({
                query: Object.keys(currentQuery).length ? currentQuery : void 0
              });
            };
            /**
            * Loads the pagination preferences from local storage or URL query parameter
            * Current page is only saved in the URL query parameters
            * Page size and sort are saved both in local storage and URL query parameters, with query parameters taking precedence
            */
            const loadPaginationPreferences = async () => {
              if (props.type !== "list-paginated") return;
              const query = route.query;
              const localStorageValues = n8nLocalStorage.loadProjectPreferencesFromLocalStorage(route.params.projectId ?? "", "workflows");
              const emitPayload = {};
              if (query.page) {
                const newPage = parseInt(query.page, 10);
                if (newPage > 1) {
                  currentPage.value = newPage;
                  emitPayload.page = newPage;
                }
              }
              if (query.pageSize ?? localStorageValues.pageSize) {
                const newPageSize = findNearestPageSize(parseInt(query.pageSize || String(localStorageValues.pageSize), 10));
                rowsPerPage.value = newPageSize;
                emitPayload.pageSize = newPageSize;
                preferredPageSize.value = newPageSize;
              } else {
                rowsPerPage.value = props.customPageSize;
                emitPayload.pageSize = props.customPageSize;
              }
              if (query.sort) sortBy.value = emitPayload.sort = preferredSort.value = query.sort;else if (localStorageValues.sort) {
                await setSorting(localStorageValues.sort, false);
                emitPayload.sort = localStorageValues.sort;
                preferredSort.value = localStorageValues.sort;
              } else sortBy.value = props.sortOptions[0];
              emit("update:pagination-and-sort", emitPayload);
            };
            const getScrollContainer = () => {
              if (props.type === "list-paginated") return listItemsRef.value ?? null;
              return listWrapperRef.value ?? null;
            };
            __expose({
              currentPage,
              setCurrentPage,
              getScrollContainer
            });
            return (_ctx, _cache) => {
              return openBlock(), createBlock(PageViewLayout_default, null, {
                header: withCtx(() => [renderSlot(_ctx.$slots, "header", {}, void 0, true)]),
                default: withCtx(() => [_ctx.loading ? (openBlock(), createElementBlock("div", _hoisted_1, [createVNode(unref(N8nLoading_default), {
                  rows: 25,
                  "shrink-last": false
                })])) : (openBlock(), createElementBlock(Fragment, {
                  key: 1
                }, [showEmptyState.value ? (openBlock(), createElementBlock("div", _hoisted_2, [renderSlot(_ctx.$slots, "empty", {}, () => [createVNode(unref(N8nActionBox_default), {
                  "data-test-id": "empty-resources-list",
                  emoji: "👋",
                  heading: unref(getResourceText)(unref(usersStore).currentUser?.firstName ? "empty.heading" : "empty.heading.userNotSetup", unref(usersStore).currentUser?.firstName ? "empty.heading" : "empty.heading.userNotSetup", {
                    name: unref(usersStore).currentUser?.firstName ?? ""
                  }),
                  description: unref(getResourceText)("empty.description"),
                  "button-text": unref(getResourceText)("empty.button"),
                  "button-type": "secondary",
                  "button-disabled": _ctx.disabled,
                  "onClick:button": onAddButtonClick
                }, {
                  disabledButtonTooltip: withCtx(() => [createTextVNode(toDisplayString(unref(getResourceText)("empty.button.disabled.tooltip")), 1)]),
                  _: 1
                }, 8, ["heading", "description", "button-text", "button-disabled"])], true)])) : (openBlock(), createBlock(PageViewLayoutList_default, {
                  key: 1
                }, {
                  header: withCtx(() => [createBaseVNode("div", {
                    class: normalizeClass(_ctx.$style["filters-row"])
                  }, [createBaseVNode("div", {
                    class: normalizeClass(_ctx.$style.filters)
                  }, [renderSlot(_ctx.$slots, "breadcrumbs", {}, void 0, true), props.uiConfig.searchEnabled ? (openBlock(), createBlock(unref(N8nInput_default), {
                    key: 0,
                    ref_key: "search",
                    ref: search$1,
                    "model-value": filtersModel.value.search,
                    class: normalizeClass(_ctx.$style.search),
                    placeholder: unref(getResourceText)("search.placeholder", "search.placeholder"),
                    size: "small",
                    clearable: "",
                    "data-test-id": "resources-list-search",
                    "onUpdate:modelValue": onSearch
                  }, {
                    prefix: withCtx(() => [createVNode(unref(N8nIcon_default), {
                      icon: "search"
                    })]),
                    _: 1
                  }, 8, ["model-value", "class", "placeholder"])) : createCommentVNode("", true), props.uiConfig.sortEnabled ? (openBlock(), createElementBlock("div", {
                    key: 1,
                    class: normalizeClass(_ctx.$style["sort-and-filter"])
                  }, [createVNode(unref(N8nSelect_default), {
                    modelValue: sortBy.value,
                    "onUpdate:modelValue": _cache[0] || (_cache[0] = $event => sortBy.value = $event),
                    size: "small",
                    "data-test-id": "resources-list-sort",
                    onChange: _cache[1] || (_cache[1] = $event => setSorting(sortBy.value))
                  }, {
                    default: withCtx(() => [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.sortOptions, sortOption => {
                      return openBlock(), createBlock(unref(N8nOption_default), {
                        key: sortOption,
                        "data-test-id": "resources-list-sort-item",
                        value: sortOption,
                        label: unref(getResourceText)(`sort.${sortOption}`, `sort.${sortOption}`)
                      }, null, 8, ["value", "label"]);
                    }), 128))]),
                    _: 1
                  }, 8, ["modelValue"])], 2)) : createCommentVNode("", true), props.uiConfig.showFiltersDropdown ? (openBlock(), createElementBlock("div", {
                    key: 2,
                    class: normalizeClass(_ctx.$style["sort-and-filter"])
                  }, [createVNode(ResourceFiltersDropdown_default, {
                    keys: filterKeys.value,
                    reset: resetFilters,
                    "model-value": filtersModel.value,
                    shareable: _ctx.shareable,
                    "just-icon": true,
                    "onUpdate:modelValue": onUpdateFilters,
                    "onUpdate:filtersLength": onUpdateFiltersLength
                  }, {
                    default: withCtx(resourceFiltersSlotProps => [renderSlot(_ctx.$slots, "filters", normalizeProps(guardReactiveProps(resourceFiltersSlotProps)), void 0, true)]),
                    _: 3
                  }, 8, ["keys", "model-value", "shareable"]), renderSlot(_ctx.$slots, "add-button", {}, void 0, true)], 2)) : createCommentVNode("", true)], 2)], 2), renderSlot(_ctx.$slots, "callout", {}, void 0, true), props.uiConfig.showFiltersDropdown ? withDirectives((openBlock(), createElementBlock("div", _hoisted_3, [createVNode(unref(N8nInfoTip_default), {
                    bold: false
                  }, {
                    default: withCtx(() => [createTextVNode(toDisplayString(hasOnlyFiltersThatShowMoreResults.value ? unref(getResourceText)("filters.active.shortText", "filters.active.shortText") : unref(getResourceText)("filters.active", "filters.active")) + " ", 1), createVNode(unref(N8nLink_default), {
                      "data-test-id": "workflows-filter-reset",
                      size: "small",
                      onClick: resetFilters
                    }, {
                      default: withCtx(() => [createTextVNode(toDisplayString(unref(getResourceText)("filters.active.reset", "filters.active.reset")), 1)]),
                      _: 1
                    })]),
                    _: 1
                  })], 512)), [[vShow, hasFilters.value]]) : createCommentVNode("", true), _cache[4] || (_cache[4] = createBaseVNode("div", {
                    class: "pb-xs"
                  }, null, -1))]),
                  default: withCtx(() => [renderSlot(_ctx.$slots, "preamble", {}, void 0, true), _ctx.resourcesRefreshing ? (openBlock(), createElementBlock("div", _hoisted_4, [createVNode(unref(N8nLoading_default), {
                    rows: rowsPerPage.value,
                    "shrink-last": false
                  }, null, 8, ["rows"])])) : filteredAndSortedResources.value.length > 0 ? (openBlock(), createElementBlock("div", {
                    key: 1,
                    ref_key: "listWrapperRef",
                    ref: listWrapperRef,
                    "data-test-id": "resources-list-wrapper",
                    class: normalizeClass(_ctx.$style.listWrapper)
                  }, [_ctx.type === "list-full" ? (openBlock(), createBlock(unref(N8nRecycleScroller_default), {
                    key: 0,
                    "data-test-id": "resources-list",
                    items: filteredAndSortedResources.value,
                    "item-size": itemSize(),
                    "item-key": "id"
                  }, {
                    default: withCtx(({
                      item,
                      updateItemSize
                    }) => [renderSlot(_ctx.$slots, "default", {
                      data: item,
                      updateItemSize
                    }, void 0, true)]),
                    _: 3
                  }, 8, ["items", "item-size"])) : _ctx.type === "list-paginated" ? (openBlock(), createElementBlock("div", {
                    key: 1,
                    class: normalizeClass(_ctx.$style.paginatedListWrapper),
                    "data-test-id": "paginated-list"
                  }, [createBaseVNode("div", {
                    ref_key: "listItemsRef",
                    ref: listItemsRef,
                    class: normalizeClass(_ctx.$style.listItems)
                  }, [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.resources, (item, index) => {
                    return openBlock(), createElementBlock("div", {
                      key: index,
                      class: normalizeClass(_ctx.$style.listItem)
                    }, [renderSlot(_ctx.$slots, "item", {
                      item,
                      index
                    }, () => [createTextVNode(toDisplayString(item), 1)], true)], 2);
                  }), 128))], 2), createBaseVNode("div", {
                    class: normalizeClass(_ctx.$style.listPagination)
                  }, [createVNode(unref(ElPagination), {
                    "current-page": currentPage.value,
                    "onUpdate:currentPage": [_cache[2] || (_cache[2] = $event => currentPage.value = $event), setCurrentPage],
                    "page-size": rowsPerPage.value,
                    "onUpdate:pageSize": _cache[3] || (_cache[3] = $event => rowsPerPage.value = $event),
                    background: "",
                    total: _ctx.totalItems,
                    "page-sizes": _ctx.availablePageSizeOptions,
                    layout: "total, prev, pager, next, sizes",
                    "data-test-id": "resources-list-pagination",
                    onSizeChange: setRowsPerPage
                  }, null, 8, ["current-page", "page-size", "total", "page-sizes"])], 2)], 2)) : createCommentVNode("", true), _ctx.type === "datatable" ? (openBlock(), createBlock(unref(N8nDatatable_default), {
                    key: 2,
                    "data-test-id": "resources-table",
                    class: normalizeClass(_ctx.$style.datatable),
                    columns: getColumns(),
                    rows: filteredAndSortedResources.value,
                    "current-page": currentPage.value,
                    "rows-per-page": rowsPerPage.value,
                    "onUpdate:currentPage": setCurrentPage,
                    "onUpdate:rowsPerPage": setRowsPerPage
                  }, {
                    row: withCtx(({
                      columns,
                      row
                    }) => [renderSlot(_ctx.$slots, "default", {
                      data: row,
                      columns
                    }, void 0, true)]),
                    postdata: withCtx(() => [renderSlot(_ctx.$slots, "postdata", {}, void 0, true)]),
                    _: 3
                  }, 8, ["class", "columns", "rows", "current-page", "rows-per-page"])) : createCommentVNode("", true)], 2)) : hasAppliedFilters() || filtersModel.value.search !== "" ? (openBlock(), createBlock(unref(N8nText_default), {
                    key: 2,
                    color: "text-base",
                    size: "medium",
                    "data-test-id": "resources-list-empty"
                  }, {
                    default: withCtx(() => [createTextVNode(toDisplayString(unref(getResourceText)("noResults", "noResults")), 1)]),
                    _: 1
                  })) : createCommentVNode("", true), renderSlot(_ctx.$slots, "postamble", {}, void 0, true)]),
                  _: 3
                }))], 64))]),
                _: 3
              });
            };
          }
        }); //#endregion
        //#region src/app/components/layouts/ResourcesListLayout.vue?vue&type=style&index=0&lang.module.scss
        filters = "_filters_lkzqj_123";
        search = "_search_lkzqj_154";
        listWrapper = "_listWrapper_lkzqj_167";
        paginatedListWrapper = "_paginatedListWrapper_lkzqj_173";
        listItems = "_listItems_lkzqj_181";
        listPagination = "_listPagination_lkzqj_185";
        datatable = "_datatable_lkzqj_212";
        ResourcesListLayout_vue_vue_type_style_index_0_lang_module_default = {
          "filters-row": "_filters-row_lkzqj_123",
          filters,
          "sort-and-filter": "_sort-and-filter_lkzqj_141",
          search,
          listWrapper,
          paginatedListWrapper,
          listItems,
          listPagination,
          datatable
        }; //#endregion
        //#region src/app/components/layouts/ResourcesListLayout.vue
        cssModules = {
          "$style": ResourcesListLayout_vue_vue_type_style_index_0_lang_module_default
        };
        _export("t", ResourcesListLayout_default = /* @__PURE__ */__plugin_vue_export_helper_default(ResourcesListLayout_vue_vue_type_script_setup_true_lang_default, [["__cssModules", cssModules], ["__scopeId", "data-v-b3f25b76"]])); //#endregion
      }
    };
  });
})();