kempo 4.5.1 → 4.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +5 -0
  2. package/dist/admin/components/Dashboard.js +67 -0
  3. package/dist/admin/components/Dashboard.js.map +1 -0
  4. package/dist/admin/components/dashboardLayout.js +2 -0
  5. package/dist/admin/components/dashboardLayout.js.map +1 -0
  6. package/dist/admin/components/widgets/Content.js +4 -0
  7. package/dist/admin/components/widgets/Content.js.map +1 -0
  8. package/dist/admin/components/widgets/Extensions.js +5 -0
  9. package/dist/admin/components/widgets/Extensions.js.map +1 -0
  10. package/dist/admin/components/widgets/Notifications.js +4 -0
  11. package/dist/admin/components/widgets/Notifications.js.map +1 -0
  12. package/dist/admin/components/widgets/Pages.js +23 -0
  13. package/dist/admin/components/widgets/Pages.js.map +1 -0
  14. package/dist/admin/components/widgets/Users.js +5 -0
  15. package/dist/admin/components/widgets/Users.js.map +1 -0
  16. package/dist/admin/index.page.html +2 -1
  17. package/dist/admin/nav.fragment.html +57 -58
  18. package/dist/admin/realtime/index.page.html +2 -2
  19. package/dist/kempo/api/dashboard/widgets/GET.js +2 -0
  20. package/dist/kempo/api/dashboard/widgets/GET.js.map +1 -0
  21. package/dist/kempo/api/notifications/GET.js +1 -1
  22. package/dist/kempo/api/notifications/[id]/DELETE.js +1 -1
  23. package/dist/kempo/api/notifications/[id]/handled/POST.js +1 -1
  24. package/dist/kempo/api/notifications/[id]/read/POST.js +1 -1
  25. package/dist/kempo/api/notifications/count/GET.js +1 -1
  26. package/dist/kempo/api/notifications/read-all/POST.js +1 -1
  27. package/dist/kempo/components/AdminNavFooter.js +2 -0
  28. package/dist/kempo/components/AdminNavFooter.js.map +1 -0
  29. package/dist/kempo/components/DashboardWidget.js +18 -0
  30. package/dist/kempo/components/DashboardWidget.js.map +1 -0
  31. package/dist/kempo/components/Login.js +1 -1
  32. package/dist/kempo/components/NotificationBell.js +3 -3
  33. package/dist/kempo/components/NotificationBell.js.map +1 -1
  34. package/dist/kempo/components/NotificationList.js +1 -1
  35. package/dist/kempo/components/Register.js +1 -1
  36. package/dist/kempo/sdk.js +2 -2
  37. package/dist/kempo/sdk.js.map +1 -1
  38. package/dist/kempo/utils/safeNext.js +1 -1
  39. package/package.json +1 -1
  40. package/server/db/schema.js +34 -1
  41. package/server/sdk.js +8 -0
  42. package/server/utils/dashboard/coreWidgets.js +87 -0
  43. package/server/utils/dashboard/helpers.js +144 -0
  44. package/server/utils/dashboard/listDashboardWidgets.js +63 -0
  45. package/server/utils/dashboard/registerDashboardWidget.js +40 -0
  46. package/server/utils/dashboard/unregisterDashboardWidget.js +24 -0
  47. package/server/utils/extensions/installExtension.js +11 -0
  48. package/server/utils/extensions/uninstallExtension.js +2 -1
  49. package/server/utils/extensions/updateExtension.js +18 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"src\\kempo\\components\\DashboardWidget.js","names":["LightComponent","html","nothing","Dialog","currentUserHasPermission","DashboardWidget","static","width","type","Number","reflect","height","definition","attribute","loading","state","failure","ctaAllowed","constructor","super","this","cta","connectedCallback","classList","add","style","refresh","checkCta","load","async","error","message","getCta","actions","unwrap","data","request","Error","msg","openForm","title","fields","confirmText","submit","content","document","createElement","className","inputs","forEach","name","label","placeholder","value","options","wrapper","caption","Object","assign","textContent","input","option","append","selected","role","dialog","create","cancelText","confirmAction","event","keepDialogOpen","values","fromEntries","map","trim","missing","find","required","close","focus","permission","hasPermission","renderTitle","icon","renderActions","compact","href","onClick","primary","classes","renderHeader","renderContent","renderBody","renderFooter","renderLightDom"],"sources":["0"],"sourcesContent":["import LightComponent from '/kempo-ui/components/LightComponent.js';\nimport { html, nothing } from '/kempo-ui/lit-all.min.js';\nimport '/kempo-ui/components/Icon.js';\nimport Dialog from '/kempo-ui/components/Dialog.js';\nimport { currentUserHasPermission } from '/kempo/sdk.js';\n\n/*\n The base class for an admin dashboard widget. Extend it, define your element, and register the widget\n with `registerDashboardWidget` (or `kempo.widgets` in package.json).\n\n The dashboard creates the element only when the user has the widget on screen, and sets `width` and\n `height` (in blocks) on it, so a widget never loads data for a tile that is hidden. Override:\n\n `load()` fetch what the widget needs and assign it to reactive properties. Throw to show\n the failure message with a retry button. Runs when the element connects and\n again on `refresh()`.\n `renderContent()` return the markup for a loaded widget. Use `width` and `height` to show more\n when there is room.\n\n Declare your own properties by spreading the base ones:\n `static properties = { ...DashboardWidget.properties, items: { state: true } }`.\n\n The widget fills a bordered tile and owns everything inside it, its header included. `renderHeader()`\n returns the header region; the default is the widget's icon and title from `definition` (the registered\n widget, set by the dashboard). Override it to add buttons, filters or a different title, and use\n `renderTitle()` to keep the default title inside your own header.\n\n Call to action. A widget may offer one primary thing to do, drawn the same way in every tile as a button\n in a footer. It is optional. Set `this.cta` in the constructor (or override `getCta()` when it depends on\n state) to `{ label, icon, href }` for a link, or `{ label, icon, onClick }` for a callback, and add\n `permission` to show it only to people who hold that permission. For a callback that needs input, call\n `openForm()` to get a standard dialog.\n\n Header actions are separate: links declared on the registration (`actions`), or returned from\n `actions()`, appear as small buttons beside the title.\n\n Call `super.updated(changed)` if you override `updated()`.\n*/\nexport default class DashboardWidget extends LightComponent {\n static properties = {\n width: { type: Number, reflect: true },\n height: { type: Number, reflect: true },\n definition: { attribute: false },\n loading: { state: true },\n failure: { state: true },\n ctaAllowed: { state: true }\n };\n\n constructor(){\n super();\n this.width = 2;\n this.height = 1;\n this.definition = null;\n this.cta = null;\n this.loading = true;\n this.failure = '';\n this.ctaAllowed = false;\n }\n\n /*\n Lifecycle Callbacks\n */\n\n connectedCallback(){\n super.connectedCallback();\n this.classList.add('d-b');\n this.style.height = '100%';\n this.refresh();\n this.checkCta();\n }\n\n /*\n Public Methods\n */\n\n load = async () => {};\n\n refresh = async () => {\n try {\n await this.load();\n this.failure = '';\n } catch(error) {\n this.failure = error?.message || 'Could not load this widget.';\n }\n this.loading = false;\n };\n\n getCta(){\n return this.cta;\n }\n\n actions(){\n return [];\n }\n\n /*\n Resolves an SDK call, which returns `[error, data]`, to its data, or throws the error's message so\n `load()` can stay a straight line.\n */\n unwrap = async request => {\n const [error, data] = await request;\n if(error) throw new Error(error.msg || 'Request failed');\n return data;\n };\n\n /*\n Opens a standard dialog with a few fields and a confirm button.\n\n `fields` are `{ name, label, type, placeholder, value, options, required }` where `type` is `text`\n (default), `email`, `password` or `select` (then `options` is `[{ value, label }]`). `submit` receives\n `{ [name]: value }` and returns nothing on success, which closes the dialog, or an error message, which\n is shown in the dialog and keeps it open with what was typed.\n */\n openForm = ({ title, fields, confirmText = 'Save', submit }) => {\n const content = document.createElement('div');\n content.className = 'p';\n const inputs = {};\n\n fields.forEach(({ name, label, type = 'text', placeholder = '', value = '', options = [] }) => {\n const wrapper = document.createElement('div');\n wrapper.className = 'mb';\n const caption = Object.assign(document.createElement('label'), { className: 'd-b mbq', textContent: label });\n let input;\n\n if(type === 'select'){\n input = document.createElement('select');\n input.className = 'full';\n options.forEach(option => input.append(Object.assign(document.createElement('option'), { value: option.value, textContent: option.label, selected: option.value === value })));\n } else {\n input = Object.assign(document.createElement('input'), { type, className: 'full', placeholder, value });\n }\n\n inputs[name] = input;\n wrapper.append(caption, input);\n content.append(wrapper);\n });\n\n const error = Object.assign(document.createElement('p'), { className: 'tc-danger m0', role: 'alert' });\n content.append(error);\n\n const dialog = Dialog.create(content, {\n title,\n confirmText,\n cancelText: 'Cancel',\n confirmAction: async event => {\n event.keepDialogOpen = true;\n error.textContent = '';\n const values = Object.fromEntries(fields.map(({ name }) => [name, inputs[name].value.trim()]));\n const missing = fields.find(({ name, required = true }) => required && !values[name]);\n\n if(missing){\n error.textContent = `${missing.label} is required.`;\n return;\n }\n\n const message = await submit(values);\n\n if(message) error.textContent = message;\n else dialog.close();\n }\n });\n\n Object.values(inputs)[0]?.focus();\n return dialog;\n };\n\n /*\n Utility Functions\n */\n\n checkCta = async () => {\n const permission = this.getCta()?.permission;\n\n if(!permission){\n this.ctaAllowed = true;\n return;\n }\n\n const [error, data] = await currentUserHasPermission({ permission });\n this.ctaAllowed = !error && !!data?.hasPermission;\n };\n\n /*\n Rendering\n */\n\n renderTitle = () => html`\n ${this.definition?.icon ? html`<k-icon class=\"mr\" name=${this.definition.icon}></k-icon>` : nothing}\n <strong class=\"flex\">${this.definition?.title ?? ''}</strong>\n `;\n\n renderActions = () => {\n const compact = this.width < 2;\n return [...(this.definition?.actions ?? []), ...this.actions()].map(({ label, icon, href, onClick, primary }) => {\n const content = icon\n ? html`<k-icon name=${icon}></k-icon>${compact ? nothing : html` ${label}`}`\n : label;\n const classes = `btn ml ${primary ? 'primary' : ''}`;\n return href\n ? html`<a class=${classes} href=${href} title=${label} aria-label=${label}>${content}</a>`\n : html`<button class=${classes} title=${label} aria-label=${label} @click=${onClick}>${content}</button>`;\n });\n };\n\n renderHeader(){\n return html`<header class=\"d-f px pyh bb\" style=\"align-items: center;\">${this.renderTitle()}${this.renderActions()}</header>`;\n }\n\n renderContent(){\n return nothing;\n }\n\n renderBody(){\n if(this.failure){\n return html`\n <p class=\"tc-danger\" role=\"alert\">${this.failure}</p>\n <button @click=${this.refresh}>Try again</button>\n `;\n }\n if(this.loading) return html`<p class=\"tc-muted\">Loading&hellip;</p>`;\n return this.renderContent();\n }\n\n renderFooter = () => {\n const cta = this.getCta();\n\n if(!cta || !this.ctaAllowed || this.failure) return nothing;\n\n const content = html`${cta.icon ? html`<k-icon name=${cta.icon}></k-icon> ` : nothing}${cta.label}`;\n\n return html`\n <footer class=\"d-f px pyh bt\" style=\"justify-content: flex-end;\">\n ${cta.href\n ? html`<a class=\"btn primary\" href=${cta.href}>${content}</a>`\n : html`<button class=\"primary\" @click=${cta.onClick}>${content}</button>`}\n </footer>\n `;\n };\n\n renderLightDom(){\n return html`\n <div style=\"display: flex; flex-direction: column; height: 100%; min-height: 0;\">\n ${this.renderHeader()}\n <div class=\"p\" style=\"flex: 1; min-height: 0; overflow: auto;\">${this.renderBody()}</div>\n ${this.renderFooter()}\n </div>\n `;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -15,4 +15,4 @@ import e from"/kempo-ui/components/LightComponent.js";import{html as s}from"/kem
15
15
  <p class="mt"><a href="/forgot-password">Forgot Password?</a></p>
16
16
  <p class="mt">Don't have an account? <a href="/register">Register</a></p>
17
17
  `}}customElements.define("k-login",a);
18
- //# sourceMappingURL=c:\Users\dusti\dev\kempo\dist\kempo\components\Login.js.map
18
+ //# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\kempo\components\Login.js.map
@@ -1,6 +1,6 @@
1
- import t from"/kempo-ui/components/LightComponent.js";import{html as i,nothing as e}from"/kempo-ui/lit-all.min.js";import"/kempo-ui/components/Dropdown.js";import"/kempo-ui/components/Icon.js";import"./NotificationList.js";import{getUnreadNotificationCount as n,markAllNotificationsRead as s}from"/kempo/sdk.js";export default class o extends t{static properties={pageHref:{type:String,attribute:"page-href"},interval:{type:Number},openDirection:{type:String,attribute:"open-direction"},count:{state:!0},signedOut:{state:!0}};#t=null;constructor(){super(),this.pageHref="",this.interval=6e4,this.openDirection="down right",this.count=0,this.signedOut=!1}connectedCallback(){super.connectedCallback(),window.addEventListener("focus",this.refreshCount),document.addEventListener("visibilitychange",this.handleVisibility),this.refreshCount(),this.interval>0&&(this.#t=setInterval(this.handleTick,this.interval))}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("focus",this.refreshCount),document.removeEventListener("visibilitychange",this.handleVisibility),clearInterval(this.#t)}refreshCount=async()=>{const[t,i]=await n();if(t)return this.signedOut=401===t.code,void(this.signedOut&&(this.count=0));this.signedOut=!1,this.count=i.count};handleTick=()=>{document.hidden||this.refreshCount()};handleVisibility=()=>{document.hidden||this.refreshCount()};handleOpened=t=>{t.target.closest("k-notification-bell")===this&&(this.querySelector("k-notification-list")?.refresh(),this.refreshCount())};handleChange=t=>{this.count=t.detail.unread};markAll=async()=>{await s(),await(this.querySelector("k-notification-list")?.refresh())};renderLightDom(){return this.signedOut?e:i`
1
+ import t from"/kempo-ui/components/LightComponent.js";import{html as i,nothing as e}from"/kempo-ui/lit-all.min.js";import"/kempo-ui/components/Dropdown.js";import"/kempo-ui/components/Icon.js";import"./NotificationList.js";import{getUnreadNotificationCount as n,markAllNotificationsRead as s}from"/kempo/sdk.js";export default class o extends t{static properties={pageHref:{type:String,attribute:"page-href"},interval:{type:Number},openDirection:{type:String,attribute:"open-direction"},buttonClass:{type:String,attribute:"button-class"},count:{state:!0},signedOut:{state:!0}};#t=null;constructor(){super(),this.pageHref="",this.interval=6e4,this.openDirection="down right",this.buttonClass="",this.count=0,this.signedOut=!1}connectedCallback(){super.connectedCallback(),window.addEventListener("focus",this.refreshCount),document.addEventListener("visibilitychange",this.handleVisibility),this.refreshCount(),this.interval>0&&(this.#t=setInterval(this.handleTick,this.interval))}disconnectedCallback(){super.disconnectedCallback(),window.removeEventListener("focus",this.refreshCount),document.removeEventListener("visibilitychange",this.handleVisibility),clearInterval(this.#t)}refreshCount=async()=>{const[t,i]=await n();if(t)return this.signedOut=401===t.code,void(this.signedOut&&(this.count=0));this.signedOut=!1,this.count=i.count};handleTick=()=>{document.hidden||this.refreshCount()};handleVisibility=()=>{document.hidden||this.refreshCount()};handleOpened=t=>{t.target.closest("k-notification-bell")===this&&(this.querySelector("k-notification-list")?.refresh(),this.refreshCount())};handleChange=t=>{this.count=t.detail.unread};markAll=async()=>{await s(),await(this.querySelector("k-notification-list")?.refresh())};renderLightDom(){return this.signedOut?e:i`
2
2
  <k-dropdown close-on-select="false" open-direction=${this.openDirection} @opened=${this.handleOpened}>
3
- <button slot="trigger" class="no-btn d-f" aria-label=${this.count?`Notifications, ${this.count} unread`:"Notifications"}>
3
+ <button slot="trigger" class="no-btn d-f ${this.buttonClass}" aria-label=${this.count?`Notifications, ${this.count} unread`:"Notifications"}>
4
4
  <k-icon name="notifications"></k-icon>
5
5
  ${this.count?i`<span class="bg-danger round pxh ml" data-unread-badge>${this.count>99?"99+":this.count}</span>`:e}
6
6
  </button>
@@ -14,4 +14,4 @@ import t from"/kempo-ui/components/LightComponent.js";import{html as i,nothing a
14
14
  </div>
15
15
  </k-dropdown>
16
16
  `}}customElements.define("k-notification-bell",o);
17
- //# sourceMappingURL=C:\Users\dusti\dev\kempo-notifications\dist\kempo\components\NotificationBell.js.map
17
+ //# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\kempo\components\NotificationBell.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"src\\kempo\\components\\NotificationBell.js","names":["LightComponent","html","nothing","getUnreadNotificationCount","markAllNotificationsRead","NotificationBell","static","pageHref","type","String","attribute","interval","Number","openDirection","count","state","signedOut","timer","constructor","super","this","connectedCallback","window","addEventListener","refreshCount","document","handleVisibility","setInterval","handleTick","disconnectedCallback","removeEventListener","clearInterval","async","error","data","code","hidden","handleOpened","event","target","closest","querySelector","refresh","handleChange","detail","unread","markAll","renderLightDom","customElements","define"],"sources":["0"],"sourcesContent":["import LightComponent from '/kempo-ui/components/LightComponent.js';\nimport { html, nothing } from '/kempo-ui/lit-all.min.js';\nimport '/kempo-ui/components/Dropdown.js';\nimport '/kempo-ui/components/Icon.js';\nimport './NotificationList.js';\nimport { getUnreadNotificationCount, markAllNotificationsRead } from '/kempo/sdk.js';\n\n/*\n A bell with an unread badge that opens the latest notifications. It is the one element a site needs to\n show a signed-in user their notifications; it renders nothing when nobody is signed in.\n\n Attributes: `page-href` (a \"View all\" link to a full notifications page, hidden when unset),\n `interval` (milliseconds between background checks of the count, default 60000, 0 to turn them off) and\n `open-direction` (passed to the dropdown). The count is also refreshed on load, when the window regains\n focus and whenever the panel opens.\n*/\nexport default class NotificationBell extends LightComponent {\n static properties = {\n pageHref: { type: String, attribute: 'page-href' },\n interval: { type: Number },\n openDirection: { type: String, attribute: 'open-direction' },\n count: { state: true },\n signedOut: { state: true }\n };\n\n #timer = null;\n\n constructor(){\n super();\n this.pageHref = '';\n this.interval = 60000;\n this.openDirection = 'down right';\n this.count = 0;\n this.signedOut = false;\n }\n\n /*\n Lifecycle Callbacks\n */\n\n connectedCallback(){\n super.connectedCallback();\n window.addEventListener('focus', this.refreshCount);\n document.addEventListener('visibilitychange', this.handleVisibility);\n this.refreshCount();\n if(this.interval > 0) this.#timer = setInterval(this.handleTick, this.interval);\n }\n\n disconnectedCallback(){\n super.disconnectedCallback();\n window.removeEventListener('focus', this.refreshCount);\n document.removeEventListener('visibilitychange', this.handleVisibility);\n clearInterval(this.#timer);\n }\n\n /*\n Public Methods\n */\n\n refreshCount = async () => {\n const [error, data] = await getUnreadNotificationCount();\n if(error){\n this.signedOut = error.code === 401;\n if(this.signedOut) this.count = 0;\n return;\n }\n this.signedOut = false;\n this.count = data.count;\n };\n\n /*\n Event Handlers\n */\n\n handleTick = () => {\n if(!document.hidden) this.refreshCount();\n };\n\n handleVisibility = () => {\n if(!document.hidden) this.refreshCount();\n };\n\n handleOpened = event => {\n if(event.target.closest('k-notification-bell') !== this) return;\n this.querySelector('k-notification-list')?.refresh();\n this.refreshCount();\n };\n\n handleChange = event => {\n this.count = event.detail.unread;\n };\n\n markAll = async () => {\n await markAllNotificationsRead();\n await this.querySelector('k-notification-list')?.refresh();\n };\n\n /*\n Rendering\n */\n\n renderLightDom(){\n if(this.signedOut) return nothing;\n return html`\n <k-dropdown close-on-select=\"false\" open-direction=${this.openDirection} @opened=${this.handleOpened}>\n <button slot=\"trigger\" class=\"no-btn d-f\" aria-label=${this.count ? `Notifications, ${this.count} unread` : 'Notifications'}>\n <k-icon name=\"notifications\"></k-icon>\n ${this.count ? html`<span class=\"bg-danger round pxh ml\" data-unread-badge>${this.count > 99 ? '99+' : this.count}</span>` : nothing}\n </button>\n <div @notifications-change=${this.handleChange}>\n <div class=\"d-f p b-bottom\">\n <strong class=\"flex\">Notifications</strong>\n <button class=\"link\" ?disabled=${!this.count} @click=${this.markAll}>Mark all read</button>\n </div>\n <k-notification-list compact page-size=\"8\"></k-notification-list>\n ${this.pageHref ? html`<div class=\"ta-center p\"><a href=${this.pageHref}>View all</a></div>` : nothing}\n </div>\n </k-dropdown>\n `;\n }\n}\n\ncustomElements.define('k-notification-bell', NotificationBell);\n"],"mappings":"OAAOA,MAAoB,wDAClBC,aAAMC,MAAe,iCACvB,yCACA,qCACA,6DACEC,8BAA4BC,MAAgC,+BAWtD,MAAMC,UAAyBL,EAC5CM,kBAAoB,CAClBC,SAAU,CAAEC,KAAMC,OAAQC,UAAW,aACrCC,SAAU,CAAEH,KAAMI,QAClBC,cAAe,CAAEL,KAAMC,OAAQC,UAAW,kBAC1CI,MAAO,CAAEC,OAAO,GAChBC,UAAW,CAAED,OAAO,IAGtBE,GAAS,KAET,WAAAC,GACEC,QACAC,KAAKb,SAAW,GAChBa,KAAKT,SAAW,IAChBS,KAAKP,cAAgB,aACrBO,KAAKN,MAAQ,EACbM,KAAKJ,WAAY,CACnB,CAMA,iBAAAK,GACEF,MAAME,oBACNC,OAAOC,iBAAiB,QAASH,KAAKI,cACtCC,SAASF,iBAAiB,mBAAoBH,KAAKM,kBACnDN,KAAKI,eACFJ,KAAKT,SAAW,IAAGS,MAAKH,EAASU,YAAYP,KAAKQ,WAAYR,KAAKT,UACxE,CAEA,oBAAAkB,GACEV,MAAMU,uBACNP,OAAOQ,oBAAoB,QAASV,KAAKI,cACzCC,SAASK,oBAAoB,mBAAoBV,KAAKM,kBACtDK,cAAcX,MAAKH,EACrB,CAMAO,aAAeQ,UACb,MAAOC,EAAOC,SAAc/B,IAC5B,GAAG8B,EAGD,OAFAb,KAAKJ,UAA2B,MAAfiB,EAAME,UACpBf,KAAKJ,YAAWI,KAAKN,MAAQ,IAGlCM,KAAKJ,WAAY,EACjBI,KAAKN,MAAQoB,EAAKpB,OAOpBc,WAAa,KACPH,SAASW,QAAQhB,KAAKI,gBAG5BE,iBAAmB,KACbD,SAASW,QAAQhB,KAAKI,gBAG5Ba,aAAeC,IACVA,EAAMC,OAAOC,QAAQ,yBAA2BpB,OACnDA,KAAKqB,cAAc,wBAAwBC,UAC3CtB,KAAKI,iBAGPmB,aAAeL,IACblB,KAAKN,MAAQwB,EAAMM,OAAOC,QAG5BC,QAAUd,gBACF5B,UACAgB,KAAKqB,cAAc,wBAAwBC,YAOnD,cAAAK,GACE,OAAG3B,KAAKJ,UAAkBd,EACnBD,CAAI;2DAC4CmB,KAAKP,yBAAyBO,KAAKiB;+DAC/BjB,KAAKN,MAAQ,kBAAkBM,KAAKN,eAAiB;;YAExGM,KAAKN,MAAQb,CAAI,0DAA0DmB,KAAKN,MAAQ,GAAK,MAAQM,KAAKN,eAAiBZ;;qCAElGkB,KAAKuB;;;8CAGIvB,KAAKN,gBAAgBM,KAAK0B;;;YAG5D1B,KAAKb,SAAWN,CAAI,oCAAoCmB,KAAKb,8BAAgCL;;;KAIvG,EAGF8C,eAAeC,OAAO,sBAAuB5C","ignoreList":[]}
1
+ {"version":3,"file":"src\\kempo\\components\\NotificationBell.js","names":["LightComponent","html","nothing","getUnreadNotificationCount","markAllNotificationsRead","NotificationBell","static","pageHref","type","String","attribute","interval","Number","openDirection","buttonClass","count","state","signedOut","timer","constructor","super","this","connectedCallback","window","addEventListener","refreshCount","document","handleVisibility","setInterval","handleTick","disconnectedCallback","removeEventListener","clearInterval","async","error","data","code","hidden","handleOpened","event","target","closest","querySelector","refresh","handleChange","detail","unread","markAll","renderLightDom","customElements","define"],"sources":["0"],"sourcesContent":["import LightComponent from '/kempo-ui/components/LightComponent.js';\r\nimport { html, nothing } from '/kempo-ui/lit-all.min.js';\r\nimport '/kempo-ui/components/Dropdown.js';\r\nimport '/kempo-ui/components/Icon.js';\r\nimport './NotificationList.js';\r\nimport { getUnreadNotificationCount, markAllNotificationsRead } from '/kempo/sdk.js';\r\n\r\n/*\r\n A bell with an unread badge that opens the latest notifications. It is the one element a site needs to\r\n show a signed-in user their notifications; it renders nothing when nobody is signed in.\r\n\r\n Attributes: `page-href` (a \"View all\" link to a full notifications page, hidden when unset),\r\n `interval` (milliseconds between background checks of the count, default 60000, 0 to turn them off) and\r\n `open-direction` (passed to the dropdown) and `button-class` (extra classes for the trigger button, for\r\n example to size it like the surrounding controls). The count is also refreshed on load, when the window regains\r\n focus and whenever the panel opens.\r\n*/\r\nexport default class NotificationBell extends LightComponent {\r\n static properties = {\r\n pageHref: { type: String, attribute: 'page-href' },\r\n interval: { type: Number },\r\n openDirection: { type: String, attribute: 'open-direction' },\r\n buttonClass: { type: String, attribute: 'button-class' },\r\n count: { state: true },\r\n signedOut: { state: true }\r\n };\r\n\r\n #timer = null;\r\n\r\n constructor(){\r\n super();\r\n this.pageHref = '';\r\n this.interval = 60000;\r\n this.openDirection = 'down right';\r\n this.buttonClass = '';\r\n this.count = 0;\r\n this.signedOut = false;\r\n }\r\n\r\n /*\r\n Lifecycle Callbacks\r\n */\r\n\r\n connectedCallback(){\r\n super.connectedCallback();\r\n window.addEventListener('focus', this.refreshCount);\r\n document.addEventListener('visibilitychange', this.handleVisibility);\r\n this.refreshCount();\r\n if(this.interval > 0) this.#timer = setInterval(this.handleTick, this.interval);\r\n }\r\n\r\n disconnectedCallback(){\r\n super.disconnectedCallback();\r\n window.removeEventListener('focus', this.refreshCount);\r\n document.removeEventListener('visibilitychange', this.handleVisibility);\r\n clearInterval(this.#timer);\r\n }\r\n\r\n /*\r\n Public Methods\r\n */\r\n\r\n refreshCount = async () => {\r\n const [error, data] = await getUnreadNotificationCount();\r\n if(error){\r\n this.signedOut = error.code === 401;\r\n if(this.signedOut) this.count = 0;\r\n return;\r\n }\r\n this.signedOut = false;\r\n this.count = data.count;\r\n };\r\n\r\n /*\r\n Event Handlers\r\n */\r\n\r\n handleTick = () => {\r\n if(!document.hidden) this.refreshCount();\r\n };\r\n\r\n handleVisibility = () => {\r\n if(!document.hidden) this.refreshCount();\r\n };\r\n\r\n handleOpened = event => {\r\n if(event.target.closest('k-notification-bell') !== this) return;\r\n this.querySelector('k-notification-list')?.refresh();\r\n this.refreshCount();\r\n };\r\n\r\n handleChange = event => {\r\n this.count = event.detail.unread;\r\n };\r\n\r\n markAll = async () => {\r\n await markAllNotificationsRead();\r\n await this.querySelector('k-notification-list')?.refresh();\r\n };\r\n\r\n /*\r\n Rendering\r\n */\r\n\r\n renderLightDom(){\r\n if(this.signedOut) return nothing;\r\n return html`\r\n <k-dropdown close-on-select=\"false\" open-direction=${this.openDirection} @opened=${this.handleOpened}>\r\n <button slot=\"trigger\" class=\"no-btn d-f ${this.buttonClass}\" aria-label=${this.count ? `Notifications, ${this.count} unread` : 'Notifications'}>\r\n <k-icon name=\"notifications\"></k-icon>\r\n ${this.count ? html`<span class=\"bg-danger round pxh ml\" data-unread-badge>${this.count > 99 ? '99+' : this.count}</span>` : nothing}\r\n </button>\r\n <div @notifications-change=${this.handleChange}>\r\n <div class=\"d-f p b-bottom\">\r\n <strong class=\"flex\">Notifications</strong>\r\n <button class=\"link\" ?disabled=${!this.count} @click=${this.markAll}>Mark all read</button>\r\n </div>\r\n <k-notification-list compact page-size=\"8\"></k-notification-list>\r\n ${this.pageHref ? html`<div class=\"ta-center p\"><a href=${this.pageHref}>View all</a></div>` : nothing}\r\n </div>\r\n </k-dropdown>\r\n `;\r\n }\r\n}\r\n\r\ncustomElements.define('k-notification-bell', NotificationBell);\r\n"],"mappings":"OAAOA,MAAoB,wDAClBC,aAAMC,MAAe,iCACvB,yCACA,qCACA,6DACEC,8BAA4BC,MAAgC,+BAYtD,MAAMC,UAAyBL,EAC5CM,kBAAoB,CAClBC,SAAU,CAAEC,KAAMC,OAAQC,UAAW,aACrCC,SAAU,CAAEH,KAAMI,QAClBC,cAAe,CAAEL,KAAMC,OAAQC,UAAW,kBAC1CI,YAAa,CAAEN,KAAMC,OAAQC,UAAW,gBACxCK,MAAO,CAAEC,OAAO,GAChBC,UAAW,CAAED,OAAO,IAGtBE,GAAS,KAET,WAAAC,GACEC,QACAC,KAAKd,SAAW,GAChBc,KAAKV,SAAW,IAChBU,KAAKR,cAAgB,aACrBQ,KAAKP,YAAc,GACnBO,KAAKN,MAAQ,EACbM,KAAKJ,WAAY,CACnB,CAMA,iBAAAK,GACEF,MAAME,oBACNC,OAAOC,iBAAiB,QAASH,KAAKI,cACtCC,SAASF,iBAAiB,mBAAoBH,KAAKM,kBACnDN,KAAKI,eACFJ,KAAKV,SAAW,IAAGU,MAAKH,EAASU,YAAYP,KAAKQ,WAAYR,KAAKV,UACxE,CAEA,oBAAAmB,GACEV,MAAMU,uBACNP,OAAOQ,oBAAoB,QAASV,KAAKI,cACzCC,SAASK,oBAAoB,mBAAoBV,KAAKM,kBACtDK,cAAcX,MAAKH,EACrB,CAMAO,aAAeQ,UACb,MAAOC,EAAOC,SAAchC,IAC5B,GAAG+B,EAGD,OAFAb,KAAKJ,UAA2B,MAAfiB,EAAME,UACpBf,KAAKJ,YAAWI,KAAKN,MAAQ,IAGlCM,KAAKJ,WAAY,EACjBI,KAAKN,MAAQoB,EAAKpB,OAOpBc,WAAa,KACPH,SAASW,QAAQhB,KAAKI,gBAG5BE,iBAAmB,KACbD,SAASW,QAAQhB,KAAKI,gBAG5Ba,aAAeC,IACVA,EAAMC,OAAOC,QAAQ,yBAA2BpB,OACnDA,KAAKqB,cAAc,wBAAwBC,UAC3CtB,KAAKI,iBAGPmB,aAAeL,IACblB,KAAKN,MAAQwB,EAAMM,OAAOC,QAG5BC,QAAUd,gBACF7B,UACAiB,KAAKqB,cAAc,wBAAwBC,YAOnD,cAAAK,GACE,OAAG3B,KAAKJ,UAAkBf,EACnBD,CAAI;2DAC4CoB,KAAKR,yBAAyBQ,KAAKiB;mDAC3CjB,KAAKP,2BAA2BO,KAAKN,MAAQ,kBAAkBM,KAAKN,eAAiB;;YAE5HM,KAAKN,MAAQd,CAAI,0DAA0DoB,KAAKN,MAAQ,GAAK,MAAQM,KAAKN,eAAiBb;;qCAElGmB,KAAKuB;;;8CAGIvB,KAAKN,gBAAgBM,KAAK0B;;;YAG5D1B,KAAKd,SAAWN,CAAI,oCAAoCoB,KAAKd,8BAAgCL;;;KAIvG,EAGF+C,eAAeC,OAAO,sBAAuB7C","ignoreList":[]}
@@ -18,4 +18,4 @@ import t from"/kempo-ui/components/LightComponent.js";import{html as i,nothing a
18
18
  <k-pagination class="d-b my" controls="simple" .page=${this.page} .totalItems=${this.total} .itemsPerPage=${this.pageSize} @page-change=${this.handlePageChange}></k-pagination>
19
19
  `:e}
20
20
  `:i`<p class="p tc-muted">${this.unreadOnly?"No unread notifications.":"No notifications."}</p>`}}customElements.define("k-notification-list",p);
21
- //# sourceMappingURL=C:\Users\dusti\dev\kempo-notifications\dist\kempo\components\NotificationList.js.map
21
+ //# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\kempo\components\NotificationList.js.map
@@ -18,4 +18,4 @@ import e from"/kempo-ui/components/LightComponent.js";import{html as t}from"/kem
18
18
  ${this.extra}
19
19
  <p class="mt">Already have an account? <a href="/login">Login</a></p>
20
20
  `}}customElements.define("k-register",a);
21
- //# sourceMappingURL=c:\Users\dusti\dev\kempo\dist\kempo\components\Register.js.map
21
+ //# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\kempo\components\Register.js.map
package/dist/kempo/sdk.js CHANGED
@@ -1,2 +1,2 @@
1
- import{get as e,post as s,put as o,patch as n,del as t}from"./fetch.js";const a="/kempo/api";export const register=async({email:e,password:o,name:n})=>s(`${a}/auth/register/email`,{email:e,password:o,name:n});export const login=async({email:e,password:o})=>s(`${a}/auth/login/email`,{email:e,password:o});export const logout=async()=>s(`${a}/auth/logout`,{});export const getSession=async()=>e(`${a}/auth/session`);export const forgotPassword=async({email:e})=>s(`${a}/forgot-password`,{email:e});export const resetPassword=async({token:e,password:o,logoutAll:n=!1})=>s(`${a}/auth/reset-password`,{token:e,newPassword:o,logoutAll:n});export const changePassword=async({currentPassword:e,newPassword:o,logoutAll:n})=>s(`${a}/auth/change-password`,{currentPassword:e,newPassword:o,logoutAll:n});export const verifyEmail=async({token:e})=>s(`${a}/auth/verify-email`,{token:e});export const currentUserHasPermission=async({permission:s})=>e(`${a}/user/current/permissions`,{permission:s});export const currentUserHasAllPermissions=async({permissions:s})=>e(`${a}/user/current/permissions/all`,{permissions:s});export const currentUserHasSomePermissions=async({permissions:s})=>e(`${a}/user/current/permissions/some`,{permissions:s});export const getAllCurrentUserPermissions=async()=>e(`${a}/user/current/permissions/list`);export const userHasPermission=async({userid:s,permission:o})=>e(`${a}/user/${s}/permissions`,{permission:o});export const userHasAllPermissions=async({userid:s,permissions:o})=>e(`${a}/user/${s}/permissions/all`,{permissions:o});export const userHasSomePermissions=async({userid:s,permissions:o})=>e(`${a}/user/${s}/permissions/some`,{permissions:o});export const getAllUserPermissions=async({userid:s})=>e(`${a}/user/${s}/permissions/list`);export const getUsers=async({limit:s,offset:o}={})=>e(`${a}/user`,{limit:s,offset:o});export const searchUsers=async({q:s,limit:o,offset:n,inGroup:t,notInGroup:r}={})=>e(`${a}/user/search`,{q:s,limit:o,offset:n,inGroup:t,notInGroup:r});export const createUser=async({name:e,email:o,password:n,emailVerified:t})=>s(`${a}/user/create`,{name:e,email:o,password:n,emailVerified:t});export const deleteUsers=async e=>t(`${a}/user`,{ids:e});export const updateUser=async({id:e,name:s,email:o,emailVerified:t,createdAt:r})=>n(`${a}/user`,{id:e,name:s,email:o,emailVerified:t,createdAt:r});export const getUser=async s=>e(`${a}/user/${s}`);export const getUserSessions=async(s,{limit:o,offset:n}={})=>e(`${a}/user/${s}/sessions`,{limit:o,offset:n});export const deleteUserSession=async(e,s)=>t(`${a}/user/${e}/sessions`,{sessionToken:s});export const deleteExpiredUserSessions=async e=>t(`${a}/user/${e}/sessions/expired`);export const getUserGroups=async(s,{limit:o,offset:n}={})=>e(`${a}/user/${s}/groups`,{limit:o,offset:n});export const addUserToGroup=async(e,o)=>s(`${a}/user/${e}/groups`,{groupName:o});export const removeUserFromGroup=async(e,s)=>t(`${a}/user/${e}/groups`,{groupName:s});export const listGroups=async({limit:s,offset:o,owner:n}={})=>e(`${a}/groups`,{limit:s,offset:o,owner:n});export const createGroup=async({name:e,description:o})=>s(`${a}/groups`,{name:e,description:o});export const updateGroup=async({name:e,newName:s,description:o})=>n(`${a}/groups`,{name:e,newName:s,description:o});export const deleteGroups=async e=>t(`${a}/groups`,{names:e});export const getGroup=async s=>e(`${a}/groups/${encodeURIComponent(s)}`);export const getGroupMembers=async(s,{limit:o,offset:n}={})=>e(`${a}/groups/${encodeURIComponent(s)}/members`,{limit:o,offset:n});export const addMemberToGroup=async(e,o)=>s(`${a}/groups/${encodeURIComponent(e)}/members`,{userId:o});export const removeMemberFromGroup=async(e,s)=>t(`${a}/groups/${encodeURIComponent(e)}/members`,{userId:s});export const getGroupPermissions=async s=>e(`${a}/groups/${encodeURIComponent(s)}/permissions`);export const addPermissionToGroup=async(e,o)=>s(`${a}/groups/${encodeURIComponent(e)}/permissions`,{permissionName:o});export const removePermissionFromGroup=async(e,s)=>t(`${a}/groups/${encodeURIComponent(e)}/permissions`,{permissionName:s});export const listPermissions=async({limit:s,offset:o,owner:n}={})=>e(`${a}/permissions`,{limit:s,offset:o,owner:n});export const createPermissions=async e=>s(`${a}/permissions`,{permissions:e});export const updatePermission=async({name:e,description:s})=>n(`${a}/permissions`,{name:e,description:s});export const deletePermissions=async e=>t(`${a}/permissions`,{names:e});export const getSetting=async(s,o)=>e(`${a}/settings/${encodeURIComponent(s)}/${encodeURIComponent(o)}`);export const listSettings=async({owner:s,limit:o,offset:n}={})=>e(`${a}/settings/${encodeURIComponent(s)}`,{limit:o,offset:n});export const setSetting=async(e,o,n)=>s(`${a}/settings/${encodeURIComponent(e)}/${encodeURIComponent(o)}`,n);export const deleteSetting=async(e,s)=>t(`${a}/settings/${encodeURIComponent(e)}/${encodeURIComponent(s)}`);export const listPages=async({owner:s,showHidden:o,offset:n,limit:t}={})=>e(`${a}/pages`,{owner:s,showHidden:o,offset:n,limit:t});export const rescanPages=async()=>s(`${a}/pages/rescan`,{});export const listTemplates=async()=>e(`${a}/templates`);export const listDirectories=async()=>e(`${a}/pages/directories`);export const getPage=async s=>e(`${a}/pages/file`,{file:s});export const createPage=async({directory:e,name:o,template:n})=>s(`${a}/pages`,{directory:e,name:o,template:n});export const updatePage=async({file:e,name:s,title:n,description:t,author:r,template:i,contents:c,extraMetadata:l})=>o(`${a}/pages/file`,{file:e,name:s,title:n,description:t,author:r,template:i,contents:c,extraMetadata:l});export const deletePages=async e=>t(`${a}/pages`,{files:e});export const disablePage=async e=>o(`${a}/pages/disable`,{file:e});export const enablePage=async e=>o(`${a}/pages/enable`,{file:e});export const movePage=async({file:e,newFile:s})=>n(`${a}/pages/file`,{file:e,newFile:s});export const searchPagesByMetadata=async s=>e(`${a}/pages/search`,{query:JSON.stringify(s)});export const setPageLocked=async({file:e,locked:s})=>o(`${a}/pages/lock`,{file:e,locked:s});export const getTemplate=async s=>e(`${a}/templates/file`,{file:s});export const createTemplate=async({directory:e,name:o,copyFrom:n})=>s(`${a}/templates`,{directory:e,name:o,copyFrom:n});export const updateTemplate=async({file:e,name:s,author:n,markup:t})=>o(`${a}/templates/file`,{file:e,name:s,author:n,markup:t});export const deleteTemplates=async e=>t(`${a}/templates`,{files:e});export const disableTemplate=async e=>o(`${a}/templates/disable`,{file:e});export const enableTemplate=async e=>o(`${a}/templates/enable`,{file:e});export const moveTemplate=async({file:e,newFile:s})=>n(`${a}/templates/file`,{file:e,newFile:s});export const setTemplateLocked=async({file:e,locked:s})=>o(`${a}/templates/lock`,{file:e,locked:s});export const listFragments=async()=>e(`${a}/fragments`);export const getFragment=async s=>e(`${a}/fragments/file`,{file:s});export const createFragment=async({directory:e,name:o})=>s(`${a}/fragments`,{directory:e,name:o});export const updateFragment=async({file:e,author:s,markup:n})=>o(`${a}/fragments/file`,{file:e,author:s,markup:n});export const deleteFragments=async e=>t(`${a}/fragments`,{files:e});export const moveFragment=async({file:e,newFile:s})=>n(`${a}/fragments/file`,{file:e,newFile:s});export const disableFragment=async e=>o(`${a}/fragments/disable`,{file:e});export const enableFragment=async e=>o(`${a}/fragments/enable`,{file:e});export const setFragmentLocked=async({file:e,locked:s})=>o(`${a}/fragments/lock`,{file:e,locked:s});export const listGlobalContent=async()=>e(`${a}/globals`);export const getGlobalContent=async s=>e(`${a}/globals/entry`,{id:s});export const createGlobalContent=async({name:e,location:o,priority:n})=>s(`${a}/globals`,{name:e,location:o,priority:n});export const updateGlobalContent=async({id:e,name:s,location:n,priority:t,markup:r})=>o(`${a}/globals/entry`,{id:e,name:s,location:n,priority:t,markup:r});export const deleteGlobalContent=async e=>t(`${a}/globals`,{ids:e});export const disableGlobalContent=async e=>o(`${a}/globals/disable`,{id:e});export const enableGlobalContent=async e=>o(`${a}/globals/enable`,{id:e});export const setGlobalContentLocked=async({id:e,locked:s})=>o(`${a}/globals/lock`,{id:e,locked:s});export const listExtensions=async({limit:s,offset:o}={})=>e(`${a}/extensions`,{limit:s,offset:o});export const listAvailableExtensions=async()=>e(`${a}/extensions/available`);export const listKnownExtensions=async()=>e(`${a}/extensions/known`);export const getNotifications=async({unreadOnly:s=!1,limit:o,offset:n}={})=>e(`${a}/notifications`,{unreadOnly:s,limit:o,offset:n});export const getUnreadNotificationCount=async()=>e(`${a}/notifications/count`);export const markNotificationRead=async e=>s(`${a}/notifications/${encodeURIComponent(e)}/read`,{});export const markNotificationHandled=async e=>s(`${a}/notifications/${encodeURIComponent(e)}/handled`,{});export const markAllNotificationsRead=async()=>s(`${a}/notifications/read-all`,{});export const dismissNotification=async e=>t(`${a}/notifications/${encodeURIComponent(e)}`);export const listRealtimeConnections=async()=>e(`${a}/realtime/connections`);export const installExtension=async e=>s(`${a}/extensions`,{name:e});export const uninstallExtension=async(e,s=!1)=>t(`${a}/extensions`,{name:e,purgeData:s});export const enableExtension=async e=>s(`${a}/extensions/${encodeURIComponent(e)}/enable`,{});export const disableExtension=async e=>s(`${a}/extensions/${encodeURIComponent(e)}/disable`,{});export const listAdminGlobalContent=async()=>e(`${a}/admin-globals`);export const getAdminGlobalContent=async s=>e(`${a}/admin-globals/${encodeURIComponent(s)}`);export const createAdminGlobalContent=async({name:e,location:o,priority:n,owner:t,markup:r})=>s(`${a}/admin-globals`,{name:e,location:o,priority:n,owner:t,markup:r});export const updateAdminGlobalContent=async(e,{name:s,location:n,priority:t,markup:r})=>o(`${a}/admin-globals/${encodeURIComponent(e)}`,{name:s,location:n,priority:t,markup:r});export const deleteAdminGlobalContent=async e=>t(`${a}/admin-globals`,{ids:e});export const enableAdminGlobalContent=async e=>o(`${a}/admin-globals/${encodeURIComponent(e)}/enable`,{});export const disableAdminGlobalContent=async e=>o(`${a}/admin-globals/${encodeURIComponent(e)}/disable`,{});
2
- //# sourceMappingURL=C:\Users\dusti\dev\kempo-notifications\dist\kempo\sdk.js.map
1
+ import{get as e,post as s,put as o,patch as t,del as n}from"./fetch.js";const a="/kempo/api";export const register=async({email:e,password:o,name:t})=>s(`${a}/auth/register/email`,{email:e,password:o,name:t});export const login=async({email:e,password:o})=>s(`${a}/auth/login/email`,{email:e,password:o});export const logout=async()=>s(`${a}/auth/logout`,{});export const getSession=async()=>e(`${a}/auth/session`);export const forgotPassword=async({email:e})=>s(`${a}/forgot-password`,{email:e});export const resetPassword=async({token:e,password:o,logoutAll:t=!1})=>s(`${a}/auth/reset-password`,{token:e,newPassword:o,logoutAll:t});export const changePassword=async({currentPassword:e,newPassword:o,logoutAll:t})=>s(`${a}/auth/change-password`,{currentPassword:e,newPassword:o,logoutAll:t});export const verifyEmail=async({token:e})=>s(`${a}/auth/verify-email`,{token:e});export const currentUserHasPermission=async({permission:s})=>e(`${a}/user/current/permissions`,{permission:s});export const currentUserHasAllPermissions=async({permissions:s})=>e(`${a}/user/current/permissions/all`,{permissions:s});export const currentUserHasSomePermissions=async({permissions:s})=>e(`${a}/user/current/permissions/some`,{permissions:s});export const getAllCurrentUserPermissions=async()=>e(`${a}/user/current/permissions/list`);export const userHasPermission=async({userid:s,permission:o})=>e(`${a}/user/${s}/permissions`,{permission:o});export const userHasAllPermissions=async({userid:s,permissions:o})=>e(`${a}/user/${s}/permissions/all`,{permissions:o});export const userHasSomePermissions=async({userid:s,permissions:o})=>e(`${a}/user/${s}/permissions/some`,{permissions:o});export const getAllUserPermissions=async({userid:s})=>e(`${a}/user/${s}/permissions/list`);export const getUsers=async({limit:s,offset:o}={})=>e(`${a}/user`,{limit:s,offset:o});export const searchUsers=async({q:s,limit:o,offset:t,inGroup:n,notInGroup:r}={})=>e(`${a}/user/search`,{q:s,limit:o,offset:t,inGroup:n,notInGroup:r});export const createUser=async({name:e,email:o,password:t,emailVerified:n})=>s(`${a}/user/create`,{name:e,email:o,password:t,emailVerified:n});export const deleteUsers=async e=>n(`${a}/user`,{ids:e});export const updateUser=async({id:e,name:s,email:o,emailVerified:n,createdAt:r})=>t(`${a}/user`,{id:e,name:s,email:o,emailVerified:n,createdAt:r});export const getUser=async s=>e(`${a}/user/${s}`);export const getUserSessions=async(s,{limit:o,offset:t}={})=>e(`${a}/user/${s}/sessions`,{limit:o,offset:t});export const deleteUserSession=async(e,s)=>n(`${a}/user/${e}/sessions`,{sessionToken:s});export const deleteExpiredUserSessions=async e=>n(`${a}/user/${e}/sessions/expired`);export const getUserGroups=async(s,{limit:o,offset:t}={})=>e(`${a}/user/${s}/groups`,{limit:o,offset:t});export const addUserToGroup=async(e,o)=>s(`${a}/user/${e}/groups`,{groupName:o});export const removeUserFromGroup=async(e,s)=>n(`${a}/user/${e}/groups`,{groupName:s});export const listGroups=async({limit:s,offset:o,owner:t}={})=>e(`${a}/groups`,{limit:s,offset:o,owner:t});export const createGroup=async({name:e,description:o})=>s(`${a}/groups`,{name:e,description:o});export const updateGroup=async({name:e,newName:s,description:o})=>t(`${a}/groups`,{name:e,newName:s,description:o});export const deleteGroups=async e=>n(`${a}/groups`,{names:e});export const getGroup=async s=>e(`${a}/groups/${encodeURIComponent(s)}`);export const getGroupMembers=async(s,{limit:o,offset:t}={})=>e(`${a}/groups/${encodeURIComponent(s)}/members`,{limit:o,offset:t});export const addMemberToGroup=async(e,o)=>s(`${a}/groups/${encodeURIComponent(e)}/members`,{userId:o});export const removeMemberFromGroup=async(e,s)=>n(`${a}/groups/${encodeURIComponent(e)}/members`,{userId:s});export const getGroupPermissions=async s=>e(`${a}/groups/${encodeURIComponent(s)}/permissions`);export const addPermissionToGroup=async(e,o)=>s(`${a}/groups/${encodeURIComponent(e)}/permissions`,{permissionName:o});export const removePermissionFromGroup=async(e,s)=>n(`${a}/groups/${encodeURIComponent(e)}/permissions`,{permissionName:s});export const listPermissions=async({limit:s,offset:o,owner:t}={})=>e(`${a}/permissions`,{limit:s,offset:o,owner:t});export const createPermissions=async e=>s(`${a}/permissions`,{permissions:e});export const updatePermission=async({name:e,description:s})=>t(`${a}/permissions`,{name:e,description:s});export const deletePermissions=async e=>n(`${a}/permissions`,{names:e});export const getSetting=async(s,o)=>e(`${a}/settings/${encodeURIComponent(s)}/${encodeURIComponent(o)}`);export const listSettings=async({owner:s,limit:o,offset:t}={})=>e(`${a}/settings/${encodeURIComponent(s)}`,{limit:o,offset:t});export const setSetting=async(e,o,t)=>s(`${a}/settings/${encodeURIComponent(e)}/${encodeURIComponent(o)}`,t);export const deleteSetting=async(e,s)=>n(`${a}/settings/${encodeURIComponent(e)}/${encodeURIComponent(s)}`);export const listPages=async({owner:s,showHidden:o,offset:t,limit:n}={})=>e(`${a}/pages`,{owner:s,showHidden:o,offset:t,limit:n});export const rescanPages=async()=>s(`${a}/pages/rescan`,{});export const listTemplates=async()=>e(`${a}/templates`);export const listDirectories=async()=>e(`${a}/pages/directories`);export const getPage=async s=>e(`${a}/pages/file`,{file:s});export const createPage=async({directory:e,name:o,template:t})=>s(`${a}/pages`,{directory:e,name:o,template:t});export const updatePage=async({file:e,name:s,title:t,description:n,author:r,template:i,contents:c,extraMetadata:l})=>o(`${a}/pages/file`,{file:e,name:s,title:t,description:n,author:r,template:i,contents:c,extraMetadata:l});export const deletePages=async e=>n(`${a}/pages`,{files:e});export const disablePage=async e=>o(`${a}/pages/disable`,{file:e});export const enablePage=async e=>o(`${a}/pages/enable`,{file:e});export const movePage=async({file:e,newFile:s})=>t(`${a}/pages/file`,{file:e,newFile:s});export const searchPagesByMetadata=async s=>e(`${a}/pages/search`,{query:JSON.stringify(s)});export const setPageLocked=async({file:e,locked:s})=>o(`${a}/pages/lock`,{file:e,locked:s});export const getTemplate=async s=>e(`${a}/templates/file`,{file:s});export const createTemplate=async({directory:e,name:o,copyFrom:t})=>s(`${a}/templates`,{directory:e,name:o,copyFrom:t});export const updateTemplate=async({file:e,name:s,author:t,markup:n})=>o(`${a}/templates/file`,{file:e,name:s,author:t,markup:n});export const deleteTemplates=async e=>n(`${a}/templates`,{files:e});export const disableTemplate=async e=>o(`${a}/templates/disable`,{file:e});export const enableTemplate=async e=>o(`${a}/templates/enable`,{file:e});export const moveTemplate=async({file:e,newFile:s})=>t(`${a}/templates/file`,{file:e,newFile:s});export const setTemplateLocked=async({file:e,locked:s})=>o(`${a}/templates/lock`,{file:e,locked:s});export const listFragments=async()=>e(`${a}/fragments`);export const getFragment=async s=>e(`${a}/fragments/file`,{file:s});export const createFragment=async({directory:e,name:o})=>s(`${a}/fragments`,{directory:e,name:o});export const updateFragment=async({file:e,author:s,markup:t})=>o(`${a}/fragments/file`,{file:e,author:s,markup:t});export const deleteFragments=async e=>n(`${a}/fragments`,{files:e});export const moveFragment=async({file:e,newFile:s})=>t(`${a}/fragments/file`,{file:e,newFile:s});export const disableFragment=async e=>o(`${a}/fragments/disable`,{file:e});export const enableFragment=async e=>o(`${a}/fragments/enable`,{file:e});export const setFragmentLocked=async({file:e,locked:s})=>o(`${a}/fragments/lock`,{file:e,locked:s});export const listGlobalContent=async()=>e(`${a}/globals`);export const getGlobalContent=async s=>e(`${a}/globals/entry`,{id:s});export const createGlobalContent=async({name:e,location:o,priority:t})=>s(`${a}/globals`,{name:e,location:o,priority:t});export const updateGlobalContent=async({id:e,name:s,location:t,priority:n,markup:r})=>o(`${a}/globals/entry`,{id:e,name:s,location:t,priority:n,markup:r});export const deleteGlobalContent=async e=>n(`${a}/globals`,{ids:e});export const disableGlobalContent=async e=>o(`${a}/globals/disable`,{id:e});export const enableGlobalContent=async e=>o(`${a}/globals/enable`,{id:e});export const setGlobalContentLocked=async({id:e,locked:s})=>o(`${a}/globals/lock`,{id:e,locked:s});export const listExtensions=async({limit:s,offset:o}={})=>e(`${a}/extensions`,{limit:s,offset:o});export const listAvailableExtensions=async()=>e(`${a}/extensions/available`);export const listKnownExtensions=async()=>e(`${a}/extensions/known`);export const getDashboardWidgets=async()=>e(`${a}/dashboard/widgets`);export const getNotifications=async({unreadOnly:s=!1,limit:o,offset:t}={})=>e(`${a}/notifications`,{unreadOnly:s,limit:o,offset:t});export const getUnreadNotificationCount=async()=>e(`${a}/notifications/count`);export const markNotificationRead=async e=>s(`${a}/notifications/${encodeURIComponent(e)}/read`,{});export const markNotificationHandled=async e=>s(`${a}/notifications/${encodeURIComponent(e)}/handled`,{});export const markAllNotificationsRead=async()=>s(`${a}/notifications/read-all`,{});export const dismissNotification=async e=>n(`${a}/notifications/${encodeURIComponent(e)}`);export const listRealtimeConnections=async()=>e(`${a}/realtime/connections`);export const installExtension=async e=>s(`${a}/extensions`,{name:e});export const uninstallExtension=async(e,s=!1)=>n(`${a}/extensions`,{name:e,purgeData:s});export const enableExtension=async e=>s(`${a}/extensions/${encodeURIComponent(e)}/enable`,{});export const disableExtension=async e=>s(`${a}/extensions/${encodeURIComponent(e)}/disable`,{});export const listAdminGlobalContent=async()=>e(`${a}/admin-globals`);export const getAdminGlobalContent=async s=>e(`${a}/admin-globals/${encodeURIComponent(s)}`);export const createAdminGlobalContent=async({name:e,location:o,priority:t,owner:n,markup:r})=>s(`${a}/admin-globals`,{name:e,location:o,priority:t,owner:n,markup:r});export const updateAdminGlobalContent=async(e,{name:s,location:t,priority:n,markup:r})=>o(`${a}/admin-globals/${encodeURIComponent(e)}`,{name:s,location:t,priority:n,markup:r});export const deleteAdminGlobalContent=async e=>n(`${a}/admin-globals`,{ids:e});export const enableAdminGlobalContent=async e=>o(`${a}/admin-globals/${encodeURIComponent(e)}/enable`,{});export const disableAdminGlobalContent=async e=>o(`${a}/admin-globals/${encodeURIComponent(e)}/disable`,{});
2
+ //# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\kempo\sdk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"src\\kempo\\sdk.js","names":["get","post","put","patch","del","API_BASE","register","async","email","password","name","login","logout","getSession","forgotPassword","resetPassword","token","logoutAll","newPassword","changePassword","currentPassword","verifyEmail","currentUserHasPermission","permission","currentUserHasAllPermissions","permissions","currentUserHasSomePermissions","getAllCurrentUserPermissions","userHasPermission","userid","userHasAllPermissions","userHasSomePermissions","getAllUserPermissions","getUsers","limit","offset","searchUsers","q","inGroup","notInGroup","createUser","emailVerified","deleteUsers","ids","updateUser","id","createdAt","getUser","getUserSessions","deleteUserSession","sessionToken","deleteExpiredUserSessions","getUserGroups","addUserToGroup","groupName","removeUserFromGroup","listGroups","owner","createGroup","description","updateGroup","newName","deleteGroups","names","getGroup","encodeURIComponent","getGroupMembers","addMemberToGroup","userId","removeMemberFromGroup","getGroupPermissions","addPermissionToGroup","permissionName","removePermissionFromGroup","listPermissions","createPermissions","updatePermission","deletePermissions","getSetting","listSettings","setSetting","data","deleteSetting","listPages","showHidden","rescanPages","listTemplates","listDirectories","getPage","file","createPage","directory","template","updatePage","title","author","contents","extraMetadata","deletePages","files","disablePage","enablePage","movePage","newFile","searchPagesByMetadata","query","JSON","stringify","setPageLocked","locked","getTemplate","createTemplate","copyFrom","updateTemplate","markup","deleteTemplates","disableTemplate","enableTemplate","moveTemplate","setTemplateLocked","listFragments","getFragment","createFragment","updateFragment","deleteFragments","moveFragment","disableFragment","enableFragment","setFragmentLocked","listGlobalContent","getGlobalContent","createGlobalContent","location","priority","updateGlobalContent","deleteGlobalContent","disableGlobalContent","enableGlobalContent","setGlobalContentLocked","listExtensions","listAvailableExtensions","listKnownExtensions","getNotifications","unreadOnly","getUnreadNotificationCount","markNotificationRead","markNotificationHandled","markAllNotificationsRead","dismissNotification","listRealtimeConnections","installExtension","uninstallExtension","purgeData","enableExtension","disableExtension","listAdminGlobalContent","getAdminGlobalContent","createAdminGlobalContent","updateAdminGlobalContent","deleteAdminGlobalContent","enableAdminGlobalContent","disableAdminGlobalContent"],"sources":["0"],"sourcesContent":["import { get, post, put, patch, del } from './fetch.js';\nconst API_BASE = '/kempo/api';\n\nexport const register = async ({ email, password, name }) =>\n post(`${API_BASE}/auth/register/email`, { email, password, name });\n\nexport const login = async ({ email, password }) =>\n post(`${API_BASE}/auth/login/email`, { email, password });\n\nexport const logout = async () => post(`${API_BASE}/auth/logout`, {});\n\nexport const getSession = async () => get(`${API_BASE}/auth/session`);\n\nexport const forgotPassword = async ({ email }) =>\n post(`${API_BASE}/forgot-password`, { email });\n\nexport const resetPassword = async ({ token, password, logoutAll = false }) =>\n post(`${API_BASE}/auth/reset-password`, { token, newPassword: password, logoutAll });\n \nexport const changePassword = async ({ currentPassword, newPassword, logoutAll }) => \n post(`${API_BASE}/auth/change-password`, { currentPassword, newPassword, logoutAll });\n\nexport const verifyEmail = async ({ token }) =>\n post(`${API_BASE}/auth/verify-email`, { token });\n\nexport const currentUserHasPermission = async ({ permission }) =>\n get(`${API_BASE}/user/current/permissions`, { permission });\n\nexport const currentUserHasAllPermissions = async ({ permissions }) =>\n get(`${API_BASE}/user/current/permissions/all`, { permissions });\n\nexport const currentUserHasSomePermissions = async ({ permissions }) =>\n get(`${API_BASE}/user/current/permissions/some`, { permissions });\n\nexport const getAllCurrentUserPermissions = async () =>\n get(`${API_BASE}/user/current/permissions/list`);\n\nexport const userHasPermission = async ({ userid, permission }) =>\n get(`${API_BASE}/user/${userid}/permissions`, { permission });\n\nexport const userHasAllPermissions = async ({ userid, permissions }) =>\n get(`${API_BASE}/user/${userid}/permissions/all`, { permissions });\n\nexport const userHasSomePermissions = async ({ userid, permissions }) =>\n get(`${API_BASE}/user/${userid}/permissions/some`, { permissions });\n\nexport const getAllUserPermissions = async ({ userid }) =>\n get(`${API_BASE}/user/${userid}/permissions/list`);\n\nexport const getUsers = async ({ limit, offset } = {}) =>\n get(`${API_BASE}/user`, { limit, offset });\n\nexport const searchUsers = async ({ q, limit, offset, inGroup, notInGroup } = {}) =>\n get(`${API_BASE}/user/search`, { q, limit, offset, inGroup, notInGroup });\n\nexport const createUser = async ({ name, email, password, emailVerified }) =>\n post(`${API_BASE}/user/create`, { name, email, password, emailVerified });\n\nexport const deleteUsers = async (ids) =>\n del(`${API_BASE}/user`, { ids });\n\nexport const updateUser = async ({ id, name, email, emailVerified, createdAt }) =>\n patch(`${API_BASE}/user`, { id, name, email, emailVerified, createdAt });\n\nexport const getUser = async (userid) =>\n get(`${API_BASE}/user/${userid}`);\n\nexport const getUserSessions = async (userid, { limit, offset } = {}) =>\n get(`${API_BASE}/user/${userid}/sessions`, { limit, offset });\n\nexport const deleteUserSession = async (userid, sessionToken) =>\n del(`${API_BASE}/user/${userid}/sessions`, { sessionToken });\n\nexport const deleteExpiredUserSessions = async (userid) =>\n del(`${API_BASE}/user/${userid}/sessions/expired`);\n\nexport const getUserGroups = async (userid, { limit, offset } = {}) =>\n get(`${API_BASE}/user/${userid}/groups`, { limit, offset });\n\nexport const addUserToGroup = async (userid, groupName) =>\n post(`${API_BASE}/user/${userid}/groups`, { groupName });\n\nexport const removeUserFromGroup = async (userid, groupName) =>\n del(`${API_BASE}/user/${userid}/groups`, { groupName });\n\nexport const listGroups = async ({ limit, offset, owner } = {}) =>\n get(`${API_BASE}/groups`, { limit, offset, owner });\n\nexport const createGroup = async ({ name, description }) =>\n post(`${API_BASE}/groups`, { name, description });\n\nexport const updateGroup = async ({ name, newName, description }) =>\n patch(`${API_BASE}/groups`, { name, newName, description });\n\nexport const deleteGroups = async (names) =>\n del(`${API_BASE}/groups`, { names });\n\nexport const getGroup = async (name) =>\n get(`${API_BASE}/groups/${encodeURIComponent(name)}`);\n\nexport const getGroupMembers = async (name, { limit, offset } = {}) =>\n get(`${API_BASE}/groups/${encodeURIComponent(name)}/members`, { limit, offset });\n\nexport const addMemberToGroup = async (name, userId) =>\n post(`${API_BASE}/groups/${encodeURIComponent(name)}/members`, { userId });\n\nexport const removeMemberFromGroup = async (name, userId) =>\n del(`${API_BASE}/groups/${encodeURIComponent(name)}/members`, { userId });\n\nexport const getGroupPermissions = async (name) =>\n get(`${API_BASE}/groups/${encodeURIComponent(name)}/permissions`);\n\nexport const addPermissionToGroup = async (name, permissionName) =>\n post(`${API_BASE}/groups/${encodeURIComponent(name)}/permissions`, { permissionName });\n\nexport const removePermissionFromGroup = async (name, permissionName) =>\n del(`${API_BASE}/groups/${encodeURIComponent(name)}/permissions`, { permissionName });\n\nexport const listPermissions = async ({ limit, offset, owner } = {}) =>\n get(`${API_BASE}/permissions`, { limit, offset, owner });\n\nexport const createPermissions = async (permissions) =>\n post(`${API_BASE}/permissions`, { permissions });\n\nexport const updatePermission = async ({ name, description }) =>\n patch(`${API_BASE}/permissions`, { name, description });\n\nexport const deletePermissions = async (names) =>\n del(`${API_BASE}/permissions`, { names });\n\nexport const getSetting = async (owner, name) =>\n get(`${API_BASE}/settings/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`);\n\nexport const listSettings = async ({ owner, limit, offset } = {}) =>\n get(`${API_BASE}/settings/${encodeURIComponent(owner)}`, { limit, offset });\n\nexport const setSetting = async (owner, name, data) =>\n post(`${API_BASE}/settings/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`, data);\n\nexport const deleteSetting = async (owner, name) =>\n del(`${API_BASE}/settings/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`);\n\n/*\n Pages\n*/\n\nexport const listPages = async ({ owner, showHidden, offset, limit } = {}) =>\n get(`${API_BASE}/pages`, { owner, showHidden, offset, limit });\n\nexport const rescanPages = async () =>\n post(`${API_BASE}/pages/rescan`, {});\n\nexport const listTemplates = async () =>\n get(`${API_BASE}/templates`);\n\nexport const listDirectories = async () =>\n get(`${API_BASE}/pages/directories`);\n\nexport const getPage = async (file) =>\n get(`${API_BASE}/pages/file`, { file });\n\nexport const createPage = async ({ directory, name, template }) =>\n post(`${API_BASE}/pages`, { directory, name, template });\n\nexport const updatePage = async ({ file, name, title, description, author, template, contents, extraMetadata }) =>\n put(`${API_BASE}/pages/file`, { file, name, title, description, author, template, contents, extraMetadata });\n\nexport const deletePages = async (files) =>\n del(`${API_BASE}/pages`, { files });\n\nexport const disablePage = async (file) =>\n put(`${API_BASE}/pages/disable`, { file });\n\nexport const enablePage = async (file) =>\n put(`${API_BASE}/pages/enable`, { file });\n\nexport const movePage = async ({ file, newFile }) =>\n patch(`${API_BASE}/pages/file`, { file, newFile });\n\nexport const searchPagesByMetadata = async (query) =>\n get(`${API_BASE}/pages/search`, { query: JSON.stringify(query) });\n\nexport const setPageLocked = async ({ file, locked }) =>\n put(`${API_BASE}/pages/lock`, { file, locked });\n\n/*\n Templates\n*/\n\nexport const getTemplate = async (file) =>\n get(`${API_BASE}/templates/file`, { file });\n\nexport const createTemplate = async ({ directory, name, copyFrom }) =>\n post(`${API_BASE}/templates`, { directory, name, copyFrom });\n\nexport const updateTemplate = async ({ file, name, author, markup }) =>\n put(`${API_BASE}/templates/file`, { file, name, author, markup });\n\nexport const deleteTemplates = async (files) =>\n del(`${API_BASE}/templates`, { files });\n\nexport const disableTemplate = async (file) =>\n put(`${API_BASE}/templates/disable`, { file });\n\nexport const enableTemplate = async (file) =>\n put(`${API_BASE}/templates/enable`, { file });\n\nexport const moveTemplate = async ({ file, newFile }) =>\n patch(`${API_BASE}/templates/file`, { file, newFile });\n\nexport const setTemplateLocked = async ({ file, locked }) =>\n put(`${API_BASE}/templates/lock`, { file, locked });\n\n/*\n Fragments\n*/\n\nexport const listFragments = async () =>\n get(`${API_BASE}/fragments`);\n\nexport const getFragment = async (file) =>\n get(`${API_BASE}/fragments/file`, { file });\n\nexport const createFragment = async ({ directory, name }) =>\n post(`${API_BASE}/fragments`, { directory, name });\n\nexport const updateFragment = async ({ file, author, markup }) =>\n put(`${API_BASE}/fragments/file`, { file, author, markup });\n\nexport const deleteFragments = async (files) =>\n del(`${API_BASE}/fragments`, { files });\n\nexport const moveFragment = async ({ file, newFile }) =>\n patch(`${API_BASE}/fragments/file`, { file, newFile });\n\nexport const disableFragment = async (file) =>\n put(`${API_BASE}/fragments/disable`, { file });\n\nexport const enableFragment = async (file) =>\n put(`${API_BASE}/fragments/enable`, { file });\n\nexport const setFragmentLocked = async ({ file, locked }) =>\n put(`${API_BASE}/fragments/lock`, { file, locked });\n\n/*\n Global Content\n*/\n\nexport const listGlobalContent = async () =>\n get(`${API_BASE}/globals`);\n\nexport const getGlobalContent = async (id) =>\n get(`${API_BASE}/globals/entry`, { id });\n\nexport const createGlobalContent = async ({ name, location, priority }) =>\n post(`${API_BASE}/globals`, { name, location, priority });\n\nexport const updateGlobalContent = async ({ id, name, location, priority, markup }) =>\n put(`${API_BASE}/globals/entry`, { id, name, location, priority, markup });\n\nexport const deleteGlobalContent = async (ids) =>\n del(`${API_BASE}/globals`, { ids });\n\nexport const disableGlobalContent = async (id) =>\n put(`${API_BASE}/globals/disable`, { id });\n\nexport const enableGlobalContent = async (id) =>\n put(`${API_BASE}/globals/enable`, { id });\n\nexport const setGlobalContentLocked = async ({ id, locked }) =>\n put(`${API_BASE}/globals/lock`, { id, locked });\n\n/*\n Extensions\n*/\n\nexport const listExtensions = async ({ limit, offset } = {}) =>\n get(`${API_BASE}/extensions`, { limit, offset });\n\nexport const listAvailableExtensions = async () =>\n get(`${API_BASE}/extensions/available`);\n\nexport const listKnownExtensions = async () =>\n get(`${API_BASE}/extensions/known`);\n\nexport const getNotifications = async ({ unreadOnly = false, limit, offset } = {}) =>\n get(`${API_BASE}/notifications`, { unreadOnly, limit, offset });\n\nexport const getUnreadNotificationCount = async () =>\n get(`${API_BASE}/notifications/count`);\n\nexport const markNotificationRead = async (id) =>\n post(`${API_BASE}/notifications/${encodeURIComponent(id)}/read`, {});\n\nexport const markNotificationHandled = async (id) =>\n post(`${API_BASE}/notifications/${encodeURIComponent(id)}/handled`, {});\n\nexport const markAllNotificationsRead = async () =>\n post(`${API_BASE}/notifications/read-all`, {});\n\nexport const dismissNotification = async (id) =>\n del(`${API_BASE}/notifications/${encodeURIComponent(id)}`);\n\nexport const listRealtimeConnections = async () =>\n get(`${API_BASE}/realtime/connections`);\n\nexport const installExtension = async (name) =>\n post(`${API_BASE}/extensions`, { name });\n\nexport const uninstallExtension = async (name, purgeData = false) =>\n del(`${API_BASE}/extensions`, { name, purgeData });\n\nexport const enableExtension = async (name) =>\n post(`${API_BASE}/extensions/${encodeURIComponent(name)}/enable`, {});\n\nexport const disableExtension = async (name) =>\n post(`${API_BASE}/extensions/${encodeURIComponent(name)}/disable`, {});\n\n/*\n Admin Global Content\n*/\n\nexport const listAdminGlobalContent = async () =>\n get(`${API_BASE}/admin-globals`);\n\nexport const getAdminGlobalContent = async (id) =>\n get(`${API_BASE}/admin-globals/${encodeURIComponent(id)}`);\n\nexport const createAdminGlobalContent = async ({ name, location, priority, owner, markup }) =>\n post(`${API_BASE}/admin-globals`, { name, location, priority, owner, markup });\n\nexport const updateAdminGlobalContent = async (id, { name, location, priority, markup }) =>\n put(`${API_BASE}/admin-globals/${encodeURIComponent(id)}`, { name, location, priority, markup });\n\nexport const deleteAdminGlobalContent = async (ids) =>\n del(`${API_BASE}/admin-globals`, { ids });\n\nexport const enableAdminGlobalContent = async (id) =>\n put(`${API_BASE}/admin-globals/${encodeURIComponent(id)}/enable`, {});\n\nexport const disableAdminGlobalContent = async (id) =>\n put(`${API_BASE}/admin-globals/${encodeURIComponent(id)}/disable`, {});\n\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"src\\kempo\\sdk.js","names":["get","post","put","patch","del","API_BASE","register","async","email","password","name","login","logout","getSession","forgotPassword","resetPassword","token","logoutAll","newPassword","changePassword","currentPassword","verifyEmail","currentUserHasPermission","permission","currentUserHasAllPermissions","permissions","currentUserHasSomePermissions","getAllCurrentUserPermissions","userHasPermission","userid","userHasAllPermissions","userHasSomePermissions","getAllUserPermissions","getUsers","limit","offset","searchUsers","q","inGroup","notInGroup","createUser","emailVerified","deleteUsers","ids","updateUser","id","createdAt","getUser","getUserSessions","deleteUserSession","sessionToken","deleteExpiredUserSessions","getUserGroups","addUserToGroup","groupName","removeUserFromGroup","listGroups","owner","createGroup","description","updateGroup","newName","deleteGroups","names","getGroup","encodeURIComponent","getGroupMembers","addMemberToGroup","userId","removeMemberFromGroup","getGroupPermissions","addPermissionToGroup","permissionName","removePermissionFromGroup","listPermissions","createPermissions","updatePermission","deletePermissions","getSetting","listSettings","setSetting","data","deleteSetting","listPages","showHidden","rescanPages","listTemplates","listDirectories","getPage","file","createPage","directory","template","updatePage","title","author","contents","extraMetadata","deletePages","files","disablePage","enablePage","movePage","newFile","searchPagesByMetadata","query","JSON","stringify","setPageLocked","locked","getTemplate","createTemplate","copyFrom","updateTemplate","markup","deleteTemplates","disableTemplate","enableTemplate","moveTemplate","setTemplateLocked","listFragments","getFragment","createFragment","updateFragment","deleteFragments","moveFragment","disableFragment","enableFragment","setFragmentLocked","listGlobalContent","getGlobalContent","createGlobalContent","location","priority","updateGlobalContent","deleteGlobalContent","disableGlobalContent","enableGlobalContent","setGlobalContentLocked","listExtensions","listAvailableExtensions","listKnownExtensions","getDashboardWidgets","getNotifications","unreadOnly","getUnreadNotificationCount","markNotificationRead","markNotificationHandled","markAllNotificationsRead","dismissNotification","listRealtimeConnections","installExtension","uninstallExtension","purgeData","enableExtension","disableExtension","listAdminGlobalContent","getAdminGlobalContent","createAdminGlobalContent","updateAdminGlobalContent","deleteAdminGlobalContent","enableAdminGlobalContent","disableAdminGlobalContent"],"sources":["0"],"sourcesContent":["import { get, post, put, patch, del } from './fetch.js';\nconst API_BASE = '/kempo/api';\n\nexport const register = async ({ email, password, name }) =>\n post(`${API_BASE}/auth/register/email`, { email, password, name });\n\nexport const login = async ({ email, password }) =>\n post(`${API_BASE}/auth/login/email`, { email, password });\n\nexport const logout = async () => post(`${API_BASE}/auth/logout`, {});\n\nexport const getSession = async () => get(`${API_BASE}/auth/session`);\n\nexport const forgotPassword = async ({ email }) =>\n post(`${API_BASE}/forgot-password`, { email });\n\nexport const resetPassword = async ({ token, password, logoutAll = false }) =>\n post(`${API_BASE}/auth/reset-password`, { token, newPassword: password, logoutAll });\n \nexport const changePassword = async ({ currentPassword, newPassword, logoutAll }) => \n post(`${API_BASE}/auth/change-password`, { currentPassword, newPassword, logoutAll });\n\nexport const verifyEmail = async ({ token }) =>\n post(`${API_BASE}/auth/verify-email`, { token });\n\nexport const currentUserHasPermission = async ({ permission }) =>\n get(`${API_BASE}/user/current/permissions`, { permission });\n\nexport const currentUserHasAllPermissions = async ({ permissions }) =>\n get(`${API_BASE}/user/current/permissions/all`, { permissions });\n\nexport const currentUserHasSomePermissions = async ({ permissions }) =>\n get(`${API_BASE}/user/current/permissions/some`, { permissions });\n\nexport const getAllCurrentUserPermissions = async () =>\n get(`${API_BASE}/user/current/permissions/list`);\n\nexport const userHasPermission = async ({ userid, permission }) =>\n get(`${API_BASE}/user/${userid}/permissions`, { permission });\n\nexport const userHasAllPermissions = async ({ userid, permissions }) =>\n get(`${API_BASE}/user/${userid}/permissions/all`, { permissions });\n\nexport const userHasSomePermissions = async ({ userid, permissions }) =>\n get(`${API_BASE}/user/${userid}/permissions/some`, { permissions });\n\nexport const getAllUserPermissions = async ({ userid }) =>\n get(`${API_BASE}/user/${userid}/permissions/list`);\n\nexport const getUsers = async ({ limit, offset } = {}) =>\n get(`${API_BASE}/user`, { limit, offset });\n\nexport const searchUsers = async ({ q, limit, offset, inGroup, notInGroup } = {}) =>\n get(`${API_BASE}/user/search`, { q, limit, offset, inGroup, notInGroup });\n\nexport const createUser = async ({ name, email, password, emailVerified }) =>\n post(`${API_BASE}/user/create`, { name, email, password, emailVerified });\n\nexport const deleteUsers = async (ids) =>\n del(`${API_BASE}/user`, { ids });\n\nexport const updateUser = async ({ id, name, email, emailVerified, createdAt }) =>\n patch(`${API_BASE}/user`, { id, name, email, emailVerified, createdAt });\n\nexport const getUser = async (userid) =>\n get(`${API_BASE}/user/${userid}`);\n\nexport const getUserSessions = async (userid, { limit, offset } = {}) =>\n get(`${API_BASE}/user/${userid}/sessions`, { limit, offset });\n\nexport const deleteUserSession = async (userid, sessionToken) =>\n del(`${API_BASE}/user/${userid}/sessions`, { sessionToken });\n\nexport const deleteExpiredUserSessions = async (userid) =>\n del(`${API_BASE}/user/${userid}/sessions/expired`);\n\nexport const getUserGroups = async (userid, { limit, offset } = {}) =>\n get(`${API_BASE}/user/${userid}/groups`, { limit, offset });\n\nexport const addUserToGroup = async (userid, groupName) =>\n post(`${API_BASE}/user/${userid}/groups`, { groupName });\n\nexport const removeUserFromGroup = async (userid, groupName) =>\n del(`${API_BASE}/user/${userid}/groups`, { groupName });\n\nexport const listGroups = async ({ limit, offset, owner } = {}) =>\n get(`${API_BASE}/groups`, { limit, offset, owner });\n\nexport const createGroup = async ({ name, description }) =>\n post(`${API_BASE}/groups`, { name, description });\n\nexport const updateGroup = async ({ name, newName, description }) =>\n patch(`${API_BASE}/groups`, { name, newName, description });\n\nexport const deleteGroups = async (names) =>\n del(`${API_BASE}/groups`, { names });\n\nexport const getGroup = async (name) =>\n get(`${API_BASE}/groups/${encodeURIComponent(name)}`);\n\nexport const getGroupMembers = async (name, { limit, offset } = {}) =>\n get(`${API_BASE}/groups/${encodeURIComponent(name)}/members`, { limit, offset });\n\nexport const addMemberToGroup = async (name, userId) =>\n post(`${API_BASE}/groups/${encodeURIComponent(name)}/members`, { userId });\n\nexport const removeMemberFromGroup = async (name, userId) =>\n del(`${API_BASE}/groups/${encodeURIComponent(name)}/members`, { userId });\n\nexport const getGroupPermissions = async (name) =>\n get(`${API_BASE}/groups/${encodeURIComponent(name)}/permissions`);\n\nexport const addPermissionToGroup = async (name, permissionName) =>\n post(`${API_BASE}/groups/${encodeURIComponent(name)}/permissions`, { permissionName });\n\nexport const removePermissionFromGroup = async (name, permissionName) =>\n del(`${API_BASE}/groups/${encodeURIComponent(name)}/permissions`, { permissionName });\n\nexport const listPermissions = async ({ limit, offset, owner } = {}) =>\n get(`${API_BASE}/permissions`, { limit, offset, owner });\n\nexport const createPermissions = async (permissions) =>\n post(`${API_BASE}/permissions`, { permissions });\n\nexport const updatePermission = async ({ name, description }) =>\n patch(`${API_BASE}/permissions`, { name, description });\n\nexport const deletePermissions = async (names) =>\n del(`${API_BASE}/permissions`, { names });\n\nexport const getSetting = async (owner, name) =>\n get(`${API_BASE}/settings/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`);\n\nexport const listSettings = async ({ owner, limit, offset } = {}) =>\n get(`${API_BASE}/settings/${encodeURIComponent(owner)}`, { limit, offset });\n\nexport const setSetting = async (owner, name, data) =>\n post(`${API_BASE}/settings/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`, data);\n\nexport const deleteSetting = async (owner, name) =>\n del(`${API_BASE}/settings/${encodeURIComponent(owner)}/${encodeURIComponent(name)}`);\n\n/*\n Pages\n*/\n\nexport const listPages = async ({ owner, showHidden, offset, limit } = {}) =>\n get(`${API_BASE}/pages`, { owner, showHidden, offset, limit });\n\nexport const rescanPages = async () =>\n post(`${API_BASE}/pages/rescan`, {});\n\nexport const listTemplates = async () =>\n get(`${API_BASE}/templates`);\n\nexport const listDirectories = async () =>\n get(`${API_BASE}/pages/directories`);\n\nexport const getPage = async (file) =>\n get(`${API_BASE}/pages/file`, { file });\n\nexport const createPage = async ({ directory, name, template }) =>\n post(`${API_BASE}/pages`, { directory, name, template });\n\nexport const updatePage = async ({ file, name, title, description, author, template, contents, extraMetadata }) =>\n put(`${API_BASE}/pages/file`, { file, name, title, description, author, template, contents, extraMetadata });\n\nexport const deletePages = async (files) =>\n del(`${API_BASE}/pages`, { files });\n\nexport const disablePage = async (file) =>\n put(`${API_BASE}/pages/disable`, { file });\n\nexport const enablePage = async (file) =>\n put(`${API_BASE}/pages/enable`, { file });\n\nexport const movePage = async ({ file, newFile }) =>\n patch(`${API_BASE}/pages/file`, { file, newFile });\n\nexport const searchPagesByMetadata = async (query) =>\n get(`${API_BASE}/pages/search`, { query: JSON.stringify(query) });\n\nexport const setPageLocked = async ({ file, locked }) =>\n put(`${API_BASE}/pages/lock`, { file, locked });\n\n/*\n Templates\n*/\n\nexport const getTemplate = async (file) =>\n get(`${API_BASE}/templates/file`, { file });\n\nexport const createTemplate = async ({ directory, name, copyFrom }) =>\n post(`${API_BASE}/templates`, { directory, name, copyFrom });\n\nexport const updateTemplate = async ({ file, name, author, markup }) =>\n put(`${API_BASE}/templates/file`, { file, name, author, markup });\n\nexport const deleteTemplates = async (files) =>\n del(`${API_BASE}/templates`, { files });\n\nexport const disableTemplate = async (file) =>\n put(`${API_BASE}/templates/disable`, { file });\n\nexport const enableTemplate = async (file) =>\n put(`${API_BASE}/templates/enable`, { file });\n\nexport const moveTemplate = async ({ file, newFile }) =>\n patch(`${API_BASE}/templates/file`, { file, newFile });\n\nexport const setTemplateLocked = async ({ file, locked }) =>\n put(`${API_BASE}/templates/lock`, { file, locked });\n\n/*\n Fragments\n*/\n\nexport const listFragments = async () =>\n get(`${API_BASE}/fragments`);\n\nexport const getFragment = async (file) =>\n get(`${API_BASE}/fragments/file`, { file });\n\nexport const createFragment = async ({ directory, name }) =>\n post(`${API_BASE}/fragments`, { directory, name });\n\nexport const updateFragment = async ({ file, author, markup }) =>\n put(`${API_BASE}/fragments/file`, { file, author, markup });\n\nexport const deleteFragments = async (files) =>\n del(`${API_BASE}/fragments`, { files });\n\nexport const moveFragment = async ({ file, newFile }) =>\n patch(`${API_BASE}/fragments/file`, { file, newFile });\n\nexport const disableFragment = async (file) =>\n put(`${API_BASE}/fragments/disable`, { file });\n\nexport const enableFragment = async (file) =>\n put(`${API_BASE}/fragments/enable`, { file });\n\nexport const setFragmentLocked = async ({ file, locked }) =>\n put(`${API_BASE}/fragments/lock`, { file, locked });\n\n/*\n Global Content\n*/\n\nexport const listGlobalContent = async () =>\n get(`${API_BASE}/globals`);\n\nexport const getGlobalContent = async (id) =>\n get(`${API_BASE}/globals/entry`, { id });\n\nexport const createGlobalContent = async ({ name, location, priority }) =>\n post(`${API_BASE}/globals`, { name, location, priority });\n\nexport const updateGlobalContent = async ({ id, name, location, priority, markup }) =>\n put(`${API_BASE}/globals/entry`, { id, name, location, priority, markup });\n\nexport const deleteGlobalContent = async (ids) =>\n del(`${API_BASE}/globals`, { ids });\n\nexport const disableGlobalContent = async (id) =>\n put(`${API_BASE}/globals/disable`, { id });\n\nexport const enableGlobalContent = async (id) =>\n put(`${API_BASE}/globals/enable`, { id });\n\nexport const setGlobalContentLocked = async ({ id, locked }) =>\n put(`${API_BASE}/globals/lock`, { id, locked });\n\n/*\n Extensions\n*/\n\nexport const listExtensions = async ({ limit, offset } = {}) =>\n get(`${API_BASE}/extensions`, { limit, offset });\n\nexport const listAvailableExtensions = async () =>\n get(`${API_BASE}/extensions/available`);\n\nexport const listKnownExtensions = async () =>\n get(`${API_BASE}/extensions/known`);\n\n/*\n Dashboard\n*/\n\nexport const getDashboardWidgets = async () =>\n get(`${API_BASE}/dashboard/widgets`);\n\n/*\n Notifications\n*/\n\nexport const getNotifications = async ({ unreadOnly = false, limit, offset } = {}) =>\n get(`${API_BASE}/notifications`, { unreadOnly, limit, offset });\n\nexport const getUnreadNotificationCount = async () =>\n get(`${API_BASE}/notifications/count`);\n\nexport const markNotificationRead = async (id) =>\n post(`${API_BASE}/notifications/${encodeURIComponent(id)}/read`, {});\n\nexport const markNotificationHandled = async (id) =>\n post(`${API_BASE}/notifications/${encodeURIComponent(id)}/handled`, {});\n\nexport const markAllNotificationsRead = async () =>\n post(`${API_BASE}/notifications/read-all`, {});\n\nexport const dismissNotification = async (id) =>\n del(`${API_BASE}/notifications/${encodeURIComponent(id)}`);\n\nexport const listRealtimeConnections = async () =>\n get(`${API_BASE}/realtime/connections`);\n\nexport const installExtension = async (name) =>\n post(`${API_BASE}/extensions`, { name });\n\nexport const uninstallExtension = async (name, purgeData = false) =>\n del(`${API_BASE}/extensions`, { name, purgeData });\n\nexport const enableExtension = async (name) =>\n post(`${API_BASE}/extensions/${encodeURIComponent(name)}/enable`, {});\n\nexport const disableExtension = async (name) =>\n post(`${API_BASE}/extensions/${encodeURIComponent(name)}/disable`, {});\n\n/*\n Admin Global Content\n*/\n\nexport const listAdminGlobalContent = async () =>\n get(`${API_BASE}/admin-globals`);\n\nexport const getAdminGlobalContent = async (id) =>\n get(`${API_BASE}/admin-globals/${encodeURIComponent(id)}`);\n\nexport const createAdminGlobalContent = async ({ name, location, priority, owner, markup }) =>\n post(`${API_BASE}/admin-globals`, { name, location, priority, owner, markup });\n\nexport const updateAdminGlobalContent = async (id, { name, location, priority, markup }) =>\n put(`${API_BASE}/admin-globals/${encodeURIComponent(id)}`, { name, location, priority, markup });\n\nexport const deleteAdminGlobalContent = async (ids) =>\n del(`${API_BASE}/admin-globals`, { ids });\n\nexport const enableAdminGlobalContent = async (id) =>\n put(`${API_BASE}/admin-globals/${encodeURIComponent(id)}/enable`, {});\n\nexport const disableAdminGlobalContent = async (id) =>\n put(`${API_BASE}/admin-globals/${encodeURIComponent(id)}/disable`, {});\n\n"],"mappings":"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","ignoreList":[]}
@@ -1,2 +1,2 @@
1
1
  export default t=>"string"!=typeof t||t.length>2048||!t.startsWith("/")||t.startsWith("//")||/[\\\u0000-\u001f\u007f]/.test(t)?"":t;
2
- //# sourceMappingURL=c:\Users\dusti\dev\kempo\dist\kempo\utils\safeNext.js.map
2
+ //# sourceMappingURL=C:\Users\dusti\dev\kempo\dist\kempo\utils\safeNext.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kempo",
3
- "version": "4.5.1",
3
+ "version": "4.5.3",
4
4
  "type": "module",
5
5
  "description": "A fullstack CMS framework for creating websites with user authentication",
6
6
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  import { sql } from 'drizzle-orm';
2
- import { pgTable, text, timestamp, boolean, index, uniqueIndex, primaryKey, jsonb, bigserial, bigint } from 'drizzle-orm/pg-core';
2
+ import { pgTable, text, timestamp, boolean, index, uniqueIndex, primaryKey, jsonb, bigserial, bigint, integer } from 'drizzle-orm/pg-core';
3
3
 
4
4
  /*
5
5
  Auth Tables
@@ -188,6 +188,39 @@ export const notificationRecipient = pgTable('notificationRecipient', {
188
188
  index('notificationRecipient_userId_idx').on(table.userId),
189
189
  ]);
190
190
 
191
+ /*
192
+ Dashboard Widget System
193
+
194
+ A tile an extension adds to the admin dashboard. `id` is `owner:key`, which is also what the browser
195
+ stores its layout against. `element` is the custom element the dashboard creates and `module` is the
196
+ script that defines it; the widget fetches its own data once it is on the page. Kempo's own widgets
197
+ are not rows: they live in code (`server/utils/dashboard/coreWidgets.js`) so they need no seeding.
198
+ */
199
+ export const dashboardWidget = pgTable('dashboardWidget', {
200
+ id: text('id').primaryKey(),
201
+ owner: text('owner').notNull(),
202
+ key: text('key').notNull(),
203
+ title: text('title').notNull(),
204
+ description: text('description'),
205
+ icon: text('icon'),
206
+ element: text('element').notNull(),
207
+ module: text('module').notNull(),
208
+ defaultWidth: integer('defaultWidth').notNull().default(2),
209
+ defaultHeight: integer('defaultHeight').notNull().default(1),
210
+ minWidth: integer('minWidth').notNull().default(1),
211
+ maxWidth: integer('maxWidth').notNull().default(4),
212
+ minHeight: integer('minHeight').notNull().default(1),
213
+ maxHeight: integer('maxHeight').notNull().default(3),
214
+ permission: text('permission'),
215
+ actions: jsonb('actions').notNull().default([]),
216
+ priority: integer('priority').notNull().default(100),
217
+ defaultVisible: boolean('defaultVisible').notNull().default(true),
218
+ createdAt: timestamp('createdAt').notNull(),
219
+ updatedAt: timestamp('updatedAt').notNull(),
220
+ }, table => [
221
+ uniqueIndex('dashboardWidget_owner_key_idx').on(table.owner, table.key),
222
+ ]);
223
+
191
224
  /*
192
225
  Triggers to prevent deletion of system resources
193
226
  */
package/server/sdk.js CHANGED
@@ -209,6 +209,14 @@ export { default as markHandled } from './utils/notifications/markHandled.js';
209
209
  export { default as markRead } from './utils/notifications/markRead.js';
210
210
  export { default as pruneNotifications } from './utils/notifications/pruneNotifications.js';
211
211
 
212
+ /*
213
+ Dashboard
214
+ */
215
+
216
+ export { default as listDashboardWidgets } from './utils/dashboard/listDashboardWidgets.js';
217
+ export { default as registerDashboardWidget } from './utils/dashboard/registerDashboardWidget.js';
218
+ export { default as unregisterDashboardWidget } from './utils/dashboard/unregisterDashboardWidget.js';
219
+
212
220
  /*
213
221
  Realtime
214
222
  */
@@ -0,0 +1,87 @@
1
+ import { CORE_OWNER } from './helpers.js';
2
+
3
+ const core = widget => ({
4
+ owner: CORE_OWNER,
5
+ description: null,
6
+ icon: null,
7
+ defaultWidth: 2,
8
+ defaultHeight: 1,
9
+ minWidth: 1,
10
+ maxWidth: 4,
11
+ minHeight: 1,
12
+ maxHeight: 3,
13
+ permission: null,
14
+ actions: [],
15
+ defaultVisible: true,
16
+ ...widget,
17
+ id: `${CORE_OWNER}:${widget.key}`
18
+ });
19
+
20
+ /*
21
+ The widgets Kempo itself puts on the dashboard. They are code, not rows, so an existing site gets
22
+ them on upgrade with nothing to seed, and `priority` leaves room for extensions on either side.
23
+ */
24
+ export default [
25
+ core({
26
+ key: 'pages',
27
+ title: 'Pages',
28
+ description: 'How many pages the site has and which changed most recently.',
29
+ icon: 'docs',
30
+ element: 'k-widget-pages',
31
+ module: '/admin/components/widgets/Pages.js',
32
+ defaultWidth: 2,
33
+ defaultHeight: 2,
34
+ minWidth: 2,
35
+ minHeight: 2,
36
+ permission: 'system:pages:read',
37
+ priority: 10
38
+ }),
39
+ core({
40
+ key: 'content',
41
+ title: 'Content',
42
+ description: 'Templates, fragments and global content at a glance.',
43
+ icon: 'content',
44
+ element: 'k-widget-content',
45
+ module: '/admin/components/widgets/Content.js',
46
+ defaultWidth: 1,
47
+ defaultHeight: 1,
48
+ permission: 'system:pages:read',
49
+ priority: 20
50
+ }),
51
+ core({
52
+ key: 'users',
53
+ title: 'Users',
54
+ description: 'How many people have an account.',
55
+ icon: 'person',
56
+ element: 'k-widget-users',
57
+ module: '/admin/components/widgets/Users.js',
58
+ defaultWidth: 1,
59
+ defaultHeight: 1,
60
+ permission: 'system:user:read',
61
+ priority: 30
62
+ }),
63
+ core({
64
+ key: 'notifications',
65
+ title: 'Notifications',
66
+ description: 'Your unread notifications.',
67
+ icon: 'notifications',
68
+ element: 'k-widget-notifications',
69
+ module: '/admin/components/widgets/Notifications.js',
70
+ defaultWidth: 2,
71
+ defaultHeight: 2,
72
+ minWidth: 2,
73
+ priority: 40
74
+ }),
75
+ core({
76
+ key: 'extensions',
77
+ title: 'Extensions',
78
+ description: 'Installed extensions and whether they are enabled.',
79
+ icon: 'extension',
80
+ element: 'k-widget-extensions',
81
+ module: '/admin/components/widgets/Extensions.js',
82
+ defaultWidth: 1,
83
+ defaultHeight: 1,
84
+ permission: 'system:extensions:read',
85
+ priority: 50
86
+ })
87
+ ];
@@ -0,0 +1,144 @@
1
+ import { isLocalPath } from '../notifications/helpers.js';
2
+
3
+ export const MAX_WIDTH = 4;
4
+ export const MAX_HEIGHT = 3;
5
+ export const CORE_OWNER = 'kempo';
6
+ export const MAX_ACTIONS = 3;
7
+
8
+ const ELEMENT_PATTERN = /^[a-z][a-z0-9]*(-[a-z0-9]+)+$/;
9
+ const KEY_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_.-]*$/;
10
+
11
+ const isText = (value, max) => typeof value === 'string' && value.trim().length > 0 && value.length <= max;
12
+
13
+ const isBlocks = (value, max) => Number.isInteger(value) && value >= 1 && value <= max;
14
+
15
+ /*
16
+ Reduces a widget definition to the stored fields and fills in the defaults, so nothing a caller
17
+ passes beyond them is kept. Returns an error tuple for anything that would leave the dashboard
18
+ unable to render the widget: a size outside the grid, bounds that contradict each other, an element
19
+ name that is not a valid custom element, or a module that is not a path on this site.
20
+ */
21
+ export const normalizeWidget = ({
22
+ owner,
23
+ key,
24
+ title,
25
+ description = null,
26
+ icon = null,
27
+ element,
28
+ module,
29
+ defaultWidth = 2,
30
+ defaultHeight = 1,
31
+ minWidth = 1,
32
+ maxWidth = MAX_WIDTH,
33
+ minHeight = 1,
34
+ maxHeight = MAX_HEIGHT,
35
+ permission = null,
36
+ actions = [],
37
+ priority = 100,
38
+ defaultVisible = true
39
+ } = {}) => {
40
+ if(!isText(owner, 100)){
41
+ return [{ code: 400, msg: 'Owner is required' }, null];
42
+ }
43
+
44
+ if(typeof key !== 'string' || !KEY_PATTERN.test(key) || key.length > 100){
45
+ return [{ code: 400, msg: 'Key is required and may only contain letters, numbers, ".", "_" and "-"' }, null];
46
+ }
47
+
48
+ if(!isText(title, 100)){
49
+ return [{ code: 400, msg: 'Title is required and must be at most 100 characters' }, null];
50
+ }
51
+
52
+ if(description !== null && !(typeof description === 'string' && description.length <= 300)){
53
+ return [{ code: 400, msg: 'Description must be a string of at most 300 characters' }, null];
54
+ }
55
+
56
+ if(icon !== null && !isText(icon, 60)){
57
+ return [{ code: 400, msg: 'Icon must be an icon name' }, null];
58
+ }
59
+
60
+ if(typeof element !== 'string' || !ELEMENT_PATTERN.test(element)){
61
+ return [{ code: 400, msg: 'Element must be a custom element tag name such as "my-ext-widget"' }, null];
62
+ }
63
+
64
+ if(!isLocalPath(module)){
65
+ return [{ code: 400, msg: 'Module must be a path on this site, beginning with a single "/"' }, null];
66
+ }
67
+
68
+ if(!isBlocks(minWidth, MAX_WIDTH) || !isBlocks(maxWidth, MAX_WIDTH) || minWidth > maxWidth){
69
+ return [{ code: 400, msg: `minWidth and maxWidth must be whole numbers from 1 to ${MAX_WIDTH}, minWidth no greater than maxWidth` }, null];
70
+ }
71
+
72
+ if(!isBlocks(minHeight, MAX_HEIGHT) || !isBlocks(maxHeight, MAX_HEIGHT) || minHeight > maxHeight){
73
+ return [{ code: 400, msg: `minHeight and maxHeight must be whole numbers from 1 to ${MAX_HEIGHT}, minHeight no greater than maxHeight` }, null];
74
+ }
75
+
76
+ if(!Number.isInteger(defaultWidth) || defaultWidth < minWidth || defaultWidth > maxWidth){
77
+ return [{ code: 400, msg: 'defaultWidth must be a whole number between minWidth and maxWidth' }, null];
78
+ }
79
+
80
+ if(!Number.isInteger(defaultHeight) || defaultHeight < minHeight || defaultHeight > maxHeight){
81
+ return [{ code: 400, msg: 'defaultHeight must be a whole number between minHeight and maxHeight' }, null];
82
+ }
83
+
84
+ if(permission !== null && !isText(permission, 200)){
85
+ return [{ code: 400, msg: 'Permission must be a permission name' }, null];
86
+ }
87
+
88
+ if(!Array.isArray(actions) || actions.length > MAX_ACTIONS){
89
+ return [{ code: 400, msg: `actions must be an array of at most ${MAX_ACTIONS} items` }, null];
90
+ }
91
+
92
+ const cleanActions = [];
93
+
94
+ for(const action of actions){
95
+ if(!action || typeof action !== 'object' || Array.isArray(action)){
96
+ return [{ code: 400, msg: 'Each action must be an object' }, null];
97
+ }
98
+
99
+ const { label, href, icon: actionIcon = null, permission: actionPermission = null } = action;
100
+
101
+ if(!isText(label, 40)){
102
+ return [{ code: 400, msg: 'Each action needs a label of at most 40 characters' }, null];
103
+ }
104
+
105
+ if(!isLocalPath(href)){
106
+ return [{ code: 400, msg: 'An action href must be a path on this site, beginning with a single "/"' }, null];
107
+ }
108
+
109
+ if(actionIcon !== null && !isText(actionIcon, 60)){
110
+ return [{ code: 400, msg: 'An action icon must be an icon name' }, null];
111
+ }
112
+
113
+ if(actionPermission !== null && !isText(actionPermission, 200)){
114
+ return [{ code: 400, msg: 'An action permission must be a permission name' }, null];
115
+ }
116
+
117
+ cleanActions.push({ label: label.trim(), href, icon: actionIcon, permission: actionPermission });
118
+ }
119
+
120
+ if(!Number.isInteger(priority)){
121
+ return [{ code: 400, msg: 'Priority must be a whole number' }, null];
122
+ }
123
+
124
+ return [null, {
125
+ id: `${owner}:${key}`,
126
+ owner,
127
+ key,
128
+ title: title.trim(),
129
+ description,
130
+ icon,
131
+ element,
132
+ module,
133
+ defaultWidth,
134
+ defaultHeight,
135
+ minWidth,
136
+ maxWidth,
137
+ minHeight,
138
+ maxHeight,
139
+ permission,
140
+ actions: cleanActions,
141
+ priority,
142
+ defaultVisible: defaultVisible !== false
143
+ }];
144
+ };