Builder saves backend and front end seperately (#88)

* refactoring server for screens & page layout restructure

* Disable API calls, UI placeholders.

* buildPropsHierarchy is gone & screen has url

* Recent changes.

* router

* router

* updated git-ignore to reinclude server/utilities/builder

* modified cli - budi new create new file structure

* Fix uuid import.

* prettier fixes

* prettier fixes

* prettier fixes

* page/screen restructure.. broken tests

* all tests passing at last

* screen routing tests

* Working screen editor and preview.

* Render page previews to the screen.

* Key input lists to ensure new array references when updating styles.

* Ensure the iframe html and body fills the container.

* Save screens via the API.

* Get all save APIs almost working.

* Write pages.json to disk.

* Use correct API endpoint for saving styles.

* Differentiate between saving properties of screens and pages.

* Add required fields to default pages layouts.

* Add _css default property to newly created screens.

* Add default code property.

* page layout / screens - app output

* backend and fronend save seperately

Co-authored-by: pngwn <pnda007@gmail.com>
This commit is contained in:
Michael Shanks 2020-02-10 21:35:51 +00:00 committed by GitHub
parent f7bea46f01
commit da7339035f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 13522 additions and 11612 deletions

View File

@ -295,7 +295,7 @@ const saveCurrentNode = store => () => {
s.currentNodeIsNew = false s.currentNodeIsNew = false
savePackage(store, s) saveBackend(s)
return s return s
}) })
@ -331,7 +331,7 @@ const deleteCurrentNode = store => () => {
)(nodeToDelete.parent().indexes) )(nodeToDelete.parent().indexes)
} }
s.errors = [] s.errors = []
savePackage(store, s) saveBackend(s)
return s return s
}) })
} }
@ -370,7 +370,7 @@ const saveAction = store => (newAction, isNew, oldAction = null) => {
} else { } else {
s.actions.push(newAction) s.actions.push(newAction)
} }
savePackage(store, s) saveBackend(s)
return s return s
}) })
} }
@ -378,7 +378,7 @@ const saveAction = store => (newAction, isNew, oldAction = null) => {
const deleteAction = store => action => { const deleteAction = store => action => {
store.update(s => { store.update(s => {
s.actions = filter(a => a.name !== action.name)(s.actions) s.actions = filter(a => a.name !== action.name)(s.actions)
savePackage(store, s) saveBackend(s)
return s return s
}) })
} }
@ -396,7 +396,7 @@ const saveTrigger = store => (newTrigger, isNew, oldTrigger = null) => {
} else { } else {
s.triggers.push(newTrigger) s.triggers.push(newTrigger)
} }
savePackage(store, s) saveBackend(s)
return s return s
}) })
} }
@ -429,7 +429,7 @@ const saveLevel = store => (newLevel, isNew, oldLevel = null) => {
incrementAccessLevelsVersion(s) incrementAccessLevelsVersion(s)
savePackage(store, s) saveBackend(s)
return s return s
}) })
} }
@ -440,7 +440,7 @@ const deleteLevel = store => level => {
s.accessLevels.levels s.accessLevels.levels
) )
incrementAccessLevelsVersion(s) incrementAccessLevelsVersion(s)
savePackage(store, s) saveBackend(s)
return s return s
}) })
} }
@ -477,18 +477,18 @@ const _saveScreen = (store, s, screen) => {
`/_builder/api/${s.appname}/pages/${s.currentPageName}/screen`, `/_builder/api/${s.appname}/pages/${s.currentPageName}/screen`,
screen screen
) )
.then(() => savePackage(store, s)) .then(() => _savePage(s))
return s return s
} }
const _save = (appname, screen, store, s) => const _saveScreenApi = (screen, s) =>
api api
.post( .post(
`/_builder/api/${s.appname}/pages/${s.currentPageName}/screen`, `/_builder/api/${s.appname}/pages/${s.currentPageName}/screen`,
screen screen
) )
.then(() => savePackage(store, s)) .then(() => _savePage(s))
const createScreen = store => (screenName, route, layoutComponentName) => { const createScreen = store => (screenName, route, layoutComponentName) => {
store.update(s => { store.update(s => {
@ -530,7 +530,7 @@ const createGeneratedComponents = store => components => {
await api.post(`/_builder/api/${s.appname}/screen`, c) await api.post(`/_builder/api/${s.appname}/screen`, c)
} }
await savePackage(store, s) await _savePage(s)
} }
doCreate() doCreate()
@ -591,7 +591,7 @@ const renameScreen = store => (oldname, newname) => {
}) })
.then(() => saveAllChanged()) .then(() => saveAllChanged())
.then(() => { .then(() => {
savePackage(store, s) _savePage(s)
}) })
return s return s
@ -605,7 +605,7 @@ const savePage = store => async page => {
} }
s.pages[s.currentPageName] = page s.pages[s.currentPageName] = page
savePackage(store, s) _savePage(s)
return s return s
}) })
} }
@ -634,7 +634,7 @@ const addComponentLibrary = store => async lib => {
]) ])
s.pages.componentLibraries.push(lib) s.pages.componentLibraries.push(lib)
savePackage(store, s) _savePage(s)
} }
return s return s
@ -646,7 +646,7 @@ const removeComponentLibrary = store => lib => {
s.pages.componentLibraries = filter(l => l !== lib)( s.pages.componentLibraries = filter(l => l !== lib)(
s.pages.componentLibraries s.pages.componentLibraries
) )
savePackage(store, s) _savePage(s)
return s return s
}) })
@ -655,7 +655,7 @@ const removeComponentLibrary = store => lib => {
const addStylesheet = store => stylesheet => { const addStylesheet = store => stylesheet => {
store.update(s => { store.update(s => {
s.pages.stylesheets.push(stylesheet) s.pages.stylesheets.push(stylesheet)
savePackage(store, s) _savePage(s)
return s return s
}) })
} }
@ -663,14 +663,14 @@ const addStylesheet = store => stylesheet => {
const removeStylesheet = store => stylesheet => { const removeStylesheet = store => stylesheet => {
store.update(s => { store.update(s => {
s.pages.stylesheets = filter(s => s !== stylesheet)(s.pages.stylesheets) s.pages.stylesheets = filter(s => s !== stylesheet)(s.pages.stylesheets)
savePackage(store, s) _savePage(s)
return s return s
}) })
} }
const refreshComponents = store => async () => { const refreshComponents = store => async () => {
const componentsAndGenerators = await api const componentsAndGenerators = await api
.get(`/_builder/api/${db.appname}/components`) .get(`/_builder/api/${appname}/components`)
.then(r => r.json()) .then(r => r.json())
const components = pipe(componentsAndGenerators.components, [ const components = pipe(componentsAndGenerators.components, [
@ -688,20 +688,24 @@ const refreshComponents = store => async () => {
}) })
} }
const savePackage = async (store, s) => { const _savePage = async s => {
const page = s.pages[s.currentPageName] const page = s.pages[s.currentPageName]
await api.post(`/_builder/api/${appname}/pages/${s.currentPageName}`, { await api.post(`/_builder/api/${appname}/pages/${s.currentPageName}`, {
page: { componentLibraries: s.pages.componentLibraries, ...page },
uiFunctions: "{'1234':() => 'test return'}",
screens: page.screens,
})
}
const saveBackend = async s => {
await api.post(`/_builder/api/${appname}/backend`, {
appDefinition: { appDefinition: {
hierarchy: s.hierarchy, hierarchy: s.hierarchy,
actions: s.actions, actions: s.actions,
triggers: s.triggers, triggers: s.triggers,
}, },
accessLevels: s.accessLevels, accessLevels: s.accessLevels,
page: { componentLibraries: s.pages.componentLibraries, ...page },
uiFunctions: "{'1234':() => 'test return'}",
props: page.props,
screens: page.screens,
}) })
} }
@ -731,7 +735,7 @@ const addChildComponent = store => componentName => {
newComponent.props newComponent.props
) )
savePackage(store, s) _savePage(s)
return s return s
}) })
@ -750,7 +754,7 @@ const setComponentProp = store => (name, value) => {
s.currentComponentInfo[name] = value s.currentComponentInfo[name] = value
s.currentFrontEndType === "page" s.currentFrontEndType === "page"
? savePackage(store, s, s.currentPreviewItem) ? _savePage(s, s.currentPreviewItem)
: _saveScreen(store, s, s.currentPreviewItem) : _saveScreen(store, s, s.currentPreviewItem)
s.currentComponentInfo = current_component s.currentComponentInfo = current_component
@ -770,8 +774,8 @@ const setComponentStyle = store => (type, name, value) => {
// save without messing with the store // save without messing with the store
s.currentFrontEndType === "page" s.currentFrontEndType === "page"
? savePackage(store, s, s.currentPreviewItem) ? _savePage(s)
: _save(s.appname, s.currentPreviewItem, store, s) : _saveScreenApi(s.currentPreviewItem, s)
return s return s
}) })
} }
@ -782,7 +786,7 @@ const setComponentCode = store => code => {
setCurrentScreenFunctions(s) setCurrentScreenFunctions(s)
// save without messing with the store // save without messing with the store
_save(s.appname, s.currentPreviewItem, store, s) _saveScreenApi(s.currentPreviewItem, s)
return s return s
}) })

View File

@ -29,14 +29,17 @@
[map(s => `<link rel="stylesheet" href="${s}"/>`), join("\n")] [map(s => `<link rel="stylesheet" href="${s}"/>`), join("\n")]
) )
$: appDefinition = { $: frontendDefinition = {
componentLibraries: $store.loadLibraryUrls(), componentLibraries: $store.loadLibraryUrls(),
props: page: $store.currentPreviewItem,
$store.currentPreviewItem && screens: [],
transform_component($store.currentPreviewItem, true),
hierarchy: $store.hierarchy,
appRootPath: "", appRootPath: "",
} }
$: backendDefinition = {
hierarchy: $store.hierarchy,
}
</script> </script>
<div class="component-container"> <div class="component-container">
@ -55,8 +58,9 @@
} }
<\/style> <\/style>
<\script> <\script>
window["##BUDIBASE_APPDEFINITION##"] = ${JSON.stringify(appDefinition)}; window["##BUDIBASE_FRONTEND_DEFINITION##"] = ${JSON.stringify(frontendDefinition)};
window["##BUDIBASE_UIFUNCTIONS"] = ${$store.currentScreenFunctions}; window["##BUDIBASE_BACKEND_DEFINITION##"] = ${JSON.stringify(backendDefinition)};
window["##BUDIBASE_FRONTEND_FUNCTIONS##"] = ${$store.currentScreenFunctions};
import('/_builder/budibase-client.esm.mjs') import('/_builder/budibase-client.esm.mjs')
.then(module => { .then(module => {

View File

@ -1,10 +1,10 @@
export const createCoreApp = (appDefinition, user) => { export const createCoreApp = (backendDefinition, user) => {
const app = { const app = {
datastore: null, datastore: null,
crypto: null, crypto: null,
publish: () => {}, publish: () => {},
hierarchy: appDefinition.hierarchy, hierarchy: backendDefinition.hierarchy,
actions: appDefinition.actions, actions: backendDefinition.actions,
user, user,
} }

View File

@ -2,8 +2,8 @@ import { createCoreApp } from "./createCoreApp"
import { getNew, getNewChild } from "../../../core/src/recordApi/getNew" import { getNew, getNewChild } from "../../../core/src/recordApi/getNew"
import { constructHierarchy } from "../../../core/src/templateApi/createNodes" import { constructHierarchy } from "../../../core/src/templateApi/createNodes"
export const createCoreApi = (appDefinition, user) => { export const createCoreApi = (backendDefinition, user) => {
const app = createCoreApp(appDefinition, user) const app = createCoreApp(backendDefinition, user)
return { return {
recordApi: { recordApi: {

View File

@ -11,22 +11,23 @@ import { screenRouter } from "./render/screenRouter"
export const createApp = ( export const createApp = (
document, document,
componentLibraries, componentLibraries,
appDefinition, frontendDefinition,
backendDefinition,
user, user,
uiFunctions, uiFunctions,
screens screens
) => { ) => {
const coreApi = createCoreApi(appDefinition, user) const coreApi = createCoreApi(backendDefinition, user)
appDefinition.hierarchy = coreApi.templateApi.constructHierarchy( backendDefinition.hierarchy = coreApi.templateApi.constructHierarchy(
appDefinition.hierarchy backendDefinition.hierarchy
) )
const pageStore = writable({ const pageStore = writable({
_bbuser: user, _bbuser: user,
}) })
const relativeUrl = url => const relativeUrl = url =>
appDefinition.appRootPath frontendDefinition.appRootPath
? appDefinition.appRootPath + "/" + trimSlash(url) ? frontendDefinition.appRootPath + "/" + trimSlash(url)
: url : url
const apiCall = method => (url, body) => const apiCall = method => (url, body) =>
@ -89,7 +90,7 @@ export const createApp = (
store, store,
document, document,
componentLibraries, componentLibraries,
appDefinition, frontendDefinition,
hydrate, hydrate,
uiFunctions, uiFunctions,
treeNode, treeNode,

View File

@ -10,8 +10,9 @@ export const loadBudibase = async ({
localStorage, localStorage,
uiFunctions, uiFunctions,
}) => { }) => {
const appDefinition = window["##BUDIBASE_APPDEFINITION##"] const backendDefinition = window["##BUDIBASE_BACKEND_DEFINITION##"]
const uiFunctionsFromWindow = window["##BUDIBASE_UIFUNCTIONS##"] const frontendDefinition = window["##BUDIBASE_FRONTEND_DEFINITION##"]
const uiFunctionsFromWindow = window["##BUDIBASE_FRONTEND_FUNCTIONS##"]
uiFunctions = uiFunctionsFromWindow || uiFunctions uiFunctions = uiFunctionsFromWindow || uiFunctions
const userFromStorage = localStorage.getItem("budibase:user") const userFromStorage = localStorage.getItem("budibase:user")
@ -26,16 +27,16 @@ export const loadBudibase = async ({
} }
const rootPath = const rootPath =
appDefinition.appRootPath === "" frontendDefinition.appRootPath === ""
? "" ? ""
: "/" + trimSlash(appDefinition.appRootPath) : "/" + trimSlash(frontendDefinition.appRootPath)
if (!componentLibraries) { if (!componentLibraries) {
const componentLibraryUrl = lib => rootPath + "/" + trimSlash(lib) const componentLibraryUrl = lib => rootPath + "/" + trimSlash(lib)
componentLibraries = {} componentLibraries = {}
for (let lib of appDefinition.componentLibraries) { for (let lib of frontendDefinition.componentLibraries) {
componentLibraries[lib.libName] = await import( componentLibraries[lib.libName] = await import(
componentLibraryUrl(lib.importPath) componentLibraryUrl(lib.importPath)
) )
@ -45,17 +46,18 @@ export const loadBudibase = async ({
componentLibraries[builtinLibName] = builtins(window) componentLibraries[builtinLibName] = builtins(window)
if (!page) { if (!page) {
page = appDefinition.page page = frontendDefinition.page
} }
if (!screens) { if (!screens) {
screens = appDefinition.screens screens = frontendDefinition.screens
} }
const { initialisePage, screenStore, pageStore, routeTo, rootNode } = createApp( const { initialisePage, screenStore, pageStore, routeTo, rootNode } = createApp(
window.document, window.document,
componentLibraries, componentLibraries,
appDefinition, frontendDefinition,
backendDefinition,
user, user,
uiFunctions || {}, uiFunctions || {},
screens screens

View File

@ -16,7 +16,7 @@ export const initialiseChildren = initialiseOpts => (
store, store,
componentLibraries, componentLibraries,
treeNode, treeNode,
appDefinition, frontendDefinition,
hydrate, hydrate,
onScreenSlotRendered, onScreenSlotRendered,
} = initialiseOpts } = initialiseOpts
@ -43,7 +43,7 @@ export const initialiseChildren = initialiseOpts => (
store, store,
childProps, childProps,
coreApi, coreApi,
appDefinition.appRootPath frontendDefinition.appRootPath
) )
const componentConstructor = componentLibraries[libName][componentName] const componentConstructor = componentLibraries[libName][componentName]

View File

@ -51,13 +51,16 @@ const autoAssignIds = (props, count = 0) => {
} }
const setAppDef = (window, page, screens) => { const setAppDef = (window, page, screens) => {
window["##BUDIBASE_APPDEFINITION##"] = { window["##BUDIBASE_FRONTEND_DEFINITION##"] = {
componentLibraries: [], componentLibraries: [],
page, page,
screens, screens,
hierarchy: {},
appRootPath: "", appRootPath: "",
} }
window["##BUDIBASE_BACKEND_DEFINITION##"] = {
hierarchy: {},
}
} }
const allLibs = window => ({ const allLibs = window => ({

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,8 @@
</style> </style>
<script src='/_master/clientAppDefinition.js'></script> <script src='/_master/clientFrontendDefinition.js'></script>
<script src='/_master/clientBackendDefinition.js'></script>
<script src='/_master/budibase-client.js'></script> <script src='/_master/budibase-client.js'></script>
<script> <script>
loadBudibase(); loadBudibase();

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,8 @@
</style> </style>
<script src='/_master/clientAppDefinition.js'></script> <script src='/_master/clientFrontendDefinition.js'></script>
<script src='/_master/clientBackendDefinition.js'></script>
<script src='/_master/budibase-client.js'></script> <script src='/_master/budibase-client.js'></script>
<script> <script>
loadBudibase(); loadBudibase();

File diff suppressed because one or more lines are too long

View File

@ -29,7 +29,8 @@
<script src='/clientAppDefinition.js'></script> <script src='/_master/clientFrontendDefinition.js'></script>
<script src='/_master/clientBackendDefinition.js'></script>
<script src='/budibase-client.js'></script> <script src='/budibase-client.js'></script>
<script> <script>
loadBudibase(); loadBudibase();

File diff suppressed because one or more lines are too long

View File

@ -17,7 +17,8 @@
<link rel='stylesheet' href='https://css-r-us.com/myawesomestyles.css'> <link rel='stylesheet' href='https://css-r-us.com/myawesomestyles.css'>
<link rel='stylesheet' href='///local.css'> <link rel='stylesheet' href='///local.css'>
<script src='/clientAppDefinition.js'></script> <script src='/_master/clientFrontendDefinition.js'></script>
<script src='/_master/clientBackendDefinition.js'></script>
<script src='/budibase-client.js'></script> <script src='/budibase-client.js'></script>
<script> <script>
loadBudibase(); loadBudibase();

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,8 @@
<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css'> <link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css'>
<script src='/testApp2/clientAppDefinition.js'></script> <script src='/_master/clientFrontendDefinition.js'></script>
<script src='/_master/clientBackendDefinition.js'></script>
<script src='/testApp2/budibase-client.js'></script> <script src='/testApp2/budibase-client.js'></script>
<script> <script>
loadBudibase(); loadBudibase();

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,8 @@
<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css'> <link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css'>
<script src='/testApp2/clientAppDefinition.js'></script> <script src='/_master/clientFrontendDefinition.js'></script>
<script src='/_master/clientBackendDefinition.js'></script>
<script src='/testApp2/budibase-client.js'></script> <script src='/testApp2/budibase-client.js'></script>
<script> <script>
loadBudibase(); loadBudibase();

View File

@ -11,9 +11,10 @@ const {
saveScreen, saveScreen,
renameScreen, renameScreen,
deleteScreen, deleteScreen,
savePagePackage, buildPage,
componentLibraryInfo, componentLibraryInfo,
listScreens, listScreens,
saveBackend,
} = require("../utilities/builder") } = require("../utilities/builder")
const builderPath = resolve(__dirname, "../builder") const builderPath = resolve(__dirname, "../builder")
@ -179,8 +180,17 @@ module.exports = (config, app) => {
ctx.body = info.generators ctx.body = info.generators
ctx.response.status = StatusCodes.OK ctx.response.status = StatusCodes.OK
}) })
.post("/_builder/api/:appname/backend", async ctx => {
await saveBackend(
config,
ctx.params.appname,
ctx.request.body.appDefinition,
ctx.request.body.accessLevels
)
ctx.response.status = StatusCodes.OK
})
.post("/_builder/api/:appname/pages/:pageName", async ctx => { .post("/_builder/api/:appname/pages/:pageName", async ctx => {
await savePagePackage( await buildPage(
config, config,
ctx.params.appname, ctx.params.appname,
ctx.params.pageName, ctx.params.pageName,

View File

@ -8,24 +8,27 @@ const {
copyFile, copyFile,
writeFile, writeFile,
readFile, readFile,
writeJSON,
} = require("fs-extra") } = require("fs-extra")
const { join, resolve, dirname } = require("path") const { join, resolve, dirname } = require("path")
const sqrl = require("squirrelly") const sqrl = require("squirrelly")
const { convertCssToFiles } = require("./convertCssToFiles") const { convertCssToFiles } = require("./convertCssToFiles")
const publicPath = require("./publicPath")
module.exports = async (config, appname, pkg) => { module.exports = async (config, appname, pageName, pkg) => {
const appPath = appPackageFolder(config, appname) const appPath = appPackageFolder(config, appname)
await convertCssToFiles(publicPath(appPath, pkg.pageName), pkg) await convertCssToFiles(publicPath(appPath, pageName), pkg)
await buildIndexHtml(config, appname, appPath, pkg) await buildIndexHtml(config, appname, pageName, appPath, pkg)
await buildClientAppDefinition(config, appname, pkg, appPath) await buildFrontendAppDefinition(config, appname, pageName, pkg, appPath)
await copyClientLib(appPath, pkg.pageName) await copyClientLib(appPath, pageName)
await savePageJson(appPath, pageName, pkg)
} }
const publicPath = (appPath, pageName) => join(appPath, "public", pageName)
const rootPath = (config, appname) => const rootPath = (config, appname) =>
config.useAppRootPath ? `/${appname}` : "" config.useAppRootPath ? `/${appname}` : ""
@ -42,8 +45,8 @@ const copyClientLib = async (appPath, pageName) => {
) )
} }
const buildIndexHtml = async (config, appname, appPath, pkg) => { const buildIndexHtml = async (config, appname, pageName, appPath, pkg) => {
const appPublicPath = publicPath(appPath, pkg.pageName) const appPublicPath = publicPath(appPath, pageName)
const appRootPath = rootPath(config, appname) const appRootPath = rootPath(config, appname)
const stylesheetUrl = s => const stylesheetUrl = s =>
@ -72,9 +75,9 @@ const buildIndexHtml = async (config, appname, appPath, pkg) => {
await writeFile(indexHtmlPath, indexHtml, { flag: "w+" }) await writeFile(indexHtmlPath, indexHtml, { flag: "w+" })
} }
const buildClientAppDefinition = async (config, appname, pkg) => { const buildFrontendAppDefinition = async (config, appname, pageName, pkg) => {
const appPath = appPackageFolder(config, appname) const appPath = appPackageFolder(config, appname)
const appPublicPath = publicPath(appPath, pkg.pageName) const appPublicPath = publicPath(appPath, pageName)
const appRootPath = rootPath(config, appname) const appRootPath = rootPath(config, appname)
const componentLibraries = [] const componentLibraries = []
@ -109,7 +112,7 @@ const buildClientAppDefinition = async (config, appname, pkg) => {
} }
} }
const filename = join(appPublicPath, "clientAppDefinition.js") const filename = join(appPublicPath, "clientFrontendDefinition.js")
if (pkg.page._css) { if (pkg.page._css) {
delete pkg.page._css delete pkg.page._css
@ -121,17 +124,32 @@ const buildClientAppDefinition = async (config, appname, pkg) => {
} }
} }
const clientAppDefObj = { const clientUiDefinition = JSON.stringify({
hierarchy: pkg.appDefinition.hierarchy,
componentLibraries: componentLibraries, componentLibraries: componentLibraries,
appRootPath: appRootPath, appRootPath: appRootPath,
page: pkg.page, page: pkg.page,
screens: pkg.screens, screens: pkg.screens,
} })
await writeFile( await writeFile(
filename, filename,
`window['##BUDIBASE_APPDEFINITION##'] = ${JSON.stringify(clientAppDefObj)}; `window['##BUDIBASE_FRONTEND_DEINITION##'] = ${clientUiDefinition};
window['##BUDIBASE_UIFUNCTIONS##'] = ${pkg.uiFunctions}` window['##BUDIBASE_FRONTEND_FUNCTIONS##'] = ${pkg.uiFunctions}`
) )
} }
const savePageJson = async (appPath, pageName, pkg) => {
const pageFile = join(appPath, "pages", pageName, "page.json")
if (pkg.page._css) {
delete pkg.page._css
}
if (pkg.page.name) {
delete pkg.page.name
}
await writeJSON(pageFile, pkg.page, {
spaces: 2,
})
}

View File

@ -0,0 +1,20 @@
const { readJSON, readdir } = require("fs-extra")
const { join } = require("path")
module.exports = async appPath => {
const pages = {}
const pageFolders = await readdir(join(appPath, "pages"))
for (let pageFolder of pageFolders) {
try {
pages[pageFolder] = await readJSON(
join(appPath, "pages", pageFolder, "page.json")
)
pages[pageFolder].name = pageFolder
} catch (_) {
// ignore error
}
}
return pages
}

View File

@ -3,7 +3,6 @@ const {
readJSON, readJSON,
writeJSON, writeJSON,
readdir, readdir,
stat,
ensureDir, ensureDir,
rename, rename,
unlink, unlink,
@ -11,14 +10,18 @@ const {
} = require("fs-extra") } = require("fs-extra")
const { join, dirname } = require("path") const { join, dirname } = require("path")
const { $ } = require("@budibase/core").common const { $ } = require("@budibase/core").common
const { keyBy, intersection, map, values, flatten } = require("lodash/fp") const { intersection, map, values, flatten } = require("lodash/fp")
const { merge } = require("lodash") const { merge } = require("lodash")
const { componentLibraryInfo } = require("./componentLibraryInfo") const { componentLibraryInfo } = require("./componentLibraryInfo")
const savePagePackage = require("./savePagePackage")
const buildPage = require("./buildPage") const buildPage = require("./buildPage")
const getPages = require("./getPages")
const listScreens = require("./listScreens")
const saveBackend = require("./saveBackend")
module.exports.savePagePackage = savePagePackage module.exports.buildPage = buildPage
module.exports.listScreens = listScreens
module.exports.saveBackend = saveBackend
const getAppDefinition = async appPath => const getAppDefinition = async appPath =>
await readJSON(`${appPath}/appDefinition.json`) await readJSON(`${appPath}/appDefinition.json`)
@ -45,31 +48,9 @@ module.exports.getApps = async (config, master) => {
return $(master.listApplications(), [map(a => a.name), intersection(dirs)]) return $(master.listApplications(), [map(a => a.name), intersection(dirs)])
} }
const getPages = async appPath => {
const pages = {}
const pageFolders = await readdir(join(appPath, "pages"))
for (let pageFolder of pageFolders) {
try {
pages[pageFolder] = await readJSON(
join(appPath, "pages", pageFolder, "page.json")
)
} catch (_) {
// ignore error
}
}
return pages
}
const screenPath = (appPath, pageName, name) => const screenPath = (appPath, pageName, name) =>
join(appPath, "pages", pageName, "screens", name + ".json") join(appPath, "pages", pageName, "screens", name + ".json")
module.exports.listScreens = async (config, appname, pagename) => {
const appPath = appPackageFolder(config, appname)
return keyBy("name")(await fetchscreens(appPath, pagename))
}
module.exports.saveScreen = async (config, appname, pagename, screen) => { module.exports.saveScreen = async (config, appname, pagename, screen) => {
const appPath = appPackageFolder(config, appname) const appPath = appPackageFolder(config, appname)
const compPath = screenPath(appPath, pagename, screen.name) const compPath = screenPath(appPath, pagename, screen.name)
@ -158,43 +139,4 @@ const getComponents = async (appPath, pages, lib) => {
return { components, generators } return { components, generators }
} }
const fetchscreens = async (appPath, pagename, relativePath = "") => {
const currentDir = join(appPath, "pages", pagename, "screens", relativePath)
const contents = await readdir(currentDir)
const screens = []
for (let item of contents) {
const itemRelativePath = join(relativePath, item)
const itemFullPath = join(currentDir, item)
const stats = await stat(itemFullPath)
if (stats.isFile()) {
if (!item.endsWith(".json")) continue
const component = await readJSON(itemFullPath)
component.name = itemRelativePath
.substring(0, itemRelativePath.length - 5)
.replace(/\\/g, "/")
component.props = component.props || {}
screens.push(component)
} else {
const childComponents = await fetchscreens(
appPath,
join(relativePath, item)
)
for (let c of childComponents) {
screens.push(c)
}
}
}
return screens
}
module.exports.getComponents = getComponents module.exports.getComponents = getComponents

View File

@ -27,7 +27,8 @@
{{ /if }} {{ /if }}
<script src='{{ appRootPath }}/clientAppDefinition.js'></script> <script src='{{ appRootPath }}/clientFrontendDefinition.js'></script>
<script src='{{ appRootPath }}/clientBackendDefinition.js'></script>
<script src='{{ appRootPath }}/budibase-client.js'></script> <script src='{{ appRootPath }}/budibase-client.js'></script>
<script> <script>
loadBudibase(); loadBudibase();

View File

@ -0,0 +1,48 @@
const { appPackageFolder } = require("../createAppPackage")
const { readJSON, readdir, stat } = require("fs-extra")
const { join } = require("path")
const { keyBy } = require("lodash/fp")
module.exports = async (config, appname, pagename) => {
const appPath = appPackageFolder(config, appname)
return keyBy("name")(await fetchscreens(appPath, pagename))
}
const fetchscreens = async (appPath, pagename, relativePath = "") => {
const currentDir = join(appPath, "pages", pagename, "screens", relativePath)
const contents = await readdir(currentDir)
const screens = []
for (let item of contents) {
const itemRelativePath = join(relativePath, item)
const itemFullPath = join(currentDir, item)
const stats = await stat(itemFullPath)
if (stats.isFile()) {
if (!item.endsWith(".json")) continue
const component = await readJSON(itemFullPath)
component.name = itemRelativePath
.substring(0, itemRelativePath.length - 5)
.replace(/\\/g, "/")
component.props = component.props || {}
screens.push(component)
} else {
const childComponents = await fetchscreens(
appPath,
join(relativePath, item)
)
for (let c of childComponents) {
screens.push(c)
}
}
}
return screens
}

View File

@ -0,0 +1,3 @@
const { join } = require("path")
module.exports = (appPath, pageName) => join(appPath, "public", pageName)

View File

@ -0,0 +1,28 @@
const getPages = require("./getPages")
const { appPackageFolder } = require("../createAppPackage")
const { writeJSON, writeFile } = require("fs-extra")
const { join } = require("path")
const publicPath = require("./publicPath")
module.exports = async (config, appname, appDefinition, accessLevels) => {
const appPath = appPackageFolder(config, appname)
await writeJSON(`${appPath}/appDefinition.json`, appDefinition, {
spaces: 2,
})
await writeJSON(`${appPath}/access_levels.json`, accessLevels, {
spaces: 2,
})
const pages = await getPages(appPath)
for (let pageName in pages) {
const pagePublicPath = publicPath(appPath, pageName)
const filename = join(pagePublicPath, "clientBackendDefinition.js")
const appDefString = JSON.stringify(appDefinition)
await writeFile(
filename,
`window['##BUDIBASE_FRONTEND_DEINITION##'] = ${appDefString};`
)
}
}

View File

@ -1,30 +0,0 @@
const { appPackageFolder } = require("../createAppPackage")
const { writeJSON } = require("fs-extra")
const { join } = require("path")
const buildPage = require("./buildPage")
module.exports = async (config, appname, pageName, pkg) => {
const appPath = appPackageFolder(config, appname)
pkg.pageName = pageName
await writeJSON(`${appPath}/appDefinition.json`, pkg.appDefinition, {
spaces: 2,
})
await writeJSON(`${appPath}/access_levels.json`, pkg.accessLevels, {
spaces: 2,
})
await buildPage(config, appname, pkg)
const pageFile = join(appPath, "pages", pageName, "page.json")
if (pkg.page._css) {
delete pkg.page._css
}
await writeJSON(pageFile, pkg.page, {
spaces: 2,
})
}

File diff suppressed because one or more lines are too long