diff --git a/packages/noco-docs/docusaurus.config.js b/packages/noco-docs/docusaurus.config.js index 2003e5ead2..6d6c35ff42 100644 --- a/packages/noco-docs/docusaurus.config.js +++ b/packages/noco-docs/docusaurus.config.js @@ -206,7 +206,7 @@ const config = { }, }, }), - clientModules: [require.resolve("./src/modules/tele.js")], + clientModules: [require.resolve("./src/modules/tele.js"), require.resolve("./src/modules/maintenance.js")], }; module.exports = config; diff --git a/packages/noco-docs/src/css/custom.scss b/packages/noco-docs/src/css/custom.scss index feecefdfff..ac34ba2c60 100644 --- a/packages/noco-docs/src/css/custom.scss +++ b/packages/noco-docs/src/css/custom.scss @@ -1,6 +1,8 @@ @use 'header'; +@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@200..800&display=swap'); + /** * Any CSS included here will be global. The classic template * bundles Infima by default. Infima is a CSS framework designed to diff --git a/packages/noco-docs/src/modules/maintenance.js b/packages/noco-docs/src/modules/maintenance.js new file mode 100644 index 0000000000..48767f03b0 --- /dev/null +++ b/packages/noco-docs/src/modules/maintenance.js @@ -0,0 +1,126 @@ +import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment'; + + +function isValid(date) { + const now = new Date(); + if (new Date(date) > now) { + const lastDismissedDate = localStorage.getItem( + "lastMaintenanceDismissed" + ); + const todayString = now.toISOString().split("T")[0]; + + if (lastDismissedDate !== todayString) { + return true; + } + } + return false; +} + +const timeZoneAbbreviated = () => { + const { 1: tz } = new Date().toString().match(/\((.+)\)/); + + if (tz.includes(" ")) { + return tz + .split(" ") + .map(([first]) => first) + .join(""); + } else { + return tz; + } +}; + +function renderEjsTemplate(template, data) { + return template.replace( + /<%= (\w+) %>/g, + (match, key) => data[key] || "" + ); +} + +if (ExecutionEnvironment.canUseDOM) { + const dayjs = require('dayjs'); + + dayjs.extend(require('dayjs/plugin/utc')); + dayjs.extend(require('dayjs/plugin/advancedFormat')); + dayjs.extend(require('dayjs/plugin/timezone')); + + let config = await fetch( + "https://nocodb.com/api/v1/config?get=maintenance" + ) + .then(async (res) => (await res.json()).value) + .catch((e) => { + console.error("Error fetching maintenance config", e); + return null; + }); + + if (typeof config === "string") { + config = JSON.parse(config); + } + + if (config && isValid(config.date)) { + const compiledText = renderEjsTemplate(config.description, { + date: `${dayjs(config.date).format( + "YYYY-MM-DD HH:mm" + )} ${timeZoneAbbreviated()}`, + ptTime: dayjs(config.date) + .tz("America/Los_Angeles") + .format("HH:mm z"), + }); + + const innerHtml = ` +
+ `; + + const divElem = document.createElement("div"); + divElem.classList.add("maintenance-banner"); + divElem.style.position = "fixed"; + divElem.style.bottom = "20px"; + divElem.style.right = "-350px"; + divElem.style.borderRadius = "0.75rem"; + divElem.style.width = "300px"; + divElem.style.padding = "12px"; + divElem.style.transition = "1s opacity, 1s right"; + divElem.style.background = "#FEE6D6"; + divElem.style.color = "#1F293A"; + divElem.style.zIndex = "1000"; + divElem.style.display = "flex"; + divElem.innerHTML = innerHtml; + + const closeBtn = document.createElement("button"); + closeBtn.style.position = "absolute"; + closeBtn.style.top = "8px"; + closeBtn.style.right = "8px"; + closeBtn.style.background = "transparent"; + closeBtn.style.border = "none"; + closeBtn.style.cursor = "pointer"; + closeBtn.style.color = "#1F293A"; + closeBtn.innerHTML = + ''; + closeBtn.onclick = () => { + divElem.style.display = "none"; + localStorage.setItem( + "lastMaintenanceDismissed", + new Date().toISOString().split("T")[0] + ); + }; + + const styleEl = document.createElement("style"); + styleEl.innerHTML = ` + .maintenance-banner.active { + opacity: 1; + right:28px !important; + } + `; + + divElem.appendChild(closeBtn); + + document.body.appendChild(divElem); + setTimeout(() => divElem.classList.add("active"), 2000); + document.body.appendChild(styleEl); + } +}