component library modules and definitions refactor - moved to backend. More routing and middleware reorganisation
This commit is contained in:
parent
3564fec064
commit
5b4bce8b8f
|
@ -1,5 +0,0 @@
|
|||
.DS_Store
|
||||
node_modules
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
dist/index.js
|
|
@ -1,33 +0,0 @@
|
|||
*Psst — looking for an app template? Go here --> [sveltejs/template](https://github.com/sveltejs/template)*
|
||||
|
||||
---
|
||||
|
||||
# component-template
|
||||
|
||||
A base for building shareable Svelte components. Clone it with [degit](https://github.com/Rich-Harris/degit):
|
||||
|
||||
```bash
|
||||
npx degit sveltejs/component-template my-new-component
|
||||
cd my-new-component
|
||||
npm install # or yarn
|
||||
```
|
||||
|
||||
Your component's source code lives in `src/index.html`.
|
||||
|
||||
TODO
|
||||
|
||||
* [ ] some firm opinions about the best way to test components
|
||||
* [ ] update `degit` so that it automates some of the setup work
|
||||
|
||||
|
||||
## Setting up
|
||||
|
||||
* Run `npm init` (or `yarn init`)
|
||||
* Replace this README with your own
|
||||
|
||||
|
||||
## Consuming components
|
||||
|
||||
Your package.json has a `"svelte"` field pointing to `src/index.html`, which allows Svelte apps to import the source code directly, if they are using a bundler plugin like [rollup-plugin-svelte](https://github.com/rollup/rollup-plugin-svelte) or [svelte-loader](https://github.com/sveltejs/svelte-loader) (where [`resolve.mainFields`](https://webpack.js.org/configuration/resolve/#resolve-mainfields) in your webpack config includes `"svelte"`). **This is recommended.**
|
||||
|
||||
For everyone else, `npm run build` will bundle your component's source code into a plain JavaScript module (`index.mjs`) and a UMD script (`index.js`). This will happen automatically when you publish your component to npm, courtesy of the `prepublishOnly` hook in package.json.
|
|
@ -1,47 +0,0 @@
|
|||
{
|
||||
"_lib": "./dist/index.js",
|
||||
"form" : {
|
||||
"importPath": "Form",
|
||||
"name": "Form",
|
||||
"description": "A form - allgned fields with labels",
|
||||
"props" : {
|
||||
"containerClass": "string",
|
||||
"formControls": {
|
||||
"type":"array",
|
||||
"elementDefinition": {
|
||||
"label": "string",
|
||||
"control":"component",
|
||||
"controlPosition": {
|
||||
"type":"options",
|
||||
"options": ["Before Label","After Label"],
|
||||
"default": "After Label"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": ["form"]
|
||||
},
|
||||
"nav": {
|
||||
"importPath": "Nav",
|
||||
"name": "Nav",
|
||||
"description": "A nav - a side bar of buttons that control the currently active component",
|
||||
"props" : {
|
||||
"items": {
|
||||
"type": "array",
|
||||
"elementDefinition" : {
|
||||
"title": "string",
|
||||
"component": "component"
|
||||
}
|
||||
},
|
||||
"selectedItem":"string",
|
||||
"pills":"bool",
|
||||
"orientation":{"type":"options", "options": ["horizontal", "vertical"]},
|
||||
"alignment":{"type":"options", "options": ["start", "center", "end"]},
|
||||
"fill":"bool",
|
||||
"hideNavBar":"bool",
|
||||
"className": "string"
|
||||
|
||||
},
|
||||
"tags": ["nav", "navigation", "sidebar"]
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -1,36 +0,0 @@
|
|||
{
|
||||
"name": "@budibase/bootstrap-components",
|
||||
"svelte": "src/index.svelte",
|
||||
"main": "dist/index.js",
|
||||
"module": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "rollup -c",
|
||||
"prepublishOnly": "npm run build",
|
||||
"testbuild": "rollup -w -c rollup.testconfig.js",
|
||||
"dev": "run-p start:dev testbuild",
|
||||
"start:dev": "sirv public --single --dev",
|
||||
"publishdev": "yarn build && node ./scripts/publishDev.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@budibase/client": "^0.0.32",
|
||||
"fs-extra": "^8.1.0",
|
||||
"lodash": "^4.17.15",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^1.11.0",
|
||||
"rollup-plugin-commonjs": "^10.0.2",
|
||||
"rollup-plugin-json": "^4.0.0",
|
||||
"rollup-plugin-livereload": "^1.0.1",
|
||||
"rollup-plugin-node-resolve": "^5.0.0",
|
||||
"rollup-plugin-svelte": "^5.0.0",
|
||||
"rollup-plugin-terser": "^5.1.1",
|
||||
"shortid": "^2.2.15",
|
||||
"sirv-cli": "^0.4.4",
|
||||
"svelte": "^3.12.1"
|
||||
},
|
||||
"keywords": [
|
||||
"svelte"
|
||||
],
|
||||
"version": "0.0.32",
|
||||
"license": "MIT",
|
||||
"gitHead": "b1f4f90927d9e494e513220ef060af28d2d42455"
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 12 KiB |
|
@ -1,13 +0,0 @@
|
|||
#current_component.svelte-1xqz9vm{height:100%;width:100%}
|
||||
.root.svelte-10kw8to{display:grid}
|
||||
.root.svelte-crnq0a{height:100%;display:grid;grid-template-columns:[left] 1fr [middle] auto [right] 1fr;grid-template-rows:[top] 1fr [center] auto [bottom] 1fr}.content.svelte-crnq0a{grid-column-start:middle;grid-row-start:center;width:400px}.logo-container.svelte-crnq0a{margin-bottom:20px
|
||||
}.logo-container.svelte-crnq0a>img.svelte-crnq0a{max-width:100%}.login-button-container.svelte-crnq0a{text-align:right;margin-top:20px}.incorrect-details-panel.svelte-crnq0a{margin-top:30px;padding:10px;border-style:solid;border-width:1px;border-color:maroon;border-radius:1px;text-align:center;color:maroon;background-color:mistyrose}.form-root.svelte-crnq0a{display:grid;grid-template-columns:[label] auto [control] 1fr}.label.svelte-crnq0a{grid-column-start:label;padding:5px 10px;vertical-align:middle}.control.svelte-crnq0a{grid-column-start:control;padding:5px 10px}.default-input.svelte-crnq0a{font-family:inherit;font-size:inherit;padding:0.4em;margin:0 0 0.5em 0;box-sizing:border-box;border:1px solid #ccc;border-radius:2px;width:100%}.default-button.svelte-crnq0a{font-family:inherit;font-size:inherit;padding:0.4em;margin:0 0 0.5em 0;box-sizing:border-box;border:1px solid #ccc;border-radius:2px;color:#333;background-color:#f4f4f4;outline:none}.default-button.svelte-crnq0a:active{background-color:#ddd}.default-button.svelte-crnq0a:focus{border-color:#666}
|
||||
.form-root.svelte-m9d6ue{display:grid;grid-template-columns:[label] auto [control] 1fr}.label.svelte-m9d6ue{grid-column-start:label;padding:5px 10px;vertical-align:middle}.control.svelte-m9d6ue{grid-column-start:control;padding:5px 10px}.overflow.svelte-m9d6ue{grid-column-start:overflow}.full-width.svelte-m9d6ue{width:100%}
|
||||
.root.svelte-aihwli{height:100%;width:100%;grid-template-columns:[navbar] auto [content] 1fr;display:grid}.navbar.svelte-aihwli{grid-column:navbar;background:var(--navBarBackground);border:var(--navBarBorder);color:var(--navBarColor)}.navitem.svelte-aihwli{padding:10px 17px;cursor:pointer}.navitem.svelte-aihwli:hover{background:var(--itemHoverBackground);color:var(--itemHoverColor)}.navitem.selected.svelte-aihwli{background:var(--selectedItemBackground);border:var(--selectedItemBorder);color:var(--selectedItemColor)}.content.svelte-aihwli{grid-column:content}
|
||||
.default.svelte-1ec4wqj{width:100%;font-family:inherit;font-size:inherit;padding:0.4em;margin:0 0 0.5em 0;box-sizing:border-box;border:1px solid #ccc;border-radius:2px;width:100%}.default.svelte-1ec4wqj:disabled{color:#ccc}
|
||||
.panel.svelte-6yfcjx:hover{background:var(--hoverBackground);color:var(--hoverColor)}
|
||||
.horizontal.svelte-osi0db{display:inline-block}.vertical.svelte-osi0db{display:block}
|
||||
.table-default.svelte-h8rqk6{width:100%;margin-bottom:1rem;color:#212529;border-collapse:collapse}.table-default.svelte-h8rqk6 .thead-default .th-default.svelte-h8rqk6{vertical-align:bottom;border-bottom:2px solid #dee2e6;font-weight:bold}.table-default.svelte-h8rqk6 .th-default.svelte-h8rqk6{padding:.75rem;vertical-align:top;border-top:1px solid #dee2e6;font-weight:normal}.th-default.svelte-h8rqk6{text-align:inherit}.table-default.svelte-h8rqk6 .tbody-default .tr-default.svelte-h8rqk6:hover{color:#212529;background-color:rgba(0,0,0,.075);cursor:pointer}
|
||||
.default.svelte-1q8lga0{font-family:inherit;font-size:inherit;padding:0.4em;margin:0 0 0.5em 0;box-sizing:border-box;border:1px solid #ccc;border-radius:2px;color:#333;background-color:#f4f4f4;outline:none}.default.svelte-1q8lga0:active{background-color:#ddd}.default.svelte-1q8lga0:focus{border-color:#666}
|
||||
|
||||
/*# sourceMappingURL=bundle.css.map */
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
"version": 3,
|
||||
"file": "bundle.css",
|
||||
"sources": [
|
||||
"..\\src\\Test\\TestApp.svelte",
|
||||
"..\\src\\Grid.svelte",
|
||||
"..\\src\\Login.svelte",
|
||||
"..\\src\\Form.svelte",
|
||||
"..\\src\\Nav.svelte",
|
||||
"..\\src\\Textbox.svelte",
|
||||
"..\\src\\Panel.svelte",
|
||||
"..\\src\\StackPanel.svelte",
|
||||
"..\\src\\Table.svelte",
|
||||
"..\\src\\Button.svelte"
|
||||
],
|
||||
"sourcesContent": [
|
||||
"<script>\nimport createApp from \"./createApp\";\nimport { props } from \"./props\";\n\nlet _bb;\n\nconst _appPromise = createApp();\n_appPromise.then(a => _bb = a);\n\nconst testProps = props.hiddenNav;\n\nlet currentComponent;\n\n$: {\n if(_bb && currentComponent) {\n _bb.initialiseComponent(testProps, currentComponent);\n }\n}\n\n\n\n</script>\n\n{#await _appPromise}\nloading\n{:then _bb}\n\n<div id=\"current_component\" bind:this={currentComponent}>\n</div>\n\n{/await}\n\n\n<style>\n#current_component {\n height: 100%;\n width: 100%;\n}\n</style>\n\n",
|
||||
"<script>\r\nimport { onMount } from 'svelte'\r\nimport {buildStyle} from \"./buildStyle\";\r\n\r\nexport let gridTemplateRows =\"\";\r\nexport let gridTemplateColumns =\"\";\r\nexport let children = [];\r\nexport let width = \"auto\";\r\nexport let height = \"auto\";\r\nexport let containerClass=\"\";\r\nexport let itemContainerClass=\"\";\r\n\r\n/*\"gridColumnStart\":\"string\",\r\n\"gridColumnEnd\":\"string\",\r\n\"gridRowStart\":\"string\",\r\n\"gridRowEnd\":\"string\"*/\r\n\r\n\r\nexport let _bb;\r\n\r\nlet style=\"\";\r\nlet htmlElements = {};\r\n\r\n$ : {\r\n if(_bb && htmlElements) {\r\n for(let el in htmlElements) {\r\n _bb.initialiseComponent(\r\n children[el].control,\r\n htmlElements[el]\r\n );\r\n }\r\n }\r\n}\r\n\r\nconst childStyle = child => \r\n buildStyle({\r\n \"grid-column-start\": child.gridColumnStart,\r\n \"grid-column-end\": child.gridColumnEnd,\r\n \"grid-column\": child.gridColumn,\r\n \"grid-row-start\": child.gridRowStart,\r\n \"grid-row-end\": child.gridRowStart,\r\n \"grid-row\": child.gridRow,\r\n });\r\n\r\n</script>\r\n\r\n<div class=\"root {containerClass}\"\r\n style=\"width: {width}; height: {height}; grid-template-columns: {gridTemplateColumns}; grid-template-rows: {gridTemplateRows};\">\r\n {#each children as child, index}\r\n <div class=\"{itemContainerClass}\"\r\n style={childStyle(child)}\r\n bind:this={htmlElements[index]}>\r\n </div>\r\n {/each}\r\n</div>\r\n\r\n<style>\r\n\r\n.root {\r\n display: grid;\r\n}\r\n\r\n</style>",
|
||||
"<script>\n\nimport Textbox from \"./Textbox.svelte\";\nimport Form from \"./Form.svelte\";\nimport Button from \"./Button.svelte\";\n\nexport let usernameLabel = \"Username\";\nexport let passwordLabel = \"Password\";\nexport let loginButtonLabel = \"Login\";\nexport let loginRedirect = \"\";\nexport let logo = \"\";\nexport let buttonClass = \"\";\nexport let inputClass=\"\"\n\nexport let _bb;\n\nlet username = \"\";\nlet password = \"\";\nlet busy = false;\nlet incorrect = false;\nlet _logo = \"\";\nlet _buttonClass = \"\";\nlet _inputClass = \"\";\n\n$: {\n _logo = _bb.relativeUrl(logo);\n _buttonClass = buttonClass || \"default-button\";\n _inputClass = inputClass || \"default-input\";\n}\n\nconst login = () => {\n busy = true;\n _bb.api.post(\"/api/authenticate\", {username, password})\n .then(r => {\n busy = false;\n if(r.status === 200) {\n return r.json();\n } else {\n incorrect = true;\n return;\n }\n })\n .then(user => {\n if(user) {\n localStorage.setItem(\"budibase:user\", user);\n location.reload();\n }\n })\n}\n\n</script>\n\n<div class=\"root\">\n\n <div class=\"content\">\n\n {#if _logo}\n <div class=\"logo-container\">\n <img src={_logo} alt=\"logo\"/>\n </div>\n {/if}\n\n <div class=\"form-root\">\n <div class=\"label\">\n {usernameLabel}\n </div>\n <div class=\"control\">\n <input bind:value={username} type=\"text\" class={_inputClass}/>\n </div>\n <div class=\"label\">\n {passwordLabel}\n </div>\n <div class=\"control\">\n <input bind:value={password} type=\"password\" class={_inputClass}/>\n </div>\n </div>\n\n <div class=\"login-button-container\">\n <button disabled={busy} \n on:click={login}\n class={_buttonClass}>\n {loginButtonLabel}\n </button>\n </div>\n\n {#if incorrect}\n <div class=\"incorrect-details-panel\">\n Incorrect username or password\n </div>\n {/if}\n\n </div>\n\n</div>\n\n<style>\n\n.root {\n height: 100%;\n display:grid;\n grid-template-columns: [left] 1fr [middle] auto [right] 1fr;\n grid-template-rows: [top] 1fr [center] auto [bottom] 1fr;\n}\n\n.content {\n grid-column-start: middle;\n grid-row-start: center;\n width: 400px;\n}\n\n.logo-container {\n margin-bottom: 20px\n}\n\n.logo-container > img {\n max-width: 100%;\n}\n\n.login-button-container {\n text-align: right;\n margin-top: 20px;\n}\n\n.incorrect-details-panel {\n margin-top: 30px;\n padding: 10px;\n border-style: solid;\n border-width: 1px;\n border-color: maroon;\n border-radius: 1px;\n text-align: center;\n color: maroon;\n background-color: mistyrose;\n}\n\n.form-root {\n display: grid;\n grid-template-columns: [label] auto [control] 1fr; /* [overflow] auto;*/\n}\n\n.label {\n grid-column-start: label;\n padding: 5px 10px;\n vertical-align: middle;\n}\n.control {\n grid-column-start: control;\n padding: 5px 10px;\n}\n\n.default-input {\n\tfont-family: inherit;\n\tfont-size: inherit;\n\tpadding: 0.4em;\n\tmargin: 0 0 0.5em 0;\n\tbox-sizing: border-box;\n\tborder: 1px solid #ccc;\n border-radius: 2px;\n width: 100%;\n}\n\n.default-button {\n\tfont-family: inherit;\n\tfont-size: inherit;\n\tpadding: 0.4em;\n\tmargin: 0 0 0.5em 0;\n\tbox-sizing: border-box;\n\tborder: 1px solid #ccc;\n\tborder-radius: 2px;\n\tcolor: #333;\n\tbackground-color: #f4f4f4;\n\toutline: none;\n}\n\n.default-button:active {\n\tbackground-color: #ddd;\n}\n\n.default-button:focus {\n\tborder-color: #666;\n}\n\n</style>",
|
||||
"<script>\nexport let containerClass = \"\";\nexport let formControls = [];\n\nexport let _bb;\n\nlet htmlElements = {};\nlet labels = {};\n\n$ : {\n let cIndex = 0;\n for(let c of formControls) {\n labels[cIndex] = c.label;\n cIndex++;\n }\n\n if(_bb && htmlElements) {\n for(let el in htmlElements) {\n _bb.initialiseComponent(\n formControls[el].control,\n htmlElements[el]\n );\n }\n }\n}\n\n</script>\n\n<div class=\"form-root {containerClass}\">\n {#each formControls as child, index}\n <div class=\"label\">{labels[index]}</div>\n <div class=\"control\"\n bind:this={htmlElements[index]}>\n </div>\n {/each}\n</div>\n\n<style>\n.form-root {\n display: grid;\n grid-template-columns: [label] auto [control] 1fr; /* [overflow] auto;*/\n}\n\n.label {\n grid-column-start: label;\n padding: 5px 10px;\n vertical-align: middle;\n}\n.control {\n grid-column-start: control;\n padding: 5px 10px;\n}\n.overflow {\n grid-column-start: overflow;\n}\n.full-width {\n width: 100%;\n}\n</style>",
|
||||
"<script>\r\nimport cssVars from \"./cssVars\";\r\n\r\nexport let navBarBackground = \"\";\r\nexport let navBarBorder=\"\";\r\nexport let navBarColor=\"\";\r\nexport let selectedItemBackground=\"\";\r\nexport let selectedItemColor=\"\";\r\nexport let selectedItemBorder=\"\";\r\nexport let itemHoverBackground=\"\";\r\nexport let itemHoverColor=\"\";\r\nexport let items = [];\r\nexport let hideNavBar=false;\r\nexport let selectedItem=\"\";\r\n\r\nexport let _bb;\r\n\r\nlet selectedIndex = -1;\r\nlet styleVars={};\r\nlet components = {};\r\nlet componentElements = {}\r\n\r\n\r\nconst hasComponentElements = () => \r\n Object.getOwnPropertyNames(componentElements).length > 0;\r\n\r\n$: {\r\n styleVars = {\r\n navBarBackground, navBarBorder,\r\n navBarColor, selectedItemBackground,\r\n selectedItemColor, selectedItemBorder,\r\n itemHoverBackground, itemHoverColor\r\n };\r\n\r\n if(items && items.length > 0 && hasComponentElements()) {\r\n const currentSelectedItem = selectedIndex > 0\r\n ? items[selectedIndex].title\r\n : \"\";\r\n if(selectedItem && currentSelectedItem !== selectedItem) {\r\n let i=0;\r\n for(let item of items) {\r\n if(item.title === selectedItem) {\r\n onSelectItem(i)();\r\n }\r\n i++;\r\n }\r\n } else if(!currentSelectedItem) {\r\n onSelectItem(0);\r\n }\r\n }\r\n}\r\n\r\nconst onSelectItem = (index) => () => {\r\n selectedIndex = index;\r\n if(!components[index]) {\r\n const comp = _bb.initialiseComponent(\r\n items[index].component, componentElements[index]);\r\n components[index] = comp; \r\n }\r\n}\r\n\r\n\r\n</script>\r\n\r\n<div class=\"root\" use:cssVars={styleVars}>\r\n {#if !hideNavBar}\r\n <div class=\"navbar\">\r\n {#each items as navItem, index}\r\n <div class=\"navitem\"\r\n on:click={onSelectItem(index)}\r\n class:selected={selectedIndex === index}>\r\n {navItem.title}\r\n </div>\r\n {/each}\r\n </div>\r\n {/if}\r\n {#each items as navItem, index}\r\n\r\n <div class=\"content\"\r\n bind:this={componentElements[index]}>\r\n </div>\r\n {/each}\r\n</div>\r\n\r\n<style>\r\n\r\n.root {\r\n height: 100%;\r\n width:100%;\r\n grid-template-columns: [navbar] auto [content] 1fr;\r\n display: grid;\r\n}\r\n\r\n.navbar {\r\n grid-column: navbar;\r\n background: var(--navBarBackground);\r\n border: var(--navBarBorder);\r\n color: var(--navBarColor);\r\n}\r\n\r\n.navitem {\r\n padding: 10px 17px;\r\n cursor: pointer;\r\n}\r\n\r\n.navitem:hover {\r\n background: var(--itemHoverBackground);\r\n color: var(--itemHoverColor);\r\n}\r\n\r\n.navitem.selected {\r\n background: var(--selectedItemBackground);\r\n border: var(--selectedItemBorder);\r\n color: var(--selectedItemColor);\r\n}\r\n\r\n.content {\r\n grid-column: content;\r\n}\r\n\r\n</style>\r\n\r\n",
|
||||
"<script>\n\nexport let value=\"\";\nexport let hideValue = false;\nexport let className = \"default\";\n\nexport let _bb;\n\nlet actualValue = \"\";\n$: {\n\tif(_bb && value._isstate) {\n\t\t_bb.store.subscribe(s => {\n\t\t\tactualValue = _bb.store.getValue(s, value);\n\t\t});\n\t}\n}\n\nconst onchange = (ev) => {\n\tif(_bb && value._isstate) {\n\t\t_bb.store.setValue(value, ev.target.value);\n\t} else if(!value._isstate) {\n\t\tactualValue = ev.target.value;\n\t}\n}\n\n</script>\n\n{#if hideValue}\n<input class={className} \n\t type=\"password\" \n\t value={actualValue} on:change/>\n{:else}\n<input class={className} type=\"text\" value={actualValue}/>\n{/if}\n\n<style>\n.default {\n width: 100%;\n\tfont-family: inherit;\n\tfont-size: inherit;\n\tpadding: 0.4em;\n\tmargin: 0 0 0.5em 0;\n\tbox-sizing: border-box;\n\tborder: 1px solid #ccc;\n border-radius: 2px;\n width: 100%;\n}\n\n.default:disabled {\n\tcolor: #ccc;\n}\n\n</style>",
|
||||
"<script>\r\nimport {buildStyle} from \"./buildStyle\";\r\nimport cssVars from \"./cssVars\";\r\n\r\nexport let component=\"\";\r\nexport let text=\"\";\r\nexport let containerClass=\"\";\r\nexport let background=\"\";\r\nexport let border=\"\";\r\nexport let borderRadius=\"\";\r\nexport let font=\"\";\r\nexport let display=\"\";\r\nexport let textAlign=\"\";\r\nexport let color=\"\";\r\nexport let padding=\"\";\r\nexport let margin=\"\";\r\nexport let hoverBackground=\"\";\r\nexport let hoverColor=\"\";\r\nexport let onClick;\r\nexport let height;\r\nexport let width;\r\n\r\nexport let _bb;\r\n\r\nlet styleVars;\r\nlet style=\"\";\r\nlet componentElement;\r\n\r\n$: {\r\n style=buildStyle({\r\n border, background, font, margin,\r\n padding, display, color, height, width,\r\n \"text-align\": textAlign,\r\n \"border-radius\":borderRadius,\r\n cursor: onClick ? \"pointer\" : \"none\"\r\n });\r\n\r\n if(_bb && component) {\r\n _bb.initialiseComponent(component, componentElement);\r\n }\r\n\r\n styleVars = {\r\n hoverBackground:hoverBackground || background, \r\n hoverColor:hoverColor || color\r\n }\r\n}\r\n\r\nconst clickHandler = () => {\r\n if(onClick) onClick();\r\n}\r\n\r\n</script>\r\n\r\n<div class=\"{containerClass} panel\" \r\n style={style}\r\n use:cssVars={styleVars}\r\n this:bind={componentElement}\r\n on:click={clickHandler}>\r\n {component && component._component ? \"\" : text}\r\n</div>\r\n\r\n<style>\r\n\r\n.panel:hover {\r\n background: var(--hoverBackground);\r\n color: var(--hoverColor);\r\n\r\n}\r\n\r\n</style>\r\n",
|
||||
"<script>\n\nimport { emptyProps } from \"./emptyProps\";\n\nexport let direction = \"horizontal\";\nexport let children = [];\nexport let width = \"auto\";\nexport let height = \"auto\";\nexport let containerClass=\"\";\nexport let itemContainerClass=\"\";\nexport let onLoad;\n\nexport let data=[];\nexport let dataItemComponent;\n\nexport let _bb;\n\nlet staticHtmlElements = {};\nlet staticComponents = {};\nlet dataBoundElements = {};\nlet dataBoundComponents = {};\n\nlet onLoadCalled = false;\n\nconst hasDataBoundComponents = () => \n Object.getOwnPropertyNames(dataBoundComponents).length > 0;\n\nconst hasData = () => \n Array.isArray(data) && data.length > 0;\n\nconst hasStaticComponents = () => {\n return Object.getOwnPropertyNames(staticComponents).length > 0;\n}\n\n$: {\n\n if(staticHtmlElements) {\n if(hasStaticComponents()) {\n for(let c in staticComponents) {\n staticComponents[c].$destroy();\n }\n staticComponents = {};\n }\n\n for(let el in staticHtmlElements) {\n staticComponents[el] = _bb.initialiseComponent(\n children[el].control,\n staticHtmlElements[el]\n );\n }\n }\n \n\n if(hasDataBoundComponents()) {\n for(let c in dataBoundComponents) {\n dataBoundComponents[c].$destroy();\n }\n dataBoundComponents = {};\n }\n\n if(hasData()) {\n let index = 0;\n for(let d in dataBoundElements) {\n _bb.initialiseComponent(\n dataItemComponent,\n dataBoundElements[d],\n data[parseInt(d)]\n );\n }\n }\n\n if(!onLoadCalled && onLoad && !onLoad.isPlaceholder) {\n onLoad();\n onLoadCalled = true;\n }\n}\n\n\n</script>\n\n<div class=\"root {containerClass}\"\n style=\"width: {width}; height: {height}\">\n\n {#if children}\n {#each children as child, index}\n <div class={direction}>\n <div class=\"{itemContainerClass}\"\n bind:this={staticHtmlElements[index]}>\n </div>\n </div>\n {/each}\n {/if}\n\n {#if data && data.length > 0}\n {#each data as child, index}\n <div class={direction}>\n <div class=\"{itemContainerClass}\"\n bind:this={dataBoundElements[index]}>\n </div>\n </div>\n {/each}\n {/if}\n</div>\n\n<style>\n\n.horizontal {\n display:inline-block;\n}\n\n.vertical {\n display: block;\n}\n\n</style>",
|
||||
"<script>\r\n\r\nexport let columns=[];\r\nexport let data=\"\";\r\nexport let tableClass=\"\";\r\nexport let theadClass=\"\";\r\nexport let tbodyClass=\"\";\r\nexport let trClass=\"\";\r\nexport let thClass=\"\";\r\nexport let onRowClick;\r\n\r\nexport let _bb;\r\n\r\nconst rowClickHandler = (row) => () => {\r\n onRowClick(row);\r\n}\r\n\r\n</script>\r\n\r\n <table class={tableClass}>\r\n <thead class={theadClass}>\r\n <tr class={trClass}>\r\n {#each columns as col}\r\n <th class={thClass}>{col.title}</th>\r\n {/each}\r\n </tr>\r\n </thead>\r\n <tbody class={tbodyClass}>\r\n {#each data as row}\r\n <tr class={trClass}\r\n on:click={rowClickHandler(row)} >\r\n {#each columns as col}\r\n <th class={thClass}>{_bb.getStateOrValue(col.value, row)}</th>\r\n {/each}\r\n </tr>\r\n {/each}\r\n </tbody>\r\n</table> \r\n\r\n<style>\r\n\r\n.table-default {\r\n width: 100%;\r\n margin-bottom: 1rem;\r\n color: #212529;\r\n border-collapse: collapse;\r\n}\r\n\r\n.table-default .thead-default .th-default {\r\n vertical-align: bottom;\r\n border-bottom: 2px solid #dee2e6;\r\n font-weight: bold;\r\n}\r\n\r\n.table-default .th-default {\r\n padding: .75rem;\r\n vertical-align: top;\r\n border-top: 1px solid #dee2e6;\r\n font-weight: normal;\r\n}\r\n\r\n.th-default {\r\n text-align: inherit;\r\n}\r\n\r\n.table-default .tbody-default .tr-default:hover {\r\n color: #212529;\r\n background-color: rgba(0,0,0,.075);\r\n cursor: pointer;\r\n}\r\n\r\n</style>",
|
||||
"<script>\nexport let className = \"default\";\nexport let disabled = false;\nexport let contentText;\nexport let contentComponent;\nexport let onClick = () => {};\n\nexport let _bb;\nlet contentComponentContainer;\n\n$:{\n\tif(_bb && contentComponentContainer && contentComponent._component)\n\t\t_bb.initialiseComponent(contentComponent, contentComponentContainer);\n}\n\n\nconst clickHandler = () => {\n\tif(onClick) onClick();\n}\n\n</script>\n\n\n<button class={className} {disabled} on:click={clickHandler}>\n {#if contentComponent && contentComponent._component}\n\t<div bind:this={contentComponentContainer}>\n\t</div>\n {:else if contentText}\n {contentText}\n {:else}\n <slot />\n {/if}\n</button>\n\n\n<style>\n\n.default {\n\tfont-family: inherit;\n\tfont-size: inherit;\n\tpadding: 0.4em;\n\tmargin: 0 0 0.5em 0;\n\tbox-sizing: border-box;\n\tborder: 1px solid #ccc;\n\tborder-radius: 2px;\n\tcolor: #333;\n\tbackground-color: #f4f4f4;\n\toutline: none;\n}\n\n.default:active {\n\tbackground-color: #ddd;\n}\n\n.default:focus {\n\tborder-color: #666;\n}\n\n</style>"
|
||||
],
|
||||
"names": [],
|
||||
"mappings": "AAkCA,kBAAkB,eAAC,CAAC,AAChB,MAAM,CAAE,IAAI,CACZ,KAAK,CAAE,IAAI,AACf,CAAC;ACqBD,KAAK,eAAC,CAAC,AACH,OAAO,CAAE,IAAI,AACjB,CAAC;ACqCD,KAAK,cAAC,CAAC,AACH,MAAM,CAAE,IAAI,CACZ,QAAQ,IAAI,CACZ,qBAAqB,CAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAC3D,kBAAkB,CAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,AAC5D,CAAC,AAED,QAAQ,cAAC,CAAC,AACN,iBAAiB,CAAE,MAAM,CACzB,cAAc,CAAE,MAAM,CACtB,KAAK,CAAE,KAAK,AAChB,CAAC,AAED,eAAe,cAAC,CAAC,AACb,aAAa,CAAE,IAAI;AACvB,CAAC,AAED,6BAAe,CAAG,GAAG,cAAC,CAAC,AACnB,SAAS,CAAE,IAAI,AACnB,CAAC,AAED,uBAAuB,cAAC,CAAC,AACrB,UAAU,CAAE,KAAK,CACjB,UAAU,CAAE,IAAI,AACpB,CAAC,AAED,wBAAwB,cAAC,CAAC,AACtB,UAAU,CAAE,IAAI,CAChB,OAAO,CAAE,IAAI,CACb,YAAY,CAAE,KAAK,CACnB,YAAY,CAAE,GAAG,CACjB,YAAY,CAAE,MAAM,CACpB,aAAa,CAAE,GAAG,CAClB,UAAU,CAAE,MAAM,CAClB,KAAK,CAAE,MAAM,CACb,gBAAgB,CAAE,SAAS,AAC/B,CAAC,AAED,UAAU,cAAC,CAAC,AACR,OAAO,CAAE,IAAI,CACb,qBAAqB,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,AACrD,CAAC,AAED,MAAM,cAAC,CAAC,AACJ,iBAAiB,CAAE,KAAK,CACxB,OAAO,CAAE,GAAG,CAAC,IAAI,CACjB,cAAc,CAAE,MAAM,AAC1B,CAAC,AACD,QAAQ,cAAC,CAAC,AACN,iBAAiB,CAAE,OAAO,CAC1B,OAAO,CAAE,GAAG,CAAC,IAAI,AACrB,CAAC,AAED,cAAc,cAAC,CAAC,AACf,WAAW,CAAE,OAAO,CACpB,SAAS,CAAE,OAAO,CAClB,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACnB,UAAU,CAAE,UAAU,CACtB,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CACnB,aAAa,CAAE,GAAG,CAClB,KAAK,CAAE,IAAI,AACf,CAAC,AAED,eAAe,cAAC,CAAC,AAChB,WAAW,CAAE,OAAO,CACpB,SAAS,CAAE,OAAO,CAClB,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACnB,UAAU,CAAE,UAAU,CACtB,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CACtB,aAAa,CAAE,GAAG,CAClB,KAAK,CAAE,IAAI,CACX,gBAAgB,CAAE,OAAO,CACzB,OAAO,CAAE,IAAI,AACd,CAAC,AAED,6BAAe,OAAO,AAAC,CAAC,AACvB,gBAAgB,CAAE,IAAI,AACvB,CAAC,AAED,6BAAe,MAAM,AAAC,CAAC,AACtB,YAAY,CAAE,IAAI,AACnB,CAAC;AC9ID,UAAU,cAAC,CAAC,AACR,OAAO,CAAE,IAAI,CACb,qBAAqB,CAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,AACrD,CAAC,AAED,MAAM,cAAC,CAAC,AACJ,iBAAiB,CAAE,KAAK,CACxB,OAAO,CAAE,GAAG,CAAC,IAAI,CACjB,cAAc,CAAE,MAAM,AAC1B,CAAC,AACD,QAAQ,cAAC,CAAC,AACN,iBAAiB,CAAE,OAAO,CAC1B,OAAO,CAAE,GAAG,CAAC,IAAI,AACrB,CAAC,AACD,SAAS,cAAC,CAAC,AACP,iBAAiB,CAAE,QAAQ,AAC/B,CAAC,AACD,WAAW,cAAC,CAAC,AACT,KAAK,CAAE,IAAI,AACf,CAAC;AC6BD,KAAK,cAAC,CAAC,AACH,MAAM,CAAE,IAAI,CACZ,MAAM,IAAI,CACV,qBAAqB,CAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAClD,OAAO,CAAE,IAAI,AACjB,CAAC,AAED,OAAO,cAAC,CAAC,AACL,WAAW,CAAE,MAAM,CACnB,UAAU,CAAE,IAAI,kBAAkB,CAAC,CACnC,MAAM,CAAE,IAAI,cAAc,CAAC,CAC3B,KAAK,CAAE,IAAI,aAAa,CAAC,AAC7B,CAAC,AAED,QAAQ,cAAC,CAAC,AACN,OAAO,CAAE,IAAI,CAAC,IAAI,CAClB,MAAM,CAAE,OAAO,AACnB,CAAC,AAED,sBAAQ,MAAM,AAAC,CAAC,AACZ,UAAU,CAAE,IAAI,qBAAqB,CAAC,CACtC,KAAK,CAAE,IAAI,gBAAgB,CAAC,AAChC,CAAC,AAED,QAAQ,SAAS,cAAC,CAAC,AACf,UAAU,CAAE,IAAI,wBAAwB,CAAC,CACzC,MAAM,CAAE,IAAI,oBAAoB,CAAC,CACjC,KAAK,CAAE,IAAI,mBAAmB,CAAC,AACnC,CAAC,AAED,QAAQ,cAAC,CAAC,AACN,WAAW,CAAE,OAAO,AACxB,CAAC;AClFD,QAAQ,eAAC,CAAC,AACN,KAAK,CAAE,IAAI,CACd,WAAW,CAAE,OAAO,CACpB,SAAS,CAAE,OAAO,CAClB,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACnB,UAAU,CAAE,UAAU,CACtB,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CACnB,aAAa,CAAE,GAAG,CAClB,KAAK,CAAE,IAAI,AACf,CAAC,AAED,uBAAQ,SAAS,AAAC,CAAC,AAClB,KAAK,CAAE,IAAI,AACZ,CAAC;ACaD,oBAAM,MAAM,AAAC,CAAC,AACV,UAAU,CAAE,IAAI,iBAAiB,CAAC,CAClC,KAAK,CAAE,IAAI,YAAY,CAAC,AAE5B,CAAC;ACuCD,WAAW,cAAC,CAAC,AACT,QAAQ,YAAY,AACxB,CAAC,AAED,SAAS,cAAC,CAAC,AACP,OAAO,CAAE,KAAK,AAClB,CAAC;ACvED,cAAc,cAAC,CAAC,AACZ,KAAK,CAAE,IAAI,CACX,aAAa,CAAE,IAAI,CACnB,KAAK,CAAE,OAAO,CACd,eAAe,CAAE,QAAQ,AAC7B,CAAC,AAED,4BAAc,CAAC,cAAc,CAAC,WAAW,cAAC,CAAC,AACvC,cAAc,CAAE,MAAM,CACtB,aAAa,CAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAChC,WAAW,CAAE,IAAI,AACrB,CAAC,AAED,4BAAc,CAAC,WAAW,cAAC,CAAC,AACxB,OAAO,CAAE,MAAM,CACf,cAAc,CAAE,GAAG,CACnB,UAAU,CAAE,GAAG,CAAC,KAAK,CAAC,OAAO,CAC7B,WAAW,CAAE,MAAM,AACvB,CAAC,AAED,WAAW,cAAC,CAAC,AACT,UAAU,CAAE,OAAO,AACvB,CAAC,AAED,4BAAc,CAAC,cAAc,CAAC,yBAAW,MAAM,AAAC,CAAC,AAC7C,KAAK,CAAE,OAAO,CACd,gBAAgB,CAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAClC,MAAM,CAAE,OAAO,AACnB,CAAC;AChCD,QAAQ,eAAC,CAAC,AACT,WAAW,CAAE,OAAO,CACpB,SAAS,CAAE,OAAO,CAClB,OAAO,CAAE,KAAK,CACd,MAAM,CAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CACnB,UAAU,CAAE,UAAU,CACtB,MAAM,CAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CACtB,aAAa,CAAE,GAAG,CAClB,KAAK,CAAE,IAAI,CACX,gBAAgB,CAAE,OAAO,CACzB,OAAO,CAAE,IAAI,AACd,CAAC,AAED,uBAAQ,OAAO,AAAC,CAAC,AAChB,gBAAgB,CAAE,IAAI,AACvB,CAAC,AAED,uBAAQ,MAAM,AAAC,CAAC,AACf,YAAY,CAAE,IAAI,AACnB,CAAC"
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -1,103 +0,0 @@
|
|||
window["##BUDIBASE_APPDEFINITION##"] = {
|
||||
hierarchy: {
|
||||
name: "root",
|
||||
type: "root",
|
||||
children: [
|
||||
{
|
||||
name: "customer",
|
||||
type: "record",
|
||||
fields: [
|
||||
{
|
||||
name: "name",
|
||||
type: "string",
|
||||
typeOptions: {
|
||||
maxLength: 1000,
|
||||
values: null,
|
||||
allowDeclaredValuesOnly: false,
|
||||
},
|
||||
label: "name",
|
||||
getInitialValue: "default",
|
||||
getUndefinedValue: "default",
|
||||
},
|
||||
],
|
||||
children: [
|
||||
{
|
||||
name: "invoiceyooo",
|
||||
type: "record",
|
||||
fields: [
|
||||
{
|
||||
name: "amount",
|
||||
type: "number",
|
||||
typeOptions: {
|
||||
minValue: 99999999999,
|
||||
maxValue: 99999999999,
|
||||
decimalPlaces: 2,
|
||||
},
|
||||
label: "amount",
|
||||
getInitialValue: "default",
|
||||
getUndefinedValue: "default",
|
||||
},
|
||||
],
|
||||
children: [],
|
||||
validationRules: [],
|
||||
nodeId: 2,
|
||||
indexes: [],
|
||||
allidsShardFactor: 1,
|
||||
collectionName: "invoices",
|
||||
isSingle: false,
|
||||
},
|
||||
],
|
||||
validationRules: [],
|
||||
nodeId: 1,
|
||||
indexes: [
|
||||
{
|
||||
name: "customer_invoices",
|
||||
type: "index",
|
||||
map: "return {...record};",
|
||||
filter: "",
|
||||
indexType: "ancestor",
|
||||
getShardName: "",
|
||||
getSortKey: "record.id",
|
||||
aggregateGroups: [],
|
||||
allowedModelNodeIds: [2],
|
||||
nodeId: 5,
|
||||
},
|
||||
],
|
||||
allidsShardFactor: 64,
|
||||
collectionName: "customers",
|
||||
isSingle: false,
|
||||
},
|
||||
],
|
||||
pathMaps: [],
|
||||
indexes: [
|
||||
{
|
||||
name: "Yeo index",
|
||||
type: "index",
|
||||
map: "return {...record};",
|
||||
filter: "",
|
||||
indexType: "ancestor",
|
||||
getShardName: "",
|
||||
getSortKey: "record.id",
|
||||
aggregateGroups: [],
|
||||
allowedModelNodeIds: [1],
|
||||
nodeId: 4,
|
||||
},
|
||||
{
|
||||
name: "everyones_invoices",
|
||||
type: "index",
|
||||
map: "return {...record};",
|
||||
filter: "",
|
||||
indexType: "ancestor",
|
||||
getShardName: "",
|
||||
getSortKey: "record.id",
|
||||
aggregateGroups: [],
|
||||
allowedModelNodeIds: [2],
|
||||
nodeId: 6,
|
||||
},
|
||||
],
|
||||
nodeId: 0,
|
||||
},
|
||||
componentLibraries: ["budibase-standard-components"],
|
||||
appRootPath: "/testApp2",
|
||||
props: {},
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 3.1 KiB |
|
@ -1,62 +0,0 @@
|
|||
html, body {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color: rgb(0,100,200);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a:visited {
|
||||
color: rgb(0,80,160);
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input, button, select, textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 0.4em;
|
||||
margin: 0 0 0.5em 0;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
color: #333;
|
||||
background-color: #f4f4f4;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
button:focus {
|
||||
border-color: #666;
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf8'>
|
||||
<meta name='viewport' content='width=device-width'>
|
||||
|
||||
<title>Svelte app</title>
|
||||
|
||||
<link rel='icon' type='image/png' href='/favicon.png'>
|
||||
<link rel='stylesheet' href='/global.css'>
|
||||
<link rel='stylesheet' href='/bundle.css'>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src='/bundle.js'></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,20 +0,0 @@
|
|||
import svelte from "rollup-plugin-svelte"
|
||||
import resolve from "rollup-plugin-node-resolve"
|
||||
|
||||
export default {
|
||||
input: "src/index.js",
|
||||
output: [
|
||||
{
|
||||
file: "dist/index.js",
|
||||
format: "esm",
|
||||
name: "budibaseStandardComponents",
|
||||
sourcemap: "inline",
|
||||
},
|
||||
],
|
||||
plugins: [
|
||||
svelte({
|
||||
hydratable: true,
|
||||
}),
|
||||
resolve(),
|
||||
],
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
import svelte from "rollup-plugin-svelte"
|
||||
import resolve from "rollup-plugin-node-resolve"
|
||||
import commonjs from "rollup-plugin-commonjs"
|
||||
import livereload from "rollup-plugin-livereload"
|
||||
import { terser } from "rollup-plugin-terser"
|
||||
import json from "rollup-plugin-json"
|
||||
|
||||
const production = !process.env.ROLLUP_WATCH
|
||||
|
||||
const lodash_fp_exports = [
|
||||
"find",
|
||||
"isUndefined",
|
||||
"split",
|
||||
"last",
|
||||
"union",
|
||||
"reduce",
|
||||
"isObject",
|
||||
"cloneDeep",
|
||||
"some",
|
||||
"isArray",
|
||||
"map",
|
||||
"filter",
|
||||
"keys",
|
||||
"isFunction",
|
||||
"isEmpty",
|
||||
"countBy",
|
||||
"join",
|
||||
"includes",
|
||||
"flatten",
|
||||
"constant",
|
||||
"first",
|
||||
"intersection",
|
||||
"take",
|
||||
"has",
|
||||
"mapValues",
|
||||
"isString",
|
||||
"isBoolean",
|
||||
"isNull",
|
||||
"isNumber",
|
||||
"isObjectLike",
|
||||
"isDate",
|
||||
"clone",
|
||||
"values",
|
||||
"keyBy",
|
||||
"isNaN",
|
||||
"isInteger",
|
||||
"toNumber",
|
||||
]
|
||||
|
||||
const lodash_exports = [
|
||||
"flow",
|
||||
"head",
|
||||
"tail",
|
||||
"findIndex",
|
||||
"startsWith",
|
||||
"dropRight",
|
||||
"takeRight",
|
||||
"trim",
|
||||
"split",
|
||||
"replace",
|
||||
"merge",
|
||||
"assign",
|
||||
]
|
||||
|
||||
const coreExternal = [
|
||||
"lodash",
|
||||
"lodash/fp",
|
||||
"date-fns",
|
||||
"lunr",
|
||||
"safe-buffer",
|
||||
"shortid",
|
||||
"@nx-js/compiler-util",
|
||||
]
|
||||
|
||||
export default {
|
||||
input: "src/Test/testMain.js",
|
||||
output: {
|
||||
sourcemap: true,
|
||||
format: "iife",
|
||||
name: "app",
|
||||
file: "public/bundle.js",
|
||||
},
|
||||
plugins: [
|
||||
svelte({
|
||||
// enable run-time checks when not in production
|
||||
dev: !production,
|
||||
// we'll extract any component CSS out into
|
||||
// a separate file — better for performance
|
||||
css: css => {
|
||||
css.write("public/bundle.css")
|
||||
},
|
||||
|
||||
hydratable: true,
|
||||
}),
|
||||
|
||||
// If you have external dependencies installed from
|
||||
// npm, you'll most likely need these plugins. In
|
||||
// some cases you'll need additional configuration —
|
||||
// consult the documentation for details:
|
||||
// https://github.com/rollup/rollup-plugin-commonjs
|
||||
resolve({
|
||||
browser: true,
|
||||
dedupe: importee => {
|
||||
return (
|
||||
importee === "svelte" ||
|
||||
importee.startsWith("svelte/") ||
|
||||
coreExternal.includes(importee)
|
||||
)
|
||||
},
|
||||
}),
|
||||
commonjs({
|
||||
namedExports: {
|
||||
"lodash/fp": lodash_fp_exports,
|
||||
lodash: lodash_exports,
|
||||
shortid: ["generate"],
|
||||
},
|
||||
}),
|
||||
json(),
|
||||
|
||||
// Watch the `public` directory and refresh the
|
||||
// browser on changes when not in production
|
||||
!production && livereload("public"),
|
||||
|
||||
// If we're building for production (npm run build
|
||||
// instead of npm run dev), minify
|
||||
production && terser(),
|
||||
],
|
||||
watch: {
|
||||
clearScreen: false,
|
||||
},
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
const { readdir, stat, copyFile } = require("fs-extra")
|
||||
const { constants } = require("fs")
|
||||
const { join, basename } = require("path")
|
||||
|
||||
const packagesFolder = ".."
|
||||
|
||||
const jsFile = dir => join(dir, "index.js")
|
||||
const jsMapFile = dir => join(dir, "index.js.map")
|
||||
const sourceJs = jsFile("dist")
|
||||
const sourceJsMap = jsMapFile("dist")
|
||||
const componentsFile = "components.json"
|
||||
|
||||
const appPackages = join(packagesFolder, "server", "appPackages")
|
||||
|
||||
const publicMain = appName =>
|
||||
join(
|
||||
appPackages,
|
||||
appName,
|
||||
"public",
|
||||
"main",
|
||||
"lib",
|
||||
"node_modules",
|
||||
"@budibase",
|
||||
"bootstrap-components"
|
||||
)
|
||||
const publicUnauth = appName =>
|
||||
join(
|
||||
appPackages,
|
||||
appName,
|
||||
"public",
|
||||
"unauthenticated",
|
||||
"lib",
|
||||
"node_modules",
|
||||
"@budibase",
|
||||
"bootstrap-components"
|
||||
)
|
||||
const nodeModulesDist = appName =>
|
||||
join(
|
||||
appPackages,
|
||||
appName,
|
||||
"node_modules",
|
||||
"@budibase",
|
||||
"bootstrap-components",
|
||||
"dist"
|
||||
)
|
||||
const nodeModules = appName =>
|
||||
join(
|
||||
appPackages,
|
||||
appName,
|
||||
"node_modules",
|
||||
"@budibase",
|
||||
"bootstrap-components"
|
||||
)
|
||||
|
||||
;(async () => {
|
||||
const apps = await readdir(appPackages)
|
||||
|
||||
const copySource = file => async toDir => {
|
||||
const dest = join(toDir, basename(file))
|
||||
try {
|
||||
await copyFile(file, dest, constants.COPYFILE_FICLONE)
|
||||
console.log(`COPIED ${file} to ${dest}`)
|
||||
} catch (e) {
|
||||
console.log(`COPY FAILED ${file} to ${dest}: ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
const copySourceJs = copySource(sourceJs)
|
||||
const copySourceJsMap = copySource(sourceJsMap)
|
||||
const copyComponentsJson = copySource(componentsFile)
|
||||
|
||||
for (let app of apps) {
|
||||
if (!(await stat(join(appPackages, app))).isDirectory()) continue
|
||||
|
||||
await copySourceJs(nodeModulesDist(app))
|
||||
await copySourceJsMap(nodeModulesDist(app))
|
||||
|
||||
await copyComponentsJson(nodeModules(app))
|
||||
|
||||
await copySourceJs(join(publicMain(app), "dist"))
|
||||
await copySourceJsMap(join(publicMain(app), "dist"))
|
||||
|
||||
await copySourceJs(join(publicUnauth(app), "dist"))
|
||||
await copySourceJsMap(join(publicUnauth(app), "dist"))
|
||||
}
|
||||
})()
|
|
@ -1,44 +0,0 @@
|
|||
<script>
|
||||
export let formControls = []
|
||||
|
||||
export let _bb
|
||||
|
||||
let htmlElements = {}
|
||||
let labelElements = {}
|
||||
let labels = {}
|
||||
let isInitialised = false
|
||||
|
||||
$: {
|
||||
if (_bb && htmlElements && !isInitialised) {
|
||||
let cIndex = 0
|
||||
for (let c of formControls) {
|
||||
labels[cIndex] = c.label
|
||||
cIndex++
|
||||
}
|
||||
|
||||
for (let el in htmlElements) {
|
||||
if (formControls[el].control.controlPosition === "Before Label") {
|
||||
_bb.insertChildren(
|
||||
_bb.props.formControls[el].control,
|
||||
htmlElements[el],
|
||||
htmlElements[el].childNodes.find(n => n.tagName === "LABEL")
|
||||
)
|
||||
} else {
|
||||
_bb.appendChildren(
|
||||
_bb.props.formControls[el].control,
|
||||
htmlElements[el]
|
||||
)
|
||||
}
|
||||
}
|
||||
isInitialised = true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<form>
|
||||
{#each formControls as child, idx}
|
||||
<div class="form-group" bind:this={htmlElements[idx]}>
|
||||
<label>{labels[idx]}</label>
|
||||
</div>
|
||||
{/each}
|
||||
</form>
|
|
@ -1,119 +0,0 @@
|
|||
<script>
|
||||
export let items = []
|
||||
export let hideNavBar = false
|
||||
export let selectedItem = ""
|
||||
export let orientation = "horizontal" // horizontal, verical
|
||||
export let alignment = "start" // start, center, end
|
||||
export let pills = false
|
||||
export let fill = false
|
||||
export let className = ""
|
||||
export let _bb
|
||||
|
||||
let selectedIndex = -1
|
||||
let styleVars = {}
|
||||
let components = {}
|
||||
let componentElement
|
||||
let orientationClass = ""
|
||||
let navClasses = ""
|
||||
let currentComponent
|
||||
let _selectedItem = ""
|
||||
|
||||
const hasComponentElements = () =>
|
||||
Object.getOwnPropertyNames(componentElements).length > 0
|
||||
|
||||
const getSelectedItemByIndex = index => (index >= 0 ? items[index].title : "")
|
||||
|
||||
$: {
|
||||
let _navClasses = ""
|
||||
|
||||
if (orientation === "vertical") {
|
||||
_navClasses += " flex-column"
|
||||
} else {
|
||||
_navClasses += ` justify-content-${alignment}`
|
||||
}
|
||||
|
||||
if (pills) _navClasses += " nav-pills"
|
||||
|
||||
if (fill) _navClasses += " nav-fill nav-justified"
|
||||
|
||||
navClasses = _navClasses
|
||||
|
||||
if (items && componentElement) {
|
||||
const currentSelectedItem = getSelectedItemByIndex(selectedIndex)
|
||||
|
||||
if (selectedItem && currentSelectedItem !== selectedItem) {
|
||||
let i = 0
|
||||
for (let item of items) {
|
||||
if (item.title === selectedItem) {
|
||||
SelectItem(i)
|
||||
}
|
||||
i++
|
||||
}
|
||||
} else if (!selectedItem) {
|
||||
SelectItem(-1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SelectItem = index => {
|
||||
selectedIndex = index
|
||||
const newSelectedItem = getSelectedItemByIndex(index)
|
||||
if (newSelectedItem !== selectedItem) {
|
||||
selectedItem = newSelectedItem
|
||||
}
|
||||
|
||||
if (currentComponent) {
|
||||
try {
|
||||
currentComponent.$destroy()
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
if (index >= 0)
|
||||
currentComponent = _bb.hydrateChildren(
|
||||
_bb.props.items[index].component,
|
||||
componentElement
|
||||
)
|
||||
}
|
||||
|
||||
const onSelectItemClicked = index => () => {
|
||||
if (_bb.props.selectedItem) {
|
||||
// binding - call state, which should SelectItem(..)
|
||||
const selectedItemBinding = _bb.props.selectedItem
|
||||
_bb.setStateFromBinding(
|
||||
selectedItemBinding,
|
||||
getSelectedItemByIndex(index)
|
||||
)
|
||||
} else {
|
||||
// no binding - call this
|
||||
SelectItem(index)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="root {className}">
|
||||
{#if !hideNavBar}
|
||||
<ul class="nav {navClasses}">
|
||||
{#each items as navItem, index}
|
||||
<li class="nav-item">
|
||||
<button
|
||||
class="nav-link btn btn-link"
|
||||
on:click={onSelectItemClicked(index)}
|
||||
class:disabled={navItem.disabled}
|
||||
class:active={selectedIndex === index}>
|
||||
{navItem.title}
|
||||
</button>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
{/if}
|
||||
{#each items as navItem, index}
|
||||
<div bind:this={componentElement} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
|
@ -1,34 +0,0 @@
|
|||
<script>
|
||||
import createApp from "./createApp"
|
||||
import { props } from "./props"
|
||||
|
||||
let _bb
|
||||
|
||||
const _appPromise = createApp()
|
||||
_appPromise.then(a => (_bb = a))
|
||||
|
||||
const testProps = props.hiddenNav
|
||||
|
||||
let currentComponent
|
||||
|
||||
$: {
|
||||
if (_bb && currentComponent) {
|
||||
_bb.hydrateChildren(testProps, currentComponent)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await _appPromise}
|
||||
loading
|
||||
{:then _bb}
|
||||
|
||||
<div id="current_component" bind:this={currentComponent} />
|
||||
|
||||
{/await}
|
||||
|
||||
<style>
|
||||
#current_component {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
|
@ -1,43 +0,0 @@
|
|||
import Login from "../Login.svelte"
|
||||
import Grid from "../Grid.svelte"
|
||||
import Form from "../Form.svelte"
|
||||
import Textbox from "../Textbox.svelte"
|
||||
import Text from "../Text.svelte"
|
||||
import Nav from "../Nav.svelte"
|
||||
import Panel from "../Panel.svelte"
|
||||
import StackPanel from "../StackPanel.svelte"
|
||||
import Table from "../Table.svelte"
|
||||
import Button from "../Button.svelte"
|
||||
import { createApp } from "@budibase/client/src/createApp"
|
||||
|
||||
export default async () => {
|
||||
const componentLibraries = {
|
||||
components: {
|
||||
login: Login,
|
||||
grid: Grid,
|
||||
form: Form,
|
||||
textbox: Textbox,
|
||||
text: Text,
|
||||
nav: Nav,
|
||||
panel: Panel,
|
||||
table: Table,
|
||||
stackpanel: StackPanel,
|
||||
button: Button,
|
||||
},
|
||||
}
|
||||
|
||||
const appDef = { hierarchy: {}, actions: {} }
|
||||
const user = { name: "yeo", permissions: [] }
|
||||
|
||||
var app = createApp(componentLibraries, appDef, user)
|
||||
app.store.update(s => {
|
||||
s.people = [
|
||||
{ name: "bob", address: "123 Main Street", status: "Open" },
|
||||
{ name: "poppy", address: "456 Side Road", status: "Closed" },
|
||||
{ name: "Oscar", address: "678 Dodgy Alley", status: "Open" },
|
||||
]
|
||||
return s
|
||||
})
|
||||
|
||||
return app
|
||||
}
|
|
@ -1,247 +0,0 @@
|
|||
export const props = {
|
||||
login: { _component: "components/login" },
|
||||
|
||||
form: {
|
||||
_component: "components/form",
|
||||
formControls: [
|
||||
{
|
||||
control: {
|
||||
_component: "components/textbox",
|
||||
},
|
||||
label: "First Name",
|
||||
},
|
||||
{
|
||||
control: {
|
||||
_component: "components/textbox",
|
||||
},
|
||||
label: "Last Name",
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
nav: {
|
||||
_component: "components/nav",
|
||||
navBarBackground: "red",
|
||||
navBarBorder: "1px solid maroon",
|
||||
navBarColor: "black",
|
||||
selectedItemBackground: "maroon",
|
||||
selectedItemColor: "white",
|
||||
selectedItemBorder: "green",
|
||||
itemHoverBackground: "yellow",
|
||||
itemHoverColor: "pink",
|
||||
items: [
|
||||
{
|
||||
title: "People",
|
||||
component: {
|
||||
_component: "components/panel",
|
||||
text: "People Panel",
|
||||
padding: "40px",
|
||||
border: "2px solid pink",
|
||||
background: "mistyrose",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Animals",
|
||||
component: {
|
||||
_component: "components/panel",
|
||||
text: "Animals Panel",
|
||||
padding: "40px",
|
||||
border: "2px solid green",
|
||||
background: "azure",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
table: {
|
||||
_component: "components/table",
|
||||
columns: [
|
||||
{
|
||||
title: {
|
||||
"##bbstate": "NameColumnName",
|
||||
"##bbsource": "store",
|
||||
"##bbstatefallback": "Name",
|
||||
},
|
||||
value: {
|
||||
"##bbstate": "name",
|
||||
"##bbsource": "context",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Address",
|
||||
value: {
|
||||
"##bbstate": "address",
|
||||
"##bbsource": "context",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Status",
|
||||
value: {
|
||||
"##bbstate": "status",
|
||||
"##bbsource": "context",
|
||||
},
|
||||
},
|
||||
],
|
||||
data: {
|
||||
"##bbstate": "people",
|
||||
},
|
||||
onRowClick: [
|
||||
{
|
||||
"##eventHandlerType": "Set State",
|
||||
parameters: {
|
||||
path: "NameColumnName",
|
||||
value: {
|
||||
"##bbstate": "name",
|
||||
"##bbsource": "context",
|
||||
"##bbstatefallback": "balls to that",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
tableClass: "table-default",
|
||||
theadClass: "thead-default",
|
||||
tbodyClass: "tbody-default",
|
||||
trClass: "tr-default",
|
||||
thClass: "th-default",
|
||||
},
|
||||
|
||||
grid: {
|
||||
_component: "components/grid",
|
||||
gridTemplateColumns: "[left] auto [center] auto [right] auto",
|
||||
gridTemplateRows: "[top] auto [middle] auto [bottom] auto",
|
||||
children: [
|
||||
{
|
||||
control: {
|
||||
_component: "components/text",
|
||||
value: "1",
|
||||
background: "blue",
|
||||
textAlign: "center",
|
||||
color: "white",
|
||||
},
|
||||
gridColumn: "left",
|
||||
gridRow: "top",
|
||||
},
|
||||
{
|
||||
control: {
|
||||
_component: "components/text",
|
||||
value: "2",
|
||||
background: "red",
|
||||
textAlign: "center",
|
||||
color: "white",
|
||||
padding: "10px",
|
||||
},
|
||||
gridColumn: "center",
|
||||
gridRow: "middle",
|
||||
},
|
||||
{
|
||||
control: {
|
||||
_component: "components/text",
|
||||
value: "3",
|
||||
background: "yellow",
|
||||
textAlign: "center",
|
||||
color: "black",
|
||||
},
|
||||
gridColumn: "right",
|
||||
gridRow: "bottom",
|
||||
},
|
||||
],
|
||||
},
|
||||
boundStackPanel: {
|
||||
_component: "components/stackpanel",
|
||||
direction: "horizontal",
|
||||
children: [
|
||||
{
|
||||
control: {
|
||||
_component: "components/text",
|
||||
value: "STATIC",
|
||||
},
|
||||
},
|
||||
],
|
||||
data: {
|
||||
"##bbstate": "people",
|
||||
},
|
||||
dataItemComponent: {
|
||||
_component: "components/panel",
|
||||
text: {
|
||||
"##bbstate": "name",
|
||||
"##bbsource": "context",
|
||||
"##bbstatefallback": "balls to that",
|
||||
},
|
||||
padding: "10px",
|
||||
border: "5px solid black",
|
||||
margin: "10px",
|
||||
hoverColor: "white",
|
||||
hoverBackground: "black",
|
||||
height: "200px",
|
||||
weight: "200px",
|
||||
},
|
||||
},
|
||||
hiddenNav: {
|
||||
_component: "components/stackpanel",
|
||||
children: [
|
||||
{
|
||||
control: {
|
||||
_component: "components/button",
|
||||
contentText: "Peep",
|
||||
onClick: [
|
||||
{
|
||||
"##eventHandlerType": "Set State",
|
||||
parameters: {
|
||||
path: "selected",
|
||||
value: "People",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
control: {
|
||||
_component: "components/button",
|
||||
contentText: "Ani",
|
||||
onClick: [
|
||||
{
|
||||
"##eventHandlerType": "Set State",
|
||||
parameters: {
|
||||
path: "selected",
|
||||
value: "Animals",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
control: {
|
||||
_component: "components/nav",
|
||||
hideNavBar: true,
|
||||
selectedItem: {
|
||||
"##bbstate": "selected",
|
||||
"##bbsource": "store",
|
||||
"##bbstatefallback": "Animals",
|
||||
},
|
||||
items: [
|
||||
{
|
||||
title: "People",
|
||||
component: {
|
||||
_component: "components/panel",
|
||||
text: "People Panel",
|
||||
padding: "40px",
|
||||
border: "2px solid pink",
|
||||
background: "mistyrose",
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "Animals",
|
||||
component: {
|
||||
_component: "components/panel",
|
||||
text: "Animals Panel",
|
||||
padding: "40px",
|
||||
border: "2px solid green",
|
||||
background: "azure",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import App from "./TestApp.svelte"
|
||||
|
||||
const app = new App({
|
||||
target: document.body,
|
||||
})
|
||||
|
||||
export default app
|
|
@ -1,9 +0,0 @@
|
|||
export const buildStyle = styles => {
|
||||
let str = ""
|
||||
for (let s in styles) {
|
||||
if (styles[s]) {
|
||||
str += `${s}: ${styles[s]}; `
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
// https://github.com/kaisermann/svelte-css-vars
|
||||
|
||||
export default (node, props) => {
|
||||
Object.entries(props).forEach(([key, value]) => {
|
||||
node.style.setProperty(`--${key}`, value)
|
||||
})
|
||||
|
||||
return {
|
||||
update(new_props) {
|
||||
Object.entries(new_props).forEach(([key, value]) => {
|
||||
node.style.setProperty(`--${key}`, value)
|
||||
delete props[key]
|
||||
})
|
||||
|
||||
Object.keys(props).forEach(name => node.style.removeProperty(`--${name}`))
|
||||
props = new_props
|
||||
},
|
||||
}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export const emptyProps = () => ({ _component: "" })
|
|
@ -1,2 +0,0 @@
|
|||
export { default as form } from "./Form.svelte"
|
||||
export { default as nav } from "./Nav.svelte"
|
|
@ -1,4 +1,5 @@
|
|||
import { filter, map, reduce, toPairs, pipe } from "lodash/fp"
|
||||
import { pipe } from "components/common/core";
|
||||
import { filter, map, reduce, toPairs } from "lodash/fp"
|
||||
|
||||
const self = n => n
|
||||
const join_with = delimiter => a => a.join(delimiter)
|
||||
|
|
|
@ -1,56 +1,73 @@
|
|||
import { flatten, values, uniq, map } from "lodash/fp"
|
||||
import { pipe } from "components/common/core"
|
||||
/**
|
||||
* Fetches the definitions for component library components. This includes
|
||||
* their props and other metadata from components.json.
|
||||
* @param {string} clientId - ID of the current client
|
||||
* @param {string} appId - ID of the currently running app
|
||||
*/
|
||||
export const fetchComponentLibDefinitions = async (clientId, appId) => {
|
||||
const LIB_DEFINITION_URL = `/${clientId}/${appId}/components/definitions`;
|
||||
try {
|
||||
const libDefinitionResponse = await fetch(LIB_DEFINITION_URL);
|
||||
return await libDefinitionResponse.json();
|
||||
} catch (err) {
|
||||
console.error(`Error fetching component definitions for ${appId}`, err);
|
||||
}
|
||||
};
|
||||
|
||||
export const loadLibs = async (appId, appPackage) => {
|
||||
/**
|
||||
* Loads the JavaScript files for app component libraries and returns a map of their modules.
|
||||
* @param {object} application - package definition
|
||||
*/
|
||||
export const fetchComponentLibModules = async application => {
|
||||
const allLibraries = {}
|
||||
|
||||
for (let lib of libsFromPages(appPackage.pages)) {
|
||||
console.log(libModule);
|
||||
const libModule = await import(makeLibraryUrl(appId, lib))
|
||||
allLibraries[lib] = libModule
|
||||
for (let libraryName of application.componentLibraries) {
|
||||
const LIBRARY_URL = `/${application._id}/componentlibrary?library=${libraryName}`;
|
||||
const libraryModule = await import(LIBRARY_URL)
|
||||
allLibraries[libraryName] = libraryModule
|
||||
}
|
||||
|
||||
return allLibraries
|
||||
}
|
||||
|
||||
export const loadLibUrls = (appId, appPackage) => {
|
||||
const allLibraries = []
|
||||
for (let lib of libsFromPages(appPackage.pages)) {
|
||||
const libUrl = makeLibraryUrl(appId, lib)
|
||||
allLibraries.push({ libName: lib, importPath: libUrl })
|
||||
}
|
||||
// export const loadLibUrls = (appId, appPackage) => {
|
||||
// const allLibraries = []
|
||||
// for (let lib of libsFromPages(appPackage.pages)) {
|
||||
// const libUrl = makeLibraryUrl(appId, lib)
|
||||
// allLibraries.push({ libName: lib, importPath: libUrl })
|
||||
// }
|
||||
|
||||
return allLibraries
|
||||
}
|
||||
// return allLibraries
|
||||
// }
|
||||
|
||||
export const loadLib = async (appId, lib, allLibs) => {
|
||||
allLibs[lib] = await import(makeLibraryUrl(appId, lib))
|
||||
return allLibs
|
||||
}
|
||||
// export const loadLib = async (appId, lib, allLibs) => {
|
||||
// allLibs[lib] = await import(makeLibraryUrl(appId, lib))
|
||||
// return allLibs
|
||||
// }
|
||||
|
||||
export const makeLibraryUrl = (appId, lib) =>
|
||||
`/_builder/${appId}/componentlibrary?lib=${encodeURI(lib)}`
|
||||
// export const makeLibraryUrl = (appId, lib) =>
|
||||
// `/_builder/${appId}/componentlibrary?lib=${encodeURI(lib)}`
|
||||
|
||||
export const libsFromPages = pages =>
|
||||
pipe(pages, [values, map(p => p.componentLibraries), flatten, uniq])
|
||||
// export const libsFromPages = pages =>
|
||||
// pipe(pages, [values, map(p => p.componentLibraries), flatten, uniq])
|
||||
|
||||
export const libUrlsForPreview = (appPackage, pageName) => {
|
||||
const resolve = path => {
|
||||
let file = appPackage.components.libraryPaths[path]
|
||||
if (file.startsWith("./")) file = file.substring(2)
|
||||
if (file.startsWith("/")) file = file.substring(1)
|
||||
// export const libUrlsForPreview = (appPackage, pageName) => {
|
||||
// const resolve = path => {
|
||||
// let file = appPackage.components.libraryPaths[path]
|
||||
// if (file.startsWith("./")) file = file.substring(2)
|
||||
// if (file.startsWith("/")) file = file.substring(1)
|
||||
|
||||
let newPath = path
|
||||
// let newPath = path
|
||||
|
||||
if (!newPath.startsWith("./") && !newPath.startsWith("/")) {
|
||||
newPath = `/node_modules/${path}`
|
||||
}
|
||||
// if (!newPath.startsWith("./") && !newPath.startsWith("/")) {
|
||||
// newPath = `/node_modules/${path}`
|
||||
// }
|
||||
|
||||
return {
|
||||
importPath: `/lib${newPath}/${file}`,
|
||||
libName: path,
|
||||
}
|
||||
}
|
||||
// return {
|
||||
// importPath: `/lib${newPath}/${file}`,
|
||||
// libName: path,
|
||||
// }
|
||||
// }
|
||||
|
||||
return pipe([appPackage.pages[pageName]], [libsFromPages, map(resolve)])
|
||||
}
|
||||
// return pipe([appPackage.pages[pageName]], [libsFromPages, map(resolve)])
|
||||
// }
|
||||
|
|
|
@ -1,12 +1,5 @@
|
|||
import { writable } from "svelte/store"
|
||||
import api from "../api"
|
||||
import { find } from "lodash/fp"
|
||||
import {
|
||||
getNode,
|
||||
constructHierarchy,
|
||||
} from "components/common/core"
|
||||
|
||||
import backendActions from "../../actions/backend";
|
||||
|
||||
export const getBackendUiStore = () => {
|
||||
const INITIAL_BACKEND_UI_STATE = {
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
import { filter, cloneDeep, last, concat, isEmpty, values } from "lodash/fp"
|
||||
import { pipe, getNode, constructHierarchy } from "components/common/core"
|
||||
import { filter, cloneDeep, values } from "lodash/fp"
|
||||
import { pipe } from "components/common/core"
|
||||
import * as backendStoreActions from "./backend"
|
||||
import { writable } from "svelte/store"
|
||||
import { defaultPagesObject } from "components/userInterface/pagesParsing/defaultPagesObject"
|
||||
import api from "../api"
|
||||
import {
|
||||
DEFAULT_PAGES_OBJECT
|
||||
} from "../../constants";
|
||||
import { getExactComponent } from "components/userInterface/pagesParsing/searchComponents"
|
||||
import { rename } from "components/userInterface/pagesParsing/renameScreen"
|
||||
import {
|
||||
getNewScreen,
|
||||
// getNewScreen,
|
||||
createProps,
|
||||
makePropsSafe,
|
||||
getBuiltin,
|
||||
} from "components/userInterface/pagesParsing/createProps"
|
||||
import { expandComponentDefinition } from "components/userInterface/pagesParsing/types"
|
||||
import { loadLibs, libUrlsForPreview } from "../loadComponentLibraries"
|
||||
import {
|
||||
fetchComponentLibModules,
|
||||
fetchComponentLibDefinitions
|
||||
} from "../loadComponentLibraries"
|
||||
import { buildCodeForScreens } from "../buildCodeForScreens"
|
||||
import { generate_screen_css } from "../generate_css"
|
||||
import { insertCodeMetadata } from "../insertCodeMetadata"
|
||||
|
@ -24,7 +28,7 @@ export const getStore = () => {
|
|||
apps: [],
|
||||
appname: "",
|
||||
hierarchy: {},
|
||||
pages: defaultPagesObject(),
|
||||
pages: DEFAULT_PAGES_OBJECT,
|
||||
mainUi: {},
|
||||
unauthenticatedUi: {},
|
||||
components: [],
|
||||
|
@ -35,8 +39,6 @@ export const getStore = () => {
|
|||
currentComponentProps: null,
|
||||
errors: [],
|
||||
hasAppPackage: false,
|
||||
// accessLevels: { version: 0, levels: [] },
|
||||
// currentNode: null,
|
||||
libraries: null,
|
||||
appId: ""
|
||||
}
|
||||
|
@ -52,7 +54,7 @@ export const getStore = () => {
|
|||
// store.deleteAction = backendStoreActions.deleteAction(store)
|
||||
// store.saveTrigger = backendStoreActions.saveTrigger(store)
|
||||
// store.deleteTrigger = backendStoreActions.deleteTrigger(store)
|
||||
store.importAppDefinition = importAppDefinition(store)
|
||||
// store.importAppDefinition = importAppDefinition(store)
|
||||
|
||||
store.saveScreen = saveScreen(store)
|
||||
store.renameScreen = renameScreen(store)
|
||||
|
@ -60,11 +62,9 @@ export const getStore = () => {
|
|||
store.setCurrentScreen = setCurrentScreen(store)
|
||||
store.setCurrentPage = setCurrentPage(store)
|
||||
store.createScreen = createScreen(store)
|
||||
// store.removeComponentLibrary = removeComponentLibrary(store)
|
||||
store.addStylesheet = addStylesheet(store)
|
||||
store.removeStylesheet = removeStylesheet(store)
|
||||
store.savePage = savePage(store)
|
||||
store.createGeneratedComponents = createGeneratedComponents(store)
|
||||
store.addChildComponent = addChildComponent(store)
|
||||
store.selectComponent = selectComponent(store)
|
||||
store.setComponentProp = setComponentProp(store)
|
||||
|
@ -102,7 +102,9 @@ const setPackage = (store, initial) => async (pkg) => {
|
|||
},
|
||||
}
|
||||
|
||||
initial.libraries = await loadLibs(pkg.application._id, pkg)
|
||||
initial.libraries = await fetchComponentLibModules(pkg.application)
|
||||
// TODO: Rename to componentDefinitions
|
||||
initial.components = await fetchComponentLibDefinitions(pkg.clientId, pkg.application._id);
|
||||
initial.loadLibraryUrls = pageName => {
|
||||
const libs = libUrlsForPreview(pkg, pageName)
|
||||
return libs
|
||||
|
@ -111,40 +113,20 @@ const setPackage = (store, initial) => async (pkg) => {
|
|||
initial.appId = pkg.application._id
|
||||
initial.pages = pkg.pages
|
||||
initial.hasAppPackage = true
|
||||
initial.hierarchy = pkg.appDefinition.hierarchy
|
||||
initial.accessLevels = pkg.accessLevels
|
||||
initial.screens = values(pkg.screens)
|
||||
initial.components = values(pkg.components.components).map(
|
||||
expandComponentDefinition
|
||||
)
|
||||
initial.templates = pkg.components.templates
|
||||
initial.builtins = [getBuiltin("##builtin/screenslot")]
|
||||
initial.actions = values(pkg.appDefinition.actions)
|
||||
initial.triggers = pkg.appDefinition.triggers
|
||||
initial.appInstances = pkg.application.instances
|
||||
initial.appId = pkg.application._id
|
||||
|
||||
store.set(initial)
|
||||
console.log(initial)
|
||||
return initial
|
||||
}
|
||||
|
||||
const importAppDefinition = store => appDefinition => {
|
||||
store.update(s => {
|
||||
s.hierarchy = appDefinition.hierarchy
|
||||
s.currentNode =
|
||||
appDefinition.hierarchy.children.length > 0
|
||||
? appDefinition.hierarchy.children[0]
|
||||
: null
|
||||
s.actions = appDefinition.actions
|
||||
s.triggers = appDefinition.triggers
|
||||
s.currentNodeIsNew = false
|
||||
return s
|
||||
})
|
||||
}
|
||||
|
||||
const saveScreen = store => screen => {
|
||||
store.update(s => {
|
||||
return _saveScreen(store, s, screen)
|
||||
store.update(state => {
|
||||
return _saveScreen(store, state, screen)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -166,10 +148,7 @@ const _saveScreen = async (store, s, screen) => {
|
|||
innerState.screens = screens
|
||||
innerState.currentPreviewItem = screen
|
||||
const safeProps = makePropsSafe(
|
||||
getComponentDefinition(
|
||||
innerState.components,
|
||||
screen.props._component
|
||||
),
|
||||
innerState.components[screen.props._component],
|
||||
screen.props
|
||||
)
|
||||
innerState.currentComponentInfo = safeProps
|
||||
|
@ -192,21 +171,27 @@ const _saveScreenApi = (screen, s) =>
|
|||
.then(() => _savePage(s))
|
||||
|
||||
const createScreen = store => (screenName, route, layoutComponentName) => {
|
||||
store.update(s => {
|
||||
const newScreen = getNewScreen(
|
||||
s.components,
|
||||
layoutComponentName,
|
||||
screenName
|
||||
)
|
||||
store.update(state => {
|
||||
console.log(layoutComponentName);
|
||||
const rootComponent = state.components[layoutComponentName]
|
||||
|
||||
const newScreen = {
|
||||
name: screenName || "",
|
||||
description: "",
|
||||
url: "",
|
||||
_css: "",
|
||||
uiFunctions: "",
|
||||
props: createProps(rootComponent).props,
|
||||
}
|
||||
|
||||
newScreen.route = route
|
||||
s.currentPreviewItem = newScreen
|
||||
s.currentComponentInfo = newScreen.props
|
||||
s.currentFrontEndType = "screen"
|
||||
state.currentPreviewItem = newScreen
|
||||
state.currentComponentInfo = newScreen.props
|
||||
state.currentFrontEndType = "screen"
|
||||
|
||||
_saveScreen(store, s, newScreen)
|
||||
_saveScreen(store, state, newScreen)
|
||||
|
||||
return s
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -219,7 +204,7 @@ const setCurrentScreen = store => screenName => {
|
|||
s.currentView = "detail"
|
||||
|
||||
const safeProps = makePropsSafe(
|
||||
getComponentDefinition(s.components, screen.props._component),
|
||||
s.components[screen.props._component],
|
||||
screen.props
|
||||
)
|
||||
screen.props = safeProps
|
||||
|
@ -229,25 +214,6 @@ const setCurrentScreen = store => screenName => {
|
|||
})
|
||||
}
|
||||
|
||||
const createGeneratedComponents = store => components => {
|
||||
store.update(s => {
|
||||
s.components = [...s.components, ...components]
|
||||
s.screens = [...s.screens, ...components]
|
||||
|
||||
const doCreate = async () => {
|
||||
for (let c of components) {
|
||||
await api.post(`/_builder/api/${s.appId}/screen`, c)
|
||||
}
|
||||
|
||||
await _savePage(s)
|
||||
}
|
||||
|
||||
doCreate()
|
||||
|
||||
return s
|
||||
})
|
||||
}
|
||||
|
||||
const deleteScreen = store => name => {
|
||||
store.update(s => {
|
||||
const components = pipe(s.components, [filter(c => c.name !== name)])
|
||||
|
@ -319,46 +285,6 @@ const savePage = store => async page => {
|
|||
})
|
||||
}
|
||||
|
||||
// const addComponentLibrary = store => async lib => {
|
||||
// const response = await api.get(
|
||||
// `/_builder/api/${s.appId}/componentlibrary?lib=${encodeURI(lib)}`,
|
||||
// undefined,
|
||||
// false
|
||||
// )
|
||||
|
||||
// const success = response.status === 200
|
||||
|
||||
// const components = success ? await response.json() : []
|
||||
|
||||
// store.update(s => {
|
||||
// if (success) {
|
||||
// const componentsArray = []
|
||||
// for (let c in components) {
|
||||
// componentsArray.push(expandComponentDefinition(components[c]))
|
||||
// }
|
||||
|
||||
// s.components = pipe(s.components, [
|
||||
// filter(c => !c.name.startsWith(`${lib}/`)),
|
||||
// concat(componentsArray),
|
||||
// ])
|
||||
|
||||
// s.pages.componentLibraries.push(lib)
|
||||
// _savePage(s)
|
||||
// }
|
||||
|
||||
// return s
|
||||
// })
|
||||
// }
|
||||
|
||||
// const removeComponentLibrary = store => lib => {
|
||||
// store.update(state => {
|
||||
// state.pages.componentLibraries = state.pages.componentLibraries.filter(l => l !== lib);
|
||||
// _savePage(state);
|
||||
|
||||
// return state;
|
||||
// })
|
||||
// }
|
||||
|
||||
const addStylesheet = store => stylesheet => {
|
||||
store.update(s => {
|
||||
s.pages.stylesheets.push(stylesheet)
|
||||
|
@ -386,42 +312,44 @@ const _savePage = async s => {
|
|||
}
|
||||
|
||||
const setCurrentPage = store => pageName => {
|
||||
store.update(s => {
|
||||
const current_screens = s.pages[pageName]._screens
|
||||
store.update(state => {
|
||||
const current_screens = state.pages[pageName]._screens
|
||||
|
||||
s.currentFrontEndType = "page"
|
||||
s.currentPageName = pageName
|
||||
s.screens = Array.isArray(current_screens)
|
||||
const currentPage = state.pages[pageName];
|
||||
|
||||
state.currentFrontEndType = "page"
|
||||
state.currentPageName = pageName
|
||||
state.screens = Array.isArray(current_screens)
|
||||
? current_screens
|
||||
: Object.values(current_screens)
|
||||
const safeProps = makePropsSafe(
|
||||
getComponentDefinition(s.components, s.pages[pageName].props._component),
|
||||
s.pages[pageName].props
|
||||
state.components[currentPage.props._component],
|
||||
currentPage.props
|
||||
)
|
||||
s.currentComponentInfo = safeProps
|
||||
s.pages[pageName].props = safeProps
|
||||
s.currentPreviewItem = s.pages[pageName]
|
||||
s.currentPreviewItem._css = generate_screen_css([
|
||||
s.currentPreviewItem.props,
|
||||
state.currentComponentInfo = safeProps
|
||||
currentPage.props = safeProps
|
||||
state.currentPreviewItem = state.pages[pageName]
|
||||
state.currentPreviewItem._css = generate_screen_css([
|
||||
state.currentPreviewItem.props,
|
||||
])
|
||||
|
||||
for (let screen of s.screens) {
|
||||
for (let screen of state.screens) {
|
||||
screen._css = generate_screen_css([screen.props])
|
||||
}
|
||||
|
||||
setCurrentPageFunctions(s)
|
||||
return s
|
||||
setCurrentPageFunctions(state)
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
const getComponentDefinition = (components, name) =>
|
||||
components.find(c => c.name === name)
|
||||
// const getComponentDefinition = (components, name) => components.find(c => c.name === name)
|
||||
|
||||
/**
|
||||
* @param {string} componentToAdd - name of the component to add to the application
|
||||
* @param {string} presetName - name of the component preset if defined
|
||||
*/
|
||||
const addChildComponent = store => (componentToAdd, presetName) => {
|
||||
// componentToAdd looks like: @budibase/standard-components/container
|
||||
store.update(state => {
|
||||
function findSlot(component_array) {
|
||||
for (let i = 0; i < component_array.length; i += 1) {
|
||||
|
@ -442,7 +370,7 @@ const addChildComponent = store => (componentToAdd, presetName) => {
|
|||
|
||||
const component = componentToAdd.startsWith("##")
|
||||
? getBuiltin(componentToAdd)
|
||||
: state.components.find(({ name }) => name === componentToAdd)
|
||||
: state.components[componentToAdd]
|
||||
|
||||
const presetProps = presetName ? component.presets[presetName] : {}
|
||||
const newComponent = createProps(component, presetProps)
|
||||
|
@ -488,7 +416,7 @@ const selectComponent = store => component => {
|
|||
store.update(state => {
|
||||
const componentDef = component._component.startsWith("##")
|
||||
? component
|
||||
: state.components.find(c => c.name === component._component)
|
||||
: state.components[component._component]
|
||||
state.currentComponentInfo = makePropsSafe(componentDef, component)
|
||||
state.currentView = "component"
|
||||
return state
|
||||
|
@ -508,28 +436,28 @@ const setComponentProp = store => (name, value) => {
|
|||
}
|
||||
|
||||
const setComponentStyle = store => (type, name, value) => {
|
||||
store.update(s => {
|
||||
if (!s.currentComponentInfo._styles) {
|
||||
s.currentComponentInfo._styles = {}
|
||||
store.update(state => {
|
||||
if (!state.currentComponentInfo._styles) {
|
||||
state.currentComponentInfo._styles = {}
|
||||
}
|
||||
s.currentComponentInfo._styles[type][name] = value
|
||||
s.currentPreviewItem._css = generate_screen_css([
|
||||
s.currentPreviewItem.props,
|
||||
state.currentComponentInfo._styles[type][name] = value
|
||||
state.currentPreviewItem._css = generate_screen_css([
|
||||
state.currentPreviewItem.props,
|
||||
])
|
||||
|
||||
// save without messing with the store
|
||||
_saveCurrentPreviewItem(s)
|
||||
return s
|
||||
_saveCurrentPreviewItem(state)
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
const setComponentCode = store => code => {
|
||||
store.update(s => {
|
||||
s.currentComponentInfo._code = code
|
||||
store.update(state => {
|
||||
state.currentComponentInfo._code = code
|
||||
|
||||
setCurrentPageFunctions(s)
|
||||
setCurrentPageFunctions(state)
|
||||
// save without messing with the store
|
||||
_saveScreenApi(s.currentPreviewItem, s)
|
||||
_saveScreenApi(state.currentPreviewItem, state)
|
||||
|
||||
return s
|
||||
})
|
||||
|
@ -543,31 +471,31 @@ const setCurrentPageFunctions = s => {
|
|||
const buildPageCode = (screens, page) => buildCodeForScreens([page, ...screens])
|
||||
|
||||
const setScreenType = store => type => {
|
||||
store.update(s => {
|
||||
s.currentFrontEndType = type
|
||||
store.update(state => {
|
||||
state.currentFrontEndType = type
|
||||
|
||||
const pageOrScreen =
|
||||
type === "page"
|
||||
? s.pages[s.currentPageName]
|
||||
: s.pages[s.currentPageName]._screens[0]
|
||||
? state.pages[state.currentPageName]
|
||||
: state.pages[state.currentPageName]._screens[0]
|
||||
|
||||
s.currentComponentInfo = pageOrScreen ? pageOrScreen.props : null
|
||||
s.currentPreviewItem = pageOrScreen
|
||||
return s
|
||||
state.currentComponentInfo = pageOrScreen ? pageOrScreen.props : null
|
||||
state.currentPreviewItem = pageOrScreen
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
const deleteComponent = store => component => {
|
||||
store.update(s => {
|
||||
const parent = getParent(s.currentPreviewItem.props, component)
|
||||
const deleteComponent = store => componentName => {
|
||||
store.update(state => {
|
||||
const parent = getParent(state.currentPreviewItem.props, componentName)
|
||||
|
||||
if (parent) {
|
||||
parent._children = parent._children.filter(c => c !== component)
|
||||
parent._children = parent._children.filter(component => component !== componentName)
|
||||
}
|
||||
|
||||
_saveCurrentPreviewItem(s)
|
||||
_saveCurrentPreviewItem(state)
|
||||
|
||||
return s
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,133 +0,0 @@
|
|||
<script>
|
||||
import Textbox from "components/common/Textbox.svelte"
|
||||
import Button from "components/common/Button.svelte"
|
||||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
import ButtonGroup from "components/common/ButtonGroup.svelte"
|
||||
import { cloneDeep, filter, keys, map, isUndefined } from "lodash/fp"
|
||||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||
import { validateActions, pipe } from "components/common/core"
|
||||
import getIcon from "components/common/icon"
|
||||
|
||||
export let action
|
||||
export let onFinished = action => {}
|
||||
export let allActions
|
||||
|
||||
let optKey = ""
|
||||
let optValue = ""
|
||||
|
||||
let clonedAction = cloneDeep(action)
|
||||
let initialOptions = pipe(action.initialOptions, [
|
||||
keys,
|
||||
map(k => ({ key: k, value: action.initialOptions[k] })),
|
||||
])
|
||||
let errors = []
|
||||
|
||||
const addNewOption = () => {
|
||||
if (
|
||||
optKey &&
|
||||
optValue &&
|
||||
isUndefined(clonedAction.initialOptions[optKey])
|
||||
) {
|
||||
clonedAction.initialOptions[optKey] = optValue
|
||||
initialOptions = [
|
||||
...initialOptions,
|
||||
{
|
||||
key: optKey,
|
||||
value: optValue,
|
||||
},
|
||||
]
|
||||
optKey = ""
|
||||
optValue = ""
|
||||
}
|
||||
}
|
||||
|
||||
const removeOption = opt => {
|
||||
if (opt) {
|
||||
delete clonedAction.initialOptions[opt.key]
|
||||
initialOptions = pipe(initialOptions, [filter(o => o.key !== opt.key)])
|
||||
}
|
||||
}
|
||||
|
||||
const save = () => {
|
||||
const newActionsList = [
|
||||
...pipe(allActions, [filter(a => a !== action)]),
|
||||
clonedAction,
|
||||
]
|
||||
|
||||
errors = pipe(newActionsList, [validateActions, map(e => e.error)])
|
||||
|
||||
if (errors.length === 0) onFinished(clonedAction)
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
onFinished()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
|
||||
<ErrorsBox {errors} />
|
||||
|
||||
<form on:submit|preventDefault class="uk-form-horizontal">
|
||||
|
||||
<Textbox label="Name" bind:text={clonedAction.name} />
|
||||
<Textbox
|
||||
label="Behaviour Source"
|
||||
bind:text={clonedAction.behaviourSource} />
|
||||
<Textbox label="Behaviour" bind:text={clonedAction.behaviourName} />
|
||||
|
||||
</form>
|
||||
|
||||
<div class=" uk-form-stacked" style="margin-bottom: 20px">
|
||||
<label class="uk-form-label">Default Options</label>
|
||||
<div class="uk-grid-small" uk-grid>
|
||||
<input
|
||||
class="uk-input uk-width-1-4 uk-margin-right"
|
||||
placeholder="key"
|
||||
bind:value={optKey} />
|
||||
<input
|
||||
class="uk-input uk-width-1-4 uk-margin-right"
|
||||
placeholder="value"
|
||||
bind:value={optValue} />
|
||||
<ActionButton primary on:click={addNewOption}>Add</ActionButton>
|
||||
</div>
|
||||
<div style="margin-top: 10px">
|
||||
{#each initialOptions as option}
|
||||
<span class="option-container">
|
||||
{option.key} : {option.value}
|
||||
<span
|
||||
style="font-size:10pt; cursor: pointer"
|
||||
on:click={() => removeOption(option)}>
|
||||
{@html getIcon('trash-2')}
|
||||
</span>
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-modal-footer uk-text-right">
|
||||
<ButtonGroup>
|
||||
<ActionButton primary grouped on:click={save}>Save</ActionButton>
|
||||
<ActionButton alert grouped on:click={cancel}>Cancel</ActionButton>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.root {
|
||||
padding: 2rem;
|
||||
border-radius: 2rem;
|
||||
}
|
||||
|
||||
.uk-grid-small {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.option-container {
|
||||
border-style: dotted;
|
||||
border-width: 1px;
|
||||
border-color: var(--primary75);
|
||||
padding: 3px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
</style>
|
|
@ -1,108 +0,0 @@
|
|||
<script>
|
||||
import getIcon from "components/common/icon"
|
||||
import { store } from "builderStore"
|
||||
import Button from "components/common/Button.svelte"
|
||||
import ButtonGroup from "components/common/ButtonGroup.svelte"
|
||||
import ActionView from "./ActionView.svelte"
|
||||
import Modal from "components/common/Modal.svelte"
|
||||
import { pipe } from "components/common/core"
|
||||
import { keys, map, join } from "lodash/fp"
|
||||
|
||||
export let editingActionIsNew = false
|
||||
export let editingAction = null
|
||||
export let onActionEdit = action => {}
|
||||
export let onActionDelete = action => {}
|
||||
export let onActionSave = action => {}
|
||||
export let onActionCancel = () => {}
|
||||
|
||||
$: isEditing = editingAction !== null
|
||||
|
||||
let actionsArray = []
|
||||
store.subscribe(s => {
|
||||
actionsArray = pipe(s.actions, [keys, map(k => s.actions[k])])
|
||||
})
|
||||
|
||||
let getDefaultOptionsHtml = defaultOptions =>
|
||||
pipe(defaultOptions, [
|
||||
keys,
|
||||
map(
|
||||
k =>
|
||||
`<span style="color:var(--slate)">${k}: </span>${JSON.stringify(
|
||||
defaultOptions[k]
|
||||
)}`
|
||||
),
|
||||
join("<br>"),
|
||||
])
|
||||
|
||||
let actionEditingFinished = action => {
|
||||
if (action) {
|
||||
onActionSave(action)
|
||||
} else {
|
||||
onActionCancel()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<h3 class="budibase__title--3">Actions</h3>
|
||||
|
||||
{#if actionsArray}
|
||||
<table class="fields-table uk-table uk-table-small uk-table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<th>Behaviour Source</th>
|
||||
<th>Behaviour Name</th>
|
||||
<th>Default Options</th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each actionsArray as action}
|
||||
<tr>
|
||||
<td class="table-content">{action.name}</td>
|
||||
<td class="table-content">{action.behaviourSource}</td>
|
||||
<td class="table-content">{action.behaviourName}</td>
|
||||
<td class="table-content">
|
||||
{@html getDefaultOptionsHtml(action.initialOptions)}
|
||||
</td>
|
||||
<td class="edit-button">
|
||||
<span on:click={() => onActionEdit(action)}>
|
||||
{@html getIcon('edit')}
|
||||
</span>
|
||||
<span on:click={() => onActionDelete(action)}>
|
||||
{@html getIcon('trash')}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{:else}(no actions added){/if}
|
||||
|
||||
<Modal
|
||||
title={editingActionIsNew ? 'Create Action' : 'Edit Action'}
|
||||
bind:isOpen={isEditing}>
|
||||
{#if isEditing}
|
||||
<ActionView
|
||||
action={editingAction}
|
||||
allActions={$store.actions}
|
||||
onFinished={actionEditingFinished}
|
||||
isNew={editingActionIsNew} />
|
||||
{/if}
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.edit-button {
|
||||
cursor: pointer;
|
||||
color: var(--secondary25);
|
||||
}
|
||||
|
||||
tr:hover .edit-button {
|
||||
color: var(--secondary75);
|
||||
}
|
||||
|
||||
.table-content {
|
||||
font-weight: 500;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
</style>
|
|
@ -1,135 +0,0 @@
|
|||
<script>
|
||||
import getIcon from "components/common/icon"
|
||||
import { store } from "builderStore"
|
||||
import Button from "components/common/Button.svelte"
|
||||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
import ButtonGroup from "components/common/ButtonGroup.svelte"
|
||||
import Actions from "./Actions.svelte"
|
||||
import Triggers from "./Triggers.svelte"
|
||||
import { getNewAction, getNewTrigger } from "components/common/core"
|
||||
|
||||
let editingAction = null
|
||||
let editingActionIsNew = true
|
||||
let editingTrigger = null
|
||||
let editingTriggerIsNew = true
|
||||
|
||||
let getDefaultOptionsHtml = defaultOptions =>
|
||||
pipe(
|
||||
defaultOptions,
|
||||
[
|
||||
keys,
|
||||
map(
|
||||
k =>
|
||||
`<span style="color:var(--slate)">${k}: </span>${JSON.parse(
|
||||
typeOptions[k]
|
||||
)}`
|
||||
),
|
||||
join("<br>"),
|
||||
]
|
||||
)
|
||||
|
||||
let onActionEdit = action => {
|
||||
editingAction = action
|
||||
editingActionIsNew = false
|
||||
}
|
||||
|
||||
let newAction = () => {
|
||||
editingAction = getNewAction()
|
||||
editingActionIsNew = true
|
||||
}
|
||||
|
||||
let onActionDelete = action => {
|
||||
store.deleteAction(action)
|
||||
}
|
||||
|
||||
let deleteTrigger = () => {}
|
||||
|
||||
let editTrigger = trigger => {
|
||||
editingTrigger = trigger
|
||||
editingTriggerIsNew = false
|
||||
}
|
||||
|
||||
let newTrigger = () => {
|
||||
editingTrigger = getNewTrigger()
|
||||
editingTriggerIsNew = true
|
||||
}
|
||||
|
||||
let onActionSave = action => {
|
||||
store.saveAction(action, editingActionIsNew, editingAction)
|
||||
|
||||
editingAction = null
|
||||
}
|
||||
|
||||
let onActionCancel = () => {
|
||||
editingAction = null
|
||||
}
|
||||
|
||||
let onTriggerSave = trigger => {
|
||||
store.saveTrigger(trigger, editingTriggerIsNew, editingTrigger)
|
||||
|
||||
editingTrigger = null
|
||||
}
|
||||
|
||||
let onTriggerCancel = () => {
|
||||
editingTrigger = null
|
||||
}
|
||||
|
||||
let onTriggerEdit = trigger => {
|
||||
editingTrigger = trigger
|
||||
editingTriggerIsNew = false
|
||||
}
|
||||
|
||||
let onTriggerDelete = trigger => {
|
||||
store.deleteTrigger(trigger)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
<div class="actions-header">
|
||||
<ButtonGroup>
|
||||
<ActionButton color="secondary" grouped on:click={newAction}>
|
||||
Create New Action
|
||||
</ActionButton>
|
||||
<ActionButton color="tertiary" grouped on:click={newTrigger}>
|
||||
Create New Trigger
|
||||
</ActionButton>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
|
||||
<div class="node-view">
|
||||
<Actions
|
||||
{editingActionIsNew}
|
||||
{editingAction}
|
||||
{onActionEdit}
|
||||
{onActionDelete}
|
||||
{onActionSave}
|
||||
{onActionCancel} />
|
||||
|
||||
<Triggers
|
||||
{editingTriggerIsNew}
|
||||
{editingTrigger}
|
||||
{onTriggerEdit}
|
||||
{onTriggerDelete}
|
||||
{onTriggerSave}
|
||||
{onTriggerCancel} />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.root {
|
||||
height: 100%;
|
||||
position: relative;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.actions-header {
|
||||
flex: 0 1 auto;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.node-view {
|
||||
overflow-y: auto;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
</style>
|
|
@ -1,74 +0,0 @@
|
|||
<script>
|
||||
import Textbox from "components/common/Textbox.svelte"
|
||||
import Button from "components/common/Button.svelte"
|
||||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
import Dropdown from "components/common/Dropdown.svelte"
|
||||
import ButtonGroup from "components/common/ButtonGroup.svelte"
|
||||
import CodeArea from "components/common/CodeArea.svelte"
|
||||
import { cloneDeep, filter, keys, some, map, isUndefined } from "lodash/fp"
|
||||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||
import { validateTriggers, pipe, events } from "components/common/core"
|
||||
import getIcon from "components/common/icon"
|
||||
|
||||
export let trigger
|
||||
export let onFinished = action => {}
|
||||
export let allTriggers
|
||||
export let allActions
|
||||
|
||||
let clonedTrigger = cloneDeep(trigger)
|
||||
let errors = []
|
||||
$: actionNames = map(a => a.name)(allActions)
|
||||
|
||||
let cancel = () => onFinished()
|
||||
let save = () => {
|
||||
const newTriggersList = [
|
||||
...pipe(allTriggers, [filter(t => t !== trigger)]),
|
||||
clonedTrigger,
|
||||
]
|
||||
|
||||
errors = validateTriggers(newTriggersList, allActions)
|
||||
|
||||
const test = map(
|
||||
t => !t.actionName || some(a => a.name === t.actionName)(allActions)
|
||||
)(newTriggersList)
|
||||
|
||||
if (errors.length === 0) onFinished(clonedTrigger)
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
|
||||
<ErrorsBox {errors} style="margin-bottom:20px" />
|
||||
|
||||
<form on:submit|preventDefault class="uk-form-horizontal">
|
||||
|
||||
<Dropdown
|
||||
label="Event"
|
||||
options={['', ...events]}
|
||||
bind:selected={clonedTrigger.eventName} />
|
||||
<Dropdown
|
||||
label="Action"
|
||||
options={['', ...actionNames]}
|
||||
bind:selected={clonedTrigger.actionName} />
|
||||
<CodeArea
|
||||
label="Condition"
|
||||
javascript
|
||||
bind:text={clonedTrigger.condition} />
|
||||
<CodeArea
|
||||
label="Action Options Creator"
|
||||
javascript
|
||||
bind:text={clonedTrigger.optionsCreator} />
|
||||
|
||||
</form>
|
||||
|
||||
<div class="uk-modal-footer uk-text-right">
|
||||
<ButtonGroup>
|
||||
<ActionButton primary on:click={save}>Save</ActionButton>
|
||||
<ActionButton alert on:click={cancel}>Cancel</ActionButton>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
|
@ -1,93 +0,0 @@
|
|||
<script>
|
||||
import { store } from "builderStore"
|
||||
import getIcon from "components/common/icon"
|
||||
import Button from "components/common/Button.svelte"
|
||||
import Modal from "components/common/Modal.svelte"
|
||||
import TriggerView from "./TriggerView.svelte"
|
||||
|
||||
export let editingTrigger = null
|
||||
export let editingTriggerIsNew = true
|
||||
export let onTriggerEdit = trigger => {}
|
||||
export let onTriggerDelete = trigger => {}
|
||||
export let onTriggerSave = trigger => {}
|
||||
export let onTriggerCancel = () => {}
|
||||
|
||||
$: isEditing = editingTrigger !== null
|
||||
|
||||
let triggerEditingFinished = trigger => {
|
||||
if (trigger) {
|
||||
onTriggerSave(trigger)
|
||||
} else {
|
||||
onTriggerCancel()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<h3 class="budibase__title--3">Triggers</h3>
|
||||
|
||||
{#if $store.triggers}
|
||||
<table class="fields-table uk-table uk-table-small uk-table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Event</th>
|
||||
<th>Action</th>
|
||||
<th>Condition</th>
|
||||
<th>Create Options</th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each $store.triggers as trigger}
|
||||
<tr>
|
||||
<td class="table-content">{trigger.eventName}</td>
|
||||
<td class="table-content">{trigger.actionName}</td>
|
||||
<td class="table-content">{trigger.condition}</td>
|
||||
<td class="table-content">{trigger.optionsCreator}</td>
|
||||
<td class="edit-button">
|
||||
<span on:click={() => onTriggerEdit(trigger)}>
|
||||
{@html getIcon('edit')}
|
||||
</span>
|
||||
<span on:click={() => onTriggerDelete(trigger)}>
|
||||
{@html getIcon('trash')}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
</table>
|
||||
{:else}(no triggers added){/if}
|
||||
|
||||
<Modal
|
||||
title={editingTriggerIsNew ? 'Create Trigger' : 'Edit Trigger'}
|
||||
onClosed={() => (isEditing = false)}
|
||||
bind:isOpen={isEditing}>
|
||||
{#if isEditing}
|
||||
<TriggerView
|
||||
trigger={editingTrigger}
|
||||
allActions={$store.actions}
|
||||
allTriggers={$store.triggers}
|
||||
onFinished={triggerEditingFinished}
|
||||
isNew={editingTriggerIsNew} />
|
||||
{/if}
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.edit-button {
|
||||
cursor: pointer;
|
||||
color: var(--secondary25);
|
||||
}
|
||||
|
||||
.title {
|
||||
margin: 3rem 0rem 0rem 0rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.table-content {
|
||||
font-weight: 500;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
tr:hover .edit-button {
|
||||
color: var(--secondary75);
|
||||
}
|
||||
</style>
|
|
@ -1,67 +0,0 @@
|
|||
<script>
|
||||
import getIcon from "./icon"
|
||||
export let iconName
|
||||
export let actions = [] // [ {label: "Action Name", onclick: () => {...} } ]
|
||||
let isDroppedDown = false
|
||||
</script>
|
||||
|
||||
<div class="root" on:click={() => (isDroppedDown = !isDroppedDown)}>
|
||||
{@html getIcon(iconName)}
|
||||
|
||||
<div
|
||||
class="dropdown-background"
|
||||
on:click|stopPropagation={() => (isDroppedDown = false)}
|
||||
style="display: {isDroppedDown ? 'block' : 'none'}" />
|
||||
|
||||
<div
|
||||
class="dropdown-content"
|
||||
style="display: {isDroppedDown ? 'inline-block' : 'none'}">
|
||||
{#each actions as action}
|
||||
<div class="budibase__nav-item" on:click={action.onclick}>
|
||||
{action.label}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.dropdown-background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.root {
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
position: absolute;
|
||||
background-color: var(--white);
|
||||
min-width: 160px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
|
||||
z-index: 1;
|
||||
font-weight: normal;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
border-color: var(--secondary10);
|
||||
}
|
||||
|
||||
.dropdown-content:not(:focus) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.action-row {
|
||||
padding: 7px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.action-row:hover {
|
||||
background-color: var(--primary100);
|
||||
color: var(--white);
|
||||
}
|
||||
</style>
|
|
@ -14,7 +14,6 @@
|
|||
takeRight,
|
||||
} from "lodash/fp"
|
||||
import Select from "components/common/Select.svelte"
|
||||
import { getIndexSchema } from "components/common/core"
|
||||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
import TablePagination from "./TablePagination.svelte"
|
||||
import { DeleteRecordModal, CreateEditRecordModal } from "./modals"
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
import api from "builderStore/api"
|
||||
import { store, backendUiStore } from "builderStore"
|
||||
import { common, hierarchy } from "../../../../../../../core/src/"
|
||||
import { getNode } from "components/common/core"
|
||||
import { templateApi, pipe, validate } from "components/common/core"
|
||||
import { pipe } from "components/common/core"
|
||||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||
|
||||
export let model = { schema: {} }
|
||||
|
|
|
@ -10,10 +10,6 @@
|
|||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
import DatePicker from "components/common/DatePicker.svelte"
|
||||
import { keys, cloneDeep } from "lodash/fp"
|
||||
import {
|
||||
allTypes,
|
||||
validate,
|
||||
} from "components/common/core"
|
||||
|
||||
const FIELD_TYPES = ["string", "number", "boolean"]
|
||||
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
import { compose, map, get, flatten } from "lodash/fp"
|
||||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
import Select from "components/common/Select.svelte"
|
||||
import {
|
||||
getNewRecord,
|
||||
joinKey,
|
||||
getExactNodeForKey,
|
||||
} from "components/common/core"
|
||||
import RecordFieldControl from "./RecordFieldControl.svelte"
|
||||
import * as api from "../api"
|
||||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
import { getContext, onMount } from "svelte"
|
||||
import { store, backendUiStore } from "builderStore"
|
||||
import HierarchyRow from "./HierarchyRow.svelte"
|
||||
import DropdownButton from "components/common/DropdownButton.svelte"
|
||||
import NavItem from "./NavItem.svelte"
|
||||
import getIcon from "components/common/icon"
|
||||
import api from "builderStore/api"
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
$: screensExist = $store.currentPreviewItem._screens && $store.currentPreviewItem._screens.length > 0
|
||||
|
||||
$: frontendDefinition = {
|
||||
componentLibraries: $store.loadLibraryUrls($store.currentPageName),
|
||||
libraries: $store.libraries,
|
||||
page: $store.currentPreviewItem,
|
||||
screens: screensExist ? $store.currentPreviewItem._screens : [{
|
||||
name: "Screen Placeholder",
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./CurrentItemPreview.svelte";
|
|
@ -29,23 +29,6 @@
|
|||
const categories = components.categories
|
||||
let selectedCategory = categories[0]
|
||||
|
||||
// const onTemplateChosen = template => {
|
||||
// selectedComponent = null
|
||||
// const { componentName, libName } = splitName(template.name)
|
||||
// const templateOptions = {
|
||||
// records: getRecordNodes(hierarchy),
|
||||
// indexes: getIndexNodes(hierarchy),
|
||||
// helpers: {
|
||||
// indexSchema: getIndexSchema(hierarchy),
|
||||
// },
|
||||
// }
|
||||
|
||||
// templateInstances = libraryModules[libName][componentName](templateOptions)
|
||||
// if (!templateInstances || templateInstances.length === 0) return
|
||||
// selectedTemplateInstance = templateInstances[0].name
|
||||
// selectTemplateDialog.show()
|
||||
// }
|
||||
|
||||
const onComponentChosen = component => {
|
||||
if (component.template) {
|
||||
// onTemplateChosen(component.template)
|
||||
|
@ -55,28 +38,26 @@
|
|||
}
|
||||
}
|
||||
|
||||
const onTemplateInstanceChosen = () => {
|
||||
selectedComponent = null
|
||||
const instance = templateInstances.find(
|
||||
i => i.name === selectedTemplateInstance
|
||||
)
|
||||
store.addTemplatedComponent(instance.props)
|
||||
toggleTab()
|
||||
}
|
||||
// const onTemplateInstanceChosen = () => {
|
||||
// selectedComponent = null
|
||||
// const instance = templateInstances.find(
|
||||
// i => i.name === selectedTemplateInstance
|
||||
// )
|
||||
// store.addTemplatedComponent(instance.props)
|
||||
// toggleTab()
|
||||
// }
|
||||
|
||||
$: templatesByComponent = groupBy(t => t.component)($store.templates)
|
||||
$: hierarchy = $store.hierarchy
|
||||
$: libraryModules = $store.libraries
|
||||
$: standaloneTemplates = pipe(
|
||||
templatesByComponent,
|
||||
[
|
||||
values,
|
||||
flatten,
|
||||
filter(t => !$store.components.some(c => c.name === t.component)),
|
||||
map(t => ({ name: splitName(t.component).componentName, template: t })),
|
||||
uniqBy(t => t.name),
|
||||
]
|
||||
)
|
||||
// $: templatesByComponent = groupBy(t => t.component)($store.templates)
|
||||
// $: standaloneTemplates = pipe(
|
||||
// templatesByComponent,
|
||||
// [
|
||||
// values,
|
||||
// flatten,
|
||||
// filter(t => !$store.components.some(c => c.name === t.component)),
|
||||
// map(t => ({ name: splitName(t.component).componentName, template: t })),
|
||||
// uniqBy(t => t.name),
|
||||
// ]
|
||||
// )
|
||||
</script>
|
||||
|
||||
<div class="root">
|
||||
|
@ -93,12 +74,11 @@
|
|||
<Tab
|
||||
list={selectedCategory}
|
||||
on:selectItem={e => onComponentChosen(e.detail)}
|
||||
{onTemplateChosen}
|
||||
{toggleTab} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ConfirmDialog
|
||||
<!-- <ConfirmDialog
|
||||
bind:this={selectTemplateDialog}
|
||||
title="Choose Template"
|
||||
onCancel={() => (selectedComponent = null)}
|
||||
|
@ -115,7 +95,7 @@
|
|||
</label>
|
||||
</div>
|
||||
{/each}
|
||||
</ConfirmDialog>
|
||||
</ConfirmDialog> -->
|
||||
|
||||
<style>
|
||||
.tabs {
|
||||
|
|
|
@ -33,8 +33,6 @@
|
|||
|
||||
const isComponentSelected = (current, comp) => current === comp
|
||||
|
||||
const isFolderSelected = (current, folder) => isInSubfolder(current, folder)
|
||||
|
||||
$: _screens = pipe(
|
||||
screens,
|
||||
[map(c => ({ component: c, title: lastPartOfName(c) })), sortBy("title")]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { last, pipe } from "lodash/fp"
|
||||
import { last } from "lodash/fp"
|
||||
import { pipe } from "components/common/core";
|
||||
import {
|
||||
XCircleIcon,
|
||||
ChevronUpIcon,
|
||||
|
|
|
@ -33,9 +33,7 @@
|
|||
let selectedEvent = null
|
||||
|
||||
$: {
|
||||
const componentDefinition = components.find(
|
||||
c => c.name === component._component
|
||||
)
|
||||
const componentDefinition = components[component._component];
|
||||
events = Object.keys(componentDefinition.props)
|
||||
.filter(
|
||||
propName => componentDefinition.props[propName].type === EVENT_TYPE
|
||||
|
|
|
@ -26,20 +26,13 @@
|
|||
|
||||
let saveAttempted = false
|
||||
|
||||
$: layoutComponents = pipe(
|
||||
$store.components,
|
||||
[
|
||||
filter(c => c.container),
|
||||
map(c => ({ name: c.name, ...splitName(c.name) })),
|
||||
]
|
||||
)
|
||||
$: layoutComponents = Object.values($store.components).filter(componentDefinition => componentDefinition.container)
|
||||
|
||||
$: layoutComponent = layoutComponent
|
||||
? find(c => c.name === layoutComponent.name)(layoutComponents)
|
||||
? layoutComponents.find(component => component._component === layoutComponent._component)
|
||||
: layoutComponents[0]
|
||||
|
||||
$: screens = $store.screens
|
||||
$: route = !route && screens.length === 0 ? "*" : route
|
||||
$: route = !route && $store.screens.length === 0 ? "*" : route
|
||||
|
||||
const save = () => {
|
||||
saveAttempted = true
|
||||
|
@ -53,7 +46,7 @@
|
|||
|
||||
if (!isValid) return
|
||||
|
||||
store.createScreen(name, route, layoutComponent.name)
|
||||
store.createScreen(name, route, layoutComponent._component)
|
||||
dialog.hide()
|
||||
}
|
||||
|
||||
|
@ -62,21 +55,16 @@
|
|||
}
|
||||
|
||||
const screenNameExists = name => {
|
||||
return some(s => {
|
||||
return s.name.toLowerCase() === name.toLowerCase()
|
||||
})(screens)
|
||||
return $store.screens.some(screen => screen.name.toLowerCase() === name.toLowerCase());
|
||||
}
|
||||
|
||||
const routeNameExists = route => {
|
||||
return some(s => {
|
||||
return s.route.toLowerCase() === route.toLowerCase()
|
||||
})(screens)
|
||||
return $store.screens.some(screen => screen.route.toLowerCase() === route.toLowerCase());
|
||||
}
|
||||
|
||||
const routeChanged = event => {
|
||||
const r = event.target.value
|
||||
if (!r.startsWith("/")) {
|
||||
route = "/" + r
|
||||
if (!event.target.value.startsWith("/")) {
|
||||
route = "/" + event.target.value
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -100,7 +88,7 @@
|
|||
</div>
|
||||
|
||||
<div class="uk-margin">
|
||||
<label class="uk-form-label">Route (Url)</label>
|
||||
<label class="uk-form-label">Route (URL)</label>
|
||||
<div class="uk-form-controls">
|
||||
<input
|
||||
class="uk-input uk-form-small"
|
||||
|
@ -117,8 +105,8 @@
|
|||
class="uk-select uk-form-small"
|
||||
bind:value={layoutComponent}
|
||||
class:uk-form-danger={saveAttempted && !layoutComponent}>
|
||||
{#each layoutComponents as comp}
|
||||
<option value={comp}>{comp.componentName} - {comp.libName}</option>
|
||||
{#each layoutComponents as { _component, name }}
|
||||
<option value={_component}>{name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// import { tick } from "svelte"
|
||||
import ComponentsHierarchyChildren from "./ComponentsHierarchyChildren.svelte"
|
||||
|
||||
import { last, sortBy, map, trimCharsStart, trimChars, join } from "lodash/fp"
|
||||
import { last, sortBy, map, trimCharsStart, trimChars, join, compose } from "lodash/fp"
|
||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||
import { pipe } from "components/common/core"
|
||||
import { store } from "builderStore"
|
||||
|
@ -15,28 +15,15 @@
|
|||
|
||||
const joinPath = join("/")
|
||||
|
||||
const normalizedName = name =>
|
||||
pipe(
|
||||
name,
|
||||
[
|
||||
trimCharsStart("./"),
|
||||
trimCharsStart("~/"),
|
||||
trimCharsStart("../"),
|
||||
trimChars(" "),
|
||||
]
|
||||
)
|
||||
|
||||
const lastPartOfName = c =>
|
||||
c && last(c.name ? c.name.split("/") : c._component.split("/"))
|
||||
|
||||
const isComponentSelected = (current, comp) => current === comp
|
||||
|
||||
const isFolderSelected = (current, folder) => isInSubfolder(current, folder)
|
||||
|
||||
$: _layout = pipe(
|
||||
layout,
|
||||
[c => ({ component: c, title: lastPartOfName(c) })]
|
||||
)
|
||||
$: _layout = {
|
||||
component: layout,
|
||||
title: lastPartOfName(layout)
|
||||
}
|
||||
|
||||
const isScreenSelected = component =>
|
||||
component.component &&
|
||||
|
@ -45,7 +32,6 @@
|
|||
|
||||
const confirmDeleteComponent = async component => {
|
||||
componentToDelete = component
|
||||
// await tick()
|
||||
confirmDeleteDialog.show()
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -7,16 +7,15 @@
|
|||
import { pipe } from "components/common/core"
|
||||
import { filter, find, concat } from "lodash/fp"
|
||||
|
||||
const notSeletedComponent = { name: "(none selected)" }
|
||||
const notSelectedComponent = { name: "(none selected)" }
|
||||
|
||||
$: page = $store.pages[$store.currentPageName]
|
||||
$: title = page.index.title
|
||||
$: components = pipe(
|
||||
$store.components,
|
||||
[filter(store => !isRootComponent($store)), concat([notSeletedComponent])]
|
||||
[filter(store => !isRootComponent($store)), concat([notSelectedComponent])]
|
||||
)
|
||||
$: entryComponent =
|
||||
find(c => c.name === page.appBody)(components) || notSeletedComponent
|
||||
$: entryComponent = components[page.appBody] || notSelectedComponent
|
||||
|
||||
const save = () => {
|
||||
if (!title || !entryComponent || entryComponent === notSeletedComponent)
|
||||
|
|
|
@ -12,10 +12,7 @@
|
|||
let errors = []
|
||||
const props_to_ignore = ["_component", "_children", "_styles", "_code", "_id"]
|
||||
|
||||
$: componentDef =
|
||||
component &&
|
||||
components &&
|
||||
components.find(({ name }) => name === component._component)
|
||||
$: componentDef = components[component._component]
|
||||
|
||||
let setProp = (name, value) => {
|
||||
onPropChanged(name, value)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { store } from "builderStore"
|
||||
import IconButton from "components/common/IconButton.svelte"
|
||||
import NewScreen from "./NewScreen.svelte"
|
||||
import CurrentItemPreview from "./CurrentItemPreview.svelte"
|
||||
import AppPreview from "./AppPreview"
|
||||
import PageView from "./PageView.svelte"
|
||||
import ComponentsPaneSwitcher from "./ComponentsPaneSwitcher.svelte"
|
||||
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
|
||||
|
@ -71,7 +71,7 @@
|
|||
</div>
|
||||
|
||||
<div class="preview-pane">
|
||||
<CurrentItemPreview />
|
||||
<AppPreview />
|
||||
</div>
|
||||
|
||||
{#if $store.currentFrontEndType === 'screen' || $store.currentFrontEndType === 'page'}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { isString, isUndefined } from "lodash/fp"
|
||||
import { types } from "./types"
|
||||
import { TYPE_MAP } from "./types"
|
||||
import { assign } from "lodash"
|
||||
import { uuid } from "builderStore/uuid"
|
||||
|
||||
|
@ -12,17 +12,17 @@ export const getBuiltin = name => {
|
|||
}
|
||||
}
|
||||
|
||||
export const getNewScreen = (components, rootComponentName, name) => {
|
||||
const rootComponent = components.find(c => c.name === rootComponentName)
|
||||
return {
|
||||
name: name || "",
|
||||
description: "",
|
||||
url: "",
|
||||
_css: "",
|
||||
uiFunctions: "",
|
||||
props: createProps(rootComponent).props,
|
||||
}
|
||||
}
|
||||
// export const getNewScreen = (components, rootComponentName, name) => {
|
||||
// const rootComponent = components[rootComponentName]
|
||||
// return {
|
||||
// name: name || "",
|
||||
// description: "",
|
||||
// url: "",
|
||||
// _css: "",
|
||||
// uiFunctions: "",
|
||||
// props: createProps(rootComponent).props,
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* @param {object} componentDefinition - component definition from a component library
|
||||
|
@ -33,9 +33,9 @@ export const createProps = (componentDefinition, derivedFromProps) => {
|
|||
const errorOccurred = (propName, error) => errors.push({ propName, error })
|
||||
|
||||
const props = {
|
||||
_component: componentDefinition.name,
|
||||
_styles: { position: {}, layout: {} },
|
||||
_id: uuid(),
|
||||
_component: componentDefinition._component,
|
||||
_styles: { position: {}, layout: {} },
|
||||
_code: "",
|
||||
}
|
||||
|
||||
|
@ -44,11 +44,14 @@ export const createProps = (componentDefinition, derivedFromProps) => {
|
|||
if (!componentDefinition.name)
|
||||
errorOccurred("_component", "Component name not supplied")
|
||||
|
||||
const propsDef = componentDefinition.props
|
||||
for (let propDef in propsDef) {
|
||||
const parsedPropDef = parsePropDef(propsDef[propDef])
|
||||
if (parsedPropDef.error) errorOccurred(propDef, parsedPropDef.error)
|
||||
else props[propDef] = parsedPropDef
|
||||
for (let propName in componentDefinition.props) {
|
||||
const parsedPropDef = parsePropDef(componentDefinition.props[propName])
|
||||
|
||||
if (parsedPropDef.error) {
|
||||
errors.push({ propName, error: parsedPropDef.error })
|
||||
} else {
|
||||
props[propName] = parsedPropDef
|
||||
}
|
||||
}
|
||||
|
||||
if (derivedFromProps) {
|
||||
|
@ -88,20 +91,18 @@ const parsePropDef = propDef => {
|
|||
const error = message => ({ error: message, propDef })
|
||||
|
||||
if (isString(propDef)) {
|
||||
if (!types[propDef]) return error(`Do not recognise type ${propDef}`)
|
||||
if (!TYPE_MAP[propDef]) return error(`Type ${propDef} is not recognised.`)
|
||||
|
||||
return types[propDef].default()
|
||||
return TYPE_MAP[propDef].default
|
||||
}
|
||||
|
||||
if (!propDef.type) return error("Property Definition must declare a type")
|
||||
const type = TYPE_MAP[propDef.type]
|
||||
if (!type) return error(`Type ${propDef.type} is not recognised.`)
|
||||
|
||||
const type = types[propDef.type]
|
||||
if (!type) return error(`Do not recognise type ${propDef.type}`)
|
||||
// if (isUndefined(propDef.default)) return type.default(propDef)
|
||||
|
||||
if (isUndefined(propDef.default)) return type.default(propDef)
|
||||
|
||||
if (!type.isOfType(propDef.default))
|
||||
return error(`${propDef.default} is not of type ${type}`)
|
||||
// if (!type.isOfType(propDef.default))
|
||||
// return error(`${propDef.default} is not of type ${type}`)
|
||||
|
||||
return propDef.default
|
||||
}
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
import { splitName } from "./splitRootComponentName"
|
||||
import { find, filter, cloneDeep, isPlainObject, isArray } from "lodash/fp"
|
||||
import { isRootComponent } from "./searchComponents"
|
||||
|
||||
export const libraryDependencies = (components, lib) => {
|
||||
const componentDependsOnLibrary = comp => {
|
||||
if (isRootComponent(comp)) {
|
||||
const { libName } = splitName(comp.name)
|
||||
return libName === lib
|
||||
}
|
||||
return componentDependsOnLibrary(
|
||||
find(c => c.name === comp.props._component)(components)
|
||||
)
|
||||
}
|
||||
|
||||
return filter(c => !isRootComponent(c) && componentDependsOnLibrary(c))(
|
||||
components
|
||||
)
|
||||
}
|
||||
|
||||
export const componentDependencies = (
|
||||
pages,
|
||||
screens,
|
||||
components,
|
||||
dependsOn
|
||||
) => {
|
||||
const allComponents = [...cloneDeep(components), ...cloneDeep(screens)]
|
||||
|
||||
pages = cloneDeep(pages)
|
||||
const dependantComponents = []
|
||||
const dependantPages = []
|
||||
|
||||
const traverseProps = props => {
|
||||
if (props._component && props._component === dependsOn.name) {
|
||||
return true
|
||||
}
|
||||
|
||||
for (let propName in props) {
|
||||
const prop = props[propName]
|
||||
if (isPlainObject(prop) && prop._component) {
|
||||
if (traverseProps(prop)) return true
|
||||
}
|
||||
if (isArray(prop)) {
|
||||
for (let element of prop) {
|
||||
if (traverseProps(element)) return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
for (let component of allComponents) {
|
||||
if (isRootComponent(component)) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (component.name === dependsOn.name) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (component.props._component === dependsOn.name) {
|
||||
dependantComponents.push(component)
|
||||
continue
|
||||
}
|
||||
|
||||
if (traverseProps(component.props)) {
|
||||
dependantComponents.push(component)
|
||||
}
|
||||
}
|
||||
|
||||
for (let pageName in pages) {
|
||||
const page = pages[pageName]
|
||||
if (page.appBody === dependsOn.name) {
|
||||
dependantPages.push(pageName)
|
||||
}
|
||||
}
|
||||
|
||||
return { dependantComponents, dependantPages }
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { find, isUndefined, filter, some, includes, pipe } from "lodash/fp"
|
||||
import { find, isUndefined, filter, some, includes } from "lodash/fp"
|
||||
import { pipe } from "components/common/core";
|
||||
|
||||
const normalString = s => (s || "").trim().toLowerCase()
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { split, last, pipe } from "lodash/fp"
|
||||
import { split, last } from "lodash/fp"
|
||||
import { pipe } from "components/common/core";
|
||||
|
||||
export const splitName = fullname => {
|
||||
const componentName = pipe(fullname, [split("/"), last])
|
||||
|
|
|
@ -14,70 +14,86 @@ import {
|
|||
BB_STATE_BINDINGPATH,
|
||||
} from "@budibase/client/src/state/parseBinding"
|
||||
|
||||
const defaultDef = typeName => () => ({
|
||||
type: typeName,
|
||||
required: false,
|
||||
default: types[typeName].default(),
|
||||
options: typeName === "options" ? [] : undefined,
|
||||
})
|
||||
// const defaultDef = typeName => () => ({
|
||||
// type: typeName,
|
||||
// required: false,
|
||||
// default: types[typeName].default,
|
||||
// options: typeName === "options" ? [] : undefined,
|
||||
// })
|
||||
|
||||
const propType = (defaultValue, isOfType, defaultDefinition) => ({
|
||||
isOfType,
|
||||
default: defaultValue,
|
||||
defaultDefinition,
|
||||
})
|
||||
// const propType = (defaultValue, isOfType, defaultDefinition) => ({
|
||||
// isOfType,
|
||||
// default: defaultValue,
|
||||
// defaultDefinition,
|
||||
// })
|
||||
|
||||
const expandSingleProp = propDef => {
|
||||
const p = isString(propDef) ? types[propDef].defaultDefinition() : propDef
|
||||
// const expandSingleProp = propDef => {
|
||||
// const p = isString(propDef) ? types[propDef].defaultDefinition() : propDef
|
||||
|
||||
if (!isString(propDef)) {
|
||||
const def = types[propDef.type].defaultDefinition()
|
||||
for (let p in def) {
|
||||
if (propDef[p] === undefined) {
|
||||
propDef[p] = def[p]
|
||||
}
|
||||
}
|
||||
// if (!isString(propDef)) {
|
||||
// const def = types[propDef.type].defaultDefinition()
|
||||
// for (let p in def) {
|
||||
// if (propDef[p] === undefined) {
|
||||
// propDef[p] = def[p]
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// return p
|
||||
// }
|
||||
|
||||
// export const expandComponentDefinition = componentDefinition => {
|
||||
// const expandedProps = {}
|
||||
// const expandedComponent = { ...componentDefinition }
|
||||
|
||||
// for (let p in componentDefinition.props) {
|
||||
// expandedProps[p] = expandSingleProp(componentDefinition.props[p])
|
||||
// }
|
||||
|
||||
// expandedComponent.props = expandedProps
|
||||
|
||||
// if (expandedComponent.children !== false) {
|
||||
// expandedComponent.children = true
|
||||
// }
|
||||
|
||||
// return expandedComponent
|
||||
// }
|
||||
|
||||
// const isEvent = e =>
|
||||
// isPlainObject(e) &&
|
||||
// isString(e[EVENT_TYPE_MEMBER_NAME]) &&
|
||||
// isPlainObject(e.parameters)
|
||||
|
||||
// const isEventList = e => isArray(e) && every(isEvent)(e)
|
||||
|
||||
// // const EMPTY_STATE = () => ({ [BB_STATE_BINDINGPATH]: "" });
|
||||
|
||||
// export const types = {
|
||||
// string: propType("", isString, defaultDef("string")),
|
||||
// bool: propType(false, isBoolean, defaultDef("bool")),
|
||||
// number: propType(0, isNumber, defaultDef("number")),
|
||||
// options: propType("", isString, defaultDef("options")),
|
||||
// asset: propType("", isString, defaultDef("asset")),
|
||||
// event: propType([], isEventList, defaultDef("event")),
|
||||
// // state: propType(EMPTY_STATE, isBound, defaultDef("state")),
|
||||
// }
|
||||
|
||||
|
||||
export const TYPE_MAP = {
|
||||
string: {
|
||||
default: ""
|
||||
},
|
||||
bool: {
|
||||
default: false
|
||||
},
|
||||
number: {
|
||||
default: 0
|
||||
},
|
||||
options: {
|
||||
default: [],
|
||||
options: []
|
||||
},
|
||||
event: {
|
||||
default: [],
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
export const expandComponentDefinition = componentDefinition => {
|
||||
const expandedProps = {}
|
||||
const expandedComponent = { ...componentDefinition }
|
||||
|
||||
for (let p in componentDefinition.props) {
|
||||
expandedProps[p] = expandSingleProp(componentDefinition.props[p])
|
||||
}
|
||||
|
||||
expandedComponent.props = expandedProps
|
||||
|
||||
if (expandedComponent.children !== false) {
|
||||
expandedComponent.children = true
|
||||
}
|
||||
|
||||
return expandedComponent
|
||||
}
|
||||
|
||||
const isEvent = e =>
|
||||
isPlainObject(e) &&
|
||||
isString(e[EVENT_TYPE_MEMBER_NAME]) &&
|
||||
isPlainObject(e.parameters)
|
||||
|
||||
const isEventList = e => isArray(e) && every(isEvent)(e)
|
||||
|
||||
const emptyState = () => {
|
||||
const s = {}
|
||||
s[BB_STATE_BINDINGPATH] = ""
|
||||
return s
|
||||
}
|
||||
|
||||
export const types = {
|
||||
string: propType(() => "", isString, defaultDef("string")),
|
||||
bool: propType(() => false, isBoolean, defaultDef("bool")),
|
||||
number: propType(() => 0, isNumber, defaultDef("number")),
|
||||
options: propType(() => "", isString, defaultDef("options")),
|
||||
asset: propType(() => "", isString, defaultDef("asset")),
|
||||
event: propType(() => [], isEventList, defaultDef("event")),
|
||||
state: propType(() => emptyState(), isBound, defaultDef("state")),
|
||||
}
|
||||
};
|
|
@ -1,64 +0,0 @@
|
|||
import { isString, keys, flatten, isArray, map, filter } from "lodash/fp"
|
||||
import { common } from "../../../../../core/src"
|
||||
const pipe = common.$
|
||||
|
||||
export const validatePage = page => {
|
||||
const errors = []
|
||||
const error = message => errors.push(message)
|
||||
|
||||
const noIndex = !page.index
|
||||
if (noIndex) {
|
||||
error("Page does not define an index member")
|
||||
}
|
||||
|
||||
if (
|
||||
!page.appBody ||
|
||||
!isString(page.appBody) ||
|
||||
!page.appBody.endsWith(".json")
|
||||
) {
|
||||
error("App body must be set to a valid JSON file")
|
||||
}
|
||||
|
||||
/* Commenting this for now
|
||||
* index is a load of static members just now, but maybe useful
|
||||
for pageLayout props (which is just a pipe dream at time of writing)
|
||||
const indexHtmlErrors = noIndex
|
||||
? []
|
||||
: pipe(
|
||||
recursivelyValidate(page.index, getComponent), [
|
||||
map(e => `Index.html: ${e.error}`)
|
||||
]);
|
||||
*/
|
||||
|
||||
return errors
|
||||
}
|
||||
|
||||
export const validatePages = (pages, getComponent) => {
|
||||
let errors = []
|
||||
const error = message => errors.push(message)
|
||||
|
||||
if (!pages.main) {
|
||||
error("must have a 'main' page")
|
||||
}
|
||||
|
||||
if (!pages.unauthenticated) {
|
||||
error("must have a 'unauthenticated' (login) page")
|
||||
}
|
||||
|
||||
if (
|
||||
!pages.componentLibraries ||
|
||||
!isArray(pages.componentLibraries) ||
|
||||
pages.componentLibraries.length === 0
|
||||
) {
|
||||
error("componentLibraries must be set to a non-empty array of strings")
|
||||
}
|
||||
|
||||
const pageErrors = pipe(pages, [
|
||||
keys,
|
||||
filter(k => k !== "componentLibraries"),
|
||||
map(k => validatePage(pages[k], getComponent)),
|
||||
flatten,
|
||||
])
|
||||
|
||||
return [...errors, ...pageErrors]
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
export const defaultPagesObject = () => ({
|
||||
export const DEFAULT_PAGES_OBJECT = {
|
||||
main: {
|
||||
_props: {},
|
||||
_screens: {},
|
||||
|
@ -17,4 +17,4 @@ export const defaultPagesObject = () => ({
|
|||
},
|
||||
componentLibraries: [],
|
||||
stylesheets: [],
|
||||
})
|
||||
}
|
|
@ -71,6 +71,10 @@ html, body {
|
|||
width:100%;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: var(--fontblack);
|
||||
font-size: 36pt;
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
// Get Package and set store
|
||||
export let application
|
||||
|
||||
let ready = false
|
||||
|
||||
let promise = getPackage()
|
||||
|
||||
async function getPackage() {
|
||||
|
@ -71,6 +73,8 @@
|
|||
<div />
|
||||
{:then}
|
||||
<slot />
|
||||
{:catch error}
|
||||
<p>Something went wrong: {error.message}</p>
|
||||
{/await}
|
||||
|
||||
</div>
|
||||
|
@ -94,13 +98,6 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1 1 auto;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.content > div {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
|
|
@ -4,11 +4,8 @@
|
|||
import { onMount } from "svelte"
|
||||
|
||||
$: instances = $store.appInstances
|
||||
$: views = $store.hierarchy.indexes
|
||||
|
||||
async function selectDatabase(database) {
|
||||
backendUiStore.actions.records.select(null)
|
||||
backendUiStore.actions.views.select(views[0])
|
||||
backendUiStore.actions.database.select(database)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
import {
|
||||
validatePages,
|
||||
validatePage,
|
||||
} from "../src/components/userInterface/pagesParsing/validatePages"
|
||||
|
||||
const validPages = () => ({
|
||||
main: {
|
||||
index: {
|
||||
title: "My Cool App",
|
||||
},
|
||||
appBody: "./main.app.json",
|
||||
},
|
||||
unauthenticated: {
|
||||
index: {
|
||||
title: "My Cool App - Login",
|
||||
},
|
||||
appBody: "./unauthenticated.app.json",
|
||||
},
|
||||
componentLibraries: ["./myComponents"],
|
||||
})
|
||||
|
||||
const getComponent = name =>
|
||||
({
|
||||
testIndexHtml: {
|
||||
name: "testIndexHtml",
|
||||
props: {
|
||||
title: "string",
|
||||
},
|
||||
},
|
||||
}[name])
|
||||
|
||||
describe("validate single page", () => {
|
||||
it("should return no errors when page is valid", () => {
|
||||
const errors = validatePage(validPages().main, getComponent)
|
||||
|
||||
expect(errors).toEqual([])
|
||||
})
|
||||
|
||||
it("should return error when index is not set, or set incorrectly", () => {
|
||||
let page = validPages().main
|
||||
delete page.index
|
||||
expect(validatePage(page, getComponent).length).toEqual(1)
|
||||
})
|
||||
|
||||
it("should return error when appBody is not set, or set incorrectly", () => {
|
||||
let page = validPages().main
|
||||
delete page.appBody
|
||||
expect(validatePage(page, getComponent).length).toEqual(1)
|
||||
|
||||
page.appBody = true // not a string
|
||||
expect(validatePage(page, getComponent).length).toEqual(1)
|
||||
|
||||
page.appBody = "something.js" // not a json
|
||||
expect(validatePage(page, getComponent).length).toEqual(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe("validate pages", () => {
|
||||
it("should return no errors when pages are valid", () => {
|
||||
const errors = validatePages(validPages(), getComponent)
|
||||
|
||||
expect(errors).toEqual([])
|
||||
})
|
||||
|
||||
it("should return error when component libraries not set", () => {
|
||||
const pages = validPages()
|
||||
|
||||
delete pages.componentLibraries
|
||||
let errors = validatePages(pages, getComponent)
|
||||
expect(errors.length).toBe(1)
|
||||
|
||||
pages.componentLibraries = []
|
||||
errors = validatePages(pages, getComponent)
|
||||
expect(errors.length).toBe(1)
|
||||
})
|
||||
|
||||
it("should return error when no main or unauthenticated page", () => {
|
||||
let pages = validPages()
|
||||
delete pages.main
|
||||
let errors = validatePages(pages, getComponent)
|
||||
expect(errors.length).toBe(1)
|
||||
|
||||
pages = validPages()
|
||||
delete pages.unauthenticated
|
||||
errors = validatePages(pages, getComponent)
|
||||
expect(errors.length).toBe(1)
|
||||
})
|
||||
|
||||
it("should return error when page is invalid", () => {
|
||||
const pages = validPages()
|
||||
delete pages.main.index
|
||||
const errors = validatePages(pages, getComponent)
|
||||
expect(errors.length).toBe(1)
|
||||
})
|
||||
})
|
|
@ -20,7 +20,6 @@
|
|||
"author": "Budibase",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"dependencies": {
|
||||
"@budibase/datastores": "^0.0.32",
|
||||
"@budibase/server": "^0.0.32",
|
||||
"@inquirer/password": "^0.0.6-alpha.0",
|
||||
"chalk": "^2.4.2",
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"title": "Test App",
|
||||
"favicon": "./_shared/favicon.png",
|
||||
"stylesheets": [],
|
||||
"componentLibraries": ["@budibase/standard-components", "@budibase/materialdesign-components"],
|
||||
"props" : {
|
||||
"_component": "@budibase/standard-components/container",
|
||||
"_children": [],
|
||||
"_id": 0,
|
||||
"type": "div",
|
||||
"_styles": {
|
||||
"layout": {},
|
||||
"position": {}
|
||||
},
|
||||
"_code": ""
|
||||
},
|
||||
"_css": "",
|
||||
"uiFunctions": ""
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"title": "Test App",
|
||||
"favicon": "./_shared/favicon.png",
|
||||
"stylesheets": [],
|
||||
"componentLibraries": ["@budibase/standard-components", "@budibase/materialdesign-components"],
|
||||
"props" : {
|
||||
"_component": "@budibase/standard-components/container",
|
||||
"_children": [],
|
||||
"_id": 1,
|
||||
"type": "div",
|
||||
"_styles": {
|
||||
"layout": {},
|
||||
"position": {}
|
||||
},
|
||||
"_code": ""
|
||||
},
|
||||
"_css": "",
|
||||
"uiFunctions": ""
|
||||
}
|
|
@ -6,7 +6,6 @@ const { copy, readJSON, writeJSON, remove, exists } = require("fs-extra")
|
|||
const { resolve, join } = require("path")
|
||||
const chalk = require("chalk")
|
||||
const { exec } = require("child_process")
|
||||
const glob = require("glob");
|
||||
|
||||
module.exports = opts => {
|
||||
run(opts)
|
||||
|
|
|
@ -1,27 +1,20 @@
|
|||
const { resolve, join } = require("path")
|
||||
const { cwd } = require("process")
|
||||
const { homedir } = require("os")
|
||||
const buildAppContext = require("@budibase/server/initialise/buildAppContext")
|
||||
|
||||
module.exports.serverFileName = relativePath =>
|
||||
resolve(__dirname, "..", "node_modules", "@budibase", "server", relativePath)
|
||||
|
||||
module.exports.getAppContext = async ({ configName, masterIsCreated }) => {
|
||||
if (configName) {
|
||||
if (!configName.endsWith(".js")) {
|
||||
configName = `config.${configName}.js`
|
||||
}
|
||||
} else {
|
||||
configName = "config.js"
|
||||
}
|
||||
// module.exports.getAppContext = async ({ configName, masterIsCreated }) => {
|
||||
// if (configName) {
|
||||
// if (!configName.endsWith(".js")) {
|
||||
// configName = `config.${configName}.js`
|
||||
// }
|
||||
// } else {
|
||||
// configName = "config.js"
|
||||
// }
|
||||
|
||||
const config = require(resolve(cwd(), configName))()
|
||||
return await buildAppContext(config, masterIsCreated)
|
||||
}
|
||||
// const config = require(resolve(cwd(), configName))()
|
||||
// return await buildAppContext(config, masterIsCreated)
|
||||
// }
|
||||
|
||||
module.exports.xPlatHomeDir = dir => {
|
||||
if (dir.startsWith("~")) {
|
||||
dir = join(homedir(), dir.substring(1))
|
||||
}
|
||||
return dir
|
||||
}
|
||||
module.exports.xPlatHomeDir = dir => dir.startsWith("~") ? join(homedir(), dir.substring(1)) : dir;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,15 +8,14 @@ import { createStateManager } from "./state/stateManager"
|
|||
export const createApp = (
|
||||
componentLibraries,
|
||||
frontendDefinition,
|
||||
backendDefinition,
|
||||
user,
|
||||
uiFunctions,
|
||||
window
|
||||
) => {
|
||||
const coreApi = createCoreApi(backendDefinition, user)
|
||||
backendDefinition.hierarchy = coreApi.templateApi.constructHierarchy(
|
||||
backendDefinition.hierarchy
|
||||
)
|
||||
// const coreApi = createCoreApi(backendDefinition, user)
|
||||
// backendDefinition.hierarchy = coreApi.templateApi.constructHierarchy(
|
||||
// backendDefinition.hierarchy
|
||||
// )
|
||||
|
||||
let routeTo
|
||||
let currentUrl
|
||||
|
@ -26,7 +25,6 @@ export const createApp = (
|
|||
const onScreenSelected = (screen, store, url) => {
|
||||
const stateManager = createStateManager({
|
||||
store,
|
||||
coreApi,
|
||||
frontendDefinition,
|
||||
componentLibraries,
|
||||
uiFunctions,
|
||||
|
@ -74,7 +72,6 @@ export const createApp = (
|
|||
let rootTreeNode
|
||||
const pageStateManager = createStateManager({
|
||||
store: writable({ _bbuser: user }),
|
||||
coreApi,
|
||||
frontendDefinition,
|
||||
componentLibraries,
|
||||
uiFunctions,
|
||||
|
|
|
@ -27,7 +27,7 @@ export const loadBudibase = async opts => {
|
|||
temp: false,
|
||||
}
|
||||
|
||||
const { appRootPath } = frontendDefinition;
|
||||
let { appRootPath } = frontendDefinition;
|
||||
appRootPath = appRootPath === "" ? "" : "/" + trimSlash(appRootPath)
|
||||
|
||||
// if (!componentLibraries) componentLibraries = {};
|
||||
|
@ -58,7 +58,6 @@ export const loadBudibase = async opts => {
|
|||
} = createApp(
|
||||
componentLibraries,
|
||||
frontendDefinition,
|
||||
backendDefinition,
|
||||
user,
|
||||
uiFunctions || {},
|
||||
_window,
|
||||
|
|
|
@ -7,7 +7,7 @@ import { getNewChildRecordToState, getNewRecordToState } from "./coreHandlers"
|
|||
|
||||
export const EVENT_TYPE_MEMBER_NAME = "##eventHandlerType"
|
||||
|
||||
export const eventHandlers = (store, coreApi, rootPath, routeTo) => {
|
||||
export const eventHandlers = (store, rootPath, routeTo) => {
|
||||
const handler = (parameters, execute) => ({
|
||||
execute,
|
||||
parameters,
|
||||
|
@ -34,15 +34,15 @@ export const eventHandlers = (store, coreApi, rootPath, routeTo) => {
|
|||
"List Records": handler(["indexKey", "statePath"], api.listRecords),
|
||||
"Save Record": handler(["statePath"], api.saveRecord),
|
||||
|
||||
"Get New Child Record": handler(
|
||||
["recordKey", "collectionName", "childRecordType", "statePath"],
|
||||
getNewChildRecordToState(coreApi, setStateWithStore)
|
||||
),
|
||||
// "Get New Child Record": handler(
|
||||
// ["recordKey", "collectionName", "childRecordType", "statePath"],
|
||||
// getNewChildRecordToState(coreApi, setStateWithStore)
|
||||
// ),
|
||||
|
||||
"Get New Record": handler(
|
||||
["collectionKey", "childRecordType", "statePath"],
|
||||
getNewRecordToState(coreApi, setStateWithStore)
|
||||
),
|
||||
// "Get New Record": handler(
|
||||
// ["collectionKey", "childRecordType", "statePath"],
|
||||
// getNewRecordToState(coreApi, setStateWithStore)
|
||||
// ),
|
||||
|
||||
"Navigate To": handler(["url"], param => routeTo(param && param.url)),
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ const isMetaProp = propName =>
|
|||
|
||||
export const createStateManager = ({
|
||||
store,
|
||||
coreApi,
|
||||
appRootPath,
|
||||
frontendDefinition,
|
||||
componentLibraries,
|
||||
|
@ -30,7 +29,7 @@ export const createStateManager = ({
|
|||
onScreenSlotRendered,
|
||||
routeTo,
|
||||
}) => {
|
||||
let handlerTypes = eventHandlers(store, coreApi, appRootPath, routeTo)
|
||||
let handlerTypes = eventHandlers(store, appRootPath, routeTo)
|
||||
let currentState
|
||||
|
||||
// any nodes that have props that are bound to the store
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"presets": ["@babel/env"],
|
||||
"sourceMaps": "inline",
|
||||
"retainLines": true
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
/node_modules/
|
|
@ -1,5 +0,0 @@
|
|||
*
|
||||
!datastores/*
|
||||
!index.js
|
||||
!config.js
|
||||
!config.template.js
|
|
@ -1,20 +0,0 @@
|
|||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "debug memory",
|
||||
"program": "${workspaceFolder}/index.js",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node",
|
||||
"runtimeArgs": ["--nolazy"],
|
||||
"args":["memory"],
|
||||
"skipFiles": [
|
||||
"<node_internals>/**/*.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
import fs from "fs"
|
||||
import { join } from "path"
|
||||
import { promisify } from "es6-promisify"
|
||||
import _rimraf from "rimraf"
|
||||
|
||||
const mkdir = promisify(fs.mkdir)
|
||||
const rimraf = promisify(_rimraf)
|
||||
|
||||
const getConfig = async () => {
|
||||
const config = {
|
||||
local: {
|
||||
root: "./output/local/files",
|
||||
},
|
||||
memory: {
|
||||
root: "./output/memory",
|
||||
},
|
||||
azure: {
|
||||
root: "./output/azure",
|
||||
},
|
||||
}
|
||||
|
||||
await rimraf("./output")
|
||||
await mkdir("./output")
|
||||
|
||||
for (let type in config) {
|
||||
await mkdir(join("output", type))
|
||||
}
|
||||
|
||||
await mkdir("./output/local/files")
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
export default getConfig
|
|
@ -1,26 +0,0 @@
|
|||
import { mkdir } from "fs"
|
||||
import { join } from "path"
|
||||
import { promisify } from "es6-promisify"
|
||||
|
||||
const mkdirp = promisify(mkdir)
|
||||
|
||||
const getConfig = async () => {
|
||||
const config = {
|
||||
local: {
|
||||
root: "./output/local/files",
|
||||
},
|
||||
memory: {},
|
||||
}
|
||||
|
||||
await mkdirp("./output")
|
||||
|
||||
for (let type in config) {
|
||||
await mkdirp(join("output", type))
|
||||
}
|
||||
|
||||
await mkdirp("./output/local/files")
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
export default getConfig
|
|
@ -1,81 +0,0 @@
|
|||
import {
|
||||
SharedKeyCredential,
|
||||
BlockBlobURL,
|
||||
BlobURL,
|
||||
ContainerURL,
|
||||
ServiceURL,
|
||||
StorageURL,
|
||||
Aborter,
|
||||
} from "@azure/storage-blob"
|
||||
|
||||
export const createFile = ({ containerUrl }) => async (key, content) => {
|
||||
const blobURL = BlobURL.fromContainerURL(containerUrl, key)
|
||||
const blockBlobURL = BlockBlobURL.fromBlobURL(blobURL)
|
||||
await blockBlobURL.upload(Aborter.none, content, content.length)
|
||||
}
|
||||
|
||||
export const updateFile = opts => async (path, content) =>
|
||||
createFile(opts)(path, content)
|
||||
|
||||
export const loadFile = ({ containerUrl }) => async (key, content) => {
|
||||
const blobURL = BlobURL.fromContainerURL(containerUrl, key)
|
||||
|
||||
const downloadBlockBlobResponse = await blobURL.download(Aborter.none, 0)
|
||||
|
||||
return downloadBlockBlobResponse.readableStreamBody
|
||||
.read(content.length)
|
||||
.toString()
|
||||
}
|
||||
|
||||
export const exists = ({ containerUrl }) => async key => {
|
||||
const blobURL = BlobURL.fromContainerURL(containerUrl, key)
|
||||
const getPropsResponse = await blobURL.getProperties()
|
||||
return getPropsResponse._response.StatusCode === 200
|
||||
}
|
||||
|
||||
export const deleteFile = ({ containerURL }) => async key => {
|
||||
const blobURL = BlobURL.fromContainerURL(containerURL, key)
|
||||
await blobURL.delete(Aborter.none)
|
||||
}
|
||||
|
||||
export const createContainer = ({ containerUrl }) => async () =>
|
||||
await containerUrl.create(Aborter.none)
|
||||
|
||||
export const deleteContainer = ({ containerUrl }) => async () =>
|
||||
await containerUrl.delete(Aborter.none)
|
||||
|
||||
const initialise = opts => {
|
||||
const sharedKeyCredential = new SharedKeyCredential(
|
||||
opts.account,
|
||||
opts.accountKey
|
||||
)
|
||||
|
||||
const pipeline = StorageURL.newPipeline(sharedKeyCredential)
|
||||
|
||||
const serviceURL = new ServiceURL(
|
||||
`https://${opts.account}.blob.core.windows.net`,
|
||||
pipeline
|
||||
)
|
||||
|
||||
const containerURL = ContainerURL.fromServiceURL(
|
||||
serviceURL,
|
||||
opts.containerName
|
||||
)
|
||||
|
||||
return {
|
||||
containerURL,
|
||||
}
|
||||
}
|
||||
|
||||
export default opts => {
|
||||
const access = initialise(opts)
|
||||
return {
|
||||
createFile: createFile(access),
|
||||
updateFile: updateFile(access),
|
||||
loadFile: loadFile(access),
|
||||
exists: exists(access),
|
||||
|
||||
datastoreType: "azure-blob-storage",
|
||||
datastoreDescription: "",
|
||||
}
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
const {
|
||||
access,
|
||||
mkdir,
|
||||
remove,
|
||||
unlink,
|
||||
readdir,
|
||||
rename,
|
||||
stat,
|
||||
readFile,
|
||||
writeFile,
|
||||
} = require("fs-extra")
|
||||
const { join } = require("path")
|
||||
const { createReadStream, createWriteStream } = require("fs")
|
||||
|
||||
const _writeFile = (path, content, overwrite) =>
|
||||
writeFile(path, content, {
|
||||
encoding: "utf8",
|
||||
flag: overwrite ? "w" : "wx",
|
||||
})
|
||||
|
||||
const updateFile = root => async (path, file) =>
|
||||
await _writeFile(join(root, path), file, true)
|
||||
|
||||
const createFile = root => async (path, file) =>
|
||||
await _writeFile(join(root, path), file, false)
|
||||
|
||||
const loadFile = root => async path => await readFile(join(root, path), "utf8")
|
||||
|
||||
const exists = root => async path => {
|
||||
try {
|
||||
await access(join(root, path))
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const createFolder = root => async path => await mkdir(join(root, path))
|
||||
|
||||
const deleteFile = root => async path => await unlink(join(root, path))
|
||||
|
||||
module.exports.deleteFile = deleteFile
|
||||
|
||||
const deleteFolder = root => async path => await remove(join(root, path))
|
||||
|
||||
const readableFileStream = root => async path =>
|
||||
createReadStream(join(root, path))
|
||||
|
||||
const writableFileStream = root => path =>
|
||||
new Promise((resolve, reject) => {
|
||||
const stream = createWriteStream(join(root, path), "utf8")
|
||||
stream.on("open", () => resolve(stream))
|
||||
stream.on("error", reject)
|
||||
})
|
||||
|
||||
const getFolderContents = root => async path => await readdir(join(root, path))
|
||||
|
||||
const renameFile = root => async (oldPath, newPath) =>
|
||||
await rename(join(root, oldPath), join(root, newPath))
|
||||
|
||||
const getFileSize = root => async path => (await stat(join(root, path))).size
|
||||
|
||||
const datastoreFolder = (applicationId, instanceId) =>
|
||||
applicationId === "master" ? "master" : `app.${applicationId}.${instanceId}`
|
||||
|
||||
const createEmptyDb = rootConfig => async (applicationId, instanceId) => {
|
||||
const folder = datastoreFolder(applicationId, instanceId)
|
||||
const dbRootConfig = getDbRootConfig(rootConfig, applicationId, instanceId)
|
||||
await createFolder(dbRootConfig)(folder)
|
||||
return folder
|
||||
}
|
||||
|
||||
const getDatastoreConfig = rootConfig => (applicationId, instanceId) =>
|
||||
join(rootConfig.rootPath, datastoreFolder(applicationId, instanceId))
|
||||
|
||||
const getMasterDbRootConfig = rootConfig => () => rootConfig.rootPath
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const getInstanceDbRootConfig = rootConfig => (_applicationId, _instanceId) =>
|
||||
rootConfig.rootPath
|
||||
const getDbRootConfig = (rootConfig, applicationId, instanceId) =>
|
||||
applicationId === "master"
|
||||
? getMasterDbRootConfig(rootConfig)()
|
||||
: getInstanceDbRootConfig(rootConfig)(applicationId, instanceId)
|
||||
|
||||
module.exports.databaseManager = rootConfig => ({
|
||||
createEmptyDb: createEmptyDb(rootConfig),
|
||||
getDatastoreConfig: getDatastoreConfig(rootConfig),
|
||||
getMasterDbRootConfig: getMasterDbRootConfig(rootConfig),
|
||||
getInstanceDbRootConfig: getInstanceDbRootConfig(rootConfig),
|
||||
})
|
||||
|
||||
module.exports.getDatastore = rootFolderPath => ({
|
||||
createFile: createFile(rootFolderPath),
|
||||
updateFile: updateFile(rootFolderPath),
|
||||
loadFile: loadFile(rootFolderPath),
|
||||
exists: exists(rootFolderPath),
|
||||
deleteFile: deleteFile(rootFolderPath),
|
||||
createFolder: createFolder(rootFolderPath),
|
||||
deleteFolder: deleteFolder(rootFolderPath),
|
||||
readableFileStream: readableFileStream(rootFolderPath),
|
||||
writableFileStream: writableFileStream(rootFolderPath),
|
||||
renameFile: renameFile(rootFolderPath),
|
||||
getFolderContents: getFolderContents(rootFolderPath),
|
||||
getFileSize: getFileSize(rootFolderPath),
|
||||
createEmptyDb: createEmptyDb(rootFolderPath),
|
||||
datastoreType: "local",
|
||||
datastoreDescription: rootFolderPath,
|
||||
})
|
||||
|
||||
module.exports.configParameters = {
|
||||
rootPath: "Root Data Folder",
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
import { isUndefined, has } from "lodash"
|
||||
import { take } from "lodash/fp"
|
||||
import { Readable, Writable } from "readable-stream"
|
||||
import { Buffer } from "safe-buffer"
|
||||
import { splitKey, joinKey, $ } from "../src/common"
|
||||
import { getLastPartInKey } from "../src/templateApi/heirarchy"
|
||||
|
||||
const folderMarker = "OH-YES-ITSA-FOLDER-"
|
||||
const isFolder = val => val.includes(folderMarker)
|
||||
|
||||
const getParentFolderKey = key =>
|
||||
$(key, [splitKey, take(splitKey(key).length - 1), joinKey])
|
||||
|
||||
const getParentFolder = (data, key) => {
|
||||
const parentKey = getParentFolderKey(key)
|
||||
if (data[parentKey] === undefined)
|
||||
throw new Error(
|
||||
"Parent folder for " + key + " does not exist (" + parentKey + ")"
|
||||
)
|
||||
return JSON.parse(data[parentKey])
|
||||
}
|
||||
|
||||
const addItemToParentFolder = (data, path) => {
|
||||
if (getParentFolderKey(path) === "/") return
|
||||
const parentFolder = getParentFolder(data, path)
|
||||
parentFolder.items.push(getLastPartInKey(path))
|
||||
data[getParentFolderKey(path)] = JSON.stringify(parentFolder)
|
||||
}
|
||||
|
||||
export const createFile = data => async (path, content) => {
|
||||
if (await exists(data)(path)) {
|
||||
throw new Error(path + " already exists")
|
||||
}
|
||||
addItemToParentFolder(data, path)
|
||||
data[path] = content
|
||||
}
|
||||
export const updateFile = data => async (path, content) => {
|
||||
// putting this check in to force use of create
|
||||
if (!(await exists(data)(path)))
|
||||
throw new Error("cannot update " + path + " - does not exist")
|
||||
data[path] = content
|
||||
}
|
||||
|
||||
export const writableFileStream = data => async path => {
|
||||
//if(!await exists(data)(path)) throw new Error("cannot write stream to " + path + " - does not exist");
|
||||
const stream = Writable()
|
||||
stream._write = (chunk, encoding, done) => {
|
||||
data[path] = data[path] === undefined ? [] : data[path]
|
||||
data[path] = [...data[path], ...chunk]
|
||||
done()
|
||||
}
|
||||
return stream
|
||||
}
|
||||
|
||||
export const readableFileStream = data => async path => {
|
||||
if (!(await exists(data)(path)))
|
||||
throw new Error("cannot read stream from " + path + " - does not exist")
|
||||
const s = new Readable()
|
||||
s._read = () => {
|
||||
s.push(Buffer.from(data[path]))
|
||||
s.push(null)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
export const renameFile = data => async (oldKey, newKey) => {
|
||||
if (!(await exists(data)(oldKey)))
|
||||
throw new Error("cannot rename path: " + oldKey + " ... does not exist")
|
||||
if (await exists(data)(newKey))
|
||||
throw new Error("cannot rename path: " + newKey + " ... already exists")
|
||||
data[newKey] = data[oldKey]
|
||||
delete data[oldKey]
|
||||
}
|
||||
|
||||
export const loadFile = data => async path => {
|
||||
const result = data[path]
|
||||
if (isUndefined(result))
|
||||
throw new Error("Load failed - path " + path + " does not exist")
|
||||
return result
|
||||
}
|
||||
export const exists = data => async path => has(data, path)
|
||||
export const deleteFile = data => async path => {
|
||||
if (!(await exists(data)(path)))
|
||||
throw new Error("Cannot delete file, path " + path + " does not exist")
|
||||
if (isFolder(data[path]))
|
||||
throw new Error("DeleteFile: Path " + path + " is a folder, not a file")
|
||||
const parentFolder = getParentFolder(data, path)
|
||||
parentFolder.items = parentFolder.items.filter(
|
||||
i => i !== getLastPartInKey(path)
|
||||
)
|
||||
data[getParentFolderKey(path)] = JSON.stringify(parentFolder)
|
||||
delete data[path]
|
||||
}
|
||||
export const createFolder = data => async path => {
|
||||
if (await exists(data)(path))
|
||||
throw new Error("Cannot create folder, path " + path + " already exists")
|
||||
addItemToParentFolder(data, path)
|
||||
data[path] = JSON.stringify({ folderMarker, items: [] })
|
||||
}
|
||||
export const deleteFolder = data => async path => {
|
||||
if (!(await exists(data)(path)))
|
||||
throw new Error("Cannot delete folder, path " + path + " does not exist")
|
||||
if (!isFolder(data[path]))
|
||||
throw new Error("DeleteFolder: Path " + path + " is not a folder")
|
||||
delete data[path]
|
||||
}
|
||||
|
||||
export const getFolderContents = data => async folderPath => {
|
||||
if (!isFolder(data[folderPath]))
|
||||
throw new Error("Not a folder: " + folderPath)
|
||||
if (!(await exists(data)(folderPath)))
|
||||
throw new Error("Folder does not exist: " + folderPath)
|
||||
return JSON.parse(data[folderPath]).items
|
||||
}
|
||||
|
||||
export default data => {
|
||||
return {
|
||||
createFile: createFile(data),
|
||||
updateFile: updateFile(data),
|
||||
loadFile: loadFile(data),
|
||||
exists: exists(data),
|
||||
deleteFile: deleteFile(data),
|
||||
createFolder: createFolder(data),
|
||||
deleteFolder: deleteFolder(data),
|
||||
readableFileStream: readableFileStream(data),
|
||||
writableFileStream: writableFileStream(data),
|
||||
renameFile: renameFile(data),
|
||||
getFolderContents: getFolderContents(data),
|
||||
datastoreType: "memory",
|
||||
datastoreDescription: "",
|
||||
data,
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
import local from "./datastores/local"
|
||||
import azureBlob from "./datastores/azure-blob"
|
||||
import memory from "./datastores/memory"
|
||||
import getConfig from "./config"
|
||||
import tests from "./tests"
|
||||
|
||||
const initialise = async () => {
|
||||
const type = process.argv[2]
|
||||
const config = (await getConfig())[type]
|
||||
|
||||
switch (type) {
|
||||
case "local":
|
||||
return { datastore: local(config.root), config }
|
||||
case "memory":
|
||||
return { datastore: memory(config), config }
|
||||
case "azure":
|
||||
return { datastore: azureBlob(config), config }
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
initialise()
|
||||
.then(init => {
|
||||
return tests(init.datastore, init.config)
|
||||
})
|
||||
.then(() => console.log("done"))
|
||||
.catch(e => console.log(e))
|
|
@ -1,39 +0,0 @@
|
|||
{
|
||||
"name": "@budibase/datastores",
|
||||
"version": "0.0.32",
|
||||
"description": "implementations of all the datastores... azureblob, local etc",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"memory": "npx babel-node index.js memory",
|
||||
"local": "npx babel-node index.js local",
|
||||
"azure": "npx babel-node index.js azure"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+ssh://git@gitlab.com/budibase-source/budibase-datastores.git"
|
||||
},
|
||||
"keywords": [
|
||||
"budibase"
|
||||
],
|
||||
"author": "Michael Shanks",
|
||||
"license": "AGPL-3.0",
|
||||
"bugs": {
|
||||
"url": "https://gitlab.com/budibase-source/budibase-datastores/issues"
|
||||
},
|
||||
"homepage": "https://gitlab.com/budibase-source/budibase-datastores#README",
|
||||
"dependencies": {
|
||||
"@azure/storage-blob": "^10.1.0-preview",
|
||||
"@babel/cli": "^7.1.2",
|
||||
"@babel/core": "^7.1.2",
|
||||
"@babel/node": "^7.0.0",
|
||||
"@babel/preset-env": "^7.1.0",
|
||||
"@budibase/core": "^0.0.32",
|
||||
"es6-promisify": "^6.0.1",
|
||||
"fs-extra": "^8.1.0",
|
||||
"lodash": "^4.17.13",
|
||||
"p-limit": "^2.0.0",
|
||||
"papaparse": "^4.6.1",
|
||||
"rimraf": "^2.6.2"
|
||||
},
|
||||
"gitHead": "b1f4f90927d9e494e513220ef060af28d2d42455"
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
import { eventsList } from "@budibase/core"
|
||||
import { filter, union, has, map } from "lodash/fp"
|
||||
|
||||
const allEventsOfType = type => filter(e => e.endsWith(`:${type}`))(eventsList)
|
||||
|
||||
const hasRecord = has("record")
|
||||
|
||||
export const register = (app, logTimeElapsed, eventNamespaces = []) => {
|
||||
const onCompleteEvents =
|
||||
eventNamespaces.length === 0
|
||||
? allEventsOfType("onComplete")
|
||||
: map(e => `${e}:onComplete`)(eventNamespaces)
|
||||
|
||||
const onErrorEvents =
|
||||
eventNamespaces.length === 0
|
||||
? allEventsOfType("onError")
|
||||
: map(e => `${e}:onError`)(eventNamespaces)
|
||||
|
||||
for (let ev of union(onCompleteEvents)(onErrorEvents)) {
|
||||
app.subscribe(ev, (_, ctx) => {
|
||||
const info = hasRecord(ctx) ? ctx.record.type() : ""
|
||||
|
||||
logTimeElapsed(ev, ctx.elapsed, info)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import { map } from "lodash"
|
||||
|
||||
export const action = (name, run, iterator = iterateActionTimes(1)) => ({
|
||||
name,
|
||||
run,
|
||||
iterator,
|
||||
})
|
||||
|
||||
export const iterateActionTimes = times => run =>
|
||||
map([...Array(times).keys()], run)
|
||||
|
||||
export const iterateCollection = getCollection => run =>
|
||||
map(getCollection(), run)
|
|
@ -1,60 +0,0 @@
|
|||
import setup from "./setup"
|
||||
import records from "./records"
|
||||
import { register } from "./diagnosticPlugin"
|
||||
import pLimit from "p-limit"
|
||||
import papa from "papaparse"
|
||||
import { writeFileSync } from "fs"
|
||||
|
||||
const limit = pLimit(1)
|
||||
|
||||
const iterateActions = async (apis, getIterator) => {
|
||||
const iterator = getIterator(apis)
|
||||
let result = iterator()
|
||||
while (!result.done) {
|
||||
try {
|
||||
const runPromises = result.action.iterator(i =>
|
||||
limit(() => result.action.run(i))
|
||||
)
|
||||
|
||||
await Promise.all(runPromises)
|
||||
result = iterator()
|
||||
} catch (e) {
|
||||
e.message = `FAILED: ${result.action.name}: ${e.message}`
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default async (datastore, config) => {
|
||||
const apis = await setup(datastore)
|
||||
|
||||
const diagnostics = []
|
||||
let currentRecordCount = 0
|
||||
|
||||
register(
|
||||
apis,
|
||||
(ev, elapsed, info) => {
|
||||
if (ev === "recordApi:save:onComplete") {
|
||||
currentRecordCount++
|
||||
} else if (ev === "recordApi:delete:onComplete") {
|
||||
currentRecordCount--
|
||||
}
|
||||
diagnostics.push({ method: ev, elapsed, info, count: currentRecordCount })
|
||||
console.log(`${ev} ${info} ${elapsed / 1000} s`)
|
||||
},
|
||||
[
|
||||
"recordApi:save",
|
||||
"recordApi:load",
|
||||
"viewApi:listItems",
|
||||
"recordApi:delete",
|
||||
]
|
||||
)
|
||||
|
||||
await iterateActions(apis, records)
|
||||
|
||||
const diagnosticscsv = papa.unparse(diagnostics)
|
||||
|
||||
writeFileSync(config.root + "\\results.csv", diagnosticscsv, {
|
||||
encoding: "utf8",
|
||||
})
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
import { action, iterateActionTimes } from "./helpers"
|
||||
import { isUndefined, union } from "lodash"
|
||||
|
||||
const createClient = (apis, getState) => async i => {
|
||||
const client = apis.recordApi.getNew("/clients", "client")
|
||||
client.FamilyName = "Humperdink"
|
||||
client.Address1 = `${i} Mainitucetts Avenue`
|
||||
client.Address2 = "Longerton Road South"
|
||||
client.Address3 = "Chalico City"
|
||||
client.Address4 = "Northern Humranistan"
|
||||
client.Postcode = "BY71 5FR"
|
||||
client.CreatedDate = new Date()
|
||||
|
||||
const state = getState()
|
||||
if (isUndefined(state.clientKeys)) state.clientKeys = []
|
||||
state.clientKeys.push(client.key())
|
||||
|
||||
await apis.recordApi.save(client)
|
||||
|
||||
return client.key()
|
||||
}
|
||||
|
||||
const listClients = (apis, getState) => async () => {
|
||||
const clients = await apis.viewApi.listItems("/clients/default")
|
||||
const state = getState()
|
||||
if (state.clientKeys.length !== clients.length) {
|
||||
throw new Error(
|
||||
"list CLients, expected " +
|
||||
state.clientKeys.length.toString() +
|
||||
" clients, actual " +
|
||||
clients.length.toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default apis => {
|
||||
const state = {}
|
||||
const getState = () => state
|
||||
|
||||
const noOfRecords = 10000
|
||||
const recordsPerIteration = 10
|
||||
const noOfIterations = noOfRecords / recordsPerIteration
|
||||
|
||||
const actionsInOneIteration = () => [
|
||||
action(
|
||||
"Create client",
|
||||
createClient(apis, getState),
|
||||
iterateActionTimes(recordsPerIteration)
|
||||
),
|
||||
|
||||
action("List Clients", listClients(apis, getState)),
|
||||
]
|
||||
|
||||
let actions = []
|
||||
for (let index = 0; index < noOfIterations; index++) {
|
||||
actions = union(actions, actionsInOneIteration())
|
||||
}
|
||||
|
||||
let actionIndex = 0
|
||||
|
||||
return () => {
|
||||
if (actionIndex == actions.length) {
|
||||
return { done: true }
|
||||
}
|
||||
const result = { action: actions[actionIndex], done: false }
|
||||
actionIndex++
|
||||
return result
|
||||
}
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
import { getAppApis, getTemplateApi, setupDatastore } from "@budibase/core"
|
||||
|
||||
const addField = templateApi => type => (record, name) => {
|
||||
const field = templateApi.getNewField(type)
|
||||
field.name = name
|
||||
field.type = type
|
||||
field.label = name
|
||||
templateApi.addField(record, field)
|
||||
}
|
||||
|
||||
export default async datastore => {
|
||||
datastore = setupDatastore(datastore)
|
||||
const templateApi = await getTemplateApi(datastore)
|
||||
const addStringField = addField(templateApi)("string")
|
||||
const addDateField = addField(templateApi)("datetime")
|
||||
const addBoolField = addField(templateApi)("bool")
|
||||
|
||||
const root = templateApi.getNewRootLevel()
|
||||
|
||||
const clients = templateApi.getNewCollectionTemplate(root)
|
||||
clients.name = "clients"
|
||||
|
||||
const client = templateApi.getNewModelTemplate(clients)
|
||||
client.name = "client"
|
||||
addStringField(client, "FamilyName")
|
||||
addStringField(client, "Address1")
|
||||
addStringField(client, "Address2")
|
||||
addStringField(client, "Address3")
|
||||
addStringField(client, "Address4")
|
||||
addStringField(client, "Postcode")
|
||||
addDateField(client, "CreatedDate")
|
||||
|
||||
const children = templateApi.getNewCollectionTemplate(client)
|
||||
children.name = "children"
|
||||
|
||||
const child = templateApi.getNewModelTemplate(children)
|
||||
child.name = "child"
|
||||
addStringField(child, "FirstName")
|
||||
addStringField(child, "Surname")
|
||||
addDateField(child, "DateOfBirth")
|
||||
addBoolField(child, "Current")
|
||||
|
||||
const contacts = templateApi.getNewCollectionTemplate(client)
|
||||
contacts.name = "contacts"
|
||||
|
||||
const contact = templateApi.getNewModelTemplate(contacts)
|
||||
contact.name = "contact"
|
||||
addStringField(contact, "Name")
|
||||
addStringField(contact, "relationship")
|
||||
addStringField(contact, "phone1")
|
||||
addStringField(contact, "phone2")
|
||||
addBoolField(contact, "active")
|
||||
|
||||
await templateApi.saveApplicationHeirarchy(root)
|
||||
|
||||
const apis = await getAppApis(datastore)
|
||||
|
||||
await apis.collectionApi.initialiseAll()
|
||||
|
||||
return apis
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -24,6 +24,10 @@ exports.create = async function(ctx) {
|
|||
const { id, rev } = await clientDb.post({
|
||||
type: "app",
|
||||
instances: [],
|
||||
componentLibraries: [
|
||||
"@budibase/standard-components",
|
||||
"@budibase/materialdesign-components"
|
||||
],
|
||||
...ctx.request.body,
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
const CouchDB = require("../../db");
|
||||
const { homedir } = require("os");
|
||||
const { resolve, join } = require("path");
|
||||
|
||||
exports.fetchAppComponentDefinitions = async function(ctx) {
|
||||
const db = new CouchDB(`client-${ctx.params.clientId}`);
|
||||
const app = await db.get(ctx.params.appId)
|
||||
|
||||
const componentDefinitions = app.componentLibraries.reduce((acc, componentLibrary) => {
|
||||
const appDirectory = resolve(homedir(), ".budibase", ctx.params.appId, "node_modules");
|
||||
const componentJson = require(join(appDirectory, componentLibrary, "components.json"));
|
||||
|
||||
const result = {};
|
||||
|
||||
// map over the components.json and add the library identifier as a key
|
||||
// button -> @budibase/standard-components/button
|
||||
for (key in componentJson) {
|
||||
const fullComponentName = `${componentLibrary}/${key}`;
|
||||
result[fullComponentName] = {
|
||||
_component: fullComponentName,
|
||||
...componentJson[key]
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
...result
|
||||
};
|
||||
}, {});
|
||||
|
||||
ctx.body = componentDefinitions;
|
||||
};
|
|
@ -1,5 +1,6 @@
|
|||
const send = require("koa-send");
|
||||
const { resolve } = require("path")
|
||||
const { homedir } = require("os");
|
||||
|
||||
// either serve the builder or serve the actual app index.html
|
||||
const builderPath = resolve(process.cwd(), "builder")
|
||||
|
@ -16,5 +17,29 @@ exports.serveApp = async function(ctx) {
|
|||
}
|
||||
|
||||
exports.serveComponentLibrary = async function(ctx) {
|
||||
await send(ctx, "/index.html", { root: builderPath })
|
||||
// TODO: update to run wherever budi is run
|
||||
const componentLibraryPath = resolve(
|
||||
homedir(),
|
||||
".budibase",
|
||||
ctx.params.appId,
|
||||
"node_modules",
|
||||
decodeURI(ctx.query.library),
|
||||
"dist"
|
||||
);
|
||||
|
||||
await send(ctx, "/index.js", { root: componentLibraryPath })
|
||||
}
|
||||
|
||||
exports.serveComponentDefinitions = async function(ctx) {
|
||||
// TODO: update to run wherever budi is run
|
||||
const componentLibraryPath = resolve(
|
||||
homedir(),
|
||||
".budibase",
|
||||
ctx.params.appId,
|
||||
"node_modules",
|
||||
decodeURI(ctx.query.library),
|
||||
"dist"
|
||||
);
|
||||
|
||||
await send(ctx, "/index.js", { root: componentLibraryPath })
|
||||
}
|
|
@ -1,16 +1,15 @@
|
|||
const Router = require("@koa/router")
|
||||
const session = require("../middleware/session")
|
||||
const StatusCodes = require("../utilities/statusCodes")
|
||||
const compress = require("koa-compress");
|
||||
const zlib = require("zlib");
|
||||
const { resolve } = require("path")
|
||||
const { homedir } = require("os")
|
||||
const send = require("koa-send")
|
||||
const routeHandlers = require("../middleware/routeHandlers")
|
||||
const {
|
||||
componentLibraryInfo,
|
||||
} = require("../utilities/builder")
|
||||
const {
|
||||
componentRoutes,
|
||||
appsRoutes,
|
||||
// componentRoutes,
|
||||
pageRoutes,
|
||||
userRoutes,
|
||||
authenticatedRoutes
|
||||
|
@ -24,11 +23,21 @@ const applicationRoutes = require("./routes/neo/application");
|
|||
const modelsRoutes = require("./routes/neo/model");
|
||||
const viewsRoutes = require("./routes/neo/view");
|
||||
const staticRoutes = require("./routes/neo/static");
|
||||
const componentRoutes = require("./routes/neo/component");
|
||||
|
||||
module.exports = app => {
|
||||
const router = new Router()
|
||||
|
||||
router
|
||||
.use(compress({
|
||||
threshold: 2048,
|
||||
gzip: {
|
||||
flush: zlib.Z_SYNC_FLUSH
|
||||
},
|
||||
deflate: {
|
||||
flush: zlib.Z_SYNC_FLUSH,
|
||||
}
|
||||
}))
|
||||
// .use(session(app))
|
||||
.use(async (ctx, next) => {
|
||||
// TODO: temp dev middleware
|
||||
|
@ -107,14 +116,14 @@ module.exports = app => {
|
|||
// .get("/_builder", async ctx => {
|
||||
// await send(ctx, "/index.html", { root: builderPath })
|
||||
// })
|
||||
.get("/_builder/:appname/componentlibrary", async ctx => {
|
||||
const info = await componentLibraryInfo(
|
||||
ctx.config,
|
||||
ctx.params.appname,
|
||||
ctx.query.lib
|
||||
)
|
||||
await send(ctx, info.components._lib || "index.js", { root: info.libDir })
|
||||
})
|
||||
// .get("/_builder/:appname/componentlibrary", async ctx => {
|
||||
// const info = await componentLibraryInfo(
|
||||
// ctx.config,
|
||||
// ctx.params.appname,
|
||||
// ctx.query.lib
|
||||
// )
|
||||
// await send(ctx, info.components._lib || "index.js", { root: info.libDir })
|
||||
// })
|
||||
// .get("/_builder/*", async (ctx, next) => {
|
||||
// const path = ctx.path.replace("/_builder", "")
|
||||
|
||||
|
@ -149,8 +158,8 @@ module.exports = app => {
|
|||
router.use(userRoutes.allowedMethods());
|
||||
// router.use(appsRoutes.routes())
|
||||
// router.use(appsRoutes.allowedMethods());
|
||||
router.use(componentRoutes.routes());
|
||||
router.use(componentRoutes.allowedMethods());
|
||||
// router.use(componentRoutes.routes());
|
||||
// router.use(componentRoutes.allowedMethods());
|
||||
router.use(pageRoutes.routes());
|
||||
router.use(pageRoutes.allowedMethods());
|
||||
|
||||
|
@ -167,6 +176,9 @@ module.exports = app => {
|
|||
router.use(applicationRoutes.routes());
|
||||
router.use(applicationRoutes.allowedMethods());
|
||||
|
||||
router.use(componentRoutes.routes());
|
||||
router.use(componentRoutes.allowedMethods());
|
||||
|
||||
router.use(clientRoutes.routes());
|
||||
router.use(clientRoutes.allowedMethods());
|
||||
|
||||
|
@ -188,8 +200,8 @@ module.exports = app => {
|
|||
// .get("/_builder/instance/:appname/:instanceid/*", routeHandlers.appDefault)
|
||||
|
||||
|
||||
router.use(authenticatedRoutes.routes());
|
||||
router.use(authenticatedRoutes.allowedMethods());
|
||||
// router.use(authenticatedRoutes.routes());
|
||||
// router.use(authenticatedRoutes.allowedMethods());
|
||||
|
||||
return router
|
||||
}
|
||||
|
|
|
@ -26,15 +26,15 @@ const router = Router();
|
|||
// routeHandlers.changeMyPassword
|
||||
// )
|
||||
|
||||
router.post(
|
||||
"/:appname/api/executeAction/:actionname",
|
||||
routeHandlers.executeAction
|
||||
)
|
||||
// router.post(
|
||||
// "/:appname/api/executeAction/:actionname",
|
||||
// routeHandlers.executeAction
|
||||
// )
|
||||
|
||||
router.post(
|
||||
"/_builder/instance/:appname/:instanceid/api/executeAction/:actionname",
|
||||
routeHandlers.executeAction
|
||||
)
|
||||
// router.post(
|
||||
// "/_builder/instance/:appname/:instanceid/api/executeAction/:actionname",
|
||||
// routeHandlers.executeAction
|
||||
// )
|
||||
|
||||
// router.post("/:appname/api/createUser", routeHandlers.createUser)
|
||||
|
||||
|
|
|
@ -2,21 +2,20 @@ const Router = require("@koa/router");
|
|||
const send = require("koa-send")
|
||||
const StatusCodes = require("../../utilities/statusCodes")
|
||||
const {
|
||||
getComponentDefinitions,
|
||||
componentLibraryInfo,
|
||||
} = require("../../utilities/builder")
|
||||
|
||||
|
||||
const router = Router();
|
||||
|
||||
router.get("/_builder/:appname/componentlibrary", async ctx => {
|
||||
const info = await componentLibraryInfo(
|
||||
ctx.config,
|
||||
ctx.params.appname,
|
||||
ctx.query.lib
|
||||
)
|
||||
await send(ctx, info.components._lib || "index.js", { root: info.libDir })
|
||||
})
|
||||
// router.get("/_builder/:appname/componentlibrary", async ctx => {
|
||||
// const info = await componentLibraryInfo(
|
||||
// ctx.config,
|
||||
// ctx.params.appname,
|
||||
// ctx.query.lib
|
||||
// )
|
||||
// await send(ctx, info.components._lib || "index.js", { root: info.libDir })
|
||||
// })
|
||||
|
||||
// router.get("/_builder/api/:appname/components", async ctx => {
|
||||
// try {
|
||||
|
@ -35,14 +34,14 @@ router.get("/_builder/:appname/componentlibrary", async ctx => {
|
|||
// }
|
||||
// })
|
||||
|
||||
router.get("/_builder/api/:appname/componentlibrary", async ctx => {
|
||||
const info = await componentLibraryInfo(
|
||||
ctx.config,
|
||||
ctx.params.appname,
|
||||
ctx.query.lib ? decodeURI(ctx.query.lib) : ""
|
||||
)
|
||||
ctx.body = info.components
|
||||
ctx.response.status = StatusCodes.OK
|
||||
})
|
||||
// router.get("/_builder/api/:appname/componentlibrary", async ctx => {
|
||||
// const info = await componentLibraryInfo(
|
||||
// ctx.config,
|
||||
// ctx.params.appname,
|
||||
// ctx.query.lib ? decodeURI(ctx.query.lib) : ""
|
||||
// )
|
||||
// ctx.body = info.components
|
||||
// ctx.response.status = StatusCodes.OK
|
||||
// })
|
||||
|
||||
module.exports = router
|
|
@ -0,0 +1,9 @@
|
|||
const Router = require("@koa/router");
|
||||
const controller = require("../../controllers/component");
|
||||
|
||||
const router = Router();
|
||||
|
||||
router
|
||||
.get("/:clientId/:appId/components/definitions", controller.fetchAppComponentDefinitions);
|
||||
|
||||
module.exports = router;
|
|
@ -9,6 +9,7 @@ router
|
|||
await next();
|
||||
})
|
||||
.get("/_builder/:file*", controller.serveBuilder)
|
||||
.get("/:appName", controller.serveApp);
|
||||
.get("/_app/:appId", controller.serveApp)
|
||||
.get("/:appId/componentlibrary", controller.serveComponentLibrary);
|
||||
|
||||
module.exports = router;
|
|
@ -27,6 +27,7 @@
|
|||
"jsonwebtoken": "^8.5.1",
|
||||
"koa": "^2.7.0",
|
||||
"koa-body": "^4.1.0",
|
||||
"koa-compress": "^4.0.1",
|
||||
"koa-logger": "^3.2.1",
|
||||
"koa-send": "^5.0.0",
|
||||
"koa-session": "^5.12.0",
|
||||
|
@ -37,7 +38,8 @@
|
|||
"squirrelly": "^7.5.0",
|
||||
"tar-fs": "^2.0.0",
|
||||
"uuid": "^3.3.2",
|
||||
"yargs": "^13.2.4"
|
||||
"yargs": "^13.2.4",
|
||||
"zlib": "^1.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jest/test-sequencer": "^24.8.0",
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue