formatting
This commit is contained in:
parent
ff73793b4c
commit
f82a954666
|
@ -107,7 +107,7 @@ const lodash_fp_exports = [
|
||||||
"findIndex",
|
"findIndex",
|
||||||
"compose",
|
"compose",
|
||||||
"get",
|
"get",
|
||||||
"tap"
|
"tap",
|
||||||
]
|
]
|
||||||
|
|
||||||
const lodash_exports = [
|
const lodash_exports = [
|
||||||
|
@ -164,7 +164,9 @@ export default {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
replace({
|
replace({
|
||||||
"process.env.NODE_ENV": JSON.stringify(production ? "production" : "development")
|
"process.env.NODE_ENV": JSON.stringify(
|
||||||
|
production ? "production" : "development"
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
svelte({
|
svelte({
|
||||||
|
|
|
@ -11,16 +11,15 @@
|
||||||
FRONTEND: "frontend",
|
FRONTEND: "frontend",
|
||||||
}
|
}
|
||||||
|
|
||||||
let selectedTab = TABS.BACKEND
|
let selectedTab = TABS.BACKEND
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="root">
|
<div class="root">
|
||||||
|
|
||||||
<div class="top-nav">
|
<div class="top-nav">
|
||||||
<div class="topleftnav">
|
<div class="topleftnav">
|
||||||
<button class="home-logo">
|
<button class="home-logo">
|
||||||
<img src="/_builder/assets/budibase-emblem-white.svg" />
|
<img src="/_builder/assets/budibase-emblem-white.svg" />
|
||||||
</button>
|
</button>
|
||||||
<!-- <IconButton icon="home"
|
<!-- <IconButton icon="home"
|
||||||
color="var(--slate)"
|
color="var(--slate)"
|
||||||
|
@ -28,13 +27,13 @@
|
||||||
<span
|
<span
|
||||||
class:active={selectedTab === TABS.BACKEND}
|
class:active={selectedTab === TABS.BACKEND}
|
||||||
class="topnavitem"
|
class="topnavitem"
|
||||||
on:click={() => selectedTab = TABS.BACKEND}>
|
on:click={() => (selectedTab = TABS.BACKEND)}>
|
||||||
Backend
|
Backend
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class:active={selectedTab === TABS.FRONTEND}
|
class:active={selectedTab === TABS.FRONTEND}
|
||||||
class="topnavitem"
|
class="topnavitem"
|
||||||
on:click={() => selectedTab = TABS.FRONTEND}>
|
on:click={() => (selectedTab = TABS.FRONTEND)}>
|
||||||
Frontend
|
Frontend
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,13 +43,13 @@
|
||||||
class:active={selectedTab === TABS.FRONTEND}
|
class:active={selectedTab === TABS.FRONTEND}
|
||||||
class="topnavitemright"
|
class="topnavitemright"
|
||||||
on:click={() => selectedTab === TABS.FRONTEND}>
|
on:click={() => selectedTab === TABS.FRONTEND}>
|
||||||
<SettingsIcon />
|
<SettingsIcon />
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
class:active={selectedTab === TABS.FRONTEND}
|
class:active={selectedTab === TABS.FRONTEND}
|
||||||
class="topnavitemright"
|
class="topnavitemright"
|
||||||
on:click={() => selectedTab === TABS.FRONTEND}>
|
on:click={() => selectedTab === TABS.FRONTEND}>
|
||||||
<PreviewIcon />
|
<PreviewIcon />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -140,7 +139,7 @@
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex:1;
|
flex: 1;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,12 @@
|
||||||
|
|
||||||
let editingLevel = null
|
let editingLevel = null
|
||||||
let editingLevelIsNew = false
|
let editingLevelIsNew = false
|
||||||
$: {
|
$: {
|
||||||
if (editingLevel !== null) {
|
if (editingLevel !== null) {
|
||||||
backendUiStore.actions.modals.show("ACCESS_LEVELS")
|
backendUiStore.actions.modals.show("ACCESS_LEVELS")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$: modalOpen = $backendUiStore.visibleModal === 'ACCESS_LEVELS'
|
$: modalOpen = $backendUiStore.visibleModal === "ACCESS_LEVELS"
|
||||||
|
|
||||||
let allPermissions = []
|
let allPermissions = []
|
||||||
store.subscribe(db => {
|
store.subscribe(db => {
|
||||||
|
@ -92,15 +92,14 @@
|
||||||
onClosed={backendUiStore.actions.modals.hide}
|
onClosed={backendUiStore.actions.modals.hide}
|
||||||
bind:isOpen={modalOpen}
|
bind:isOpen={modalOpen}
|
||||||
title={modalOpen ? 'Edit Access Level' : 'Create Access Level'}>
|
title={modalOpen ? 'Edit Access Level' : 'Create Access Level'}>
|
||||||
<AccessLevelView
|
<AccessLevelView
|
||||||
level={editingLevel}
|
level={editingLevel}
|
||||||
{allPermissions}
|
{allPermissions}
|
||||||
onFinished={onEditingFinished}
|
onFinished={onEditingFinished}
|
||||||
isNew={editingLevelIsNew}
|
isNew={editingLevelIsNew}
|
||||||
allLevels={$store.accessLevels.levels}
|
allLevels={$store.accessLevels.levels}
|
||||||
hierarchy={$store.hierarchy}
|
hierarchy={$store.hierarchy}
|
||||||
actions={$store.actions}
|
actions={$store.actions} />
|
||||||
/>
|
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -39,7 +39,7 @@ const css_map = {
|
||||||
},
|
},
|
||||||
direction: {
|
direction: {
|
||||||
name: "flex-direction",
|
name: "flex-direction",
|
||||||
generate: self
|
generate: self,
|
||||||
},
|
},
|
||||||
gridarea: {
|
gridarea: {
|
||||||
name: "grid-area",
|
name: "grid-area",
|
||||||
|
@ -113,7 +113,7 @@ const object_to_css_string = [
|
||||||
export const generate_css = ({ layout, position }) => {
|
export const generate_css = ({ layout, position }) => {
|
||||||
let _layout = pipe(layout, object_to_css_string)
|
let _layout = pipe(layout, object_to_css_string)
|
||||||
if (_layout.length) {
|
if (_layout.length) {
|
||||||
_layout += `\ndisplay: ${_layout.includes("flex") ? "flex" : "grid"};`;
|
_layout += `\ndisplay: ${_layout.includes("flex") ? "flex" : "grid"};`
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { getStore } from "./store"
|
import { getStore } from "./store"
|
||||||
import { getBackendUiStore } from "./store/backend"
|
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 backendUiStore = getBackendUiStore()
|
||||||
|
@ -8,7 +8,7 @@ export const backendUiStore = getBackendUiStore()
|
||||||
export const initialise = async () => {
|
export const initialise = async () => {
|
||||||
try {
|
try {
|
||||||
if (process.env.NODE_ENV === "production") {
|
if (process.env.NODE_ENV === "production") {
|
||||||
LogRocket.init("knlald/budibase");
|
LogRocket.init("knlald/budibase")
|
||||||
}
|
}
|
||||||
setupRouter(store)
|
setupRouter(store)
|
||||||
await store.initialise()
|
await store.initialise()
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
import { writable } from "svelte/store";
|
import { writable } from "svelte/store"
|
||||||
import api from "../api"
|
import api from "../api"
|
||||||
import {
|
import { cloneDeep, sortBy, find, remove } from "lodash/fp"
|
||||||
cloneDeep,
|
|
||||||
sortBy,
|
|
||||||
find,
|
|
||||||
remove
|
|
||||||
} from "lodash/fp"
|
|
||||||
import { hierarchy as hierarchyFunctions } from "../../../../core/src"
|
import { hierarchy as hierarchyFunctions } from "../../../../core/src"
|
||||||
import {
|
import {
|
||||||
getNode,
|
getNode,
|
||||||
|
@ -14,7 +9,7 @@ import {
|
||||||
templateApi,
|
templateApi,
|
||||||
isIndex,
|
isIndex,
|
||||||
canDeleteIndex,
|
canDeleteIndex,
|
||||||
canDeleteRecord
|
canDeleteRecord,
|
||||||
} from "../../common/core"
|
} from "../../common/core"
|
||||||
|
|
||||||
export const getBackendUiStore = () => {
|
export const getBackendUiStore = () => {
|
||||||
|
@ -22,7 +17,7 @@ export const getBackendUiStore = () => {
|
||||||
leftNavItem: "DATABASE",
|
leftNavItem: "DATABASE",
|
||||||
selectedView: {
|
selectedView: {
|
||||||
records: [],
|
records: [],
|
||||||
name: ""
|
name: "",
|
||||||
},
|
},
|
||||||
breadcrumbs: [],
|
breadcrumbs: [],
|
||||||
selectedDatabase: {},
|
selectedDatabase: {},
|
||||||
|
@ -34,54 +29,61 @@ export const getBackendUiStore = () => {
|
||||||
store.actions = {
|
store.actions = {
|
||||||
navigate: name => store.update(state => ({ ...state, leftNavItem: name })),
|
navigate: name => store.update(state => ({ ...state, leftNavItem: name })),
|
||||||
database: {
|
database: {
|
||||||
select: db => store.update(state => {
|
select: db =>
|
||||||
|
store.update(state => {
|
||||||
state.selectedDatabase = db
|
state.selectedDatabase = db
|
||||||
state.breadcrumbs = [db.name]
|
state.breadcrumbs = [db.name]
|
||||||
return state
|
return state
|
||||||
})
|
}),
|
||||||
},
|
},
|
||||||
records: {
|
records: {
|
||||||
delete: () => store.update(state => {
|
delete: () =>
|
||||||
state.selectedView = state.selectedView
|
store.update(state => {
|
||||||
return state
|
state.selectedView = state.selectedView
|
||||||
}),
|
return state
|
||||||
view: record => store.update(state => {
|
}),
|
||||||
state.breadcrumbs = [state.selectedDatabase.name, record.id]
|
view: record =>
|
||||||
return state
|
store.update(state => {
|
||||||
}),
|
state.breadcrumbs = [state.selectedDatabase.name, record.id]
|
||||||
select: record => store.update(state => {
|
return state
|
||||||
state.selectedRecord = record
|
}),
|
||||||
return state
|
select: record =>
|
||||||
})
|
store.update(state => {
|
||||||
|
state.selectedRecord = record
|
||||||
|
return state
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
views: {
|
views: {
|
||||||
select: view => store.update(state => {
|
select: view =>
|
||||||
state.selectedView = view
|
store.update(state => {
|
||||||
return state
|
state.selectedView = view
|
||||||
})
|
return state
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
modals: {
|
modals: {
|
||||||
show: modal => store.update(state => ({ ...state, visibleModal: modal })),
|
show: modal => store.update(state => ({ ...state, visibleModal: modal })),
|
||||||
hide: () => store.update(state => ({ ...state, visibleModal: null }))
|
hide: () => store.update(state => ({ ...state, visibleModal: null })),
|
||||||
},
|
},
|
||||||
users: {
|
users: {
|
||||||
create: user => store.update(state => {
|
create: user =>
|
||||||
state.users.push(user)
|
store.update(state => {
|
||||||
state.users = state.users
|
state.users.push(user)
|
||||||
return state
|
state.users = state.users
|
||||||
})
|
return state
|
||||||
}
|
}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return store
|
return store
|
||||||
};
|
}
|
||||||
|
|
||||||
// Store Actions
|
// Store Actions
|
||||||
export const createShadowHierarchy = hierarchy => constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
|
export const createShadowHierarchy = hierarchy =>
|
||||||
|
constructHierarchy(JSON.parse(JSON.stringify(hierarchy)))
|
||||||
|
|
||||||
export const createDatabaseForApp = store => appInstance => {
|
export const createDatabaseForApp = store => appInstance => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
state.appInstances.push(appInstance)
|
state.appInstances.push(appInstance)
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -244,7 +246,9 @@ export const deleteCurrentNode = store => () => {
|
||||||
|
|
||||||
export const saveField = store => field => {
|
export const saveField = store => field => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
state.currentNode.fields = state.currentNode.fields.filter(f => f.id !== field.id)
|
state.currentNode.fields = state.currentNode.fields.filter(
|
||||||
|
f => f.id !== field.id
|
||||||
|
)
|
||||||
|
|
||||||
templateApi(state.hierarchy).addField(state.currentNode, field)
|
templateApi(state.hierarchy).addField(state.currentNode, field)
|
||||||
return state
|
return state
|
||||||
|
@ -253,13 +257,17 @@ export const saveField = store => field => {
|
||||||
|
|
||||||
export const deleteField = store => field => {
|
export const deleteField = store => field => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
state.currentNode.fields = state.currentNode.fields.filter(f => f.name !== field.name)
|
state.currentNode.fields = state.currentNode.fields.filter(
|
||||||
|
f => f.name !== field.name
|
||||||
|
)
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const incrementAccessLevelsVersion = state => {
|
const incrementAccessLevelsVersion = state => {
|
||||||
state.accessLevels.version = state.accessLevels.version ? state.accessLevels.version + 1 : 1
|
state.accessLevels.version = state.accessLevels.version
|
||||||
|
? state.accessLevels.version + 1
|
||||||
|
: 1
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,7 +280,9 @@ export const saveLevel = store => (newLevel, isNew, oldLevel = null) => {
|
||||||
: find(a => a.name === oldLevel.name)(levels)
|
: find(a => a.name === oldLevel.name)(levels)
|
||||||
|
|
||||||
if (existingLevel) {
|
if (existingLevel) {
|
||||||
state.accessLevels.levels = levels.map(level => level === existingLevel ? newLevel : level)
|
state.accessLevels.levels = levels.map(level =>
|
||||||
|
level === existingLevel ? newLevel : level
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
state.accessLevels.levels.push(newLevel)
|
state.accessLevels.levels.push(newLevel)
|
||||||
}
|
}
|
||||||
|
@ -286,7 +296,9 @@ export const saveLevel = store => (newLevel, isNew, oldLevel = null) => {
|
||||||
|
|
||||||
export const deleteLevel = store => level => {
|
export const deleteLevel = store => level => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
state.accessLevels.levels = state.accessLevels.levels.filter(t => t.name !== level.name)
|
state.accessLevels.levels = state.accessLevels.levels.filter(
|
||||||
|
t => t.name !== level.name
|
||||||
|
)
|
||||||
incrementAccessLevelsVersion(s)
|
incrementAccessLevelsVersion(s)
|
||||||
saveBackend(state)
|
saveBackend(state)
|
||||||
return state
|
return state
|
||||||
|
@ -300,7 +312,9 @@ export const saveAction = store => (newAction, isNew, oldAction = null) => {
|
||||||
: find(a => a.name === oldAction.name)(s.actions)
|
: find(a => a.name === oldAction.name)(s.actions)
|
||||||
|
|
||||||
if (existingAction) {
|
if (existingAction) {
|
||||||
s.actions = s.actions.map(action => action === existingAction ? newAction : action)
|
s.actions = s.actions.map(action =>
|
||||||
|
action === existingAction ? newAction : action
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
s.actions.push(newAction)
|
s.actions.push(newAction)
|
||||||
}
|
}
|
||||||
|
@ -311,9 +325,9 @@ export const saveAction = store => (newAction, isNew, oldAction = null) => {
|
||||||
|
|
||||||
export const deleteAction = store => action => {
|
export const deleteAction = store => action => {
|
||||||
store.update(state => {
|
store.update(state => {
|
||||||
state.actions = state.actions.filter(a => a.name !== action.name);
|
state.actions = state.actions.filter(a => a.name !== action.name)
|
||||||
saveBackend(state);
|
saveBackend(state)
|
||||||
return state;
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,4 +352,4 @@ export const deleteTrigger = store => trigger => {
|
||||||
s.triggers = s.triggers.filter(t => t.name !== trigger.name)
|
s.triggers = s.triggers.filter(t => t.name !== trigger.name)
|
||||||
return s
|
return s
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,6 @@
|
||||||
import {
|
import { filter, cloneDeep, last, concat, isEmpty, values } from "lodash/fp"
|
||||||
filter,
|
import { pipe, getNode, constructHierarchy } from "../../common/core"
|
||||||
cloneDeep,
|
import * as backendStoreActions from "./backend"
|
||||||
last,
|
|
||||||
concat,
|
|
||||||
isEmpty,
|
|
||||||
values,
|
|
||||||
} from "lodash/fp"
|
|
||||||
import {
|
|
||||||
pipe,
|
|
||||||
getNode,
|
|
||||||
constructHierarchy,
|
|
||||||
} 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"
|
||||||
|
@ -224,29 +213,27 @@ const _saveScreen = async (store, s, screen) => {
|
||||||
screen
|
screen
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
if (currentPageScreens.includes(screen)) return
|
||||||
|
|
||||||
if(currentPageScreens.includes(screen)) return
|
const screens = [...currentPageScreens, screen]
|
||||||
|
|
||||||
const screens = [
|
|
||||||
...currentPageScreens,
|
|
||||||
screen,
|
|
||||||
]
|
|
||||||
|
|
||||||
store.update(innerState => {
|
store.update(innerState => {
|
||||||
innerState.pages[s.currentPageName]._screens = screens
|
innerState.pages[s.currentPageName]._screens = screens
|
||||||
innerState.screens = screens
|
innerState.screens = screens
|
||||||
innerState.currentPreviewItem = screen
|
innerState.currentPreviewItem = screen
|
||||||
const safeProps = makePropsSafe(
|
const safeProps = makePropsSafe(
|
||||||
getComponentDefinition(innerState.components, screen.props._component),
|
getComponentDefinition(
|
||||||
|
innerState.components,
|
||||||
|
screen.props._component
|
||||||
|
),
|
||||||
screen.props
|
screen.props
|
||||||
)
|
)
|
||||||
innerState.currentComponentInfo = safeProps
|
innerState.currentComponentInfo = safeProps
|
||||||
screen.props = safeProps
|
screen.props = safeProps
|
||||||
|
|
||||||
_savePage(innerState)
|
_savePage(innerState)
|
||||||
return innerState
|
return innerState
|
||||||
})
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return s
|
return s
|
||||||
|
@ -485,7 +472,7 @@ const setCurrentPage = store => pageName => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getComponentDefinition = (components, name) =>
|
const getComponentDefinition = (components, name) =>
|
||||||
components.find(c => c.name === name)
|
components.find(c => c.name === name)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -544,7 +531,9 @@ const addTemplatedComponent = store => props => {
|
||||||
state.currentComponentInfo._children = state.currentComponentInfo._children.concat(
|
state.currentComponentInfo._children = state.currentComponentInfo._children.concat(
|
||||||
props
|
props
|
||||||
)
|
)
|
||||||
state.currentPreviewItem._css = generate_screen_css([state.currentPreviewItem.props])
|
state.currentPreviewItem._css = generate_screen_css([
|
||||||
|
state.currentPreviewItem.props,
|
||||||
|
])
|
||||||
|
|
||||||
setCurrentPageFunctions(state)
|
setCurrentPageFunctions(state)
|
||||||
_saveCurrentPreviewItem(state)
|
_saveCurrentPreviewItem(state)
|
||||||
|
|
|
@ -53,14 +53,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.uk-modal-footer {
|
||||||
|
background: var(--lightslate);
|
||||||
|
}
|
||||||
|
|
||||||
.uk-modal-footer {
|
.uk-modal-dialog {
|
||||||
background: var(--lightslate);
|
width: 400px;
|
||||||
}
|
border-radius: 5px;
|
||||||
|
}
|
||||||
.uk-modal-dialog {
|
|
||||||
width: 400px;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -7,12 +7,7 @@
|
||||||
{#if hasErrors}
|
{#if hasErrors}
|
||||||
<div uk-alert class="uk-alert-danger">
|
<div uk-alert class="uk-alert-danger">
|
||||||
{#each errors as error}
|
{#each errors as error}
|
||||||
<div>
|
<div>{error.field ? `${error.field}: ` : ''}{error.error}</div>
|
||||||
{error.field ? `${error.field}: ` : ''}{error.error}
|
|
||||||
</div>
|
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24">
|
height="24">
|
||||||
<path fill="none" d="M0 0h24v24H0z"/>
|
<path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10 10zM10.622 8.415a.4.4 0 00-.622.332v6.506a.4.4 0 00.622.332l4.879-3.252a.4.4 0 000-.666l-4.88-3.252z"
|
<path
|
||||||
fill="currentColor"/>
|
d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10-4.477 10-10
|
||||||
</svg>
|
10zM10.622 8.415a.4.4 0 00-.622.332v6.506a.4.4 0 00.622.332l4.879-3.252a.4.4
|
||||||
|
0 000-.666l-4.88-3.252z"
|
||||||
|
fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 349 B After Width: | Height: | Size: 362 B |
|
@ -3,6 +3,9 @@
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24">
|
height="24">
|
||||||
<path d="M0 0h24v24H0z" fill="none"/>
|
<path d="M0 0h24v24H0z" fill="none" />
|
||||||
<path d="M12 1l9.5 5.5v11L12 23l-9.5-5.5v-11L12 1zm0 14a3 3 0 1 0 0-6 3 3 0 0 0 0 6z" fill="currentColor"/>
|
<path
|
||||||
</svg>
|
d="M12 1l9.5 5.5v11L12 23l-9.5-5.5v-11L12 1zm0 14a3 3 0 1 0 0-6 3 3 0 0 0 0
|
||||||
|
6z"
|
||||||
|
fill="currentColor" />
|
||||||
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 244 B After Width: | Height: | Size: 263 B |
|
@ -18,4 +18,3 @@ export { default as AddIcon } from "./Add.svelte"
|
||||||
export { default as JavaScriptIcon } from "./JavaScript.svelte"
|
export { default as JavaScriptIcon } from "./JavaScript.svelte"
|
||||||
export { default as PreviewIcon } from "./Preview.svelte"
|
export { default as PreviewIcon } from "./Preview.svelte"
|
||||||
export { default as SettingsIcon } from "./Settings.svelte"
|
export { default as SettingsIcon } from "./Settings.svelte"
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={ukModal} uk-modal {id}>
|
<div bind:this={ukModal} uk-modal {id}>
|
||||||
|
|
|
@ -9,10 +9,7 @@
|
||||||
{#if icon}
|
{#if icon}
|
||||||
<i class={icon} />
|
<i class={icon} />
|
||||||
{/if}
|
{/if}
|
||||||
<select
|
<select class:adjusted={icon} on:change bind:value>
|
||||||
class:adjusted={icon}
|
|
||||||
on:change bind:value
|
|
||||||
>
|
|
||||||
<slot />
|
<slot />
|
||||||
</select>
|
</select>
|
||||||
<span class="arrow">
|
<span class="arrow">
|
||||||
|
|
|
@ -21,9 +21,7 @@
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<div class="button-container">
|
<div class="button-container">
|
||||||
{#if !$store.currentNodeIsNew}
|
{#if !$store.currentNodeIsNew}
|
||||||
<ActionButton alert on:click={deleteCurrentNode}>
|
<ActionButton alert on:click={deleteCurrentNode}>Delete</ActionButton>
|
||||||
Delete
|
|
||||||
</ActionButton>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<ActionButton color="secondary" on:click={store.saveCurrentNode}>
|
<ActionButton color="secondary" on:click={store.saveCurrentNode}>
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
CreateEditViewModal,
|
CreateEditViewModal,
|
||||||
CreateDatabaseModal,
|
CreateDatabaseModal,
|
||||||
DeleteRecordModal,
|
DeleteRecordModal,
|
||||||
CreateUserModal
|
CreateUserModal,
|
||||||
} from "./ModelDataTable/modals"
|
} from "./ModelDataTable/modals"
|
||||||
|
|
||||||
let selectedRecord
|
let selectedRecord
|
||||||
|
@ -64,9 +64,7 @@
|
||||||
<div class="root">
|
<div class="root">
|
||||||
<div class="node-view">
|
<div class="node-view">
|
||||||
<div class="database-actions">
|
<div class="database-actions">
|
||||||
<div class="budibase__label--big">
|
<div class="budibase__label--big">{breadcrumbs}</div>
|
||||||
{breadcrumbs}
|
|
||||||
</div>
|
|
||||||
{#if $backendUiStore.selectedDatabase.id}
|
{#if $backendUiStore.selectedDatabase.id}
|
||||||
<ActionButton
|
<ActionButton
|
||||||
primary
|
primary
|
||||||
|
@ -80,9 +78,7 @@
|
||||||
</div>
|
</div>
|
||||||
{#if $backendUiStore.selectedDatabase.id}
|
{#if $backendUiStore.selectedDatabase.id}
|
||||||
<ModelDataTable {selectRecord} />
|
<ModelDataTable {selectRecord} />
|
||||||
{:else}
|
{:else}Please select a database{/if}
|
||||||
Please select a database
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
flatten,
|
flatten,
|
||||||
map,
|
map,
|
||||||
remove,
|
remove,
|
||||||
keys
|
keys,
|
||||||
} from "lodash/fp"
|
} from "lodash/fp"
|
||||||
import Select from "../../common/Select.svelte"
|
import Select from "../../common/Select.svelte"
|
||||||
import { getIndexSchema } from "../../common/core"
|
import { getIndexSchema } from "../../common/core"
|
||||||
|
@ -23,13 +23,7 @@
|
||||||
|
|
||||||
const ITEMS_PER_PAGE = 10
|
const ITEMS_PER_PAGE = 10
|
||||||
// Internal headers we want to hide from the user
|
// Internal headers we want to hide from the user
|
||||||
const INTERNAL_HEADERS = [
|
const INTERNAL_HEADERS = ["key", "sortKey", "type", "id", "isNew"]
|
||||||
"key",
|
|
||||||
"sortKey",
|
|
||||||
"type",
|
|
||||||
"id",
|
|
||||||
"isNew"
|
|
||||||
]
|
|
||||||
|
|
||||||
let modalOpen = false
|
let modalOpen = false
|
||||||
let data = []
|
let data = []
|
||||||
|
@ -61,11 +55,7 @@
|
||||||
|
|
||||||
const getSchema = getIndexSchema($store.hierarchy)
|
const getSchema = getIndexSchema($store.hierarchy)
|
||||||
|
|
||||||
const childViewsForRecord = compose(
|
const childViewsForRecord = compose(flatten, map("indexes"), get("children"))
|
||||||
flatten,
|
|
||||||
map("indexes"),
|
|
||||||
get("children")
|
|
||||||
)
|
|
||||||
|
|
||||||
const hideInternalHeaders = compose(
|
const hideInternalHeaders = compose(
|
||||||
remove(headerName => INTERNAL_HEADERS.includes(headerName)),
|
remove(headerName => INTERNAL_HEADERS.includes(headerName)),
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
$: numPages = Math.ceil(data.length / ITEMS_PER_PAGE)
|
$: numPages = Math.ceil(data.length / ITEMS_PER_PAGE)
|
||||||
|
|
||||||
const next = () => {
|
const next = () => {
|
||||||
if (currentPage + 1 === numPages) return;
|
if (currentPage + 1 === numPages) return
|
||||||
currentPage = currentPage + 1
|
currentPage = currentPage + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
const previous = () => {
|
const previous = () => {
|
||||||
if (currentPage == 0) return;
|
if (currentPage == 0) return
|
||||||
currentPage = currentPage - 1
|
currentPage = currentPage - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export { default } from "./ModelDataTable.svelte"
|
export { default } from "./ModelDataTable.svelte"
|
||||||
|
|
|
@ -9,4 +9,4 @@
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
<ModelView />
|
<ModelView />
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -5,7 +5,11 @@
|
||||||
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, joinKey, getExactNodeForKey } from "../../../common/core"
|
import {
|
||||||
|
getNewRecord,
|
||||||
|
joinKey,
|
||||||
|
getExactNodeForKey,
|
||||||
|
} from "../../../common/core"
|
||||||
import RecordFieldControl from "./RecordFieldControl.svelte"
|
import RecordFieldControl from "./RecordFieldControl.svelte"
|
||||||
import * as api from "../api"
|
import * as api from "../api"
|
||||||
import ErrorsBox from "../../../common/ErrorsBox.svelte"
|
import ErrorsBox from "../../../common/ErrorsBox.svelte"
|
||||||
|
@ -14,12 +18,8 @@
|
||||||
export let onClosed
|
export let onClosed
|
||||||
|
|
||||||
let errors = []
|
let errors = []
|
||||||
|
|
||||||
const childModelsForModel = compose(
|
const childModelsForModel = compose(flatten, map("children"), get("children"))
|
||||||
flatten,
|
|
||||||
map("children"),
|
|
||||||
get("children")
|
|
||||||
)
|
|
||||||
|
|
||||||
$: currentAppInfo = {
|
$: currentAppInfo = {
|
||||||
appname: $store.appname,
|
appname: $store.appname,
|
||||||
|
@ -31,24 +31,28 @@
|
||||||
|
|
||||||
let selectedModel
|
let selectedModel
|
||||||
$: {
|
$: {
|
||||||
if (record) {
|
if (record) {
|
||||||
selectedModel = getExactNodeForKey($store.hierarchy)(record.key)
|
selectedModel = getExactNodeForKey($store.hierarchy)(record.key)
|
||||||
} else {
|
} else {
|
||||||
selectedModel = selectedModel || models[0]
|
selectedModel = selectedModel || models[0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$: modelFields = selectedModel
|
$: modelFields = selectedModel ? selectedModel.fields : []
|
||||||
? selectedModel.fields
|
|
||||||
: []
|
|
||||||
|
|
||||||
function getCurrentCollectionKey(selectedRecord) {
|
function getCurrentCollectionKey(selectedRecord) {
|
||||||
return selectedRecord
|
return selectedRecord
|
||||||
? joinKey(selectedRecord.key, selectedModel.collectionName)
|
? joinKey(selectedRecord.key, selectedModel.collectionName)
|
||||||
: joinKey(selectedModel.collectionName)
|
: joinKey(selectedModel.collectionName)
|
||||||
}
|
}
|
||||||
|
|
||||||
$: editingRecord = record || editingRecord || getNewRecord(selectedModel, getCurrentCollectionKey($backendUiStore.selectedRecord))
|
$: editingRecord =
|
||||||
|
record ||
|
||||||
|
editingRecord ||
|
||||||
|
getNewRecord(
|
||||||
|
selectedModel,
|
||||||
|
getCurrentCollectionKey($backendUiStore.selectedRecord)
|
||||||
|
)
|
||||||
|
|
||||||
function closed() {
|
function closed() {
|
||||||
editingRecord = null
|
editingRecord = null
|
||||||
|
@ -56,10 +60,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveRecord() {
|
async function saveRecord() {
|
||||||
const recordResponse = await api.saveRecord(
|
const recordResponse = await api.saveRecord(editingRecord, currentAppInfo)
|
||||||
editingRecord,
|
|
||||||
currentAppInfo
|
|
||||||
)
|
|
||||||
backendUiStore.update(state => {
|
backendUiStore.update(state => {
|
||||||
state.selectedView = state.selectedView
|
state.selectedView = state.selectedView
|
||||||
return state
|
return state
|
||||||
|
@ -83,11 +84,8 @@
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#each (modelFields || []) as field}
|
{#each modelFields || [] as field}
|
||||||
<RecordFieldControl
|
<RecordFieldControl record={editingRecord} {field} {errors} />
|
||||||
record={editingRecord}
|
|
||||||
{field}
|
|
||||||
{errors} />
|
|
||||||
{/each}
|
{/each}
|
||||||
</form>
|
</form>
|
||||||
<footer>
|
<footer>
|
||||||
|
|
|
@ -23,11 +23,7 @@
|
||||||
enabled: true,
|
enabled: true,
|
||||||
temporaryAccessId: "",
|
temporaryAccessId: "",
|
||||||
}
|
}
|
||||||
const response = await api.createUser(
|
const response = await api.createUser(password, user, currentAppInfo)
|
||||||
password,
|
|
||||||
user,
|
|
||||||
currentAppInfo
|
|
||||||
)
|
|
||||||
backendUiStore.actions.users.save(user)
|
backendUiStore.actions.users.save(user)
|
||||||
onClosed()
|
onClosed()
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
$: currentAppInfo = {
|
$: currentAppInfo = {
|
||||||
appname: $store.appname,
|
appname: $store.appname,
|
||||||
instanceId: $backendUiStore.selectedDatabase.id
|
instanceId: $backendUiStore.selectedDatabase.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClosed() {
|
function onClosed() {
|
||||||
|
@ -45,7 +45,7 @@
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-actions {
|
.modal-actions {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -62,6 +62,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
margin: 0 0 0 10px;
|
margin: 0 0 0 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,41 +1,38 @@
|
||||||
<script>
|
<script>
|
||||||
import Select from "../../../common/Select.svelte"
|
import Select from "../../../common/Select.svelte"
|
||||||
|
|
||||||
export let record
|
export let record
|
||||||
export let field
|
export let field
|
||||||
export let errors
|
export let errors
|
||||||
|
|
||||||
$: isDropdown =
|
$: isDropdown =
|
||||||
field.type === "string"
|
field.type === "string" &&
|
||||||
&& field.typeOptions.values
|
field.typeOptions.values &&
|
||||||
&& field.typeOptions.values.length > 0
|
field.typeOptions.values.length > 0
|
||||||
|
|
||||||
$: isNumber = field.type === "number"
|
$: isNumber = field.type === "number"
|
||||||
|
|
||||||
$: isText =
|
$: isText = field.type === "string" && !isDropdown
|
||||||
field.type === "string"
|
|
||||||
&& !isDropdown
|
|
||||||
|
|
||||||
$: isCheckbox = field.type === "bool"
|
$: isCheckbox = field.type === "bool"
|
||||||
|
|
||||||
$: isError = errors && errors.some(e => e.field && e.field === field.name)
|
$: isError = errors && errors.some(e => e.field && e.field === field.name)
|
||||||
|
|
||||||
$: isDatetime = field.type === "datetime"
|
|
||||||
|
|
||||||
|
$: isDatetime = field.type === "datetime"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="uk-margin">
|
<div class="uk-margin">
|
||||||
{#if !isCheckbox}
|
{#if !isCheckbox}
|
||||||
<label class="uk-form-label" for={field.name}>{field.label}</label>
|
<label class="uk-form-label" for={field.name}>{field.label}</label>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="uk-form-controls">
|
<div class="uk-form-controls">
|
||||||
{#if isDropdown}
|
{#if isDropdown}
|
||||||
<Select bind:value={record[field.name]}>
|
<Select bind:value={record[field.name]}>
|
||||||
<option value=""></option>
|
<option value="" />
|
||||||
{#each field.typeOptions.values as val}
|
{#each field.typeOptions.values as val}
|
||||||
<option value={val}>{val}</option>
|
<option value={val}>{val}</option>
|
||||||
{/each}
|
{/each}
|
||||||
</Select>
|
</Select>
|
||||||
{:else if isText}
|
{:else if isText}
|
||||||
<input
|
<input
|
||||||
class="uk-input"
|
class="uk-input"
|
||||||
|
@ -61,9 +58,9 @@ $: isDatetime = field.type === "datetime"
|
||||||
class="uk-checkbox"
|
class="uk-checkbox"
|
||||||
class:uk-form-danger={isError}
|
class:uk-form-danger={isError}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
bind:checked={record[field.name]} >
|
bind:checked={record[field.name]} />
|
||||||
{field.label}
|
{field.label}
|
||||||
</label>
|
</label>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
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 CreateEditViewModal } from "./CreateEditView.svelte"
|
||||||
export { default as CreateDatabaseModal } from "./CreateDatabase.svelte";
|
export { default as CreateDatabaseModal } from "./CreateDatabase.svelte"
|
||||||
export { default as CreateUserModal } from "./CreateUser.svelte";
|
export { default as CreateUserModal } from "./CreateUser.svelte"
|
||||||
|
|
|
@ -39,10 +39,8 @@
|
||||||
$: models = $store.hierarchy.children
|
$: models = $store.hierarchy.children
|
||||||
$: parent = record && record.parent()
|
$: parent = record && record.parent()
|
||||||
$: isChildModel = parent && parent.name !== "root"
|
$: isChildModel = parent && parent.name !== "root"
|
||||||
$: modelExistsInHierarchy = $store.currentNode && getNode(
|
$: modelExistsInHierarchy =
|
||||||
$store.hierarchy,
|
$store.currentNode && getNode($store.hierarchy, $store.currentNode.nodeId)
|
||||||
$store.currentNode.nodeId
|
|
||||||
)
|
|
||||||
|
|
||||||
store.subscribe($store => {
|
store.subscribe($store => {
|
||||||
record = $store.currentNode
|
record = $store.currentNode
|
||||||
|
|
|
@ -15,5 +15,5 @@ import "codemirror/theme/monokai.css"
|
||||||
|
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
const app = new App({
|
const app = new App({
|
||||||
target: document.getElementById("app")
|
target: document.getElementById("app"),
|
||||||
})
|
})
|
||||||
|
|
|
@ -30,10 +30,9 @@
|
||||||
<div class="components-list-container">
|
<div class="components-list-container">
|
||||||
<div class="nav-group-header">
|
<div class="nav-group-header">
|
||||||
<div class="hierarchy-title">Users</div>
|
<div class="hierarchy-title">Users</div>
|
||||||
<i
|
<i
|
||||||
class="ri-add-line hoverable"
|
class="ri-add-line hoverable"
|
||||||
on:click={() => backendUiStore.actions.modals.show('USER')}
|
on:click={() => backendUiStore.actions.modals.show('USER')} />
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { tick } from "svelte";
|
import { tick } from "svelte"
|
||||||
import { store, backendUiStore } 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"
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: rgba(0,0,0,0);
|
background: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
import { backendUiStore } from "../builderStore";
|
import { backendUiStore } from "../builderStore"
|
||||||
|
|
||||||
export let name = ""
|
export let name = ""
|
||||||
export let label = ""
|
export let label = ""
|
||||||
|
|
||||||
$: navActive = $backendUiStore.leftNavItem === name
|
$: navActive = $backendUiStore.leftNavItem === name
|
||||||
|
|
||||||
const setActive = () => backendUiStore.actions.navigate(name)
|
const setActive = () => backendUiStore.actions.navigate(name)
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -30,16 +30,8 @@
|
||||||
<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
|
<li class="hoverable" on:click={newModel}>Model</li>
|
||||||
class="hoverable"
|
<li class="hoverable" on:click={newView}>View</li>
|
||||||
on:click={newModel}>
|
|
||||||
Model
|
|
||||||
</li>
|
|
||||||
<li
|
|
||||||
class="hoverable"
|
|
||||||
on:click={newView}>
|
|
||||||
View
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { store, backendUiStore } from "../builderStore"
|
import { store, backendUiStore } from "../builderStore"
|
||||||
import api from "../builderStore/api";
|
import api from "../builderStore/api"
|
||||||
import getIcon from "../common/icon"
|
import getIcon from "../common/icon"
|
||||||
import { CheckIcon } from "../common/Icons"
|
import { CheckIcon } from "../common/Icons"
|
||||||
|
|
||||||
|
@ -14,12 +14,12 @@
|
||||||
|
|
||||||
$: currentAppInfo = {
|
$: currentAppInfo = {
|
||||||
appname: $store.appname,
|
appname: $store.appname,
|
||||||
instanceId: $backendUiStore.selectedDatabase.id
|
instanceId: $backendUiStore.selectedDatabase.id,
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchUsers() {
|
async function fetchUsers() {
|
||||||
const FETCH_USERS_URL = `/_builder/instance/${currentAppInfo.appname}/${currentAppInfo.instanceId}/api/users`
|
const FETCH_USERS_URL = `/_builder/instance/${currentAppInfo.appname}/${currentAppInfo.instanceId}/api/users`
|
||||||
const response = await api.get(FETCH_USERS_URL);
|
const response = await api.get(FETCH_USERS_URL)
|
||||||
users = await response.json()
|
users = await response.json()
|
||||||
backendUiStore.update(state => {
|
backendUiStore.update(state => {
|
||||||
state.users = users
|
state.users = users
|
||||||
|
@ -35,7 +35,9 @@
|
||||||
{#each users as user}
|
{#each users as user}
|
||||||
<li>
|
<li>
|
||||||
<i class="ri-user-4-line" />
|
<i class="ri-user-4-line" />
|
||||||
<button class:active={user.id === $store.currentUserId}>{user.name}</button>
|
<button class:active={user.id === $store.currentUserId}>
|
||||||
|
{user.name}
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -69,7 +71,7 @@
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: rgba(0,0,0,0);
|
background: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
|
|
|
@ -178,8 +178,6 @@
|
||||||
height: 48px;
|
height: 48px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
li button {
|
li button {
|
||||||
width: 48px;
|
width: 48px;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
|
|
|
@ -35,16 +35,13 @@
|
||||||
$: templatesByComponent = groupBy(t => t.component)($store.templates)
|
$: templatesByComponent = groupBy(t => t.component)($store.templates)
|
||||||
$: hierarchy = $store.hierarchy
|
$: hierarchy = $store.hierarchy
|
||||||
$: libraryModules = $store.libraries
|
$: libraryModules = $store.libraries
|
||||||
$: standaloneTemplates = pipe(
|
$: standaloneTemplates = pipe(templatesByComponent, [
|
||||||
templatesByComponent,
|
values,
|
||||||
[
|
flatten,
|
||||||
values,
|
filter(t => !$store.components.some(c => c.name === t.component)),
|
||||||
flatten,
|
map(t => ({ name: splitName(t.component).componentName, template: t })),
|
||||||
filter(t => !$store.components.some(c => c.name === t.component)),
|
uniqBy(t => t.name),
|
||||||
map(t => ({ name: splitName(t.component).componentName, template: t })),
|
])
|
||||||
uniqBy(t => t.name),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
const addRootComponent = (component, allComponents) => {
|
const addRootComponent = (component, allComponents) => {
|
||||||
const { libName } = splitName(component.name)
|
const { libName } = splitName(component.name)
|
||||||
|
@ -278,7 +275,7 @@
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
color:var(--secondary80);
|
color: var(--secondary80);
|
||||||
}
|
}
|
||||||
|
|
||||||
.preset-menu > span {
|
.preset-menu > span {
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -74,7 +74,7 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
background: rgba(0,0,0,0);
|
background: rgba(0, 0, 0, 0);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: var(--secondary40);
|
color: var(--secondary40);
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import InputGroup from "../common/Inputs/InputGroup.svelte"
|
import InputGroup from "../common/Inputs/InputGroup.svelte"
|
||||||
import LayoutTemplateControls from "./LayoutTemplateControls.svelte";
|
import LayoutTemplateControls from "./LayoutTemplateControls.svelte"
|
||||||
|
|
||||||
export let onStyleChanged = () => {}
|
export let onStyleChanged = () => {}
|
||||||
export let component
|
export let component
|
||||||
|
@ -59,14 +59,13 @@
|
||||||
{#each Object.entries(display) as [key, [name, meta, size]] (component._id + key)}
|
{#each Object.entries(display) as [key, [name, meta, size]] (component._id + key)}
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
<h5>{name}:</h5>
|
<h5>{name}:</h5>
|
||||||
<LayoutTemplateControls
|
<LayoutTemplateControls
|
||||||
onStyleChanged={_value => onStyleChanged('layout', key, _value)}
|
onStyleChanged={_value => onStyleChanged('layout', key, _value)}
|
||||||
values={layout[key] || newValue(meta.length)}
|
values={layout[key] || newValue(meta.length)}
|
||||||
propertyName={name}
|
propertyName={name}
|
||||||
{meta}
|
{meta}
|
||||||
{size}
|
{size}
|
||||||
type="text"
|
type="text" />
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -115,9 +115,7 @@
|
||||||
bind:value={layoutComponent}
|
bind:value={layoutComponent}
|
||||||
class:uk-form-danger={saveAttempted && !layoutComponent}>
|
class:uk-form-danger={saveAttempted && !layoutComponent}>
|
||||||
{#each layoutComponents as comp}
|
{#each layoutComponents as comp}
|
||||||
<option value={comp}>
|
<option value={comp}>{comp.componentName} - {comp.libName}</option>
|
||||||
{comp.componentName} - {comp.libName}
|
|
||||||
</option>
|
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -127,35 +125,32 @@
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.uk-margin {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.uk-margin {
|
.uk-form-controls {
|
||||||
display: flex;
|
margin-left: 0 !important;
|
||||||
flex-direction: column;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.uk-form-controls {
|
.uk-form-label {
|
||||||
margin-left: 0 !important;
|
padding-bottom: 10px;
|
||||||
}
|
font-weight: 500;
|
||||||
|
font-size: 16px;
|
||||||
|
color: var(--secondary80);
|
||||||
|
}
|
||||||
|
|
||||||
.uk-form-label {
|
.uk-input {
|
||||||
padding-bottom: 10px;
|
height: 40px !important;
|
||||||
font-weight: 500;
|
border-radius: 3px;
|
||||||
font-size: 16px;
|
}
|
||||||
color: var(--secondary80);
|
|
||||||
}
|
|
||||||
|
|
||||||
.uk-input {
|
|
||||||
height: 40px !important;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.uk-select {
|
|
||||||
height: 40px !important;
|
|
||||||
font-weight: 500px;
|
|
||||||
color: var(--secondary60);
|
|
||||||
border: 1px solid var(--slate);
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
.uk-select {
|
||||||
|
height: 40px !important;
|
||||||
|
font-weight: 500px;
|
||||||
|
color: var(--secondary60);
|
||||||
|
border: 1px solid var(--slate);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
outline: none;
|
outline: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: rgba(0,0,0,0);
|
background: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.active {
|
.active {
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
<div class="pages-list-container">
|
<div class="pages-list-container">
|
||||||
<div class="nav-header">
|
<div class="nav-header">
|
||||||
<span class="navigator-title">Navigator</span>
|
<span class="navigator-title">Navigator</span>
|
||||||
<div class="border-line" />
|
<div class="border-line" />
|
||||||
|
|
||||||
<span class="components-nav-page">Pages</span>
|
<span class="components-nav-page">Pages</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -110,24 +110,23 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.root {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 275px 1fr 275px;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
background: #fafafa;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media only screen and (min-width: 1800px) {
|
|
||||||
.root {
|
.root {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 300px 1fr 300px;
|
grid-template-columns: 275px 1fr 275px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@media only screen and (min-width: 1800px) {
|
||||||
|
.root {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 300px 1fr 300px;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.ui-nav {
|
.ui-nav {
|
||||||
grid-column: 1;
|
grid-column: 1;
|
||||||
|
|
|
@ -15,9 +15,12 @@ export const bbFactory = ({
|
||||||
}) => {
|
}) => {
|
||||||
const relativeUrl = url => {
|
const relativeUrl = url => {
|
||||||
if (!frontendDefinition.appRootPath) return url
|
if (!frontendDefinition.appRootPath) return url
|
||||||
if (url.startsWith("http:")
|
if (
|
||||||
|| url.startsWith("https:")
|
url.startsWith("http:") ||
|
||||||
|| url.startsWith("./")) return url
|
url.startsWith("https:") ||
|
||||||
|
url.startsWith("./")
|
||||||
|
)
|
||||||
|
return url
|
||||||
|
|
||||||
return frontendDefinition.appRootPath + "/" + trimSlash(url)
|
return frontendDefinition.appRootPath + "/" + trimSlash(url)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,4 +5,4 @@ export const cloneApp = (app, mergeWith) => {
|
||||||
Object.assign(newApp, mergeWith)
|
Object.assign(newApp, mergeWith)
|
||||||
setCleanupFunc(newApp)
|
setCleanupFunc(newApp)
|
||||||
return newApp
|
return newApp
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,25 +21,25 @@ export const initialiseData = async (
|
||||||
applicationDefinition,
|
applicationDefinition,
|
||||||
accessLevels
|
accessLevels
|
||||||
) => {
|
) => {
|
||||||
if (!await datastore.exists(configFolder))
|
if (!(await datastore.exists(configFolder)))
|
||||||
await datastore.createFolder(configFolder)
|
await datastore.createFolder(configFolder)
|
||||||
|
|
||||||
if (!await datastore.exists(appDefinitionFile))
|
if (!(await datastore.exists(appDefinitionFile)))
|
||||||
await datastore.createJson(appDefinitionFile, applicationDefinition)
|
await datastore.createJson(appDefinitionFile, applicationDefinition)
|
||||||
|
|
||||||
await initialiseRootCollections(datastore, applicationDefinition.hierarchy)
|
await initialiseRootCollections(datastore, applicationDefinition.hierarchy)
|
||||||
await initialiseRootIndexes(datastore, applicationDefinition.hierarchy)
|
await initialiseRootIndexes(datastore, applicationDefinition.hierarchy)
|
||||||
|
|
||||||
if (!await datastore.exists(TRANSACTIONS_FOLDER))
|
if (!(await datastore.exists(TRANSACTIONS_FOLDER)))
|
||||||
await datastore.createFolder(TRANSACTIONS_FOLDER)
|
await datastore.createFolder(TRANSACTIONS_FOLDER)
|
||||||
|
|
||||||
if (!await datastore.exists(AUTH_FOLDER))
|
if (!(await datastore.exists(AUTH_FOLDER)))
|
||||||
await datastore.createFolder(AUTH_FOLDER)
|
await datastore.createFolder(AUTH_FOLDER)
|
||||||
|
|
||||||
if (!await datastore.exists(USERS_LIST_FILE))
|
if (!(await datastore.exists(USERS_LIST_FILE)))
|
||||||
await datastore.createJson(USERS_LIST_FILE, [])
|
await datastore.createJson(USERS_LIST_FILE, [])
|
||||||
|
|
||||||
if (!await datastore.exists(ACCESS_LEVELS_FILE))
|
if (!(await datastore.exists(ACCESS_LEVELS_FILE)))
|
||||||
await datastore.createJson(
|
await datastore.createJson(
|
||||||
ACCESS_LEVELS_FILE,
|
ACCESS_LEVELS_FILE,
|
||||||
accessLevels ? accessLevels : { version: 0, levels: [] }
|
accessLevels ? accessLevels : { version: 0, levels: [] }
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
import {
|
import { compileCode as cCode } from "@nx-js/compiler-util"
|
||||||
compileCode as cCode,
|
|
||||||
} from "@nx-js/compiler-util"
|
|
||||||
import { includes } from "lodash/fp"
|
import { includes } from "lodash/fp"
|
||||||
|
|
||||||
|
|
||||||
export const compileCode = code => {
|
export const compileCode = code => {
|
||||||
let func
|
let func
|
||||||
let safeCode
|
let safeCode
|
||||||
|
@ -12,9 +9,9 @@ export const compileCode = code => {
|
||||||
safeCode = code
|
safeCode = code
|
||||||
} else {
|
} else {
|
||||||
let trimmed = code.trim()
|
let trimmed = code.trim()
|
||||||
trimmed = trimmed.endsWith(";")
|
trimmed = trimmed.endsWith(";")
|
||||||
? trimmed.substring(0, trimmed.length - 1)
|
? trimmed.substring(0, trimmed.length - 1)
|
||||||
: trimmed
|
: trimmed
|
||||||
safeCode = `return (${trimmed})`
|
safeCode = `return (${trimmed})`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ const buildHeirarchalIndex = async (app, indexNode) => {
|
||||||
)
|
)
|
||||||
|
|
||||||
let allIds = await allIdsIterator()
|
let allIds = await allIdsIterator()
|
||||||
while (allIds.done === false) {
|
while (allIds.done === false) {
|
||||||
await createTransactionsForIds(
|
await createTransactionsForIds(
|
||||||
allIds.result.collectionKey,
|
allIds.result.collectionKey,
|
||||||
allIds.result.ids
|
allIds.result.ids
|
||||||
|
@ -140,5 +140,4 @@ const buildHeirarchalIndex = async (app, indexNode) => {
|
||||||
const recordNodeApplies = indexNode => recordNode =>
|
const recordNodeApplies = indexNode => recordNode =>
|
||||||
includes(recordNode.nodeId)(indexNode.allowedRecordNodeIds)
|
includes(recordNode.nodeId)(indexNode.allowedRecordNodeIds)
|
||||||
|
|
||||||
|
|
||||||
export default buildIndex
|
export default buildIndex
|
||||||
|
|
|
@ -58,10 +58,9 @@ export const folderStructureArray = recordNode => {
|
||||||
|
|
||||||
export const getAllIdsIterator = app => async collection_Key_or_NodeKey => {
|
export const getAllIdsIterator = app => async collection_Key_or_NodeKey => {
|
||||||
collection_Key_or_NodeKey = safeKey(collection_Key_or_NodeKey)
|
collection_Key_or_NodeKey = safeKey(collection_Key_or_NodeKey)
|
||||||
const recordNode = getCollectionNodeByKeyOrNodeKey(
|
const recordNode =
|
||||||
app.hierarchy,
|
getCollectionNodeByKeyOrNodeKey(app.hierarchy, collection_Key_or_NodeKey) ||
|
||||||
collection_Key_or_NodeKey
|
getNodeByKeyOrNodeKey(app.hierarchy, collection_Key_or_NodeKey)
|
||||||
) || getNodeByKeyOrNodeKey(app.hierarchy, collection_Key_or_NodeKey)
|
|
||||||
|
|
||||||
const getAllIdsIteratorForCollectionKey = async (
|
const getAllIdsIteratorForCollectionKey = async (
|
||||||
recordNode,
|
recordNode,
|
||||||
|
|
|
@ -10,18 +10,18 @@ export const initialiseIndex = async (datastore, dir, index) => {
|
||||||
const indexDir = joinKey(dir, index.name)
|
const indexDir = joinKey(dir, index.name)
|
||||||
|
|
||||||
let newDir = false
|
let newDir = false
|
||||||
if (!await datastore.exists(indexDir)) {
|
if (!(await datastore.exists(indexDir))) {
|
||||||
await datastore.createFolder(indexDir)
|
await datastore.createFolder(indexDir)
|
||||||
newDir = true
|
newDir = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isShardedIndex(index)) {
|
if (isShardedIndex(index)) {
|
||||||
const shardFile = getShardMapKey(indexDir)
|
const shardFile = getShardMapKey(indexDir)
|
||||||
if (newDir || !await datastore.exists(shardFile))
|
if (newDir || !(await datastore.exists(shardFile)))
|
||||||
await datastore.createFile(shardFile, "[]")
|
await datastore.createFile(shardFile, "[]")
|
||||||
} else {
|
} else {
|
||||||
const indexFile = getUnshardedIndexDataKey(indexDir)
|
const indexFile = getUnshardedIndexDataKey(indexDir)
|
||||||
if (newDir || !await datastore.exists(indexFile))
|
if (newDir || !(await datastore.exists(indexFile)))
|
||||||
await createIndexFile(datastore, indexFile, index)
|
await createIndexFile(datastore, indexFile, index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,10 @@ import { promiseReadableStream } from "./promiseReadableStream"
|
||||||
import { createIndexFile } from "./sharding"
|
import { createIndexFile } from "./sharding"
|
||||||
import { generateSchema } from "./indexSchemaCreator"
|
import { generateSchema } from "./indexSchemaCreator"
|
||||||
import { getIndexReader, CONTINUE_READING_RECORDS } from "./serializer"
|
import { getIndexReader, CONTINUE_READING_RECORDS } from "./serializer"
|
||||||
import { getAllowedRecordNodesForIndex, getRecordNodeId } from "../templateApi/hierarchy"
|
import {
|
||||||
|
getAllowedRecordNodesForIndex,
|
||||||
|
getRecordNodeId,
|
||||||
|
} from "../templateApi/hierarchy"
|
||||||
import { $ } from "../common"
|
import { $ } from "../common"
|
||||||
import { filter, includes, find } from "lodash/fp"
|
import { filter, includes, find } from "lodash/fp"
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const getNew = app => (collectionKey, recordTypeName) => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a record object that can be saved to the backend.
|
* Constructs a record object that can be saved to the backend.
|
||||||
* @param {*} recordNode - record
|
* @param {*} recordNode - record
|
||||||
* @param {*} collectionKey - nested collection key that the record will be saved to.
|
* @param {*} collectionKey - nested collection key that the record will be saved to.
|
||||||
*/
|
*/
|
||||||
export const _getNew = (recordNode, collectionKey) =>
|
export const _getNew = (recordNode, collectionKey) =>
|
||||||
|
|
|
@ -14,29 +14,28 @@ import { getRecordInfo } from "./recordInfo"
|
||||||
import { getAllIdsIterator } from "../indexing/allIds"
|
import { getAllIdsIterator } from "../indexing/allIds"
|
||||||
|
|
||||||
export const initialiseChildren = async (app, recordInfoOrKey) => {
|
export const initialiseChildren = async (app, recordInfoOrKey) => {
|
||||||
const recordInfo = isString(recordInfoOrKey)
|
const recordInfo = isString(recordInfoOrKey)
|
||||||
? getRecordInfo(app.hierarchy, recordInfoOrKey)
|
? getRecordInfo(app.hierarchy, recordInfoOrKey)
|
||||||
: recordInfoOrKey
|
: recordInfoOrKey
|
||||||
await initialiseReverseReferenceIndexes(app, recordInfo)
|
await initialiseReverseReferenceIndexes(app, recordInfo)
|
||||||
await initialiseAncestorIndexes(app, recordInfo)
|
await initialiseAncestorIndexes(app, recordInfo)
|
||||||
await initialiseChildCollections(app, recordInfo)
|
await initialiseChildCollections(app, recordInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const initialiseChildrenForNode = async (app, recordNode) => {
|
export const initialiseChildrenForNode = async (app, recordNode) => {
|
||||||
|
|
||||||
if (isTopLevelRecord(recordNode)) {
|
if (isTopLevelRecord(recordNode)) {
|
||||||
await initialiseChildren(
|
await initialiseChildren(app, recordNode.nodeKey())
|
||||||
app, recordNode.nodeKey())
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const iterate = await getAllIdsIterator(app)(recordNode.parent().collectionNodeKey())
|
const iterate = await getAllIdsIterator(app)(
|
||||||
|
recordNode.parent().collectionNodeKey()
|
||||||
|
)
|
||||||
let iterateResult = await iterate()
|
let iterateResult = await iterate()
|
||||||
while (!iterateResult.done) {
|
while (!iterateResult.done) {
|
||||||
const { result } = iterateResult
|
const { result } = iterateResult
|
||||||
for (const id of result.ids) {
|
for (const id of result.ids) {
|
||||||
const initialisingRecordKey = joinKey(
|
const initialisingRecordKey = joinKey(result.collectionKey, id)
|
||||||
result.collectionKey, id)
|
|
||||||
await initialiseChildren(app, initialisingRecordKey)
|
await initialiseChildren(app, initialisingRecordKey)
|
||||||
}
|
}
|
||||||
iterateResult = await iterate()
|
iterateResult = await iterate()
|
||||||
|
@ -78,5 +77,3 @@ const fieldsThatReferenceThisRecord = (app, recordNode) =>
|
||||||
flatten,
|
flatten,
|
||||||
filter(fieldReversesReferenceToNode(recordNode)),
|
filter(fieldReversesReferenceToNode(recordNode)),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,52 +1,54 @@
|
||||||
import {
|
import {
|
||||||
findRoot,
|
findRoot,
|
||||||
getFlattenedHierarchy,
|
getFlattenedHierarchy,
|
||||||
fieldReversesReferenceToIndex,
|
fieldReversesReferenceToIndex,
|
||||||
isRecord
|
isRecord,
|
||||||
} from "./hierarchy"
|
} from "./hierarchy"
|
||||||
import { $ } from "../common"
|
import { $ } from "../common"
|
||||||
import { map, filter, reduce } from "lodash/fp"
|
import { map, filter, reduce } from "lodash/fp"
|
||||||
|
|
||||||
export const canDeleteIndex = indexNode => {
|
export const canDeleteIndex = indexNode => {
|
||||||
const flatHierarchy = $(indexNode, [
|
const flatHierarchy = $(indexNode, [findRoot, getFlattenedHierarchy])
|
||||||
findRoot,
|
|
||||||
getFlattenedHierarchy
|
|
||||||
])
|
|
||||||
|
|
||||||
const reverseIndexes = $(flatHierarchy,[
|
const reverseIndexes = $(flatHierarchy, [
|
||||||
filter(isRecord),
|
filter(isRecord),
|
||||||
reduce((obj, r) => {
|
reduce((obj, r) => {
|
||||||
for (let field of r.fields) {
|
for (let field of r.fields) {
|
||||||
if (fieldReversesReferenceToIndex(indexNode)(field)) {
|
if (fieldReversesReferenceToIndex(indexNode)(field)) {
|
||||||
obj.push({ ...field, record:r })
|
obj.push({ ...field, record: r })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return obj
|
return obj
|
||||||
},[]),
|
}, []),
|
||||||
map(f => `field "${f.name}" on record "${f.record.name}" uses this index as a reference`)
|
map(
|
||||||
|
f =>
|
||||||
|
`field "${f.name}" on record "${f.record.name}" uses this index as a reference`
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
const lookupIndexes = $(flatHierarchy,[
|
const lookupIndexes = $(flatHierarchy, [
|
||||||
filter(isRecord),
|
filter(isRecord),
|
||||||
reduce((obj, r) => {
|
reduce((obj, r) => {
|
||||||
for (let field of r.fields) {
|
for (let field of r.fields) {
|
||||||
if (field.type === "reference"
|
if (
|
||||||
&& field.typeOptions.indexNodeKey === indexNode.nodeKey()) {
|
field.type === "reference" &&
|
||||||
obj.push({ ...field, record:r })
|
field.typeOptions.indexNodeKey === indexNode.nodeKey()
|
||||||
|
) {
|
||||||
|
obj.push({ ...field, record: r })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return obj
|
return obj
|
||||||
},[]),
|
}, []),
|
||||||
map(f => `field "${f.name}" on record "${f.record.name}" uses this index as a lookup`)
|
map(
|
||||||
|
f =>
|
||||||
|
`field "${f.name}" on record "${f.record.name}" uses this index as a lookup`
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
const errors = [
|
const errors = [...reverseIndexes, ...lookupIndexes]
|
||||||
...reverseIndexes,
|
|
||||||
...lookupIndexes
|
|
||||||
]
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
canDelete: errors.length === 0,
|
canDelete: errors.length === 0,
|
||||||
errors
|
errors,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
import {
|
import {
|
||||||
findRoot,
|
findRoot,
|
||||||
getFlattenedHierarchy,
|
getFlattenedHierarchy,
|
||||||
fieldReversesReferenceToIndex,
|
fieldReversesReferenceToIndex,
|
||||||
isRecord,
|
isRecord,
|
||||||
isAncestorIndex,
|
isAncestorIndex,
|
||||||
isAncestor
|
isAncestor,
|
||||||
} from "./hierarchy"
|
} from "./hierarchy"
|
||||||
import { $ } from "../common"
|
import { $ } from "../common"
|
||||||
import { map, filter, includes } from "lodash/fp"
|
import { map, filter, includes } from "lodash/fp"
|
||||||
|
|
||||||
export const canDeleteRecord = recordNode => {
|
export const canDeleteRecord = recordNode => {
|
||||||
const flatHierarchy = $(recordNode, [
|
const flatHierarchy = $(recordNode, [findRoot, getFlattenedHierarchy])
|
||||||
findRoot,
|
|
||||||
getFlattenedHierarchy
|
|
||||||
])
|
|
||||||
|
|
||||||
const ancestors = $(flatHierarchy, [
|
const ancestors = $(flatHierarchy, [filter(isAncestor(recordNode))])
|
||||||
filter(isAncestor(recordNode))
|
|
||||||
])
|
const belongsToAncestor = i => ancestors.includes(i.parent())
|
||||||
|
|
||||||
const belongsToAncestor = i =>
|
|
||||||
ancestors.includes(i.parent())
|
|
||||||
|
|
||||||
const errorsForNode = node => {
|
const errorsForNode = node => {
|
||||||
const errorsThisNode = $(flatHierarchy, [
|
const errorsThisNode = $(flatHierarchy, [
|
||||||
filter(i => isAncestorIndex(i)
|
filter(
|
||||||
&& belongsToAncestor(i)
|
i =>
|
||||||
&& includes(node.nodeId)(i.allowedRecordNodeIds)),
|
isAncestorIndex(i) &&
|
||||||
map(i => `index "${i.name}" indexes this record. Please remove the record from the index, or delete the index`)
|
belongsToAncestor(i) &&
|
||||||
|
includes(node.nodeId)(i.allowedRecordNodeIds)
|
||||||
|
),
|
||||||
|
map(
|
||||||
|
i =>
|
||||||
|
`index "${i.name}" indexes this record. Please remove the record from the index, or delete the index`
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
for (let child of node.children) {
|
for (let child of node.children) {
|
||||||
|
@ -36,10 +36,10 @@ export const canDeleteRecord = recordNode => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return errorsThisNode
|
return errorsThisNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const errors = errorsForNode(recordNode)
|
const errors = errorsForNode(recordNode)
|
||||||
|
|
||||||
return { errors, canDelete: errors.length === 0 }
|
return { errors, canDelete: errors.length === 0 }
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ import { isTopLevelIndex, getParentKey, getLastPartInKey } from "./hierarchy"
|
||||||
import { safeKey, joinKey } from "../common"
|
import { safeKey, joinKey } from "../common"
|
||||||
|
|
||||||
export const deleteAllIndexFilesForNode = async (app, indexNode) => {
|
export const deleteAllIndexFilesForNode = async (app, indexNode) => {
|
||||||
|
|
||||||
if (isTopLevelIndex(indexNode)) {
|
if (isTopLevelIndex(indexNode)) {
|
||||||
await app.datastore.deleteFolder(indexNode.nodeKey())
|
await app.datastore.deleteFolder(indexNode.nodeKey())
|
||||||
return
|
return
|
||||||
|
@ -15,13 +14,11 @@ export const deleteAllIndexFilesForNode = async (app, indexNode) => {
|
||||||
while (!iterateResult.done) {
|
while (!iterateResult.done) {
|
||||||
const { result } = iterateResult
|
const { result } = iterateResult
|
||||||
for (const id of result.ids) {
|
for (const id of result.ids) {
|
||||||
const deletingIndexKey = joinKey(
|
const deletingIndexKey = joinKey(result.collectionKey, id, indexNode.name)
|
||||||
result.collectionKey, id, indexNode.name)
|
|
||||||
await deleteIndexFolder(app, deletingIndexKey)
|
await deleteIndexFolder(app, deletingIndexKey)
|
||||||
}
|
}
|
||||||
iterateResult = await iterate()
|
iterateResult = await iterate()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteIndexFolder = async (app, indexKey) => {
|
const deleteIndexFolder = async (app, indexKey) => {
|
||||||
|
@ -29,6 +26,5 @@ const deleteIndexFolder = async (app, indexKey) => {
|
||||||
const indexName = getLastPartInKey(indexKey)
|
const indexName = getLastPartInKey(indexKey)
|
||||||
const parentRecordKey = getParentKey(indexKey)
|
const parentRecordKey = getParentKey(indexKey)
|
||||||
const recordInfo = getRecordInfo(app.hierarchy, parentRecordKey)
|
const recordInfo = getRecordInfo(app.hierarchy, parentRecordKey)
|
||||||
await app.datastore.deleteFolder(
|
await app.datastore.deleteFolder(joinKey(recordInfo.dir, indexName))
|
||||||
joinKey(recordInfo.dir, indexName))
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -4,10 +4,8 @@ import { isTopLevelRecord, getCollectionKey } from "./hierarchy"
|
||||||
import { safeKey, joinKey } from "../common"
|
import { safeKey, joinKey } from "../common"
|
||||||
|
|
||||||
export const deleteAllRecordsForNode = async (app, recordNode) => {
|
export const deleteAllRecordsForNode = async (app, recordNode) => {
|
||||||
|
|
||||||
if (isTopLevelRecord(recordNode)) {
|
if (isTopLevelRecord(recordNode)) {
|
||||||
await deleteRecordCollection(
|
await deleteRecordCollection(app, recordNode.collectionName)
|
||||||
app, recordNode.collectionName)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,16 +15,19 @@ export const deleteAllRecordsForNode = async (app, recordNode) => {
|
||||||
const { result } = iterateResult
|
const { result } = iterateResult
|
||||||
for (const id of result.ids) {
|
for (const id of result.ids) {
|
||||||
const deletingCollectionKey = joinKey(
|
const deletingCollectionKey = joinKey(
|
||||||
result.collectionKey, id, recordNode.collectionName)
|
result.collectionKey,
|
||||||
|
id,
|
||||||
|
recordNode.collectionName
|
||||||
|
)
|
||||||
await deleteRecordCollection(app, deletingCollectionKey)
|
await deleteRecordCollection(app, deletingCollectionKey)
|
||||||
}
|
}
|
||||||
iterateResult = await iterate()
|
iterateResult = await iterate()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteRecordCollection = async (app, collectionKey) => {
|
const deleteRecordCollection = async (app, collectionKey) => {
|
||||||
collectionKey = safeKey(collectionKey)
|
collectionKey = safeKey(collectionKey)
|
||||||
await app.datastore.deleteFolder(
|
await app.datastore.deleteFolder(
|
||||||
getCollectionDir(app.hierarchy, collectionKey))
|
getCollectionDir(app.hierarchy, collectionKey)
|
||||||
}
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
import { getFlattenedHierarchy, isRecord, isIndex, isAncestor } from "./hierarchy"
|
import {
|
||||||
|
getFlattenedHierarchy,
|
||||||
|
isRecord,
|
||||||
|
isIndex,
|
||||||
|
isAncestor,
|
||||||
|
} from "./hierarchy"
|
||||||
import { $, none } from "../common"
|
import { $, none } from "../common"
|
||||||
import { map, filter, some, find, difference } from "lodash/fp"
|
import { map, filter, some, find, difference } from "lodash/fp"
|
||||||
|
|
||||||
|
@ -19,13 +24,16 @@ export const diffHierarchy = (oldHierarchy, newHierarchy) => {
|
||||||
|
|
||||||
const createdRecords = findCreatedRecords(oldHierarchyFlat, newHierarchyFlat)
|
const createdRecords = findCreatedRecords(oldHierarchyFlat, newHierarchyFlat)
|
||||||
const deletedRecords = findDeletedRecords(oldHierarchyFlat, newHierarchyFlat)
|
const deletedRecords = findDeletedRecords(oldHierarchyFlat, newHierarchyFlat)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
...createdRecords,
|
...createdRecords,
|
||||||
...deletedRecords,
|
...deletedRecords,
|
||||||
...findRenamedRecords(oldHierarchyFlat, newHierarchyFlat),
|
...findRenamedRecords(oldHierarchyFlat, newHierarchyFlat),
|
||||||
...findRecordsWithFieldsChanged(oldHierarchyFlat, newHierarchyFlat),
|
...findRecordsWithFieldsChanged(oldHierarchyFlat, newHierarchyFlat),
|
||||||
...findRecordsWithEstimatedRecordTypeChanged(oldHierarchyFlat, newHierarchyFlat),
|
...findRecordsWithEstimatedRecordTypeChanged(
|
||||||
|
oldHierarchyFlat,
|
||||||
|
newHierarchyFlat
|
||||||
|
),
|
||||||
...findCreatedIndexes(oldHierarchyFlat, newHierarchyFlat, createdRecords),
|
...findCreatedIndexes(oldHierarchyFlat, newHierarchyFlat, createdRecords),
|
||||||
...findDeletedIndexes(oldHierarchyFlat, newHierarchyFlat, deletedRecords),
|
...findDeletedIndexes(oldHierarchyFlat, newHierarchyFlat, deletedRecords),
|
||||||
...findUpdatedIndexes(oldHierarchyFlat, newHierarchyFlat),
|
...findUpdatedIndexes(oldHierarchyFlat, newHierarchyFlat),
|
||||||
|
@ -33,18 +41,20 @@ export const diffHierarchy = (oldHierarchy, newHierarchy) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const changeItem = (type, oldNode, newNode) => ({
|
const changeItem = (type, oldNode, newNode) => ({
|
||||||
type, oldNode, newNode,
|
type,
|
||||||
|
oldNode,
|
||||||
|
newNode,
|
||||||
})
|
})
|
||||||
|
|
||||||
const findCreatedRecords = (oldHierarchyFlat, newHierarchyFlat) => {
|
const findCreatedRecords = (oldHierarchyFlat, newHierarchyFlat) => {
|
||||||
const allCreated = $(newHierarchyFlat, [
|
const allCreated = $(newHierarchyFlat, [
|
||||||
filter(isRecord),
|
filter(isRecord),
|
||||||
filter(nodeDoesNotExistIn(oldHierarchyFlat)),
|
filter(nodeDoesNotExistIn(oldHierarchyFlat)),
|
||||||
map(n => changeItem(HierarchyChangeTypes.recordCreated, null, n))
|
map(n => changeItem(HierarchyChangeTypes.recordCreated, null, n)),
|
||||||
])
|
])
|
||||||
|
|
||||||
return $(allCreated, [
|
return $(allCreated, [
|
||||||
filter(r => none(r2 => isAncestor(r.newNode)(r2.newNode))(allCreated))
|
filter(r => none(r2 => isAncestor(r.newNode)(r2.newNode))(allCreated)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,117 +62,142 @@ const findDeletedRecords = (oldHierarchyFlat, newHierarchyFlat) => {
|
||||||
const allDeleted = $(oldHierarchyFlat, [
|
const allDeleted = $(oldHierarchyFlat, [
|
||||||
filter(isRecord),
|
filter(isRecord),
|
||||||
filter(nodeDoesNotExistIn(newHierarchyFlat)),
|
filter(nodeDoesNotExistIn(newHierarchyFlat)),
|
||||||
map(n => changeItem(HierarchyChangeTypes.recordDeleted, n, null))
|
map(n => changeItem(HierarchyChangeTypes.recordDeleted, n, null)),
|
||||||
])
|
])
|
||||||
|
|
||||||
return $(allDeleted, [
|
return $(allDeleted, [
|
||||||
filter(r => none(r2 => isAncestor(r.oldNode)(r2.oldNode))(allDeleted))
|
filter(r => none(r2 => isAncestor(r.oldNode)(r2.oldNode))(allDeleted)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
const findRenamedRecords = (oldHierarchyFlat, newHierarchyFlat) =>
|
const findRenamedRecords = (oldHierarchyFlat, newHierarchyFlat) =>
|
||||||
$(oldHierarchyFlat, [
|
$(oldHierarchyFlat, [
|
||||||
filter(isRecord),
|
filter(isRecord),
|
||||||
filter(nodeExistsIn(newHierarchyFlat)),
|
filter(nodeExistsIn(newHierarchyFlat)),
|
||||||
filter(nodeChanged(newHierarchyFlat, (_new,old) =>_new.collectionKey !== old.collectionKey )),
|
filter(
|
||||||
map(n => changeItem(
|
nodeChanged(
|
||||||
HierarchyChangeTypes.recordRenamed,
|
newHierarchyFlat,
|
||||||
n,
|
(_new, old) => _new.collectionKey !== old.collectionKey
|
||||||
findNodeIn(n, newHierarchyFlat))
|
)
|
||||||
)
|
),
|
||||||
|
map(n =>
|
||||||
|
changeItem(
|
||||||
|
HierarchyChangeTypes.recordRenamed,
|
||||||
|
n,
|
||||||
|
findNodeIn(n, newHierarchyFlat)
|
||||||
|
)
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
const findRecordsWithFieldsChanged = (oldHierarchyFlat, newHierarchyFlat) =>
|
const findRecordsWithFieldsChanged = (oldHierarchyFlat, newHierarchyFlat) =>
|
||||||
$(oldHierarchyFlat, [
|
$(oldHierarchyFlat, [
|
||||||
filter(isRecord),
|
filter(isRecord),
|
||||||
filter(nodeExistsIn(newHierarchyFlat)),
|
filter(nodeExistsIn(newHierarchyFlat)),
|
||||||
filter(hasDifferentFields(newHierarchyFlat)),
|
filter(hasDifferentFields(newHierarchyFlat)),
|
||||||
map(n => changeItem(
|
map(n =>
|
||||||
HierarchyChangeTypes.recordFieldsChanged,
|
changeItem(
|
||||||
n,
|
HierarchyChangeTypes.recordFieldsChanged,
|
||||||
findNodeIn(n, newHierarchyFlat))
|
n,
|
||||||
)
|
findNodeIn(n, newHierarchyFlat)
|
||||||
|
)
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
const findRecordsWithEstimatedRecordTypeChanged = (oldHierarchyFlat, newHierarchyFlat) =>
|
const findRecordsWithEstimatedRecordTypeChanged = (
|
||||||
|
oldHierarchyFlat,
|
||||||
|
newHierarchyFlat
|
||||||
|
) =>
|
||||||
$(oldHierarchyFlat, [
|
$(oldHierarchyFlat, [
|
||||||
filter(isRecord),
|
filter(isRecord),
|
||||||
filter(nodeExistsIn(newHierarchyFlat)),
|
filter(nodeExistsIn(newHierarchyFlat)),
|
||||||
filter(nodeChanged(newHierarchyFlat, (_new,old) =>_new.estimatedRecordCount !== old.estimatedRecordCount)),
|
filter(
|
||||||
map(n => changeItem(
|
nodeChanged(
|
||||||
HierarchyChangeTypes.recordEstimatedRecordTypeChanged,
|
newHierarchyFlat,
|
||||||
n,
|
(_new, old) => _new.estimatedRecordCount !== old.estimatedRecordCount
|
||||||
findNodeIn(n, newHierarchyFlat))
|
)
|
||||||
)
|
),
|
||||||
|
map(n =>
|
||||||
|
changeItem(
|
||||||
|
HierarchyChangeTypes.recordEstimatedRecordTypeChanged,
|
||||||
|
n,
|
||||||
|
findNodeIn(n, newHierarchyFlat)
|
||||||
|
)
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
const findCreatedIndexes = (oldHierarchyFlat, newHierarchyFlat, createdRecords) => {
|
const findCreatedIndexes = (
|
||||||
|
oldHierarchyFlat,
|
||||||
|
newHierarchyFlat,
|
||||||
|
createdRecords
|
||||||
|
) => {
|
||||||
const allCreated = $(newHierarchyFlat, [
|
const allCreated = $(newHierarchyFlat, [
|
||||||
filter(isIndex),
|
filter(isIndex),
|
||||||
filter(nodeDoesNotExistIn(oldHierarchyFlat)),
|
filter(nodeDoesNotExistIn(oldHierarchyFlat)),
|
||||||
map(n => changeItem(HierarchyChangeTypes.indexCreated, null, n))
|
map(n => changeItem(HierarchyChangeTypes.indexCreated, null, n)),
|
||||||
])
|
])
|
||||||
|
|
||||||
return $(allCreated, [
|
return $(allCreated, [
|
||||||
filter(r => none(r2 => isAncestor(r.newNode)(r2.newNode))(createdRecords))
|
filter(r => none(r2 => isAncestor(r.newNode)(r2.newNode))(createdRecords)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
const findDeletedIndexes = (oldHierarchyFlat, newHierarchyFlat, deletedRecords) => {
|
const findDeletedIndexes = (
|
||||||
|
oldHierarchyFlat,
|
||||||
|
newHierarchyFlat,
|
||||||
|
deletedRecords
|
||||||
|
) => {
|
||||||
const allDeleted = $(oldHierarchyFlat, [
|
const allDeleted = $(oldHierarchyFlat, [
|
||||||
filter(isIndex),
|
filter(isIndex),
|
||||||
filter(nodeDoesNotExistIn(newHierarchyFlat)),
|
filter(nodeDoesNotExistIn(newHierarchyFlat)),
|
||||||
map(n => changeItem(HierarchyChangeTypes.indexDeleted, n, null))
|
map(n => changeItem(HierarchyChangeTypes.indexDeleted, n, null)),
|
||||||
])
|
])
|
||||||
|
|
||||||
return $(allDeleted, [
|
return $(allDeleted, [
|
||||||
filter(r => none(r2 => isAncestor(r.oldNode)(r2.oldNode))(deletedRecords))
|
filter(r => none(r2 => isAncestor(r.oldNode)(r2.oldNode))(deletedRecords)),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const findUpdatedIndexes = (oldHierarchyFlat, newHierarchyFlat) =>
|
||||||
const findUpdatedIndexes = (oldHierarchyFlat, newHierarchyFlat) =>
|
|
||||||
$(oldHierarchyFlat, [
|
$(oldHierarchyFlat, [
|
||||||
filter(isIndex),
|
filter(isIndex),
|
||||||
filter(nodeExistsIn(newHierarchyFlat)),
|
filter(nodeExistsIn(newHierarchyFlat)),
|
||||||
filter(nodeChanged(newHierarchyFlat, indexHasChanged)),
|
filter(nodeChanged(newHierarchyFlat, indexHasChanged)),
|
||||||
map(n => changeItem(
|
map(n =>
|
||||||
HierarchyChangeTypes.indexChanged,
|
changeItem(
|
||||||
n,
|
HierarchyChangeTypes.indexChanged,
|
||||||
findNodeIn(n, newHierarchyFlat))
|
n,
|
||||||
)
|
findNodeIn(n, newHierarchyFlat)
|
||||||
|
)
|
||||||
|
),
|
||||||
])
|
])
|
||||||
|
|
||||||
const hasDifferentFields = otherFlatHierarchy => record1 => {
|
const hasDifferentFields = otherFlatHierarchy => record1 => {
|
||||||
|
|
||||||
const record2 = findNodeIn(record1, otherFlatHierarchy)
|
const record2 = findNodeIn(record1, otherFlatHierarchy)
|
||||||
|
|
||||||
if(record1.fields.length !== record2.fields.length) return true
|
if (record1.fields.length !== record2.fields.length) return true
|
||||||
|
|
||||||
for(let f1 of record1.fields) {
|
for (let f1 of record1.fields) {
|
||||||
if (none(isFieldSame(f1))(record2.fields)) return true
|
if (none(isFieldSame(f1))(record2.fields)) return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const indexHasChanged = (_new, old) =>
|
const indexHasChanged = (_new, old) =>
|
||||||
_new.map !== old.map
|
_new.map !== old.map ||
|
||||||
|| _new.filter !== old.filter
|
_new.filter !== old.filter ||
|
||||||
|| _new.getShardName !== old.getShardName
|
_new.getShardName !== old.getShardName ||
|
||||||
|| difference(_new.allowedRecordNodeIds)(old.allowedRecordNodeIds).length > 0
|
difference(_new.allowedRecordNodeIds)(old.allowedRecordNodeIds).length > 0
|
||||||
|
|
||||||
const isFieldSame = f1 => f2 =>
|
const isFieldSame = f1 => f2 => f1.name === f2.name && f1.type === f2.type
|
||||||
f1.name === f2.name && f1.type === f2.type
|
|
||||||
|
|
||||||
const nodeDoesNotExistIn = inThis => node =>
|
const nodeDoesNotExistIn = inThis => node =>
|
||||||
none(n => n.nodeId === node.nodeId)(inThis)
|
none(n => n.nodeId === node.nodeId)(inThis)
|
||||||
|
|
||||||
const nodeExistsIn = inThis => node =>
|
const nodeExistsIn = inThis => node =>
|
||||||
some(n => n.nodeId === node.nodeId)(inThis)
|
some(n => n.nodeId === node.nodeId)(inThis)
|
||||||
|
|
||||||
const nodeChanged = (inThis, isChanged) => node =>
|
const nodeChanged = (inThis, isChanged) => node =>
|
||||||
some(n => n.nodeId === node.nodeId && isChanged(n, node))(inThis)
|
some(n => n.nodeId === node.nodeId && isChanged(n, node))(inThis)
|
||||||
|
|
||||||
const findNodeIn = (node, inThis) =>
|
const findNodeIn = (node, inThis) => find(n => n.nodeId === node.nodeId)(inThis)
|
||||||
find(n => n.nodeId === node.nodeId)(inThis)
|
|
||||||
|
|
|
@ -192,8 +192,8 @@ export const getAllowedRecordNodesForIndex = (appHierarchy, indexNode) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDependantIndexes = (hierarchy, recordNode) => {
|
export const getDependantIndexes = (hierarchy, recordNode) => {
|
||||||
const allIndexes = $(hierarchy, [ getFlattenedHierarchy, filter(isIndex)])
|
const allIndexes = $(hierarchy, [getFlattenedHierarchy, filter(isIndex)])
|
||||||
|
|
||||||
const allowedAncestors = $(allIndexes, [
|
const allowedAncestors = $(allIndexes, [
|
||||||
filter(isAncestorIndex),
|
filter(isAncestorIndex),
|
||||||
filter(i => recordNodeIsAllowed(i)(recordNode)),
|
filter(i => recordNodeIsAllowed(i)(recordNode)),
|
||||||
|
@ -201,7 +201,7 @@ export const getDependantIndexes = (hierarchy, recordNode) => {
|
||||||
|
|
||||||
const allowedReference = $(allIndexes, [
|
const allowedReference = $(allIndexes, [
|
||||||
filter(isReferenceIndex),
|
filter(isReferenceIndex),
|
||||||
filter(i => some(fieldReversesReferenceToIndex(i))(recordNode.fields))
|
filter(i => some(fieldReversesReferenceToIndex(i))(recordNode.fields)),
|
||||||
])
|
])
|
||||||
|
|
||||||
return [...allowedAncestors, ...allowedReference]
|
return [...allowedAncestors, ...allowedReference]
|
||||||
|
@ -222,7 +222,7 @@ export const isaggregateGroup = node =>
|
||||||
export const isShardedIndex = node =>
|
export const isShardedIndex = node =>
|
||||||
isIndex(node) && isNonEmptyString(node.getShardName)
|
isIndex(node) && isNonEmptyString(node.getShardName)
|
||||||
export const isRoot = node => isSomething(node) && node.isRoot()
|
export const isRoot = node => isSomething(node) && node.isRoot()
|
||||||
export const findRoot = node => isRoot(node) ? node : findRoot(node.parent())
|
export const findRoot = node => (isRoot(node) ? node : findRoot(node.parent()))
|
||||||
export const isDecendantOfARecord = hasMatchingAncestor(isRecord)
|
export const isDecendantOfARecord = hasMatchingAncestor(isRecord)
|
||||||
export const isGlobalIndex = node => isIndex(node) && isRoot(node.parent())
|
export const isGlobalIndex = node => isIndex(node) && isRoot(node.parent())
|
||||||
export const isReferenceIndex = node =>
|
export const isReferenceIndex = node =>
|
||||||
|
@ -231,10 +231,8 @@ export const isAncestorIndex = node =>
|
||||||
isIndex(node) && node.indexType === indexTypes.ancestor
|
isIndex(node) && node.indexType === indexTypes.ancestor
|
||||||
export const isTopLevelRecord = node => isRoot(node.parent()) && isRecord(node)
|
export const isTopLevelRecord = node => isRoot(node.parent()) && isRecord(node)
|
||||||
export const isTopLevelIndex = node => isRoot(node.parent()) && isIndex(node)
|
export const isTopLevelIndex = node => isRoot(node.parent()) && isIndex(node)
|
||||||
export const getCollectionKey = recordKey => $(recordKey, [
|
export const getCollectionKey = recordKey =>
|
||||||
splitKey,
|
$(recordKey, [splitKey, parts => joinKey(parts.slice(0, parts.length - 1))])
|
||||||
parts => joinKey(parts.slice(0, parts.length - 1))
|
|
||||||
])
|
|
||||||
export const fieldReversesReferenceToNode = node => field =>
|
export const fieldReversesReferenceToNode = node => field =>
|
||||||
field.type === "reference" &&
|
field.type === "reference" &&
|
||||||
intersection(field.typeOptions.reverseIndexNodeKeys)(
|
intersection(field.typeOptions.reverseIndexNodeKeys)(
|
||||||
|
|
|
@ -58,7 +58,7 @@ const api = app => ({
|
||||||
validateNode,
|
validateNode,
|
||||||
validateAll,
|
validateAll,
|
||||||
validateTriggers,
|
validateTriggers,
|
||||||
upgradeData: upgradeData(app)
|
upgradeData: upgradeData(app),
|
||||||
})
|
})
|
||||||
|
|
||||||
export const getTemplateApi = app => api(app)
|
export const getTemplateApi = app => api(app)
|
||||||
|
|
|
@ -5,7 +5,6 @@ import { joinKey } from "../common"
|
||||||
import { initialiseIndex } from "../indexing/initialiseIndex"
|
import { initialiseIndex } from "../indexing/initialiseIndex"
|
||||||
|
|
||||||
export const initialiseNewIndex = async (app, indexNode) => {
|
export const initialiseNewIndex = async (app, indexNode) => {
|
||||||
|
|
||||||
if (isTopLevelIndex(indexNode)) {
|
if (isTopLevelIndex(indexNode)) {
|
||||||
await initialiseIndex(app.datastore, "/", indexNode)
|
await initialiseIndex(app.datastore, "/", indexNode)
|
||||||
return
|
return
|
||||||
|
@ -18,10 +17,11 @@ export const initialiseNewIndex = async (app, indexNode) => {
|
||||||
for (const id of result.ids) {
|
for (const id of result.ids) {
|
||||||
const recordKey = joinKey(result.collectionKey, id)
|
const recordKey = joinKey(result.collectionKey, id)
|
||||||
await initialiseIndex(
|
await initialiseIndex(
|
||||||
app.datastore,
|
app.datastore,
|
||||||
getRecordInfo(app.hierarchy, recordKey).dir,
|
getRecordInfo(app.hierarchy, recordKey).dir,
|
||||||
indexNode)
|
indexNode
|
||||||
|
)
|
||||||
}
|
}
|
||||||
iterateResult = await iterate()
|
iterateResult = await iterate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import { diffHierarchy, HierarchyChangeTypes } from "./diffHierarchy"
|
import { diffHierarchy, HierarchyChangeTypes } from "./diffHierarchy"
|
||||||
import { $, switchCase } from "../common"
|
import { $, switchCase } from "../common"
|
||||||
import {
|
import {
|
||||||
differenceBy,
|
differenceBy,
|
||||||
isEqual,
|
isEqual,
|
||||||
some,
|
some,
|
||||||
map,
|
map,
|
||||||
filter,
|
filter,
|
||||||
uniqBy,
|
uniqBy,
|
||||||
flatten
|
flatten,
|
||||||
} from "lodash/fp"
|
} from "lodash/fp"
|
||||||
import {
|
import {
|
||||||
findRoot,
|
findRoot,
|
||||||
getDependantIndexes,
|
getDependantIndexes,
|
||||||
isTopLevelRecord,
|
isTopLevelRecord,
|
||||||
isAncestorIndex
|
isAncestorIndex,
|
||||||
} from "./hierarchy"
|
} from "./hierarchy"
|
||||||
import { generateSchema } from "../indexing/indexSchemaCreator"
|
import { generateSchema } from "../indexing/indexSchemaCreator"
|
||||||
import { _buildIndex } from "../indexApi/buildIndex"
|
import { _buildIndex } from "../indexApi/buildIndex"
|
||||||
|
@ -36,121 +36,130 @@ export const upgradeData = app => async newHierarchy => {
|
||||||
|
|
||||||
if (changeActions.length === 0) return
|
if (changeActions.length === 0) return
|
||||||
|
|
||||||
const newApp = newHierarchy && cloneApp(app, {
|
const newApp =
|
||||||
hierarchy: newHierarchy
|
newHierarchy &&
|
||||||
})
|
cloneApp(app, {
|
||||||
|
hierarchy: newHierarchy,
|
||||||
|
})
|
||||||
await doUpgrade(app, newApp, changeActions)
|
await doUpgrade(app, newApp, changeActions)
|
||||||
await _saveApplicationHierarchy(newApp.datastore, newHierarchy)
|
await _saveApplicationHierarchy(newApp.datastore, newHierarchy)
|
||||||
}
|
}
|
||||||
|
|
||||||
const gatherChangeActions = (diff) =>
|
const gatherChangeActions = diff =>
|
||||||
$(diff, [
|
$(diff, [map(actionForChange), flatten, uniqBy(a => a.compareKey)])
|
||||||
map(actionForChange),
|
|
||||||
flatten,
|
|
||||||
uniqBy(a => a.compareKey)
|
|
||||||
])
|
|
||||||
|
|
||||||
const doUpgrade = async (oldApp, newApp, changeActions) => {
|
const doUpgrade = async (oldApp, newApp, changeActions) => {
|
||||||
for(let action of changeActions) {
|
for (let action of changeActions) {
|
||||||
await action.run(oldApp, newApp, action.diff)
|
await action.run(oldApp, newApp, action.diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionForChange = diff =>
|
const actionForChange = diff =>
|
||||||
switchCase(
|
switchCase(
|
||||||
|
|
||||||
[isChangeType(HierarchyChangeTypes.recordCreated), recordCreatedAction],
|
[isChangeType(HierarchyChangeTypes.recordCreated), recordCreatedAction],
|
||||||
|
|
||||||
[isChangeType(HierarchyChangeTypes.recordDeleted), deleteRecordsAction],
|
[isChangeType(HierarchyChangeTypes.recordDeleted), deleteRecordsAction],
|
||||||
|
|
||||||
[
|
[
|
||||||
isChangeType(HierarchyChangeTypes.recordFieldsChanged),
|
isChangeType(HierarchyChangeTypes.recordFieldsChanged),
|
||||||
rebuildAffectedIndexesAction
|
rebuildAffectedIndexesAction,
|
||||||
],
|
],
|
||||||
|
|
||||||
[isChangeType(HierarchyChangeTypes.recordRenamed), renameRecordAction],
|
[isChangeType(HierarchyChangeTypes.recordRenamed), renameRecordAction],
|
||||||
|
|
||||||
[
|
[
|
||||||
isChangeType(HierarchyChangeTypes.recordEstimatedRecordTypeChanged),
|
isChangeType(HierarchyChangeTypes.recordEstimatedRecordTypeChanged),
|
||||||
reshardRecordsAction
|
reshardRecordsAction,
|
||||||
],
|
],
|
||||||
|
|
||||||
[isChangeType(HierarchyChangeTypes.indexCreated), newIndexAction],
|
[isChangeType(HierarchyChangeTypes.indexCreated), newIndexAction],
|
||||||
|
|
||||||
[isChangeType(HierarchyChangeTypes.indexDeleted), deleteIndexAction],
|
[isChangeType(HierarchyChangeTypes.indexDeleted), deleteIndexAction],
|
||||||
|
|
||||||
[isChangeType(HierarchyChangeTypes.indexChanged), rebuildIndexAction],
|
[isChangeType(HierarchyChangeTypes.indexChanged), rebuildIndexAction]
|
||||||
|
|
||||||
)(diff)
|
)(diff)
|
||||||
|
|
||||||
|
const isChangeType = changeType => change => change.type === changeType
|
||||||
const isChangeType = changeType => change =>
|
|
||||||
change.type === changeType
|
|
||||||
|
|
||||||
const action = (diff, compareKey, run) => ({
|
const action = (diff, compareKey, run) => ({
|
||||||
diff,
|
diff,
|
||||||
compareKey,
|
compareKey,
|
||||||
run,
|
run,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const reshardRecordsAction = diff => [
|
||||||
const reshardRecordsAction = diff =>
|
action(diff, `reshardRecords-${diff.oldNode.nodeKey()}`, runReshardRecords),
|
||||||
[action(diff, `reshardRecords-${diff.oldNode.nodeKey()}`, runReshardRecords)]
|
]
|
||||||
|
|
||||||
const rebuildIndexAction = diff =>
|
const rebuildIndexAction = diff => [
|
||||||
[action(diff, `rebuildIndex-${diff.newNode.nodeKey()}`, runRebuildIndex)]
|
action(diff, `rebuildIndex-${diff.newNode.nodeKey()}`, runRebuildIndex),
|
||||||
|
]
|
||||||
|
|
||||||
const newIndexAction = diff => {
|
const newIndexAction = diff => {
|
||||||
if (isAncestorIndex(diff.newNode)) {
|
if (isAncestorIndex(diff.newNode)) {
|
||||||
return [action(diff, `rebuildIndex-${diff.newNode.nodeKey()}`, runRebuildIndex)]
|
return [
|
||||||
|
action(diff, `rebuildIndex-${diff.newNode.nodeKey()}`, runRebuildIndex),
|
||||||
|
]
|
||||||
} else {
|
} else {
|
||||||
return [action(diff, `newIndex-${diff.newNode.nodeKey()}`, runNewIndex)]
|
return [action(diff, `newIndex-${diff.newNode.nodeKey()}`, runNewIndex)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteIndexAction = diff =>
|
const deleteIndexAction = diff => [
|
||||||
[action(diff, `deleteIndex-${diff.oldNode.nodeKey()}`, runDeleteIndex)]
|
action(diff, `deleteIndex-${diff.oldNode.nodeKey()}`, runDeleteIndex),
|
||||||
|
]
|
||||||
|
|
||||||
const deleteRecordsAction = diff =>
|
const deleteRecordsAction = diff => [
|
||||||
[action(diff, `deleteRecords-${diff.oldNode.nodeKey()}`, runDeleteRecords)]
|
action(diff, `deleteRecords-${diff.oldNode.nodeKey()}`, runDeleteRecords),
|
||||||
|
]
|
||||||
|
|
||||||
const renameRecordAction = diff =>
|
const renameRecordAction = diff => [
|
||||||
[action(diff, `renameRecords-${diff.oldNode.nodeKey()}`, runRenameRecord)]
|
action(diff, `renameRecords-${diff.oldNode.nodeKey()}`, runRenameRecord),
|
||||||
|
]
|
||||||
|
|
||||||
const recordCreatedAction = diff => {
|
const recordCreatedAction = diff => {
|
||||||
if (isTopLevelRecord(diff.newNode)) {
|
if (isTopLevelRecord(diff.newNode)) {
|
||||||
return [action(diff, `initialiseRoot`, runInitialiseRoot)]
|
return [action(diff, `initialiseRoot`, runInitialiseRoot)]
|
||||||
}
|
}
|
||||||
|
|
||||||
return [action(diff, `initialiseChildRecord-${diff.newNode.nodeKey()}`, runInitialiseChildRecord)]
|
return [
|
||||||
|
action(
|
||||||
|
diff,
|
||||||
|
`initialiseChildRecord-${diff.newNode.nodeKey()}`,
|
||||||
|
runInitialiseChildRecord
|
||||||
|
),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
const rebuildAffectedIndexesAction = diff =>{
|
const rebuildAffectedIndexesAction = diff => {
|
||||||
const newHierarchy = findRoot(diff.newNode)
|
const newHierarchy = findRoot(diff.newNode)
|
||||||
const oldHierarchy = findRoot(diff.oldNode)
|
const oldHierarchy = findRoot(diff.oldNode)
|
||||||
const indexes = getDependantIndexes(newHierarchy, diff.newNode)
|
const indexes = getDependantIndexes(newHierarchy, diff.newNode)
|
||||||
|
|
||||||
const changedFields = (() => {
|
const changedFields = (() => {
|
||||||
const addedFields = differenceBy(f => f.name)
|
const addedFields = differenceBy(f => f.name)(diff.oldNode.fields)(
|
||||||
(diff.oldNode.fields)
|
diff.newNode.fields
|
||||||
(diff.newNode.fields)
|
)
|
||||||
|
|
||||||
|
const removedFields = differenceBy(f => f.name)(diff.newNode.fields)(
|
||||||
|
diff.oldNode.fields
|
||||||
|
)
|
||||||
|
|
||||||
const removedFields = differenceBy(f => f.name)
|
|
||||||
(diff.newNode.fields)
|
|
||||||
(diff.oldNode.fields)
|
|
||||||
|
|
||||||
return map(f => f.name)([...addedFields, ...removedFields])
|
return map(f => f.name)([...addedFields, ...removedFields])
|
||||||
})()
|
})()
|
||||||
|
|
||||||
const isIndexAffected = i => {
|
const isIndexAffected = i => {
|
||||||
if (!isEqual(
|
if (
|
||||||
generateSchema(oldHierarchy, i),
|
!isEqual(generateSchema(oldHierarchy, i), generateSchema(newHierarchy, i))
|
||||||
generateSchema(newHierarchy, i))) return true
|
)
|
||||||
|
return true
|
||||||
|
|
||||||
if (some(f => indexes.filter.indexOf(`record.${f}`) > -1)(changedFields))
|
if (some(f => indexes.filter.indexOf(`record.${f}`) > -1)(changedFields))
|
||||||
return true
|
return true
|
||||||
|
|
||||||
if (some(f => indexes.getShardName.indexOf(`record.${f}`) > -1)(changedFields))
|
if (
|
||||||
|
some(f => indexes.getShardName.indexOf(`record.${f}`) > -1)(changedFields)
|
||||||
|
)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
@ -158,10 +167,12 @@ const rebuildAffectedIndexesAction = diff =>{
|
||||||
|
|
||||||
return $(indexes, [
|
return $(indexes, [
|
||||||
filter(isIndexAffected),
|
filter(isIndexAffected),
|
||||||
map(i => action({ newNode:i }, `rebuildIndex-${i.nodeKey()}`, runRebuildIndex))
|
map(i =>
|
||||||
|
action({ newNode: i }, `rebuildIndex-${i.nodeKey()}`, runRebuildIndex)
|
||||||
|
),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
const runReshardRecords = async change => {
|
const runReshardRecords = async change => {
|
||||||
throw new Error("Resharding of records is not supported yet")
|
throw new Error("Resharding of records is not supported yet")
|
||||||
}
|
}
|
||||||
|
@ -170,7 +181,7 @@ const runRebuildIndex = async (_, newApp, diff) => {
|
||||||
await _buildIndex(newApp, diff.newNode.nodeKey())
|
await _buildIndex(newApp, diff.newNode.nodeKey())
|
||||||
}
|
}
|
||||||
|
|
||||||
const runDeleteIndex = async (oldApp, _, diff) => {
|
const runDeleteIndex = async (oldApp, _, diff) => {
|
||||||
await deleteAllIndexFilesForNode(oldApp, diff.oldNode)
|
await deleteAllIndexFilesForNode(oldApp, diff.oldNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,4 +205,4 @@ const runInitialiseRoot = async (_, newApp) => {
|
||||||
|
|
||||||
const runInitialiseChildRecord = async (_, newApp, diff) => {
|
const runInitialiseChildRecord = async (_, newApp, diff) => {
|
||||||
await initialiseChildrenForNode(newApp, diff.newNode)
|
await initialiseChildrenForNode(newApp, diff.newNode)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@ export const cleanup = async app => {
|
||||||
} finally {
|
} finally {
|
||||||
await releaseLock(app, lock)
|
await releaseLock(app, lock)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getTransactionLock = async app =>
|
const getTransactionLock = async app =>
|
||||||
|
|
|
@ -40,7 +40,7 @@ import {
|
||||||
fieldReversesReferenceToIndex,
|
fieldReversesReferenceToIndex,
|
||||||
isReferenceIndex,
|
isReferenceIndex,
|
||||||
getExactNodeForKey,
|
getExactNodeForKey,
|
||||||
getParentKey
|
getParentKey,
|
||||||
} from "../templateApi/hierarchy"
|
} from "../templateApi/hierarchy"
|
||||||
import { getRecordInfo } from "../recordApi/recordInfo"
|
import { getRecordInfo } from "../recordApi/recordInfo"
|
||||||
import { getIndexDir } from "../indexApi/getIndexDir"
|
import { getIndexDir } from "../indexApi/getIndexDir"
|
||||||
|
@ -52,7 +52,7 @@ export const executeTransactions = app => async transactions => {
|
||||||
for (const shard of keys(recordsByShard)) {
|
for (const shard of keys(recordsByShard)) {
|
||||||
if (recordsByShard[shard].isRebuild)
|
if (recordsByShard[shard].isRebuild)
|
||||||
await initialiseIndex(
|
await initialiseIndex(
|
||||||
app.datastore,
|
app.datastore,
|
||||||
getParentKey(recordsByShard[shard].indexDir),
|
getParentKey(recordsByShard[shard].indexDir),
|
||||||
recordsByShard[shard].indexNode
|
recordsByShard[shard].indexNode
|
||||||
)
|
)
|
||||||
|
@ -87,8 +87,9 @@ const mappedRecordsByIndexShard = (hierarchy, transactions) => {
|
||||||
transByShard[t.indexShardKey] = {
|
transByShard[t.indexShardKey] = {
|
||||||
writes: [],
|
writes: [],
|
||||||
removes: [],
|
removes: [],
|
||||||
isRebuild: some(i => i.indexShardKey === t.indexShardKey)(indexBuild.toWrite)
|
isRebuild:
|
||||||
|| some(i => i.indexShardKey === t.indexShardKey)(indexBuild.toRemove),
|
some(i => i.indexShardKey === t.indexShardKey)(indexBuild.toWrite) ||
|
||||||
|
some(i => i.indexShardKey === t.indexShardKey)(indexBuild.toRemove),
|
||||||
indexDir: t.indexDir,
|
indexDir: t.indexDir,
|
||||||
indexNodeKey: t.indexNode.nodeKey(),
|
indexNodeKey: t.indexNode.nodeKey(),
|
||||||
indexNode: t.indexNode,
|
indexNode: t.indexNode,
|
||||||
|
@ -219,7 +220,7 @@ const getUpdateTransactionsByShard = (hierarchy, transactions) => {
|
||||||
|
|
||||||
const getBuildIndexTransactionsByShard = (hierarchy, transactions) => {
|
const getBuildIndexTransactionsByShard = (hierarchy, transactions) => {
|
||||||
const buildTransactions = $(transactions, [filter(isBuildIndex)])
|
const buildTransactions = $(transactions, [filter(isBuildIndex)])
|
||||||
if (!isNonEmptyArray(buildTransactions)) return { toWrite:[], toRemove:[] }
|
if (!isNonEmptyArray(buildTransactions)) return { toWrite: [], toRemove: [] }
|
||||||
const indexNode = transactions.indexNode
|
const indexNode = transactions.indexNode
|
||||||
|
|
||||||
const getIndexDirs = t => {
|
const getIndexDirs = t => {
|
||||||
|
@ -259,7 +260,7 @@ const getBuildIndexTransactionsByShard = (hierarchy, transactions) => {
|
||||||
|
|
||||||
return $(buildTransactions, [
|
return $(buildTransactions, [
|
||||||
map(t => {
|
map(t => {
|
||||||
const mappedRecord = evaluate(t.record)(indexNode)
|
const mappedRecord = evaluate(t.record)(indexNode)
|
||||||
mappedRecord.result = mappedRecord.result || t.record
|
mappedRecord.result = mappedRecord.result || t.record
|
||||||
const indexDirs = getIndexDirs(t)
|
const indexDirs = getIndexDirs(t)
|
||||||
return $(indexDirs, [
|
return $(indexDirs, [
|
||||||
|
@ -274,16 +275,16 @@ const getBuildIndexTransactionsByShard = (hierarchy, transactions) => {
|
||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
])
|
])
|
||||||
|
|
||||||
}),
|
}),
|
||||||
flatten,
|
flatten,
|
||||||
reduce((obj, res) => {
|
reduce(
|
||||||
if (res.mappedRecord.passedFilter)
|
(obj, res) => {
|
||||||
obj.toWrite.push(res)
|
if (res.mappedRecord.passedFilter) obj.toWrite.push(res)
|
||||||
else
|
else obj.toRemove.push(res)
|
||||||
obj.toRemove.push(res)
|
return obj
|
||||||
return obj
|
},
|
||||||
}, { toWrite: [], toRemove: [] })
|
{ toWrite: [], toRemove: [] }
|
||||||
|
),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,15 +31,16 @@ export const retrieve = async app => {
|
||||||
app,
|
app,
|
||||||
joinKey(TRANSACTIONS_FOLDER, buildIndexFolder)
|
joinKey(TRANSACTIONS_FOLDER, buildIndexFolder)
|
||||||
)
|
)
|
||||||
if(transactions.length === 0) {
|
if (transactions.length === 0) {
|
||||||
await app.datastore.deleteFolder(
|
await app.datastore.deleteFolder(
|
||||||
joinKey(TRANSACTIONS_FOLDER, buildIndexFolder))
|
joinKey(TRANSACTIONS_FOLDER, buildIndexFolder)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
return transactions
|
return transactions
|
||||||
}
|
}
|
||||||
currentFolderIndex += 1
|
currentFolderIndex += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@ const retrieveBuildIndexTransactions = async (app, buildIndexFolder) => {
|
||||||
const files = await app.datastore.getFolderContents(childFolderKey)
|
const files = await app.datastore.getFolderContents(childFolderKey)
|
||||||
|
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
return { childFolderKey, files }
|
return { childFolderKey, files }
|
||||||
}
|
}
|
||||||
|
|
||||||
await app.datastore.deleteFolder(childFolderKey)
|
await app.datastore.deleteFolder(childFolderKey)
|
||||||
|
|
|
@ -11,4 +11,4 @@ export const setCleanupFunc = (app, cleanupTransactions) => {
|
||||||
newCleanup.isDefault = true
|
newCleanup.isDefault = true
|
||||||
app.cleanupTransactions = newCleanup
|
app.cleanupTransactions = newCleanup
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,10 @@ export const UPDATE_RECORD_TRANSACTION = "update"
|
||||||
export const DELETE_RECORD_TRANSACTION = "delete"
|
export const DELETE_RECORD_TRANSACTION = "delete"
|
||||||
export const BUILD_INDEX_TRANSACTION = "build"
|
export const BUILD_INDEX_TRANSACTION = "build"
|
||||||
|
|
||||||
export const isUpdate_Or_Rebuild = isOfType(UPDATE_RECORD_TRANSACTION, BUILD_INDEX_TRANSACTION)
|
export const isUpdate_Or_Rebuild = isOfType(
|
||||||
|
UPDATE_RECORD_TRANSACTION,
|
||||||
|
BUILD_INDEX_TRANSACTION
|
||||||
|
)
|
||||||
export const isUpdate = isOfType(UPDATE_RECORD_TRANSACTION)
|
export const isUpdate = isOfType(UPDATE_RECORD_TRANSACTION)
|
||||||
export const isDelete = isOfType(DELETE_RECORD_TRANSACTION)
|
export const isDelete = isOfType(DELETE_RECORD_TRANSACTION)
|
||||||
export const isCreate = isOfType(CREATE_RECORD_TRANSACTION)
|
export const isCreate = isOfType(CREATE_RECORD_TRANSACTION)
|
||||||
|
|
|
@ -39,7 +39,7 @@ export const testTemplatesPath = testAreaName =>
|
||||||
path.join(testFileArea(testAreaName), templateDefinitions)
|
path.join(testFileArea(testAreaName), templateDefinitions)
|
||||||
|
|
||||||
export const getMemoryStore = () => setupDatastore(memory({}))
|
export const getMemoryStore = () => setupDatastore(memory({}))
|
||||||
export const getMemoryTemplateApi = (store) => {
|
export const getMemoryTemplateApi = store => {
|
||||||
const app = {
|
const app = {
|
||||||
datastore: store || getMemoryStore(),
|
datastore: store || getMemoryStore(),
|
||||||
publish: () => {},
|
publish: () => {},
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { getMemoryTemplateApi, appFromTempalteApi } from "./specHelpers"
|
||||||
import { getFlattenedHierarchy } from "../src/templateApi/hierarchy"
|
import { getFlattenedHierarchy } from "../src/templateApi/hierarchy"
|
||||||
import { initialiseData } from "../src/appInitialise/initialiseData"
|
import { initialiseData } from "../src/appInitialise/initialiseData"
|
||||||
|
|
||||||
export const setup = async (store) => {
|
export const setup = async store => {
|
||||||
const { templateApi } = await getMemoryTemplateApi(store)
|
const { templateApi } = await getMemoryTemplateApi(store)
|
||||||
const root = templateApi.getNewRootLevel()
|
const root = templateApi.getNewRootLevel()
|
||||||
const contact = templateApi.getNewRecordTemplate(root, "contact", true)
|
const contact = templateApi.getNewRecordTemplate(root, "contact", true)
|
||||||
|
@ -21,10 +21,10 @@ export const setup = async (store) => {
|
||||||
const deal = templateApi.getNewRecordTemplate(contact, "deal", true)
|
const deal = templateApi.getNewRecordTemplate(contact, "deal", true)
|
||||||
deal.collectionName = "deals"
|
deal.collectionName = "deals"
|
||||||
|
|
||||||
templateApi.addField(deal, {...nameField})
|
templateApi.addField(deal, { ...nameField })
|
||||||
templateApi.addField(deal, {...statusField})
|
templateApi.addField(deal, { ...statusField })
|
||||||
|
|
||||||
templateApi.addField(lead, {...nameField})
|
templateApi.addField(lead, { ...nameField })
|
||||||
|
|
||||||
getFlattenedHierarchy(root)
|
getFlattenedHierarchy(root)
|
||||||
|
|
||||||
|
@ -38,10 +38,15 @@ export const setup = async (store) => {
|
||||||
app.hierarchy = root
|
app.hierarchy = root
|
||||||
|
|
||||||
return {
|
return {
|
||||||
root, contact, lead, app,
|
root,
|
||||||
deal, templateApi, store: templateApi._storeHandle,
|
contact,
|
||||||
|
lead,
|
||||||
|
app,
|
||||||
|
deal,
|
||||||
|
templateApi,
|
||||||
|
store: templateApi._storeHandle,
|
||||||
all_contacts: root.indexes[0],
|
all_contacts: root.indexes[0],
|
||||||
all_leads: root.indexes[1],
|
all_leads: root.indexes[1],
|
||||||
deals_for_contacts: contact.indexes[0],
|
deals_for_contacts: contact.indexes[0],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,3 @@ export { default as CardBody } from "./CardBody.svelte"
|
||||||
export { default as CardFooter } from "./CardFooter.svelte"
|
export { default as CardFooter } from "./CardFooter.svelte"
|
||||||
export { default as CardHeader } from "./CardHeader.svelte"
|
export { default as CardHeader } from "./CardHeader.svelte"
|
||||||
export { default as CardImage } from "./CardImage.svelte"
|
export { default as CardImage } from "./CardImage.svelte"
|
||||||
|
|
||||||
|
|
|
@ -1,54 +1,54 @@
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
|
|
||||||
function createItemsStore(componentOnSelect) {
|
function createItemsStore(componentOnSelect) {
|
||||||
const { subscribe, set, update } = writable([])
|
const { subscribe, set, update } = writable([])
|
||||||
|
|
||||||
function addItem(item) {
|
function addItem(item) {
|
||||||
update(items => {
|
update(items => {
|
||||||
return [...items, item]
|
return [...items, item]
|
||||||
})
|
})
|
||||||
if (componentOnSelect) {
|
if (componentOnSelect) {
|
||||||
componentOnSelect()
|
componentOnSelect()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function addSingleItem(item) {
|
function addSingleItem(item) {
|
||||||
set([item])
|
set([item])
|
||||||
if (componentOnSelect) {
|
if (componentOnSelect) {
|
||||||
componentOnSelect();
|
componentOnSelect()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function removeItem(itemId) {
|
function removeItem(itemId) {
|
||||||
update(items => {
|
update(items => {
|
||||||
let index = getItemIdx(items, itemId)
|
let index = getItemIdx(items, itemId)
|
||||||
items.splice(index, 1);
|
items.splice(index, 1)
|
||||||
return items;
|
return items
|
||||||
})
|
})
|
||||||
if (componentOnSelect) {
|
if (componentOnSelect) {
|
||||||
componentOnSelect();
|
componentOnSelect()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function clearItems() {
|
function clearItems() {
|
||||||
set([]);
|
set([])
|
||||||
if (componentOnSelect) {
|
if (componentOnSelect) {
|
||||||
componentOnSelect();
|
componentOnSelect()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getItemIdx(items, itemId) {
|
function getItemIdx(items, itemId) {
|
||||||
return items.findIndex(i => i && i._id === itemId);
|
return items.findIndex(i => i && i._id === itemId)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
subscribe,
|
subscribe,
|
||||||
addItem,
|
addItem,
|
||||||
addSingleItem,
|
addSingleItem,
|
||||||
removeItem,
|
removeItem,
|
||||||
clearItems,
|
clearItems,
|
||||||
getItemIdx
|
getItemIdx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default createItemsStore
|
export default createItemsStore
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
const isDate = /^\d{1,2}\/\d{1,2}\/\d{4}$/
|
const isDate = /^\d{1,2}\/\d{1,2}\/\d{4}$/
|
||||||
if (isDate.test(value)) {
|
if (isDate.test(value)) {
|
||||||
const [year, month, day] = value.split("/").reverse()
|
const [year, month, day] = value.split("/").reverse()
|
||||||
if (month > 0 && month <= 12 && (day > 0 && day <= 31)) {
|
if (month > 0 && month <= 12 && day > 0 && day <= 31) {
|
||||||
date = new Date(year, month - 1, day)
|
date = new Date(year, month - 1, day)
|
||||||
navDate = date
|
navDate = date
|
||||||
openCalendar(true)
|
openCalendar(true)
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
import "./_style.scss";
|
import "./_style.scss"
|
||||||
export { default as DatePicker } from "./DatePicker.svelte";
|
export { default as DatePicker } from "./DatePicker.svelte"
|
||||||
|
|
|
@ -2,4 +2,4 @@ import "./_style.scss"
|
||||||
export { default as Dialog } from "./Dialog.svelte"
|
export { default as Dialog } from "./Dialog.svelte"
|
||||||
export { default as DialogActions } from "./DialogActions.svelte"
|
export { default as DialogActions } from "./DialogActions.svelte"
|
||||||
export { default as DialogContent } from "./DialogContent.svelte"
|
export { default as DialogContent } from "./DialogContent.svelte"
|
||||||
export { default as DialogHeader } from "./DialogHeader.svelte"
|
export { default as DialogHeader } from "./DialogHeader.svelte"
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
import "./_style.scss";
|
import "./_style.scss"
|
||||||
export { default as IconButton } from "./IconButton.svelte";
|
export { default as IconButton } from "./IconButton.svelte"
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
})
|
})
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
let item = itemData()
|
let item = itemData()
|
||||||
if (!disabled) {
|
if (!disabled) {
|
||||||
if (
|
if (
|
||||||
listProps.singleSelection ||
|
listProps.singleSelection ||
|
||||||
|
|
|
@ -32,18 +32,17 @@
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
_bb.setContext("BBMD:list:props", { singleSelection: true })
|
_bb.setContext("BBMD:list:props", { singleSelection: true })
|
||||||
_bb.setContext("BBMD:list:addItem", i => listItems = [...listItems, i])
|
_bb.setContext("BBMD:list:addItem", i => (listItems = [...listItems, i]))
|
||||||
|
|
||||||
selectedItemsStore = createItemsStore(() => {
|
selectedItemsStore = createItemsStore(() => {
|
||||||
|
const v =
|
||||||
const v = $selectedItemsStore && $selectedItemsStore.length > 0
|
$selectedItemsStore && $selectedItemsStore.length > 0
|
||||||
? $selectedItemsStore[0].value
|
? $selectedItemsStore[0].value
|
||||||
: "";
|
: ""
|
||||||
|
|
||||||
value = v
|
value = v
|
||||||
_bb.setStateFromBinding(_bb.props.value, v)
|
_bb.setStateFromBinding(_bb.props.value, v)
|
||||||
_bb.call(onSelect, v)
|
_bb.call(onSelect, v)
|
||||||
|
|
||||||
})
|
})
|
||||||
_bb.setContext("BBMD:list:selectItemStore", selectedItemsStore)
|
_bb.setContext("BBMD:list:selectItemStore", selectedItemsStore)
|
||||||
|
|
||||||
|
@ -58,10 +57,8 @@
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
$: useNotchedOutline = variant === "outlined"
|
$: useNotchedOutline = variant === "outlined"
|
||||||
$: selectList && _bb.attachChildren(selectList)
|
$: selectList && _bb.attachChildren(selectList)
|
||||||
|
|
||||||
|
|
||||||
$: modifiers = { variant, disabled, required, noLabel: !label }
|
$: modifiers = { variant, disabled, required, noLabel: !label }
|
||||||
$: props = { modifiers }
|
$: props = { modifiers }
|
||||||
|
@ -69,8 +66,6 @@
|
||||||
$: if (value !== undefined && instance && listItems.length > 0) {
|
$: if (value !== undefined && instance && listItems.length > 0) {
|
||||||
instance.selectedIndex = listItems.findIndex(i => i.value === value)
|
instance.selectedIndex = listItems.findIndex(i => i.value === value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={select} id={_helperId} class={selectClass}>
|
<div bind:this={select} id={_helperId} class={selectClass}>
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import "./_style.scss"
|
import "./_style.scss"
|
||||||
export { default as HelperText } from "./HelperText.svelte"
|
export { default as HelperText } from "./HelperText.svelte"
|
||||||
export { default as Select } from "./Select.svelte";
|
export { default as Select } from "./Select.svelte"
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
import "./_style.scss"
|
import "./_style.scss"
|
||||||
export {default as Slider} from "./Slider.svelte"
|
export { default as Slider } from "./Slider.svelte"
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
import "./_style.scss"
|
import "./_style.scss"
|
||||||
export { default as Switch } from "./Switch.svelte"
|
export { default as Switch } from "./Switch.svelte"
|
||||||
|
|
|
@ -346,7 +346,7 @@ module.exports = async context => {
|
||||||
await bb.recordApi.save(userInMaster)
|
await bb.recordApi.save(userInMaster)
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteLatestPackageFromCache = (appname) => {
|
const deleteLatestPackageFromCache = appname => {
|
||||||
deleteCachedPackage(context, appname, LATEST_VERSIONID)
|
deleteCachedPackage(context, appname, LATEST_VERSIONID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue