moving code from main store to backend file
This commit is contained in:
parent
8cb49fb27e
commit
fa95ba2d79
|
@ -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
|
||||
})
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
import { hierarchy as hierarchyFunctions } from "../../../core/src"
|
||||
import {
|
||||
filter,
|
||||
cloneDeep,
|
||||
sortBy,
|
||||
// sortBy,
|
||||
map,
|
||||
last,
|
||||
concat,
|
||||
|
@ -13,27 +12,28 @@ import {
|
|||
import {
|
||||
pipe,
|
||||
getNode,
|
||||
validate,
|
||||
// validate,
|
||||
constructHierarchy,
|
||||
templateApi,
|
||||
} from "../common/core"
|
||||
// templateApi,
|
||||
} from "../../common/core"
|
||||
import * as backendStoreActions from "./backend";
|
||||
import { writable } from "svelte/store"
|
||||
import { defaultPagesObject } from "../userInterface/pagesParsing/defaultPagesObject"
|
||||
import api from "./api"
|
||||
import { getExactComponent } from "../userInterface/pagesParsing/searchComponents"
|
||||
import { rename } from "../userInterface/pagesParsing/renameScreen"
|
||||
import { defaultPagesObject } from "../../userInterface/pagesParsing/defaultPagesObject"
|
||||
import api from "../api"
|
||||
import { getExactComponent } from "../../userInterface/pagesParsing/searchComponents"
|
||||
import { rename } from "../../userInterface/pagesParsing/renameScreen"
|
||||
import {
|
||||
getNewScreen,
|
||||
createProps,
|
||||
makePropsSafe,
|
||||
getBuiltin,
|
||||
} from "../userInterface/pagesParsing/createProps"
|
||||
import { expandComponentDefinition } from "../userInterface/pagesParsing/types"
|
||||
import { loadLibs, libUrlsForPreview } from "./loadComponentLibraries"
|
||||
import { buildCodeForScreens } from "./buildCodeForScreens"
|
||||
import { generate_screen_css } from "./generate_css"
|
||||
import { insertCodeMetadata } from "./insertCodeMetadata"
|
||||
import { uuid } from "./uuid"
|
||||
} from "../../userInterface/pagesParsing/createProps"
|
||||
import { expandComponentDefinition } from "../../userInterface/pagesParsing/types"
|
||||
import { loadLibs, libUrlsForPreview } from "../loadComponentLibraries"
|
||||
import { buildCodeForScreens } from "../buildCodeForScreens"
|
||||
import { generate_screen_css } from "../generate_css"
|
||||
import { insertCodeMetadata } from "../insertCodeMetadata"
|
||||
import { uuid } from "../uuid"
|
||||
|
||||
let appname = ""
|
||||
|
||||
|
@ -121,16 +121,18 @@ export const getStore = () => {
|
|||
// }
|
||||
|
||||
store.initialise = initialise(store, initial)
|
||||
store.newChildRecord = newRecord(store, false)
|
||||
store.newRootRecord = newRecord(store, true)
|
||||
store.selectExistingNode = selectExistingNode(store)
|
||||
store.newChildIndex = newIndex(store, false)
|
||||
store.newRootIndex = newIndex(store, true)
|
||||
store.saveCurrentNode = saveCurrentNode(store)
|
||||
|
||||
store.newChildRecord = backendStoreActions.newRecord(store, false)
|
||||
store.newRootRecord = backendStoreActions.newRecord(store, true)
|
||||
store.selectExistingNode = backendStoreActions.selectExistingNode(store)
|
||||
store.newChildIndex = backendStoreActions.newIndex(store, false)
|
||||
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.deleteCurrentNode = deleteCurrentNode(store)
|
||||
store.saveField = saveField(store)
|
||||
store.deleteField = deleteField(store)
|
||||
|
||||
store.saveAction = saveAction(store)
|
||||
store.deleteAction = deleteAction(store)
|
||||
store.saveTrigger = saveTrigger(store)
|
||||
|
@ -245,101 +247,12 @@ const showSettings = store => () => {
|
|||
}
|
||||
|
||||
const useAnalytics = store => () => {
|
||||
store.update(s => {
|
||||
s.useAnalytics = !s.useAnalytics
|
||||
return s
|
||||
store.update(state => {
|
||||
state.useAnalytics = !s.useAnalytics
|
||||
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 => {
|
||||
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) => {
|
||||
store.update(s => {
|
||||
const existingAction = isNew
|
||||
|
@ -526,32 +397,6 @@ const _saveScreen = async (store, s, screen) => {
|
|||
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
|
||||
|
@ -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 => {
|
||||
store.update(s => {
|
||||
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) =>
|
||||
components.find(c => c.name === name)
|
||||
|
|
@ -14,19 +14,22 @@
|
|||
confirmDelete = true
|
||||
}
|
||||
|
||||
// const deleteCurrentNode = () => {
|
||||
// confirmDelete = false
|
||||
// store.deleteCurrentNode()
|
||||
// }
|
||||
|
||||
// TODO: COMPLETELY REFACTOR THIS SHIT
|
||||
const deleteCurrentNode = () => {
|
||||
confirmDelete = false
|
||||
store.deleteCurrentNode()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="root" style="left: {left}">
|
||||
<div class="root">
|
||||
<ButtonGroup>
|
||||
<ActionButton
|
||||
color="secondary"
|
||||
grouped
|
||||
on:click={store.saveCurrentNode}>
|
||||
{#if $store.currentNodeIsNew}Create{:else}Update{/if}
|
||||
<ActionButton color="secondary" grouped on:click={store.saveCurrentNode}>
|
||||
Save
|
||||
</ActionButton>
|
||||
|
||||
{#if !$store.currentNodeIsNew}
|
||||
|
|
|
@ -7,61 +7,34 @@
|
|||
import { store } from "../builderStore"
|
||||
import getIcon from "../common/icon"
|
||||
import DropdownButton from "../common/DropdownButton.svelte"
|
||||
import ActionButton from "../common/ActionButton.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 = [
|
||||
{
|
||||
label: "New Root Index",
|
||||
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,
|
||||
},
|
||||
]
|
||||
function selectRecord(record) {
|
||||
selectedRecord = record
|
||||
modalOpen = true
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<CreateEditRecordModal bind:modalOpen record={selectedRecord} />
|
||||
<!-- <DeleteRecordModal modalOpen={deleteRecordModal} record={selectedRecord} /> -->
|
||||
|
||||
<div class="root">
|
||||
<!-- <div class="actions-header">
|
||||
{#if $store.currentNode}
|
||||
<ActionsHeader />
|
||||
{/if}
|
||||
</div> -->
|
||||
<div class="node-view">
|
||||
<div class="breadcrumbs">{$store.currentlySelectedDatabase}</div>
|
||||
<ModelDataTable />
|
||||
<ActionButton
|
||||
primary
|
||||
on:click={() => {
|
||||
selectedRecord = null
|
||||
modalOpen = true
|
||||
}}>
|
||||
Create new record
|
||||
</ActionButton>
|
||||
<ModelDataTable {selectRecord} />
|
||||
{#if $store.currentNode}
|
||||
<Modal isOpen={$store.currentNode}>
|
||||
{#if $store.currentNode.type === 'record'}
|
||||
|
@ -82,10 +55,6 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.actions-header {
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
.node-view {
|
||||
overflow-y: auto;
|
||||
flex: 1 1 auto;
|
||||
|
|
|
@ -110,11 +110,6 @@
|
|||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.index-label {
|
||||
color: #333;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
.snippet-selector__heading {
|
||||
margin-right: 20px;
|
||||
opacity: 0.7;
|
||||
|
|
|
@ -1,43 +1,53 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { store } from "../../builderStore"
|
||||
import Select from "../../common/Select.svelte"
|
||||
import { CreateEditRecordModal, DeleteRecordModal } from "./modals"
|
||||
import { getIndexSchema } from "../../common/core"
|
||||
import ActionButton from "../../common/ActionButton.svelte"
|
||||
import TablePagination from "./TablePagination.svelte"
|
||||
import { DeleteRecordModal } from "./modals"
|
||||
import * as api from "./api"
|
||||
import { getIndexSchema } from "../../common/core"
|
||||
|
||||
export let selectRecord
|
||||
|
||||
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 modalOpen = 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)
|
||||
|
||||
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>
|
||||
|
||||
<CreateEditRecordModal bind:modalOpen />
|
||||
<DeleteRecordModal modalOpen={deleteRecordModal} />
|
||||
<DeleteRecordModal modalOpen={deleteRecordModal} record={selectedRecord} />
|
||||
|
||||
<section>
|
||||
<div class="table-controls">
|
||||
<h4 class="budibase__title--3">Shoe database</h4>
|
||||
<Select
|
||||
icon="ri-eye-line"
|
||||
on:change={e => api.fetchDataForView(e.target.value)}>
|
||||
{#each indexes as index}
|
||||
({console.log(getSchema(index))})
|
||||
<option value={index.name}>{index.name}</option>
|
||||
on:change={e => fetchRecordsForView(e.target.value)}>
|
||||
{#each views as view}
|
||||
<!-- ({console.log(getSchema(view))}) ({console.log(view)}) -->
|
||||
<option value={view.name}>{view.name}</option>
|
||||
{/each}
|
||||
</Select>
|
||||
</div>
|
||||
|
@ -61,11 +71,18 @@
|
|||
<li>
|
||||
<div>View</div>
|
||||
</li>
|
||||
<li>
|
||||
<div on:click={() => (modalOpen = true)}>Edit</div>
|
||||
<li
|
||||
on:click={() => selectRecord(row)}>
|
||||
<div>Edit</div>
|
||||
</li>
|
||||
<li>
|
||||
<div on:click={() => (deleteRecordModal = true)}>Delete</div>
|
||||
<div
|
||||
on:click={() => {
|
||||
deleteRecordModal = true
|
||||
selectedRecord = row
|
||||
}}>
|
||||
Delete
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<div>Duplicate</div>
|
||||
|
@ -111,7 +128,8 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.ri-more-line:hover, .uk-dropdown-nav li:hover{
|
||||
.ri-more-line:hover,
|
||||
.uk-dropdown-nav li:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,24 +1,26 @@
|
|||
import api from "../../builderStore/api";
|
||||
import { getNewRecord } from "../../common/core"
|
||||
|
||||
export async function deleteRecord(appName, appInstanceId, record) {
|
||||
const DELETE_RECORDS_URL = `/_builder/instance/${appName}/${appInstanceId}/api/record/${record.name}/${record.id}`
|
||||
export async function deleteRecord(record, { appname, instanceId }) {
|
||||
const DELETE_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/record/${record.name}/${record.id}`
|
||||
const response = await api.delete({
|
||||
url: DELETE_RECORDS_URL
|
||||
});
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function createNewRecord(record) {
|
||||
console.log(record);
|
||||
export async function saveRecord(record, { appname, instanceId }) {
|
||||
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) {
|
||||
console.log(viewName);
|
||||
// const FETCH_RECORDS_URL = `/_builder/instance/${}/${}/api/listRecords/`
|
||||
export async function fetchDataForView(viewName, { appname, instanceId }) {
|
||||
const FETCH_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/listRecords/${viewName}`;
|
||||
|
||||
// const response = await api.get({ url: FETCH_RECORDS_URL });
|
||||
|
||||
// console.log(response);
|
||||
|
||||
// GET /_builder/instance/:appname/:instanceid/api/listRecords/contacts/abcd1234/all_deals
|
||||
// TODO: Error handling
|
||||
const response = await api.get(FETCH_RECORDS_URL);
|
||||
return await response.json();
|
||||
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
</script>
|
||||
|
||||
<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">
|
||||
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
||||
<ActionButton
|
||||
|
|
|
@ -1,60 +1,84 @@
|
|||
<script>
|
||||
import { onMount } from "svelte"
|
||||
import { store } from "../../../builderStore"
|
||||
import Modal from "../../../common/Modal.svelte"
|
||||
import ActionButton from "../../../common/ActionButton.svelte"
|
||||
import Select from "../../../common/Select.svelte"
|
||||
import * as api from "../api"
|
||||
|
||||
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)
|
||||
</script>
|
||||
|
||||
<Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}>
|
||||
<Modal {onClosed} isOpen={modalOpen}>
|
||||
<h4 class="budibase__title--4">Create / Edit Record</h4>
|
||||
<div class="actions">
|
||||
<form>
|
||||
{console.log('record', record)}
|
||||
{console.log('selectedModel', selectedModel)}
|
||||
{console.log('recordFields', recordFields)}
|
||||
<form class="uk-form-stacked">
|
||||
{#if !record}
|
||||
<div class="uk-margin">
|
||||
<label class="uk-form-label" for="form-stacked-text">Text</label>
|
||||
<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 modelFields as field}
|
||||
<div class="uk-margin">
|
||||
<label class="uk-form-label" for="form-stacked-text">{field}</label>
|
||||
<div class="uk-form-controls">
|
||||
<input
|
||||
class="uk-input"
|
||||
id="form-stacked-text"
|
||||
type="text"
|
||||
placeholder="Some text..." />
|
||||
bind:value={selectedModel[field]} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/each}
|
||||
{#each recordFields as field}
|
||||
<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">
|
||||
<select class="uk-select" id="form-stacked-select">
|
||||
<option>Option 01</option>
|
||||
<option>Option 02</option>
|
||||
</select>
|
||||
<input
|
||||
class="uk-input"
|
||||
id="form-stacked-text"
|
||||
type="text"
|
||||
bind:value={record[field]} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="uk-margin">
|
||||
<div class="uk-form-label">Radio</div>
|
||||
<div class="uk-form-controls">
|
||||
<label>
|
||||
<input class="uk-radio" type="radio" name="radio1" />
|
||||
Option 01
|
||||
</label>
|
||||
<br />
|
||||
<label>
|
||||
<input class="uk-radio" type="radio" name="radio1" />
|
||||
Option 02
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/each}
|
||||
</form>
|
||||
<div class="actions">
|
||||
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
||||
<ActionButton
|
||||
disabled={false}
|
||||
on:click={() => api.createNewRecord(recordInfo)}>
|
||||
on:click={() => api.saveRecord(record || selectedModel, currentAppInfo)}>
|
||||
Save
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<style>
|
||||
.actions {
|
||||
position: absolute;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -4,20 +4,22 @@
|
|||
import * as api from "../api"
|
||||
|
||||
export let modalOpen = false
|
||||
|
||||
let recordInfo = {}
|
||||
export let record
|
||||
|
||||
const onClosed = () => (modalOpen = false)
|
||||
</script>
|
||||
|
||||
<Modal {onClosed} bind:isOpen={modalOpen} title={"Delete Record?"}>
|
||||
<Modal {onClosed} bind:isOpen={modalOpen}>
|
||||
<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.
|
||||
<div class="modal-actions">
|
||||
<ActionButton on:click={onClosed}>Cancel</ActionButton>
|
||||
<ActionButton
|
||||
alert
|
||||
on:click={() => api.deleteRecord(recordInfo)}>
|
||||
on:click={async () => {
|
||||
await api.deleteRecord(record)
|
||||
onClosed();
|
||||
}}>
|
||||
Delete
|
||||
</ActionButton>
|
||||
</div>
|
||||
|
|
|
@ -139,7 +139,7 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each record.fields as field}
|
||||
{#each record ? record.fields : [] as field}
|
||||
<tr>
|
||||
<td>
|
||||
<i class="ri-more-line" on:click={() => editField(field)} />
|
||||
|
@ -150,9 +150,6 @@
|
|||
<td>{field.type}</td>
|
||||
<td>({console.log(field.typeOptions)}) {field.typeOptions.values}</td>
|
||||
<td>
|
||||
<!-- <span class="edit-button" on:click={() => editField(field)}>
|
||||
{@html getIcon('edit')}
|
||||
</span> -->
|
||||
<span class="edit-button" on:click={() => deleteField(field)}>
|
||||
{@html getIcon('trash')}
|
||||
</span>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script>
|
||||
import { navigate } from "svelte-routing"
|
||||
import { store } from "../builderStore"
|
||||
import getIcon from "../common/icon"
|
||||
import { CheckIcon } from "../common/Icons"
|
||||
|
@ -11,7 +10,6 @@
|
|||
state.currentlySelectedDatabase = databaseId
|
||||
return state
|
||||
})
|
||||
navigate("/database", { replace: true })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -71,13 +71,13 @@
|
|||
<div class="nav-group-header">
|
||||
<div class="hierarchy-title">Schema</div>
|
||||
<div class="uk-inline">
|
||||
<i class="ri-add-line" />
|
||||
<i class="ri-add-line hoverable" />
|
||||
<div uk-dropdown="mode: click">
|
||||
<ul class="uk-nav uk-dropdown-nav">
|
||||
<li>
|
||||
<li class="hoverable" on:click={() => {}}>
|
||||
Model
|
||||
</li>
|
||||
<li>
|
||||
<li class="hoverable" on:click={() => {}}>
|
||||
View
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -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) =>
|
||||
constructRecord(recordNode, getNewFieldValue, collectionKey)
|
||||
|
||||
|
|
Loading…
Reference in New Issue