UNPKG

strapi-plugin-meilisearch

Version:

Synchronise and search in your Strapi content-types with Meilisearch

1,004 lines (1,003 loc) 39.7 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const jsxRuntime = require("react/jsx-runtime"); const React = require("react"); const reactRouterDom = require("react-router-dom"); const admin = require("@strapi/strapi/admin"); const index = require("./index-OgM-GMGo.js"); const designSystem = require("@strapi/design-system"); function _interopNamespace(e) { if (e && e.__esModule) return e; const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } }); if (e) { for (const k in e) { if (k !== "default") { const d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: () => e[k] }); } } } n.default = e; return Object.freeze(n); } const React__namespace = /* @__PURE__ */ _interopNamespace(React); var __assign = function() { __assign = Object.assign || function __assign2(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; var reactIs$1 = { exports: {} }; var reactIs_production_min = {}; /** @license React v16.13.1 * react-is.production.min.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var hasRequiredReactIs_production_min; function requireReactIs_production_min() { if (hasRequiredReactIs_production_min) return reactIs_production_min; hasRequiredReactIs_production_min = 1; var b = "function" === typeof Symbol && Symbol.for, c = b ? Symbol.for("react.element") : 60103, d = b ? Symbol.for("react.portal") : 60106, e = b ? Symbol.for("react.fragment") : 60107, f = b ? Symbol.for("react.strict_mode") : 60108, g = b ? Symbol.for("react.profiler") : 60114, h = b ? Symbol.for("react.provider") : 60109, k = b ? Symbol.for("react.context") : 60110, l = b ? Symbol.for("react.async_mode") : 60111, m = b ? Symbol.for("react.concurrent_mode") : 60111, n = b ? Symbol.for("react.forward_ref") : 60112, p = b ? Symbol.for("react.suspense") : 60113, q = b ? Symbol.for("react.suspense_list") : 60120, r = b ? Symbol.for("react.memo") : 60115, t = b ? Symbol.for("react.lazy") : 60116, v = b ? Symbol.for("react.block") : 60121, w = b ? Symbol.for("react.fundamental") : 60117, x = b ? Symbol.for("react.responder") : 60118, y = b ? Symbol.for("react.scope") : 60119; function z(a) { if ("object" === typeof a && null !== a) { var u = a.$$typeof; switch (u) { case c: switch (a = a.type, a) { case l: case m: case e: case g: case f: case p: return a; default: switch (a = a && a.$$typeof, a) { case k: case n: case t: case r: case h: return a; default: return u; } } case d: return u; } } } function A(a) { return z(a) === m; } reactIs_production_min.AsyncMode = l; reactIs_production_min.ConcurrentMode = m; reactIs_production_min.ContextConsumer = k; reactIs_production_min.ContextProvider = h; reactIs_production_min.Element = c; reactIs_production_min.ForwardRef = n; reactIs_production_min.Fragment = e; reactIs_production_min.Lazy = t; reactIs_production_min.Memo = r; reactIs_production_min.Portal = d; reactIs_production_min.Profiler = g; reactIs_production_min.StrictMode = f; reactIs_production_min.Suspense = p; reactIs_production_min.isAsyncMode = function(a) { return A(a) || z(a) === l; }; reactIs_production_min.isConcurrentMode = A; reactIs_production_min.isContextConsumer = function(a) { return z(a) === k; }; reactIs_production_min.isContextProvider = function(a) { return z(a) === h; }; reactIs_production_min.isElement = function(a) { return "object" === typeof a && null !== a && a.$$typeof === c; }; reactIs_production_min.isForwardRef = function(a) { return z(a) === n; }; reactIs_production_min.isFragment = function(a) { return z(a) === e; }; reactIs_production_min.isLazy = function(a) { return z(a) === t; }; reactIs_production_min.isMemo = function(a) { return z(a) === r; }; reactIs_production_min.isPortal = function(a) { return z(a) === d; }; reactIs_production_min.isProfiler = function(a) { return z(a) === g; }; reactIs_production_min.isStrictMode = function(a) { return z(a) === f; }; reactIs_production_min.isSuspense = function(a) { return z(a) === p; }; reactIs_production_min.isValidElementType = function(a) { return "string" === typeof a || "function" === typeof a || a === e || a === m || a === g || a === f || a === p || a === q || "object" === typeof a && null !== a && (a.$$typeof === t || a.$$typeof === r || a.$$typeof === h || a.$$typeof === k || a.$$typeof === n || a.$$typeof === w || a.$$typeof === x || a.$$typeof === y || a.$$typeof === v); }; reactIs_production_min.typeOf = z; return reactIs_production_min; } var reactIs_development = {}; /** @license React v16.13.1 * react-is.development.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var hasRequiredReactIs_development; function requireReactIs_development() { if (hasRequiredReactIs_development) return reactIs_development; hasRequiredReactIs_development = 1; if (process.env.NODE_ENV !== "production") { (function() { var hasSymbol = typeof Symbol === "function" && Symbol.for; var REACT_ELEMENT_TYPE = hasSymbol ? Symbol.for("react.element") : 60103; var REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106; var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107; var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 60108; var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 60114; var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 60109; var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 60110; var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for("react.async_mode") : 60111; var REACT_CONCURRENT_MODE_TYPE = hasSymbol ? Symbol.for("react.concurrent_mode") : 60111; var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for("react.forward_ref") : 60112; var REACT_SUSPENSE_TYPE = hasSymbol ? Symbol.for("react.suspense") : 60113; var REACT_SUSPENSE_LIST_TYPE = hasSymbol ? Symbol.for("react.suspense_list") : 60120; var REACT_MEMO_TYPE = hasSymbol ? Symbol.for("react.memo") : 60115; var REACT_LAZY_TYPE = hasSymbol ? Symbol.for("react.lazy") : 60116; var REACT_BLOCK_TYPE = hasSymbol ? Symbol.for("react.block") : 60121; var REACT_FUNDAMENTAL_TYPE = hasSymbol ? Symbol.for("react.fundamental") : 60117; var REACT_RESPONDER_TYPE = hasSymbol ? Symbol.for("react.responder") : 60118; var REACT_SCOPE_TYPE = hasSymbol ? Symbol.for("react.scope") : 60119; function isValidElementType(type) { return typeof type === "string" || typeof type === "function" || // Note: its typeof might be other than 'symbol' or 'number' if it's a polyfill. type === REACT_FRAGMENT_TYPE || type === REACT_CONCURRENT_MODE_TYPE || type === REACT_PROFILER_TYPE || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || typeof type === "object" && type !== null && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_RESPONDER_TYPE || type.$$typeof === REACT_SCOPE_TYPE || type.$$typeof === REACT_BLOCK_TYPE); } function typeOf(object) { if (typeof object === "object" && object !== null) { var $$typeof = object.$$typeof; switch ($$typeof) { case REACT_ELEMENT_TYPE: var type = object.type; switch (type) { case REACT_ASYNC_MODE_TYPE: case REACT_CONCURRENT_MODE_TYPE: case REACT_FRAGMENT_TYPE: case REACT_PROFILER_TYPE: case REACT_STRICT_MODE_TYPE: case REACT_SUSPENSE_TYPE: return type; default: var $$typeofType = type && type.$$typeof; switch ($$typeofType) { case REACT_CONTEXT_TYPE: case REACT_FORWARD_REF_TYPE: case REACT_LAZY_TYPE: case REACT_MEMO_TYPE: case REACT_PROVIDER_TYPE: return $$typeofType; default: return $$typeof; } } case REACT_PORTAL_TYPE: return $$typeof; } } return void 0; } var AsyncMode = REACT_ASYNC_MODE_TYPE; var ConcurrentMode = REACT_CONCURRENT_MODE_TYPE; var ContextConsumer = REACT_CONTEXT_TYPE; var ContextProvider = REACT_PROVIDER_TYPE; var Element = REACT_ELEMENT_TYPE; var ForwardRef = REACT_FORWARD_REF_TYPE; var Fragment = REACT_FRAGMENT_TYPE; var Lazy = REACT_LAZY_TYPE; var Memo = REACT_MEMO_TYPE; var Portal = REACT_PORTAL_TYPE; var Profiler = REACT_PROFILER_TYPE; var StrictMode = REACT_STRICT_MODE_TYPE; var Suspense = REACT_SUSPENSE_TYPE; var hasWarnedAboutDeprecatedIsAsyncMode = false; function isAsyncMode(object) { { if (!hasWarnedAboutDeprecatedIsAsyncMode) { hasWarnedAboutDeprecatedIsAsyncMode = true; console["warn"]("The ReactIs.isAsyncMode() alias has been deprecated, and will be removed in React 17+. Update your code to use ReactIs.isConcurrentMode() instead. It has the exact same API."); } } return isConcurrentMode(object) || typeOf(object) === REACT_ASYNC_MODE_TYPE; } function isConcurrentMode(object) { return typeOf(object) === REACT_CONCURRENT_MODE_TYPE; } function isContextConsumer(object) { return typeOf(object) === REACT_CONTEXT_TYPE; } function isContextProvider(object) { return typeOf(object) === REACT_PROVIDER_TYPE; } function isElement(object) { return typeof object === "object" && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; } function isForwardRef(object) { return typeOf(object) === REACT_FORWARD_REF_TYPE; } function isFragment(object) { return typeOf(object) === REACT_FRAGMENT_TYPE; } function isLazy(object) { return typeOf(object) === REACT_LAZY_TYPE; } function isMemo(object) { return typeOf(object) === REACT_MEMO_TYPE; } function isPortal(object) { return typeOf(object) === REACT_PORTAL_TYPE; } function isProfiler(object) { return typeOf(object) === REACT_PROFILER_TYPE; } function isStrictMode(object) { return typeOf(object) === REACT_STRICT_MODE_TYPE; } function isSuspense(object) { return typeOf(object) === REACT_SUSPENSE_TYPE; } reactIs_development.AsyncMode = AsyncMode; reactIs_development.ConcurrentMode = ConcurrentMode; reactIs_development.ContextConsumer = ContextConsumer; reactIs_development.ContextProvider = ContextProvider; reactIs_development.Element = Element; reactIs_development.ForwardRef = ForwardRef; reactIs_development.Fragment = Fragment; reactIs_development.Lazy = Lazy; reactIs_development.Memo = Memo; reactIs_development.Portal = Portal; reactIs_development.Profiler = Profiler; reactIs_development.StrictMode = StrictMode; reactIs_development.Suspense = Suspense; reactIs_development.isAsyncMode = isAsyncMode; reactIs_development.isConcurrentMode = isConcurrentMode; reactIs_development.isContextConsumer = isContextConsumer; reactIs_development.isContextProvider = isContextProvider; reactIs_development.isElement = isElement; reactIs_development.isForwardRef = isForwardRef; reactIs_development.isFragment = isFragment; reactIs_development.isLazy = isLazy; reactIs_development.isMemo = isMemo; reactIs_development.isPortal = isPortal; reactIs_development.isProfiler = isProfiler; reactIs_development.isStrictMode = isStrictMode; reactIs_development.isSuspense = isSuspense; reactIs_development.isValidElementType = isValidElementType; reactIs_development.typeOf = typeOf; })(); } return reactIs_development; } if (process.env.NODE_ENV === "production") { reactIs$1.exports = requireReactIs_production_min(); } else { reactIs$1.exports = requireReactIs_development(); } var reactIsExports = reactIs$1.exports; var reactIs = reactIsExports; var FORWARD_REF_STATICS = { "$$typeof": true, render: true, defaultProps: true, displayName: true, propTypes: true }; var MEMO_STATICS = { "$$typeof": true, compare: true, defaultProps: true, displayName: true, propTypes: true, type: true }; var TYPE_STATICS = {}; TYPE_STATICS[reactIs.ForwardRef] = FORWARD_REF_STATICS; TYPE_STATICS[reactIs.Memo] = MEMO_STATICS; function invariant(condition, message, Err) { if (Err === void 0) { Err = Error; } if (!condition) { throw new Err(message); } } var defaultErrorHandler = function(error) { if (process.env.NODE_ENV !== "production") { console.error(error); } }; var defaultWarnHandler = function(warning) { if (process.env.NODE_ENV !== "production") { console.warn(warning); } }; var DEFAULT_INTL_CONFIG = { formats: {}, messages: {}, timeZone: void 0, defaultLocale: "en", defaultFormats: {}, fallbackOnEmptyString: true, onError: defaultErrorHandler, onWarn: defaultWarnHandler }; function invariantIntlContext(intl) { invariant(intl, "[React Intl] Could not find required `intl` object. <IntlProvider> needs to exist in the component ancestry."); } __assign(__assign({}, DEFAULT_INTL_CONFIG), { textComponent: React__namespace.Fragment }); var IntlContext = typeof window !== "undefined" && !window.__REACT_INTL_BYPASS_GLOBAL_CONTEXT__ ? window.__REACT_INTL_CONTEXT__ || (window.__REACT_INTL_CONTEXT__ = React__namespace.createContext(null)) : React__namespace.createContext(null); IntlContext.Consumer; IntlContext.Provider; var Context = IntlContext; function useIntl() { var intl = React__namespace.useContext(Context); invariantIntlContext(intl); return intl; } var DisplayName; (function(DisplayName2) { DisplayName2["formatDate"] = "FormattedDate"; DisplayName2["formatTime"] = "FormattedTime"; DisplayName2["formatNumber"] = "FormattedNumber"; DisplayName2["formatList"] = "FormattedList"; DisplayName2["formatDisplayName"] = "FormattedDisplayName"; })(DisplayName || (DisplayName = {})); var DisplayNameParts; (function(DisplayNameParts2) { DisplayNameParts2["formatDate"] = "FormattedDateParts"; DisplayNameParts2["formatTime"] = "FormattedTimeParts"; DisplayNameParts2["formatNumber"] = "FormattedNumberParts"; DisplayNameParts2["formatList"] = "FormattedListParts"; })(DisplayNameParts || (DisplayNameParts = {})); function createFormattedDateTimePartsComponent(name) { var ComponentParts = function(props) { var intl = useIntl(); var value = props.value, children = props.children, formatProps = __rest(props, ["value", "children"]); var date = typeof value === "string" ? new Date(value || 0) : value; var formattedParts = name === "formatDate" ? intl.formatDateToParts(date, formatProps) : intl.formatTimeToParts(date, formatProps); return children(formattedParts); }; ComponentParts.displayName = DisplayNameParts[name]; return ComponentParts; } function createFormattedComponent(name) { var Component = function(props) { var intl = useIntl(); var value = props.value, children = props.children, formatProps = __rest( props, ["value", "children"] ); var formattedValue = intl[name](value, formatProps); if (typeof children === "function") { return children(formattedValue); } var Text = intl.textComponent || React__namespace.Fragment; return React__namespace.createElement(Text, null, formattedValue); }; Component.displayName = DisplayName[name]; return Component; } createFormattedComponent("formatDate"); createFormattedComponent("formatTime"); createFormattedComponent("formatNumber"); createFormattedComponent("formatList"); createFormattedComponent("formatDisplayName"); createFormattedDateTimePartsComponent("formatDate"); createFormattedDateTimePartsComponent("formatTime"); const useI18n = () => { const { formatMessage } = useIntl(); const i18n = (key, defaultMessage) => { return formatMessage({ id: `${index.pluginId}.${key}`, defaultMessage }); }; return { i18n }; }; function useAlert() { const { toggleNotification } = admin.useNotification(); const { i18n } = useI18n(); function handleNotification({ type = "info", message = i18n( "plugin.message.something", "Something occurred in Meilisearch" ), link, blockTransition = true, title }) { toggleNotification({ // optional title, // required // type: 'info|success|warning', type, // required message: i18n("notification.meilisearch.message", message), // optional link, // optional: default = false blockTransition, // optional onClose: () => localStorage.setItem("STRAPI_UPDATE_NOTIF", "true") }); } const checkForbiddenError = ({ response }) => { const status = response?.data?.error?.status; if (status && status === 403) { handleNotification({ title: i18n("plugin.message.forbidden.title", "Forbidden"), type: "warning", message: i18n( "plugin.message.forbidden.description", "You do not have permission to do this action" ), blockTransition: false }); } }; return { handleNotification, checkForbiddenError }; } function useCollection() { const [collections, setCollections] = React.useState([]); const [refetchIndex, setRefetchIndex] = React.useState(true); const [reloadNeeded, setReloadNeeded] = React.useState(false); const [realTimeReports, setRealTimeReports] = React.useState(false); const { handleNotification, checkForbiddenError } = useAlert(); const { i18n } = useI18n(); const { get, del, post, put } = admin.useFetchClient(); const refetchCollection = () => setRefetchIndex((prevRefetchIndex) => !prevRefetchIndex); const hookingTextRendering = ({ indexed, listened }) => { if (indexed && listened) return i18n("plugin.table.td.hookingText.hooked", "Hooked"); if (!indexed && !listened) return "/"; return i18n("plugin.table.td.hookingText.reload", "Reload needed"); }; const fetchCollections = async () => { try { const { data: { data, error } } = await get(`/${index.pluginId}/content-type/`); if (error) { handleNotification({ type: "warning", message: error.message, link: error.link }); } else { const collections2 = data.contentTypes.map((collection) => { collection["reloadNeeded"] = hookingTextRendering({ indexed: collection.indexed, listened: collection.listened }); return collection; }); const reload = collections2.find( (col) => col.reloadNeeded === i18n("plugin.table.td.hookingText.reload", "Reload needed") ); const isIndexing = collections2.find((col) => col.isIndexing === true); if (!isIndexing) setRealTimeReports(false); else setRealTimeReports(true); if (reload) { setReloadNeeded(true); } else setReloadNeeded(false); setCollections(collections2); } } catch (error) { checkForbiddenError(error); } }; const deleteCollection = async ({ contentType }) => { try { const { data: { error } } = await del(`/${index.pluginId}/content-type/${contentType}`); if (error) { handleNotification({ type: "warning", message: error.message, link: error.link }); } else { refetchCollection(); handleNotification({ type: "success", message: i18n( "plugin.message.success.delete", "Request to delete content-type is successful" ), blockTransition: false }); } } catch (error) { checkForbiddenError(error); } }; const addCollection = async ({ contentType }) => { try { const { data: { error } } = await post(`/${index.pluginId}/content-type`, { contentType }); console.log(error); if (error) { handleNotification({ type: "warning", message: error.message, link: error.link }); } else { refetchCollection(); handleNotification({ type: "success", message: i18n( "plugin.message.success.add", "Request to add a content-type is successful" ), blockTransition: false }); } } catch (error) { checkForbiddenError(error); } }; const updateCollection = async ({ contentType }) => { try { const { data: { error } } = await put(`/${index.pluginId}/content-type`, { contentType }); if (error) { handleNotification({ type: "warning", message: error.message, link: error.link }); } else { refetchCollection(); handleNotification({ type: "success", message: i18n( "plugin.message.success.update", "Request to update content-type is successful" ), blockTransition: false }); } } catch (error) { checkForbiddenError(error); } }; React.useEffect(() => { fetchCollections(); }, [refetchIndex]); React.useEffect(() => { let interval; if (realTimeReports) { interval = setInterval(() => { refetchCollection(); }, 1e3); } else { clearInterval(interval); } return () => clearInterval(interval); }, [realTimeReports]); return { collections, deleteCollection, addCollection, updateCollection, reloadNeeded, refetchCollection, handleNotification }; } const CollectionColumn = ({ entry, deleteCollection, addCollection, updateCollection }) => { const { i18n } = useI18n(); const { allowedActions: { canCreate, canUpdate, canDelete } } = admin.useRBAC(index.PERMISSIONS.collections); return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [ (canCreate || canDelete) && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx( designSystem.Checkbox, { "aria-label": `Select ${entry.collection}`, onCheckedChange: () => { if (entry.indexed) deleteCollection({ contentType: entry.contentType }); else addCollection({ contentType: entry.contentType }); }, checked: entry.indexed } ) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: entry.collection }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: entry.indexed ? i18n("plugin.table.td.yes", "Yes") : i18n("plugin.table.td.no", "No") }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: entry.isIndexing ? i18n("plugin.table.td.yes", "Yes") : i18n("plugin.table.td.no", "No") }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: entry.indexUid }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { textColor: "neutral800", children: [ entry.numberOfDocuments, " / ", entry.numberOfEntries ] }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { textColor: "neutral800", children: entry.reloadNeeded }) }), canUpdate && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Flex, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingLeft: 1, children: entry.indexed && /* @__PURE__ */ jsxRuntime.jsx( designSystem.Button, { onClick: () => updateCollection({ contentType: entry.contentType }), size: "S", variant: "secondary", children: i18n("plugin.update", "Update") } ) }) }) }) ] }, entry.contentType); }; const CollectionColumn$1 = React.memo(CollectionColumn); const CollectionTableHeader = () => { const { i18n } = useI18n(); const { allowedActions: { canCreate, canUpdate, canDelete } } = admin.useRBAC(index.PERMISSIONS.collections); return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [ (canCreate || canDelete) && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { children: "INDEX" }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: i18n("plugin.table.header.name", "NAME") }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: i18n("plugin.table.header.in-meilisearch", "IN MEILISEARCH ?") }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: i18n("plugin.table.header.indexing", "INDEXING ?") }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: i18n("plugin.table.header.index-name", "INDEX NAME") }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: i18n("plugin.table.header.documents", "DOCUMENTS") }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: i18n("plugin.table.header.hooks", "HOOKS") }) }), canUpdate && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.VisuallyHidden, { children: "Actions" }) }) ] }) }); }; const CollectionTableHeader$1 = React.memo(CollectionTableHeader); const SERVER_HAS_NOT_BEEN_KILLED_MESSAGE = "did-not-kill-server"; const SERVER_HAS_BEEN_KILLED_MESSAGE = "server is down"; function serverRestartWatcher(response, didShutDownServer) { return new Promise((resolve) => { fetch(`${window.strapi.backendURL}/_health`, { method: "HEAD", mode: "no-cors", headers: { "Content-Type": "application/json", "Keep-Alive": "false" } }).then((res) => { if (res.status >= 400) { throw new Error(SERVER_HAS_BEEN_KILLED_MESSAGE); } if (!didShutDownServer) { throw new Error(SERVER_HAS_NOT_BEEN_KILLED_MESSAGE); } resolve(response); }).catch((err) => { setTimeout(() => { return serverRestartWatcher( response, err.message !== SERVER_HAS_NOT_BEEN_KILLED_MESSAGE ).then(resolve); }, 100); }); }); } const Collection = () => { const { collections, deleteCollection, addCollection, updateCollection, reloadNeeded, refetchCollection } = useCollection(); const { lockAppWithAutoreload, unlockAppWithAutoreload } = admin.private_useAutoReloadOverlayBlocker(); const { get } = admin.useFetchClient(); const [reload, setReload] = React.useState(false); const { i18n } = useI18n(); const ROW_COUNT = 6; const COL_COUNT = 10; const reloadServer = async () => { try { lockAppWithAutoreload(); await get(`/${index.pluginId}/reload`, true); await serverRestartWatcher(true); setReload(false); } catch (err) { console.error(err); } finally { unlockAppWithAutoreload(); refetchCollection(); } }; React.useEffect(() => { if (reload) reloadServer(); }, [reload]); return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { background: "neutral100", children: [ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { colCount: COL_COUNT, rowCount: ROW_COUNT, children: [ /* @__PURE__ */ jsxRuntime.jsx(CollectionTableHeader$1, {}), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: collections.map((collection) => /* @__PURE__ */ jsxRuntime.jsx( CollectionColumn$1, { entry: collection, deleteCollection, addCollection, updateCollection }, collection.collection )) }) ] }), reloadNeeded && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 5, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { onClick: () => setReload(true), children: i18n("plugin.reload-server", "Reload server") }) }) ] }); }; const CollectionTable = React.memo(Collection); function useCredential() { const [credentials, setCredentials] = React.useState({ host: "", apiKey: "", ApiKeyIsFromConfigFile: true, HostIsFromConfigFile: true }); const [refetchIndex, setRefetchIndex] = React.useState(true); const [host, setHost] = React.useState(""); const [apiKey, setApiKey] = React.useState(""); const { handleNotification } = useAlert(); const { i18n } = useI18n(); const { get, post } = admin.useFetchClient(); const refetchCredentials = () => setRefetchIndex((prevRefetchIndex) => !prevRefetchIndex); const updateCredentials = async () => { const { data: { error } } = await post(`/${index.pluginId}/credential`, { apiKey, host }); if (error) { handleNotification({ type: "warning", message: error.message, link: error.link }); } else { refetchCredentials(); handleNotification({ type: "success", message: i18n( "plugin.message.success.credentials", "Credentials sucessfully updated!" ), blockTransition: false }); } }; const fetchCredentials = async () => { const { data: { data, error } } = await get(`/${index.pluginId}/credential`); if (error) { handleNotification({ type: "warning", message: error.message, link: error.link }); } else { setCredentials(data); setHost(data.host); setApiKey(data.apiKey); } }; React.useEffect(() => { fetchCredentials(); }, [refetchIndex]); return { credentials, updateCredentials, setHost, setApiKey, host, apiKey }; } const Credentials = () => { const { host, apiKey, credentials, setHost, setApiKey, updateCredentials } = useCredential(); const { i18n } = useI18n(); const { allowedActions: { canEdit } } = admin.useRBAC(index.PERMISSIONS.settingsEdit); return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Box, { children: [ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 2, children: /* @__PURE__ */ jsxRuntime.jsxs( designSystem.Field.Root, { id: "host", hint: i18n( "plugin.tab.settings.input.url.hint", "The URL on which your Meilisearch is running" ), children: [ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: i18n("plugin.tab.settings.input.url.label", "Meilisearch URL") }), /* @__PURE__ */ jsxRuntime.jsx( designSystem.Field.Input, { type: "text", name: "host", value: host, placeholder: i18n( "plugin.tab.settings.input.url.placeholder", "URL" ), onChange: (e) => setHost(e.target.value), disabled: credentials.HostIsFromConfigFile } ), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}) ] } ) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 2, children: /* @__PURE__ */ jsxRuntime.jsxs( designSystem.Field.Root, { id: "apiKey", hint: i18n( "plugin.tab.settings.input.apiKey.hint", "A valid API key with enough permission to create indexes (or the master key)." ), children: [ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: i18n( "plugin.tab.settings.input.apiKey.label", "Meilisearch API Key" ) }), /* @__PURE__ */ jsxRuntime.jsx( designSystem.Field.Input, { type: "password", name: "apiKey", placeholder: i18n( "plugin.tab.settings.input.apiKey.placeholder", "API key" ), value: apiKey, onChange: (e) => setApiKey(e.target.value), disabled: credentials.ApiKeyIsFromConfigFile } ), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Hint, {}) ] } ) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 1, paddingLeft: 2, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "pi", style: { color: "red" }, children: [ i18n( "plugin.tab.settings.warning.credentials.1", "Do not use this API key on your front-end as it has too much rights. Instead, use the public key available using" ), " ", /* @__PURE__ */ jsxRuntime.jsx( designSystem.Link, { isExternal: true, href: "https://www.meilisearch.com/docs/reference/api/keys#get-keys", children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", style: { color: "red" }, children: i18n( "plugin.tab.settings.warning.credentials.2", "the key route" ) }) } ), "." ] }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, paddingLeft: 2, paddingRight: 2, paddingBottom: 2, children: canEdit && /* @__PURE__ */ jsxRuntime.jsx( designSystem.Button, { variant: "secondary", onClick: () => updateCredentials(), disabled: credentials.ApiKeyIsFromConfigFile && credentials.HostIsFromConfigFile, children: i18n("plugin.save", "Save") } ) }) ] }); }; const Credentials$1 = React.memo(Credentials); const Settings = () => { return /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { padding: 5, children: /* @__PURE__ */ jsxRuntime.jsx(Credentials$1, {}) }); }; const PluginTabs = () => { const { i18n } = useI18n(); const { allowedActions: allowedActionsCollection } = admin.useRBAC( index.PERMISSIONS.collections ); const { allowedActions: allowedActionsSettings } = admin.useRBAC( index.PERMISSIONS.settings ); const canSeeCollections = Object.values(allowedActionsCollection).some( (value) => !!value ); const canSeeSettings = Object.values(allowedActionsSettings).some( (value) => !!value ); return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.Root, { defaultValue: "collections", children: [ /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tabs.List, { children: [ /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "collections", children: i18n("plugin.tab.collections", "Collections") }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Trigger, { value: "settings", children: i18n("plugin.tab.settings", "Settings") }) ] }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "collections", children: canSeeCollections && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { color: "neutral800", padding: 4, background: "neutral0", children: /* @__PURE__ */ jsxRuntime.jsx(CollectionTable, {}) }) }), /* @__PURE__ */ jsxRuntime.jsx(designSystem.Tabs.Content, { value: "settings", children: canSeeSettings && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { color: "neutral800", padding: 4, background: "neutral0", children: /* @__PURE__ */ jsxRuntime.jsx(Settings, {}) }) }) ] }); }; const HomePage = () => { const { i18n } = useI18n(); return /* @__PURE__ */ jsxRuntime.jsx(admin.private_AutoReloadOverlayBlockerProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(admin.Page.Main, { children: [ /* @__PURE__ */ jsxRuntime.jsx( admin.Layouts.Header, { title: i18n("plugin.name", "Meilisearch"), subtitle: i18n( "plugin.description", "Search in your content-types with the Meilisearch plugin" ), navigationAction: /* @__PURE__ */ jsxRuntime.jsx(admin.BackButton, {}) } ), /* @__PURE__ */ jsxRuntime.jsx(admin.Layouts.Content, { children: /* @__PURE__ */ jsxRuntime.jsx(PluginTabs, {}) }) ] }) }); }; const App = () => { return /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Protect, { permissions: index.PERMISSIONS.main, children: /* @__PURE__ */ jsxRuntime.jsxs(reactRouterDom.Routes, { children: [ /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { index: true, element: /* @__PURE__ */ jsxRuntime.jsx(HomePage, {}) }), /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Route, { path: "*", element: /* @__PURE__ */ jsxRuntime.jsx(admin.Page.Error, {}) }) ] }) }); }; exports.App = App;