added model props

This commit is contained in:
Martin McKeaveney 2020-05-07 14:59:06 +01:00
parent a28322f538
commit 96a1bc52de
14 changed files with 131 additions and 77 deletions

View File

@ -80,15 +80,4 @@ export const createDatabaseForApp = store => appInstance => {
state.appInstances.push(appInstance) state.appInstances.push(appInstance)
return state return state
}) })
} }
export const saveBackend = async state => {
await api.post(`/_builder/api/${state.appname}/backend`, {
appDefinition: {
hierarchy: state.hierarchy,
actions: state.actions,
triggers: state.triggers,
},
accessLevels: state.accessLevels,
})
}

View File

@ -24,7 +24,6 @@ export const getStore = () => {
const initial = { const initial = {
apps: [], apps: [],
appname: "", appname: "",
hierarchy: {},
pages: DEFAULT_PAGES_OBJECT, pages: DEFAULT_PAGES_OBJECT,
mainUi: {}, mainUi: {},
unauthenticatedUi: {}, unauthenticatedUi: {},
@ -44,14 +43,7 @@ export const getStore = () => {
store.setPackage = setPackage(store, initial) store.setPackage = setPackage(store, initial)
// store.saveLevel = backendStoreActions.saveLevel(store)
// store.deleteLevel = backendStoreActions.deleteLevel(store)
store.createDatabaseForApp = backendStoreActions.createDatabaseForApp(store) store.createDatabaseForApp = backendStoreActions.createDatabaseForApp(store)
// store.saveAction = backendStoreActions.saveAction(store)
// store.deleteAction = backendStoreActions.deleteAction(store)
// store.saveTrigger = backendStoreActions.saveTrigger(store)
// store.deleteTrigger = backendStoreActions.deleteTrigger(store)
// store.importAppDefinition = importAppDefinition(store)
store.saveScreen = saveScreen(store) store.saveScreen = saveScreen(store)
store.renameScreen = renameScreen(store) store.renameScreen = renameScreen(store)
@ -364,7 +356,7 @@ const addChildComponent = store => (componentToAdd, presetName) => {
: state.components[componentToAdd] : state.components[componentToAdd]
const presetProps = presetName ? component.presets[presetName] : {} const presetProps = presetName ? component.presets[presetName] : {}
const newComponent = createProps(component, presetProps) const newComponent = createProps(component, presetProps, state)
state.currentComponentInfo._children = state.currentComponentInfo._children.concat( state.currentComponentInfo._children = state.currentComponentInfo._children.concat(
newComponent.props newComponent.props

View File

@ -80,15 +80,6 @@
currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE
) )
function drillIntoRecord(record) {
backendUiStore.update(state => {
state.breadcrumbs = [...state.breadcrumbs, record.type, record.id]
state.selectedRecord = record
state.selectedView = childViewsForRecord($store.hierarchy)[0]
return state
})
}
onMount(() => { onMount(() => {
if (views.length) { if (views.length) {
backendUiStore.actions.views.select(views[0]) backendUiStore.actions.views.select(views[0])

View File

@ -20,10 +20,6 @@
$: instanceId = $backendUiStore.selectedDatabase.id $: instanceId = $backendUiStore.selectedDatabase.id
$: models = $backendUiStore.selectedRecord
? childModelsForModel($store.hierarchy)
: $store.hierarchy.children
$: modelSchema = $backendUiStore.selectedModel $: modelSchema = $backendUiStore.selectedModel
? Object.entries($backendUiStore.selectedModel.schema) ? Object.entries($backendUiStore.selectedModel.schema)
: [] : []
@ -65,16 +61,6 @@
<h4 class="budibase__title--4">Create / Edit Record</h4> <h4 class="budibase__title--4">Create / Edit Record</h4>
<ErrorsBox {errors} /> <ErrorsBox {errors} />
<form on:submit|preventDefault class="uk-form-stacked"> <form on:submit|preventDefault class="uk-form-stacked">
{#if !record}
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Model</label>
<Select bind:value={selectedModel}>
{#each models as model}
<option value={model}>{model.name}</option>
{/each}
</Select>
</div>
{/if}
{#each modelSchema as [key, meta]} {#each modelSchema as [key, meta]}
<div class="uk-margin"> <div class="uk-margin">
<RecordFieldControl <RecordFieldControl

View File

@ -6,7 +6,6 @@
import { CheckIcon } from "../common/Icons" import { CheckIcon } from "../common/Icons"
$: instances = $store.appInstances $: instances = $store.appInstances
// $: views = $store.hierarchy.indexes
async function selectDatabase(database) { async function selectDatabase(database) {
backendUiStore.actions.database.select(database) backendUiStore.actions.database.select(database)

View File

@ -20,7 +20,7 @@
<h5>{prop_name}</h5> <h5>{prop_name}</h5>
<StateBindingControl <StateBindingControl
value={prop_value} value={prop_value}
type={prop_definition.type} type={prop_definition.type || prop_definition}
options={prop_definition.options} options={prop_definition.options}
styleBindingProperty={prop_definition.styleBindingProperty} styleBindingProperty={prop_definition.styleBindingProperty}
onChanged={v => setProp(prop_name, v)} /> onChanged={v => setProp(prop_name, v)} />

View File

@ -1,4 +1,5 @@
<script> <script>
import { backendUiStore } from "builderStore";
import IconButton from "../common/IconButton.svelte" import IconButton from "../common/IconButton.svelte"
import Input from "../common/Input.svelte" import Input from "../common/Input.svelte"
import PropertyCascader from "./PropertyCascader" import PropertyCascader from "./PropertyCascader"
@ -22,7 +23,16 @@
size="19" size="19"
on:click={() => onChanged(!value)} /> on:click={() => onChanged(!value)} />
</div> </div>
{:else if type === 'options'} {:else if type === 'models'}
<select
class="uk-select uk-form-small"
{value}
on:change={ev => onChanged(ev.target.value)}>
{#each $backendUiStore.models || [] as option}
<option value={`all_${option._id}`}>{option.name}</option>
{/each}
</select>
{:else if type === 'options' || type === 'models'}
<select <select
class="uk-select uk-form-small" class="uk-select uk-form-small"
{value} {value}

View File

@ -26,12 +26,14 @@ export const createProps = (componentDefinition, derivedFromProps) => {
_component: componentDefinition._component, _component: componentDefinition._component,
_styles: { position: {}, layout: {} }, _styles: { position: {}, layout: {} },
_code: "", _code: "",
_instanceId: "dev-1" // TODO fix
} }
const errors = [] const errors = []
if (!componentDefinition.name) if (!componentDefinition._component) {
errorOccurred("_component", "Component name not supplied") errorOccurred("_component", "Component name not supplied")
}
for (let propName in componentDefinition.props) { for (let propName in componentDefinition.props) {
const parsedPropDef = parsePropDef(componentDefinition.props[propName]) const parsedPropDef = parsePropDef(componentDefinition.props[propName])
@ -93,10 +95,3 @@ const parsePropDef = propDef => {
export const arrayElementComponentName = (parentComponentName, arrayPropName) => export const arrayElementComponentName = (parentComponentName, arrayPropName) =>
`${parentComponentName}:${arrayPropName}` `${parentComponentName}:${arrayPropName}`
/*
Allowed propDefOptions
- type: string, bool, number, array
- default: default value, when undefined
- required: field is required
*/

View File

@ -20,4 +20,7 @@ export const TYPE_MAP = {
"##bbstate": "", "##bbstate": "",
}, },
}, },
models: {
default: [],
}
} }

View File

@ -4,7 +4,6 @@
import { onMount } from "svelte" import { onMount } from "svelte"
$: instances = $store.appInstances $: instances = $store.appInstances
$: views = $store.hierarchy.indexes
async function selectDatabase(database) { async function selectDatabase(database) {
backendUiStore.actions.database.select(database) backendUiStore.actions.database.select(database)

View File

@ -16,7 +16,6 @@
import { AddIcon } from "components/common/Icons" import { AddIcon } from "components/common/Icons"
$: instances = $store.appInstances $: instances = $store.appInstances
$: views = $store.hierarchy.indexes
async function selectDatabase(database) { async function selectDatabase(database) {
backendUiStore.actions.database.select(database) backendUiStore.actions.database.select(database)

View File

@ -264,23 +264,16 @@
}, },
"datatable": { "datatable": {
"description": "an HTML table that fetches data from a model or view and displays it.", "description": "an HTML table that fetches data from a model or view and displays it.",
"data": true,
"props": { "props": {
"_instanceId": "string", "model": "models"
"model": {
"type": "options",
"default": "",
"options": [
"all_6dc86335-83b7-462c-90ca-1fe7feb08942",
"all_fcd00735-01f0-451c-819e-902a3ea53c26"
]
}
} }
}, },
"dataform": { "dataform": {
"description": "an HTML table that fetches data from a model or view and displays it.", "description": "an HTML table that fetches data from a model or view and displays it.",
"data": true,
"props": { "props": {
"_viewName": "string", "model": "models"
"_instanceId": "string"
} }
}, },
"link": { "link": {

View File

@ -0,0 +1,99 @@
<script>
import { onMount } from "svelte"
export let _bb
export let onLoad
export let _instanceId
export let model
let cssVariables
let headers = []
let data = []
async function fetchData() {
const FETCH_RECORDS_URL = `/api/${_instanceId}/${model}/records`
const response = await _bb.api.get(FETCH_RECORDS_URL)
if (response.status === 200) {
const json = await response.json()
data = json
} else {
throw new Error("Failed to fetch records.", response)
}
}
onMount(async () => {
await fetchData()
})
</script>
<!-- This prop was in the old one -->
<!-- use:cssVars={cssVariables} -->
<table class="uk-table">
<thead>
<tr>
{#each headers as header}
<th>{header}</th>
{/each}
</tr>
</thead>
<tbody>
{#each data as row}
<tr>
{#each headers as header}
{#if row[header]}
<td>{row[header]}</td>
{/if}
{/each}
</tr>
{/each}
</tbody>
</table>
<!-- <button
bind:this={theButton}
use:cssVars={cssVariables}
class="{className}
{customClasses}"
disabled={disabled || false}
on:click={clickHandler}
style={buttonStyles}>
{#if !_bb.props._children || _bb.props._children.length === 0}
{contentText}
{/if}
</button> -->
<style>
table {
border: 1px solid #ccc;
background: #fff;
border-radius: 3px;
border-collapse: collapse;
}
thead {
background: #f9f9f9;
border: 1px solid #ccc;
}
thead th {
color: var(--button-text);
text-transform: capitalize;
font-weight: 500;
font-size: 14px;
text-rendering: optimizeLegibility;
letter-spacing: 1px;
}
tbody tr {
border-bottom: 1px solid #ccc;
transition: 0.3s background-color;
color: var(--secondary100);
font-size: 14px;
}
tbody tr:hover {
background: #fafafa;
}
</style>

View File

@ -9,29 +9,28 @@
const fs = require("fs") const fs = require("fs")
const { resolve } = require("path") const { resolve } = require("path")
const rimraf = require("rimraf");
const devDir = "/tmp/.budibase/@budibase" const devDir = "/tmp/.budibase"
// create the dev directory if it doesn't exist rimraf.sync(devDir);
if (!fs.existsSync(devDir)) { fs.mkdirSync(`${devDir}/@budibase`, { recursive: true })
fs.mkdirSync(devDir, { recursive: true })
}
const SYMLINK_PATHS = [ const SYMLINK_PATHS = [
{ {
symlink: "/tmp/.budibase/@budibase/materialdesign-components", symlink: `${devDir}/@budibase/materialdesign-components`,
destination: resolve("packages/materialdesign-components"), destination: resolve("packages/materialdesign-components"),
}, },
{ {
symlink: "/tmp/.budibase/@budibase/standard-components", symlink: `${devDir}/@budibase/standard-components`,
destination: resolve("packages/standard-components"), destination: resolve("packages/standard-components"),
}, },
{ {
symlink: "/tmp/.budibase/budibase-client.esm.mjs", symlink: `${devDir}/budibase-client.esm.mjs`,
destination: resolve("packages/client/dist/budibase-client.esm.mjs"), destination: resolve("packages/client/dist/budibase-client.esm.mjs"),
}, },
{ {
symlink: "/tmp/.budibase/budibase-client.js", symlink: `${devDir}/budibase-client.js`,
destination: resolve("packages/client/dist/budibase-client.js"), destination: resolve("packages/client/dist/budibase-client.js"),
}, },
] ]