1
0
Fork 0
mirror of synced 2024-07-08 15:56:23 +12:00

moving code from main store to backend file

This commit is contained in:
Martin McKeaveney 2020-03-16 18:54:48 +00:00
parent 4678f2c168
commit db6135e801
15 changed files with 358 additions and 351 deletions

View file

@ -0,0 +1,163 @@
import api from "../api"
import {
filter,
cloneDeep,
sortBy,
find
} from "lodash/fp"
import { hierarchy as hierarchyFunctions } from "../../../../core/src"
import {
pipe,
getNode,
validate,
constructHierarchy,
templateApi,
} from "../../common/core"
import { store } from "../index";
export const createShadowHierarchy = hierarchy =>
constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
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,
})
}
export const newRecord = (store, useRoot) => () => {
store.update(s => {
s.currentNodeIsNew = true
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
const parent = useRoot
? shadowHierarchy
: getNode(shadowHierarchy, s.currentNode.nodeId)
s.errors = []
s.currentNode = templateApi(shadowHierarchy).getNewRecordTemplate(
parent,
"",
true
)
return s
})
}
export const selectExistingNode = store => nodeId => {
store.update(s => {
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
s.currentNode = getNode(shadowHierarchy, nodeId)
s.currentNodeIsNew = false
s.errors = []
return s
})
}
export const newIndex = (store, useRoot) => () => {
store.update(s => {
s.currentNodeIsNew = true
s.errors = []
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
const parent = useRoot
? shadowHierarchy
: getNode(shadowHierarchy, s.currentNode.nodeId)
s.currentNode = templateApi(shadowHierarchy).getNewIndexTemplate(parent)
return s
})
}
// TODO: ONLY SEEMS TO BE CALLED BY THE BACKEND
export const saveCurrentNode = store => () => {
store.update(s => {
const errors = validate.node(s.currentNode)
s.errors = errors
if (errors.length > 0) {
return s
}
const parentNode = getNode(s.hierarchy, s.currentNode.parent().nodeId)
const existingNode = getNode(s.hierarchy, s.currentNode.nodeId)
let index = parentNode.children.length
if (existingNode) {
// remove existing
index = existingNode.parent().children.indexOf(existingNode)
existingNode.parent().children = pipe(existingNode.parent().children, [
filter(c => c.nodeId !== existingNode.nodeId),
])
}
// should add node into existing hierarchy
const cloned = cloneDeep(s.currentNode)
templateApi(s.hierarchy).constructNode(parentNode, cloned)
const newIndexOfChild = child => {
if (child === cloned) return index
const currentIndex = parentNode.children.indexOf(child)
return currentIndex >= index ? currentIndex + 1 : currentIndex
}
parentNode.children = pipe(parentNode.children, [sortBy(newIndexOfChild)])
if (!existingNode && s.currentNode.type === "record") {
const defaultIndex = templateApi(s.hierarchy).getNewIndexTemplate(
cloned.parent()
)
defaultIndex.name = `all_${cloned.collectionName}`
defaultIndex.allowedRecordNodeIds = [cloned.nodeId]
}
s.currentNodeIsNew = false
saveBackend(s)
return s
})
}
export const deleteCurrentNode = store => () => {
store.update(s => {
const nodeToDelete = getNode(s.hierarchy, s.currentNode.nodeId)
s.currentNode = hierarchyFunctions.isRoot(nodeToDelete.parent())
? find(n => n != s.currentNode)(s.hierarchy.children)
: nodeToDelete.parent()
if (hierarchyFunctions.isRecord(nodeToDelete)) {
nodeToDelete.parent().children = filter(
c => c.nodeId !== nodeToDelete.nodeId
)(nodeToDelete.parent().children)
} else {
nodeToDelete.parent().indexes = filter(
c => c.nodeId !== nodeToDelete.nodeId
)(nodeToDelete.parent().indexes)
}
s.errors = []
saveBackend(s)
return s
})
}
export const saveField = databaseStore => field => {
databaseStore.update(db => {
db.currentNode.fields = filter(f => f.name !== field.name)(
db.currentNode.fields
)
templateApi(db.hierarchy).addField(db.currentNode, field)
return db
})
}
export const deleteField = databaseStore => field => {
databaseStore.update(db => {
db.currentNode.fields = filter(f => f.name !== field.name)(
db.currentNode.fields
)
return db
})
}

View file

@ -1,8 +1,7 @@
import { hierarchy as hierarchyFunctions } from "../../../core/src"
import { import {
filter, filter,
cloneDeep, cloneDeep,
sortBy, // sortBy,
map, map,
last, last,
concat, concat,
@ -13,27 +12,28 @@ import {
import { import {
pipe, pipe,
getNode, getNode,
validate, // validate,
constructHierarchy, constructHierarchy,
templateApi, // templateApi,
} from "../common/core" } from "../../common/core"
import * as backendStoreActions from "./backend";
import { writable } from "svelte/store" import { writable } from "svelte/store"
import { defaultPagesObject } from "../userInterface/pagesParsing/defaultPagesObject" import { defaultPagesObject } from "../../userInterface/pagesParsing/defaultPagesObject"
import api from "./api" import api from "../api"
import { getExactComponent } from "../userInterface/pagesParsing/searchComponents" import { getExactComponent } from "../../userInterface/pagesParsing/searchComponents"
import { rename } from "../userInterface/pagesParsing/renameScreen" import { rename } from "../../userInterface/pagesParsing/renameScreen"
import { import {
getNewScreen, getNewScreen,
createProps, createProps,
makePropsSafe, makePropsSafe,
getBuiltin, getBuiltin,
} from "../userInterface/pagesParsing/createProps" } from "../../userInterface/pagesParsing/createProps"
import { expandComponentDefinition } from "../userInterface/pagesParsing/types" import { expandComponentDefinition } from "../../userInterface/pagesParsing/types"
import { loadLibs, libUrlsForPreview } from "./loadComponentLibraries" import { loadLibs, libUrlsForPreview } from "../loadComponentLibraries"
import { buildCodeForScreens } from "./buildCodeForScreens" import { buildCodeForScreens } from "../buildCodeForScreens"
import { generate_screen_css } from "./generate_css" import { generate_screen_css } from "../generate_css"
import { insertCodeMetadata } from "./insertCodeMetadata" import { insertCodeMetadata } from "../insertCodeMetadata"
import { uuid } from "./uuid" import { uuid } from "../uuid"
let appname = "" let appname = ""
@ -121,16 +121,18 @@ export const getStore = () => {
// } // }
store.initialise = initialise(store, initial) store.initialise = initialise(store, initial)
store.newChildRecord = newRecord(store, false)
store.newRootRecord = newRecord(store, true) store.newChildRecord = backendStoreActions.newRecord(store, false)
store.selectExistingNode = selectExistingNode(store) store.newRootRecord = backendStoreActions.newRecord(store, true)
store.newChildIndex = newIndex(store, false) store.selectExistingNode = backendStoreActions.selectExistingNode(store)
store.newRootIndex = newIndex(store, true) store.newChildIndex = backendStoreActions.newIndex(store, false)
store.saveCurrentNode = saveCurrentNode(store) store.newRootIndex = backendStoreActions.newIndex(store, true)
store.saveCurrentNode = backendStoreActions.saveCurrentNode(store)
store.deleteCurrentNode = backendStoreActions.deleteCurrentNode(store)
store.saveField = backendStoreActions.saveField(store)
store.deleteField = backendStoreActions.deleteField(store)
store.importAppDefinition = importAppDefinition(store) store.importAppDefinition = importAppDefinition(store)
store.deleteCurrentNode = deleteCurrentNode(store)
store.saveField = saveField(store)
store.deleteField = deleteField(store)
store.saveAction = saveAction(store) store.saveAction = saveAction(store)
store.deleteAction = deleteAction(store) store.deleteAction = deleteAction(store)
store.saveTrigger = saveTrigger(store) store.saveTrigger = saveTrigger(store)
@ -245,101 +247,12 @@ const showSettings = store => () => {
} }
const useAnalytics = store => () => { const useAnalytics = store => () => {
store.update(s => { store.update(state => {
s.useAnalytics = !s.useAnalytics state.useAnalytics = !s.useAnalytics
return s return state
}) })
} }
const newRecord = (store, useRoot) => () => {
store.update(s => {
s.currentNodeIsNew = true
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
const parent = useRoot
? shadowHierarchy
: getNode(shadowHierarchy, s.currentNode.nodeId)
s.errors = []
s.currentNode = templateApi(shadowHierarchy).getNewRecordTemplate(
parent,
"",
true
)
return s
})
}
const selectExistingNode = store => nodeId => {
store.update(s => {
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
s.currentNode = getNode(shadowHierarchy, nodeId)
s.currentNodeIsNew = false
s.errors = []
return s
})
}
const newIndex = (store, useRoot) => () => {
store.update(s => {
s.currentNodeIsNew = true
s.errors = []
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
const parent = useRoot
? shadowHierarchy
: getNode(shadowHierarchy, s.currentNode.nodeId)
s.currentNode = templateApi(shadowHierarchy).getNewIndexTemplate(parent)
return s
})
}
const saveCurrentNode = store => () => {
store.update(s => {
const errors = validate.node(s.currentNode)
s.errors = errors
if (errors.length > 0) {
return s
}
const parentNode = getNode(s.hierarchy, s.currentNode.parent().nodeId)
const existingNode = getNode(s.hierarchy, s.currentNode.nodeId)
let index = parentNode.children.length
if (existingNode) {
// remove existing
index = existingNode.parent().children.indexOf(existingNode)
existingNode.parent().children = pipe(existingNode.parent().children, [
filter(c => c.nodeId !== existingNode.nodeId),
])
}
// should add node into existing hierarchy
const cloned = cloneDeep(s.currentNode)
templateApi(s.hierarchy).constructNode(parentNode, cloned)
const newIndexOfChild = child => {
if (child === cloned) return index
const currentIndex = parentNode.children.indexOf(child)
return currentIndex >= index ? currentIndex + 1 : currentIndex
}
parentNode.children = pipe(parentNode.children, [sortBy(newIndexOfChild)])
if (!existingNode && s.currentNode.type === "record") {
const defaultIndex = templateApi(s.hierarchy).getNewIndexTemplate(
cloned.parent()
)
defaultIndex.name = `all_${cloned.collectionName}`
defaultIndex.allowedRecordNodeIds = [cloned.nodeId]
}
s.currentNodeIsNew = false
saveBackend(s)
return s
})
}
const importAppDefinition = store => appDefinition => { const importAppDefinition = store => appDefinition => {
store.update(s => { store.update(s => {
@ -355,48 +268,6 @@ const importAppDefinition = store => appDefinition => {
}) })
} }
const deleteCurrentNode = store => () => {
store.update(s => {
const nodeToDelete = getNode(s.hierarchy, s.currentNode.nodeId)
s.currentNode = hierarchyFunctions.isRoot(nodeToDelete.parent())
? find(n => n != s.currentNode)(s.hierarchy.children)
: nodeToDelete.parent()
if (hierarchyFunctions.isRecord(nodeToDelete)) {
nodeToDelete.parent().children = filter(
c => c.nodeId !== nodeToDelete.nodeId
)(nodeToDelete.parent().children)
} else {
nodeToDelete.parent().indexes = filter(
c => c.nodeId !== nodeToDelete.nodeId
)(nodeToDelete.parent().indexes)
}
s.errors = []
saveBackend(s)
return s
})
}
const saveField = databaseStore => field => {
databaseStore.update(db => {
db.currentNode.fields = filter(f => f.name !== field.name)(
db.currentNode.fields
)
templateApi(db.hierarchy).addField(db.currentNode, field)
return db
})
}
const deleteField = databaseStore => field => {
databaseStore.update(db => {
db.currentNode.fields = filter(f => f.name !== field.name)(
db.currentNode.fields
)
return db
})
}
const saveAction = store => (newAction, isNew, oldAction = null) => { const saveAction = store => (newAction, isNew, oldAction = null) => {
store.update(s => { store.update(s => {
const existingAction = isNew const existingAction = isNew
@ -526,32 +397,6 @@ const _saveScreen = async (store, s, screen) => {
return innerState return innerState
}) })
/*const updatedScreen = await savedScreen.json()
const screens = [
...currentPageScreens.filter(
storeScreen => storeScreen.name !== updatedScreen.name
),
updatedScreen,
]
store.update(innerState => {
innerState.pages[s.currentPageName]._screens = screens
innerState.screens = screens
let curentComponentId
walkProps(screen.props, p => {
if(p === innerState.currentComponentInfo)
currentComponentId = p._id
})
innerState.currentPreviewItem = updatedScreen
innerState.currentComponentInfo = makePropsSafe(componentDef, component)
_savePage(innerState)
return innerState
})
*/
}) })
return s return s
@ -761,17 +606,6 @@ const _savePage = async s => {
}) })
} }
const saveBackend = async state => {
await api.post(`/_builder/api/${appname}/backend`, {
appDefinition: {
hierarchy: state.hierarchy,
actions: state.actions,
triggers: state.triggers,
},
accessLevels: state.accessLevels,
})
}
const setCurrentPage = store => pageName => { const setCurrentPage = store => pageName => {
store.update(s => { store.update(s => {
const current_screens = s.pages[pageName]._screens const current_screens = s.pages[pageName]._screens
@ -801,9 +635,6 @@ const setCurrentPage = store => pageName => {
}) })
} }
const getContainerComponent = components =>
getComponentDefinition(components, "@budibase/standard-components/container")
const getComponentDefinition = (components, name) => const getComponentDefinition = (components, name) =>
components.find(c => c.name === name) components.find(c => c.name === name)

View file

@ -14,19 +14,22 @@
confirmDelete = true confirmDelete = true
} }
// const deleteCurrentNode = () => {
// confirmDelete = false
// store.deleteCurrentNode()
// }
// TODO: COMPLETELY REFACTOR THIS SHIT
const deleteCurrentNode = () => { const deleteCurrentNode = () => {
confirmDelete = false confirmDelete = false
store.deleteCurrentNode() store.deleteCurrentNode()
} }
</script> </script>
<div class="root" style="left: {left}"> <div class="root">
<ButtonGroup> <ButtonGroup>
<ActionButton <ActionButton color="secondary" grouped on:click={store.saveCurrentNode}>
color="secondary" Save
grouped
on:click={store.saveCurrentNode}>
{#if $store.currentNodeIsNew}Create{:else}Update{/if}
</ActionButton> </ActionButton>
{#if !$store.currentNodeIsNew} {#if !$store.currentNodeIsNew}

View file

@ -7,61 +7,34 @@
import { store } from "../builderStore" import { store } from "../builderStore"
import getIcon from "../common/icon" import getIcon from "../common/icon"
import DropdownButton from "../common/DropdownButton.svelte" import DropdownButton from "../common/DropdownButton.svelte"
import ActionButton from "../common/ActionButton.svelte"
import Modal from "../common/Modal.svelte" import Modal from "../common/Modal.svelte"
import { hierarchy as hierarchyFunctions } from "../../../core/src" import { CreateEditRecordModal } from "./ModelDataTable/modals"
const hierarchyWidth = "200px" let modalOpen
let selectedRecord
const defaultNewIndexActions = [ function selectRecord(record) {
{ selectedRecord = record
label: "New Root Index", modalOpen = true
onclick: store.newRootIndex, }
},
]
const defaultNewRecordActions = [
{
label: "New Root Record",
onclick: store.newRootRecord,
},
]
let newIndexActions = defaultNewIndexActions
let newRecordActions = defaultNewRecordActions
store.subscribe(db => {
if (!db.currentNode || hierarchyFunctions.isIndex(db.currentNode)) {
newRecordActions = defaultNewRecordActions
newIndexActions = defaultNewIndexActions
} else {
newRecordActions = [
...defaultNewRecordActions,
{
label: `New Child Record of ${db.currentNode.name}`,
onclick: store.newChildRecord,
},
]
newIndexActions = [
...defaultNewIndexActions,
{
label: `New Index on ${db.currentNode.name}`,
onclick: store.newChildIndex,
},
]
}
})
</script> </script>
<CreateEditRecordModal bind:modalOpen record={selectedRecord} />
<!-- <DeleteRecordModal modalOpen={deleteRecordModal} record={selectedRecord} /> -->
<div class="root"> <div class="root">
<!-- <div class="actions-header">
{#if $store.currentNode}
<ActionsHeader />
{/if}
</div> -->
<div class="node-view"> <div class="node-view">
<div class="breadcrumbs">{$store.currentlySelectedDatabase}</div> <div class="breadcrumbs">{$store.currentlySelectedDatabase}</div>
<ModelDataTable /> <ActionButton
primary
on:click={() => {
selectedRecord = null
modalOpen = true
}}>
Create new record
</ActionButton>
<ModelDataTable {selectRecord} />
{#if $store.currentNode} {#if $store.currentNode}
<Modal isOpen={$store.currentNode}> <Modal isOpen={$store.currentNode}>
{#if $store.currentNode.type === 'record'} {#if $store.currentNode.type === 'record'}
@ -82,10 +55,6 @@
position: relative; position: relative;
} }
.actions-header {
flex: 0 1 auto;
}
.node-view { .node-view {
overflow-y: auto; overflow-y: auto;
flex: 1 1 auto; flex: 1 1 auto;

View file

@ -110,11 +110,6 @@
margin-right: 30px; margin-right: 30px;
} }
.index-label {
color: #333;
font-size: 0.875rem;
}
.snippet-selector__heading { .snippet-selector__heading {
margin-right: 20px; margin-right: 20px;
opacity: 0.7; opacity: 0.7;

View file

@ -1,43 +1,53 @@
<script> <script>
import { onMount } from "svelte"
import { store } from "../../builderStore" import { store } from "../../builderStore"
import Select from "../../common/Select.svelte" import Select from "../../common/Select.svelte"
import { CreateEditRecordModal, DeleteRecordModal } from "./modals" import { getIndexSchema } from "../../common/core"
import ActionButton from "../../common/ActionButton.svelte" import ActionButton from "../../common/ActionButton.svelte"
import TablePagination from "./TablePagination.svelte" import TablePagination from "./TablePagination.svelte"
import { DeleteRecordModal } from "./modals"
import * as api from "./api" import * as api from "./api"
import { getIndexSchema } from "../../common/core"
export let selectRecord
let pages = [1, 2, 3] let pages = [1, 2, 3]
export let data = [
{ name: "Joe", inStock: true },
{ name: "Mike", inStock: false },
{ name: "Martin", inStock: true },
]
export let headers = ["name", "inStock"]
// export let pageSize = 10
let selectedView = "" let selectedView = ""
let modalOpen = false let modalOpen = false
let deleteRecordModal = false let deleteRecordModal = false
let data = []
let headers = []
let selectedRecord
$: indexes = $store.hierarchy.indexes $: views = $store.hierarchy.indexes
$: currentAppInfo = {
appname: $store.appname,
instanceId: $store.currentInstanceId
}
const getSchema = getIndexSchema($store.hierarchy) const getSchema = getIndexSchema($store.hierarchy)
async function fetchRecordsForView(viewName) {
const recordsForIndex = await api.fetchDataForView(viewName, currentAppInfo)
data = recordsForIndex
headers = Object.keys(data[0])
}
onMount(async () => {
await fetchRecordsForView(views[0].name, currentAppInfo)
})
</script> </script>
<CreateEditRecordModal bind:modalOpen /> <DeleteRecordModal modalOpen={deleteRecordModal} record={selectedRecord} />
<DeleteRecordModal modalOpen={deleteRecordModal} />
<section> <section>
<div class="table-controls"> <div class="table-controls">
<h4 class="budibase__title--3">Shoe database</h4> <h4 class="budibase__title--3">Shoe database</h4>
<Select <Select
icon="ri-eye-line" icon="ri-eye-line"
on:change={e => api.fetchDataForView(e.target.value)}> on:change={e => fetchRecordsForView(e.target.value)}>
{#each indexes as index} {#each views as view}
({console.log(getSchema(index))}) <!-- ({console.log(getSchema(view))}) ({console.log(view)}) -->
<option value={index.name}>{index.name}</option> <option value={view.name}>{view.name}</option>
{/each} {/each}
</Select> </Select>
</div> </div>
@ -61,11 +71,18 @@
<li> <li>
<div>View</div> <div>View</div>
</li> </li>
<li> <li
<div on:click={() => (modalOpen = true)}>Edit</div> on:click={() => selectRecord(row)}>
<div>Edit</div>
</li> </li>
<li> <li>
<div on:click={() => (deleteRecordModal = true)}>Delete</div> <div
on:click={() => {
deleteRecordModal = true
selectedRecord = row
}}>
Delete
</div>
</li> </li>
<li> <li>
<div>Duplicate</div> <div>Duplicate</div>
@ -111,7 +128,8 @@
align-items: center; align-items: center;
} }
.ri-more-line:hover, .uk-dropdown-nav li:hover{ .ri-more-line:hover,
.uk-dropdown-nav li:hover {
cursor: pointer; cursor: pointer;
} }
</style> </style>

View file

@ -1,24 +1,26 @@
import api from "../../builderStore/api"; import api from "../../builderStore/api";
import { getNewRecord } from "../../common/core"
export async function deleteRecord(appName, appInstanceId, record) { export async function deleteRecord(record, { appname, instanceId }) {
const DELETE_RECORDS_URL = `/_builder/instance/${appName}/${appInstanceId}/api/record/${record.name}/${record.id}` const DELETE_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/record/${record.name}/${record.id}`
const response = await api.delete({ const response = await api.delete({
url: DELETE_RECORDS_URL url: DELETE_RECORDS_URL
}); });
return response;
} }
export async function createNewRecord(record) { export async function saveRecord(record, { appname, instanceId }) {
console.log(record); const SAVE_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/record`
const updatedRecord = getNewRecord(record, "")
const response = await api.post(SAVE_RECORDS_URL, updatedRecord)
return response
} }
export async function fetchDataForView(viewName) { export async function fetchDataForView(viewName, { appname, instanceId }) {
console.log(viewName); const FETCH_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/listRecords/${viewName}`;
// const FETCH_RECORDS_URL = `/_builder/instance/${}/${}/api/listRecords/`
// const response = await api.get({ url: FETCH_RECORDS_URL }); // TODO: Error handling
const response = await api.get(FETCH_RECORDS_URL);
// console.log(response); return await response.json();
// GET /_builder/instance/:appname/:instanceid/api/listRecords/contacts/abcd1234/all_deals
} }

View file

@ -11,7 +11,7 @@
</script> </script>
<Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}> <Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}>
<h4 class="budibase__title--4">Create / Edit Record</h4> <h4 class="budibase__title--4">Create / Edit Model</h4>
<div class="actions"> <div class="actions">
<ActionButton alert on:click={onClosed}>Cancel</ActionButton> <ActionButton alert on:click={onClosed}>Cancel</ActionButton>
<ActionButton <ActionButton

View file

@ -1,60 +1,84 @@
<script> <script>
import { onMount } from "svelte"
import { store } from "../../../builderStore"
import Modal from "../../../common/Modal.svelte" import Modal from "../../../common/Modal.svelte"
import ActionButton from "../../../common/ActionButton.svelte" import ActionButton from "../../../common/ActionButton.svelte"
import Select from "../../../common/Select.svelte"
import * as api from "../api" import * as api from "../api"
export let modalOpen = false export let modalOpen = false
export let model = {} export let record
let selectedModel
$: currentAppInfo = {
instanceId: $store.currentInstanceId,
appname: $store.appname,
}
$: recordFields = record ? Object.keys(record) : []
$: models = $store.hierarchy.children
$: modelFields = selectedModel
? selectedModel.fields.map(({ name }) => name)
: []
const onClosed = () => (modalOpen = false) const onClosed = () => (modalOpen = false)
</script> </script>
<Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}> <Modal {onClosed} isOpen={modalOpen}>
<h4 class="budibase__title--4">Create / Edit Record</h4> <h4 class="budibase__title--4">Create / Edit Record</h4>
<div class="actions"> <div class="actions">
<form> {console.log('record', record)}
<div class="uk-margin"> {console.log('selectedModel', selectedModel)}
<label class="uk-form-label" for="form-stacked-text">Text</label> {console.log('recordFields', recordFields)}
<div class="uk-form-controls"> <form class="uk-form-stacked">
<input {#if !record}
class="uk-input" <div class="uk-margin">
id="form-stacked-text" <label class="uk-form-label" for="form-stacked-text">Model</label>
type="text" <Select bind:value={selectedModel}>
placeholder="Some text..." /> {#each models as model}
<option value={model}>{model.name}</option>
{/each}
</Select>
</div> </div>
</div> {/if}
{#each modelFields as field}
<div class="uk-margin"> <div class="uk-margin">
<label class="uk-form-label" for="form-stacked-select">Select</label> <label class="uk-form-label" for="form-stacked-text">{field}</label>
<div class="uk-form-controls"> <div class="uk-form-controls">
<select class="uk-select" id="form-stacked-select"> <input
<option>Option 01</option> class="uk-input"
<option>Option 02</option> id="form-stacked-text"
</select> type="text"
bind:value={selectedModel[field]} />
</div>
</div> </div>
</div> {/each}
{#each recordFields as field}
<div class="uk-margin"> <div class="uk-margin">
<div class="uk-form-label">Radio</div> <label class="uk-form-label" for="form-stacked-text">{field}</label>
<div class="uk-form-controls"> <div class="uk-form-controls">
<label> <input
<input class="uk-radio" type="radio" name="radio1" /> class="uk-input"
Option 01 id="form-stacked-text"
</label> type="text"
<br /> bind:value={record[field]} />
<label> </div>
<input class="uk-radio" type="radio" name="radio1" />
Option 02
</label>
</div> </div>
</div> {/each}
</form> </form>
<ActionButton alert on:click={onClosed}>Cancel</ActionButton> <div class="actions">
<ActionButton <ActionButton alert on:click={onClosed}>Cancel</ActionButton>
disabled={false} <ActionButton
on:click={() => api.createNewRecord(recordInfo)}> disabled={false}
Save on:click={() => api.saveRecord(record || selectedModel, currentAppInfo)}>
</ActionButton> Save
</ActionButton>
</div>
</div> </div>
</Modal> </Modal>
<style>
.actions {
position: absolute;
}
</style>

View file

@ -4,20 +4,22 @@
import * as api from "../api" import * as api from "../api"
export let modalOpen = false export let modalOpen = false
export let record
let recordInfo = {}
const onClosed = () => (modalOpen = false) const onClosed = () => (modalOpen = false)
</script> </script>
<Modal {onClosed} bind:isOpen={modalOpen} title={"Delete Record?"}> <Modal {onClosed} bind:isOpen={modalOpen}>
<h4 class="budibase__title--4">Delete Record</h4> <h4 class="budibase__title--4">Delete Record</h4>
Are you sure you want to delete this record? All of your data will be permanently removed. This action cannot be undone. Are you sure you want to delete this record? All of your data will be permanently removed. This action cannot be undone.
<div class="modal-actions"> <div class="modal-actions">
<ActionButton on:click={onClosed}>Cancel</ActionButton> <ActionButton on:click={onClosed}>Cancel</ActionButton>
<ActionButton <ActionButton
alert alert
on:click={() => api.deleteRecord(recordInfo)}> on:click={async () => {
await api.deleteRecord(record)
onClosed();
}}>
Delete Delete
</ActionButton> </ActionButton>
</div> </div>

View file

@ -139,7 +139,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{#each record.fields as field} {#each record ? record.fields : [] as field}
<tr> <tr>
<td> <td>
<i class="ri-more-line" on:click={() => editField(field)} /> <i class="ri-more-line" on:click={() => editField(field)} />
@ -150,9 +150,6 @@
<td>{field.type}</td> <td>{field.type}</td>
<td>({console.log(field.typeOptions)}) {field.typeOptions.values}</td> <td>({console.log(field.typeOptions)}) {field.typeOptions.values}</td>
<td> <td>
<!-- <span class="edit-button" on:click={() => editField(field)}>
{@html getIcon('edit')}
</span> -->
<span class="edit-button" on:click={() => deleteField(field)}> <span class="edit-button" on:click={() => deleteField(field)}>
{@html getIcon('trash')} {@html getIcon('trash')}
</span> </span>

View file

@ -1,5 +1,4 @@
<script> <script>
import { navigate } from "svelte-routing"
import { store } from "../builderStore" import { store } from "../builderStore"
import getIcon from "../common/icon" import getIcon from "../common/icon"
import { CheckIcon } from "../common/Icons" import { CheckIcon } from "../common/Icons"
@ -11,7 +10,6 @@
state.currentlySelectedDatabase = databaseId state.currentlySelectedDatabase = databaseId
return state return state
}) })
navigate("/database", { replace: true })
} }
</script> </script>

View file

@ -71,13 +71,13 @@
<div class="nav-group-header"> <div class="nav-group-header">
<div class="hierarchy-title">Schema</div> <div class="hierarchy-title">Schema</div>
<div class="uk-inline"> <div class="uk-inline">
<i class="ri-add-line" /> <i class="ri-add-line hoverable" />
<div uk-dropdown="mode: click"> <div uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav"> <ul class="uk-nav uk-dropdown-nav">
<li> <li class="hoverable" on:click={() => {}}>
Model Model
</li> </li>
<li> <li class="hoverable" on:click={() => {}}>
View View
</li> </li>
</ul> </ul>

View file

@ -22,6 +22,11 @@ export const getNew = app => (collectionKey, recordTypeName) => {
) )
} }
/**
* Constructs a record object that can be saved to the backend.
* @param {*} recordNode - record
* @param {*} collectionKey - nested collection key that the record will be saved to.
*/
export const _getNew = (recordNode, collectionKey) => export const _getNew = (recordNode, collectionKey) =>
constructRecord(recordNode, getNewFieldValue, collectionKey) constructRecord(recordNode, getNewFieldValue, collectionKey)