adding, deleting and editing records working
This commit is contained in:
parent
38d7623862
commit
a8fec53ff3
|
@ -103,6 +103,7 @@ const lodash_fp_exports = [
|
||||||
"toNumber",
|
"toNumber",
|
||||||
"takeRight",
|
"takeRight",
|
||||||
"toPairs",
|
"toPairs",
|
||||||
|
"remove"
|
||||||
]
|
]
|
||||||
|
|
||||||
const lodash_exports = [
|
const lodash_exports = [
|
||||||
|
|
|
@ -7,10 +7,7 @@
|
||||||
import AccessLevels from "./accessLevels/AccessLevelsRoot.svelte"
|
import AccessLevels from "./accessLevels/AccessLevelsRoot.svelte"
|
||||||
import ComingSoon from "./common/ComingSoon.svelte"
|
import ComingSoon from "./common/ComingSoon.svelte"
|
||||||
|
|
||||||
import { store } from "./builderStore"
|
import { store, backendUiStore } from "./builderStore"
|
||||||
import { setContext } from "svelte"
|
|
||||||
|
|
||||||
let activeNav = "database"
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
@ -18,13 +15,14 @@
|
||||||
<BackendNav />
|
<BackendNav />
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<Database />
|
{#if $backendUiStore.leftNavItem === 'DATABASE'}
|
||||||
</div>
|
<Database />
|
||||||
<!-- {:else if activeNav === 'actions'}
|
{:else if $backendUiStore.leftNavItem === 'ACTIONS'}
|
||||||
<ActionsAndTriggers />
|
<ActionsAndTriggers />
|
||||||
{:else if activeNav === 'access levels'}
|
{:else if $backendUiStore.leftNavItem === 'ACCESS_LEVELS'}
|
||||||
<AccessLevels />
|
<AccessLevels />
|
||||||
{/if} -->
|
{/if}
|
||||||
|
</div>
|
||||||
<div class="nav">
|
<div class="nav">
|
||||||
<SchemaManagementDrawer />
|
<SchemaManagementDrawer />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import getStore from "./store"
|
import { getStore } from "./store"
|
||||||
|
import { getBackendUiStore } from "./store/backend"
|
||||||
import LogRocket from "logrocket";
|
import LogRocket from "logrocket";
|
||||||
|
|
||||||
export const store = getStore()
|
export const store = getStore()
|
||||||
|
export const backendUiStore = getBackendUiStore()
|
||||||
|
|
||||||
export const initialise = async () => {
|
export const initialise = async () => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
|
import { writable } from "svelte/store";
|
||||||
import api from "../api"
|
import api from "../api"
|
||||||
import {
|
import {
|
||||||
filter,
|
filter,
|
||||||
cloneDeep,
|
cloneDeep,
|
||||||
sortBy,
|
sortBy,
|
||||||
find
|
map,
|
||||||
|
find,
|
||||||
|
remove
|
||||||
} from "lodash/fp"
|
} from "lodash/fp"
|
||||||
import { hierarchy as hierarchyFunctions } from "../../../../core/src"
|
import { hierarchy as hierarchyFunctions } from "../../../../core/src"
|
||||||
import {
|
import {
|
||||||
|
@ -13,10 +16,47 @@ import {
|
||||||
constructHierarchy,
|
constructHierarchy,
|
||||||
templateApi,
|
templateApi,
|
||||||
} from "../../common/core"
|
} from "../../common/core"
|
||||||
import { store } from "../index";
|
|
||||||
|
|
||||||
export const createShadowHierarchy = hierarchy =>
|
export const getBackendUiStore = () => {
|
||||||
constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
|
const INITIAL_BACKEND_UI_STATE = {
|
||||||
|
leftNavItem: "DATABASE",
|
||||||
|
selectedView: {
|
||||||
|
records: [],
|
||||||
|
name: ""
|
||||||
|
},
|
||||||
|
selectedRecord: {},
|
||||||
|
selectedDatabase: {},
|
||||||
|
selectedModel: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = writable(INITIAL_BACKEND_UI_STATE)
|
||||||
|
|
||||||
|
store.actions = {
|
||||||
|
navigate: name => store.update(state => ({ ...state, leftNavItem: name })),
|
||||||
|
database: {
|
||||||
|
select: db => store.update(state => ({ ...state, selectedDatabase: db })),
|
||||||
|
},
|
||||||
|
records: {
|
||||||
|
delete: record => store.update(state => {
|
||||||
|
state.selectedView.records = remove(state.selectedView.records, { key: record.key });
|
||||||
|
return state
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
modals: {
|
||||||
|
show: modal => store.update(state => ({ ...state, visibleModal: modal })),
|
||||||
|
hide: () => store.update(state => ({ ...state, visibleModal: null }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return store
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store Actions
|
||||||
|
export const createShadowHierarchy = hierarchy => {
|
||||||
|
const hi = constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
|
||||||
|
console.log(hi)
|
||||||
|
return hi
|
||||||
|
}
|
||||||
|
|
||||||
export const saveBackend = async state => {
|
export const saveBackend = async state => {
|
||||||
await api.post(`/_builder/api/${state.appname}/backend`, {
|
await api.post(`/_builder/api/${state.appname}/backend`, {
|
||||||
|
@ -30,58 +70,57 @@ export const saveBackend = async state => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const newRecord = (store, useRoot) => () => {
|
export const newRecord = (store, useRoot) => () => {
|
||||||
store.update(s => {
|
store.update(state => {
|
||||||
s.currentNodeIsNew = true
|
state.currentNodeIsNew = true
|
||||||
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
|
const shadowHierarchy = createShadowHierarchy(state.hierarchy)
|
||||||
const parent = useRoot
|
const parent = useRoot
|
||||||
? shadowHierarchy
|
? shadowHierarchy
|
||||||
: getNode(shadowHierarchy, s.currentNode.nodeId)
|
: getNode(shadowHierarchy, state.currentNode.nodeId)
|
||||||
s.errors = []
|
state.errors = []
|
||||||
s.currentNode = templateApi(shadowHierarchy).getNewRecordTemplate(
|
state.currentNode = templateApi(shadowHierarchy).getNewRecordTemplate(
|
||||||
parent,
|
parent,
|
||||||
"",
|
"",
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
return s
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selectExistingNode = store => nodeId => {
|
export const selectExistingNode = store => nodeId => {
|
||||||
store.update(s => {
|
store.update(state => {
|
||||||
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
|
const shadowHierarchy = createShadowHierarchy(state.hierarchy)
|
||||||
s.currentNode = getNode(shadowHierarchy, nodeId)
|
state.currentNode = getNode(shadowHierarchy, nodeId)
|
||||||
s.currentNodeIsNew = false
|
state.currentNodeIsNew = false
|
||||||
s.errors = []
|
state.errors = []
|
||||||
return s
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const newIndex = (store, useRoot) => () => {
|
export const newIndex = (store, useRoot) => () => {
|
||||||
store.update(s => {
|
store.update(state => {
|
||||||
s.currentNodeIsNew = true
|
state.currentNodeIsNew = true
|
||||||
s.errors = []
|
state.errors = []
|
||||||
const shadowHierarchy = createShadowHierarchy(s.hierarchy)
|
const shadowHierarchy = createShadowHierarchy(state.hierarchy)
|
||||||
const parent = useRoot
|
const parent = useRoot
|
||||||
? shadowHierarchy
|
? shadowHierarchy
|
||||||
: getNode(shadowHierarchy, s.currentNode.nodeId)
|
: getNode(shadowHierarchy, state.currentNode.nodeId)
|
||||||
|
|
||||||
s.currentNode = templateApi(shadowHierarchy).getNewIndexTemplate(parent)
|
state.currentNode = templateApi(shadowHierarchy).getNewIndexTemplate(parent)
|
||||||
return s
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: ONLY SEEMS TO BE CALLED BY THE BACKEND
|
|
||||||
export const saveCurrentNode = store => () => {
|
export const saveCurrentNode = store => () => {
|
||||||
store.update(s => {
|
store.update(state => {
|
||||||
const errors = validate.node(s.currentNode)
|
const errors = validate.node(state.currentNode)
|
||||||
s.errors = errors
|
state.errors = errors
|
||||||
if (errors.length > 0) {
|
if (errorstate.length > 0) {
|
||||||
return s
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentNode = getNode(s.hierarchy, s.currentNode.parent().nodeId)
|
const parentNode = getNode(state.hierarchy, state.currentNode.parent().nodeId)
|
||||||
|
|
||||||
const existingNode = getNode(s.hierarchy, s.currentNode.nodeId)
|
const existingNode = getNode(state.hierarchy, state.currentNode.nodeId)
|
||||||
|
|
||||||
let index = parentNode.children.length
|
let index = parentNode.children.length
|
||||||
if (existingNode) {
|
if (existingNode) {
|
||||||
|
@ -93,8 +132,8 @@ export const saveCurrentNode = store => () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// should add node into existing hierarchy
|
// should add node into existing hierarchy
|
||||||
const cloned = cloneDeep(s.currentNode)
|
const cloned = cloneDeep(state.currentNode)
|
||||||
templateApi(s.hierarchy).constructNode(parentNode, cloned)
|
templateApi(state.hierarchy).constructNode(parentNode, cloned)
|
||||||
|
|
||||||
const newIndexOfChild = child => {
|
const newIndexOfChild = child => {
|
||||||
if (child === cloned) return index
|
if (child === cloned) return index
|
||||||
|
@ -104,29 +143,29 @@ export const saveCurrentNode = store => () => {
|
||||||
|
|
||||||
parentNode.children = pipe(parentNode.children, [sortBy(newIndexOfChild)])
|
parentNode.children = pipe(parentNode.children, [sortBy(newIndexOfChild)])
|
||||||
|
|
||||||
if (!existingNode && s.currentNode.type === "record") {
|
if (!existingNode && state.currentNode.type === "record") {
|
||||||
const defaultIndex = templateApi(s.hierarchy).getNewIndexTemplate(
|
const defaultIndex = templateApi(state.hierarchy).getNewIndexTemplate(
|
||||||
cloned.parent()
|
cloned.parent()
|
||||||
)
|
)
|
||||||
defaultIndex.name = `all_${cloned.collectionName}`
|
defaultIndex.name = `all_${cloned.collectionName}`
|
||||||
defaultIndex.allowedRecordNodeIds = [cloned.nodeId]
|
defaultIndex.allowedRecordNodeIds = [cloned.nodeId]
|
||||||
}
|
}
|
||||||
|
|
||||||
s.currentNodeIsNew = false
|
state.currentNodeIsNew = false
|
||||||
|
|
||||||
saveBackend(s)
|
saveBackend(state)
|
||||||
|
|
||||||
return s
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const deleteCurrentNode = store => () => {
|
export const deleteCurrentNode = store => () => {
|
||||||
store.update(s => {
|
store.update(state => {
|
||||||
const nodeToDelete = getNode(s.hierarchy, s.currentNode.nodeId)
|
const nodeToDelete = getNode(state.hierarchy, state.currentNode.nodeId)
|
||||||
s.currentNode = hierarchyFunctions.isRoot(nodeToDelete.parent())
|
state.currentNode = hierarchyFunctionstate.isRoot(nodeToDelete.parent())
|
||||||
? find(n => n != s.currentNode)(s.hierarchy.children)
|
? find(n => n != state.currentNode)(state.hierarchy.children)
|
||||||
: nodeToDelete.parent()
|
: nodeToDelete.parent()
|
||||||
if (hierarchyFunctions.isRecord(nodeToDelete)) {
|
if (hierarchyFunctionstate.isRecord(nodeToDelete)) {
|
||||||
nodeToDelete.parent().children = filter(
|
nodeToDelete.parent().children = filter(
|
||||||
c => c.nodeId !== nodeToDelete.nodeId
|
c => c.nodeId !== nodeToDelete.nodeId
|
||||||
)(nodeToDelete.parent().children)
|
)(nodeToDelete.parent().children)
|
||||||
|
@ -135,9 +174,9 @@ export const deleteCurrentNode = store => () => {
|
||||||
c => c.nodeId !== nodeToDelete.nodeId
|
c => c.nodeId !== nodeToDelete.nodeId
|
||||||
)(nodeToDelete.parent().indexes)
|
)(nodeToDelete.parent().indexes)
|
||||||
}
|
}
|
||||||
s.errors = []
|
state.errors = []
|
||||||
saveBackend(s)
|
saveBackend(state)
|
||||||
return s
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,4 +199,41 @@ export const deleteField = databaseStore => field => {
|
||||||
|
|
||||||
return db
|
return db
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const incrementAccessLevelsVersion = state =>
|
||||||
|
(state.accessLevelstate.version = (state.accessLevelstate.version || 0) + 1)
|
||||||
|
|
||||||
|
export const saveLevel = store => (newLevel, isNew, oldLevel = null) => {
|
||||||
|
store.update(state => {
|
||||||
|
const levels = state.accessLevelstate.levels
|
||||||
|
|
||||||
|
const existingLevel = isNew
|
||||||
|
? null
|
||||||
|
: find(a => a.name === oldLevel.name)(levels)
|
||||||
|
|
||||||
|
if (existingLevel) {
|
||||||
|
state.accessLevelstate.levels = pipe(levels, [
|
||||||
|
map(a => (a === existingLevel ? newLevel : a)),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
state.accessLevelstate.levelstate.push(newLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
incrementAccessLevelsVersion(s)
|
||||||
|
|
||||||
|
saveBackend(state)
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const deleteLevel = store => level => {
|
||||||
|
store.update(state => {
|
||||||
|
state.accessLevelstate.levels = filter(t => t.name !== level.name)(
|
||||||
|
state.accessLevelstate.levels
|
||||||
|
)
|
||||||
|
incrementAccessLevelsVersion(s)
|
||||||
|
saveBackend(state)
|
||||||
|
return state
|
||||||
|
})
|
||||||
}
|
}
|
|
@ -65,61 +65,6 @@ export const getStore = () => {
|
||||||
|
|
||||||
const store = writable(initial)
|
const store = writable(initial)
|
||||||
|
|
||||||
// store.api = {
|
|
||||||
// appDefinition: {
|
|
||||||
// create: () => {},
|
|
||||||
// },
|
|
||||||
// records: {
|
|
||||||
// create: () => {},
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {},
|
|
||||||
// },
|
|
||||||
// indexes: {
|
|
||||||
// create: () => {},
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {},
|
|
||||||
// },
|
|
||||||
// pages: {
|
|
||||||
// create: () => {},
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {},
|
|
||||||
// },
|
|
||||||
// screens: {
|
|
||||||
// create: () => {},
|
|
||||||
// select: () => {},
|
|
||||||
// rename: () => {}
|
|
||||||
// },
|
|
||||||
// accessLevels: {
|
|
||||||
// create: () => {},
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {},
|
|
||||||
// },
|
|
||||||
// users: {
|
|
||||||
// create: () => {},
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {},
|
|
||||||
// },
|
|
||||||
// actions: {
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {}
|
|
||||||
// },
|
|
||||||
// triggers: {
|
|
||||||
// create: () => {},
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {},
|
|
||||||
// },
|
|
||||||
// stylesheets: {
|
|
||||||
// create: () => {},
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {},
|
|
||||||
// },
|
|
||||||
// components: {
|
|
||||||
// create: () => {},
|
|
||||||
// update: () => {},
|
|
||||||
// delete: () => {},
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
store.initialise = initialise(store, initial)
|
store.initialise = initialise(store, initial)
|
||||||
|
|
||||||
store.newChildRecord = backendStoreActions.newRecord(store, false)
|
store.newChildRecord = backendStoreActions.newRecord(store, false)
|
||||||
|
@ -131,14 +76,14 @@ export const getStore = () => {
|
||||||
store.deleteCurrentNode = backendStoreActions.deleteCurrentNode(store)
|
store.deleteCurrentNode = backendStoreActions.deleteCurrentNode(store)
|
||||||
store.saveField = backendStoreActions.saveField(store)
|
store.saveField = backendStoreActions.saveField(store)
|
||||||
store.deleteField = backendStoreActions.deleteField(store)
|
store.deleteField = backendStoreActions.deleteField(store)
|
||||||
|
store.saveLevel = backendStoreActions.saveLevel(store)
|
||||||
|
store.deleteLevel = backendStoreActions.deleteLevel(store)
|
||||||
store.importAppDefinition = importAppDefinition(store)
|
store.importAppDefinition = importAppDefinition(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)
|
||||||
store.deleteTrigger = deleteTrigger(store)
|
store.deleteTrigger = deleteTrigger(store)
|
||||||
store.saveLevel = saveLevel(store)
|
|
||||||
store.deleteLevel = deleteLevel(store)
|
|
||||||
store.saveScreen = saveScreen(store)
|
store.saveScreen = saveScreen(store)
|
||||||
store.addComponentLibrary = addComponentLibrary(store)
|
store.addComponentLibrary = addComponentLibrary(store)
|
||||||
store.renameScreen = renameScreen(store)
|
store.renameScreen = renameScreen(store)
|
||||||
|
@ -319,43 +264,6 @@ const deleteTrigger = store => trigger => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const incrementAccessLevelsVersion = s =>
|
|
||||||
(s.accessLevels.version = (s.accessLevels.version || 0) + 1)
|
|
||||||
|
|
||||||
const saveLevel = store => (newLevel, isNew, oldLevel = null) => {
|
|
||||||
store.update(s => {
|
|
||||||
const levels = s.accessLevels.levels
|
|
||||||
|
|
||||||
const existingLevel = isNew
|
|
||||||
? null
|
|
||||||
: find(a => a.name === oldLevel.name)(levels)
|
|
||||||
|
|
||||||
if (existingLevel) {
|
|
||||||
s.accessLevels.levels = pipe(levels, [
|
|
||||||
map(a => (a === existingLevel ? newLevel : a)),
|
|
||||||
])
|
|
||||||
} else {
|
|
||||||
s.accessLevels.levels.push(newLevel)
|
|
||||||
}
|
|
||||||
|
|
||||||
incrementAccessLevelsVersion(s)
|
|
||||||
|
|
||||||
saveBackend(s)
|
|
||||||
return s
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteLevel = store => level => {
|
|
||||||
store.update(s => {
|
|
||||||
s.accessLevels.levels = filter(t => t.name !== level.name)(
|
|
||||||
s.accessLevels.levels
|
|
||||||
)
|
|
||||||
incrementAccessLevelsVersion(s)
|
|
||||||
saveBackend(s)
|
|
||||||
return s
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const createShadowHierarchy = hierarchy =>
|
const createShadowHierarchy = hierarchy =>
|
||||||
constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
|
constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
import ActionButton from "../common/ActionButton.svelte"
|
import ActionButton from "../common/ActionButton.svelte"
|
||||||
|
|
||||||
export let isOpen = false
|
export let isOpen = false
|
||||||
export let onClosed = () => {}
|
export let onClosed
|
||||||
export let id = ""
|
export let id = ""
|
||||||
export let title
|
export let title
|
||||||
|
|
||||||
|
@ -27,19 +27,21 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={ukModal} uk-modal {id}>
|
<div bind:this={ukModal} uk-modal {id}>
|
||||||
<div class="uk-modal-dialog" uk-overflow-auto>
|
{#if isOpen}
|
||||||
{#if title}
|
<div class="uk-modal-dialog" uk-overflow-auto>
|
||||||
<div class="uk-modal-header">
|
{#if title}
|
||||||
<h4 class="budibase__title--4">{title}</h4>
|
<div class="uk-modal-header">
|
||||||
</div>
|
<h4 class="budibase__title--4">{title}</h4>
|
||||||
{/if}
|
</div>
|
||||||
<div class="uk-modal-body">
|
|
||||||
{#if onClosed}
|
|
||||||
<button class="uk-modal-close-default" type="button" uk-close />
|
|
||||||
{/if}
|
{/if}
|
||||||
<slot />
|
<div class="uk-modal-body">
|
||||||
|
{#if onClosed}
|
||||||
|
<button class="uk-modal-close-default" type="button" uk-close />
|
||||||
|
{/if}
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -6,20 +6,12 @@
|
||||||
import Modal from "../common/Modal.svelte"
|
import Modal from "../common/Modal.svelte"
|
||||||
import ErrorsBox from "../common/ErrorsBox.svelte"
|
import ErrorsBox from "../common/ErrorsBox.svelte"
|
||||||
|
|
||||||
export let left
|
|
||||||
|
|
||||||
let confirmDelete = false
|
let confirmDelete = false
|
||||||
|
|
||||||
const openConfirmDelete = () => {
|
const openConfirmDelete = () => {
|
||||||
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()
|
||||||
|
@ -39,10 +31,8 @@
|
||||||
{/if}
|
{/if}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
|
|
||||||
{#if !!$store.errors && $store.errors.length > 0}
|
{#if $store.errors && $store.errors.length > 0}
|
||||||
<div style="width: 500px">
|
<ErrorsBox errors={$store.errors} />
|
||||||
<ErrorsBox errors={$store.errors} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<Modal onClosed={() => (confirmDelete = false)} bind:isOpen={confirmDelete}>
|
<Modal onClosed={() => (confirmDelete = false)} bind:isOpen={confirmDelete}>
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import HierarchyRow from "./HierarchyRow.svelte"
|
|
||||||
import ModelView from "./ModelView.svelte"
|
import ModelView from "./ModelView.svelte"
|
||||||
import IndexView from "./IndexView.svelte"
|
import IndexView from "./IndexView.svelte"
|
||||||
import ModelDataTable from "./ModelDataTable"
|
import ModelDataTable from "./ModelDataTable"
|
||||||
import ActionsHeader from "./ActionsHeader.svelte"
|
import ActionsHeader from "./ActionsHeader.svelte"
|
||||||
import { store } from "../builderStore"
|
import { store, backendUiStore } 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 ActionButton from "../common/ActionButton.svelte"
|
||||||
|
@ -13,35 +12,53 @@
|
||||||
CreateEditRecordModal,
|
CreateEditRecordModal,
|
||||||
CreateEditModelModal,
|
CreateEditModelModal,
|
||||||
CreateEditViewModal,
|
CreateEditViewModal,
|
||||||
|
CreateDatabaseModal
|
||||||
} from "./ModelDataTable/modals"
|
} from "./ModelDataTable/modals"
|
||||||
|
|
||||||
let modalOpen
|
|
||||||
let selectedRecord
|
let selectedRecord
|
||||||
|
|
||||||
function selectRecord(record) {
|
function selectRecord(record) {
|
||||||
selectedRecord = record
|
selectedRecord = record
|
||||||
modalOpen = true
|
backendUiStore.actions.modals.show("RECORD")
|
||||||
}
|
}
|
||||||
|
|
||||||
$: recordOpen = $store.currentNode && $store.currentNode.type === 'record'
|
function onClosed() {
|
||||||
$: viewOpen = $store.currentNode && $store.currentNode.type === 'index'
|
// backendUiStore.actions.modals.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
$: recordOpen = $backendUiStore.visibleModal === "RECORD"
|
||||||
|
$: modelOpen = $backendUiStore.visibleModal === "MODEL"
|
||||||
|
$: viewOpen = $backendUiStore.visibleModal === "VIEW"
|
||||||
|
$: databaseOpen = $backendUiStore.visibleModal === "DATABASE"
|
||||||
|
// $: recordOpen = $store.currentNode && $store.currentNode.type === 'record'
|
||||||
|
// $: viewOpen = $store.currentNode && $store.currentNode.type === 'index'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<CreateEditRecordModal bind:modalOpen record={selectedRecord} />
|
({ console.log($backendUiStore.visibleModal) })
|
||||||
<CreateEditModelModal modalOpen={recordOpen} />
|
|
||||||
<CreateEditViewModal modalOpen={viewOpen} />
|
<CreateEditRecordModal modalOpen={recordOpen} record={selectedRecord} {onClosed} />
|
||||||
|
<CreateEditModelModal modalOpen={modelOpen} {onClosed} />
|
||||||
|
<CreateEditViewModal modalOpen={viewOpen} {onClosed} />
|
||||||
|
<CreateDatabaseModal modalOpen={databaseOpen} {onClosed} />
|
||||||
|
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<div class="node-view">
|
<div class="node-view">
|
||||||
<div class="breadcrumbs">{$store.currentlySelectedDatabase}</div>
|
<div class="database-actions">
|
||||||
<ActionButton
|
<div class="budibase__label--big">
|
||||||
primary
|
{#if $backendUiStore.selectedDatabase.name}
|
||||||
on:click={() => {
|
{$backendUiStore.selectedDatabase.name} / {$store.currentNode}
|
||||||
selectedRecord = null
|
{/if}
|
||||||
modalOpen = true
|
</div>
|
||||||
}}>
|
<ActionButton
|
||||||
Create new record
|
primary
|
||||||
</ActionButton>
|
on:click={() => {
|
||||||
|
selectedRecord = null
|
||||||
|
backendUiStore.actions.modals.show("RECORD")
|
||||||
|
}}>
|
||||||
|
Create new record
|
||||||
|
</ActionButton>
|
||||||
|
</div>
|
||||||
<ModelDataTable {selectRecord} />
|
<ModelDataTable {selectRecord} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -56,4 +73,9 @@
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.database-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
<script>
|
|
||||||
import { store } from "../builderStore"
|
|
||||||
import { cloneDeep } from "lodash/fp"
|
|
||||||
export let level = 0
|
|
||||||
export let node
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="root">
|
|
||||||
<div
|
|
||||||
class="title"
|
|
||||||
on:click={() => store.selectExistingNode(node.nodeId)}
|
|
||||||
style="padding-left: {20 + level * 20}px">
|
|
||||||
{node.name}
|
|
||||||
</div>
|
|
||||||
{#if node.children}
|
|
||||||
{#each node.children as child}
|
|
||||||
<svelte:self node={child} level={level + 1} />
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.root {
|
|
||||||
display: block;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
width: 100%;
|
|
||||||
cursor: pointer;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font: var(--fontblack);
|
|
||||||
padding-top: 10px;
|
|
||||||
padding-right: 5px;
|
|
||||||
padding-bottom: 10px;
|
|
||||||
color: var(--secondary100);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title:hover {
|
|
||||||
background-color: var(--secondary10);
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { store } from "../../builderStore"
|
import { store, backendUiStore } from "../../builderStore"
|
||||||
import Select from "../../common/Select.svelte"
|
import Select from "../../common/Select.svelte"
|
||||||
import { getIndexSchema } from "../../common/core"
|
import { getIndexSchema } from "../../common/core"
|
||||||
import ActionButton from "../../common/ActionButton.svelte"
|
import ActionButton from "../../common/ActionButton.svelte"
|
||||||
|
@ -13,8 +13,6 @@
|
||||||
let pages = [1, 2, 3]
|
let pages = [1, 2, 3]
|
||||||
let selectedView = ""
|
let selectedView = ""
|
||||||
let modalOpen = false
|
let modalOpen = false
|
||||||
let deleteRecordModal = false
|
|
||||||
let data = []
|
|
||||||
let headers = []
|
let headers = []
|
||||||
let selectedRecord
|
let selectedRecord
|
||||||
|
|
||||||
|
@ -23,13 +21,20 @@
|
||||||
appname: $store.appname,
|
appname: $store.appname,
|
||||||
instanceId: $store.currentInstanceId
|
instanceId: $store.currentInstanceId
|
||||||
}
|
}
|
||||||
|
$: data = $backendUiStore.selectedView.records
|
||||||
|
$: deleteRecordModal = $backendUiStore.visibleModal === "DELETE_RECORD"
|
||||||
|
|
||||||
const getSchema = getIndexSchema($store.hierarchy)
|
const getSchema = getIndexSchema($store.hierarchy)
|
||||||
|
|
||||||
async function fetchRecordsForView(viewName) {
|
async function fetchRecordsForView(viewName) {
|
||||||
const recordsForIndex = await api.fetchDataForView(viewName, currentAppInfo)
|
const recordsForIndex = await api.fetchDataForView(viewName, currentAppInfo)
|
||||||
data = recordsForIndex
|
backendUiStore.update(state => {
|
||||||
headers = Object.keys(data[0])
|
state.selectedView.records = recordsForIndex
|
||||||
|
if (state.selectedView.records.length > 0) {
|
||||||
|
headers = Object.keys(recordsForIndex[0])
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
|
@ -37,7 +42,10 @@
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DeleteRecordModal modalOpen={deleteRecordModal} record={selectedRecord} />
|
<DeleteRecordModal
|
||||||
|
modalOpen={deleteRecordModal}
|
||||||
|
record={selectedRecord}
|
||||||
|
/>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<div class="table-controls">
|
<div class="table-controls">
|
||||||
|
@ -46,7 +54,6 @@
|
||||||
icon="ri-eye-line"
|
icon="ri-eye-line"
|
||||||
on:change={e => fetchRecordsForView(e.target.value)}>
|
on:change={e => fetchRecordsForView(e.target.value)}>
|
||||||
{#each views as view}
|
{#each views as view}
|
||||||
<!-- ({console.log(getSchema(view))}) ({console.log(view)}) -->
|
|
||||||
<option value={view.name}>{view.name}</option>
|
<option value={view.name}>{view.name}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
|
@ -62,7 +69,7 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each data as row}
|
{#each data as row}
|
||||||
<tr>
|
<tr class="hoverable">
|
||||||
<td>
|
<td>
|
||||||
<div class="uk-inline">
|
<div class="uk-inline">
|
||||||
<i class="ri-more-line" />
|
<i class="ri-more-line" />
|
||||||
|
@ -78,8 +85,8 @@
|
||||||
<li>
|
<li>
|
||||||
<div
|
<div
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
deleteRecordModal = true
|
|
||||||
selectedRecord = row
|
selectedRecord = row
|
||||||
|
backendUiStore.actions.modals.show("DELETE_RECORD")
|
||||||
}}>
|
}}>
|
||||||
Delete
|
Delete
|
||||||
</div>
|
</div>
|
||||||
|
@ -98,7 +105,7 @@
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<TablePagination {data} />
|
<TablePagination />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -118,8 +125,13 @@
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
tr {
|
tbody tr {
|
||||||
border-bottom: 1px solid #ccc;
|
border-bottom: 1px solid #ccc;
|
||||||
|
transition: 0.3s background-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody tr:hover {
|
||||||
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
|
|
||||||
.table-controls {
|
.table-controls {
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
export let data = []
|
import { backendUiStore } from "../../builderStore"
|
||||||
|
|
||||||
|
$: data = $backendUiStore.selectedView.records
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="pagination">
|
<div class="pagination">
|
||||||
|
@ -41,4 +43,4 @@
|
||||||
.ri-more-line:hover {
|
.ri-more-line:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,18 +2,27 @@
|
||||||
import { getNewRecord } from "../../common/core"
|
import { getNewRecord } from "../../common/core"
|
||||||
|
|
||||||
export async function deleteRecord(record, { appname, instanceId }) {
|
export async function deleteRecord(record, { appname, instanceId }) {
|
||||||
const DELETE_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/record/${record.name}/${record.id}`
|
const DELETE_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/record${record.key}`
|
||||||
const response = await api.delete({
|
const response = await api.delete(DELETE_RECORDS_URL);
|
||||||
url: DELETE_RECORDS_URL
|
|
||||||
});
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function saveRecord(record, { appname, instanceId }) {
|
export async function saveRecord(record, { appname, instanceId }) {
|
||||||
const SAVE_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/record`
|
let recordBase = { ...record }
|
||||||
const updatedRecord = getNewRecord(record, "")
|
|
||||||
const response = await api.post(SAVE_RECORDS_URL, updatedRecord)
|
// brand new record
|
||||||
return response
|
if (record.collectionName) {
|
||||||
|
const collectionKey = `/${record.collectionName}`
|
||||||
|
recordBase = getNewRecord(recordBase, collectionKey)
|
||||||
|
// overwrite the new record template values
|
||||||
|
for (let key in recordBase) {
|
||||||
|
if (record[key]) recordBase[key] = record[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const SAVE_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/record/`
|
||||||
|
const response = await api.post(SAVE_RECORDS_URL, recordBase)
|
||||||
|
return await response.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchDataForView(viewName, { appname, instanceId }) {
|
export async function fetchDataForView(viewName, { appname, instanceId }) {
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<script>
|
||||||
|
import Modal from "../../../common/Modal.svelte"
|
||||||
|
import ActionButton from "../../../common/ActionButton.svelte"
|
||||||
|
import * as api from "../api"
|
||||||
|
|
||||||
|
export let modalOpen = false
|
||||||
|
|
||||||
|
const onClosed = () => (modalOpen = false)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Modal {onClosed} isOpen={modalOpen}>
|
||||||
|
CREATE A NEW DATABASE FROM HERE
|
||||||
|
<div class="actions">
|
||||||
|
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
||||||
|
<ActionButton disabled={false}>Save</ActionButton>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
|
@ -10,7 +10,7 @@
|
||||||
const onClosed = () => (modalOpen = false)
|
const onClosed = () => (modalOpen = false)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal {onClosed} bind:isOpen={modalOpen} title={"Create / Edit Field"}>
|
<Modal {onClosed} isOpen={modalOpen}>
|
||||||
|
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
||||||
|
|
|
@ -1,27 +1,22 @@
|
||||||
<script>
|
<script>
|
||||||
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 { backendUiStore } from "../../../builderStore"
|
||||||
import ModelView from "../../ModelView.svelte"
|
import ModelView from "../../ModelView.svelte"
|
||||||
import ActionsHeader from "../../ActionsHeader.svelte"
|
import ActionsHeader from "../../ActionsHeader.svelte"
|
||||||
import * as api from "./api"
|
import * as api from "../api"
|
||||||
|
|
||||||
export let modalOpen = false
|
export let modalOpen = false
|
||||||
|
export let onClosed
|
||||||
let recordInfo = {}
|
|
||||||
|
|
||||||
const onClosed = () => (modalOpen = false)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}>
|
<Modal {onClosed} isOpen={modalOpen}>
|
||||||
<h4 class="budibase__title--4">Create / Edit Model</h4>
|
<h4 class="budibase__title--4">
|
||||||
|
<i class="ri-list-settings-line" />
|
||||||
|
Create / Edit Model
|
||||||
|
</h4>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<ModelView />
|
<ModelView />
|
||||||
<ActionsHeader />
|
<ActionsHeader />
|
||||||
<!-- <ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
|
||||||
<ActionButton
|
|
||||||
disabled={false}
|
|
||||||
on:click={() => api.createNewRecord(recordInfo)}>
|
|
||||||
Save
|
|
||||||
</ActionButton> -->
|
|
||||||
</div>
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { store } from "../../../builderStore"
|
import { store, backendUiStore } 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 Select from "../../../common/Select.svelte"
|
||||||
|
import { getNewRecord } from "../../../common/core"
|
||||||
import * as api from "../api"
|
import * as api from "../api"
|
||||||
|
|
||||||
export let modalOpen = false
|
export let modalOpen = false
|
||||||
export let record
|
export let record
|
||||||
|
export let onClosed
|
||||||
|
|
||||||
let selectedModel
|
let selectedModel
|
||||||
|
|
||||||
|
@ -20,16 +22,12 @@
|
||||||
$: modelFields = selectedModel
|
$: modelFields = selectedModel
|
||||||
? selectedModel.fields.map(({ name }) => name)
|
? selectedModel.fields.map(({ name }) => name)
|
||||||
: []
|
: []
|
||||||
|
|
||||||
const onClosed = () => (modalOpen = false)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal {onClosed} isOpen={modalOpen}>
|
<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">
|
||||||
{console.log('record', record)}
|
|
||||||
{console.log('selectedModel', selectedModel)}
|
|
||||||
{console.log('recordFields', recordFields)}
|
|
||||||
<form class="uk-form-stacked">
|
<form class="uk-form-stacked">
|
||||||
{#if !record}
|
{#if !record}
|
||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
|
@ -70,7 +68,14 @@
|
||||||
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
||||||
<ActionButton
|
<ActionButton
|
||||||
disabled={false}
|
disabled={false}
|
||||||
on:click={() => api.saveRecord(record || selectedModel, currentAppInfo)}>
|
on:click={async () => {
|
||||||
|
const recordResponse = await api.saveRecord(record || selectedModel, currentAppInfo)
|
||||||
|
backendUiStore.update(state => {
|
||||||
|
state.selectedView.records.push(recordResponse)
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
onClosed()
|
||||||
|
}}>
|
||||||
Save
|
Save
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,23 +1,25 @@
|
||||||
<script>
|
<script>
|
||||||
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 * as api from "./api"
|
import IndexView from "../../IndexView.svelte"
|
||||||
|
import ActionsHeader from "../../ActionsHeader.svelte"
|
||||||
|
import * as api from "../api"
|
||||||
|
|
||||||
export let modalOpen = false
|
export let modalOpen = false
|
||||||
|
export let onClosed
|
||||||
|
|
||||||
let recordInfo = {}
|
let recordInfo = {}
|
||||||
|
|
||||||
const onClosed = () => (modalOpen = false)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}>
|
<Modal {onClosed} isOpen={modalOpen}>
|
||||||
|
<IndexView />
|
||||||
|
<ActionsHeader />
|
||||||
|
|
||||||
<div class="actions">
|
<!-- <div class="actions">
|
||||||
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
|
||||||
<ActionButton
|
<ActionButton disabled={false} on:click={() => api.saveRecord(recordInfo)}>
|
||||||
disabled={false}
|
|
||||||
on:click={() => api.createNewRecord(recordInfo)}>
|
|
||||||
Save
|
Save
|
||||||
</ActionButton>
|
</ActionButton>
|
||||||
</div>
|
</div> -->
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
|
@ -1,15 +1,24 @@
|
||||||
<script>
|
<script>
|
||||||
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 { store, backendUiStore } from "../../../builderStore"
|
||||||
import * as api from "../api"
|
import * as api from "../api"
|
||||||
|
|
||||||
export let modalOpen = false
|
export let modalOpen = false
|
||||||
export let record
|
export let record
|
||||||
|
|
||||||
const onClosed = () => (modalOpen = false)
|
$: currentAppInfo = {
|
||||||
|
instanceId: $store.currentInstanceId,
|
||||||
|
appname: $store.appname,
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClosed() {
|
||||||
|
backendUiStore.actions.modals.hide()
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal {onClosed} bind:isOpen={modalOpen}>
|
<Modal {onClosed} 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">
|
||||||
|
@ -17,7 +26,8 @@
|
||||||
<ActionButton
|
<ActionButton
|
||||||
alert
|
alert
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
await api.deleteRecord(record)
|
await api.deleteRecord(record, currentAppInfo)
|
||||||
|
backendUiStore.actions.records.delete(record)
|
||||||
onClosed();
|
onClosed();
|
||||||
}}>
|
}}>
|
||||||
Delete
|
Delete
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
export { default as DeleteRecordModal } from "./DeleteRecord.svelte";
|
export { default as DeleteRecordModal } from "./DeleteRecord.svelte";
|
||||||
export { default as CreateEditRecordModal } from "./CreateEditRecord.svelte";
|
export { default as CreateEditRecordModal } from "./CreateEditRecord.svelte";
|
||||||
export { default as CreateEditModelModal } from "./CreateEditModel.svelte";
|
export { default as CreateEditModelModal } from "./CreateEditModel.svelte";
|
||||||
|
export { default as CreateEditViewModal } from "./CreateEditView.svelte";
|
||||||
|
export { default as CreateDatabaseModal } from "./CreateDatabase.svelte";
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import Textbox from "../common/Textbox.svelte"
|
import Textbox from "../common/Textbox.svelte"
|
||||||
import Button from "../common/Button.svelte"
|
import Button from "../common/Button.svelte"
|
||||||
|
import Select from "../common/Select.svelte"
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
import FieldView from "./FieldView.svelte"
|
import FieldView from "./FieldView.svelte"
|
||||||
import Modal from "../common/Modal.svelte"
|
import Modal from "../common/Modal.svelte"
|
||||||
|
@ -19,6 +20,9 @@
|
||||||
let deleteField
|
let deleteField
|
||||||
let onFinishedFieldEdit
|
let onFinishedFieldEdit
|
||||||
let editIndex
|
let editIndex
|
||||||
|
let parentRecord
|
||||||
|
|
||||||
|
$: models = $store.hierarchy.children
|
||||||
|
|
||||||
store.subscribe($store => {
|
store.subscribe($store => {
|
||||||
record = $store.currentNode
|
record = $store.currentNode
|
||||||
|
@ -98,16 +102,20 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
|
||||||
<form class="uk-form-stacked">
|
<form class="uk-form-stacked">
|
||||||
<h3 class="budibase__title--3">
|
|
||||||
<i class="ri-list-settings-line" />
|
|
||||||
Create / Edit Model
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<h3 class="budibase__label--big">Settings</h3>
|
<h3 class="budibase__label--big">Settings</h3>
|
||||||
|
|
||||||
<Textbox label="Name" bind:text={record.name} on:change={nameChanged} />
|
<Textbox label="Name" bind:text={record.name} on:change={nameChanged} />
|
||||||
|
<label class="uk-form-label">Parent</label>
|
||||||
|
<div class="uk-form-controls">
|
||||||
|
<Select
|
||||||
|
value={parentRecord}
|
||||||
|
on:change={e => (parentRecord = e.target.value)}>
|
||||||
|
{#each models as model}
|
||||||
|
<option value={model}>{model.name}</option>
|
||||||
|
{/each}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
{#if !record.isSingle}
|
{#if !record.isSingle}
|
||||||
<Textbox label="Collection Name" bind:text={record.collectionName} />
|
<Textbox label="Collection Name" bind:text={record.collectionName} />
|
||||||
<Textbox
|
<Textbox
|
||||||
|
@ -121,12 +129,6 @@
|
||||||
<span class="budibase__label--big">Fields</span>
|
<span class="budibase__label--big">Fields</span>
|
||||||
<h4 class="hoverable" on:click={newField}>Add new field</h4>
|
<h4 class="hoverable" on:click={newField}>Add new field</h4>
|
||||||
</div>
|
</div>
|
||||||
<!-- <h3 class="budibase__label--big">
|
|
||||||
Fields
|
|
||||||
<span class="add-field-button" on:click={newField}>
|
|
||||||
{@html getIcon('plus')}
|
|
||||||
</span>
|
|
||||||
</h3> -->
|
|
||||||
|
|
||||||
<table class="fields-table uk-table budibase__table">
|
<table class="fields-table uk-table budibase__table">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -139,7 +141,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each record ? 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)} />
|
||||||
|
@ -148,7 +150,7 @@
|
||||||
<div>{field.name}</div>
|
<div>{field.name}</div>
|
||||||
</td>
|
</td>
|
||||||
<td>{field.type}</td>
|
<td>{field.type}</td>
|
||||||
<td>({console.log(field.typeOptions)}) {field.typeOptions.values}</td>
|
<td>{field.typeOptions.values}</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="edit-button" on:click={() => deleteField(field)}>
|
<span class="edit-button" on:click={() => deleteField(field)}>
|
||||||
{@html getIcon('trash')}
|
{@html getIcon('trash')}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte"
|
import { getContext } from "svelte"
|
||||||
import { store } from "../builderStore"
|
import { store, backendUiStore } from "../builderStore"
|
||||||
import HierarchyRow from "./HierarchyRow.svelte"
|
import HierarchyRow from "./HierarchyRow.svelte"
|
||||||
import DatabasesList from "./DatabasesList.svelte"
|
import DatabasesList from "./DatabasesList.svelte"
|
||||||
import UsersList from "./UsersList.svelte"
|
import UsersList from "./UsersList.svelte"
|
||||||
|
@ -8,59 +8,16 @@
|
||||||
import NavItem from "./NavItem.svelte"
|
import NavItem from "./NavItem.svelte"
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
|
|
||||||
// top level store modifiers
|
|
||||||
const newRootRecord = () => store.newRootRecord()
|
|
||||||
const newChildIndex = () => store.newChildIndex()
|
|
||||||
const newRootIndex = () => store.newRootIndex()
|
|
||||||
const newUser = () => {
|
|
||||||
store.update(state => {})
|
|
||||||
}
|
|
||||||
const newDatabase = () => {
|
const newDatabase = () => {
|
||||||
store.update(state => {})
|
store.update(state => {})
|
||||||
}
|
}
|
||||||
|
|
||||||
const userManagementActions = [
|
|
||||||
{
|
|
||||||
label: "New User",
|
|
||||||
onclick: newUser,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
const databaseManagementActions = [
|
const databaseManagementActions = [
|
||||||
{
|
{
|
||||||
label: "New Database",
|
label: "New Database",
|
||||||
onclick: newDatabase,
|
onclick: newDatabase,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
// let newChildActions = defaultNewChildActions
|
|
||||||
|
|
||||||
const setActiveNav = name => () => getContext("navigation").setActiveNav(name);
|
|
||||||
|
|
||||||
// store.subscribe(db => {
|
|
||||||
// if (!db.currentNode || hierarchyFunctions.isIndex(db.currentNode)) {
|
|
||||||
// newChildActions = defaultNewChildActions
|
|
||||||
// } else {
|
|
||||||
// newChildActions = [
|
|
||||||
// {
|
|
||||||
// label: "New Root Record",
|
|
||||||
// onclick: newRootRecord,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: "New Root Index",
|
|
||||||
// onclick: newRootIndex,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: `New Child Record of ${db.currentNode.name}`,
|
|
||||||
// onclick: newChildRecord,
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// label: `New Index on ${db.currentNode.name}`,
|
|
||||||
// onclick: newChildIndex,
|
|
||||||
// },
|
|
||||||
// ]
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="items-root">
|
<div class="items-root">
|
||||||
|
@ -68,20 +25,12 @@
|
||||||
<div class="components-list-container">
|
<div class="components-list-container">
|
||||||
<div class="nav-group-header">
|
<div class="nav-group-header">
|
||||||
<div class="hierarchy-title">Databases</div>
|
<div class="hierarchy-title">Databases</div>
|
||||||
<i class="ri-add-line" />
|
<i class="ri-add-line hoverable" on:click={() => backendUiStore.actions.modals.show("DATABASE")} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hierarchy-items-container">
|
<div class="hierarchy-items-container">
|
||||||
<DatabasesList />
|
<DatabasesList />
|
||||||
|
|
||||||
<!-- {#each $store.hierarchy.children as record}
|
|
||||||
<HierarchyRow node={record} type="record" />
|
|
||||||
{/each}
|
|
||||||
|
|
||||||
{#each $store.hierarchy.indexes as index}
|
|
||||||
<HierarchyRow node={index} type="index" />
|
|
||||||
{/each} -->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
|
@ -95,10 +44,9 @@
|
||||||
|
|
||||||
<div class="hierarchy-items-container">
|
<div class="hierarchy-items-container">
|
||||||
<UsersList />
|
<UsersList />
|
||||||
<!-- {#each $store.hierarchy.children as record}
|
|
||||||
<HierarchyRow node={record} type="record" />
|
|
||||||
{/each} -->
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<NavItem name="ACCESS_LEVELS" label="User Levels" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,30 @@
|
||||||
<script>
|
<script>
|
||||||
import { store } from "../builderStore"
|
import { store, backendUiStore } from "../builderStore"
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
import { CheckIcon } from "../common/Icons"
|
import { CheckIcon } from "../common/Icons"
|
||||||
|
|
||||||
$: instances = $store.appInstances
|
$: instances = $store.appInstances
|
||||||
|
|
||||||
function selectDatabase(databaseId) {
|
function selectDatabase(database) {
|
||||||
store.update(state => {
|
backendUiStore.actions.database.select(database)
|
||||||
state.currentlySelectedDatabase = databaseId
|
backendUiStore.actions.navigate("DATABASE")
|
||||||
return state
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<ul>
|
<ul>
|
||||||
{#each $store.appInstances as { id, name }}
|
{#each $store.appInstances as database}
|
||||||
<li>
|
<li>
|
||||||
<span class="icon">
|
<span class="icon">
|
||||||
{#if id === $store.currentlySelectedDatabase}
|
{#if database.id === $backendUiStore.selectedDatabase.id}
|
||||||
<CheckIcon />
|
<CheckIcon />
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class:active={id === $store.currentlySelectedDatabase}
|
class:active={database.id === $backendUiStore.selectedDatabase.id}
|
||||||
on:click={() => selectDatabase(id)}>
|
on:click={() => selectDatabase(database)}>
|
||||||
{name}
|
{database.name}
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte";
|
import { getContext } from "svelte"
|
||||||
import { store } from "../builderStore"
|
import { store, backendUiStore } from "../builderStore"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
export let level = 0
|
export let level = 0
|
||||||
|
@ -10,8 +10,8 @@
|
||||||
let navActive = ""
|
let navActive = ""
|
||||||
|
|
||||||
const ICON_MAP = {
|
const ICON_MAP = {
|
||||||
index: "ri-equalizer-line",
|
index: "ri-eye-line",
|
||||||
record: "ri-list-settings-line"
|
record: "ri-list-settings-line",
|
||||||
}
|
}
|
||||||
|
|
||||||
store.subscribe(state => {
|
store.subscribe(state => {
|
||||||
|
@ -19,13 +19,19 @@
|
||||||
navActive = node.nodeId === state.currentNode.nodeId
|
navActive = node.nodeId === state.currentNode.nodeId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function selectHierarchyItem(node) {
|
||||||
|
store.selectExistingNode(node.nodeId)
|
||||||
|
const modalType = node.type === "index" ? "VIEW" : "MODEL"
|
||||||
|
backendUiStore.actions.modals.show(modalType)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
on:click={() => store.selectExistingNode(node.nodeId)}
|
on:click={() => selectHierarchyItem(node)}
|
||||||
class="budibase__nav-item hierarchy-item"
|
class="budibase__nav-item hierarchy-item"
|
||||||
class:capitalized={type === "record"}
|
class:capitalized={type === 'record'}
|
||||||
style="padding-left: {20 + level * 20}px"
|
style="padding-left: {20 + level * 20}px"
|
||||||
class:selected={navActive}>
|
class:selected={navActive}>
|
||||||
<i class={ICON_MAP[type]} />
|
<i class={ICON_MAP[type]} />
|
||||||
|
@ -44,12 +50,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.hierarchy-item {
|
.hierarchy-item {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
}
|
}
|
||||||
|
|
||||||
.capitalized {
|
.capitalized {
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,17 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
import { getContext, setContext } from "svelte";
|
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
|
import { backendUiStore } from "../builderStore";
|
||||||
|
|
||||||
export let name = ""
|
export let name = ""
|
||||||
export let label = ""
|
export let label = ""
|
||||||
|
|
||||||
$: navActive = getContext("activeNav") === name
|
$: navActive = $backendUiStore.leftNavItem === name
|
||||||
|
|
||||||
// store.subscribe(db => {
|
const setActive = () => backendUiStore.actions.navigate(name)
|
||||||
// navActive = db.activeNav === name
|
|
||||||
// })
|
|
||||||
|
|
||||||
const setActive = () => setContext("activeNav", name);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -1,35 +1,19 @@
|
||||||
<script>
|
<script>
|
||||||
import { store } from "../builderStore"
|
import { store, backendUiStore } from "../builderStore"
|
||||||
import HierarchyRow from "./HierarchyRow.svelte"
|
import HierarchyRow from "./HierarchyRow.svelte"
|
||||||
import DropdownButton from "../common/DropdownButton.svelte"
|
import DropdownButton from "../common/DropdownButton.svelte"
|
||||||
import { hierarchy as hierarchyFunctions } from "../../../core/src"
|
import { hierarchy as hierarchyFunctions } from "../../../core/src"
|
||||||
import NavItem from "./NavItem.svelte"
|
import NavItem from "./NavItem.svelte"
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
|
|
||||||
const newRootRecord = () => {
|
|
||||||
store.newRootRecord()
|
|
||||||
}
|
|
||||||
|
|
||||||
const newRootIndex = () => {
|
|
||||||
store.newRootIndex()
|
|
||||||
}
|
|
||||||
|
|
||||||
const newChildRecord = () => {
|
|
||||||
store.newChildRecord()
|
|
||||||
}
|
|
||||||
|
|
||||||
const newChildIndex = () => {
|
|
||||||
store.newChildIndex()
|
|
||||||
}
|
|
||||||
|
|
||||||
const defaultNewChildActions = [
|
const defaultNewChildActions = [
|
||||||
{
|
{
|
||||||
label: "New Root Record",
|
label: "New Root Record",
|
||||||
onclick: newRootRecord,
|
onclick: store.newRootRecord,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "New Root Index",
|
label: "New Root Index",
|
||||||
onclick: newRootIndex,
|
onclick: store.newRootIndex,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -46,19 +30,19 @@
|
||||||
newChildActions = [
|
newChildActions = [
|
||||||
{
|
{
|
||||||
label: "New Root Record",
|
label: "New Root Record",
|
||||||
onclick: newRootRecord,
|
onclick: store.newRootRecord,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "New Root Index",
|
label: "New Root Index",
|
||||||
onclick: newRootIndex,
|
onclick: store.newRootIndex,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: `New Child Record of ${db.currentNode.name}`,
|
label: `New Child Record of ${db.currentNode.name}`,
|
||||||
onclick: newChildRecord,
|
onclick: store.newChildRecord,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: `New Index on ${db.currentNode.name}`,
|
label: `New Index on ${db.currentNode.name}`,
|
||||||
onclick: newChildIndex,
|
onclick: store.newChildIndex,
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -72,12 +56,22 @@
|
||||||
<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 hoverable" />
|
<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 class="hoverable" on:click={newRootRecord}>
|
<li
|
||||||
|
class="hoverable"
|
||||||
|
on:click={() => {
|
||||||
|
store.newRootRecord()
|
||||||
|
backendUiStore.actions.modals.show('MODEL')
|
||||||
|
}}>
|
||||||
Model
|
Model
|
||||||
</li>
|
</li>
|
||||||
<li class="hoverable" on:click={newRootIndex}>
|
<li
|
||||||
|
class="hoverable"
|
||||||
|
on:click={() => {
|
||||||
|
store.newRootIndex()
|
||||||
|
backendUiStore.actions.modals.show('VIEW')
|
||||||
|
}}>
|
||||||
View
|
View
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -237,6 +237,7 @@ module.exports = (config, app) => {
|
||||||
} else {
|
} else {
|
||||||
ctx.response.status = StatusCodes.UNAUTHORIZED
|
ctx.response.status = StatusCodes.UNAUTHORIZED
|
||||||
}
|
}
|
||||||
|
next()
|
||||||
})
|
})
|
||||||
.post("/:appname/api/changeMyPassword", routeHandlers.changeMyPassword)
|
.post("/:appname/api/changeMyPassword", routeHandlers.changeMyPassword)
|
||||||
.post(
|
.post(
|
||||||
|
@ -319,8 +320,4 @@ module.exports = (config, app) => {
|
||||||
.post("/:appname/api/apphierarchy", routeHandlers.saveAppHierarchy)
|
.post("/:appname/api/apphierarchy", routeHandlers.saveAppHierarchy)
|
||||||
|
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
front end get authenticateTemporaryAccess {}
|
|
||||||
*/
|
|
Loading…
Reference in New Issue