formatting

This commit is contained in:
Martin McKeaveney 2020-03-27 16:58:32 +00:00
parent ff73793b4c
commit f82a954666
77 changed files with 629 additions and 634 deletions

View File

@ -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({

View File

@ -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;
} }

View File

@ -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>

View File

@ -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 {

View File

@ -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()

View File

@ -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
}) })
} }

View File

@ -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)

View File

@ -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>

View File

@ -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}

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -24,7 +24,6 @@
} }
} }
} }
</script> </script>
<div bind:this={ukModal} uk-modal {id}> <div bind:this={ukModal} uk-modal {id}>

View File

@ -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">

View File

@ -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}>

View File

@ -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>

View File

@ -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)),

View File

@ -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
} }

View File

@ -1 +1 @@
export { default } from "./ModelDataTable.svelte" export { default } from "./ModelDataTable.svelte"

View File

@ -9,4 +9,4 @@
<section> <section>
<ModelView /> <ModelView />
</section> </section>

View File

@ -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>

View File

@ -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()
} }

View File

@ -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>

View File

@ -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>

View File

@ -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"

View File

@ -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

View File

@ -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"),
}) })

View File

@ -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>

View File

@ -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 {

View File

@ -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>

View File

@ -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>

View File

@ -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 {

View File

@ -178,8 +178,6 @@
height: 48px; height: 48px;
} }
li button { li button {
width: 48px; width: 48px;
height: 48px; height: 48px;

View File

@ -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 {

View File

@ -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;

View File

@ -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>

View File

@ -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>

View File

@ -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 {

View File

@ -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;

View File

@ -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)
} }

View File

@ -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
} }

View File

@ -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: [] }

View File

@ -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})`
} }

View File

@ -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

View File

@ -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,

View File

@ -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)
} }
} }

View File

@ -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"

View File

@ -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) =>

View File

@ -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)),
]) ])

View File

@ -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,
} }
} }

View File

@ -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 }
} }

View File

@ -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)) }
}

View File

@ -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)
} )
}

View File

@ -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)

View File

@ -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)(

View File

@ -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)

View File

@ -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()
} }
} }

View File

@ -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)
} }

View File

@ -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 =>

View File

@ -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: [] }
),
]) ])
} }

View File

@ -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)

View File

@ -11,4 +11,4 @@ export const setCleanupFunc = (app, cleanupTransactions) => {
newCleanup.isDefault = true newCleanup.isDefault = true
app.cleanupTransactions = newCleanup app.cleanupTransactions = newCleanup
} }
} }

View File

@ -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)

View File

@ -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: () => {},

View File

@ -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],
} }
} }

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -1,2 +1,2 @@
import "./_style.scss"; import "./_style.scss"
export { default as DatePicker } from "./DatePicker.svelte"; export { default as DatePicker } from "./DatePicker.svelte"

View File

@ -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"

View File

@ -1,2 +1,2 @@
import "./_style.scss"; import "./_style.scss"
export { default as IconButton } from "./IconButton.svelte"; export { default as IconButton } from "./IconButton.svelte"

View File

@ -56,7 +56,7 @@
}) })
function handleClick() { function handleClick() {
let item = itemData() let item = itemData()
if (!disabled) { if (!disabled) {
if ( if (
listProps.singleSelection || listProps.singleSelection ||

View File

@ -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}>

View File

@ -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"

View File

@ -1,2 +1,2 @@
import "./_style.scss" import "./_style.scss"
export {default as Slider} from "./Slider.svelte" export { default as Slider } from "./Slider.svelte"

View File

@ -1,2 +1,2 @@
import "./_style.scss" import "./_style.scss"
export { default as Switch } from "./Switch.svelte" export { default as Switch } from "./Switch.svelte"

View File

@ -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)
} }