Skip to content

Commit

Permalink
add functions
Browse files Browse the repository at this point in the history
  • Loading branch information
TheHadiAhmadi committed Sep 6, 2024
1 parent 8480da3 commit 2e6e2c4
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 26 deletions.
22 changes: 13 additions & 9 deletions functions/test.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { db } from "#services"

export default {
name: 'Test function',
slug: 'test_function',
mode: 'action',
props: [
{
slug: 'collection',
type: 'collection',
name: 'Collection'
}
],
action(req, context) {
// props: [
// {
// slug: 'collection',
// type: 'collection',
// name: 'Collection'
// }
// ],
action(body, context) {

console.log(body, context)
//
return {}
}
}
15 changes: 11 additions & 4 deletions src/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function createApp({functions, db}) {
app.use(express.static(path.join(__dirname, '../public')))
app.use(express.static('./public'))

app.use('/', contextMiddleware())
app.use('/', contextMiddleware({functions}))

// File upload
app.use('/files', express.static('./uploads'))
Expand Down Expand Up @@ -91,9 +91,16 @@ export function createApp({functions, db}) {

//#region Functions
for (let key in functions) {
// app.post('/api/ + key, (req, res) => {
// call function with req.context, req.body, ...
// })
if(functions[key].action) {

app.post('/api/fn/' + key, async (req, res) => {
// call function with req.context, req.body, ...

const resp = await functions[key].action(req.body, req.context)

return res.json(resp)
})
}
}

// OR?
Expand Down
3 changes: 3 additions & 0 deletions src/handlers/ai/createModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ function generateCreateModuleSystemPrompt({ collections, name }) {
type CheckboxProp = { "type": "checkbox", "slug": "string", "label": "string" }
type SelectProp = { "type": "select", "slug": "string", "label": "string", "multiple": "boolean", "items": "string[]" }
type RelationProp = { "type": "relation", "slug": "string", "label": "string", "collectionId": "string", "multiple": "boolean" }
type FunctionProp = { "type": "function", "slug": "string", "label": "string" }
Function types are used for form submission. form actions should be /api/fn/{{function}}. and always use POST method.
Available Handlebars helpers:
eq, ifCond, truncateText, formatDate, json, uppercase, lowercase, times, join, safeString, default
Expand Down
3 changes: 3 additions & 0 deletions src/handlers/ai/updateModule.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ function generateUpdateModuleSystemPrompt({ collections, definition }) {
- SelectProp: { "type": "select", "slug": "string", "label": "string", "multiple": boolean, "items": string[] }
- RichTextProp: { "type": "rich-text", "slug": "string", "label": "string" }
- RelationProp: { "type": "relation", "slug": "string", "label": "string", "collectionId": "string", "multiple": boolean }
- FunctionProp: { "type": "function", "slug": "string", "label": "string" }
Function types are used for form submission. form actions should be /api/fn/{{function}}. and always use POST method.
- **Available Handlebars helpers**:
eq, ifCond, truncateText, formatDate, json, uppercase, lowercase, times, join, safeString, default
Expand Down
14 changes: 7 additions & 7 deletions src/handlers/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { html } from "svelite-html"
import { Form } from "#components"
import { FieldInput } from "../pages/collections.js"

function DynamicFieldInput(field, fields, linked, module, collections) {
function DynamicFieldInput(field, fields, linked, module, collections, functions = {}) {
function getLinkedText(key) {
return fields.find(x => x.slug === key)?.label ?? key
}
Expand Down Expand Up @@ -85,10 +85,10 @@ function DynamicFieldInput(field, fields, linked, module, collections) {
options.type = 'hidden'
}

return FieldInput(options, collections)
return FieldInput(options, collections, functions)
}

function sidebarModuleSettings(definition, module, collection, collections) {
function sidebarModuleSettings(definition, module, collection, collections, functions) {
const fields = []
fields.push({slug: 'settings.logo', label: 'Site\'s Logo', type: 'file', multiple: false, file_type: 'image'})
fields.push({slug: 'settings.favicon', label: 'Site\'s Favicon', type: 'file', multiple: false, file_type: 'image'})
Expand Down Expand Up @@ -120,7 +120,7 @@ function sidebarModuleSettings(definition, module, collection, collections) {
fields: [
`<input type="hidden" name="slug" value="">`,
`<input type="hidden" name="id" value="${module.id}">`,
(definition.props ?? []).map(prop => DynamicFieldInput(prop, fields, module.links?.[prop.slug], module, collections)).join('')
(definition.props ?? []).map(prop => DynamicFieldInput(prop, fields, module.links?.[prop.slug], module, collections, functions)).join('')
],
cancelAction: 'close-module-settings'
}): `
Expand Down Expand Up @@ -183,7 +183,7 @@ export default {
links: {}
})
},
async getSettingsTemplate(body) {
async getSettingsTemplate(body, {functions} = {}) {
const moduleId = body.id
const module = await db('modules').query().filter('id', '=', moduleId).first();
const page = await getPageFromModule(module);
Expand All @@ -200,15 +200,15 @@ export default {

}

const res = sidebarModuleSettings(definition, module, collection, collections)
const res = sidebarModuleSettings(definition, module, collection, collections, functions)

return res;
}


}

const res = sidebarModuleSettings(definition, module, null, collections)
const res = sidebarModuleSettings(definition, module, null, collections, functions)
return res
},
async loadSettings(body) {
Expand Down
4 changes: 3 additions & 1 deletion src/middlewares/context.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { fileURLToPath } from 'node:url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export function contextMiddleware() {
export function contextMiddleware({functions}) {
console.log('functions: ', functions)
return async (req, res, next) => {

let user = await db('users').query().filter('id', '=', req.cookies.userId).first()
Expand All @@ -19,6 +20,7 @@ export function contextMiddleware() {
}

let context = {
functions,
user: user ? {
id: user.id,
username: user.username,
Expand Down
20 changes: 15 additions & 5 deletions src/pages/collections.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ function RichText(field) {
})
}

export function FieldInput(field, collections = []) {
export function FieldInput(field, collections = [], functions = {}) {
let options = {
name: field.slug,
label: field.label,
Expand Down Expand Up @@ -112,6 +112,15 @@ export function FieldInput(field, collections = []) {

return Select({name, placeholder, label, items})
}

function FunctionField({name, label, placeholder}) {
return Select({
name,
placeholder: 'Choose a Function',
label,
items: Object.keys(functions).map(x => ({value: x, text: functions[x].name}))
})
}

const inputs = {
input: Input,
Expand All @@ -122,6 +131,7 @@ export function FieldInput(field, collections = []) {
relation: Relation,
'rich-text': RichText,
collection: CollectionField,
function: FunctionField,
hidden: (options) => Label({text: options.label})
}

Expand Down Expand Up @@ -212,7 +222,7 @@ export async function CollectionDataListPage({query}) {
})
}

export async function CollectionDataCreatePage({query}) {
export async function CollectionDataCreatePage({query, functions}) {
const collection = await db('collections').query().filter('id', '=', query.id).first()
const collections = await db('collections').query().all()

Expand All @@ -230,14 +240,14 @@ export async function CollectionDataCreatePage({query}) {
cancelHref: back,
fields: [
`<input type="hidden" value="${collection.id}" name="_type">`,
collection.fields.filter(x => !x.hidden).map(field => FieldInput(field, collections)).join('')
collection.fields.filter(x => !x.hidden).map(field => FieldInput(field, collections, functions)).join('')
],
}),
]
})
}

export async function CollectionDataUpdatePage({query}) {
export async function CollectionDataUpdatePage({query, functions}) {
const data = await db('contents').query().filter('id', '=', query.id).first()
const collection = await db('collections').query().filter('id', '=', data._type).first()
const collections = await db('collections').query().first()
Expand All @@ -261,7 +271,7 @@ export async function CollectionDataUpdatePage({query}) {
fields: [
'<input type="hidden" value="' + id + '" name="id">',
'<input type="hidden" value="' + data._type + '" name="_type">',
collection.fields.filter(x => !x.hidden).map(field => FieldInput(field, collections)).join('')
collection.fields.filter(x => !x.hidden).map(field => FieldInput(field, collections, functions)).join('')
],
}),
]
Expand Down
1 change: 1 addition & 0 deletions src/pages/dataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ export function DataTable({filters = [], selectable, items, collectionId, fields
return renderFile(item[field.slug])
}
if(field.type === 'rich-text') return item[field.slug] ? '...' : ''
if(field.type === 'function') return item[field.slug] ?? ''
if(field.type === 'relation') {
if(!item[field.slug]) return ''

Expand Down
1 change: 1 addition & 0 deletions src/pages/fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const fieldTypes = [
{ text: 'Rich Text', value: 'rich-text' },
{ text: 'Relation', value: 'relation' },
{ text: 'Collection', value: 'collection', hidden: true },
{ text: 'Function', value: 'function' },
]

function fieldTypeText(key) {
Expand Down

0 comments on commit 2e6e2c4

Please sign in to comment.