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 {
|
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)
|
||||||
|
|
|
@ -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}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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)}
|
||||||
|
{console.log('selectedModel', selectedModel)}
|
||||||
|
{console.log('recordFields', recordFields)}
|
||||||
|
<form class="uk-form-stacked">
|
||||||
|
{#if !record}
|
||||||
<div class="uk-margin">
|
<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">
|
<div class="uk-form-controls">
|
||||||
<input
|
<input
|
||||||
class="uk-input"
|
class="uk-input"
|
||||||
id="form-stacked-text"
|
id="form-stacked-text"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Some text..." />
|
bind:value={selectedModel[field]} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/each}
|
||||||
|
{#each recordFields 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={record[field]} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/each}
|
||||||
<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>
|
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
<div class="actions">
|
||||||
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
disabled={false}
|
disabled={false}
|
||||||
on:click={() => api.createNewRecord(recordInfo)}>
|
on:click={() => api.saveRecord(record || selectedModel, currentAppInfo)}>
|
||||||
Save
|
Save
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.actions {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue