base analytics and settings
This commit is contained in:
commit
011aa9f2cc
|
@ -2,4 +2,5 @@ Contributors
|
||||||
===
|
===
|
||||||
|
|
||||||
* Michael Shanks - [@mjashanks](https://github.com/mjashanks)
|
* Michael Shanks - [@mjashanks](https://github.com/mjashanks)
|
||||||
* Daniel Loudon - [@danbudi](https://github.com/danbudi)
|
* Dan - [@danbudi](https://github.com/danbudi)
|
||||||
|
* Joe - [@joebudi](https://github.com/joebudi)
|
|
@ -33,6 +33,7 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@budibase/client": "*",
|
||||||
"@nx-js/compiler-util": "^2.0.0",
|
"@nx-js/compiler-util": "^2.0.0",
|
||||||
"date-fns": "^1.29.0",
|
"date-fns": "^1.29.0",
|
||||||
"feather-icons": "^4.21.0",
|
"feather-icons": "^4.21.0",
|
||||||
|
@ -42,8 +43,7 @@
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"shortid": "^2.2.8",
|
"shortid": "^2.2.8",
|
||||||
"string_decoder": "^1.2.0",
|
"string_decoder": "^1.2.0",
|
||||||
"uikit": "^3.1.7",
|
"uikit": "^3.1.7"
|
||||||
"universal-analytics": "^0.4.20"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.5.5",
|
"@babel/core": "^7.5.5",
|
||||||
|
|
|
@ -33,7 +33,7 @@ const production = !process.env.ROLLUP_WATCH;
|
||||||
const lodash_fp_exports = ["union", "reduce", "isUndefined", "cloneDeep", "split", "some", "map", "filter", "isEmpty", "countBy", "includes", "last", "find", "constant",
|
const lodash_fp_exports = ["union", "reduce", "isUndefined", "cloneDeep", "split", "some", "map", "filter", "isEmpty", "countBy", "includes", "last", "find", "constant",
|
||||||
"take", "first", "intersection", "mapValues", "isNull", "has", "isNumber", "isString", "isBoolean", "isDate", "isArray", "isObject", "clone", "values", "keyBy",
|
"take", "first", "intersection", "mapValues", "isNull", "has", "isNumber", "isString", "isBoolean", "isDate", "isArray", "isObject", "clone", "values", "keyBy",
|
||||||
"keys", "orderBy", "concat", "reverse", "difference", "merge", "flatten", "each", "pull", "join", "defaultCase", "uniqBy", "every", "uniqWith", "isFunction", "groupBy",
|
"keys", "orderBy", "concat", "reverse", "difference", "merge", "flatten", "each", "pull", "join", "defaultCase", "uniqBy", "every", "uniqWith", "isFunction", "groupBy",
|
||||||
"differenceBy", "intersectionBy", "isEqual", "max", "sortBy", "assign", "uniq", "trimChars", "trimCharsStart", "isObjectLike", "flattenDeep", "indexOf"];
|
"differenceBy", "intersectionBy", "isEqual", "max", "sortBy", "assign", "uniq", "trimChars", "trimCharsStart", "isObjectLike", "flattenDeep", "indexOf", "isPlainObject"];
|
||||||
|
|
||||||
const lodash_exports = ["toNumber", "flow", "isArray", "join", "replace", "trim", "dropRight", "takeRight", "head", "isUndefined", "isNull", "isNaN", "reduce", "isEmpty",
|
const lodash_exports = ["toNumber", "flow", "isArray", "join", "replace", "trim", "dropRight", "takeRight", "head", "isUndefined", "isNull", "isNaN", "reduce", "isEmpty",
|
||||||
"constant", "tail", "includes", "startsWith", "findIndex", "isInteger", "isDate", "isString", "split", "clone", "keys", "isFunction", "merge", "has", "isBoolean", "isNumber",
|
"constant", "tail", "includes", "startsWith", "findIndex", "isInteger", "isDate", "isString", "split", "clone", "keys", "isFunction", "merge", "has", "isBoolean", "isNumber",
|
||||||
|
@ -59,7 +59,8 @@ export default {
|
||||||
copy({
|
copy({
|
||||||
targets: [
|
targets: [
|
||||||
{ src: 'src/index.html', dest: outputpath },
|
{ src: 'src/index.html', dest: outputpath },
|
||||||
{ src: 'src/favicon.png', dest: outputpath }
|
{ src: 'src/favicon.png', dest: outputpath },
|
||||||
|
{ src: 'node_modules/@budibase/client/dist/budibase-client.esm.mjs', dest: outputpath }
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
main {
|
main {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-family: "Lato", Helvetica, Arial, sans-serif;
|
font-family: "Roboto", Helvetica, Arial, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings {
|
.settings {
|
||||||
|
|
|
@ -100,16 +100,19 @@ const getPermissionsString = perms => {
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
padding:10px;
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-button {
|
.actions-header {
|
||||||
cursor:pointer;
|
flex: 0 1 auto;
|
||||||
color: var(--white);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tr:hover .edit-button {
|
.node-view {
|
||||||
color: var(--secondary75);
|
overflow-y: auto;
|
||||||
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,8 +81,8 @@ const cancel = () => {
|
||||||
<div class=" uk-form-stacked" style="margin-bottom: 20px">
|
<div class=" uk-form-stacked" style="margin-bottom: 20px">
|
||||||
<label class="uk-form-label">Default Options</label>
|
<label class="uk-form-label">Default Options</label>
|
||||||
<div class="uk-grid-small" uk-grid>
|
<div class="uk-grid-small" uk-grid>
|
||||||
<input class="uk-input uk-width-1-4" placeholder="key" bind:value={optKey} >
|
<input class="uk-input uk-width-1-4 uk-margin-right" placeholder="key" bind:value={optKey} >
|
||||||
<input class="uk-input uk-width-1-4" placeholder="value" bind:value={optValue} >
|
<input class="uk-input uk-width-1-4 uk-margin-right" placeholder="value" bind:value={optValue} >
|
||||||
<Button color="primary-outline uk-width-1-4" on:click={addNewOption}>Add</Button>
|
<Button color="primary-outline uk-width-1-4" on:click={addNewOption}>Add</Button>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top: 10px">
|
<div style="margin-top: 10px">
|
||||||
|
@ -93,8 +93,8 @@ const cancel = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<Button color="primary" grouped on:click={save}>Save</Button>
|
<Button color="secondary" grouped on:click={save}>Save</Button>
|
||||||
<Button color="secondary" grouped on:click={cancel}>Cancel</Button>
|
<Button color="tertiary" grouped on:click={cancel}>Cancel</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,7 +104,12 @@ const cancel = () => {
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
padding: 10px;
|
padding: 2rem;
|
||||||
|
border-radius: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uk-grid-small {
|
||||||
|
padding: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-container {
|
.option-container {
|
||||||
|
|
|
@ -45,13 +45,13 @@ let actionEditingFinished = (action) => {
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h3>Actions</h3>
|
<h3 class="title">Actions</h3>
|
||||||
|
|
||||||
{#if actionsArray}
|
{#if actionsArray}
|
||||||
<table class="fields-table uk-table uk-table-small">
|
<table class="fields-table uk-table uk-table-small uk-table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Description</th>
|
<th >Description</th>
|
||||||
<th>Behaviour Source</th>
|
<th>Behaviour Source</th>
|
||||||
<th>Behaviour Name</th>
|
<th>Behaviour Name</th>
|
||||||
<th>Default Options</th>
|
<th>Default Options</th>
|
||||||
|
@ -61,10 +61,10 @@ let actionEditingFinished = (action) => {
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each actionsArray as action}
|
{#each actionsArray as action}
|
||||||
<tr>
|
<tr>
|
||||||
<td >{action.name}</td>
|
<td class="table-content">{action.name}</td>
|
||||||
<td >{action.behaviourSource}</td>
|
<td class="table-content">{action.behaviourSource}</td>
|
||||||
<td >{action.behaviourName}</td>
|
<td class="table-content">{action.behaviourName}</td>
|
||||||
<td >{@html getDefaultOptionsHtml(action.initialOptions)}</td>
|
<td class="table-content">{@html getDefaultOptionsHtml(action.initialOptions)}</td>
|
||||||
<td class="edit-button">
|
<td class="edit-button">
|
||||||
<span on:click={() => onActionEdit(action)}>{@html getIcon("edit")}</span>
|
<span on:click={() => onActionEdit(action)}>{@html getIcon("edit")}</span>
|
||||||
<span on:click={() => onActionDelete(action)}>{@html getIcon("trash")}</span>
|
<span on:click={() => onActionDelete(action)}>{@html getIcon("trash")}</span>
|
||||||
|
@ -92,12 +92,21 @@ let actionEditingFinished = (action) => {
|
||||||
|
|
||||||
.edit-button {
|
.edit-button {
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
color: var(--white);
|
color: var(--secondary25);
|
||||||
}
|
}
|
||||||
|
|
||||||
tr:hover .edit-button {
|
tr:hover .edit-button {
|
||||||
color: var(--secondary75);
|
color: var(--secondary75);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 3rem 0rem 0rem 0rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-content {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: .9rem;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -85,31 +85,45 @@ let onTriggerDelete = (trigger) => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
<div class="actions-header">
|
||||||
|
<ButtonGroup>
|
||||||
|
<Button color="secondary"
|
||||||
|
grouped
|
||||||
|
on:click={newAction}>Create New Action</Button>
|
||||||
|
<Button color="tertiary"
|
||||||
|
grouped
|
||||||
|
on:click={newTrigger}>Create New Trigger</Button>
|
||||||
|
</ButtonGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ButtonGroup>
|
<div class="node-view">
|
||||||
<Button color="secondary"
|
<Actions {editingActionIsNew} {editingAction}
|
||||||
grouped
|
{onActionEdit} {onActionDelete} {onActionSave}
|
||||||
on:click={newAction}>Create New Action</Button>
|
{onActionCancel} />
|
||||||
<Button color="secondary"
|
|
||||||
grouped
|
|
||||||
on:click={newTrigger}>Create New Trigger</Button>
|
|
||||||
</ButtonGroup>
|
|
||||||
|
|
||||||
<Actions {editingActionIsNew} {editingAction}
|
<Triggers {editingTriggerIsNew} {editingTrigger}
|
||||||
{onActionEdit} {onActionDelete} {onActionSave}
|
{onTriggerEdit} {onTriggerDelete} {onTriggerSave}
|
||||||
{onActionCancel} />
|
{onTriggerCancel} />
|
||||||
|
</div>
|
||||||
<Triggers {editingTriggerIsNew} {editingTrigger}
|
|
||||||
{onTriggerEdit} {onTriggerDelete} {onTriggerSave}
|
|
||||||
{onTriggerCancel} />
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
padding: 10px;
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
padding: 1.5rem;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.actions-header {
|
||||||
|
flex: 0 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.node-view {
|
||||||
|
overflow-y: auto;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -57,8 +57,8 @@ let save = () => {
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<ButtonGroup>
|
<ButtonGroup>
|
||||||
<Button grouped on:click={save}>Save</Button>
|
<Button color="primary" grouped on:click={save}>Save</Button>
|
||||||
<Button grouped on:click={cancel}>Cancel</Button>
|
<Button color="tertiary" grouped on:click={cancel}>Cancel</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,10 +27,10 @@ let triggerEditingFinished = (trigger) => {
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h3>Triggers</h3>
|
<h3 class="title">Triggers</h3>
|
||||||
|
|
||||||
{#if $store.triggers}
|
{#if $store.triggers}
|
||||||
<table class="fields-table uk-table uk-table-small">
|
<table class="fields-table uk-table uk-table-small uk-table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Event</th>
|
<th>Event</th>
|
||||||
|
@ -43,10 +43,10 @@ let triggerEditingFinished = (trigger) => {
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each $store.triggers as trigger}
|
{#each $store.triggers as trigger}
|
||||||
<tr>
|
<tr>
|
||||||
<td >{trigger.eventName}</td>
|
<td class="table-content">{trigger.eventName}</td>
|
||||||
<td >{trigger.actionName}</td>
|
<td class="table-content">{trigger.actionName}</td>
|
||||||
<td >{trigger.condition}</td>
|
<td class="table-content">{trigger.condition}</td>
|
||||||
<td >{trigger.optionsCreator}</td>
|
<td class="table-content">{trigger.optionsCreator}</td>
|
||||||
<td class="edit-button">
|
<td class="edit-button">
|
||||||
<span on:click={() => onTriggerEdit(trigger)}>{@html getIcon("edit")}</span>
|
<span on:click={() => onTriggerEdit(trigger)}>{@html getIcon("edit")}</span>
|
||||||
<span on:click={() => onTriggerDelete(trigger)}>{@html getIcon("trash")}</span>
|
<span on:click={() => onTriggerDelete(trigger)}>{@html getIcon("trash")}</span>
|
||||||
|
@ -74,7 +74,17 @@ let triggerEditingFinished = (trigger) => {
|
||||||
|
|
||||||
.edit-button {
|
.edit-button {
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
color: var(--white);
|
color: var(--secondary25);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 3rem 0rem 0rem 0rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table-content {
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: .9rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr:hover .edit-button {
|
tr:hover .edit-button {
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,3 @@
|
||||||
import { isUndefined } from "lodash/fp";
|
|
||||||
|
|
||||||
const apiCall = (method) => (url, body) =>
|
const apiCall = (method) => (url, body) =>
|
||||||
fetch(url, {
|
fetch(url, {
|
||||||
method: method,
|
method: method,
|
||||||
|
|
|
@ -11,6 +11,17 @@ export const loadLibs = async (appName, appPackage) => {
|
||||||
return allLibraries;
|
return allLibraries;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const loadLibUrls = (appName, appPackage) => {
|
||||||
|
|
||||||
|
const allLibraries = [];
|
||||||
|
for(let lib of appPackage.pages.componentLibraries) {
|
||||||
|
const libUrl = makeLibraryUrl(appName, lib);
|
||||||
|
allLibraries.push({libName:lib, importPath:libUrl});
|
||||||
|
}
|
||||||
|
|
||||||
|
return allLibraries;
|
||||||
|
}
|
||||||
|
|
||||||
export const loadLib = async (appName, lib, allLibs) => {
|
export const loadLib = async (appName, lib, allLibs) => {
|
||||||
allLibs[lib] = await import(makeLibraryUrl(appName, lib));
|
allLibs[lib] = await import(makeLibraryUrl(appName, lib));
|
||||||
return allLibs;
|
return allLibs;
|
||||||
|
|
|
@ -1,26 +1,14 @@
|
||||||
import {
|
import {
|
||||||
hierarchy as hierarchyFunctions,
|
hierarchy as hierarchyFunctions,
|
||||||
common
|
|
||||||
} from "../../../core/src";
|
} from "../../../core/src";
|
||||||
import {
|
import {
|
||||||
filter,
|
filter, cloneDeep, sortBy,
|
||||||
cloneDeep,
|
map, last, keys, concat,
|
||||||
sortBy,
|
find, isEmpty, reduce
|
||||||
map,
|
|
||||||
last,
|
|
||||||
keys,
|
|
||||||
concat,
|
|
||||||
find,
|
|
||||||
isEmpty,
|
|
||||||
groupBy,
|
|
||||||
reduce
|
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import {
|
import {
|
||||||
pipe,
|
pipe, getNode, validate,
|
||||||
getNode,
|
constructHierarchy, templateApi
|
||||||
validate,
|
|
||||||
constructHierarchy,
|
|
||||||
templateApi
|
|
||||||
} from "../common/core";
|
} from "../common/core";
|
||||||
import {writable} from "svelte/store";
|
import {writable} from "svelte/store";
|
||||||
import { defaultPagesObject } from "../userInterface/pagesParsing/defaultPagesObject"
|
import { defaultPagesObject } from "../userInterface/pagesParsing/defaultPagesObject"
|
||||||
|
@ -28,10 +16,9 @@ import { buildPropsHierarchy } from "../userInterface/pagesParsing/buildPropsHie
|
||||||
import api from "./api";
|
import api from "./api";
|
||||||
import { isRootComponent } from "../userInterface/pagesParsing/searchComponents";
|
import { isRootComponent } from "../userInterface/pagesParsing/searchComponents";
|
||||||
import {
|
import {
|
||||||
getComponentInfo,
|
getComponentInfo, getNewComponentInfo
|
||||||
getNewComponentInfo
|
|
||||||
} from "../userInterface/pagesParsing/createProps";
|
} from "../userInterface/pagesParsing/createProps";
|
||||||
import { loadLibs } from "./loadComponentLibraries";
|
import { loadLibs, loadLibUrls } from "./loadComponentLibraries";
|
||||||
|
|
||||||
let appname = "";
|
let appname = "";
|
||||||
|
|
||||||
|
@ -121,6 +108,7 @@ const initialise = (store, initial) => async () => {
|
||||||
.then(r => r.json());
|
.then(r => r.json());
|
||||||
|
|
||||||
initial.libraries = await loadLibs(appname, pkg);
|
initial.libraries = await loadLibs(appname, pkg);
|
||||||
|
initial.loadLibraryUrls = () => loadLibUrls(appname, pkg);
|
||||||
initial.appname = appname;
|
initial.appname = appname;
|
||||||
initial.pages = pkg.pages;
|
initial.pages = pkg.pages;
|
||||||
initial.hasAppPackage = true;
|
initial.hasAppPackage = true;
|
||||||
|
|
|
@ -27,8 +27,10 @@ $: borderClass = grouped
|
||||||
|
|
||||||
button {
|
button {
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
padding: 7px 15px;
|
padding: 7.5px 15px;
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
|
margin:5px;
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---- PRIMARY ----*/
|
/* ---- PRIMARY ----*/
|
||||||
|
|
|
@ -11,11 +11,14 @@ export let label = "";
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
padding:3px;
|
padding:3px;
|
||||||
background: var(--darkslate);
|
margin-top:5px;
|
||||||
|
margin-bottom:10px;
|
||||||
|
background: var(--lightslate);
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
font-family: 'Courier New', Courier, monospace;
|
font-family: 'Courier New', Courier, monospace;
|
||||||
width:95%;
|
width:95%;
|
||||||
height:100px;
|
height:100px;
|
||||||
|
border-radius: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -46,7 +46,7 @@ let isDroppedDown = false;
|
||||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
border-style:solid;
|
border-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-color: var(--secondary10);
|
border-color: var(--secondary10);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,4 +34,8 @@ $: {
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
|
.uk-modal-dialog {
|
||||||
|
border-radius: .3rem;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -0,0 +1,25 @@
|
||||||
|
import {
|
||||||
|
isString
|
||||||
|
} from "lodash/fp";
|
||||||
|
|
||||||
|
export const BB_STATE_BINDINGPATH = "##bbstate";
|
||||||
|
export const BB_STATE_FALLBACK = "##bbstatefallback";
|
||||||
|
|
||||||
|
export const isBinding = value =>
|
||||||
|
!isString(value)
|
||||||
|
&& value
|
||||||
|
&& isString(value[BB_STATE_BINDINGPATH])
|
||||||
|
&& value[BB_STATE_BINDINGPATH].length > 0;
|
||||||
|
|
||||||
|
export const setBinding = ({path, fallback}, binding={} ) => {
|
||||||
|
if(isNonEmptyString(path)) binding[BB_STATE_BINDINGPATH] = path;
|
||||||
|
if(isNonEmptyString(fallback)) binding[BB_STATE_FALLBACK] = fallback;
|
||||||
|
return binding
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getBinding = binding => ({
|
||||||
|
path: binding[BB_STATE_BINDINGPATH] || "",
|
||||||
|
fallback: binding[BB_STATE_FALLBACK] || ""
|
||||||
|
});
|
||||||
|
|
||||||
|
const isNonEmptyString = s => isString(s) && s.length > 0;
|
|
@ -0,0 +1 @@
|
||||||
|
export const EVENT_TYPE_MEMBER_NAME = "##eventHandlerType";
|
|
@ -1,3 +1,3 @@
|
||||||
import feather from "feather-icons";
|
import feather from "feather-icons";
|
||||||
const getIcon = (icon, size) => feather.icons[icon].toSvg({height:size||"24", width:size||"24"});
|
const getIcon = (icon, size) => feather.icons[icon].toSvg({height:size||"16", width:size||"16"});
|
||||||
export default getIcon;
|
export default getIcon;
|
|
@ -30,7 +30,7 @@ const deleteCurrentNode = () => {
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{#if !$store.currentNodeIsNew}
|
{#if !$store.currentNodeIsNew}
|
||||||
<Button color="secondary" grouped on:click={openConfirmDelete}>
|
<Button color="tertiary" grouped on:click={openConfirmDelete}>
|
||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -54,9 +54,9 @@ const deleteCurrentNode = () => {
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
padding:5px;
|
padding: 1.5rem;
|
||||||
top:0;
|
width: 100%;
|
||||||
width:100%;
|
align-items: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -109,7 +109,7 @@ const save = () => {
|
||||||
|
|
||||||
<ButtonGroup style="float: right;">
|
<ButtonGroup style="float: right;">
|
||||||
<Button color="primary" grouped on:click={save}>Save</Button>
|
<Button color="primary" grouped on:click={save}>Save</Button>
|
||||||
<Button color="secondary" grouped on:click={() => onFinished(false)}>Cancel</Button>
|
<Button color="tertiary" grouped on:click={() => onFinished(false)}>Cancel</Button>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -24,13 +24,13 @@ export let node;
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 13pt;
|
font-size: 1rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font: var(--bodytext);
|
font: var(--fontblack);
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
|
|
|
@ -85,18 +85,21 @@ let getTypeOptions = typeOptions =>
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
|
||||||
<form class="uk-form-horizontal">
|
<form class="uk-form-horizontal">
|
||||||
|
<h3 class="settings-title">
|
||||||
|
Settings
|
||||||
|
</h3>
|
||||||
|
|
||||||
<Textbox label="Name" bind:text={record.name} />
|
<Textbox label="Name:" bind:text={record.name} />
|
||||||
<div>{record.nodeKey()}</div>
|
|
||||||
{#if !record.isSingle}
|
{#if !record.isSingle}
|
||||||
<Textbox label="Collection Name" bind:text={record.collectionName} />
|
<Textbox label="Collection Name:" bind:text={record.collectionName} />
|
||||||
<Textbox label="Shard Factor" bind:text={record.allidsShardFactor} />
|
<Textbox label="Shard Factor:" bind:text={record.allidsShardFactor} />
|
||||||
{/if}
|
{/if}
|
||||||
|
<div class="recordkey">{record.nodeKey()}</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
<h4>
|
<h3 class="title">
|
||||||
Fields <span class="add-field-button" on:click={newField}>{@html getIcon("plus")}</span>
|
Fields <span class="add-field-button" on:click={newField}>{@html getIcon("plus")}</span>
|
||||||
</h4>
|
</h3>
|
||||||
|
|
||||||
{#if record.fields.length > 0}
|
{#if record.fields.length > 0}
|
||||||
<table class="fields-table uk-table">
|
<table class="fields-table uk-table">
|
||||||
|
@ -138,9 +141,9 @@ let getTypeOptions = typeOptions =>
|
||||||
</Modal>
|
</Modal>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<h4>
|
<h3 class="title">
|
||||||
Indexes
|
Indexes
|
||||||
</h4>
|
</h3>
|
||||||
|
|
||||||
{#each record.indexes as index}
|
{#each record.indexes as index}
|
||||||
<div class="index-container">
|
<div class="index-container">
|
||||||
|
@ -166,7 +169,9 @@ let getTypeOptions = typeOptions =>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
(no indexes added)
|
<div class="no-indexes">
|
||||||
|
No indexes added.
|
||||||
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -176,25 +181,40 @@ let getTypeOptions = typeOptions =>
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 15px;
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-title {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
margin: 3rem 0rem 0rem 0rem;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recordkey {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--primary100);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fields-table {
|
.fields-table {
|
||||||
margin:10px;
|
margin: 1rem 1rem 0rem 0rem;
|
||||||
border-collapse:collapse;
|
border-collapse:collapse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add-field-button {
|
.add-field-button {
|
||||||
margin-left:15px;
|
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-button {
|
.edit-button {
|
||||||
cursor:pointer;
|
cursor:pointer;
|
||||||
color: var(--white);
|
color: var(--secondary25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-button:hover {
|
.edit-button:hover {
|
||||||
|
cursor:pointer;
|
||||||
color: var(--secondary75);
|
color: var(--secondary75);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +223,7 @@ th {
|
||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
padding: 5px 30px 5px 0px;
|
padding: 1rem 5rem 1rem 0rem;
|
||||||
margin:0;
|
margin:0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -255,7 +275,12 @@ tbody > tr:hover .edit-button {
|
||||||
}
|
}
|
||||||
|
|
||||||
.index-field-row {
|
.index-field-row {
|
||||||
margin-top: 7px;
|
margin: 1rem 0rem 0rem 0rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.no-indexes {
|
||||||
|
margin: 1rem 0rem 0rem 0rem;
|
||||||
|
font-family: var(--fontnormal);
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.5 KiB |
|
@ -1,61 +1,47 @@
|
||||||
/* latin-ext */
|
/* latin-ext */
|
||||||
|
/* roboto-regular - latin-ext_latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Lato';
|
font-family: 'Roboto';
|
||||||
font-weight: 400;
|
font-style: normal;
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin-ext.woff2) format('woff2');
|
font-weight: 400;
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
src: local('Roboto'), local('Roboto-Regular'),
|
||||||
|
url('/_builder/assets/roboto-v20-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
|
url('/_builder/assets/roboto-v20-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
}
|
}
|
||||||
/* latin */
|
/* roboto-300 - latin-ext_latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Lato';
|
font-family: 'Roboto';
|
||||||
font-weight: 400;
|
font-style: normal;
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin.woff2) format('woff2');
|
font-weight: 300;
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
src: local('Roboto Light'), local('Roboto-Light'),
|
||||||
}
|
url('/_builder/assets/roboto-v20-latin-ext_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
|
url('/_builder/assets/roboto-v20-latin-ext_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
|
}
|
||||||
/* Black latin-ext */
|
/* roboto-500 - latin-ext_latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Lato Black';
|
font-family: 'Roboto';
|
||||||
font-weight: 900;
|
font-style: normal;
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin-ext.woff2) format('woff2');
|
font-weight: 500;
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
src: local('Roboto Medium'), local('Roboto-Medium'),
|
||||||
}
|
url('/_builder/assets/roboto-v20-latin-ext_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
/* Black latin */
|
url('/_builder/assets/roboto-v20-latin-ext_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
@font-face {
|
}
|
||||||
font-family: 'Lato Black';
|
/* roboto-700 - latin-ext_latin */
|
||||||
font-weight: 900;
|
@font-face {
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin.woff2) format('woff2');
|
font-family: 'Roboto';
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
font-style: normal;
|
||||||
}
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'),
|
||||||
/* Bold latin-ext */
|
url('/_builder/assets/roboto-v20-latin-ext_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
@font-face {
|
url('/_builder/assets/roboto-v20-latin-ext_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
font-family: 'Lato Bold';
|
}
|
||||||
font-weight: 700;
|
/* roboto-900 - latin-ext_latin */
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin-ext.woff2) format('woff2');
|
@font-face {
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
font-family: 'Roboto';
|
||||||
}
|
font-style: normal;
|
||||||
/* Bold latin */
|
font-weight: 900;
|
||||||
@font-face {
|
src: local('Roboto Black'), local('Roboto-Black'),
|
||||||
font-family: 'Lato Bold';
|
url('/_builder/assets/roboto-v20-latin-ext_latin-900.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
font-weight: 700;
|
url('/_builder/assets/roboto-v20-latin-ext_latin-900.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin.woff2) format('woff2');
|
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Semi Bold latin-ext */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lato Semi Bold';
|
|
||||||
font-weight: 600;
|
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin-ext.woff2) format('woff2');
|
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
||||||
}
|
|
||||||
/* Semi Bold latin */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lato Semi Bold';
|
|
||||||
font-weight: 600;
|
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin.woff2) format('woff2');
|
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
--primary50: #454CA080;
|
--primary50: #454CA080;
|
||||||
--primary25: #454CA040;
|
--primary25: #454CA040;
|
||||||
--primary10: #454CA01A;
|
--primary10: #454CA01A;
|
||||||
|
--primary5: #454ca00c;
|
||||||
--primarydark: #3F448A;
|
--primarydark: #3F448A;
|
||||||
|
|
||||||
--secondary100: #162B4DFF;
|
--secondary100: #162B4DFF;
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
--secondary50: #162B4D80;
|
--secondary50: #162B4D80;
|
||||||
--secondary25: #162B4D40;
|
--secondary25: #162B4D40;
|
||||||
--secondary10: #162B4D1A;
|
--secondary10: #162B4D1A;
|
||||||
|
--secondary5: rgba(22, 43, 77, 0.068);
|
||||||
--secondarydark: #3F448A;
|
--secondarydark: #3F448A;
|
||||||
|
|
||||||
--tertiary: #F2F5F7;
|
--tertiary: #F2F5F7;
|
||||||
|
@ -30,17 +32,18 @@
|
||||||
--deletiondark: #CF4046;
|
--deletiondark: #CF4046;
|
||||||
|
|
||||||
--white: #FFFFFF;
|
--white: #FFFFFF;
|
||||||
--darkslate: #5C6B82;
|
--darkslate: #1a202c;
|
||||||
--slate: #8B95A6;
|
--slate: #a0aec0;
|
||||||
--lightslate: rgb(203, 212, 228);
|
--lightslate: #f7fafc;
|
||||||
|
|
||||||
--borderradius: 2px;
|
--borderradius: 2px;
|
||||||
--borderradiusall: 2px 2px 2px 2px;
|
--borderradiusall: 2px 2px 2px 2px;
|
||||||
|
|
||||||
--fontblack: "Lato Black";
|
--fontblack: "Roboto Black";
|
||||||
--fontbold: "Lato Bold";
|
--fontbold: "Roboto Bold";
|
||||||
--fontsemibold: "Lato Semi Bold";
|
--fontsemibold: "Roboto Medium";
|
||||||
--fontnormal: "Lato";
|
--fontnormal: "Roboto";
|
||||||
|
--fontlight: "Roboto Light";
|
||||||
|
|
||||||
--bodytext: var(--fontnormal) "regular" var(--secondary100) 16pt;
|
--bodytext: var(--fontnormal) "regular" var(--secondary100) 16pt;
|
||||||
--bigbodytext: var(--fontnormal) "regular" var(--secondary100) 20pt;
|
--bigbodytext: var(--fontnormal) "regular" var(--secondary100) 20pt;
|
||||||
|
@ -79,7 +82,7 @@ h3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
font-family: var(--fontsemibold);
|
font-family: var(--fontbold);
|
||||||
font-size: 18pt;
|
font-size: 18pt;
|
||||||
color: var(--secondary100);
|
color: var(--secondary100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
import App from "./App.svelte";
|
import App from "./App.svelte";
|
||||||
import "./global.css";
|
import "./global.css";
|
||||||
import "./fonts.css";
|
import "./fonts.css";
|
||||||
import "/assets/lato-latin-ext.woff2";
|
import "/assets/roboto-v20-latin-ext_latin-300";
|
||||||
import "/assets/lato-latin.woff2";
|
import "/assets/roboto-v20-latin-ext_latin-400";
|
||||||
|
import "/assets/roboto-v20-latin-ext_latin-500";
|
||||||
|
import "/assets/roboto-v20-latin-ext_latin-700";
|
||||||
|
import "/assets/roboto-v20-latin-ext_latin-900";
|
||||||
import "/assets/budibase-logo.png";
|
import "/assets/budibase-logo.png";
|
||||||
import "/assets/budibase-logo-only.png";
|
import "/assets/budibase-logo-only.png";
|
||||||
import "uikit/dist/css/uikit.min.css";
|
import "uikit/dist/css/uikit.min.css";
|
||||||
|
|
|
@ -73,7 +73,7 @@ store.subscribe(db => {
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: var(--primary10);
|
background-color: var(--secondary5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.items-root {
|
.items-root {
|
||||||
|
@ -90,8 +90,8 @@ store.subscribe(db => {
|
||||||
|
|
||||||
|
|
||||||
.hierarchy-title-row {
|
.hierarchy-title-row {
|
||||||
padding: 15px 7px;
|
padding: 2rem 1rem 0rem 1rem;
|
||||||
font-size: 12pt;
|
font-size: 10pt;
|
||||||
display: flex;
|
display: flex;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,15 +43,14 @@ store.subscribe(s => {
|
||||||
|
|
||||||
.root {
|
.root {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 12pt;
|
font-size: 10pt;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
padding-top: 5px;
|
padding-top: .5rem;
|
||||||
padding-right: 5px;
|
padding-right: .5rem;
|
||||||
padding-bottom: 5px;
|
|
||||||
color: var(--secondary100);
|
color: var(--secondary100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ const setActive = () =>
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
padding: 7px;
|
padding: 1rem 1rem 0rem 1rem;
|
||||||
font-size: 12pt;
|
font-size: 10pt;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
|
|
|
@ -10,7 +10,7 @@ import {
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import { fade, slide } from 'svelte/transition';
|
import { fade, slide } from 'svelte/transition';
|
||||||
|
|
||||||
export let propertyName = "";
|
export let title = "";
|
||||||
export let onGoBack = () => {};
|
export let onGoBack = () => {};
|
||||||
export let instanceProps = {};
|
export let instanceProps = {};
|
||||||
export let onPropsChanged = () => {};
|
export let onPropsChanged = () => {};
|
||||||
|
@ -18,6 +18,9 @@ export let onPropsChanged = () => {};
|
||||||
|
|
||||||
let editingSubComponentName;
|
let editingSubComponentName;
|
||||||
let editingSubComponentProps;
|
let editingSubComponentProps;
|
||||||
|
let editingSubComponentArrayIndex;
|
||||||
|
let editingSubComponentArrayPropName;
|
||||||
|
let editingSubComponentTitle;
|
||||||
let allComponents;
|
let allComponents;
|
||||||
|
|
||||||
store.subscribe(s => {
|
store.subscribe(s => {
|
||||||
|
@ -33,18 +36,28 @@ const onSubComponentGoBack = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const onEditComponentProp = (propName, arrayIndex, arrayPropName) => {
|
const onEditComponentProp = (propName, arrayIndex, arrayPropName) => {
|
||||||
editingSubComponentName = isUndefined(arrayIndex)
|
editingSubComponentName = propName;
|
||||||
|
editingSubComponentTitle = isUndefined(arrayIndex)
|
||||||
? propName
|
? propName
|
||||||
: `${propName}[${arrayIndex}].${arrayPropName}`;
|
: `${propName}[${arrayIndex}].${arrayPropName}`;
|
||||||
editingSubComponentProps = isUndefined(arrayIndex)
|
editingSubComponentProps = isUndefined(arrayIndex)
|
||||||
? instanceProps[propName]
|
? instanceProps[propName]
|
||||||
: instanceProps[propName][arrayIndex][arrayPropName];
|
: instanceProps[propName][arrayIndex][arrayPropName];
|
||||||
|
editingSubComponentArrayIndex = arrayIndex;
|
||||||
|
editingSubComponentArrayPropName = arrayPropName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const onSubComponentPropsChanged = (subProps) => {
|
const onSubComponentPropsChanged = (subProps) => {
|
||||||
const newProps = cloneDeep(instanceProps);
|
const newProps = cloneDeep(instanceProps);
|
||||||
newProps[editingSubComponentName] = subProps;
|
if(isUndefined(editingSubComponentArrayIndex)) {
|
||||||
|
newProps[editingSubComponentName] = subProps;
|
||||||
|
} else {
|
||||||
|
newProps[editingSubComponentName]
|
||||||
|
[editingSubComponentArrayIndex]
|
||||||
|
[editingSubComponentArrayPropName] = subProps;
|
||||||
|
}
|
||||||
|
|
||||||
instanceProps = newProps;
|
instanceProps = newProps;
|
||||||
onPropsChanged(newProps);
|
onPropsChanged(newProps);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +75,7 @@ const propsChanged = newProps => {
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<IconButton icon="chevron-left"
|
<IconButton icon="chevron-left"
|
||||||
on:click={onGoBack}/>
|
on:click={onGoBack}/>
|
||||||
<span>{propertyName}</span>
|
<span>{title}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if editingSubComponentName}
|
{#if editingSubComponentName}
|
||||||
|
@ -71,7 +84,7 @@ const propsChanged = newProps => {
|
||||||
<svelte:self onPropsChanged={onSubComponentPropsChanged}
|
<svelte:self onPropsChanged={onSubComponentPropsChanged}
|
||||||
onGoBack={onSubComponentGoBack}
|
onGoBack={onSubComponentGoBack}
|
||||||
instanceProps={editingSubComponentProps}
|
instanceProps={editingSubComponentProps}
|
||||||
propertyName={editingSubComponentName} />
|
title={editingSubComponentTitle} />
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<PropsView {instanceProps}
|
<PropsView {instanceProps}
|
||||||
|
|
|
@ -18,7 +18,6 @@ export let props = emptyProps();
|
||||||
export let onValueChanged = () => {};
|
export let onValueChanged = () => {};
|
||||||
export let onComponentChosen = () => {};
|
export let onComponentChosen = () => {};
|
||||||
export let onEdit = () => {};
|
export let onEdit = () => {};
|
||||||
export let label = "";
|
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
|
|
||||||
const CHOOSE_COMPONENT = "choose_component";
|
const CHOOSE_COMPONENT = "choose_component";
|
||||||
|
@ -70,7 +69,6 @@ const confirmClearComponent = () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<label class="uk-form-label">{label}</label>
|
|
||||||
<div class="root uk-form-controls">
|
<div class="root uk-form-controls">
|
||||||
<div class:selectedname={componentSelected}>
|
<div class:selectedname={componentSelected}>
|
||||||
{componentSelected ? shortName : "(none)"}
|
{componentSelected ? shortName : "(none)"}
|
||||||
|
|
|
@ -2,79 +2,47 @@
|
||||||
import { store } from "../builderStore";
|
import { store } from "../builderStore";
|
||||||
import { makeLibraryUrl } from "../builderStore/loadComponentLibraries";
|
import { makeLibraryUrl } from "../builderStore/loadComponentLibraries";
|
||||||
import {
|
import {
|
||||||
last,
|
last, split, map, join
|
||||||
split,
|
|
||||||
map,
|
|
||||||
join
|
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import { pipe } from "../common/core";
|
import { pipe } from "../common/core";
|
||||||
import { splitName } from "./pagesParsing/splitRootComponentName"
|
import { splitName } from "./pagesParsing/splitRootComponentName"
|
||||||
import { afterUpdate } from 'svelte';
|
import { afterUpdate } from 'svelte';
|
||||||
import { getRootComponent } from "./pagesParsing/getRootComponent";
|
import { getRootComponent } from "./pagesParsing/getRootComponent";
|
||||||
|
import { buildPropsHierarchy } from "./pagesParsing/buildPropsHierarchy";
|
||||||
|
|
||||||
if(!window.budibaseIframeConnector) {
|
|
||||||
window.budibaseIframeConnector = {
|
|
||||||
initialiseComponent(props, htmlElement) {
|
|
||||||
const rootComponent = getRootComponent(
|
|
||||||
props._component, allComponents);
|
|
||||||
|
|
||||||
const {componentName, libName} = splitName(
|
|
||||||
rootComponent.name);
|
|
||||||
|
|
||||||
new (libraries[libName][componentName])({
|
|
||||||
target: htmlElement,
|
|
||||||
props: {...props, _app: window.budibaseIframeConnector}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let component;
|
let component;
|
||||||
let stylesheetLinks = "";
|
let stylesheetLinks = "";
|
||||||
let componentHtml = "";
|
|
||||||
let props;
|
|
||||||
let componentLibraryUrl = "";
|
|
||||||
let rootComponentName = "";
|
let rootComponentName = "";
|
||||||
let iframe;
|
|
||||||
let libraries;
|
let libraries;
|
||||||
let allComponents;
|
let allComponents;
|
||||||
|
let appDefinition = {};
|
||||||
|
|
||||||
store.subscribe(s => {
|
store.subscribe(s => {
|
||||||
const {componentName, libName} = splitName(
|
const {componentName, libName} = splitName(
|
||||||
s.currentComponentInfo.rootComponent.name);
|
s.currentComponentInfo.rootComponent.name);
|
||||||
|
|
||||||
rootComponentName = componentName;
|
rootComponentName = componentName;
|
||||||
props = s.currentComponentInfo.fullProps;
|
|
||||||
component = s.libraries[libName][componentName];
|
component = s.libraries[libName][componentName];
|
||||||
stylesheetLinks = pipe(s.pages.stylesheets, [
|
stylesheetLinks = pipe(s.pages.stylesheets, [
|
||||||
map(s => `<link rel="stylesheet" href="${s}"/>`),
|
map(s => `<link rel="stylesheet" href="${s}"/>`),
|
||||||
join("\n")
|
join("\n")
|
||||||
]);
|
]);
|
||||||
componentLibraryUrl = makeLibraryUrl(s.appname, libName);
|
appDefinition = {
|
||||||
|
componentLibraries: s.loadLibraryUrls(),
|
||||||
|
props: buildPropsHierarchy(s.allComponents, s.currentFrontEndItem)
|
||||||
|
};
|
||||||
libraries = s.libraries;
|
libraries = s.libraries;
|
||||||
allComponents = s.allComponents;
|
allComponents = s.allComponents;
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
|
||||||
afterUpdate(() => {
|
|
||||||
if(iframe) iframeLoaded();
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
const iframeLoaded = () => {
|
|
||||||
setTimeout(() => {
|
|
||||||
iframe.style.height = (iframe.contentWindow.document.body.scrollHeight + 1).toString() + "px";
|
|
||||||
iframe.style.width = (iframe.contentWindow.document.body.scrollWidth + 1).toString() + "px";
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="component-preview" >
|
<div class="component-preview" >
|
||||||
<div class="component-container">
|
<div class="component-container">
|
||||||
<iframe bind:this={iframe}
|
<iframe style="height: 100%; width: 100%"
|
||||||
on:load={iframeLoaded}
|
|
||||||
title="componentPreview"
|
title="componentPreview"
|
||||||
srcdoc={
|
srcdoc={
|
||||||
`<html>
|
`<html>
|
||||||
|
@ -82,16 +50,11 @@ const iframeLoaded = () => {
|
||||||
<head>
|
<head>
|
||||||
${stylesheetLinks}
|
${stylesheetLinks}
|
||||||
<script>
|
<script>
|
||||||
|
window["##BUDIBASE_APPDEFINITION##"] = ${JSON.stringify(appDefinition)};
|
||||||
import('${componentLibraryUrl}')
|
import('./budibase-client.esm.mjs')
|
||||||
.then(module => {
|
.then(module => {
|
||||||
const componentClass = module['${rootComponentName}'];
|
module.loadBudibase();
|
||||||
const instance = new componentClass({
|
|
||||||
target: document.body,
|
|
||||||
props: {...${JSON.stringify(props)}, _app: window.parent.budibaseIframeConnector}
|
|
||||||
}) ;
|
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
|
@ -36,6 +36,10 @@ let modalElement
|
||||||
let propsValidationErrors = [];
|
let propsValidationErrors = [];
|
||||||
let editingComponentInstance;
|
let editingComponentInstance;
|
||||||
let editingComponentInstancePropName="";
|
let editingComponentInstancePropName="";
|
||||||
|
let editingComponentArrayIndex;
|
||||||
|
let editingComponentArrayPropName;
|
||||||
|
let editingComponentInstanceTitle;
|
||||||
|
|
||||||
let allComponents;
|
let allComponents;
|
||||||
|
|
||||||
$: shortName = last(name.split("/"));
|
$: shortName = last(name.split("/"));
|
||||||
|
@ -116,9 +120,13 @@ const onEditComponentProp = (propName, arrayIndex, arrayPropName) => {
|
||||||
editingComponentInstance = isUndefined(arrayIndex)
|
editingComponentInstance = isUndefined(arrayIndex)
|
||||||
? component.props[propName]
|
? component.props[propName]
|
||||||
: component.props[propName][arrayIndex][arrayPropName];
|
: component.props[propName][arrayIndex][arrayPropName];
|
||||||
editingComponentInstancePropName = isUndefined(arrayIndex)
|
editingComponentInstancePropName = propName;
|
||||||
|
editingComponentInstanceTitle = isUndefined(arrayIndex)
|
||||||
? propName
|
? propName
|
||||||
: `${propName}[${arrayIndex}].${arrayPropName}`;
|
: `${propName}[${arrayIndex}].${arrayPropName}`;
|
||||||
|
|
||||||
|
editingComponentArrayIndex = arrayIndex;
|
||||||
|
editingComponentArrayPropName = arrayPropName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentInstanceCancelEdit = () => {
|
const componentInstanceCancelEdit = () => {
|
||||||
|
@ -127,8 +135,15 @@ const componentInstanceCancelEdit = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const componentInstancePropsChanged = (instanceProps) => {
|
const componentInstancePropsChanged = (instanceProps) => {
|
||||||
updateComponent(newComponent =>
|
updateComponent(newComponent => {
|
||||||
newComponent.props[editingComponentInstancePropName] = instanceProps);
|
if(isUndefined(editingComponentArrayIndex)) {
|
||||||
|
newComponent.props[editingComponentInstancePropName] = instanceProps;
|
||||||
|
} else {
|
||||||
|
newComponent.props[editingComponentInstancePropName]
|
||||||
|
[editingComponentArrayIndex]
|
||||||
|
[editingComponentArrayPropName] = instanceProps;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -151,11 +166,11 @@ const componentInstancePropsChanged = (instanceProps) => {
|
||||||
|
|
||||||
{#if editingComponentInstance}
|
{#if editingComponentInstance}
|
||||||
<ComponentInstanceEditor onGoBack={componentInstanceCancelEdit}
|
<ComponentInstanceEditor onGoBack={componentInstanceCancelEdit}
|
||||||
propertyName={editingComponentInstancePropName}
|
title={editingComponentInstanceTitle}
|
||||||
instanceProps={editingComponentInstance}
|
instanceProps={editingComponentInstance}
|
||||||
onPropsChanged={componentInstancePropsChanged}/>
|
onPropsChanged={componentInstancePropsChanged}/>
|
||||||
{:else}
|
{:else}
|
||||||
<div>
|
<div class="component-props-container">
|
||||||
|
|
||||||
<div class="section-header padding" on:click={() => componentDetailsExpanded = !componentDetailsExpanded}>
|
<div class="section-header padding" on:click={() => componentDetailsExpanded = !componentDetailsExpanded}>
|
||||||
<span style="margin-right: 7px">Component Details</span>
|
<span style="margin-right: 7px">Component Details</span>
|
||||||
|
@ -232,6 +247,8 @@ const componentInstancePropsChanged = (instanceProps) => {
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-color: var(--lightslate);
|
border-color: var(--lightslate);
|
||||||
border-width: 0px 0px 0px 1px;
|
border-width: 0px 0px 0px 1px;
|
||||||
|
display:flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.padding {
|
.padding {
|
||||||
|
@ -267,4 +284,8 @@ const componentInstancePropsChanged = (instanceProps) => {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.component-props-container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
|
@ -0,0 +1,97 @@
|
||||||
|
<script>
|
||||||
|
import IconButton from "../common/IconButton.svelte";
|
||||||
|
import EventSelector from "./EventSelector.svelte";
|
||||||
|
import {
|
||||||
|
filter
|
||||||
|
} from "lodash/fp";
|
||||||
|
import {EVENT_TYPE_MEMBER_NAME} from "../common/eventHandlers";
|
||||||
|
export let parentProps;
|
||||||
|
export let propDef;
|
||||||
|
export let onValueChanged;
|
||||||
|
export let onValidate = () => {};
|
||||||
|
|
||||||
|
let events = [];
|
||||||
|
let elementErrors = {};
|
||||||
|
|
||||||
|
$: {
|
||||||
|
events = parentProps[propDef.____name];
|
||||||
|
}
|
||||||
|
|
||||||
|
const addHandler = () => {
|
||||||
|
const newHandler = {parameters:{}};
|
||||||
|
newHandler[EVENT_TYPE_MEMBER_NAME] = "";
|
||||||
|
events = [...events, newHandler];
|
||||||
|
onValueChanged(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEventHandlerChanged = (oldEvent) => (newEvent) => {
|
||||||
|
const indexOfOldEvent = events.indexOf(oldEvent);
|
||||||
|
const newEvents = [...events];
|
||||||
|
newEvents.splice(
|
||||||
|
events.indexOf(oldEvent),
|
||||||
|
1,
|
||||||
|
newEvent);
|
||||||
|
events = newEvents;
|
||||||
|
onValueChanged(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeHandler = (index) => () => {
|
||||||
|
events = filter(e => e !== events[index])(events);
|
||||||
|
onValueChanged(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="root">
|
||||||
|
<div class="control-container">
|
||||||
|
{#each events as ev, index}
|
||||||
|
|
||||||
|
<div class="handler-container">
|
||||||
|
<EventSelector onChanged={onEventHandlerChanged(ev)}
|
||||||
|
onRemoved={removeHandler(index)}
|
||||||
|
event={ev} />
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="separator"></div>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<div class="addelement-container"
|
||||||
|
on:click={addHandler}>
|
||||||
|
<IconButton icon="plus"
|
||||||
|
size="12"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.addelement-container {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 3px 0px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.addelement-container:hover {
|
||||||
|
background-color: var(--primary25);
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.control-container {
|
||||||
|
padding-left: 3px;
|
||||||
|
background: var(--secondary10);
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
width: 60%;
|
||||||
|
margin: 10px auto;
|
||||||
|
border-style:solid;
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
border-color: var(--primary25);
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -0,0 +1,104 @@
|
||||||
|
<script>
|
||||||
|
import IconButton from "../common/IconButton.svelte";
|
||||||
|
import StateBindingControl from "./StateBindingControl.svelte";
|
||||||
|
import {
|
||||||
|
find, map, keys, reduce
|
||||||
|
} from "lodash/fp";
|
||||||
|
import { pipe } from "../common/core";
|
||||||
|
import { EVENT_TYPE_MEMBER_NAME } from "../common/eventHandlers";
|
||||||
|
|
||||||
|
export let event;
|
||||||
|
export let onChanged;
|
||||||
|
export let onRemoved;
|
||||||
|
|
||||||
|
const events = [
|
||||||
|
{name:"", parameters: []},
|
||||||
|
{name:"Set State", parameters: ["path", "value"]},
|
||||||
|
{name:"Load Record", parameters: ["recordKey", "statePath"]},
|
||||||
|
];
|
||||||
|
|
||||||
|
let eventType;
|
||||||
|
let parameters = [];
|
||||||
|
|
||||||
|
$: {
|
||||||
|
if(event) {
|
||||||
|
eventType = event[EVENT_TYPE_MEMBER_NAME];
|
||||||
|
parameters = pipe(event.parameters, [
|
||||||
|
keys,
|
||||||
|
map(k => ({name:k, value:event.parameters[k]}))
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
eventType = "";
|
||||||
|
parameters = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventChanged = (type, parameters) => {
|
||||||
|
const paramsAsObject = reduce(
|
||||||
|
(obj, p) => {
|
||||||
|
obj[p.name] = p.value;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
, {}
|
||||||
|
)(parameters)
|
||||||
|
|
||||||
|
const ev = {};
|
||||||
|
ev[EVENT_TYPE_MEMBER_NAME]=type;
|
||||||
|
ev.parameters = paramsAsObject;
|
||||||
|
|
||||||
|
onChanged(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
const eventTypeChanged = (ev) => {
|
||||||
|
const eType = find(e => e.name === ev.target.value)(events);
|
||||||
|
const emptyParameters = map(p => ({name:p, value:""}))(eType.parameters);
|
||||||
|
eventChanged(eType.name, emptyParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onParameterChanged = index => val => {
|
||||||
|
const newparameters = [...parameters];
|
||||||
|
newparameters[index].value = val;
|
||||||
|
eventChanged(eventType, newparameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="type-selector-container">
|
||||||
|
<select class="type-selector uk-select uk-form-small " value={eventType} on:change={eventTypeChanged}>
|
||||||
|
{#each events as ev}
|
||||||
|
<option value={ev.name}>{ev.name}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<IconButton icon="trash"
|
||||||
|
size="12"
|
||||||
|
on:click={onRemoved}/>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if parameters}
|
||||||
|
{#each parameters as p, index}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{p.name}
|
||||||
|
</div>
|
||||||
|
<StateBindingControl onChanged={onParameterChanged(index)}
|
||||||
|
value={p.value} />
|
||||||
|
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.type-selector-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.type-selector {
|
||||||
|
border-color: var(--primary50);
|
||||||
|
border-radius: 2px;
|
||||||
|
width: 50px;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
|
@ -18,7 +18,6 @@ export let onEditComponentProp = () => {};
|
||||||
|
|
||||||
let value = [];
|
let value = [];
|
||||||
let elementDefinitionArray;
|
let elementDefinitionArray;
|
||||||
let label = "";
|
|
||||||
let elementErrors = {};
|
let elementErrors = {};
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
|
@ -31,7 +30,6 @@ $: {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
elementDefinitionArray = elArray;
|
elementDefinitionArray = elArray;
|
||||||
label = propDef.____name;
|
|
||||||
value = parentProps[propDef.____name];
|
value = parentProps[propDef.____name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +71,7 @@ const onEditComponent = (index, propName) => () => {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<div>
|
|
||||||
{label}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="item-container">
|
<div class="item-container">
|
||||||
{#each value as item, index}
|
{#each value as item, index}
|
||||||
|
|
|
@ -5,6 +5,8 @@ import Textbox from "../common/Textbox.svelte";
|
||||||
import Dropdown from "../common/Dropdown.svelte";
|
import Dropdown from "../common/Dropdown.svelte";
|
||||||
import ComponentPropSelector from "./ComponentPropSelector.svelte";
|
import ComponentPropSelector from "./ComponentPropSelector.svelte";
|
||||||
import PropArraySelector from "./PropArraySelector.svelte";
|
import PropArraySelector from "./PropArraySelector.svelte";
|
||||||
|
import EventListSelector from "./EventListSelector.svelte";
|
||||||
|
import StateBindingControl from "./StateBindingControl.svelte";
|
||||||
|
|
||||||
export let errors = [];
|
export let errors = [];
|
||||||
export let setProp = () => {};
|
export let setProp = () => {};
|
||||||
|
@ -26,37 +28,39 @@ const setComponentProp = (props) => {
|
||||||
|
|
||||||
<div class="root" >
|
<div class="root" >
|
||||||
|
|
||||||
|
{#if propDef.type === "component"}
|
||||||
|
|
||||||
{#if propDef.type === "bool"}
|
<div class="prop-label">{propDef.____name}</div>
|
||||||
<Checkbox label={propDef.____name}
|
|
||||||
checked={props[propDef.____name]}
|
|
||||||
on:change={ev => setProp(propDef.____name, ev.target.checked)}
|
|
||||||
hasError={fieldHasError(propDef.____name)} />
|
|
||||||
{:else if propDef.type === "options"}
|
|
||||||
<Dropdown label={propDef.____name}
|
|
||||||
selected={props[propDef.____name]}
|
|
||||||
options={propDef.options}
|
|
||||||
on:change={ev => setProp(propDef.____name, ev.target.value)}
|
|
||||||
hasError={fieldHasError(propDef.____name)}/>
|
|
||||||
{:else if propDef.type === "component"}
|
|
||||||
<ComponentPropSelector label={propDef.____name}
|
<ComponentPropSelector label={propDef.____name}
|
||||||
props={props[propDef.____name]}
|
props={props[propDef.____name]}
|
||||||
{disabled}
|
{disabled}
|
||||||
onEdit={onEditComponent}
|
onEdit={onEditComponent}
|
||||||
onComponentChosen={onEditComponent}
|
onComponentChosen={onEditComponent}
|
||||||
onValueChanged={setComponentProp}/>
|
onValueChanged={setComponentProp}/>
|
||||||
|
|
||||||
{:else if propDef.type === "array"}
|
{:else if propDef.type === "array"}
|
||||||
|
|
||||||
|
<div class="prop-label">{propDef.____name}</div>
|
||||||
<PropArraySelector parentProps={props}
|
<PropArraySelector parentProps={props}
|
||||||
{propDef}
|
{propDef}
|
||||||
onValueChanged={setComponentProp}
|
onValueChanged={setComponentProp}
|
||||||
onEditComponentProp={onEditComponent}/>
|
onEditComponentProp={onEditComponent} />
|
||||||
|
|
||||||
|
{:else if propDef.type === "event"}
|
||||||
|
|
||||||
|
<div class="prop-label">{propDef.____name}</div>
|
||||||
|
<EventListSelector parentProps={props}
|
||||||
|
{propDef}
|
||||||
|
onValueChanged={setComponentProp} />
|
||||||
|
|
||||||
{:else}
|
{:else}
|
||||||
<Textbox label={propDef.____name}
|
|
||||||
text={props[propDef.____name]}
|
<div class="prop-label">{propDef.____name}</div>
|
||||||
on:change={ev => setProp(propDef.____name, ev.target.value)}
|
<StateBindingControl value={props[propDef.____name]}
|
||||||
margin={false}
|
type={propDef.type}
|
||||||
hasError={fieldHasError(propDef.____name)}
|
options={propDef.options}
|
||||||
{disabled}/>
|
onChanged={v => setProp(propDef.____name, v)}/>
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -70,4 +74,10 @@ const setComponentProp = (props) => {
|
||||||
border-color: var(--primary25);
|
border-color: var(--primary25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prop-label {
|
||||||
|
font-size: 0.9em;
|
||||||
|
color: var(--primary100);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
|
@ -0,0 +1,155 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
isString
|
||||||
|
} from "lodash/fp";
|
||||||
|
import IconButton from "../common/IconButton.svelte";
|
||||||
|
import {
|
||||||
|
isBinding, getBinding, setBinding
|
||||||
|
} from "../common/binding";
|
||||||
|
|
||||||
|
export let value="";
|
||||||
|
export let onChanged= () => {};
|
||||||
|
export let type="";
|
||||||
|
export let options=[];
|
||||||
|
|
||||||
|
let isBound=false;
|
||||||
|
let bindingPath="";
|
||||||
|
let bindingFallbackValue="";
|
||||||
|
let isExpanded = false;
|
||||||
|
let forceIsBound = false;
|
||||||
|
|
||||||
|
$: {
|
||||||
|
isBound= forceIsBound || isBinding(value);
|
||||||
|
|
||||||
|
if(isBound) {
|
||||||
|
const binding = getBinding(value);
|
||||||
|
bindingPath= binding.path;
|
||||||
|
bindingFallbackValue= binding.fallback;
|
||||||
|
} else {
|
||||||
|
bindingPath="";
|
||||||
|
bindingFallbackValue="";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const clearBinding = () => {
|
||||||
|
forceIsBound = false;
|
||||||
|
onChanged("");
|
||||||
|
}
|
||||||
|
|
||||||
|
const bind = (path, fallback) => {
|
||||||
|
if(!path) {
|
||||||
|
clearBinding("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const binding = setBinding({path, fallback});
|
||||||
|
onChanged(binding);
|
||||||
|
}
|
||||||
|
|
||||||
|
const setBindingPath = ev => {
|
||||||
|
forceIsBound = false;
|
||||||
|
bind(ev.target.value, bindingFallbackValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
const setBindingFallback = ev => {
|
||||||
|
bind(bindingPath, ev.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const makeBinding = () => {
|
||||||
|
forceIsBound=true;
|
||||||
|
isExpanded=true;
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if isBound}
|
||||||
|
<div>
|
||||||
|
<div class="bound-header">
|
||||||
|
<div>{isExpanded ? "" : bindingPath}</div>
|
||||||
|
<IconButton icon={isExpanded ? "chevron-up" : "chevron-down"}
|
||||||
|
size="12"
|
||||||
|
on:click={() => isExpanded=!isExpanded}/>
|
||||||
|
<IconButton icon="trash"
|
||||||
|
size="12"
|
||||||
|
on:click={clearBinding}/>
|
||||||
|
</div>
|
||||||
|
{#if isExpanded}
|
||||||
|
<div>
|
||||||
|
<div class="binding-prop-label">Binding Path</div>
|
||||||
|
<input class="uk-input uk-form-small"
|
||||||
|
value={bindingPath}
|
||||||
|
on:change={setBindingPath} >
|
||||||
|
<div class="binding-prop-label">Fallback Value</div>
|
||||||
|
<input class="uk-input uk-form-small"
|
||||||
|
value={bindingFallbackValue}
|
||||||
|
on:change={setBindingFallback} >
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="unbound-container">
|
||||||
|
|
||||||
|
{#if type === "bool"}
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<IconButton icon={value == true ? "check-square" : "square"}
|
||||||
|
size="19"
|
||||||
|
on:click={() => value = !value}/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{:else if type === "options"}
|
||||||
|
|
||||||
|
<select class="uk-select uk-form-small"
|
||||||
|
value={value}
|
||||||
|
on:change={ev => onChanged(ev.target.checked)}>
|
||||||
|
{#each options as option}
|
||||||
|
<option value={option}>{option}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
{:else}
|
||||||
|
|
||||||
|
<input class="uk-input uk-form-small"
|
||||||
|
on:change={ev => onChanged(ev.target.value)}
|
||||||
|
bind:value={value}
|
||||||
|
style="flex: 1 0 auto;" >
|
||||||
|
|
||||||
|
|
||||||
|
{/if}
|
||||||
|
<IconButton icon="link"
|
||||||
|
size="12"
|
||||||
|
on:click={makeBinding} />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.unbound-container {
|
||||||
|
display:flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unbound-container > *:nth-child(1) {
|
||||||
|
width:auto;
|
||||||
|
flex: 1 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bound-header {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bound-header > div:nth-child(1) {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
width: 30px;
|
||||||
|
color: var(--darkslate);
|
||||||
|
padding-left: 5px;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.binding-prop-label {
|
||||||
|
color: var(--darkslate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
</style>
|
|
@ -88,6 +88,7 @@ const settings = () => {
|
||||||
grid-template-columns: [uiNav] 250px [preview] auto [properties] 300px;
|
grid-template-columns: [uiNav] 250px [preview] auto [properties] 300px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-nav {
|
.ui-nav {
|
||||||
|
@ -100,6 +101,7 @@ const settings = () => {
|
||||||
grid-column-start: properties;
|
grid-column-start: properties;
|
||||||
background-color: var(--primary10);
|
background-color: var(--primary10);
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pages-list-container {
|
.pages-list-container {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {
|
import {
|
||||||
getComponentInfo, createProps, getInstanceProps
|
getComponentInfo, createProps, getInstanceProps
|
||||||
} from "./createProps";
|
} from "./createProps";
|
||||||
import { cloneDeep } from "lodash/fp";
|
|
||||||
|
|
||||||
export const buildPropsHierarchy = (allComponents, baseComponent) => {
|
export const buildPropsHierarchy = (allComponents, baseComponent) => {
|
||||||
|
|
||||||
|
@ -39,7 +38,7 @@ export const buildPropsHierarchy = (allComponents, baseComponent) => {
|
||||||
for(let element of propsArray) {
|
for(let element of propsArray) {
|
||||||
newPropsArray.push(
|
newPropsArray.push(
|
||||||
buildProps(
|
buildProps(
|
||||||
`${propName}[${index}]`,
|
`${propName}#array_element#`,
|
||||||
propDef.elementDefinition,
|
propDef.elementDefinition,
|
||||||
element));
|
element));
|
||||||
index++;
|
index++;
|
||||||
|
|
|
@ -150,7 +150,7 @@ export const createProps = (componentName, propsDefinition, derivedFromProps) =>
|
||||||
|
|
||||||
export const createArrayElementProps = (arrayPropName, elementDefinition) =>
|
export const createArrayElementProps = (arrayPropName, elementDefinition) =>
|
||||||
createProps(
|
createProps(
|
||||||
`#element#${arrayPropName}`,
|
`#${arrayPropName}#array_element`,
|
||||||
elementDefinition);
|
elementDefinition);
|
||||||
|
|
||||||
const parsePropDef = propDef => {
|
const parsePropDef = propDef => {
|
||||||
|
|
|
@ -3,9 +3,15 @@ import {
|
||||||
isBoolean,
|
isBoolean,
|
||||||
isNumber,
|
isNumber,
|
||||||
isArray,
|
isArray,
|
||||||
isObjectLike
|
isObjectLike,
|
||||||
|
isPlainObject,
|
||||||
|
every
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
|
|
||||||
|
import {
|
||||||
|
EVENT_TYPE_MEMBER_NAME
|
||||||
|
} from "../../common/eventHandlers";
|
||||||
|
|
||||||
const defaultDef = typeName => () => ({
|
const defaultDef = typeName => () => ({
|
||||||
type: typeName,
|
type: typeName,
|
||||||
required:false,
|
required:false,
|
||||||
|
@ -47,6 +53,14 @@ export const expandPropsDefinition = propsDefinition => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const isComponent = isObjectLike;
|
const isComponent = isObjectLike;
|
||||||
|
const isEvent = e =>
|
||||||
|
isPlainObject(e)
|
||||||
|
&& isString(e[EVENT_TYPE_MEMBER_NAME])
|
||||||
|
&& isPlainObject(e.parameters);
|
||||||
|
|
||||||
|
const isEventList = e =>
|
||||||
|
isArray(e) && every(isEvent)(e);
|
||||||
|
|
||||||
|
|
||||||
export const types = {
|
export const types = {
|
||||||
string: propType(() => "", isString, defaultDef("string")),
|
string: propType(() => "", isString, defaultDef("string")),
|
||||||
|
@ -56,4 +70,5 @@ export const types = {
|
||||||
options: propType(() => "", isString, defaultDef("options")),
|
options: propType(() => "", isString, defaultDef("options")),
|
||||||
component: propType(() => ({_component:""}), isComponent, defaultDef("component")),
|
component: propType(() => ({_component:""}), isComponent, defaultDef("component")),
|
||||||
asset: propType(() => "", isString, defaultDef("asset")),
|
asset: propType(() => "", isString, defaultDef("asset")),
|
||||||
|
event: propType(() => [], isEventList, defaultDef("event"))
|
||||||
};
|
};
|
|
@ -1,21 +1,17 @@
|
||||||
import { types } from "./types";
|
import { types } from "./types";
|
||||||
import {
|
import {
|
||||||
createProps,
|
createProps, arrayElementComponentName
|
||||||
arrayElementComponentName
|
|
||||||
} from "./createProps";
|
} from "./createProps";
|
||||||
import { isString } from "util";
|
import { isString } from "util";
|
||||||
import {
|
import {
|
||||||
includes,
|
includes, filter, map, keys,
|
||||||
filter,
|
flatten, flattenDeep, each,
|
||||||
map,
|
indexOf, isUndefined
|
||||||
keys,
|
|
||||||
flatten,
|
|
||||||
flattenDeep,
|
|
||||||
each,
|
|
||||||
indexOf,
|
|
||||||
isUndefined
|
|
||||||
} from "lodash/fp";
|
} from "lodash/fp";
|
||||||
import { common } from "../../../../core/src";
|
import { common } from "../../../../core/src";
|
||||||
|
import {
|
||||||
|
isBinding
|
||||||
|
} from "../../common/binding";
|
||||||
|
|
||||||
const pipe = common.$;
|
const pipe = common.$;
|
||||||
|
|
||||||
|
@ -133,7 +129,15 @@ export const validateProps = (propsDefinition, props, stack=[], isFinal=true) =>
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!type.isOfType(propValue)) {
|
if(isBinding(propValue)) {
|
||||||
|
if(propDef.type === "array"
|
||||||
|
|| propDef.type === "component"
|
||||||
|
|| propDef.type === "event") {
|
||||||
|
error(`Cannot apply binding to type ${propDef.type}`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!type.isOfType(propValue)) {
|
||||||
error(`Property ${propDefName} is not of type ${propDef.type}. Actual value ${propValue}`)
|
error(`Property ${propDefName} is not of type ${propDef.type}. Actual value ${propValue}`)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -141,7 +145,6 @@ export const validateProps = (propsDefinition, props, stack=[], isFinal=true) =>
|
||||||
if(propDef.type === "array") {
|
if(propDef.type === "array") {
|
||||||
let index = 0;
|
let index = 0;
|
||||||
for(let arrayItem of propValue) {
|
for(let arrayItem of propValue) {
|
||||||
arrayItem._component = arrayElementComponentName(props._component, propDefName);
|
|
||||||
const arrayErrs = validateProps(
|
const arrayErrs = validateProps(
|
||||||
propDef.elementDefinition,
|
propDef.elementDefinition,
|
||||||
arrayItem,
|
arrayItem,
|
||||||
|
@ -157,6 +160,7 @@ export const validateProps = (propsDefinition, props, stack=[], isFinal=true) =>
|
||||||
|
|
||||||
if(propDef.type === "options"
|
if(propDef.type === "options"
|
||||||
&& propValue
|
&& propValue
|
||||||
|
&& !isBinding(propValue)
|
||||||
&& !includes(propValue)(propDef.options)) {
|
&& !includes(propValue)(propDef.options)) {
|
||||||
error(`Property ${propDefName} is not one of allowed options. Acutal value is ${propValue}`);
|
error(`Property ${propDefName} is not one of allowed options. Acutal value is ${propValue}`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,18 @@ describe("createDefaultProps", () => {
|
||||||
expect(props.columns).toEqual([]);
|
expect(props.columns).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create a object with single empty array, when prop definition is 'event' ", () => {
|
||||||
|
const propDef = {
|
||||||
|
onClick: "event"
|
||||||
|
};
|
||||||
|
|
||||||
|
const { props, errors } = createProps("some_component",propDef);
|
||||||
|
|
||||||
|
expect(errors).toEqual([]);
|
||||||
|
expect(props.onClick).toBeDefined();
|
||||||
|
expect(props.onClick).toEqual([]);
|
||||||
|
});
|
||||||
|
|
||||||
it("should create a object with single empty component props, when prop definition is 'component' ", () => {
|
it("should create a object with single empty component props, when prop definition is 'component' ", () => {
|
||||||
const propDef = {
|
const propDef = {
|
||||||
content: "component"
|
content: "component"
|
||||||
|
|
|
@ -4,6 +4,9 @@ import {
|
||||||
recursivelyValidate
|
recursivelyValidate
|
||||||
} from "../src/userInterface/pagesParsing/validateProps";
|
} from "../src/userInterface/pagesParsing/validateProps";
|
||||||
import { createProps } from "../src/userInterface/pagesParsing/createProps";
|
import { createProps } from "../src/userInterface/pagesParsing/createProps";
|
||||||
|
import {
|
||||||
|
setBinding
|
||||||
|
} from "../src/common/binding";
|
||||||
|
|
||||||
// not that allot of this functionality is covered
|
// not that allot of this functionality is covered
|
||||||
// in createDefaultProps - as validate props uses that.
|
// in createDefaultProps - as validate props uses that.
|
||||||
|
@ -151,6 +154,14 @@ describe("validateProps", () => {
|
||||||
expect(errors[0].propName).toBe("width");
|
expect(errors[0].propName).toBe("width");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should not return error when has binding", () => {
|
||||||
|
const props = validProps();
|
||||||
|
props.columns[0].width = setBinding({path:"some_path"});
|
||||||
|
props.size = setBinding({path:"other path", fallback:"small"});
|
||||||
|
const errors = validateProps(validPropDef, props, [], true);
|
||||||
|
expect(errors.length).toEqual(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("recursivelyValidateProps", () => {
|
describe("recursivelyValidateProps", () => {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"main": "dist/budibase-client.js",
|
"main": "dist/budibase-client.js",
|
||||||
"module": "dist/budibase-client.js",
|
"module": "dist/budibase-client.esm.mjs",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"test": "jest",
|
"test": "jest",
|
||||||
|
|
|
@ -6,8 +6,8 @@ import { terser } from 'rollup-plugin-terser';
|
||||||
|
|
||||||
const lodash_fp_exports = [
|
const lodash_fp_exports = [
|
||||||
"find", "isUndefined", "split",
|
"find", "isUndefined", "split",
|
||||||
"last", "union", "reduce",
|
"last", "union", "reduce", "isObject",
|
||||||
"cloneDeep", "some"];
|
"cloneDeep", "some", "isArray"];
|
||||||
|
|
||||||
const lodash_exports = [
|
const lodash_exports = [
|
||||||
"flow","reduce", "constant", "head", "isEmpty",
|
"flow","reduce", "constant", "head", "isEmpty",
|
||||||
|
@ -26,12 +26,19 @@ const coreExternal = [
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
input: 'src/index.js',
|
input: 'src/index.js',
|
||||||
output: {
|
output: [
|
||||||
sourcemap: true,
|
{
|
||||||
format: 'iife',
|
sourcemap: true,
|
||||||
name: 'app',
|
format: 'iife',
|
||||||
file: `./dist/budibase-client.js`
|
name: 'app',
|
||||||
},
|
file: `./dist/budibase-client.js`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'dist/budibase-client.esm.mjs',
|
||||||
|
format: 'esm',
|
||||||
|
sourcemap: 'inline'
|
||||||
|
}
|
||||||
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
import {
|
||||||
|
split,
|
||||||
|
last
|
||||||
|
} from "lodash/fp";
|
||||||
|
import {writable} from "svelte/store";
|
||||||
|
import { $ } from "./core/common";
|
||||||
|
import { setupBinding } from "./state/stateBinding";
|
||||||
|
|
||||||
|
export const createApp = componentLibraries => {
|
||||||
|
|
||||||
|
const initialiseComponent = (props, htmlElement) => {
|
||||||
|
|
||||||
|
const {componentName, libName} = splitName(props._component);
|
||||||
|
|
||||||
|
if(!componentName || !libName) return;
|
||||||
|
|
||||||
|
const {initialProps, bind} = setupBinding(store, props);
|
||||||
|
|
||||||
|
const component = new (componentLibraries[libName][componentName])({
|
||||||
|
target: htmlElement,
|
||||||
|
props: {...initialProps, _app}
|
||||||
|
});
|
||||||
|
|
||||||
|
bind(component);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = writable({});
|
||||||
|
|
||||||
|
const _app = {
|
||||||
|
initialiseComponent,
|
||||||
|
store
|
||||||
|
};
|
||||||
|
|
||||||
|
return _app;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const splitName = fullname => {
|
||||||
|
const componentName = $(fullname, [
|
||||||
|
split("/"),
|
||||||
|
last
|
||||||
|
]);
|
||||||
|
|
||||||
|
const libName =fullname.substring(
|
||||||
|
0, fullname.length - componentName.length - 1);
|
||||||
|
|
||||||
|
return {libName, componentName};
|
||||||
|
}
|
|
@ -1,5 +1,32 @@
|
||||||
import { initialise } from "./initialise";
|
import { createApp } from "./createApp";
|
||||||
|
|
||||||
const appDefinition = window["##BUDIBASE_APPDEFINITION##"];
|
|
||||||
|
|
||||||
initialise(window.document, appDefinition);
|
export const loadBudibase = async (componentLibraries, props) => {
|
||||||
|
|
||||||
|
const appDefinition = window["##BUDIBASE_APPDEFINITION##"];
|
||||||
|
|
||||||
|
if(!componentLibraries) {
|
||||||
|
|
||||||
|
const componentLibraryUrl = (lib) => "./" + trimSlash(lib)
|
||||||
|
const trimSlash = (str) => str.replace(/^\/+|\/+$/g, '');
|
||||||
|
componentLibraries = {};
|
||||||
|
|
||||||
|
for(let lib of appDefinition.componentLibraries) {
|
||||||
|
componentLibraries[lib.libName] = await import(
|
||||||
|
componentLibraryUrl(lib.importPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!props) {
|
||||||
|
props = appDefinition.props;
|
||||||
|
}
|
||||||
|
|
||||||
|
const _app = createApp(componentLibraries);
|
||||||
|
_app.initialiseComponent(
|
||||||
|
props,
|
||||||
|
document.body);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
window.loadBudibase = loadBudibase;
|
|
@ -1,22 +0,0 @@
|
||||||
import { writable } from "svelte/store";
|
|
||||||
import { initialiseComponent } from "./initialiseComponent";
|
|
||||||
|
|
||||||
export const initialise = async (document, appDefinition) => {
|
|
||||||
|
|
||||||
const componentLibraries = {};
|
|
||||||
|
|
||||||
for(let lib of appDefinition.componentLibraries) {
|
|
||||||
componentLibraries[lib.libName] = await import(
|
|
||||||
componentLibraryUrl(lib.importPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = writable({});
|
|
||||||
|
|
||||||
initialiseComponent(componentLibraries, store)(
|
|
||||||
appDefinition.props,
|
|
||||||
document.body);
|
|
||||||
}
|
|
||||||
const componentLibraryUrl = (lib) => "./" + trimSlash(lib)
|
|
||||||
|
|
||||||
const trimSlash = (str) => str.replace(/^\/+|\/+$/g, '');
|
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import {
|
|
||||||
find,
|
|
||||||
isUndefined,
|
|
||||||
split,
|
|
||||||
last
|
|
||||||
} from "lodash/fp";
|
|
||||||
|
|
||||||
import { $ } from "./core/common";
|
|
||||||
|
|
||||||
export const initialiseComponent = (componentLibraries, store) => (props, htmlElement) => {
|
|
||||||
|
|
||||||
const _app = {
|
|
||||||
initialiseComponent: initialiseComponent(componentLibraries, store),
|
|
||||||
store
|
|
||||||
};
|
|
||||||
|
|
||||||
const {componentName, libName} = splitName(props._component);
|
|
||||||
|
|
||||||
new (componentLibraries[libName][componentName])({
|
|
||||||
target: htmlElement,
|
|
||||||
props: {...props, _app}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const splitName = fullname => {
|
|
||||||
const componentName = $(fullname, [
|
|
||||||
split("/"),
|
|
||||||
last
|
|
||||||
]);
|
|
||||||
|
|
||||||
const libName =fullname.substring(
|
|
||||||
0, fullname.length - componentName.length - 1);
|
|
||||||
|
|
||||||
return {libName, componentName};
|
|
||||||
}
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
import {
|
||||||
|
setState
|
||||||
|
} from "./setState";
|
||||||
|
import {
|
||||||
|
isArray, isUndefined
|
||||||
|
} from "lodash/fp";
|
||||||
|
|
||||||
|
export const EVENT_TYPE_MEMBER_NAME = "##eventHandlerType";
|
||||||
|
|
||||||
|
export const eventHandlers = store => {
|
||||||
|
|
||||||
|
const handler = (parameters, execute) => ({
|
||||||
|
execute, parameters
|
||||||
|
});
|
||||||
|
|
||||||
|
const setStateHandler = ({path, value}) => setState(store, path, value);
|
||||||
|
|
||||||
|
return {
|
||||||
|
"Set State": handler(["path", "value"], setStateHandler)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isEventType = prop =>
|
||||||
|
isArray(prop)
|
||||||
|
&& prop.length > 0
|
||||||
|
&& !isUndefined(prop[0][EVENT_TYPE_MEMBER_NAME]);
|
|
@ -0,0 +1,34 @@
|
||||||
|
import {
|
||||||
|
isUndefined,
|
||||||
|
isObject
|
||||||
|
} from "lodash/fp";
|
||||||
|
|
||||||
|
export const getState = (s, path, fallback) => {
|
||||||
|
|
||||||
|
const pathParts = path.split(".");
|
||||||
|
const safeGetPath = (obj, currentPartIndex=0) => {
|
||||||
|
|
||||||
|
const currentKey = pathParts[currentPartIndex];
|
||||||
|
|
||||||
|
if(pathParts.length - 1 == currentPartIndex) {
|
||||||
|
const value = obj[currentKey];
|
||||||
|
if(isUndefined(value))
|
||||||
|
return fallback;
|
||||||
|
else
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(obj[currentKey] === null
|
||||||
|
|| obj[currentKey] === undefined
|
||||||
|
|| !isObject(obj[currentKey])) {
|
||||||
|
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
return safeGetPath(obj[currentKey], currentPartIndex + 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return safeGetPath(s);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import {
|
||||||
|
isObject
|
||||||
|
} from "lodash/fp";
|
||||||
|
|
||||||
|
|
||||||
|
export const setState = (store, path, value) => {
|
||||||
|
|
||||||
|
const pathParts = path.split(".");
|
||||||
|
const safeSetPath = (obj, currentPartIndex=0) => {
|
||||||
|
|
||||||
|
const currentKey = pathParts[currentPartIndex];
|
||||||
|
|
||||||
|
if(pathParts.length - 1 == currentPartIndex) {
|
||||||
|
obj[currentKey] = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(obj[currentKey] === null
|
||||||
|
|| obj[currentKey] === undefined
|
||||||
|
|| !isObject(obj.currentKey)) {
|
||||||
|
|
||||||
|
obj[currentKey] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
safeSetPath(obj[currentKey], currentPartIndex + 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
store.update(s => {
|
||||||
|
safeSetPath(s);
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
import {
|
||||||
|
isEventType, eventHandlers, EVENT_TYPE_MEMBER_NAME
|
||||||
|
} from "./eventHandlers";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getState
|
||||||
|
} from "./getState";
|
||||||
|
|
||||||
|
export const BB_STATE_BINDINGPATH = "##bbstate";
|
||||||
|
export const BB_STATE_FALLBACK = "##bbstatefallback";
|
||||||
|
const doNothing = () => {};
|
||||||
|
export const setupBinding = (store, props) => {
|
||||||
|
|
||||||
|
const initialProps = {...props};
|
||||||
|
const boundProps = [];
|
||||||
|
const componentEventHandlers = [];
|
||||||
|
|
||||||
|
for(let propName in props) {
|
||||||
|
const val = initialProps[propName];
|
||||||
|
|
||||||
|
if(isState(val)) {
|
||||||
|
|
||||||
|
const binding = stateBinding(val);
|
||||||
|
const fallback = stateFallback(val);
|
||||||
|
|
||||||
|
boundProps.push({
|
||||||
|
stateBinding:binding,
|
||||||
|
fallback, propName
|
||||||
|
});
|
||||||
|
|
||||||
|
initialProps[propName] = fallback;
|
||||||
|
} else if(isEventType(val)) {
|
||||||
|
|
||||||
|
const handlers = { propName, handlers:[] };
|
||||||
|
componentEventHandlers.push(handlers);
|
||||||
|
|
||||||
|
for(let e of val) {
|
||||||
|
handlers.handlers.push({
|
||||||
|
handlerType: e[EVENT_TYPE_MEMBER_NAME],
|
||||||
|
parameters: e.parameters
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
initialProps[propName] = doNothing;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const bind = (component) => {
|
||||||
|
|
||||||
|
if(boundProps.length === 0 && componentEventHandlers.length === 0) return;
|
||||||
|
|
||||||
|
const handlerTypes = eventHandlers(store);
|
||||||
|
|
||||||
|
const unsubscribe = store.subscribe(s => {
|
||||||
|
const newProps = {};
|
||||||
|
|
||||||
|
for(let boundProp of boundProps) {
|
||||||
|
const val = getState(
|
||||||
|
s,
|
||||||
|
boundProp.stateBinding,
|
||||||
|
boundProp.fallback);
|
||||||
|
|
||||||
|
if(val === undefined && newProps[boundProp.propName] !== undefined) {
|
||||||
|
delete newProps[boundProp.propName];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(val !== undefined) {
|
||||||
|
newProps[boundProp.propName] = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(let boundHandler of componentEventHandlers) {
|
||||||
|
|
||||||
|
const closuredHandlers = [];
|
||||||
|
for(let h of boundHandler.handlers) {
|
||||||
|
const parameters = {};
|
||||||
|
for(let pname in h.parameters) {
|
||||||
|
const p = h.parameters[pname];
|
||||||
|
parameters[pname] = isState(p)
|
||||||
|
? getState(
|
||||||
|
s, p[BB_STATE_BINDINGPATH], p[BB_STATE_FALLBACK])
|
||||||
|
: p;
|
||||||
|
|
||||||
|
}
|
||||||
|
const handlerType = handlerTypes[h.handlerType];
|
||||||
|
closuredHandlers.push(() => handlerType.execute(parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
newProps[boundHandler.propName] = () => {
|
||||||
|
for(let runHandler of closuredHandlers) {
|
||||||
|
runHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
component.$set(newProps);
|
||||||
|
});
|
||||||
|
|
||||||
|
return unsubscribe;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
initialProps, bind
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const isState = (prop) => prop[BB_STATE_BINDINGPATH] !== undefined;
|
||||||
|
const stateBinding = (prop) => prop[BB_STATE_BINDINGPATH];
|
||||||
|
const stateFallback = (prop) => prop[BB_STATE_FALLBACK];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
import {
|
||||||
|
setupBinding,
|
||||||
|
BB_STATE_BINDINGPATH,
|
||||||
|
BB_STATE_FALLBACK
|
||||||
|
} from "../src/state/stateBinding";
|
||||||
|
import { EVENT_TYPE_MEMBER_NAME } from "../src/state/eventHandlers";
|
||||||
|
import {writable} from "svelte/store";
|
||||||
|
import { isFunction } from "lodash/fp";
|
||||||
|
|
||||||
|
describe("setupBinding", () => {
|
||||||
|
|
||||||
|
|
||||||
|
it("should correctly create initials props, including fallback values", () => {
|
||||||
|
|
||||||
|
const {store, props, component} = testSetup();
|
||||||
|
|
||||||
|
const {initialProps} = testSetupBinding(store, props, component);
|
||||||
|
|
||||||
|
expect(initialProps.boundWithFallback).toBe("Bob");
|
||||||
|
expect(initialProps.boundNoFallback).toBeUndefined();
|
||||||
|
expect(initialProps.unbound).toBe("hello");
|
||||||
|
|
||||||
|
expect(isFunction(initialProps.eventBound)).toBeTruthy();
|
||||||
|
initialProps.eventBound();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should update component bound props when store is updated", () => {
|
||||||
|
|
||||||
|
const {component, store, props} = testSetup();
|
||||||
|
|
||||||
|
const {bind} = testSetupBinding(store, props, component);
|
||||||
|
bind(component);
|
||||||
|
|
||||||
|
store.update(s => {
|
||||||
|
s.FirstName = "Bobby";
|
||||||
|
s.LastName = "Thedog";
|
||||||
|
s.Customer = {
|
||||||
|
Name: "ACME inc",
|
||||||
|
Address: ""
|
||||||
|
};
|
||||||
|
s.addressToSet = "123 Main Street"
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(component.props.boundWithFallback).toBe("Bobby");
|
||||||
|
expect(component.props.boundNoFallback).toBe("Thedog");
|
||||||
|
expect(component.props.multiPartBound).toBe("ACME inc");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not update unbound props when store is updated", () => {
|
||||||
|
|
||||||
|
const {component, store, props} = testSetup();
|
||||||
|
|
||||||
|
const {bind} = testSetupBinding(store, props, component);
|
||||||
|
bind(component);
|
||||||
|
|
||||||
|
store.update(s => {
|
||||||
|
s.FirstName = "Bobby";
|
||||||
|
s.LastName = "Thedog";
|
||||||
|
s.Customer = {
|
||||||
|
Name: "ACME inc",
|
||||||
|
Address: ""
|
||||||
|
};
|
||||||
|
s.addressToSet = "123 Main Street"
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(component.props.unbound).toBe("hello");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should update event handlers on state change", () => {
|
||||||
|
|
||||||
|
const {component, store, props} = testSetup();
|
||||||
|
|
||||||
|
const {bind} = testSetupBinding(store, props, component);
|
||||||
|
bind(component);
|
||||||
|
|
||||||
|
expect(component.props.boundToEventOutput).toBe("initial address");
|
||||||
|
component.props.eventBound();
|
||||||
|
expect(component.props.boundToEventOutput).toBe("event fallback address");
|
||||||
|
|
||||||
|
store.update(s => {
|
||||||
|
s.addressToSet = "123 Main Street"
|
||||||
|
return s;
|
||||||
|
});
|
||||||
|
|
||||||
|
component.props.eventBound();
|
||||||
|
expect(component.props.boundToEventOutput).toBe("123 Main Street");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
const testSetupBinding = (store, props, component) => {
|
||||||
|
const setup = setupBinding(store, props);
|
||||||
|
component.props = setup.initialProps; // svelte does this for us in real life
|
||||||
|
return setup;
|
||||||
|
}
|
||||||
|
const testSetup = () => {
|
||||||
|
|
||||||
|
const c = {};
|
||||||
|
|
||||||
|
c.props = {};
|
||||||
|
c.$set = propsToSet => {
|
||||||
|
for(let pname in propsToSet)
|
||||||
|
c.props[pname] = propsToSet[pname];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const binding = (path, fallback) => {
|
||||||
|
const b = {};
|
||||||
|
b[BB_STATE_BINDINGPATH] = path;
|
||||||
|
b[BB_STATE_FALLBACK] = fallback;
|
||||||
|
return b;
|
||||||
|
};
|
||||||
|
|
||||||
|
const event = (handlerType, parameters) => {
|
||||||
|
const e = {};
|
||||||
|
e[EVENT_TYPE_MEMBER_NAME] = handlerType;
|
||||||
|
e.parameters = parameters;
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = {
|
||||||
|
boundWithFallback : binding("FirstName", "Bob"),
|
||||||
|
boundNoFallback : binding("LastName"),
|
||||||
|
unbound: "hello",
|
||||||
|
multiPartBound: binding("Customer.Name", "ACME"),
|
||||||
|
boundToEventOutput: binding("Customer.Address", "initial address"),
|
||||||
|
eventBound: [
|
||||||
|
event("Set State", {
|
||||||
|
path: "Customer.Address",
|
||||||
|
value: binding("addressToSet", "event fallback address")
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
component:c,
|
||||||
|
store:writable({}),
|
||||||
|
props
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "Button",
|
||||||
|
"description": "PrimaryButton",
|
||||||
|
"inherits": "@budibase/standard-components/button",
|
||||||
|
"props": {
|
||||||
|
"contentText": "Save"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"button"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "LoginForm",
|
||||||
|
"description": "",
|
||||||
|
"inherits": "@budibase/standard-components/formControl",
|
||||||
|
"props": {
|
||||||
|
"label": "Joe",
|
||||||
|
"labelContainerClass": "Joe",
|
||||||
|
"controlContainerClass": "Joe",
|
||||||
|
"containerClass": "Joe",
|
||||||
|
"fullWidth": true
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"login"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"name": "joeTextBox",
|
||||||
|
"description": "",
|
||||||
|
"inherits": "subfolder/otherTextBox",
|
||||||
|
"props": {},
|
||||||
|
"tags": [
|
||||||
|
""
|
||||||
|
]
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -156,14 +156,75 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"props": {
|
"props": {
|
||||||
"main": {},
|
"main": {
|
||||||
|
"_component": "@budibase/standard-components/grid",
|
||||||
|
"gridTemplateRows": "",
|
||||||
|
"gridTemplateColumns": "[left] 1fr [right] 1fr",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"_component": "children#array_element#",
|
||||||
|
"control": {
|
||||||
|
"_component": "@budibase/standard-components/button",
|
||||||
|
"contentText": "Click Me",
|
||||||
|
"contentComponent": {
|
||||||
|
"_component": ""
|
||||||
|
},
|
||||||
|
"className": "default",
|
||||||
|
"disabled": false,
|
||||||
|
"onClick": [
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Set State",
|
||||||
|
"parameters": {
|
||||||
|
"path": "SomeText",
|
||||||
|
"value": "hello !"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gridColumn": "left",
|
||||||
|
"gridRow": "",
|
||||||
|
"gridColumnStart": "",
|
||||||
|
"gridColumnEnd": "",
|
||||||
|
"gridRowStart": "",
|
||||||
|
"gridRowEnd": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_component": "children#array_element#",
|
||||||
|
"control": {
|
||||||
|
"_component": "@budibase/standard-components/button",
|
||||||
|
"contentText": {
|
||||||
|
"##bbstate": "SomeText",
|
||||||
|
"##bbstatefallback": "(none)"
|
||||||
|
},
|
||||||
|
"contentComponent": {
|
||||||
|
"_component": ""
|
||||||
|
},
|
||||||
|
"className": "default",
|
||||||
|
"disabled": false,
|
||||||
|
"onClick": []
|
||||||
|
},
|
||||||
|
"gridColumn": "",
|
||||||
|
"gridRow": "",
|
||||||
|
"gridColumnStart": "",
|
||||||
|
"gridColumnEnd": "",
|
||||||
|
"gridRowStart": "",
|
||||||
|
"gridRowEnd": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"width": "auto",
|
||||||
|
"height": "auto",
|
||||||
|
"containerClass": "",
|
||||||
|
"itemContainerClass": ""
|
||||||
|
},
|
||||||
"unauthenticated": {
|
"unauthenticated": {
|
||||||
"_component": "budibase-standard-components/login",
|
"_component": "@budibase/standard-components/grid",
|
||||||
"logo": "/_shared/budibase-logo.png",
|
"gridTemplateRows": "",
|
||||||
"loginRedirect": "",
|
"gridTemplateColumns": "[left] 1fr [right] 1fr",
|
||||||
"usernameLabel": "Username",
|
"children": [],
|
||||||
"passwordLabel": "Password",
|
"width": "auto",
|
||||||
"loginButtonLabel": "Login"
|
"height": "auto",
|
||||||
|
"containerClass": "",
|
||||||
|
"itemContainerClass": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
{
|
||||||
|
"name": "Primary Button",
|
||||||
|
"description": "",
|
||||||
|
"inherits": "@budibase/standard-components/button",
|
||||||
|
"props": {
|
||||||
|
"onClick": [
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Load Record",
|
||||||
|
"parameters": {
|
||||||
|
"recordKey": "waa",
|
||||||
|
"statePath": "yea"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Load Record",
|
||||||
|
"parameters": {
|
||||||
|
"recordKey": "ttt",
|
||||||
|
"statePath": "eee"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contentText": {
|
||||||
|
"##bbstate": "yea"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"button"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"name": "/containers/two_columns",
|
||||||
|
"description": "",
|
||||||
|
"inherits": "@budibase/standard-components/grid",
|
||||||
|
"props": {
|
||||||
|
"gridTemplateColumns": "[left] 1fr [right] 1fr"
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"div",
|
||||||
|
"container",
|
||||||
|
"layout",
|
||||||
|
"panel",
|
||||||
|
"grid"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
{
|
||||||
|
"name": "mike",
|
||||||
|
"description": "",
|
||||||
|
"inherits": "containers/two_columns",
|
||||||
|
"props": {
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"_component": "#children#array_element",
|
||||||
|
"control": {
|
||||||
|
"_component": "@budibase/standard-components/button",
|
||||||
|
"contentText": "Click Me",
|
||||||
|
"contentComponent": {
|
||||||
|
"_component": ""
|
||||||
|
},
|
||||||
|
"className": "default",
|
||||||
|
"disabled": false,
|
||||||
|
"onClick": [
|
||||||
|
{
|
||||||
|
"##eventHandlerType": "Set State",
|
||||||
|
"parameters": {
|
||||||
|
"path": "SomeText",
|
||||||
|
"value": "hello !"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"gridColumn": "left",
|
||||||
|
"gridRow": "",
|
||||||
|
"gridColumnStart": "",
|
||||||
|
"gridColumnEnd": "",
|
||||||
|
"gridRowStart": "",
|
||||||
|
"gridRowEnd": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_component": "#children#array_element",
|
||||||
|
"control": {
|
||||||
|
"_component": "@budibase/standard-components/button",
|
||||||
|
"contentText": {
|
||||||
|
"##bbstate": "SomeText",
|
||||||
|
"##bbstatefallback": "(none)"
|
||||||
|
},
|
||||||
|
"contentComponent": {
|
||||||
|
"_component": ""
|
||||||
|
},
|
||||||
|
"className": "default",
|
||||||
|
"disabled": false,
|
||||||
|
"onClick": []
|
||||||
|
},
|
||||||
|
"gridColumn": "",
|
||||||
|
"gridRow": "",
|
||||||
|
"gridColumnStart": "",
|
||||||
|
"gridColumnEnd": "",
|
||||||
|
"gridRowStart": "",
|
||||||
|
"gridRowEnd": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
"div",
|
||||||
|
"container",
|
||||||
|
"layout",
|
||||||
|
"panel",
|
||||||
|
"grid"
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,13 +1,15 @@
|
||||||
{
|
{
|
||||||
"main": {
|
"main": {
|
||||||
"index": {},
|
"index": {
|
||||||
"appBody": ""
|
"title": "main yeo"
|
||||||
|
},
|
||||||
|
"appBody": "mike"
|
||||||
},
|
},
|
||||||
"unauthenticated": {
|
"unauthenticated": {
|
||||||
"index": {
|
"index": {
|
||||||
"title": "Test App Two"
|
"title": "main"
|
||||||
},
|
},
|
||||||
"appBody": "login"
|
"appBody": "containers/two_columns"
|
||||||
},
|
},
|
||||||
"componentLibraries": [
|
"componentLibraries": [
|
||||||
"@budibase/standard-components"
|
"@budibase/standard-components"
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
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":[],"allowedRecordNodeIds":[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":[],"allowedRecordNodeIds":[1],"nodeId":4},{"name":"everyones_invoices","type":"index","map":"return {...record};","filter":"","indexType":"ancestor","getShardName":"","getSortKey":"record.id","aggregateGroups":[],"allowedRecordNodeIds":[2],"nodeId":6}],"nodeId":0},"componentLibraries":["budibase-standard-components"],"appRootPath":"/testApp2","props":{}}
|
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":[],"allowedRecordNodeIds":[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":[],"allowedRecordNodeIds":[1],"nodeId":4},{"name":"everyones_invoices","type":"index","map":"return {...record};","filter":"","indexType":"ancestor","getShardName":"","getSortKey":"record.id","aggregateGroups":[],"allowedRecordNodeIds":[2],"nodeId":6}],"nodeId":0},"componentLibraries":[{"importPath":"/lib/node_modules/@budibase/standard-components/dist/index.js","libName":"@budibase/standard-components"}],"appRootPath":"/testApp2","props":{"_component":"@budibase/standard-components/grid","gridTemplateRows":"","gridTemplateColumns":"[left] 1fr [right] 1fr","children":[{"_component":"children#array_element#","control":{"_component":"@budibase/standard-components/button","contentText":"Click Me","contentComponent":{"_component":""},"className":"default","disabled":false,"onClick":[{"##eventHandlerType":"Set State","parameters":{"path":"SomeText","value":"hello !"}}]},"gridColumn":"left","gridRow":"","gridColumnStart":"","gridColumnEnd":"","gridRowStart":"","gridRowEnd":""},{"_component":"children#array_element#","control":{"_component":"@budibase/standard-components/button","contentText":{"##bbstate":"SomeText","##bbstatefallback":"(none)"},"contentComponent":{"_component":""},"className":"default","disabled":false,"onClick":[]},"gridColumn":"","gridRow":"","gridColumnStart":"","gridColumnEnd":"","gridRowStart":"","gridRowEnd":""}],"width":"auto","height":"auto","containerClass":"","itemContainerClass":""}}
|
|
@ -4,16 +4,26 @@
|
||||||
<meta charset='utf8'>
|
<meta charset='utf8'>
|
||||||
<meta name='viewport' content='width=device-width'>
|
<meta name='viewport' content='width=device-width'>
|
||||||
|
|
||||||
<title>Budibase App</title>
|
<title>main yeo</title>
|
||||||
<link rel='icon' type='image/png' href='/testApp2/_shared/favicon.png'>
|
<link rel='icon' type='image/png' href='/testApp2//_shared/favicon.png'>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<script src='/testApp2/clientAppDefinition.js'></script>
|
||||||
<script src='/testApp2/budibase-client.js'></script>
|
<script src='/testApp2/budibase-client.js'></script>
|
||||||
|
<script>
|
||||||
|
loadBudibase();
|
||||||
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body id="app">
|
<body id="app">
|
||||||
<script src='/testApp2/clientAppDefinition.js'></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
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":[],"allowedRecordNodeIds":[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":[],"allowedRecordNodeIds":[1],"nodeId":4},{"name":"everyones_invoices","type":"index","map":"return {...record};","filter":"","indexType":"ancestor","getShardName":"","getSortKey":"record.id","aggregateGroups":[],"allowedRecordNodeIds":[2],"nodeId":6}],"nodeId":0},"componentLibraries":["budibase-standard-components"],"appRootPath":"/testApp2","props":{"_component":"budibase-standard-components/login","logo":"/_shared/budibase-logo.png","loginRedirect":"","usernameLabel":"Username","passwordLabel":"Password","loginButtonLabel":"Login"}}
|
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":[],"allowedRecordNodeIds":[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":[],"allowedRecordNodeIds":[1],"nodeId":4},{"name":"everyones_invoices","type":"index","map":"return {...record};","filter":"","indexType":"ancestor","getShardName":"","getSortKey":"record.id","aggregateGroups":[],"allowedRecordNodeIds":[2],"nodeId":6}],"nodeId":0},"componentLibraries":[{"importPath":"/lib/node_modules/@budibase/standard-components/dist/index.js","libName":"@budibase/standard-components"}],"appRootPath":"/testApp2","props":{"_component":"@budibase/standard-components/grid","gridTemplateRows":"","gridTemplateColumns":"[left] 1fr [right] 1fr","children":[],"width":"auto","height":"auto","containerClass":"","itemContainerClass":""}}
|
|
@ -4,16 +4,26 @@
|
||||||
<meta charset='utf8'>
|
<meta charset='utf8'>
|
||||||
<meta name='viewport' content='width=device-width'>
|
<meta name='viewport' content='width=device-width'>
|
||||||
|
|
||||||
<title>Test App Two</title>
|
<title>main</title>
|
||||||
<link rel='icon' type='image/png' href='/testApp2/_shared/favicon.png'>
|
<link rel='icon' type='image/png' href='/testApp2//_shared/favicon.png'>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<script src='/testApp2/clientAppDefinition.js'></script>
|
||||||
<script src='/testApp2/budibase-client.js'></script>
|
<script src='/testApp2/budibase-client.js'></script>
|
||||||
|
<script>
|
||||||
|
loadBudibase();
|
||||||
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body id="app">
|
<body id="app">
|
||||||
<script src='/testApp2/clientAppDefinition.js'></script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
File diff suppressed because one or more lines are too long
|
@ -1,43 +1 @@
|
||||||
main.svelte-pnvh8{height:100%;width:100%;font-family:"Lato", Helvetica, Arial, sans-serif}.settings.svelte-pnvh8{position:absolute;bottom:25px;right:25px}
|
main.svelte-24wuof{height:100%;width:100%;font-family:"Roboto", Helvetica, Arial, sans-serif}.settings.svelte-24wuof{position:absolute;bottom:25px;right:25px}
|
||||||
.root.svelte-jymnqv{position:fixed;margin:0 auto;text-align:center;top:20%;width:100%}.inner.svelte-jymnqv{display:inline-block;margin:auto}.logo.svelte-jymnqv{width:300px;margin-bottom:40px}.root.svelte-jymnqv .option{width:250px}.app-link.svelte-jymnqv{margin-top:10px;display:block}
|
|
||||||
.root.svelte-h9y88z{height:100%;width:100%;display:flex;flex-direction:column}.top-nav.svelte-h9y88z{flex:0 0 auto;height:25px;background:white;border-style:solid;border-width:0px 0px 1px 0px;border-color:var(--lightslate);padding:5px;width:100%}.content.svelte-h9y88z{flex:1 1 auto;width:100%;height:100px}.content.svelte-h9y88z>div.svelte-h9y88z{height:100%;width:100%}.topnavitem.svelte-h9y88z{cursor:pointer;color:var(--slate);padding:0px 15px}.topnavitem.svelte-h9y88z:hover{color:var(--secondary75)}.active.svelte-h9y88z{color:var(--secondary100)}
|
|
||||||
.root.svelte-tavaga{height:100%;display:flex}.content.svelte-tavaga{flex:1 1 auto;height:100%;background-color:var(--white);margin:0}.nav.svelte-tavaga{flex:0 1 auto;width:300px;height:100%}
|
|
||||||
.border-normal.svelte-7rfkdx{border-radius:var(--borderradiusall)}.border-left.svelte-7rfkdx{border-radius:var(--borderradius) 0 0 var(--borderradius)}.border-right.svelte-7rfkdx{border-radius:0 var(--borderradius) var(--borderradius) 0}.border-middle.svelte-7rfkdx{border-radius:0}button.svelte-7rfkdx{border-style:solid;padding:7px 15px;cursor:pointer}.primary.svelte-7rfkdx{background-color:var(--primary100);border-color:var(--primary100);color:var(--white)}.primary.svelte-7rfkdx:hover{background-color:var(--primary75);border-color:var(--primary75)}.primary.svelte-7rfkdx:active{background-color:var(--primarydark);border-color:var(--primarydark)}.primary-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--primary100);color:var(--primary100)}.primary-outline.svelte-7rfkdx:hover{background-color:var(--primary10)}.primary-outline.svelte-7rfkdx:pressed{background-color:var(--primary25)}.secondary.svelte-7rfkdx{background-color:var(--secondary100);border-color:var(--secondary100);color:var(--white)}.secondary.svelte-7rfkdx:hover{background-color:var(--secondary75);border-color:var(--secondary75)}.secondary.svelte-7rfkdx:pressed{background-color:var(--secondarydark);border-color:var(--secondarydark)}.secondary-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--secondary100);color:var(--secondary100)}.secondary-outline.svelte-7rfkdx:hover{background-color:var(--secondary10)}.secondary-outline.svelte-7rfkdx:pressed{background-color:var(--secondary25)}.success.svelte-7rfkdx{background-color:var(--success100);border-color:var(--success100);color:var(--white)}.success.svelte-7rfkdx:hover{background-color:var(--success75);border-color:var(--success75)}.success.svelte-7rfkdx:pressed{background-color:var(--successdark);border-color:var(--successdark)}.success-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--success100);color:var(--success100)}.success-outline.svelte-7rfkdx:hover{background-color:var(--success10)}.success-outline.svelte-7rfkdx:pressed{background-color:var(--success25)}.deletion.svelte-7rfkdx{background-color:var(--deletion100);border-color:var(--deletion100);color:var(--white)}.deletion.svelte-7rfkdx:hover{background-color:var(--deletion75);border-color:var(--deletion75)}.deletion.svelte-7rfkdx:pressed{background-color:var(--deletiondark);border-color:var(--deletiondark)}.deletion-outline.svelte-7rfkdx{background-color:var(--white);border-color:var(--deletion100);color:var(--deletion100)}.deletion-outline.svelte-7rfkdx:hover{background-color:var(--deletion10)}.deletion-outline.svelte-7rfkdx:pressed{background-color:var(--deletion25)}
|
|
||||||
button.svelte-4po3k2{border-style:none;background-color:rgba(0,0,0,0);cursor:pointer;outline:none}button.svelte-4po3k2:hover{color:var(--hovercolor)}button.svelte-4po3k2:active{outline:none}
|
|
||||||
.root.svelte-1rbfs7z{display:grid;grid-template-columns:[uiNav] 250px [preview] auto [properties] 300px;height:100%;width:100%}.ui-nav.svelte-1rbfs7z{grid-column-start:uiNav;background-color:var(--primary10);height:100%}.properties-pane.svelte-1rbfs7z{grid-column-start:properties;background-color:var(--primary10);height:100%}.pages-list-container.svelte-1rbfs7z{padding-top:20px}.nav-group-header.svelte-1rbfs7z{font-size:10pt;padding-left:10px}.nav-items-container.svelte-1rbfs7z{padding-top:10px}.nav-group-header.svelte-1rbfs7z{display:grid;grid-template-columns:[icon] auto [title] 1fr [button] auto;padding:10px 2px 0px 7px}.nav-group-header.svelte-1rbfs7z>div.svelte-1rbfs7z:nth-child(1){padding:0px 7px 0px 0px;vertical-align:bottom;grid-column-start:icon;margin-right:5px}.nav-group-header.svelte-1rbfs7z>span.svelte-1rbfs7z:nth-child(2){margin-left:5px;vertical-align:bottom;grid-column-start:title;margin-top:auto}.nav-group-header.svelte-1rbfs7z>div.svelte-1rbfs7z:nth-child(3){vertical-align:bottom;grid-column-start:button;cursor:pointer;color:var(--slate)}.nav-group-header.svelte-1rbfs7z>div.svelte-1rbfs7z:nth-child(3):hover{color:var(--primary75)}
|
|
||||||
h4.svelte-o0id5a{margin-top:20px}
|
|
||||||
.root.svelte-85bkcq{height:100%;position:relative}.actions-header.svelte-85bkcq{flex:0 1 auto}.node-view.svelte-85bkcq{overflow-y:auto;flex:1 1 auto}
|
|
||||||
.root.svelte-1be865r{padding:10px}.edit-button.svelte-1be865r{cursor:pointer;color:var(--white)}tr.svelte-1be865r:hover .edit-button.svelte-1be865r{color:var(--secondary75)}
|
|
||||||
.root.svelte-1py90dy{height:100%;background-color:var(--primary10)}.items-root.svelte-1py90dy{display:flex;flex-direction:column;max-height:100%;height:10px}.hierarchy.svelte-1py90dy{flex:1 1 auto}.hierarchy-title-row.svelte-1py90dy{padding:15px 7px;font-size:12pt;display:flex;font-weight:bold}.hierarchy-title.svelte-1py90dy{flex:auto 1 1}.space-filler.svelte-1py90dy{flex:1 1 auto}
|
|
||||||
.root.svelte-1y6dy5x{padding:10px}
|
|
||||||
.root.svelte-1ba51k0{color:var(--secondary50)}.hierarchy-item.svelte-1ba51k0{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-1ba51k0:hover{color:var(--secondary75)}.component.svelte-1ba51k0{margin-left:5px}.currentfolder.svelte-1ba51k0{color:var(--secondary100)}.selected.svelte-1ba51k0{color:var(--primary100)}.title.svelte-1ba51k0{margin-left:10px}
|
|
||||||
.root.svelte-xai2hc{height:100%;border-style:solid;border-color:var(--lightslate);border-width:0px 0px 0px 1px}.padding.svelte-xai2hc{padding:0px 5px 0px 10px}.title.svelte-xai2hc{background-color:white;padding:3px;display:grid;grid-template-columns:[name] 1fr [actions] auto}.title.svelte-xai2hc>div.svelte-xai2hc:nth-child(1){grid-column-start:name;color:var(--secondary100)}.title.svelte-xai2hc>div.svelte-xai2hc:nth-child(2){grid-column-start:actions}.section-header.svelte-xai2hc{font-style:italic;color:var(--slate);border-style:solid;border-color:var(--lightslate);border-width:0px 0px 1px 0px}.section-header.svelte-xai2hc{vertical-align:middle;margin-top:20px}
|
|
||||||
.root.svelte-1iwq1b2{padding-bottom:10px;padding-left:10px;font-size:16px;color:var(--secondary50)}.hierarchy-item.svelte-1iwq1b2{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-1iwq1b2:hover{color:var(--secondary75)}.component.svelte-1iwq1b2{margin-left:5px}.selected.svelte-1iwq1b2{color:var(--primary100)}.title.svelte-1iwq1b2{margin-left:10px}
|
|
||||||
.component-preview.svelte-1rf8xuh{display:grid;grid-template-rows:[top] 1fr [middle] auto [bottom] 1fr;grid-template-columns:[left] 1fr [middle] auto [right] 1fr;grid-column-start:preview;height:100%}.component-container.svelte-1rf8xuh{grid-row-start:middle;grid-column-start:middle}
|
|
||||||
h1.svelte-2ukyrk{font-size:1.2em}
|
|
||||||
.root.svelte-is81a4{padding:15px}.help-text.svelte-is81a4{color:var(--slate);font-size:10pt}
|
|
||||||
.section-container.svelte-1t0x31f{padding:15px;border-style:dotted;border-width:1px;border-color:var(--lightslate);border-radius:2px}.section-container.svelte-1t0x31f:nth-child(1){margin-bottom:15px}.row-text.svelte-1t0x31f{margin-right:15px;color:var(--primary100)}input.svelte-1t0x31f{margin-right:15px}p.svelte-1t0x31f>span.svelte-1t0x31f{margin-left:30px}.header.svelte-1t0x31f{display:grid;grid-template-columns:[title] 1fr [icon] auto}.header.svelte-1t0x31f>div.svelte-1t0x31f:nth-child(1){grid-column-start:title}.header.svelte-1t0x31f>div.svelte-1t0x31f:nth-child(2){grid-column-start:icon}
|
|
||||||
.root.svelte-1rctf7f{display:block;font-size:13pt;width:100%;cursor:pointer}.title.svelte-1rctf7f{font:var(--bodytext);padding-top:10px;padding-right:5px;padding-bottom:10px;color:var(--secondary100)}.title.svelte-1rctf7f:hover{background-color:var(--secondary10)}
|
|
||||||
.root.svelte-gq7l8x{height:100%;padding:15px}.fields-table.svelte-gq7l8x{margin:10px;border-collapse:collapse}.add-field-button.svelte-gq7l8x{margin-left:15px;cursor:pointer}.edit-button.svelte-gq7l8x{cursor:pointer;color:var(--white)}.edit-button.svelte-gq7l8x:hover{color:var(--secondary75)}th.svelte-gq7l8x{text-align:left}td.svelte-gq7l8x{padding:5px 30px 5px 0px;margin:0}thead.svelte-gq7l8x>tr.svelte-gq7l8x{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--secondary75);margin-bottom:20px}tbody.svelte-gq7l8x>tr.svelte-gq7l8x{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--primary10)}tbody.svelte-gq7l8x>tr.svelte-gq7l8x:hover{background-color:var(--primary10)}tbody.svelte-gq7l8x>tr:hover .edit-button.svelte-gq7l8x{color:var(--secondary75)}.index-container.svelte-gq7l8x{border-style:solid;border-width:0 0 1px 0;border-color:var(--secondary25);padding:10px;margin-bottom:5px}.index-label.svelte-gq7l8x{color:var(--slate)}.index-name.svelte-gq7l8x{font-weight:bold;color:var(--primary100)}.index-container.svelte-gq7l8x code.svelte-gq7l8x{margin:0;display:inline;background-color:var(--primary10);color:var(--secondary100);padding:3px}.index-field-row.svelte-gq7l8x{margin-top:7px}
|
|
||||||
.root.svelte-1fkfoam{height:100%;padding:15px}.allowed-records.svelte-1fkfoam{margin:20px 0px}.allowed-records.svelte-1fkfoam>span.svelte-1fkfoam{margin-right:30px}
|
|
||||||
.root.svelte-160njkp{padding:5px;top:0;width:100%}
|
|
||||||
.dropdown-background.svelte-179p8ge{position:fixed;top:0;left:0;width:100vw;height:100vh}.root.svelte-179p8ge{cursor:pointer;z-index:1}.dropdown-content.svelte-179p8ge{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.svelte-179p8ge:not(:focus){display:none}.action-row.svelte-179p8ge{padding:7px 10px;cursor:pointer}.action-row.svelte-179p8ge:hover{background-color:var(--primary100);color:var(--white)}
|
|
||||||
.nav-item.svelte-1e0ymco{padding:7px;font-size:12pt;font-weight:bold;cursor:pointer;flex:0 0 auto}.nav-item.svelte-1e0ymco:hover{background-color:var(--primary10)}.active.svelte-1e0ymco{background-color:var(--primary10)}
|
|
||||||
.root.svelte-d6wwkb{display:flex}.root.svelte-d6wwkb:last-child{border-radius:0 var(--borderradius) var(--borderradius) 0}.root.svelte-d6wwkb:first-child{border-radius:var(--borderradius) 0 0 var(--borderradius)}.root.svelte-d6wwkb:not(:first-child):not(:last-child){border-radius:0}
|
|
||||||
.edit-button.svelte-12jzg4k{cursor:pointer;color:var(--white)}tr.svelte-12jzg4k:hover .edit-button.svelte-12jzg4k{color:var(--secondary75)}
|
|
||||||
.edit-button.svelte-1le5bpl{cursor:pointer;color:var(--white)}tr.svelte-1le5bpl:hover .edit-button.svelte-1le5bpl{color:var(--secondary75)}
|
|
||||||
.root.svelte-10avxhq{display:block;font-size:12pt;width:100%;cursor:pointer}.title.svelte-10avxhq{padding-top:5px;padding-right:5px;padding-bottom:5px;color:var(--secondary100)}.title.svelte-10avxhq:hover{background-color:var(--secondary10)}.active.svelte-10avxhq{background-color:var(--primary10)}
|
|
||||||
.root.svelte-beukw7{font-size:10pt}.padding.svelte-beukw7{padding:0 10px}.inherited-title.svelte-beukw7{margin-top:40px;display:grid;grid-template-columns:[name] 1fr [actions] auto;border-style:solid;border-width:0px 0px 1px 0px;border-color:var(--lightslate);font-style:italic}.inherited-title.svelte-beukw7>div.svelte-beukw7:nth-child(1){grid-column-start:name;color:var(--slate)}.inherited-title.svelte-beukw7>div.svelte-beukw7:nth-child(2){grid-column-start:actions;color:var(--secondary100)}
|
|
||||||
.info-text.svelte-um9cf7{font-size:0.8em;color:var(--slate)}
|
|
||||||
.title.svelte-1pp53c5{padding:3px;background-color:white;color:var(--secondary100);border-style:solid;border-width:1px 0 0 0;border-color:var(--lightslate)}.title.svelte-1pp53c5>span.svelte-1pp53c5{margin-left:10px}
|
|
||||||
.component.svelte-13tuzj8{padding:5px;border-style:solid;border-width:0 0 1px 0;border-color:var(--lightslate);cursor:pointer}.component.svelte-13tuzj8:hover{background-color:var(--primary10)}.component.svelte-13tuzj8>.title.svelte-13tuzj8{font-size:13pt;color:var(--secondary100)}.component.svelte-13tuzj8>.description.svelte-13tuzj8{font-size:10pt;color:var(--primary75);font-style:italic}
|
|
||||||
textarea.svelte-1ooq0hh{padding:3px;background:var(--darkslate);color:var(--white);font-family:'Courier New', Courier, monospace;width:95%;height:100px}
|
|
||||||
.error-container.svelte-jwy920{padding:10px;border-style:solid;border-color:var(--deletion100);border-radius:var(--borderradiusall);background:var(--deletion75)}.error-row.svelte-jwy920{padding:5px 0px}
|
|
||||||
input.svelte-66516k{margin-right:7px}
|
|
||||||
.root.svelte-emcy8y{padding:10px}.option-container.svelte-emcy8y{border-style:dotted;border-width:1px;border-color:var(--primary75);padding:3px;margin-right:5px}
|
|
||||||
.root.svelte-woqcuf{display:grid;grid-template-columns:[name] 1fr [actions] auto}.root.svelte-woqcuf>div.svelte-woqcuf:nth-child(1){grid-column-start:name;color:var(--secondary50)}.root.svelte-woqcuf>div.svelte-woqcuf:nth-child(2){grid-column-start:actions}.selectedname.svelte-woqcuf{font-weight:bold;color:var(--secondary)}
|
|
||||||
.root.svelte-w5on8s{padding:3px 5px 7px 10px;border-style:dotted;border-width:0 0 1px 0;border-color:var(--primary25)}
|
|
||||||
textarea.svelte-1wfv4cc{width:300px;height:200px}
|
|
||||||
.addelement-container.svelte-jliz3p{cursor:pointer;padding:3px 0px;text-align:center}.addelement-container.svelte-jliz3p:hover{background-color:var(--primary25)}.item-container.svelte-jliz3p{padding-left:3px;background:var(--secondary10)}
|
|
||||||
|
|
||||||
/*# sourceMappingURL=bundle.css.map */
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.5 KiB |
|
@ -1,61 +1,47 @@
|
||||||
/* latin-ext */
|
/* latin-ext */
|
||||||
|
/* roboto-regular - latin-ext_latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Lato';
|
font-family: 'Roboto';
|
||||||
font-weight: 400;
|
font-style: normal;
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin-ext.woff2) format('woff2');
|
font-weight: 400;
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
src: local('Roboto'), local('Roboto-Regular'),
|
||||||
|
url('/_builder/assets/roboto-v20-latin-ext_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
|
url('/_builder/assets/roboto-v20-latin-ext_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
}
|
}
|
||||||
/* latin */
|
/* roboto-300 - latin-ext_latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Lato';
|
font-family: 'Roboto';
|
||||||
font-weight: 400;
|
font-style: normal;
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin.woff2) format('woff2');
|
font-weight: 300;
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
src: local('Roboto Light'), local('Roboto-Light'),
|
||||||
}
|
url('/_builder/assets/roboto-v20-latin-ext_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
|
url('/_builder/assets/roboto-v20-latin-ext_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
|
}
|
||||||
/* Black latin-ext */
|
/* roboto-500 - latin-ext_latin */
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'Lato Black';
|
font-family: 'Roboto';
|
||||||
font-weight: 900;
|
font-style: normal;
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin-ext.woff2) format('woff2');
|
font-weight: 500;
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
src: local('Roboto Medium'), local('Roboto-Medium'),
|
||||||
}
|
url('/_builder/assets/roboto-v20-latin-ext_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
/* Black latin */
|
url('/_builder/assets/roboto-v20-latin-ext_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
@font-face {
|
}
|
||||||
font-family: 'Lato Black';
|
/* roboto-700 - latin-ext_latin */
|
||||||
font-weight: 900;
|
@font-face {
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin.woff2) format('woff2');
|
font-family: 'Roboto';
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
font-style: normal;
|
||||||
}
|
font-weight: 700;
|
||||||
|
src: local('Roboto Bold'), local('Roboto-Bold'),
|
||||||
/* Bold latin-ext */
|
url('/_builder/assets/roboto-v20-latin-ext_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
@font-face {
|
url('/_builder/assets/roboto-v20-latin-ext_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
font-family: 'Lato Bold';
|
}
|
||||||
font-weight: 700;
|
/* roboto-900 - latin-ext_latin */
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin-ext.woff2) format('woff2');
|
@font-face {
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
font-family: 'Roboto';
|
||||||
}
|
font-style: normal;
|
||||||
/* Bold latin */
|
font-weight: 900;
|
||||||
@font-face {
|
src: local('Roboto Black'), local('Roboto-Black'),
|
||||||
font-family: 'Lato Bold';
|
url('/_builder/assets/roboto-v20-latin-ext_latin-900.woff2') format('woff2'), /* Chrome 26+, Opera 23+, Firefox 39+ */
|
||||||
font-weight: 700;
|
url('/_builder/assets/roboto-v20-latin-ext_latin-900.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin.woff2) format('woff2');
|
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Semi Bold latin-ext */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lato Semi Bold';
|
|
||||||
font-weight: 600;
|
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin-ext.woff2) format('woff2');
|
|
||||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
||||||
}
|
|
||||||
/* Semi Bold latin */
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Lato Semi Bold';
|
|
||||||
font-weight: 600;
|
|
||||||
src: local('Lato Regular'), local('Lato-Regular'), url(/_builder/assets/lato-latin.woff2) format('woff2');
|
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
--primary50: #454CA080;
|
--primary50: #454CA080;
|
||||||
--primary25: #454CA040;
|
--primary25: #454CA040;
|
||||||
--primary10: #454CA01A;
|
--primary10: #454CA01A;
|
||||||
|
--primary5: #454ca00c;
|
||||||
--primarydark: #3F448A;
|
--primarydark: #3F448A;
|
||||||
|
|
||||||
--secondary100: #162B4DFF;
|
--secondary100: #162B4DFF;
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
--secondary50: #162B4D80;
|
--secondary50: #162B4D80;
|
||||||
--secondary25: #162B4D40;
|
--secondary25: #162B4D40;
|
||||||
--secondary10: #162B4D1A;
|
--secondary10: #162B4D1A;
|
||||||
|
--secondary5: rgba(22, 43, 77, 0.068);
|
||||||
--secondarydark: #3F448A;
|
--secondarydark: #3F448A;
|
||||||
|
|
||||||
--tertiary: #F2F5F7;
|
--tertiary: #F2F5F7;
|
||||||
|
@ -30,17 +32,18 @@
|
||||||
--deletiondark: #CF4046;
|
--deletiondark: #CF4046;
|
||||||
|
|
||||||
--white: #FFFFFF;
|
--white: #FFFFFF;
|
||||||
--darkslate: #5C6B82;
|
--darkslate: #1a202c;
|
||||||
--slate: #8B95A6;
|
--slate: #a0aec0;
|
||||||
--lightslate: rgb(203, 212, 228);
|
--lightslate: #f7fafc;
|
||||||
|
|
||||||
--borderradius: 2px;
|
--borderradius: 2px;
|
||||||
--borderradiusall: 2px 2px 2px 2px;
|
--borderradiusall: 2px 2px 2px 2px;
|
||||||
|
|
||||||
--fontblack: "Lato Black";
|
--fontblack: "Roboto Black";
|
||||||
--fontbold: "Lato Bold";
|
--fontbold: "Roboto Bold";
|
||||||
--fontsemibold: "Lato Semi Bold";
|
--fontsemibold: "Roboto Medium";
|
||||||
--fontnormal: "Lato";
|
--fontnormal: "Roboto";
|
||||||
|
--fontlight: "Roboto Light";
|
||||||
|
|
||||||
--bodytext: var(--fontnormal) "regular" var(--secondary100) 16pt;
|
--bodytext: var(--fontnormal) "regular" var(--secondary100) 16pt;
|
||||||
--bigbodytext: var(--fontnormal) "regular" var(--secondary100) 20pt;
|
--bigbodytext: var(--fontnormal) "regular" var(--secondary100) 20pt;
|
||||||
|
@ -79,7 +82,7 @@ h3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
font-family: var(--fontsemibold);
|
font-family: var(--fontbold);
|
||||||
font-size: 18pt;
|
font-size: 18pt;
|
||||||
color: var(--secondary100);
|
color: var(--secondary100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,13 +7,22 @@
|
||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
<link rel='icon' type='image/png' href='{{ favicon }}'>
|
<link rel='icon' type='image/png' href='{{ favicon }}'>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
{{ each(options.stylesheets) }}
|
{{ each(options.stylesheets) }}
|
||||||
<link rel='stylesheet' href='{{ @this }}'>
|
<link rel='stylesheet' href='{{ @this }}'>
|
||||||
{{ /each }}
|
{{ /each }}
|
||||||
|
|
||||||
<script src='{{ appRootPath }}/clientAppDefinition.js'></script>
|
<script src='{{ appRootPath }}/clientAppDefinition.js'></script>
|
||||||
<script src='{{ appRootPath }}/budibase-client.js'></script>
|
<script src='{{ appRootPath }}/budibase-client.js'></script>
|
||||||
|
<script>
|
||||||
|
loadBudibase();
|
||||||
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue