Browse Source

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>
master
Michael Shanks 7 years ago
committed by GitHub
parent
commit
34b957f331
  1. 60
      packages/builder/src/builderStore/store.js
  2. 18
      packages/builder/src/userInterface/CurrentItemPreview.svelte
  3. 6
      packages/client/src/core/createCoreApp.js
  4. 4
      packages/client/src/core/index.js
  5. 15
      packages/client/src/createApp.js
  6. 18
      packages/client/src/index.js
  7. 4
      packages/client/src/render/initialiseChildren.js
  8. 7
      packages/client/tests/testAppDef.js
  9. 4269
      packages/server/appPackages/_master/public/main/budibase-client.js
  10. 2
      packages/server/appPackages/_master/public/main/budibase-client.js.map
  11. 3
      packages/server/appPackages/_master/public/main/index.html
  12. 4269
      packages/server/appPackages/_master/public/unauthenticated/budibase-client.js
  13. 2
      packages/server/appPackages/_master/public/unauthenticated/budibase-client.js.map
  14. 3
      packages/server/appPackages/_master/public/unauthenticated/index.html
  15. 3435
      packages/server/appPackages/testApp/public/main/budibase-client.js
  16. 2
      packages/server/appPackages/testApp/public/main/budibase-client.js.map
  17. 3
      packages/server/appPackages/testApp/public/main/index.html
  18. 4269
      packages/server/appPackages/testApp/public/unauthenticated/budibase-client.js
  19. 2
      packages/server/appPackages/testApp/public/unauthenticated/budibase-client.js.map
  20. 3
      packages/server/appPackages/testApp/public/unauthenticated/index.html
  21. 4269
      packages/server/appPackages/testApp2/public/main/budibase-client.js
  22. 2
      packages/server/appPackages/testApp2/public/main/budibase-client.js.map
  23. 3
      packages/server/appPackages/testApp2/public/main/index.html
  24. 4269
      packages/server/appPackages/testApp2/public/unauthenticated/budibase-client.js
  25. 2
      packages/server/appPackages/testApp2/public/unauthenticated/budibase-client.js.map
  26. 3
      packages/server/appPackages/testApp2/public/unauthenticated/index.html
  27. 14
      packages/server/middleware/routers.js
  28. 50
      packages/server/utilities/builder/buildPage.js
  29. 20
      packages/server/utilities/builder/getPages.js
  30. 72
      packages/server/utilities/builder/index.js
  31. 3
      packages/server/utilities/builder/index.template.html
  32. 48
      packages/server/utilities/builder/listScreens.js
  33. 3
      packages/server/utilities/builder/publicPath.js
  34. 28
      packages/server/utilities/builder/saveBackend.js
  35. 30
      packages/server/utilities/builder/savePagePackage.js
  36. 2
      packages/standard-components/dist/generators.js

60
packages/builder/src/builderStore/store.js

@ -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
}) })

18
packages/builder/src/userInterface/CurrentItemPreview.svelte

@ -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 => {

6
packages/client/src/core/createCoreApp.js

@ -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,
} }

4
packages/client/src/core/index.js

@ -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: {

15
packages/client/src/createApp.js

@ -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,

18
packages/client/src/index.js

@ -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

4
packages/client/src/render/initialiseChildren.js

@ -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]

7
packages/client/tests/testAppDef.js

@ -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 => ({

4269
packages/server/appPackages/_master/public/main/budibase-client.js

File diff suppressed because it is too large

2
packages/server/appPackages/_master/public/main/budibase-client.js.map

File diff suppressed because one or more lines are too long

3
packages/server/appPackages/_master/public/main/index.html

@ -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();

4269
packages/server/appPackages/_master/public/unauthenticated/budibase-client.js

File diff suppressed because it is too large

2
packages/server/appPackages/_master/public/unauthenticated/budibase-client.js.map

File diff suppressed because one or more lines are too long

3
packages/server/appPackages/_master/public/unauthenticated/index.html

@ -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();

3435
packages/server/appPackages/testApp/public/main/budibase-client.js

File diff suppressed because it is too large

2
packages/server/appPackages/testApp/public/main/budibase-client.js.map

File diff suppressed because one or more lines are too long

3
packages/server/appPackages/testApp/public/main/index.html

@ -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();

4269
packages/server/appPackages/testApp/public/unauthenticated/budibase-client.js

File diff suppressed because it is too large

2
packages/server/appPackages/testApp/public/unauthenticated/budibase-client.js.map

File diff suppressed because one or more lines are too long

3
packages/server/appPackages/testApp/public/unauthenticated/index.html

@ -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();

4269
packages/server/appPackages/testApp2/public/main/budibase-client.js

File diff suppressed because it is too large

2
packages/server/appPackages/testApp2/public/main/budibase-client.js.map

File diff suppressed because one or more lines are too long

3
packages/server/appPackages/testApp2/public/main/index.html

@ -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();

4269
packages/server/appPackages/testApp2/public/unauthenticated/budibase-client.js

File diff suppressed because it is too large

2
packages/server/appPackages/testApp2/public/unauthenticated/budibase-client.js.map

File diff suppressed because one or more lines are too long

3
packages/server/appPackages/testApp2/public/unauthenticated/index.html

@ -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();

14
packages/server/middleware/routers.js

@ -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,

50
packages/server/utilities/builder/buildPage.js

@ -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,
})
}

20
packages/server/utilities/builder/getPages.js

@ -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
}

72
packages/server/utilities/builder/index.js

@ -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

3
packages/server/utilities/builder/index.template.html

@ -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();

48
packages/server/utilities/builder/listScreens.js

@ -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
}

3
packages/server/utilities/builder/publicPath.js

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

28
packages/server/utilities/builder/saveBackend.js

@ -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};`
)
}
}

30
packages/server/utilities/builder/savePagePackage.js

@ -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,
})
}

2
packages/standard-components/dist/generators.js

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save