Browse Source

Merge pull request #130 from shogunpurple/demo-prep

eslint errors fixed for CI
pull/131/head
Michael Shanks 7 years ago
committed by GitHub
parent
commit
4da68f1aeb
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      .eslintrc.json
  2. 1
      .github/workflows/budibase_ci.yml
  3. 5
      .prettierignore
  4. 1
      package.json
  5. 28
      packages/builder/rollup.config.js
  6. 1
      packages/builder/src/App.svelte
  7. 7
      packages/builder/src/accessLevels/AccessLevelsRoot.svelte
  8. 23
      packages/builder/src/actionsAndTriggers/ActionView.svelte
  9. 28
      packages/builder/src/actionsAndTriggers/Actions.svelte
  10. 5
      packages/builder/src/actionsAndTriggers/TriggerView.svelte
  11. 41
      packages/builder/src/builderStore/buildStateOrigins.js
  12. 6
      packages/builder/src/builderStore/index.js
  13. 10
      packages/builder/src/builderStore/loadComponentLibraries.js
  14. 2
      packages/builder/src/builderStore/store.js
  15. 2
      packages/builder/src/common/Dropdown.svelte
  16. 4
      packages/builder/src/common/DropdownButton.svelte
  17. 4
      packages/builder/src/common/PlusButton.svelte
  18. 2
      packages/builder/src/common/core.js
  19. 4
      packages/builder/src/database/ActionsHeader.svelte
  20. 2
      packages/builder/src/database/FieldView.svelte
  21. 21
      packages/builder/src/database/IndexView.svelte
  22. 4
      packages/builder/src/database/RecordView.svelte
  23. 1
      packages/builder/src/main.js
  24. 9
      packages/builder/src/nav/NavItem.svelte
  25. 59
      packages/builder/src/userInterface/ComponentSelectionList.svelte
  26. 24
      packages/builder/src/userInterface/ComponentsHierarchy.svelte
  27. 6
      packages/builder/src/userInterface/ComponentsHierarchyChildren.svelte
  28. 10
      packages/builder/src/userInterface/ComponentsPaneSwitcher.svelte
  29. 4
      packages/builder/src/userInterface/EventsEditor/EventEditorModal.svelte
  30. 2
      packages/builder/src/userInterface/EventsEditor/StateBindingCascader.svelte
  31. 20
      packages/builder/src/userInterface/MasterLayout.svelte
  32. 29
      packages/builder/src/userInterface/NewScreen.svelte
  33. 14
      packages/builder/src/userInterface/PropertyCascader/PropertyCascader.svelte
  34. 2
      packages/builder/src/userInterface/PropertyCascader/index.js
  35. 36
      packages/builder/src/userInterface/PropsView.svelte
  36. 2
      packages/builder/src/userInterface/StateBindingControl.svelte
  37. 2
      packages/builder/src/userInterface/pagesParsing/findDependencies.js
  38. 2
      packages/builder/src/userInterface/pagesParsing/searchComponents.js
  39. 3
      packages/builder/src/userInterface/pagesParsing/types.js
  40. 2
      packages/builder/src/userInterface/pagesParsing/validatePages.js
  41. 56
      packages/builder/tests/buildStateOrigins.spec.js
  42. 2
      packages/builder/tests/createProps.spec.js
  43. 2
      packages/cli/src/commands/new/appPackageTemplate/plugins.js
  44. 2
      packages/cli/src/common.js
  45. 1
      packages/client/rollup.config.js
  46. 2
      packages/client/scripts/publishDev.js
  47. 33
      packages/client/src/index.js
  48. 2
      packages/client/src/render/attachChildren.js
  49. 13
      packages/client/src/state/parseBinding.js
  50. 79
      packages/client/src/state/stateManager/index.js
  51. 2
      packages/core/src/indexing/allIds.js
  52. 1
      packages/core/src/indexing/sharding.js
  53. 2
      packages/core/src/recordApi/load.js
  54. 2
      packages/core/src/recordApi/recordInfo.js
  55. 4
      packages/core/src/recordApi/uploadFile.js
  56. 2
      packages/core/src/templateApi/deleteNodes.js
  57. 6
      packages/core/test/apiWrapper.spec.js
  58. 2
      packages/core/test/authApi.authenticate.spec.js
  59. 8
      packages/core/test/recordApi.files.spec.js
  60. 1
      packages/datastores/config.js
  61. 11
      packages/datastores/config.template.js
  62. 11
      packages/datastores/datastores/azure-blob.js
  63. 2
      packages/datastores/index.js
  64. 6
      packages/datastores/tests/diagnosticPlugin.js
  65. 1
      packages/datastores/tests/index.js
  66. 31
      packages/datastores/tests/records.js
  67. 1
      packages/datastores/tests/setup.js
  68. 1
      packages/materialdesign-components/rollup.config.js
  69. 2
      packages/materialdesign-components/rollup.testconfig.js
  70. 66
      packages/materialdesign-components/src/Checkbox/CheckboxGroup.svelte
  71. 7
      packages/materialdesign-components/src/Checkbox/index.js
  72. 44
      packages/materialdesign-components/src/ClassBuilder.js
  73. 38
      packages/materialdesign-components/src/Common/Formfield.svelte
  74. 14
      packages/materialdesign-components/src/Common/FormfieldStore.js
  75. 8
      packages/materialdesign-components/src/Common/Icon.svelte
  76. 8
      packages/materialdesign-components/src/Common/Label.svelte
  77. 15
      packages/materialdesign-components/src/Datatable/Datatable.svelte
  78. 13
      packages/materialdesign-components/src/Datatable/DatatableBody.svelte
  79. 3
      packages/materialdesign-components/src/Datatable/DatatableCell.svelte
  80. 12
      packages/materialdesign-components/src/Datatable/DatatableHead.svelte
  81. 28
      packages/materialdesign-components/src/Datatable/DatatableRow.svelte
  82. 38
      packages/materialdesign-components/src/Menu/Menu.svelte
  83. 4
      packages/materialdesign-components/src/Menu/index.js
  84. 6
      packages/materialdesign-components/src/Radiobutton/index.js
  85. 2
      packages/materialdesign-components/src/Test/createApp.js
  86. 6
      packages/materialdesign-components/src/Textfield/Textfield.svelte
  87. 2
      packages/materialdesign-components/src/Textfield/index.js
  88. 26
      packages/materialdesign-components/src/Typography/index.js
  89. 2
      packages/server/appPackages/testApp/plugins.js
  90. 54511
      packages/server/appPackages/testApp/public/main/budibase-client.js
  91. 2
      packages/server/appPackages/testApp/public/main/budibase-client.js.map
  92. 2
      packages/server/appPackages/testApp/public/main/clientFrontendDefinition.js
  93. 21
      packages/server/appPackages/testApp/public/main/index.html
  94. 2
      packages/server/appPackages/testApp2/plugins.js
  95. 64
      packages/server/initialise/createInstanceDb.js
  96. 40
      packages/server/initialise/createMasterDb.js
  97. 14
      packages/server/initialise/initialiseRuntimePackages.js
  98. 6
      packages/server/middleware/routers.js
  99. 6
      packages/server/middleware/session.js
  100. 1
      packages/server/tests/builder.spec.js

6
.eslintrc.json

@ -5,11 +5,13 @@
"jest": true, "jest": true,
"node": true "node": true
}, },
"parser": "babel-eslint",
"parserOptions": { "parserOptions": {
"ecmaVersion": 2019, "ecmaVersion": 2019,
"sourceType": "module" "sourceType": "module",
"allowImportExportEverywhere": true
}, },
"ignorePatterns": ["node_modules", "dist", "public"], "ignorePatterns": ["node_modules", "dist", "public", "*.spec.js", "bundle.js"],
"plugins": ["prettier", "svelte3"], "plugins": ["prettier", "svelte3"],
"extends": ["eslint:recommended"], "extends": ["eslint:recommended"],
"overrides": [ "overrides": [

1
.github/workflows/budibase_ci.yml

@ -27,6 +27,7 @@ jobs:
node-version: ${{ matrix.node-version }} node-version: ${{ matrix.node-version }}
- run: yarn - run: yarn
- run: yarn lint - run: yarn lint
- run: yarn bootstrap
- run: yarn build - run: yarn build
- run: yarn test - run: yarn test
env: env:

5
.prettierignore

@ -0,0 +1,5 @@
packages/builder/src/userInterface/CurrentItemPreview.svelte
public
dist
packages/server/builder
**/*.spec.js

1
package.json

@ -2,6 +2,7 @@
"name": "root", "name": "root",
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"babel-eslint": "^10.0.3",
"eslint": "^6.8.0", "eslint": "^6.8.0",
"eslint-plugin-prettier": "^3.1.2", "eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-svelte3": "^2.7.3", "eslint-plugin-svelte3": "^2.7.3",

28
packages/builder/rollup.config.js

@ -16,23 +16,17 @@ const _builderProxy = proxy("/_builder", {
pathRewrite: { "^/_builder": "" }, pathRewrite: { "^/_builder": "" },
}) })
const apiProxy = proxy( const apiProxy = proxy(["/_builder/api/**", "/_builder/**/componentlibrary"], {
[ target,
"/_builder/api/**", logLevel: "debug",
"/_builder/**/componentlibrary" changeOrigin: true,
], cookieDomainRewrite: true,
{ onProxyReq(proxyReq) {
target, if (proxyReq.getHeader("origin")) {
logLevel: "debug", proxyReq.setHeader("origin", target)
changeOrigin: true, }
cookieDomainRewrite: true, },
onProxyReq(proxyReq) { })
if (proxyReq.getHeader("origin")) {
proxyReq.setHeader("origin", target)
}
},
}
)
const production = !process.env.ROLLUP_WATCH const production = !process.env.ROLLUP_WATCH

1
packages/builder/src/App.svelte

@ -61,5 +61,4 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
</style> </style>

7
packages/builder/src/accessLevels/AccessLevelsRoot.svelte

@ -82,11 +82,10 @@
</table> </table>
{:else}(no actions added){/if} {:else}(no actions added){/if}
<Modal <Modal
onClosed={() => isEditing = false} onClosed={() => (isEditing = false)}
bind:isOpen={isEditing} bind:isOpen={isEditing}
title={isEditing ? "Edit Access Level" : "Create Access Level"} title={isEditing ? 'Edit Access Level' : 'Create Access Level'}>
>
{#if isEditing} {#if isEditing}
<AccessLevelView <AccessLevelView
level={editingLevel} level={editingLevel}

23
packages/builder/src/actionsAndTriggers/ActionView.svelte

@ -16,10 +16,10 @@
let optValue = "" let optValue = ""
let clonedAction = cloneDeep(action) let clonedAction = cloneDeep(action)
let initialOptions = pipe( let initialOptions = pipe(action.initialOptions, [
action.initialOptions, keys,
[keys, map(k => ({ key: k, value: action.initialOptions[k] }))] map(k => ({ key: k, value: action.initialOptions[k] })),
) ])
let errors = [] let errors = []
const addNewOption = () => { const addNewOption = () => {
@ -44,26 +44,17 @@
const removeOption = opt => { const removeOption = opt => {
if (opt) { if (opt) {
delete clonedAction.initialOptions[opt.key] delete clonedAction.initialOptions[opt.key]
initialOptions = pipe( initialOptions = pipe(initialOptions, [filter(o => o.key !== opt.key)])
initialOptions,
[filter(o => o.key !== opt.key)]
)
} }
} }
const save = () => { const save = () => {
const newActionsList = [ const newActionsList = [
...pipe( ...pipe(allActions, [filter(a => a !== action)]),
allActions,
[filter(a => a !== action)]
),
clonedAction, clonedAction,
] ]
errors = pipe( errors = pipe(newActionsList, [validateActions, map(e => e.error)])
newActionsList,
[validateActions, map(e => e.error)]
)
if (errors.length === 0) onFinished(clonedAction) if (errors.length === 0) onFinished(clonedAction)
} }

28
packages/builder/src/actionsAndTriggers/Actions.svelte

@ -19,26 +19,20 @@
let actionsArray = [] let actionsArray = []
store.subscribe(s => { store.subscribe(s => {
actionsArray = pipe( actionsArray = pipe(s.actions, [keys, map(k => s.actions[k])])
s.actions,
[keys, map(k => s.actions[k])]
)
}) })
let getDefaultOptionsHtml = defaultOptions => let getDefaultOptionsHtml = defaultOptions =>
pipe( pipe(defaultOptions, [
defaultOptions, keys,
[ map(
keys, k =>
map( `<span style="color:var(--slate)">${k}: </span>${JSON.stringify(
k => defaultOptions[k]
`<span style="color:var(--slate)">${k}: </span>${JSON.stringify( )}`
defaultOptions[k] ),
)}` join("<br>"),
), ])
join("<br>"),
]
)
let actionEditingFinished = action => { let actionEditingFinished = action => {
if (action) { if (action) {

5
packages/builder/src/actionsAndTriggers/TriggerView.svelte

@ -22,10 +22,7 @@
let cancel = () => onFinished() let cancel = () => onFinished()
let save = () => { let save = () => {
const newTriggersList = [ const newTriggersList = [
...pipe( ...pipe(allTriggers, [filter(t => t !== trigger)]),
allTriggers,
[filter(t => t !== trigger)]
),
clonedTrigger, clonedTrigger,
] ]

41
packages/builder/src/builderStore/buildStateOrigins.js

@ -1,27 +1,28 @@
/** /**
* buildStateOrigins * buildStateOrigins
* *
* Builds an object that details all the bound state in the application, and what updates it. * Builds an object that details all the bound state in the application, and what updates it.
* *
* @param screenDefinition - the screen definition metadata. * @param screenDefinition - the screen definition metadata.
* @returns {Object} an object with the client state values and how they are managed. * @returns {Object} an object with the client state values and how they are managed.
*/ */
export const buildStateOrigins = screenDefinition => { export const buildStateOrigins = screenDefinition => {
const origins = {}; const origins = {}
function traverse(propValue) { function traverse(propValue) {
for (let key in propValue) { for (let key in propValue) {
if (!Array.isArray(propValue[key])) continue; if (!Array.isArray(propValue[key])) continue
if (key === "_children") propValue[key].forEach(traverse); if (key === "_children") propValue[key].forEach(traverse)
for (let element of propValue[key]) { for (let element of propValue[key]) {
if (element["##eventHandlerType"] === "Set State") origins[element.parameters.path] = element; if (element["##eventHandlerType"] === "Set State")
} origins[element.parameters.path] = element
} }
} }
}
traverse(screenDefinition.props); traverse(screenDefinition.props)
return origins; return origins
}; }

6
packages/builder/src/builderStore/index.js

@ -1,10 +1,7 @@
import { createPackage } from "./createPackage"
import getStore from "./store" import getStore from "./store"
export const store = getStore() export const store = getStore()
export const createNewPackage = () => createPackage(packageInfo, store)
export const initialise = async () => { export const initialise = async () => {
try { try {
setupRouter(store) setupRouter(store)
@ -17,8 +14,7 @@ export const initialise = async () => {
const setupRouter = writable => { const setupRouter = writable => {
const pushState = history.pushState const pushState = history.pushState
history.pushState = () => { history.pushState = () => {
pushState.apply(history, arguments) pushState.apply(history, [writable])
//fireEvents('pushState', arguments);
writable.initialise() writable.initialise()
} }
window.addEventListener("hashchange", () => { window.addEventListener("hashchange", () => {

10
packages/builder/src/builderStore/loadComponentLibraries.js

@ -5,7 +5,6 @@ export const loadLibs = async (appName, appPackage) => {
const allLibraries = {} const allLibraries = {}
for (let lib of libsFromPages(appPackage.pages)) { for (let lib of libsFromPages(appPackage.pages)) {
const libModule = await import(makeLibraryUrl(appName, lib)) const libModule = await import(makeLibraryUrl(appName, lib))
allLibraries[lib] = libModule allLibraries[lib] = libModule
} }
@ -31,10 +30,5 @@ export const loadLib = async (appName, lib, allLibs) => {
export const makeLibraryUrl = (appName, lib) => export const makeLibraryUrl = (appName, lib) =>
`/_builder/${appName}/componentlibrary?lib=${encodeURI(lib)}` `/_builder/${appName}/componentlibrary?lib=${encodeURI(lib)}`
export const libsFromPages = pages => pipe(pages, [ export const libsFromPages = pages =>
values, pipe(pages, [values, map(p => p.componentLibraries), flatten, uniq])
map(p => p.componentLibraries),
flatten,
uniq
])

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

@ -763,7 +763,7 @@ const addChildComponent = store => (componentToAdd, presetName) => {
state.currentFrontEndType === "page" state.currentFrontEndType === "page"
? _savePage(state) ? _savePage(state)
: _saveScreenApi(state.currentPreviewItem, state) : _saveScreenApi(state.currentPreviewItem, state)
state.currentComponentInfo = newComponent.props state.currentComponentInfo = newComponent.props
return state return state

2
packages/builder/src/common/Dropdown.svelte

@ -1,6 +1,6 @@
<script> <script>
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
import Select from "../common/Select.svelte"; import Select from "../common/Select.svelte"
export let selected export let selected
export let label export let label

4
packages/builder/src/common/DropdownButton.svelte

@ -17,7 +17,9 @@
class="dropdown-content" class="dropdown-content"
style="display: {isDroppedDown ? 'inline-block' : 'none'}"> style="display: {isDroppedDown ? 'inline-block' : 'none'}">
{#each actions as action} {#each actions as action}
<div class="budibase__nav-item" on:click={action.onclick}>{action.label}</div> <div class="budibase__nav-item" on:click={action.onclick}>
{action.label}
</div>
{/each} {/each}
</div> </div>

4
packages/builder/src/common/PlusButton.svelte

@ -1,7 +1,5 @@
<button on:click> <button on:click>
<slot> <slot>+</slot>
+
</slot>
</button> </button>
<style> <style>

2
packages/builder/src/common/core.js

@ -4,7 +4,7 @@ import {
getTemplateApi, getTemplateApi,
getAuthApi, getAuthApi,
} from "../../../core/src" } from "../../../core/src"
import { find, filter, includes, keyBy, some, flatten, map } from "lodash/fp" import { find, filter, keyBy, flatten, map } from "lodash/fp"
import { generateSchema } from "../../../core/src/indexing/indexSchemaCreator" import { generateSchema } from "../../../core/src/indexing/indexSchemaCreator"

4
packages/builder/src/database/ActionsHeader.svelte

@ -39,9 +39,7 @@
{/if} {/if}
<Modal onClosed={() => (confirmDelete = false)} bind:isOpen={confirmDelete}> <Modal onClosed={() => (confirmDelete = false)} bind:isOpen={confirmDelete}>
<span> <span>Are you sure you want to delete {$store.currentNode.name}?</span>
Are you sure you want to delete {$store.currentNode.name}?
</span>
<div class="uk-modal-footer uk-text-right"> <div class="uk-modal-footer uk-text-right">
<ButtonGroup> <ButtonGroup>
<ActionButton alert on:click={deleteCurrentNode}>Yes</ActionButton> <ActionButton alert on:click={deleteCurrentNode}>Yes</ActionButton>

2
packages/builder/src/database/FieldView.svelte

@ -152,4 +152,4 @@
</ActionButton> </ActionButton>
</ButtonGroup> </ButtonGroup>
</div> </div>
</div> </div>

21
packages/builder/src/database/IndexView.svelte

@ -14,18 +14,15 @@
store.subscribe($store => { store.subscribe($store => {
index = $store.currentNode index = $store.currentNode
indexableRecords = pipe( indexableRecords = pipe($store.hierarchy, [
$store.hierarchy, hierarchyFunctions.getFlattenedHierarchy,
[ filter(hierarchyFunctions.isDecendant(index.parent())),
hierarchyFunctions.getFlattenedHierarchy, filter(hierarchyFunctions.isRecord),
filter(hierarchyFunctions.isDecendant(index.parent())), map(n => ({
filter(hierarchyFunctions.isRecord), node: n,
map(n => ({ isallowed: some(id => n.nodeId === id)(index.allowedRecordNodeIds),
node: n, })),
isallowed: some(id => n.nodeId === id)(index.allowedRecordNodeIds), ])
})),
]
)
}) })
const toggleAllowedRecord = record => { const toggleAllowedRecord = record => {

4
packages/builder/src/database/RecordView.svelte

@ -99,7 +99,9 @@
<Textbox label="Name:" bind:text={record.name} on:change={nameChanged} /> <Textbox label="Name:" bind:text={record.name} on:change={nameChanged} />
{#if !record.isSingle} {#if !record.isSingle}
<Textbox label="Collection Name:" bind:text={record.collectionName} /> <Textbox label="Collection Name:" bind:text={record.collectionName} />
<Textbox label="Estimated Record Count:" bind:text={record.estimatedRecordCount} /> <Textbox
label="Estimated Record Count:"
bind:text={record.estimatedRecordCount} />
{/if} {/if}
<div class="recordkey">{record.nodeKey()}</div> <div class="recordkey">{record.nodeKey()}</div>

1
packages/builder/src/main.js

@ -13,6 +13,7 @@ import "uikit/dist/js/uikit.min.js"
import "codemirror/lib/codemirror.css" import "codemirror/lib/codemirror.css"
import "codemirror/theme/monokai.css" import "codemirror/theme/monokai.css"
/* eslint-disable */
const app = new App({ const app = new App({
target: document.getElementById("app"), target: document.getElementById("app"),
}) })

9
packages/builder/src/nav/NavItem.svelte

@ -14,10 +14,15 @@
const setActive = () => store.setActiveNav(name) const setActive = () => store.setActiveNav(name)
</script> </script>
<div class="budibase__nav-item backend-nav-item" class:selected={navActive} on:click={setActive}>{label}</div> <div
class="budibase__nav-item backend-nav-item"
class:selected={navActive}
on:click={setActive}>
{label}
</div>
<style> <style>
.backend-nav-item { .backend-nav-item {
padding-left: 25px; padding-left: 25px;
} }
</style> </style>

59
packages/builder/src/userInterface/ComponentSelectionList.svelte

@ -1,13 +1,26 @@
<script> <script>
import { splitName } from "./pagesParsing/splitRootComponentName.js" import { splitName } from "./pagesParsing/splitRootComponentName.js"
import { store } from "../builderStore" import { store } from "../builderStore"
import { find, sortBy, groupBy, values, filter, map, uniqBy, flatten } from "lodash/fp" import {
find,
sortBy,
groupBy,
values,
filter,
map,
uniqBy,
flatten,
} from "lodash/fp"
import { ImageIcon, InputIcon, LayoutIcon } from "../common/Icons/" import { ImageIcon, InputIcon, LayoutIcon } from "../common/Icons/"
import Select from "../common/Select.svelte" import Select from "../common/Select.svelte"
import Button from "../common/PlusButton.svelte" import Button from "../common/PlusButton.svelte"
import ConfirmDialog from "../common/ConfirmDialog.svelte" import ConfirmDialog from "../common/ConfirmDialog.svelte"
import { getRecordNodes, getIndexNodes, getIndexSchema, pipe } from "../common/core" import {
getRecordNodes,
getIndexNodes,
getIndexSchema,
pipe,
} from "../common/core"
export let toggleTab export let toggleTab
@ -27,7 +40,7 @@
flatten, flatten,
filter(t => !$store.components.some(c => c.name === t.component)), filter(t => !$store.components.some(c => c.name === t.component)),
map(t => ({ name: splitName(t.component).componentName, template: t })), map(t => ({ name: splitName(t.component).componentName, template: t })),
uniqBy(t => t.name) uniqBy(t => t.name),
]) ])
const addRootComponent = (component, allComponents) => { const addRootComponent = (component, allComponents) => {
@ -62,18 +75,20 @@
records: getRecordNodes(hierarchy), records: getRecordNodes(hierarchy),
indexes: getIndexNodes(hierarchy), indexes: getIndexNodes(hierarchy),
helpers: { helpers: {
indexSchema: getIndexSchema(hierarchy) indexSchema: getIndexSchema(hierarchy),
} },
} }
templateInstances = libraryModules[libName][componentName](templateOptions) templateInstances = libraryModules[libName][componentName](templateOptions)
if(!templateInstances || templateInstances.length === 0) return if (!templateInstances || templateInstances.length === 0) return
selectedTemplateInstance = templateInstances[0].name selectedTemplateInstance = templateInstances[0].name
selectTemplateDialog.show() selectTemplateDialog.show()
} }
const onTemplateInstanceChosen = () => { const onTemplateInstanceChosen = () => {
selectedComponent = null selectedComponent = null
const instance = templateInstances.find(i => i.name === selectedTemplateInstance) const instance = templateInstances.find(
i => i.name === selectedTemplateInstance
)
store.addTemplatedComponent(instance.props) store.addTemplatedComponent(instance.props)
toggleTab() toggleTab()
} }
@ -81,7 +96,8 @@
function generate_components_list(components) { function generate_components_list(components) {
return ($store.currentFrontEndType === "page" return ($store.currentFrontEndType === "page"
? $store.builtins.concat(components) ? $store.builtins.concat(components)
: components).concat(standaloneTemplates) : components
).concat(standaloneTemplates)
} }
$: { $: {
@ -96,15 +112,12 @@
} }
$: componentLibrary = componentLibraries.find(l => l.libName === selectedLib) $: componentLibrary = componentLibraries.find(l => l.libName === selectedLib)
</script> </script>
<div class="root"> <div class="root">
<Select on:change={e => selectedLib = e.target.value}> <Select on:change={e => (selectedLib = e.target.value)}>
{#each componentLibraries as lib} {#each componentLibraries as lib}
<option value={lib.libName}> <option value={lib.libName}>{lib.libName}</option>
{lib.libName}
</option>
{/each} {/each}
</Select> </Select>
@ -136,9 +149,7 @@
{#if componentLibrary} {#if componentLibrary}
{#each generate_components_list(componentLibrary.components) as component} {#each generate_components_list(componentLibrary.components) as component}
<div class="component-container"> <div class="component-container">
<div <div class="component" on:click={() => onComponentChosen(component)}>
class="component"
on:click={() => onComponentChosen(component)}>
<div class="name">{splitName(component.name).componentName}</div> <div class="name">{splitName(component.name).componentName}</div>
{#if (component.presets || templatesByComponent[component.name]) && component.name === selectedComponent} {#if (component.presets || templatesByComponent[component.name]) && component.name === selectedComponent}
<ul class="preset-menu"> <ul class="preset-menu">
@ -152,7 +163,9 @@
{/each} {/each}
{/if} {/if}
{#if templatesByComponent[component.name]} {#if templatesByComponent[component.name]}
<span>{splitName(component.name).componentName} Templates</span> <span>
{splitName(component.name).componentName} Templates
</span>
{#each templatesByComponent[component.name] as template} {#each templatesByComponent[component.name] as template}
<li <li
on:click|stopPropagation={() => onTemplateChosen(template)}> on:click|stopPropagation={() => onTemplateChosen(template)}>
@ -180,18 +193,21 @@
{/if} {/if}
</div> </div>
</div> </div>
<ConfirmDialog <ConfirmDialog
bind:this={selectTemplateDialog} bind:this={selectTemplateDialog}
title="Choose Template" title="Choose Template"
onCancel={() => selectedComponent = null} onCancel={() => (selectedComponent = null)}
onOk={onTemplateInstanceChosen}> onOk={onTemplateInstanceChosen}>
{#each templateInstances.map(i => i.name) as instance} {#each templateInstances.map(i => i.name) as instance}
<div class="uk-margin uk-grid-small uk-child-width-auto uk-grid"> <div class="uk-margin uk-grid-small uk-child-width-auto uk-grid">
<label> <label>
<input class="uk-radio" type="radio" bind:group={selectedTemplateInstance} value={instance}> <input
class="uk-radio"
type="radio"
bind:group={selectedTemplateInstance}
value={instance} />
<span class="template-instance-label">{instance}</span> <span class="template-instance-label">{instance}</span>
</label> </label>
</div> </div>
@ -307,5 +323,4 @@
.template-instance-label { .template-instance-label {
margin-left: 20px; margin-left: 20px;
} }
</style> </style>

24
packages/builder/src/userInterface/ComponentsHierarchy.svelte

@ -15,15 +15,12 @@
const joinPath = join("/") const joinPath = join("/")
const normalizedName = name => const normalizedName = name =>
pipe( pipe(name, [
name, trimCharsStart("./"),
[ trimCharsStart("~/"),
trimCharsStart("./"), trimCharsStart("../"),
trimCharsStart("~/"), trimChars(" "),
trimCharsStart("../"), ])
trimChars(" "),
]
)
const lastPartOfName = c => { const lastPartOfName = c => {
if (!c) return "" if (!c) return ""
@ -31,15 +28,14 @@
return last(name.split("/")) return last(name.split("/"))
} }
const isComponentSelected = (current, comp) => current === comp const isComponentSelected = (current, comp) => current === comp
const isFolderSelected = (current, folder) => isInSubfolder(current, folder) const isFolderSelected = (current, folder) => isInSubfolder(current, folder)
$: _screens = pipe( $: _screens = pipe(screens, [
screens, map(c => ({ component: c, title: lastPartOfName(c) })),
[map(c => ({ component: c, title: lastPartOfName(c) })), sortBy("title")] sortBy("title"),
) ])
const isScreenSelected = component => const isScreenSelected = component =>
component.component && component.component &&

6
packages/builder/src/userInterface/ComponentsHierarchyChildren.svelte

@ -20,11 +20,7 @@
const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1) const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1)
const get_name = s => (!s ? "" : last(s.split("/"))) const get_name = s => (!s ? "" : last(s.split("/")))
const get_capitalised_name = name => const get_capitalised_name = name => pipe(name, [get_name, capitalise])
pipe(
name,
[get_name, capitalise]
)
const moveDownComponent = component => { const moveDownComponent = component => {
const c = component const c = component

10
packages/builder/src/userInterface/ComponentsPaneSwitcher.svelte

@ -3,16 +3,18 @@
import ComponentPropertiesPanel from "./ComponentPropertiesPanel.svelte" import ComponentPropertiesPanel from "./ComponentPropertiesPanel.svelte"
import ComponentSelectionList from "./ComponentSelectionList.svelte" import ComponentSelectionList from "./ComponentSelectionList.svelte"
const PROPERTIES_TAB = "properties"; const PROPERTIES_TAB = "properties"
const COMPONENT_SELECTION_TAB = "components"; const COMPONENT_SELECTION_TAB = "components"
let selected = PROPERTIES_TAB let selected = PROPERTIES_TAB
const isSelected = tab => selected === tab const isSelected = tab => selected === tab
const selectTab = tab => (selected = tab) const selectTab = tab => (selected = tab)
const toggleTab = () => selected = selected === PROPERTIES_TAB ? COMPONENT_SELECTION_TAB : PROPERTIES_TAB; const toggleTab = () =>
(selected =
selected === PROPERTIES_TAB ? COMPONENT_SELECTION_TAB : PROPERTIES_TAB)
</script> </script>
<div class="root"> <div class="root">

4
packages/builder/src/userInterface/EventsEditor/EventEditorModal.svelte

@ -20,8 +20,8 @@
let draftEventHandler = { parameters: [] } let draftEventHandler = { parameters: [] }
$: eventData = event || { handlers: [] } $: eventData = event || { handlers: [] }
$: if (!eventOptions.includes(eventType) && eventOptions.length > 0) $: if (!eventOptions.includes(eventType) && eventOptions.length > 0)
eventType = eventOptions[0].name eventType = eventOptions[0].name
const closeModal = () => { const closeModal = () => {
onClose() onClose()

2
packages/builder/src/userInterface/EventsEditor/StateBindingCascader.svelte

@ -61,7 +61,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.handler-input { .handler-input {
position: relative; position: relative;
display: flex; display: flex;

20
packages/builder/src/userInterface/MasterLayout.svelte

@ -16,15 +16,12 @@
const joinPath = join("/") const joinPath = join("/")
const normalizedName = name => const normalizedName = name =>
pipe( pipe(name, [
name, trimCharsStart("./"),
[ trimCharsStart("~/"),
trimCharsStart("./"), trimCharsStart("../"),
trimCharsStart("~/"), trimChars(" "),
trimCharsStart("../"), ])
trimChars(" "),
]
)
const lastPartOfName = c => const lastPartOfName = c =>
c && last(c.name ? c.name.split("/") : c._component.split("/")) c && last(c.name ? c.name.split("/") : c._component.split("/"))
@ -33,10 +30,7 @@
const isFolderSelected = (current, folder) => isInSubfolder(current, folder) const isFolderSelected = (current, folder) => isInSubfolder(current, folder)
$: _layout = pipe( $: _layout = pipe(layout, [c => ({ component: c, title: lastPartOfName(c) })])
layout,
[c => ({ component: c, title: lastPartOfName(c) })]
)
const isScreenSelected = component => const isScreenSelected = component =>
component.component && component.component &&

29
packages/builder/src/userInterface/NewScreen.svelte

@ -21,20 +21,17 @@
let layoutComponent let layoutComponent
let screens let screens
let name = "" let name = ""
let saveAttempted = false let saveAttempted = false
$: layoutComponents = pipe( $: layoutComponents = pipe($store.components, [
$store.components, filter(c => c.container),
[ map(c => ({ name: c.name, ...splitName(c.name) })),
filter(c => c.container), ])
map(c => ({ name: c.name, ...splitName(c.name) })),
]
)
$: layoutComponent = layoutComponent $: layoutComponent = layoutComponent
? find(c => c.name === layoutComponent.name)(layoutComponents) ? find(c => c.name === layoutComponent.name)(layoutComponents)
: layoutComponents[0] : layoutComponents[0]
$: screens = $store.screens $: screens = $store.screens
$: route = !route && screens.length === 0 ? "*" : route $: route = !route && screens.length === 0 ? "*" : route
@ -43,9 +40,11 @@
saveAttempted = true saveAttempted = true
const isValid = const isValid =
name.length > 0 && !screenNameExists(name) name.length > 0 &&
&& route.length > 0 && !routeNameExists(route) !screenNameExists(name) &&
&& layoutComponent route.length > 0 &&
!routeNameExists(route) &&
layoutComponent
if (!isValid) return if (!isValid) return
@ -101,8 +100,8 @@
<input <input
class="uk-input uk-form-small" class="uk-input uk-form-small"
class:uk-form-danger={saveAttempted && (route.length === 0 || routeNameExists(route))} class:uk-form-danger={saveAttempted && (route.length === 0 || routeNameExists(route))}
bind:value={route} bind:value={route}
on:change={routeChanged}/> on:change={routeChanged} />
</div> </div>
</div> </div>

14
packages/builder/src/userInterface/PropertyCascader/PropertyCascader.svelte

@ -3,7 +3,7 @@
import { store } from "../../builderStore" import { store } from "../../builderStore"
import { buildStateOrigins } from "../../builderStore/buildStateOrigins" import { buildStateOrigins } from "../../builderStore/buildStateOrigins"
import { isBinding, getBinding, setBinding } from "../../common/binding" import { isBinding, getBinding, setBinding } from "../../common/binding"
import StateBindingOptions from "./StateBindingOptions.svelte"; import StateBindingOptions from "./StateBindingOptions.svelte"
export let onChanged = () => {} export let onChanged = () => {}
export let value = "" export let value = ""
@ -28,7 +28,8 @@
const setBindingPath = value => const setBindingPath = value =>
bindValueToSource(value, bindingFallbackValue, bindingSource) bindValueToSource(value, bindingFallbackValue, bindingSource)
const setBindingFallback = value => bindValueToSource(bindingPath, value, bindingSource) const setBindingFallback = value =>
bindValueToSource(bindingPath, value, bindingSource)
const setBindingSource = source => const setBindingSource = source =>
bindValueToSource(bindingPath, bindingFallbackValue, source) bindValueToSource(bindingPath, bindingFallbackValue, source)
@ -69,10 +70,11 @@
</button> </button>
</div> </div>
{#if isOpen} {#if isOpen}
<StateBindingOptions onSelect={option => { <StateBindingOptions
onChanged(option); onSelect={option => {
isOpen = false; onChanged(option)
}} /> isOpen = false
}} />
{/if} {/if}
</div> </div>

2
packages/builder/src/userInterface/PropertyCascader/index.js

@ -1 +1 @@
export { default } from "./PropertyCascader.svelte" export { default } from "./PropertyCascader.svelte"

36
packages/builder/src/userInterface/PropsView.svelte

@ -11,36 +11,34 @@
let errors = [] let errors = []
const props_to_ignore = ["_component", "_children", "_styles", "_code", "_id"] const props_to_ignore = ["_component", "_children", "_styles", "_code", "_id"]
$: componentDef =
component && components &&
components.find(({ name }) => name === component._component)
$: componentDef =
component &&
components &&
components.find(({ name }) => name === component._component)
let setProp = (name, value) => { let setProp = (name, value) => {
onPropChanged(name, value) onPropChanged(name, value)
} }
</script> </script>
<div class="root"> <div class="root">
<form class="uk-form-stacked form-root"> <form class="uk-form-stacked form-root">
{#if componentDef} {#if componentDef}
{#each Object.entries(componentDef.props) as [prop_name, prop_def], index} {#each Object.entries(componentDef.props) as [prop_name, prop_def], index}
<div class="prop-container"> <div class="prop-container">
<PropControl <PropControl
{setProp} {setProp}
{prop_name} {prop_name}
prop_value={component[prop_name]} prop_value={component[prop_name]}
prop_definition={prop_def} prop_definition={prop_def}
{index} {index}
disabled={false} /> disabled={false} />
</div> </div>
{/each} {/each}
{/if} {/if}
</form> </form>

2
packages/builder/src/userInterface/StateBindingControl.svelte

@ -23,7 +23,7 @@
class="uk-select uk-form-small" class="uk-select uk-form-small"
{value} {value}
on:change={ev => onChanged(ev.target.value)}> on:change={ev => onChanged(ev.target.value)}>
{#each (options || []) as option} {#each options || [] as option}
<option value={option}>{option}</option> <option value={option}>{option}</option>
{/each} {/each}
</select> </select>

2
packages/builder/src/userInterface/pagesParsing/findDependencies.js

@ -5,7 +5,7 @@ import { isRootComponent } from "./searchComponents"
export const libraryDependencies = (components, lib) => { export const libraryDependencies = (components, lib) => {
const componentDependsOnLibrary = comp => { const componentDependsOnLibrary = comp => {
if (isRootComponent(comp)) { if (isRootComponent(comp)) {
const { libName } = splitName(component.name) const { libName } = splitName(comp.name)
return libName === lib return libName === lib
} }
return componentDependsOnLibrary( return componentDependsOnLibrary(

2
packages/builder/src/userInterface/pagesParsing/searchComponents.js

@ -1,6 +1,6 @@
import { pipe } from "../../common/core" import { pipe } from "../../common/core"
import { find, isUndefined, filter, some, includes, has } from "lodash/fp" import { find, isUndefined, filter, some, includes } from "lodash/fp"
const normalString = s => (s || "").trim().toLowerCase() const normalString = s => (s || "").trim().toLowerCase()

3
packages/builder/src/userInterface/pagesParsing/types.js

@ -3,10 +3,8 @@ import {
isBoolean, isBoolean,
isNumber, isNumber,
isArray, isArray,
isObjectLike,
isPlainObject, isPlainObject,
every, every,
isUndefined,
} from "lodash/fp" } from "lodash/fp"
import { EVENT_TYPE_MEMBER_NAME } from "../../common/eventHandlers" import { EVENT_TYPE_MEMBER_NAME } from "../../common/eventHandlers"
@ -61,7 +59,6 @@ export const expandComponentDefinition = componentDefinition => {
return expandedComponent return expandedComponent
} }
const isComponent = isObjectLike
const isEvent = e => const isEvent = e =>
isPlainObject(e) && isPlainObject(e) &&
isString(e[EVENT_TYPE_MEMBER_NAME]) && isString(e[EVENT_TYPE_MEMBER_NAME]) &&

2
packages/builder/src/userInterface/pagesParsing/validatePages.js

@ -2,7 +2,7 @@ import { isString, keys, flatten, isArray, map, filter } from "lodash/fp"
import { common } from "../../../../core/src" import { common } from "../../../../core/src"
const pipe = common.$ const pipe = common.$
export const validatePage = (page, getComponent) => { export const validatePage = page => {
const errors = [] const errors = []
const error = message => errors.push(message) const error = message => errors.push(message)

56
packages/builder/tests/buildStateOrigins.spec.js

@ -1,30 +1,32 @@
import { buildStateOrigins } from "../src/builderStore/buildStateOrigins"; import { buildStateOrigins } from "../src/builderStore/buildStateOrigins"
it("builds the correct stateOrigins object from a screen definition with handlers", () => { it("builds the correct stateOrigins object from a screen definition with handlers", () => {
expect(buildStateOrigins({ expect(
"name": "screen1", buildStateOrigins({
"description": "", name: "screen1",
"props": { description: "",
"_component": "@budibase/standard-components/container", props: {
"className": "", _component: "@budibase/standard-components/container",
"type": "div", className: "",
"onClick": [ type: "div",
{ onClick: [
"##eventHandlerType": "Set State", {
"parameters": { "##eventHandlerType": "Set State",
"path": "testKey", parameters: {
"value": "value" path: "testKey",
} value: "value",
} },
] },
} ],
})).toEqual({ },
"testKey": { })
).toEqual({
testKey: {
"##eventHandlerType": "Set State", "##eventHandlerType": "Set State",
"parameters": { parameters: {
"path": "testKey", path: "testKey",
"value": "value" value: "value",
} },
} },
}); })
}); })

2
packages/builder/tests/createProps.spec.js

@ -206,7 +206,7 @@ describe("createDefaultProps", () => {
expect(props.fieldName).toBe("surname") expect(props.fieldName).toBe("surname")
expect(props.fieldLength).toBe(500) expect(props.fieldLength).toBe(500)
}) })
it("should create standard props", () => { it("should create standard props", () => {
const comp = getcomponent() const comp = getcomponent()
comp.props.fieldName = { type: "string", default: 1 } comp.props.fieldName = { type: "string", default: 1 }

2
packages/cli/src/commands/new/appPackageTemplate/plugins.js

@ -1 +1 @@
module.exports = config => ({}) module.exports = () => ({})

2
packages/cli/src/common.js

@ -1,4 +1,4 @@
const { resolve, join } = require("path") const { resolve } = require("path")
const { cwd } = require("process") const { cwd } = require("process")
const buildAppContext = require("@budibase/server/initialise/buildAppContext") const buildAppContext = require("@budibase/server/initialise/buildAppContext")

1
packages/client/rollup.config.js

@ -2,7 +2,6 @@ import resolve from "rollup-plugin-node-resolve"
import commonjs from "rollup-plugin-commonjs" import commonjs from "rollup-plugin-commonjs"
import builtins from "rollup-plugin-node-builtins" import builtins from "rollup-plugin-node-builtins"
import nodeglobals from "rollup-plugin-node-globals" import nodeglobals from "rollup-plugin-node-globals"
import { terser } from "rollup-plugin-terser"
const lodash_fp_exports = [ const lodash_fp_exports = [
"find", "find",

2
packages/client/scripts/publishDev.js

@ -19,8 +19,6 @@ const appPackages = join(
const publicMain = appName => join(appPackages, appName, "public", "main") const publicMain = appName => join(appPackages, appName, "public", "main")
const publicUnauth = appName => const publicUnauth = appName =>
join(appPackages, appName, "public", "unauthenticated") join(appPackages, appName, "public", "unauthenticated")
const nodeModules = appName =>
join(appPackages, appName, "node_modules", "@budibase", "client", "dist")
;(async () => { ;(async () => {
const apps = await readdir(appPackages) const apps = await readdir(appPackages)

33
packages/client/src/index.js

@ -6,16 +6,15 @@ import { builtins, builtinLibName } from "./render/builtinComponents"
* create a web application from static budibase definition files. * create a web application from static budibase definition files.
* @param {object} opts - configuration options for budibase client libary * @param {object} opts - configuration options for budibase client libary
*/ */
export const loadBudibase = async (opts) => { export const loadBudibase = async opts => {
let componentLibraries = opts && opts.componentLibraries let componentLibraries = opts && opts.componentLibraries
const _window = (opts && opts.window) || window const _window = (opts && opts.window) || window
const _localStorage = (opts && opts.localStorage) || localStorage const _localStorage = (opts && opts.localStorage) || localStorage
const backendDefinition = _window["##BUDIBASE_BACKEND_DEFINITION##"] const backendDefinition = _window["##BUDIBASE_BACKEND_DEFINITION##"]
const frontendDefinition = _window["##BUDIBASE_FRONTEND_DEFINITION##"] const frontendDefinition = _window["##BUDIBASE_FRONTEND_DEFINITION##"]
const uiFunctions = _window["##BUDIBASE_FRONTEND_FUNCTIONS##"] const uiFunctions = _window["##BUDIBASE_FRONTEND_FUNCTIONS##"]
const userFromStorage = _localStorage.getItem("budibase:user") const userFromStorage = _localStorage.getItem("budibase:user")
const user = userFromStorage const user = userFromStorage
@ -33,8 +32,8 @@ export const loadBudibase = async (opts) => {
: "/" + trimSlash(frontendDefinition.appRootPath) : "/" + trimSlash(frontendDefinition.appRootPath)
if (!componentLibraries) { if (!componentLibraries) {
const componentLibraryUrl = lib =>
const componentLibraryUrl = lib => frontendDefinition.appRootPath + "/" + trimSlash(lib) frontendDefinition.appRootPath + "/" + trimSlash(lib)
componentLibraries = {} componentLibraries = {}
for (let lib of frontendDefinition.componentLibraries) { for (let lib of frontendDefinition.componentLibraries) {
@ -46,25 +45,33 @@ export const loadBudibase = async (opts) => {
componentLibraries[builtinLibName] = builtins(_window) componentLibraries[builtinLibName] = builtins(_window)
const { initialisePage, screenStore, pageStore, routeTo, rootNode } = createApp( const {
initialisePage,
screenStore,
pageStore,
routeTo,
rootNode,
} = createApp(
componentLibraries, componentLibraries,
frontendDefinition, frontendDefinition,
backendDefinition, backendDefinition,
user, user,
uiFunctions || {}, uiFunctions || {},
_window _window,
rootNode
) )
const route = _window.location const route = _window.location
? _window.location.pathname.replace(frontendDefinition.appRootPath, "") ? _window.location.pathname.replace(frontendDefinition.appRootPath, "")
: ""; : ""
initialisePage(frontendDefinition.page, _window.document.body, route)
return { return {
rootNode: initialisePage(frontendDefinition.page, _window.document.body, route),
screenStore, screenStore,
pageStore, pageStore,
routeTo, routeTo,
rootNode rootNode,
} }
} }

2
packages/client/src/render/attachChildren.js

@ -47,7 +47,7 @@ export const attachChildren = initialiseOpts => (htmlElement, options) => {
uiFunctions, uiFunctions,
htmlElement, htmlElement,
anchor, anchor,
getCurrentState getCurrentState,
}) })
for (let childNode of childNodesThisIteration) { for (let childNode of childNodesThisIteration) {

13
packages/client/src/state/parseBinding.js

@ -5,9 +5,9 @@ export const BB_STATE_FALLBACK = "##bbstatefallback"
export const isBound = prop => !!parseBinding(prop) export const isBound = prop => !!parseBinding(prop)
/** /**
* *
* @param {object|string|number} prop - component property to parse for a dynamic state binding * @param {object|string|number} prop - component property to parse for a dynamic state binding
* @returns {object|boolean} * @returns {object|boolean}
*/ */
export const parseBinding = prop => { export const parseBinding = prop => {
if (!prop) return false if (!prop) return false
@ -34,7 +34,8 @@ export const parseBinding = prop => {
} }
export const isStoreBinding = binding => binding && binding.source === "store" export const isStoreBinding = binding => binding && binding.source === "store"
export const isContextBinding = binding => binding && binding.source === "context" export const isContextBinding = binding =>
binding && binding.source === "context"
export const isEventBinding = binding => binding && binding.source === "event" export const isEventBinding = binding => binding && binding.source === "event"
const hasBindingObject = prop => const hasBindingObject = prop =>
@ -50,8 +51,8 @@ const isBindingExpression = prop =>
prop.startsWith("route.")) prop.startsWith("route."))
const parseBindingExpression = prop => { const parseBindingExpression = prop => {
let [source, ...rest] = prop.split("."); let [source, ...rest] = prop.split(".")
let path = rest.join(".") let path = rest.join(".")
if (source === "route") { if (source === "route") {
source = "state" source = "state"
@ -59,7 +60,7 @@ const parseBindingExpression = prop => {
} }
return { return {
fallback: "", // TODO: provide fallback support fallback: "", // TODO: provide fallback support
source, source,
path, path,
} }

79
packages/client/src/state/stateManager/index.js

@ -160,41 +160,46 @@ const setNodeState = (storeState, node) => {
* Bind a components event handler parameters to state, context or the event itself. * Bind a components event handler parameters to state, context or the event itself.
* @param {Array} eventHandlerProp - event handler array from component definition * @param {Array} eventHandlerProp - event handler array from component definition
*/ */
function bindComponentEventHandlers(eventHandlerProp) { function bindComponentEventHandlers(
const boundEventHandlers = [] eventHandlerProp,
for (let event of eventHandlerProp) { context,
const boundEventHandler = { getCurrentState
handlerType: event[EVENT_TYPE_MEMBER_NAME], ) {
parameters: event.parameters, const boundEventHandlers = []
} for (let event of eventHandlerProp) {
const boundEventHandler = {
handlerType: event[EVENT_TYPE_MEMBER_NAME],
parameters: event.parameters,
}
const boundParameters = {} const boundParameters = {}
for (let paramName in boundEventHandler.parameters) { for (let paramName in boundEventHandler.parameters) {
const paramValue = boundEventHandler.parameters[paramName] const paramValue = boundEventHandler.parameters[paramName]
const paramBinding = parseBinding(paramValue) const paramBinding = parseBinding(paramValue)
if (!paramBinding) { if (!paramBinding) {
boundParameters[paramName] = () => paramValue boundParameters[paramName] = () => paramValue
continue continue
} }
let paramValueSource; let paramValueSource
if (paramBinding.source === "context") paramValueSource = context; if (paramBinding.source === "context") paramValueSource = context
if (paramBinding.source === "state") paramValueSource = getCurrentState(); if (paramBinding.source === "state") paramValueSource = getCurrentState()
// The new dynamic event parameter bound to the relevant source // The new dynamic event parameter bound to the relevant source
boundParameters[paramName] = eventContext => getState( boundParameters[paramName] = eventContext =>
getState(
paramBinding.source === "event" ? eventContext : paramValueSource, paramBinding.source === "event" ? eventContext : paramValueSource,
paramBinding.path, paramBinding.path,
paramBinding.fallback paramBinding.fallback
); )
} }
boundEventHandler.parameters = boundParameters boundEventHandler.parameters = boundParameters
boundEventHandlers.push(boundEventHandlers) boundEventHandlers.push(boundEventHandlers)
return boundEventHandlers; return boundEventHandlers
} }
} }
const _setup = ( const _setup = (
@ -230,22 +235,26 @@ const _setup = (
binding.fallback, binding.fallback,
binding.source binding.source
) )
} }
if (isBound && binding.source === "context") { if (isBound && binding.source === "context") {
initialProps[propName] = !context initialProps[propName] = !context
? propValue ? propValue
: getState(context, binding.path, binding.fallback, binding.source) : getState(context, binding.path, binding.fallback, binding.source)
} }
if (isEventType(propValue)) {
const boundEventHandlers = bindComponentEventHandlers(propValue);
if (boundEventHandlers.length === 0) { if (isEventType(propValue)) {
const boundEventHandlers = bindComponentEventHandlers(
propValue,
context,
getCurrentState
)
if (boundEventHandlers.length === 0) {
initialProps[propName] = doNothing initialProps[propName] = doNothing
} else { } else {
initialProps[propName] = async context => { initialProps[propName] = async context => {
for (let handlerInfo of handlersInfos) { for (let handlerInfo of boundEventHandlers) {
const handler = makeHandler(handlerTypes, handlerInfo) const handler = makeHandler(handlerTypes, handlerInfo)
await handler(context) await handler(context)
} }
@ -271,4 +280,4 @@ const makeHandler = (handlerTypes, handlerInfo) => {
} }
handlerType.execute(parameters) handlerType.execute(parameters)
} }
} }

2
packages/core/src/indexing/allIds.js

@ -1,5 +1,5 @@
import { flatten, orderBy, filter, isUndefined } from "lodash/fp" import { flatten, orderBy, filter, isUndefined } from "lodash/fp"
import hierarchy, { import {
getFlattenedHierarchy, getFlattenedHierarchy,
getCollectionNodeByKeyOrNodeKey, getCollectionNodeByKeyOrNodeKey,
isCollectionRecord, isCollectionRecord,

1
packages/core/src/indexing/sharding.js

@ -5,7 +5,6 @@ import {
isGlobalIndex, isGlobalIndex,
getParentKey, getParentKey,
isShardedIndex, isShardedIndex,
getExactNodeForKey,
} from "../templateApi/hierarchy" } from "../templateApi/hierarchy"
import { joinKey, isNonEmptyString, splitKey, $ } from "../common" import { joinKey, isNonEmptyString, splitKey, $ } from "../common"

2
packages/core/src/recordApi/load.js

@ -1,5 +1,5 @@
import { keyBy, mapValues, filter, map, includes, last } from "lodash/fp" import { keyBy, mapValues, filter, map, includes, last } from "lodash/fp"
import { getExactNodeForKey, getNode } from "../templateApi/hierarchy" import { getNode } from "../templateApi/hierarchy"
import { safeParseField } from "../types" import { safeParseField } from "../types"
import { import {
$, $,

2
packages/core/src/recordApi/recordInfo.js

@ -5,7 +5,7 @@ import {
isSingleRecord, isSingleRecord,
getNodeForCollectionPath, getNodeForCollectionPath,
} from "../templateApi/hierarchy" } from "../templateApi/hierarchy"
import { reduce, find, filter, take } from "lodash/fp" import { reduce, find, filter } from "lodash/fp"
import { $, getFileFromKey, joinKey, safeKey, keySep } from "../common" import { $, getFileFromKey, joinKey, safeKey, keySep } from "../common"
import { folderStructureArray, allIdChars } from "../indexing/allIds" import { folderStructureArray, allIdChars } from "../indexing/allIds"

4
packages/core/src/recordApi/uploadFile.js

@ -73,9 +73,7 @@ const _uploadFile = async (
) )
if (!isExpectedFileSize) { if (!isExpectedFileSize) {
throw new BadRequestError( throw new BadRequestError(
`Fields for ${relativeFilePath} do not have expected size: ${join( `Fields for ${relativeFilePath} do not have expected size.`
","
)(incorrectFields)}`
) )
} }
}) })

2
packages/core/src/templateApi/deleteNodes.js

@ -1,6 +1,6 @@
import {} from "../templateApi/heirarchy" import {} from "../templateApi/heirarchy"
export const canDelete = (app, node) => { export const canDelete = () => {
/* /*
it must not exist on any index.allowedRecordNodeIds it must not exist on any index.allowedRecordNodeIds
it must not exist on and reference type fields it must not exist on and reference type fields

6
packages/core/test/apiWrapper.spec.js

@ -1,6 +1,6 @@
import { apiWrapper, apiWrapperSync } from "../src/common/apiWrapper" import { apiWrapper, apiWrapperSync } from "../src/common/apiWrapper"
import { filter } from "lodash/fp" import { filter } from "lodash/fp"
import { event, onComplete, onBegin, onError, events } from "../src/common" import { events } from "../src/common"
const getApp = () => { const getApp = () => {
var events = [] var events = []
@ -26,7 +26,7 @@ describe("apiWrapper", () => {
const getErrorEvents = app => app.getEvents(testNamespace.onError) const getErrorEvents = app => app.getEvents(testNamespace.onError)
const runThrowEx = (arg1, arg2) => { const runThrowEx = (arg1, arg2) => {
const throwEx = (x, y) => { const throwEx = () => {
throw new Error("test error") throw new Error("test error")
} }
const app = getApp() const app = getApp()
@ -47,7 +47,7 @@ describe("apiWrapper", () => {
} }
const runThrowExAsync = async (arg1, arg2) => { const runThrowExAsync = async (arg1, arg2) => {
const throwEx = async (x, y) => { const throwEx = async () => {
throw new Error("test error") throw new Error("test error")
} }
const app = getApp() const app = getApp()

2
packages/core/test/authApi.authenticate.spec.js

@ -33,7 +33,7 @@ describe("authApi > authenticate", () => {
}) })
it("should return null when non existing user", async () => { it("should return null when non existing user", async () => {
const { authApi, app } = await setupApphierarchy( const { authApi } = await setupApphierarchy(
basicAppHierarchyCreator_WithFields basicAppHierarchyCreator_WithFields
) )
const result = await authApi.authenticate("nobody", "password") const result = await authApi.authenticate("nobody", "password")

8
packages/core/test/recordApi.files.spec.js

@ -31,7 +31,7 @@ describe("recordApi > files", () => {
const { recordApi } = await setupApphierarchy( const { recordApi } = await setupApphierarchy(
basicAppHierarchyCreator_WithFields basicAppHierarchyCreator_WithFields
) )
const { file, stream, content } = getFile() const { file, stream } = getFile()
file.size = file.size - 1 file.size = file.size - 1
const record = recordApi.getNew("/customers", "customer") const record = recordApi.getNew("/customers", "customer")
record.surname = "Ledog" record.surname = "Ledog"
@ -46,7 +46,7 @@ describe("recordApi > files", () => {
const { recordApi } = await setupApphierarchy( const { recordApi } = await setupApphierarchy(
basicAppHierarchyCreator_WithFields basicAppHierarchyCreator_WithFields
) )
const { file, stream, content } = getFile() const { file, stream } = getFile()
const record = recordApi.getNew("/customers", "customer") const record = recordApi.getNew("/customers", "customer")
record.surname = "Ledog" record.surname = "Ledog"
record.profilepic = file record.profilepic = file
@ -80,7 +80,7 @@ describe("recordApi > files", () => {
const { recordApi } = await setupApphierarchy( const { recordApi } = await setupApphierarchy(
basicAppHierarchyCreator_WithFields basicAppHierarchyCreator_WithFields
) )
const { file, stream, content } = getFile() const { file, stream } = getFile()
const record = recordApi.getNew("/customers", "customer") const record = recordApi.getNew("/customers", "customer")
record.surname = "Ledog" record.surname = "Ledog"
record.profilepic = file record.profilepic = file
@ -98,7 +98,7 @@ describe("recordApi > files", () => {
const { recordApi } = await setupApphierarchy( const { recordApi } = await setupApphierarchy(
basicAppHierarchyCreator_WithFields basicAppHierarchyCreator_WithFields
) )
const { file, stream, content } = getFile() const { file, stream } = getFile()
const record = recordApi.getNew("/customers", "customer") const record = recordApi.getNew("/customers", "customer")
record.surname = "Ledog" record.surname = "Ledog"
record.profilepic = file record.profilepic = file

1
packages/datastores/config.js

@ -4,7 +4,6 @@ import { promisify } from "es6-promisify"
import _rimraf from "rimraf" import _rimraf from "rimraf"
const mkdir = promisify(fs.mkdir) const mkdir = promisify(fs.mkdir)
const rmdir = promisify(fs.rmdir)
const rimraf = promisify(_rimraf) const rimraf = promisify(_rimraf)
const getConfig = async () => { const getConfig = async () => {

11
packages/datastores/config.template.js

@ -1,9 +1,8 @@
import fs from "fs"
import { mkdir } from "fs" import { mkdir } from "fs"
import { join } from "path" import { join } from "path"
import { promisify } from "es6-promisify" import { promisify } from "es6-promisify"
mkdirp = promisify(mkdir) const mkdirp = promisify(mkdir)
const getConfig = async () => { const getConfig = async () => {
const config = { const config = {
@ -13,15 +12,13 @@ const getConfig = async () => {
memory: {}, memory: {},
} }
try { await mkdirp("./output")
await mkdir("./output")
} catch (e) {}
for (let type in config) { for (let type in config) {
await mkdir(join("output", type)) await mkdirp(join("output", type))
} }
await mkdir("./output/local/files") await mkdirp("./output/local/files")
return config return config
} }

11
packages/datastores/datastores/azure-blob.js

@ -9,7 +9,7 @@ import {
} from "@azure/storage-blob" } from "@azure/storage-blob"
export const createFile = ({ containerUrl }) => async (key, content) => { export const createFile = ({ containerUrl }) => async (key, content) => {
const blobURL = BlobURL.fromContainerURL(containerURL, key) const blobURL = BlobURL.fromContainerURL(containerUrl, key)
const blockBlobURL = BlockBlobURL.fromBlobURL(blobURL) const blockBlobURL = BlockBlobURL.fromBlobURL(blobURL)
await blockBlobURL.upload(Aborter.none, content, content.length) await blockBlobURL.upload(Aborter.none, content, content.length)
} }
@ -17,7 +17,7 @@ export const createFile = ({ containerUrl }) => async (key, content) => {
export const updateFile = opts => async (path, content) => export const updateFile = opts => async (path, content) =>
createFile(opts)(path, content) createFile(opts)(path, content)
export const loadFile = ({ containerUrl }) => async key => { export const loadFile = ({ containerUrl }) => async (key, content) => {
const blobURL = BlobURL.fromContainerURL(containerUrl, key) const blobURL = BlobURL.fromContainerURL(containerUrl, key)
const downloadBlockBlobResponse = await blobURL.download(Aborter.none, 0) const downloadBlockBlobResponse = await blobURL.download(Aborter.none, 0)
@ -27,8 +27,8 @@ export const loadFile = ({ containerUrl }) => async key => {
.toString() .toString()
} }
export const exists = ({ containerURL }) => async key => { export const exists = ({ containerUrl }) => async key => {
const blobURL = BlobURL.fromContainerURL(containerURL, key) const blobURL = BlobURL.fromContainerURL(containerUrl, key)
const getPropsResponse = await blobURL.getProperties() const getPropsResponse = await blobURL.getProperties()
return getPropsResponse._response.StatusCode === 200 return getPropsResponse._response.StatusCode === 200
} }
@ -53,7 +53,7 @@ const initialise = opts => {
const pipeline = StorageURL.newPipeline(sharedKeyCredential) const pipeline = StorageURL.newPipeline(sharedKeyCredential)
const serviceURL = new ServiceURL( const serviceURL = new ServiceURL(
`https://${account}.blob.core.windows.net`, `https://${opts.account}.blob.core.windows.net`,
pipeline pipeline
) )
@ -77,6 +77,5 @@ export default opts => {
datastoreType: "azure-blob-storage", datastoreType: "azure-blob-storage",
datastoreDescription: "", datastoreDescription: "",
data,
} }
} }

2
packages/datastores/index.js

@ -24,5 +24,5 @@ initialise()
.then(init => { .then(init => {
return tests(init.datastore, init.config) return tests(init.datastore, init.config)
}) })
.then(_ => console.log("done")) .then(() => console.log("done"))
.catch(e => console.log(e)) .catch(e => console.log(e))

6
packages/datastores/tests/diagnosticPlugin.js

@ -1,14 +1,8 @@
import { eventsList } from "@budibase/core" import { eventsList } from "@budibase/core"
import { filter, union, has, map } from "lodash/fp" import { filter, union, has, map } from "lodash/fp"
import records from "./records"
const allEventsOfType = type => filter(e => e.endsWith(`:${type}`))(eventsList) const allEventsOfType = type => filter(e => e.endsWith(`:${type}`))(eventsList)
const getEventNamespace = ev => {
const parts = ev.split(":")
return `${parts[0]}:${parts[1]}`
}
const hasRecord = has("record") const hasRecord = has("record")
export const register = (app, logTimeElapsed, eventNamespaces = []) => { export const register = (app, logTimeElapsed, eventNamespaces = []) => {

1
packages/datastores/tests/index.js

@ -16,7 +16,6 @@ const iterateActions = async (apis, getIterator) => {
limit(() => result.action.run(i)) limit(() => result.action.run(i))
) )
let n = 1
await Promise.all(runPromises) await Promise.all(runPromises)
result = iterator() result = iterator()
} catch (e) { } catch (e) {

31
packages/datastores/tests/records.js

@ -1,5 +1,5 @@
import { action, iterateActionTimes, iterateCollection } from "./helpers" import { action, iterateActionTimes } from "./helpers"
import { isUndefined, union, takeRight } from "lodash" import { isUndefined, union } from "lodash"
const createClient = (apis, getState) => async i => { const createClient = (apis, getState) => async i => {
const client = apis.recordApi.getNew("/clients", "client") const client = apis.recordApi.getNew("/clients", "client")
@ -20,16 +20,6 @@ const createClient = (apis, getState) => async i => {
return client.key() return client.key()
} }
const getClient = (apis, getState) => async k => {
const state = getState()
if (isUndefined(state.clients)) state.clients = []
const client = await apis.recordApi.load(k)
state.clients.push(client)
return `key: ${k} , add1: ${client.Address1} , count: ${state.clients.length}`
}
const listClients = (apis, getState) => async () => { const listClients = (apis, getState) => async () => {
const clients = await apis.viewApi.listItems("/clients/default") const clients = await apis.viewApi.listItems("/clients/default")
const state = getState() const state = getState()
@ -43,12 +33,6 @@ const listClients = (apis, getState) => async () => {
} }
} }
const deleteClient = (apis, getState) => async k => {
await apis.recordApi.delete(k)
const state = getState()
state.clientKeys = state.clientKeys.filter(key => key !== k)
}
export default apis => { export default apis => {
const state = {} const state = {}
const getState = () => state const getState = () => state
@ -64,9 +48,6 @@ export default apis => {
iterateActionTimes(recordsPerIteration) iterateActionTimes(recordsPerIteration)
), ),
/*action("Get client", getClient(apis, getState),
iterateCollection(() => takeRight(getState().clientKeys, recordsPerIteration))),*/
action("List Clients", listClients(apis, getState)), action("List Clients", listClients(apis, getState)),
] ]
@ -75,14 +56,6 @@ export default apis => {
actions = union(actions, actionsInOneIteration()) actions = union(actions, actionsInOneIteration())
} }
/*
for (let index = 0; index < noOfIterations; index++) {
actions.push(
action("Delete Clients", deleteClient(apis, getState),
iterateCollection(() => takeRight(getState().clientKeys, recordsPerIteration))),
action("List Clients", listClients(apis, getState))
);
}*/
let actionIndex = 0 let actionIndex = 0
return () => { return () => {

1
packages/datastores/tests/setup.js

@ -1,5 +1,4 @@
import { getAppApis, getTemplateApi, setupDatastore } from "@budibase/core" import { getAppApis, getTemplateApi, setupDatastore } from "@budibase/core"
import { action } from "./helpers"
const addField = templateApi => type => (record, name) => { const addField = templateApi => type => (record, name) => {
const field = templateApi.getNewField(type) const field = templateApi.getNewField(type)

1
packages/materialdesign-components/rollup.config.js

@ -1,7 +1,6 @@
import svelte from "rollup-plugin-svelte" import svelte from "rollup-plugin-svelte"
import postcss from "rollup-plugin-postcss" import postcss from "rollup-plugin-postcss"
import resolve from "rollup-plugin-node-resolve" import resolve from "rollup-plugin-node-resolve"
import path from "path"
const postcssOptions = () => ({ const postcssOptions = () => ({
extensions: [".scss", ".sass"], extensions: [".scss", ".sass"],

2
packages/materialdesign-components/rollup.testconfig.js

@ -5,7 +5,7 @@ import livereload from "rollup-plugin-livereload"
import { terser } from "rollup-plugin-terser" import { terser } from "rollup-plugin-terser"
import json from "rollup-plugin-json" import json from "rollup-plugin-json"
import alias from "rollup-plugin-alias" import alias from "rollup-plugin-alias"
import postcss from "rollup-plugin-postcss"; import postcss from "rollup-plugin-postcss"
import path from "path" import path from "path"
const aliases = { const aliases = {

66
packages/materialdesign-components/src/Checkbox/CheckboxGroup.svelte

@ -1,28 +1,48 @@
<script> <script>
import Checkbox from "./Checkbox.svelte"; import Checkbox from "./Checkbox.svelte"
import Label from "../Common/Label.svelte"; import Label from "../Common/Label.svelte"
export let label = ""; export let label = ""
export let orientation = "row"; export let orientation = "row"
export let fullwidth = false; export let fullwidth = false
export let onChange = selectedItems => {}; export let onChange = selectedItems => {}
export let items = []; export let items = []
export let disabled = false; export let disabled = false
export let alignEnd = false; export let alignEnd = false
let selectedItems = []; let selectedItems = []
function handleonChange(item) { function handleonChange(item) {
if (!!item.checked) { if (!!item.checked) {
item.checked = !item.checked; item.checked = !item.checked
} else { } else {
item.checked = true; item.checked = true
} }
onChange(items.filter(i => i.checked)); onChange(items.filter(i => i.checked))
} }
</script> </script>
<div class="checkbox-group">
<div class="checkbox-group__label">
<Label text={label} bold />
</div>
<div class={`checkbox-group__boxes ${orientation}`}>
{#each items as item, i}
<div class:fullwidth>
<Checkbox
id={`${item.label}-${i}`}
{disabled}
{alignEnd}
indeterminate={item.indeterminate || false}
label={item.label}
checked={item.checked || false}
onClick={() => handleonChange(item)} />
</div>
{/each}
</div>
</div>
<style> <style>
.checkbox-group { .checkbox-group {
display: flex; display: flex;
@ -55,23 +75,3 @@
text-align: left; text-align: left;
} }
</style> </style>
<div class="checkbox-group">
<div class="checkbox-group__label">
<Label text={label} bold />
</div>
<div class={`checkbox-group__boxes ${orientation}`}>
{#each items as item, i}
<div class:fullwidth>
<Checkbox
id={`${item.label}-${i}`}
{disabled}
{alignEnd}
indeterminate={item.indeterminate || false}
label={item.label}
checked={item.checked || false}
onClick={() => handleonChange(item)} />
</div>
{/each}
</div>
</div>

7
packages/materialdesign-components/src/Checkbox/index.js

@ -1,4 +1,3 @@
import "./_style.scss"; import "./_style.scss"
export { default as Checkbox } from "./Checkbox.svelte"; export { default as Checkbox } from "./Checkbox.svelte"
export { default as Checkboxgroup } from "./CheckboxGroup.svelte"; export { default as Checkboxgroup } from "./CheckboxGroup.svelte"

44
packages/materialdesign-components/src/ClassBuilder.js

@ -1,7 +1,7 @@
export default class ClassBuilder { export default class ClassBuilder {
constructor(block, defaultIgnoreList) { constructor(block, defaultIgnoreList) {
this.block = `mdc-${block}`; this.block = `mdc-${block}`
this.defaultIgnoreList = defaultIgnoreList; //will be ignored when building custom classes this.defaultIgnoreList = defaultIgnoreList //will be ignored when building custom classes
} }
/* /*
@ -10,32 +10,32 @@ export default class ClassBuilder {
All are optional All are optional
*/ */
build(params) { build(params) {
if (!params) return this.block; //return block if nothing passed if (!params) return this.block //return block if nothing passed
const { props, elementName } = params; const { props, elementName } = params
let base = !!elementName ? `${this.block}__${elementName}` : this.block; let base = elementName ? `${this.block}__${elementName}` : this.block
if (!props) return base; if (!props) return base
return this._handleProps(base, props); return this._handleProps(base, props)
} }
//Easily grab a simple element class //Easily grab a simple element class
elem(elementName) { elem(elementName) {
return this.build({ elementName }); return this.build({ elementName })
} }
//use if a different base is needed than whats defined by this.block //use if a different base is needed than whats defined by this.block
debase(base, elementProps) { debase(base, elementProps) {
if (!elementProps) return base; if (!elementProps) return base
return this._handleProps(base, elementProps); return this._handleProps(base, elementProps)
} }
//proxies bindProps and checks for which elementProps exist before binding //proxies bindProps and checks for which elementProps exist before binding
_handleProps(base, elementProps) { _handleProps(base, elementProps) {
let cls = base; let cls = base
const { modifiers, customs, extras } = elementProps; const { modifiers, customs, extras } = elementProps
if (!!modifiers) cls += this._bindProps(modifiers, base); if (modifiers) cls += this._bindProps(modifiers, base)
if (!!customs) cls += this._bindProps(customs, base, true); if (customs) cls += this._bindProps(customs, base, true)
if (!!extras) cls += ` ${extras.join(" ")}`; if (extras) cls += ` ${extras.join(" ")}`
return cls.trim(); return cls.trim()
} }
/* /*
@ -53,22 +53,22 @@ export default class ClassBuilder {
!!value && !!value &&
(!this.defaultIgnoreList || !this.defaultIgnoreList.includes(value)) (!this.defaultIgnoreList || !this.defaultIgnoreList.includes(value))
) { ) {
let classBase = isCustom ? `bbmd-${base}` : `${base}`; let classBase = isCustom ? `bbmd-${base}` : `${base}`
let valueType = typeof value; let valueType = typeof value
if (valueType == "string" || valueType == "number") { if (valueType == "string" || valueType == "number") {
return isCustom return isCustom
? ` ${classBase}--${this._convertCamel(property)}-${value}` ? ` ${classBase}--${this._convertCamel(property)}-${value}`
: ` ${classBase}--${value}`; : ` ${classBase}--${value}`
} else if (valueType == "boolean") { } else if (valueType == "boolean") {
return ` ${classBase}--${this._convertCamel(property)}`; return ` ${classBase}--${this._convertCamel(property)}`
} }
} }
}) })
.join(""); .join("")
} }
_convertCamel(str) { _convertCamel(str) {
return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`); return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`)
} }
} }

38
packages/materialdesign-components/src/Common/Formfield.svelte

@ -1,32 +1,32 @@
<script> <script>
import "@material/form-field/mdc-form-field.scss"; import "@material/form-field/mdc-form-field.scss"
import ClassBuilder from "../ClassBuilder.js"; import ClassBuilder from "../ClassBuilder.js"
import { fieldStore } from "./FormfieldStore.js"; import { fieldStore } from "./FormfieldStore.js"
import { MDCFormField } from "@material/form-field"; import { MDCFormField } from "@material/form-field"
import { onMount, onDestroy, setContext } from "svelte"; import { onMount, onDestroy, setContext } from "svelte"
const cb = new ClassBuilder("form-field"); const cb = new ClassBuilder("form-field")
let store; let store
const unsubscribe = fieldStore.subscribe(s => (store = s)); const unsubscribe = fieldStore.subscribe(s => (store = s))
export let id = ""; export let id = ""
export let label = ""; export let label = ""
export let alignEnd = false; export let alignEnd = false
let formField = null; let formField = null
let modifiers = { alignEnd }; let modifiers = { alignEnd }
let props = { modifiers }; let props = { modifiers }
let blockClasses = cb.build({ props }); let blockClasses = cb.build({ props })
onMount(() => { onMount(() => {
if (!!formField) fieldStore.set(new MDCFormField(formField)); if (!!formField) fieldStore.set(new MDCFormField(formField))
setContext("BBMD:field-element", fieldStore); setContext("BBMD:field-element", fieldStore)
}); })
onDestroy(unsubscribe); onDestroy(unsubscribe)
</script> </script>
<div bind:this={formField} class={blockClasses}> <div bind:this={formField} class={blockClasses}>

14
packages/materialdesign-components/src/Common/FormfieldStore.js

@ -1,19 +1,19 @@
import { writable } from "svelte/store"; import { writable } from "svelte/store"
function store() { function store() {
const { set, update, subscribe } = writable({}); const { set, update, subscribe } = writable({})
function setInput(inp) { function setInput(inp) {
update(n => { update(n => {
n.input = inp; n.input = inp
}); })
} }
return { return {
subscribe, subscribe,
set, set,
setInput setInput,
}; }
} }
export const fieldStore = store(); export const fieldStore = store()

8
packages/materialdesign-components/src/Common/Icon.svelte

@ -1,12 +1,12 @@
<script> <script>
import { getContext } from "svelte"; import { getContext } from "svelte"
export let icon = ""; export let icon = ""
let iconContext = getContext("BBMD:icon:context"); let iconContext = getContext("BBMD:icon:context")
let cls = iconContext let cls = iconContext
? `material-icons mdc-${iconContext}__icon` ? `material-icons mdc-${iconContext}__icon`
: "material-icons"; : "material-icons"
</script> </script>
<i class={cls}>{icon}</i> <i class={cls}>{icon}</i>

8
packages/materialdesign-components/src/Common/Label.svelte

@ -1,12 +1,12 @@
<script> <script>
export let bold = false; export let bold = false
export let text = ""; export let text = ""
</script> </script>
<span class="mdc-typography" class:bold>{text}</span>
<style> <style>
.bold { .bold {
font-weight: 500; font-weight: 500;
} }
</style> </style>
<span class="mdc-typography" class:bold>{text}</span>

15
packages/materialdesign-components/src/Datatable/Datatable.svelte

@ -17,12 +17,10 @@
let tableElement let tableElement
let initialied = false let initialied = false
$: { $: {
if(tableElement && datatable && !initialied) { if (tableElement && datatable && !initialied) {
const children = _bb.attachChildren(tableElement) const children = _bb.attachChildren(tableElement)
if(children.length > 0) { if (children.length > 0) {
instance = new MDCDataTable(datatable) instance = new MDCDataTable(datatable)
initialied = true initialied = true
} }
@ -34,7 +32,7 @@
return () => { return () => {
try { try {
!!instance && instance.destroy() !!instance && instance.destroy()
} catch(e) { } catch (e) {
console.log(e) console.log(e)
} }
instance = null instance = null
@ -43,7 +41,8 @@
</script> </script>
<div bind:this={datatable} class={cb.build()}> <div bind:this={datatable} class={cb.build()}>
<table class={cb.elem`table`} aria-label="Material Design Datatable" bind:this={tableElement}> <table
class={cb.elem`table`}
</table> aria-label="Material Design Datatable"
bind:this={tableElement} />
</div> </div>

13
packages/materialdesign-components/src/Datatable/DatatableBody.svelte

@ -1,14 +1,13 @@
<script> <script>
import { getContext } from "svelte" import { getContext } from "svelte"
export let _bb export let _bb
const cb = _bb.getContext("BBMD:data-table:cb") const cb = _bb.getContext("BBMD:data-table:cb")
let tbody let tbody
$: tbody && _bb.attachChildren(tbody)
$: tbody && _bb.attachChildren(tbody)
</script> </script>
<tbody bind:this={tbody} class={cb.elem`content`}></tbody> <tbody bind:this={tbody} class={cb.elem`content`} />

3
packages/materialdesign-components/src/Datatable/DatatableCell.svelte

@ -5,7 +5,7 @@
export let numeric = false export let numeric = false
export let _bb export let _bb
const cb = _bb.getContext("BBMD:data-table:cb") const cb = _bb.getContext("BBMD:data-table:cb")
let elementName = isHeader ? "header-cell" : "cell" let elementName = isHeader ? "header-cell" : "cell"
let modifiers = { numeric } let modifiers = { numeric }
@ -14,7 +14,6 @@
let element let element
$: element && _bb.attachChildren(element) $: element && _bb.attachChildren(element)
</script> </script>
{#if isHeader} {#if isHeader}

12
packages/materialdesign-components/src/Datatable/DatatableHead.svelte

@ -1,13 +1,11 @@
<script> <script>
export let _bb
export let _bb const cb = _bb.getContext("BBMD:data-table:cb")
const cb = _bb.getContext("BBMD:data-table:cb") let thead
let thead
$: thead && _bb.attachChildren(thead)
$: thead && _bb.attachChildren(thead)
</script> </script>
<thead bind:this={thead} class=className></thead> <thead bind:this={thead} class="className" />

28
packages/materialdesign-components/src/Datatable/DatatableRow.svelte

@ -1,27 +1,27 @@
<script> <script>
import { getContext } from "svelte"; import { getContext } from "svelte"
export let onSelect = () => {}; export let onSelect = () => {}
export let isHeader = false; export let isHeader = false
export let _bb export let _bb
let row = null; let row = null
let selected = false; let selected = false
const cb = _bb.getContext("BBMD:data-table:cb") const cb = _bb.getContext("BBMD:data-table:cb")
let elementName = isHeader ? "header-row" : "row"; let elementName = isHeader ? "header-row" : "row"
let modifiers = {}; let modifiers = {}
$: modifiers = { selected }; $: modifiers = { selected }
$: props = { modifiers }; $: props = { modifiers }
$: rowClass = cb.build({ elementName, props }); $: rowClass = cb.build({ elementName, props })
$: row && _bb.attachChildren(row) $: row && _bb.attachChildren(row)
function rowSelected() { function rowSelected() {
selected = !selected; selected = !selected
onSelect(); onSelect()
} }
</script> </script>

38
packages/materialdesign-components/src/Menu/Menu.svelte

@ -1,32 +1,32 @@
<script> <script>
import { List } from "../List"; import { List } from "../List"
import { MDCMenu } from "@material/menu"; import { MDCMenu } from "@material/menu"
import { onMount, setContext } from "svelte"; import { onMount, setContext } from "svelte"
export let items = []; export let items = []
export let singleSelection = true; export let singleSelection = true
export let width = "400px"; export let width = "400px"
export let open = true; export let open = true
export let useFixedPosition = false; export let useFixedPosition = false
export let useAbsolutePosition = false; export let useAbsolutePosition = false
//{x: number, y: number} //{x: number, y: number}
export let absolutePositionCoords = null; export let absolutePositionCoords = null
let menu = null; let menu = null
let instance = null; let instance = null
onMount(() => { onMount(() => {
if (!!menu) { if (!!menu) {
instance = new MDCMenu(menu); instance = new MDCMenu(menu)
instance.open = open; instance.open = open
if (useFixedPosition) { if (useFixedPosition) {
instance.setFixedPosition(true); instance.setFixedPosition(true)
} else if (useAbsolutePosition) { } else if (useAbsolutePosition) {
let { x, y } = absolutePositionCoords; let { x, y } = absolutePositionCoords
instance.setAbsolutePosition(x | 0, y | 0); instance.setAbsolutePosition(x | 0, y | 0)
} }
} }
setContext("BBMD:list:context", "menu"); setContext("BBMD:list:context", "menu")
}); })
</script> </script>
{#if useFixedPosition || useAbsolutePosition} {#if useFixedPosition || useAbsolutePosition}

4
packages/materialdesign-components/src/Menu/index.js

@ -1,2 +1,2 @@
import "./_styles.scss"; import "./_styles.scss"
export { default as Menu } from "./Menu.svelte"; export { default as Menu } from "./Menu.svelte"

6
packages/materialdesign-components/src/Radiobutton/index.js

@ -1,3 +1,3 @@
import "./_style.scss"; import "./_style.scss"
export { default as Radiobutton } from "./Radiobutton.svelte"; export { default as Radiobutton } from "./Radiobutton.svelte"
export { default as Radiobuttongroup } from "./RadiobuttonGroup.svelte"; export { default as Radiobuttongroup } from "./RadiobuttonGroup.svelte"

2
packages/materialdesign-components/src/Test/createApp.js

@ -4,7 +4,7 @@ import packageJson from "../../package.json"
import { rootComponent } from "./rootComponent" import { rootComponent } from "./rootComponent"
import * as standardcomponents from "@budibase/standard-components/src/index" import * as standardcomponents from "@budibase/standard-components/src/index"
export default async props => { export default async () => {
delete components._lib delete components._lib
const componentLibraries = {} const componentLibraries = {}
componentLibraries[packageJson.name] = components componentLibraries[packageJson.name] = components

6
packages/materialdesign-components/src/Textfield/Textfield.svelte

@ -68,7 +68,7 @@
} }
let useLabel = !!label && (!fullwidth || (fullwidth && textarea)) let useLabel = !!label && (!fullwidth || (fullwidth && textarea))
let useIcon = !!icon && (!textarea && !fullwidth) let useIcon = !!icon && !textarea && !fullwidth
if (useIcon) { if (useIcon) {
setContext("BBMD:icon:context", "text-field") setContext("BBMD:icon:context", "text-field")
@ -120,7 +120,7 @@ TODO:Needs error handling - this will depend on how Budibase handles errors
{placeholder} {placeholder}
{minLength} {minLength}
maxLength={safeMaxLength} maxLength={safeMaxLength}
value={value} {value}
on:change={changed} /> on:change={changed} />
{:else} {:else}
{#if renderLeadingIcon} {#if renderLeadingIcon}
@ -135,7 +135,7 @@ TODO:Needs error handling - this will depend on how Budibase handles errors
placeholder={!!label && fullwidth ? label : placeholder} placeholder={!!label && fullwidth ? label : placeholder}
{minLength} {minLength}
maxLength={safeMaxLength} maxLength={safeMaxLength}
value={value} {value}
aria-label={`Textfield ${variant}`} aria-label={`Textfield ${variant}`}
on:focus={focus} on:focus={focus}
on:input={changed} /> on:input={changed} />

2
packages/materialdesign-components/src/Textfield/index.js

@ -1,2 +1,2 @@
import "./_index.scss" import "./_index.scss"
export { default as Textfield } from "./Textfield.svelte" export { default as Textfield } from "./Textfield.svelte"

26
packages/materialdesign-components/src/Typography/index.js

@ -1,13 +1,13 @@
import "./_style.scss"; import "./_style.scss"
export { default as Body1 } from "./Body1.svelte"; export { default as Body1 } from "./Body1.svelte"
export { default as Body2 } from "./Body2.svelte"; export { default as Body2 } from "./Body2.svelte"
export { default as Caption } from "./Caption.svelte"; export { default as Caption } from "./Caption.svelte"
export { default as H1 } from "./H1.svelte"; export { default as H1 } from "./H1.svelte"
export { default as H2 } from "./H2.svelte"; export { default as H2 } from "./H2.svelte"
export { default as H3 } from "./H3.svelte"; export { default as H3 } from "./H3.svelte"
export { default as H4 } from "./H4.svelte"; export { default as H4 } from "./H4.svelte"
export { default as H5 } from "./H5.svelte"; export { default as H5 } from "./H5.svelte"
export { default as H6 } from "./H6.svelte"; export { default as H6 } from "./H6.svelte"
export { default as Overline } from "./Overline.svelte"; export { default as Overline } from "./Overline.svelte"
export { default as Sub1 } from "./Sub1.svelte"; export { default as Sub1 } from "./Sub1.svelte"
export { default as Sub2 } from "./Sub2.svelte"; export { default as Sub2 } from "./Sub2.svelte"

2
packages/server/appPackages/testApp/plugins.js

@ -1,6 +1,6 @@
const fs = require("fs") const fs = require("fs")
module.exports = config => ({ module.exports = () => ({
main: { main: {
outputToFile: async ({ filename, content }) => { outputToFile: async ({ filename, content }) => {
await new Promise((resolve, reject) => { await new Promise((resolve, reject) => {

54511
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

2
packages/server/appPackages/testApp/public/main/clientFrontendDefinition.js

@ -1,2 +1,2 @@
window['##BUDIBASE_FRONTEND_DEINITION##'] = {"componentLibraries":[{"importPath":"/lib/customComponents/index.js","libName":"./customComponents"},{"importPath":"/lib/moreCustomComponents/index.js","libName":"./moreCustomComponents"}],"appRootPath":"","page":{"title":"Test App","favicon":"./_shared/favicon.png","stylesheets":["my-styles.css"],"componentLibraries":["./customComponents","./moreCustomComponents"],"props":{"_component":"@budibase/standard-components/container"}},"screens":[{"name":"screen1","description":"","props":{"_component":"@budibase/standard-components/container","className":""},"_css":"/css/d121e1ecc6cf44f433213222e9ff5d40.css"},{"name":"screen2","description":"","props":{"_component":"@budibase/standard-components/container","className":""},"_css":"/css/7b7c05b78e05c06eb8d69475caadfea3.css"}]}; window['##BUDIBASE_FRONTEND_DEFINITION##'] = {"componentLibraries":[{"importPath":"/lib/customComponents/index.js","libName":"./customComponents"},{"importPath":"/lib/moreCustomComponents/index.js","libName":"./moreCustomComponents"}],"appRootPath":"","page":{"title":"Test App","favicon":"./_shared/favicon.png","stylesheets":["my-styles.css"],"componentLibraries":["./customComponents","./moreCustomComponents"],"props":{"_component":"@budibase/standard-components/container","type":"div"}},"screens":[{"name":"screen1","description":"","props":{"_component":"@budibase/standard-components/container","className":"","type":"div"},"_css":"/css/d121e1ecc6cf44f433213222e9ff5d40.css"},{"name":"screen2","description":"","props":{"_component":"@budibase/standard-components/container","className":"","type":"div"},"_css":"/css/7b7c05b78e05c06eb8d69475caadfea3.css"}]};
window['##BUDIBASE_FRONTEND_FUNCTIONS##'] = {'1234':() => 'test return'} window['##BUDIBASE_FRONTEND_FUNCTIONS##'] = {'1234':() => 'test return'}

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

@ -11,26 +11,21 @@
html, body { html, body {
height: 100%; height: 100%;
width: 100%; width: 100%;
margin: 0px;
padding: 0px;
} }
</style> </style>
<link rel='stylesheet' href='//my-styles.css'>
<link rel='stylesheet' href='//my-styles.css'> <link rel='stylesheet' href='/css/d121e1ecc6cf44f433213222e9ff5d40.css'>
<link rel='stylesheet' href='/css/7b7c05b78e05c06eb8d69475caadfea3.css'>
<link rel='stylesheet' href='/css/f66fc2928f7d850c946e619c1a1f3096.css'>
<link rel='stylesheet' href='/css/d121e1ecc6cf44f433213222e9ff5d40.css'>
<link rel='stylesheet' href='/css/7b7c05b78e05c06eb8d69475caadfea3.css'>
<link rel='stylesheet' href='/css/f66fc2928f7d850c946e619c1a1f3096.css'>
<script src='/_master/clientFrontendDefinition.js'></script> <script src='/clientFrontendDefinition.js'></script>
<script src='/_master/clientBackendDefinition.js'></script> <script src='/clientBackendDefinition.js'></script>
<script src='/budibase-client.js'></script> <script src='/budibase-client.js'></script>
<script> <script>
loadBudibase(); loadBudibase();

2
packages/server/appPackages/testApp2/plugins.js

@ -1 +1 @@
module.exports = config => ({}) module.exports = () => ({})

64
packages/server/initialise/createInstanceDb.js

@ -4,38 +4,34 @@ const { applictionVersionPackage } = require("../utilities/createAppPackage")
const { determineVersionId } = require("../utilities/runtimePackages") const { determineVersionId } = require("../utilities/runtimePackages")
module.exports = async (context, datastoreModule, app, instance) => { module.exports = async (context, datastoreModule, app, instance) => {
try { const databaseManager = getDatabaseManager(
const databaseManager = getDatabaseManager( datastoreModule,
datastoreModule, context.config.datastoreConfig
context.config.datastoreConfig )
)
await databaseManager.createEmptyInstanceDb(app.id, instance.id)
await databaseManager.createEmptyInstanceDb(app.id, instance.id)
const dbConfig = databaseManager.getInstanceDatastoreConfig(
const dbConfig = databaseManager.getInstanceDatastoreConfig( app.id,
app.id, instance.id
instance.id )
)
const datastore = setupDatastore(datastoreModule.getDatastore(dbConfig))
const datastore = setupDatastore(datastoreModule.getDatastore(dbConfig))
const versionId = determineVersionId(instance.version)
const versionId = determineVersionId(instance.version)
const appPackage = await applictionVersionPackage(
const appPackage = await applictionVersionPackage( context,
context, app.name,
app.name, versionId,
versionId, instance.key
instance.key )
)
await initialiseData(
await initialiseData( datastore,
datastore, appPackage.appDefinition,
appPackage.appDefinition, appPackage.accessLevels
appPackage.accessLevels )
)
return dbConfig
return dbConfig
} catch (e) {
throw e
}
} }

40
packages/server/initialise/createMasterDb.js

@ -10,31 +10,25 @@ const masterDbAccessLevels = require("../appPackages/_master/access_levels.json"
const { masterAppPackage } = require("../utilities/createAppPackage") const { masterAppPackage } = require("../utilities/createAppPackage")
module.exports = async (context, datastoreModule, username, password) => { module.exports = async (context, datastoreModule, username, password) => {
try { const { config } = context
const { config } = context const databaseManager = getDatabaseManager(
const databaseManager = getDatabaseManager( datastoreModule,
datastoreModule, config.datastoreConfig
config.datastoreConfig )
)
await databaseManager.createEmptyMasterDb() await databaseManager.createEmptyMasterDb()
const masterDbConfig = databaseManager.masterDatastoreConfig const masterDbConfig = databaseManager.masterDatastoreConfig
const datastore = setupDatastore( const datastore = setupDatastore(datastoreModule.getDatastore(masterDbConfig))
datastoreModule.getDatastore(masterDbConfig)
)
await initialiseData(datastore, constructHierarchy(masterDbAppDefinition)) await initialiseData(datastore, constructHierarchy(masterDbAppDefinition))
const masterPackage = masterAppPackage(context) const masterPackage = masterAppPackage(context)
const bbMaster = await getApisWithFullAccess(datastore, masterPackage) const bbMaster = await getApisWithFullAccess(datastore, masterPackage)
await bbMaster.authApi.saveAccessLevels(masterDbAccessLevels) await bbMaster.authApi.saveAccessLevels(masterDbAccessLevels)
const user = bbMaster.authApi.getNewUser() const user = bbMaster.authApi.getNewUser()
user.name = username user.name = username
user.accessLevels = ["owner"] user.accessLevels = ["owner"]
await bbMaster.authApi.createUser(user, password) await bbMaster.authApi.createUser(user, password)
return await getApisForUser(datastore, masterPackage, username, password) return await getApisForUser(datastore, masterPackage, username, password)
} catch (e) {
throw e
}
} }

14
packages/server/initialise/initialiseRuntimePackages.js

@ -13,7 +13,9 @@ const copyfolder = (source, destination) =>
}) })
}) })
module.exports = async (context, bbMaster, latestAppsFolder) => { exports.copyfolder = copyfolder
module.exports = async context => {
// create runtime folder // create runtime folder
// copy master into /master/latest // copy master into /master/latest
if (await pathExists(runtimePackagesDirectory)) { if (await pathExists(runtimePackagesDirectory)) {
@ -26,16 +28,6 @@ module.exports = async (context, bbMaster, latestAppsFolder) => {
await mkdir(runtimePackagesDirectory) await mkdir(runtimePackagesDirectory)
/*
const allApps = await bbMaster
.indexApi
.listItems("/all_applications");
for(let app of allApps) {
app.
}
*/
const apps = { const apps = {
_master: masterAppPackage(context), _master: masterAppPackage(context),
} }

6
packages/server/middleware/routers.js

@ -141,7 +141,11 @@ module.exports = (config, app) => {
}) })
.get("/_builder/api/:appname/components", async ctx => { .get("/_builder/api/:appname/components", async ctx => {
try { try {
ctx.body = getComponentDefinitions(config, ctx.params.appname, ctx.query.lib) ctx.body = getComponentDefinitions(
config,
ctx.params.appname,
ctx.query.lib
)
ctx.response.status = StatusCodes.OK ctx.response.status = StatusCodes.OK
} catch (e) { } catch (e) {
if (e.status) { if (e.status) {

6
packages/server/middleware/session.js

@ -14,9 +14,9 @@ module.exports = (config, app) => {
rolling: false /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. (default is false) */, rolling: false /** (boolean) Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown. (default is false) */,
renew: false /** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/, renew: false /** (boolean) renew session when session is nearly expired, so we can always keep user logged in. (default is false)*/,
store: { store: {
get: async (key, maxAge, { rolling }) => ({ key }), get: async key => ({ key }),
set: async (key, sess, maxAge, { rolling, changed }) => ({ key }), set: async key => ({ key }),
destroy: async key => ({}), destroy: async () => ({}),
}, },
} }

1
packages/server/tests/builder.spec.js

@ -25,6 +25,7 @@ beforeAll(async () => {
await app.start() await app.start()
}) })
afterAll(async () => await app.destroy()) afterAll(async () => await app.destroy())
it("/apppackage should get appDefinition", async () => { it("/apppackage should get appDefinition", async () => {

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save