From fe10820aac5ffaee5f42479298cd7d3b1ac71fb3 Mon Sep 17 00:00:00 2001 From: TheHadiAhmadi Date: Fri, 6 Sep 2024 22:56:17 +0430 Subject: [PATCH] add functions page --- package.json | 2 +- public/js/actions.js | 12 ++++++ services/index.js | 2 +- src/app.js | 2 +- src/handlers/role.js | 4 ++ src/page.js | 17 ++++++-- src/pages/functions.js | 89 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 src/pages/functions.js diff --git a/package.json b/package.json index 006fc13..0d628a0 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,12 @@ "version": "1.0.1-next.7", "type": "module", "bin": "bin/tailcms.js", + "main": "./services/index.js", "imports": { "#services": "./services/index.js", "#components": "./src/components/index.js", "#helpers": "./src/helpers.js" }, - "main": "index.js", "scripts": { "dev": "node bin/tailcms.js dev", "test": "echo \"Error: no test specified\" && exit 1" diff --git a/public/js/actions.js b/public/js/actions.js index 008d6ad..240c6f0 100644 --- a/public/js/actions.js +++ b/public/js/actions.js @@ -149,6 +149,18 @@ const actions = { submitButton.addEventListener('click', onButtonClick) } }, + 'open-update-function-modal'(el) { + const modal = document.querySelector('[data-modal="update-function"]') + + modal.modalOpen = true + + setFormValue(modal, { + id: el.dataset.id, + name: el.dataset.name, + status: el.dataset.status + }) + + }, async 'collection-data-create-submit'(el, ev) { const value = getFormValue(el); el.dataset.load = '' diff --git a/services/index.js b/services/index.js index ea7b37f..9059edc 100644 --- a/services/index.js +++ b/services/index.js @@ -1 +1 @@ -export { db, setDb} from './db.js' \ No newline at end of file +export { db } from './db.js' \ No newline at end of file diff --git a/src/app.js b/src/app.js index 046b63e..7d25a77 100644 --- a/src/app.js +++ b/src/app.js @@ -1,5 +1,4 @@ import express from 'express' -import { setDb } from '#services' import { renderPageController } from './controllers/page.js' import cookieParser from 'cookie-parser' import { LoginPage } from './pages/login.js' @@ -13,6 +12,7 @@ import { queryController } from './controllers/query.js' import { fileUploadController } from './controllers/file.js' import { publishController } from './controllers/publish.js' import { contextMiddleware } from './middlewares/context.js' +import { setDb } from '../services/db.js' // Get the directory of the current file const __dirname = path.dirname(fileURLToPath(import.meta.url)); diff --git a/src/handlers/role.js b/src/handlers/role.js index adb22af..f436e1e 100644 --- a/src/handlers/role.js +++ b/src/handlers/role.js @@ -65,6 +65,10 @@ export const roleFields = [ value: 'page_delete' }, { + text: 'Functions', + value: 'functions' + }, + { text: 'Blocks', value: 'blocks' }, diff --git a/src/page.js b/src/page.js index b1ca64a..a866c11 100644 --- a/src/page.js +++ b/src/page.js @@ -16,6 +16,7 @@ import { BlockCreatePage, BlockUpdatePage, CreateBlockAiModal, UpdateBlockAiModa import { Sidebar } from './pages/sidebar.js'; import { RoleCreatePage, RoleListPage, RoleUpdatePage } from './pages/roles.js'; import { constants } from 'http2'; +import { FunctionListPage } from './pages/functions.js'; let definitions = {} @@ -61,7 +62,7 @@ function DashboardPage() { body: '
Welcome!
' }) } -const pageMap = { +const pages = { 'dashboard': [DashboardPage, []], 'pages.edit' : [PageEditorPage, ['pages']], 'iframe': [PageEditorPage, ['page_content', 'page_update']], @@ -70,6 +71,7 @@ const pageMap = { 'blocks.create': [BlockCreatePage, ['block_create']], 'blocks.update': [BlockUpdatePage, ['block_update', 'block_delete']], 'collections.create': [CollectionCreatePage, ['collection_create']], + 'functions.list': [FunctionListPage, ['functions']], 'collections.update': [CollectionUpdatePage, ['collection_update']], 'collections.data.list': [CollectionDataListPage, ['collections', 'collections_sidebar']], 'collections.data.create': [CollectionDataCreatePage, ['content_create']], @@ -87,6 +89,7 @@ const pageMap = { //#region Render body export async function renderBody(body, { props, mode, url, view, context, params, ...query }) { let permissions = context.permissions + let functions = context.functions const collections = await db('collections').query().all().then(res => res.filter(x => x.sidebar)) @@ -105,6 +108,12 @@ export async function renderBody(body, { props, mode, url, view, context, params viewPrefix: 'blocks.', items: 'blocks' }, + permissions.functions && { + title: 'Functions', + icon: '', + href: getUrl({view: 'functions.list'}), + viewPrefix: 'functions.', + }, permissions.collections && { title: 'Collections', icon: '', @@ -141,14 +150,14 @@ export async function renderBody(body, { props, mode, url, view, context, params let pageContent; try { - if(!pageMap[view]) { + if(!pages[view]) { pageContent = Page({ body: EmptyTable({title: "Page Not found!", description: "This page doesn't exists", body: [ Button({href: '/admin', text: "Go Home", color: 'primary'}) ]}) }) } else { - const [page, pagePermissions] = pageMap[view] + const [page, pagePermissions] = pages[view] let access = false if(pagePermissions.length == 0) access = true for(let permission of pagePermissions) { @@ -157,7 +166,7 @@ export async function renderBody(body, { props, mode, url, view, context, params } } if(access) { - pageContent = await page({query, view, url, permissions, context}) + pageContent = await page({query, view, url, permissions, context, functions}) } else { pageContent = Page({ body: EmptyTable({title: "No Access!", description: "You don't have access to this page!", body: [ diff --git a/src/pages/functions.js b/src/pages/functions.js new file mode 100644 index 0000000..29e85d4 --- /dev/null +++ b/src/pages/functions.js @@ -0,0 +1,89 @@ +import { Form, Input, Modal, Page, Select } from "#components"; +import { DataTable } from "./dataTable.js"; + + +const functionFields = [ + { + slug: 'name', + label: 'Name', + type: 'input', + default: true, + }, + { + slug: 'slug', + label: 'Slug', + type: 'input', + default: true, + }, + { + slug: 'status', + label: 'Status', + type: 'select', + items: [ + "Enabled", + "Disabled" + ] + } +] + +function FunctionsDataTable({functions}) { + const items = { + perPage: Object.keys(functions).length, + page: 1, + data: Object.keys(functions).map(x => functions[x]) + } + + const actions = [ + { + text: "Change Status", + action: 'open-update-function-modal', + dataset: { + 'modal-name': 'update-function' + } + }, + { + text: "Call" + }, + + ] + + return DataTable({filters: [], selectable: false, items, fields: functionFields, actions, relationFilters: false}) +} + +export function FunctionListPage({functions}) { + return Page({ + title: 'Functions', + body: [ + FunctionsDataTable({functions}), + ChangeFunctionStatusModal() + ] + }) +} + +function ChangeFunctionStatusModal() { + return Modal({ + name: 'update-function', + title: "Change function status", + body: Form({ + handler: 'function.changeStatus', + cancelAction: 'modal.close', + card: false, + fields: [ + ``, + Input({ + name: 'name', + label: 'Function Name', + type: 'text' + }), + Select({ + name: 'status', + label: 'New Status', + items: [ + 'Enabled', + "Disabled" + ] + }) + ] + }) + }) +} \ No newline at end of file