From 48f6ac2b988ed46bdc8c6fa822726a02618ccd71 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 15 Jun 2020 16:41:31 +0100 Subject: [PATCH 01/20] structuring new backend UI --- packages/builder/package.json | 4 +- packages/builder/rollup.config.js | 4 + packages/builder/src/actions/backend.js | 0 packages/builder/src/actions/index.js | 0 .../builder/src/builderStore/store/backend.js | 18 +-- .../CreateEditModel/CreateEditModel.svelte | 7 -- .../src/components/nav/HierarchyRow.svelte | 8 -- .../nav/ModelNavigator/Block.svelte | 47 ++++++++ .../nav/ModelNavigator/BlockNavigator.svelte | 79 +++++++++++++ .../nav/ModelNavigator/ListItem.svelte | 46 ++++++++ .../nav/ModelNavigator/ModelNavigator.svelte | 90 ++++++++++++++ .../src/components/nav/ModelSetupNav.svelte | 111 ++++++++++++++++++ .../builder/src/constants/backend/index.js | 101 ++++++++++++++++ .../[application]/backend/_layout.svelte | 8 +- .../backend/actions/index.svelte | 0 .../database/[selectedDatabase]/Block.svelte | 49 ++++++++ .../[selectedDatabase]/newmodel.svelte | 40 +++++++ .../server/src/api/routes/tests/model.spec.js | 2 +- .../server/src/utilities/builder/index.js | 2 +- 19 files changed, 580 insertions(+), 36 deletions(-) delete mode 100644 packages/builder/src/actions/backend.js delete mode 100644 packages/builder/src/actions/index.js create mode 100644 packages/builder/src/components/nav/ModelNavigator/Block.svelte create mode 100644 packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte create mode 100644 packages/builder/src/components/nav/ModelNavigator/ListItem.svelte create mode 100644 packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte create mode 100644 packages/builder/src/components/nav/ModelSetupNav.svelte create mode 100644 packages/builder/src/constants/backend/index.js delete mode 100644 packages/builder/src/pages/[application]/backend/actions/index.svelte create mode 100644 packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/Block.svelte create mode 100644 packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/newmodel.svelte diff --git a/packages/builder/package.json b/packages/builder/package.json index 8fe9ffd494..b2de1252b3 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "@beyonk/svelte-notifications": "^2.0.3", - "@budibase/bbui": "^1.1.1", + "@budibase/bbui": "^1.4.1", "@budibase/client": "^0.0.32", "@nx-js/compiler-util": "^2.0.0", "codemirror": "^5.51.0", @@ -86,4 +86,4 @@ "svelte": "3.23.x" }, "gitHead": "115189f72a850bfb52b65ec61d932531bf327072" -} \ No newline at end of file +} diff --git a/packages/builder/rollup.config.js b/packages/builder/rollup.config.js index fd7c487c3f..5441268407 100644 --- a/packages/builder/rollup.config.js +++ b/packages/builder/rollup.config.js @@ -153,6 +153,10 @@ export default { find: "builderStore", replacement: path.resolve(projectRootDir, "src/builderStore"), }, + { + find: "constants", + replacement: path.resolve(projectRootDir, "src/constants"), + }, ], customResolver, }), diff --git a/packages/builder/src/actions/backend.js b/packages/builder/src/actions/backend.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/builder/src/actions/index.js b/packages/builder/src/actions/index.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 9a5a7b1fbc..b7e831c43b 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -39,18 +39,6 @@ export const getBackendUiStore = () => { state.views = views return state }) - /** TODO: DEMO SOLUTION**/ - if (!models || models.length === 0) { - const { open, close } = getContext("simple-modal") - open( - CreateEditModelModal, - { - onClosed: close, - }, - { styleContent: { padding: "0" } } - ) - } - /** DEMO SOLUTION END **/ }, }, records: { @@ -71,6 +59,10 @@ export const getBackendUiStore = () => { }), }, models: { + select: model => store.update(state => { + state.selectedModel = model; + return state; + }), create: model => store.update(state => { state.models.push(model) @@ -78,7 +70,7 @@ export const getBackendUiStore = () => { state.selectedModel = model state.selectedView = `all_${model._id}` return state - }), + }) }, views: { select: view => diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte index 6264b74e09..4eee351e7b 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte @@ -20,12 +20,6 @@ $: modelFields = model.schema ? Object.entries(model.schema) : [] $: instanceId = $backendUiStore.selectedDatabase._id - function editField() {} - - function deleteField() {} - - function onFinishedFieldEdit() {} - async function saveModel() { const SAVE_MODEL_URL = `/api/${instanceId}/models` const response = await api.post(SAVE_MODEL_URL, model) @@ -94,7 +88,6 @@ {:else} (showFieldView = false)} /> {/if} diff --git a/packages/builder/src/components/nav/HierarchyRow.svelte b/packages/builder/src/components/nav/HierarchyRow.svelte index 8921ab74de..d57463cc20 100644 --- a/packages/builder/src/components/nav/HierarchyRow.svelte +++ b/packages/builder/src/components/nav/HierarchyRow.svelte @@ -31,14 +31,6 @@ class:selected={$backendUiStore.selectedView === `all_${node._id}`}> {node.name} - diff --git a/packages/builder/src/components/nav/ModelNavigator/Block.svelte b/packages/builder/src/components/nav/ModelNavigator/Block.svelte new file mode 100644 index 0000000000..c9e7f67623 --- /dev/null +++ b/packages/builder/src/components/nav/ModelNavigator/Block.svelte @@ -0,0 +1,47 @@ + + +
+ + {title} +
+ + diff --git a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte new file mode 100644 index 0000000000..8c117fbcbc --- /dev/null +++ b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte @@ -0,0 +1,79 @@ + + +
+
+ {#each HEADINGS as tab} + (selectedTab = tab.key)}> + {tab.title} + + {/each} +
+ +
+ {#each Object.values(blockDefinitions[selectedTab]) as blockDefinition} + + {/each} +
+
+ + diff --git a/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte b/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte new file mode 100644 index 0000000000..6452b3459d --- /dev/null +++ b/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte @@ -0,0 +1,46 @@ + + +
+ + {title} +
+ + diff --git a/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte new file mode 100644 index 0000000000..2bf286d9ee --- /dev/null +++ b/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte @@ -0,0 +1,90 @@ + + +
+ {#if $backendUiStore.selectedDatabase._id} +
+
+ + {#if selectedTab === 'NAVIGATE'} + +
+ {#each $backendUiStore.models as model} + selectModel(model)} /> + {#each Object.keys(model.schema) as field} + selectField(model.schema[field])} /> + {/each} + {/each} +
+ {:else if selectedTab === 'ADD'} + + {/if} +
+
+
+ {/if} +
+ + diff --git a/packages/builder/src/components/nav/ModelSetupNav.svelte b/packages/builder/src/components/nav/ModelSetupNav.svelte new file mode 100644 index 0000000000..f72037d33e --- /dev/null +++ b/packages/builder/src/components/nav/ModelSetupNav.svelte @@ -0,0 +1,111 @@ + + +
+ + {#if selectedTab === 'SETUP'} +
+
Name
+ +
+
+
Import Data
+ +
+ + + {:else if selectedTab === 'DELETE'} +
+
Danger Zone
+ +
+ {/if} +
+
+ + diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js new file mode 100644 index 0000000000..b49d97d262 --- /dev/null +++ b/packages/builder/src/constants/backend/index.js @@ -0,0 +1,101 @@ +const FIELD_TYPES = ["string", "number", "boolean"] + +export const FIELDS = { + PLAIN_TEXT: { + name: "Plain Text", + icon: "ri-text", + definition: { + type: "string", + constraints: { + type: "string", + length: {}, + presence: false, + }, + }, + }, + NUMBER: { + name: "Number", + icon: "ri-number-1", + definition: { + type: "number", + constraints: { + type: "number", + presence: false, + numericality: {}, + }, + }, + }, + BOOLEAN: { + name: "True/False", + icon: "ri-toggle-line", + definition: { + type: "boolean", + constraints: { + type: "boolean", + presence: false, + }, + }, + }, + OPTIONS: { + name: "Options", + icon: "ri-list-check-2", + definition: { + type: "options", + constraints: { + type: "string", + presence: false, + }, + }, + }, + DATETIME: { + name: "Date/Time", + icon: "ri-calendar-event-fill", + definition: { + type: "date", + constraints: { + type: "date", + datetime: {}, + presence: false, + }, + }, + }, + IMAGE: { + name: "Image", + icon: "ri-image-line", + definition: { + type: "image", + constraints: { + type: "string", + presence: false, + }, + }, + }, + FILE: { + name: "Image", + icon: "ri-file-line", + definition: { + type: "file", + constraints: { + type: "string", + presence: false, + }, + }, + }, + DATA_LINK: { + name: "Data Links", + icon: "ri-link", + definition: { + type: "link", + modelId: null, + constraints: { + type: "array", + }, + }, + }, +} + +export const BLOCKS = { + +} + +export const TABLES = {} diff --git a/packages/builder/src/pages/[application]/backend/_layout.svelte b/packages/builder/src/pages/[application]/backend/_layout.svelte index 0e36980c6c..9d8cb5ef17 100644 --- a/packages/builder/src/pages/[application]/backend/_layout.svelte +++ b/packages/builder/src/pages/[application]/backend/_layout.svelte @@ -3,19 +3,19 @@ import { store, backendUiStore } from "builderStore" import * as api from "components/database/ModelDataTable/api" - import BackendNav from "components/nav/BackendNav.svelte" - import SchemaManagementDrawer from "components/nav/SchemaManagementDrawer.svelte" + import ModelNavigator from "components/nav/ModelNavigator/ModelNavigator.svelte" + import ModelSetupNav from "components/nav/ModelSetupNav.svelte"
diff --git a/packages/builder/src/pages/[application]/backend/actions/index.svelte b/packages/builder/src/pages/[application]/backend/actions/index.svelte deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/Block.svelte b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/Block.svelte new file mode 100644 index 0000000000..b31ec7776f --- /dev/null +++ b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/Block.svelte @@ -0,0 +1,49 @@ + + + +
+ + {title} +
+ + diff --git a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/newmodel.svelte b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/newmodel.svelte new file mode 100644 index 0000000000..5d4b83808f --- /dev/null +++ b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/newmodel.svelte @@ -0,0 +1,40 @@ + + +
+
+

Create New Table

+ Before you can view your table, you need to set it up. +
+ +
+

Fields

+
+ {#each Object.values(FIELDS) as field} + + {/each} +
+
+ + + +
+ + \ No newline at end of file diff --git a/packages/server/src/api/routes/tests/model.spec.js b/packages/server/src/api/routes/tests/model.spec.js index 7134245fb3..4a9710b827 100644 --- a/packages/server/src/api/routes/tests/model.spec.js +++ b/packages/server/src/api/routes/tests/model.spec.js @@ -110,7 +110,7 @@ describe("/models", () => { afterEach(() => { delete testModel._rev - }) + }); it("returns a success response when a model is deleted.", async done => { request diff --git a/packages/server/src/utilities/builder/index.js b/packages/server/src/utilities/builder/index.js index 7b9a6a69ec..9a065642ad 100644 --- a/packages/server/src/utilities/builder/index.js +++ b/packages/server/src/utilities/builder/index.js @@ -41,7 +41,7 @@ const screenPath = (appPath, pageName, name) => module.exports.saveScreen = async (config, appname, pagename, screen) => { const appPath = appPackageFolder(config, appname) - const compPath = screenPath(appPath, pagename, screen.name) + const compPath = screenPath(appPath, pagename, screen.props._instanceName) await ensureDir(dirname(compPath)) if (screen._css) { delete screen._css From 987135f7b4da8a5848301bfe726d5d3ac43d50c7 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 16 Jun 2020 20:29:18 +0100 Subject: [PATCH 02/20] saving of models and fields --- .../builder/src/builderStore/store/backend.js | 49 ++-- .../modals/CreateEditModel/FieldView.svelte | 4 +- .../nav/ModelNavigator/BlockNavigator.svelte | 8 +- .../nav/ModelNavigator/ModelNavigator.svelte | 31 ++- .../nav/ModelSetupNav/FieldView.svelte | 65 +++++ .../{ => ModelSetupNav}/ModelSetupNav.svelte | 65 ++--- .../src/components/nav/ModelSetupNav/index.js | 1 + .../builder/src/constants/backend/index.js | 80 +++--- .../[application]/backend/_layout.svelte | 2 +- .../database/[selectedDatabase]/index.svelte | 9 +- packages/server/package.json | 2 +- packages/server/src/api/controllers/model.js | 24 +- packages/server/src/api/routes/model.js | 3 +- packages/server/yarn.lock | 229 +++++++++++++++++- 14 files changed, 421 insertions(+), 151 deletions(-) create mode 100644 packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte rename packages/builder/src/components/nav/{ => ModelSetupNav}/ModelSetupNav.svelte (50%) create mode 100644 packages/builder/src/components/nav/ModelSetupNav/index.js diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index b7e831c43b..cc3d78e263 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -1,13 +1,5 @@ import { writable } from "svelte/store" import api from "../api" -import { getContext } from "svelte" - -/** TODO: DEMO SOLUTION - * this section should not be here, it is a quick fix for a demo - * when we reorg the backend UI, this should disappear - * **/ -import { CreateEditModelModal } from "components/database/ModelDataTable/modals" -/** DEMO SOLUTION END **/ export const getBackendUiStore = () => { const INITIAL_BACKEND_UI_STATE = { @@ -17,6 +9,7 @@ export const getBackendUiStore = () => { users: [], selectedDatabase: {}, selectedModel: {}, + draftModel: {} } const store = writable(INITIAL_BACKEND_UI_STATE) @@ -32,6 +25,7 @@ export const getBackendUiStore = () => { state.selectedDatabase = db if (models && models.length > 0) { state.selectedModel = models[0] + state.draftModel = models[0] state.selectedView = `all_${models[0]._id}` } state.breadcrumbs = [db.name] @@ -61,16 +55,39 @@ export const getBackendUiStore = () => { models: { select: model => store.update(state => { state.selectedModel = model; - return state; + // TODO: prevent pointing to same obj + state.draftModel = model; + state.selectedField = null + return state }), - create: model => - store.update(state => { - state.models.push(model) - state.models = state.models - state.selectedModel = model - state.selectedView = `all_${model._id}` + save: model => + store.update(async state => { + const SAVE_MODEL_URL = `/api/${state.selectedDatabase._id}/models` + const response = await api.post(SAVE_MODEL_URL, model) + const savedModel = await response.json() + + state.models = [...state.models, savedModel] + state.selectedModel = savedModel + state.draftModel = savedModel + state.selectedView = `all_${savedModel._id}` return state - }) + }), + addField: field => { + store.update(state => { + if (!state.draftModel.schema) { + state.draftModel.schema = {} + } + + state.draftModel.schema = { + ...state.draftModel.schema, + [field.name]: field + } + + state.selectedField = field + + return state + }); + } }, views: { select: view => diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/FieldView.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/FieldView.svelte index c17a0ac9c8..fde876015d 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/FieldView.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/FieldView.svelte @@ -30,9 +30,7 @@ const save = () => { constraints.presence = required ? { allowEmpty: false } : false - draftField.constraints = constraints - draftField.type = type - schema[field.name] = draftField + schema[field.name] = { type, constraints } goBack() } diff --git a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte index 8c117fbcbc..5fa886c363 100644 --- a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte @@ -1,9 +1,8 @@
@@ -36,6 +39,7 @@
{#each Object.values(blockDefinitions[selectedTab]) as blockDefinition} addField(blockDefinition)} primary={true} secondary={false} tertiary={false} diff --git a/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte index 2bf286d9ee..3d28d1bd2a 100644 --- a/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte @@ -3,7 +3,7 @@ import { Switcher } from "@budibase/bbui" import { goto } from "@sveltech/routify" import { store, backendUiStore } from "builderStore" - import BlockNavigator from "./BlockNavigator.svelte"; + import BlockNavigator from "./BlockNavigator.svelte" import SchemaManagementDrawer from "../SchemaManagementDrawer.svelte" import HierarchyRow from "../HierarchyRow.svelte" import ListItem from "./ListItem.svelte" @@ -28,22 +28,31 @@ backendUiStore.actions.models.select(model) } - function selectField() {} + function selectField(field) { + backendUiStore.update(state => { + state.selectedField = field + return state + }); + } + + function setupForNewModel() { + backendUiStore.update(state => { + state.selectedModel = {} + state.draftModel = { schema: {} } + return state + }) + $goto(`./database/${$backendUiStore.selectedDatabase._id}/newmodel`) + }
- {#if $backendUiStore.selectedDatabase._id} + {#if $backendUiStore.selectedDatabase && $backendUiStore.selectedDatabase._id}
{#if selectedTab === 'NAVIGATE'} - -
+ +
{#each $backendUiStore.models as model} selectField(model.schema[field])} /> + on:click={() => selectField({ name: field, ...model.schema[field] })} /> {/each} {/each}
diff --git a/packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte b/packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte new file mode 100644 index 0000000000..c6afe6c831 --- /dev/null +++ b/packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte @@ -0,0 +1,65 @@ + + +
+ + + + + + {#if type === 'string'} + + + {:else if type === 'datetime'} + + + {:else if type === 'number'} + + + {:else if type === 'link'} + + {/if} + + + + diff --git a/packages/builder/src/components/nav/ModelSetupNav.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte similarity index 50% rename from packages/builder/src/components/nav/ModelSetupNav.svelte rename to packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte index f72037d33e..67a83f934f 100644 --- a/packages/builder/src/components/nav/ModelSetupNav.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte @@ -2,14 +2,8 @@ import { getContext, onMount } from "svelte" import { Button, Switcher } from "@budibase/bbui" import { store, backendUiStore } from "builderStore" - import HierarchyRow from "./HierarchyRow.svelte" - import NavItem from "./NavItem.svelte" - import getIcon from "components/common/icon" import api from "builderStore/api" - import { - CreateEditModelModal, - CreateEditViewModal, - } from "components/database/ModelDataTable/modals" + import FieldView from "./FieldView.svelte" const { open, close } = getContext("simple-modal") @@ -29,18 +23,15 @@ ] let selectedTab = "SETUP" - let modelName = $backendUiStore.selectedModel.name - let edited - $: if (modelName) { - edited = modelName !== $backendUiStore.selectedModel.name - } + // TODO: draftModel undefined after save + $: edited = $backendUiStore.draftModel.name !== $backendUiStore.selectedModel.name async function deleteModel() { - const modelToDelete = $backendUiStore.selectedModel - const DELETE_MODEL_URL = `/api/${instanceId}/models/${modelToDelete._id}/${modelToDelete._rev}` - const response = await api.delete(DELETE_MODEL_URL) - backendUiStore.update(state => { + backendUiStore.update(async state => { + const modelToDelete = state.selectedModel + const DELETE_MODEL_URL = `/api/${state.selectedDatabase._id}/models/${modelToDelete._id}/${modelToDelete._rev}` + const response = await api.delete(DELETE_MODEL_URL) state.models = state.models.filter( model => model._id !== modelToDelete._id ) @@ -49,39 +40,35 @@ }) } - function selectView(view) { - backendUiStore.update(state => { - state.selectedView = view.name - return state - }) + async function saveModel() { + await backendUiStore.actions.models.save($backendUiStore.draftModel) }
{#if selectedTab === 'SETUP'} -
-
Name
- -
-
-
Import Data
- -
+ {#if $backendUiStore.selectedField} + + {:else} +
+
Name
+ +
+
+
Import Data
+ +
- + + {/if} {:else if selectedTab === 'DELETE'}
Danger Zone
- +
{/if}
diff --git a/packages/builder/src/components/nav/ModelSetupNav/index.js b/packages/builder/src/components/nav/ModelSetupNav/index.js new file mode 100644 index 0000000000..39fb8755d3 --- /dev/null +++ b/packages/builder/src/components/nav/ModelSetupNav/index.js @@ -0,0 +1 @@ +export { default as ModelSetupNav } from "./ModelSetupNav.svelte"; \ No newline at end of file diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index b49d97d262..ccf8a8d54c 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -4,93 +4,77 @@ export const FIELDS = { PLAIN_TEXT: { name: "Plain Text", icon: "ri-text", - definition: { + type: "string", + constraints: { type: "string", - constraints: { - type: "string", - length: {}, - presence: false, - }, + length: {}, + presence: false, }, }, NUMBER: { name: "Number", icon: "ri-number-1", - definition: { + type: "number", + constraints: { type: "number", - constraints: { - type: "number", - presence: false, - numericality: {}, - }, + presence: false, + numericality: {}, }, }, BOOLEAN: { name: "True/False", icon: "ri-toggle-line", - definition: { + type: "boolean", + constraints: { type: "boolean", - constraints: { - type: "boolean", - presence: false, - }, + presence: false, }, }, OPTIONS: { name: "Options", icon: "ri-list-check-2", - definition: { - type: "options", - constraints: { - type: "string", - presence: false, - }, + type: "options", + constraints: { + type: "string", + presence: false, }, }, DATETIME: { name: "Date/Time", icon: "ri-calendar-event-fill", - definition: { + type: "datetime", + constraints: { type: "date", - constraints: { - type: "date", - datetime: {}, - presence: false, - }, + datetime: {}, + presence: false, }, }, IMAGE: { name: "Image", icon: "ri-image-line", - definition: { - type: "image", - constraints: { - type: "string", - presence: false, - }, + type: "image", + constraints: { + type: "string", + presence: false, }, }, FILE: { name: "Image", icon: "ri-file-line", - definition: { - type: "file", - constraints: { - type: "string", - presence: false, - }, + type: "file", + constraints: { + type: "string", + presence: false, }, }, DATA_LINK: { name: "Data Links", icon: "ri-link", - definition: { - type: "link", - modelId: null, - constraints: { - type: "array", - }, - }, + type: "link", + modelId: null, + constraints: { + type: "array", + } }, } diff --git a/packages/builder/src/pages/[application]/backend/_layout.svelte b/packages/builder/src/pages/[application]/backend/_layout.svelte index 9d8cb5ef17..008cec7f28 100644 --- a/packages/builder/src/pages/[application]/backend/_layout.svelte +++ b/packages/builder/src/pages/[application]/backend/_layout.svelte @@ -4,7 +4,7 @@ import * as api from "components/database/ModelDataTable/api" import ModelNavigator from "components/nav/ModelNavigator/ModelNavigator.svelte" - import ModelSetupNav from "components/nav/ModelSetupNav.svelte" + import { ModelSetupNav } from "components/nav/ModelSetupNav"
diff --git a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/index.svelte b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/index.svelte index 3ebe117636..9d6e2c5685 100644 --- a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/index.svelte +++ b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/index.svelte @@ -22,13 +22,6 @@ let selectedRecord - async function selectRecord(record) { - selectedRecord = await api.loadRecord(record.key, { - appname: $store.appname, - instanceId: selectedDatabase, - }) - } - $: breadcrumbs = $backendUiStore.breadcrumbs.join(" / ") @@ -41,7 +34,7 @@ {/if}
{#if $backendUiStore.selectedDatabase._id && $backendUiStore.selectedModel.name} - + {:else} create your first model to start building diff --git a/packages/server/package.json b/packages/server/package.json index 49a5626f6f..b7f8dc128a 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -47,6 +47,7 @@ "@sendgrid/mail": "^7.1.1", "bcryptjs": "^2.4.3", "dotenv": "^8.2.0", + "electron": "^9.0.4", "electron-is-dev": "^1.2.0", "electron-unhandled": "^3.0.2", "electron-updater": "^4.3.1", @@ -73,7 +74,6 @@ }, "devDependencies": { "@jest/test-sequencer": "^24.8.0", - "electron": "^8.2.5", "electron-builder": "^22.6.0", "electron-builder-notarize": "^1.1.2", "eslint": "^6.8.0", diff --git a/packages/server/src/api/controllers/model.js b/packages/server/src/api/controllers/model.js index 650342b33c..effd179e9d 100644 --- a/packages/server/src/api/controllers/model.js +++ b/packages/server/src/api/controllers/model.js @@ -16,16 +16,16 @@ exports.find = async function(ctx) { ctx.body = model } -exports.create = async function(ctx) { +exports.save = async function(ctx) { const db = new CouchDB(ctx.params.instanceId) - const newModel = { + const modelToSave = { type: "model", - ...ctx.request.body, _id: newid(), + ...ctx.request.body, } - const result = await db.post(newModel) - newModel._rev = result.rev + const result = await db.post(modelToSave) + modelToSave._rev = result.rev const { schema } = ctx.request.body for (let key in schema) { @@ -33,9 +33,9 @@ exports.create = async function(ctx) { if (schema[key].type === "link") { // create the link field in the other model const linkedModel = await db.get(schema[key].modelId) - linkedModel.schema[newModel.name] = { + linkedModel.schema[modelToSave.name] = { type: "link", - modelId: newModel._id, + modelId: modelToSave._id, constraints: { type: "array", }, @@ -47,9 +47,9 @@ exports.create = async function(ctx) { const designDoc = await db.get("_design/database") designDoc.views = { ...designDoc.views, - [`all_${newModel._id}`]: { + [`all_${modelToSave._id}`]: { map: `function(doc) { - if (doc.modelId === "${newModel._id}") { + if (doc.modelId === "${modelToSave._id}") { emit(doc[doc.key], doc._id); } }`, @@ -58,12 +58,10 @@ exports.create = async function(ctx) { await db.put(designDoc) ctx.status = 200 - ctx.message = `Model ${ctx.request.body.name} created successfully.` - ctx.body = newModel + ctx.message = `Model ${ctx.request.body.name} saved successfully.` + ctx.body = modelToSave } -exports.update = async function() {} - exports.destroy = async function(ctx) { const db = new CouchDB(ctx.params.instanceId) diff --git a/packages/server/src/api/routes/model.js b/packages/server/src/api/routes/model.js index f1ec46dbe5..12a4315bc1 100644 --- a/packages/server/src/api/routes/model.js +++ b/packages/server/src/api/routes/model.js @@ -8,8 +8,7 @@ const router = Router() router .get("/api/:instanceId/models", authorized(BUILDER), modelController.fetch) .get("/api/:instanceId/models/:id", authorized(BUILDER), modelController.find) - .post("/api/:instanceId/models", authorized(BUILDER), modelController.create) - // .patch("/api/:instanceId/models", controller.update) + .post("/api/:instanceId/models", authorized(BUILDER), modelController.save) .delete( "/api/:instanceId/models/:modelId/:revId", authorized(BUILDER), diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index db51c0d834..bf15f722d2 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -194,6 +194,20 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" +"@budibase/client@^0.0.32": + version "0.0.32" + resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.0.32.tgz#76d9f147563a0bf939eae7f32ce75b2a527ba496" + integrity sha512-jmCCLn0CUoQbL6h623S5IqK6+GYLqX3WzUTZInSb1SCBOM3pI0eLP5HwTR6s7r42SfD0v9jTWRdyTnHiElNj8A== + dependencies: + "@nx-js/compiler-util" "^2.0.0" + bcryptjs "^2.4.3" + deep-equal "^2.0.1" + lodash "^4.17.15" + lunr "^2.3.5" + regexparam "^1.3.0" + shortid "^2.2.8" + svelte "^3.9.2" + "@budibase/core@^0.0.32": version "0.0.32" resolved "https://registry.yarnpkg.com/@budibase/core/-/core-0.0.32.tgz#c5d9ab869c5e9596a1ac337aaf041e795b1cc7fa" @@ -849,6 +863,11 @@ array-equal@^1.0.0: resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= +array-filter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-filter/-/array-filter-1.0.0.tgz#baf79e62e6ef4c2a4c0b831232daffec251f9d83" + integrity sha1-uveeYubvTCpMC4MSMtr/7CUfnYM= + array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -921,6 +940,13 @@ atomic-sleep@^1.0.0: resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== +available-typed-arrays@^1.0.0, available-typed-arrays@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz#6b098ca9d8039079ee3f77f7b783c4480ba513f5" + integrity sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ== + dependencies: + array-filter "^1.0.0" + aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -1643,6 +1669,26 @@ decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +deep-equal@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.0.3.tgz#cad1c15277ad78a5c01c49c2dee0f54de8a6a7b0" + integrity sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA== + dependencies: + es-abstract "^1.17.5" + es-get-iterator "^1.1.0" + is-arguments "^1.0.4" + is-date-object "^1.0.2" + is-regex "^1.0.5" + isarray "^2.0.5" + object-is "^1.1.2" + object-keys "^1.1.1" + object.assign "^4.1.0" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.2" + which-boxed-primitive "^1.0.1" + which-collection "^1.0.1" + which-typed-array "^1.1.2" + deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" @@ -1924,10 +1970,10 @@ electron-updater@^4.3.1: lodash.isequal "^4.5.0" semver "^7.1.3" -electron@^8.2.5: - version "8.2.5" - resolved "https://registry.yarnpkg.com/electron/-/electron-8.2.5.tgz#ae3cb23d5517b2189fd35298e487198d65d1a291" - integrity sha512-LxSCUwmlfJtRwthd3ofpYaZ+1C2hQSW8Ep1DD9K3VbnDItO+kb3t1z35daJgAab78j54aOwo9gMxJtvU0Ftj6w== +electron@^9.0.4: + version "9.0.4" + resolved "https://registry.yarnpkg.com/electron/-/electron-9.0.4.tgz#5aa72c1576c82c19f6e087311ffe1d7b74358d25" + integrity sha512-QzkeZNAiNB7KxcdoQKSoaiVT/GQdB4Vt0/ZZOuU8tIKABAsni2I7ztiAbUzxcsnQsqEBSfChuPuDQ5A4VbbzPg== dependencies: "@electron/get" "^1.0.1" "@types/node" "^12.0.12" @@ -2018,6 +2064,36 @@ es-abstract@^1.17.0-next.1, es-abstract@^1.17.2, es-abstract@^1.17.5: string.prototype.trimleft "^2.1.1" string.prototype.trimright "^2.1.1" +es-abstract@^1.17.4: + version "1.17.6" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" + integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.0" + is-regex "^1.1.0" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-get-iterator@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.0.tgz#bb98ad9d6d63b31aacdc8f89d5d0ee57bcb5b4c8" + integrity sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ== + dependencies: + es-abstract "^1.17.4" + has-symbols "^1.0.1" + is-arguments "^1.0.4" + is-map "^2.0.1" + is-set "^2.0.1" + is-string "^1.0.5" + isarray "^2.0.5" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -3010,11 +3086,21 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-bigint@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.0.tgz#73da8c33208d00f130e9b5e15d23eac9215601c4" + integrity sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g== + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -3022,6 +3108,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-boolean-object@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.1.tgz#10edc0900dd127697a92f6f9807c7617d68ac48e" + integrity sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ== + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -3032,6 +3123,11 @@ is-callable@^1.1.4, is-callable@^1.1.5: resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== +is-callable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" + integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -3058,7 +3154,7 @@ is-data-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-date-object@^1.0.1: +is-date-object@^1.0.1, is-date-object@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== @@ -3133,11 +3229,21 @@ is-installed-globally@^0.3.1: global-dirs "^2.0.1" is-path-inside "^3.0.1" +is-map@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.1.tgz#520dafc4307bb8ebc33b813de5ce7c9400d644a1" + integrity sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw== + is-npm@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== +is-number-object@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.4.tgz#36ac95e741cf18b283fc1ddf5e83da798e3ec197" + integrity sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw== + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -3174,11 +3280,28 @@ is-regex@^1.0.5: dependencies: has "^1.0.3" +is-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" + integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== + dependencies: + has-symbols "^1.0.1" + +is-set@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.1.tgz#d1604afdab1724986d30091575f54945da7e5f43" + integrity sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA== + is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-string@^1.0.4, is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + is-symbol@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -3195,11 +3318,31 @@ is-type-of@^1.0.0: is-class-hotfix "~0.0.6" isstream "~0.1.2" +is-typed-array@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.3.tgz#a4ff5a5e672e1a55f99c7f54e59597af5c1df04d" + integrity sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ== + dependencies: + available-typed-arrays "^1.0.0" + es-abstract "^1.17.4" + foreach "^2.0.5" + has-symbols "^1.0.1" + is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-weakmap@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" + integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== + +is-weakset@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.1.tgz#e9a0af88dbd751589f5e50d80f4c98b780884f83" + integrity sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw== + is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" @@ -3225,6 +3368,11 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + isbinaryfile@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-4.0.6.tgz#edcb62b224e2b4710830b67498c8e4e5a4d2610b" @@ -4637,6 +4785,14 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== +object-is@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6" + integrity sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.0.6, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -5358,6 +5514,19 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexp.prototype.flags@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + +regexparam@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexparam/-/regexparam-1.3.0.tgz#2fe42c93e32a40eff6235d635e0ffa344b92965f" + integrity sha512-6IQpFBv6e5vz1QAqI+V4k8P2e/3gRrqfCJ9FI+O1FLQTO+Uz6RXZEZOPmTJ6hlGj7gkERzY5BRCv09whKP96/g== + regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -5686,6 +5855,14 @@ shortid@^2.2.8: dependencies: nanoid "^2.1.0" +side-channel@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947" + integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA== + dependencies: + es-abstract "^1.17.0-next.1" + object-inspect "^1.7.0" + signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" @@ -5938,7 +6115,7 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" -string.prototype.trimend@^1.0.0: +string.prototype.trimend@^1.0.0, string.prototype.trimend@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== @@ -5964,7 +6141,7 @@ string.prototype.trimright@^2.1.1: es-abstract "^1.17.5" string.prototype.trimend "^1.0.0" -string.prototype.trimstart@^1.0.0: +string.prototype.trimstart@^1.0.0, string.prototype.trimstart@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== @@ -6094,6 +6271,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +svelte@^3.9.2: + version "3.23.2" + resolved "https://registry.yarnpkg.com/svelte/-/svelte-3.23.2.tgz#f3e500384261a2e77b29681ee744c3c790fbcdc3" + integrity sha512-hE8GeTM83YVR4GY6/6PeDEcGct4JS5aCi+IYbCAa76oaPSfuF7L85DQYULQxlTK/KPWzw3L1GRGmC3oPG/PQoA== + symbol-tree@^3.2.2: version "3.2.4" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" @@ -6579,11 +6761,44 @@ whatwg-url@^7.0.0: tr46 "^1.0.1" webidl-conversions "^4.0.2" +which-boxed-primitive@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz#cbe8f838ebe91ba2471bb69e9edbda67ab5a5ec1" + integrity sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ== + dependencies: + is-bigint "^1.0.0" + is-boolean-object "^1.0.0" + is-number-object "^1.0.3" + is-string "^1.0.4" + is-symbol "^1.0.2" + +which-collection@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" + integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + dependencies: + is-map "^2.0.1" + is-set "^2.0.1" + is-weakmap "^2.0.1" + is-weakset "^2.0.1" + which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= +which-typed-array@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2" + integrity sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ== + dependencies: + available-typed-arrays "^1.0.2" + es-abstract "^1.17.5" + foreach "^2.0.5" + function-bind "^1.1.1" + has-symbols "^1.0.1" + is-typed-array "^1.1.3" + which@^1.2.9, which@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" From 374a6b4bc6cea4751a8a01dd11bf7ca123979ff2 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 16 Jun 2020 20:53:13 +0100 Subject: [PATCH 03/20] new model creation, requires styling and CSS updates --- .../builder/src/builderStore/store/backend.js | 54 +++++++++++-------- .../nav/ModelSetupNav/FieldView.svelte | 9 ++-- .../nav/ModelSetupNav/ModelSetupNav.svelte | 15 ++++-- 3 files changed, 47 insertions(+), 31 deletions(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index cc3d78e263..32533f9420 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -1,4 +1,5 @@ import { writable } from "svelte/store" +import { cloneDeep } from "lodash/fp"; import api from "../api" export const getBackendUiStore = () => { @@ -56,38 +57,47 @@ export const getBackendUiStore = () => { select: model => store.update(state => { state.selectedModel = model; // TODO: prevent pointing to same obj - state.draftModel = model; + state.draftModel = cloneDeep(model); state.selectedField = null - return state + return state; }), - save: model => - store.update(async state => { - const SAVE_MODEL_URL = `/api/${state.selectedDatabase._id}/models` - const response = await api.post(SAVE_MODEL_URL, model) - const savedModel = await response.json() + save: async ({ instanceId, model }) => { + const SAVE_MODEL_URL = `/api/${instanceId}/models` + const response = await api.post(SAVE_MODEL_URL, model) + const savedModel = await response.json() + + store.update(state => { + // New model + if (!model._id) { + state.models = [...state.models, savedModel] + } else { + const existingIdx = state.models.findIndex(({ _id }) => _id === model._id); + state.models.splice(existingIdx, 1, savedModel); + state.models = state.models + } - state.models = [...state.models, savedModel] state.selectedModel = savedModel state.draftModel = savedModel state.selectedView = `all_${savedModel._id}` return state - }), - addField: field => { - store.update(state => { - if (!state.draftModel.schema) { - state.draftModel.schema = {} - } + }) + }, + addField: field => { + store.update(state => { + if (!state.draftModel.schema) { + state.draftModel.schema = {} + } - state.draftModel.schema = { - ...state.draftModel.schema, - [field.name]: field - } + state.draftModel.schema = { + ...state.draftModel.schema, + [field.name]: field + } - state.selectedField = field + state.selectedField = field - return state - }); - } + return state + }); + } }, views: { select: view => diff --git a/packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte b/packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte index c6afe6c831..fbb2004694 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte @@ -21,12 +21,11 @@ $: required = constraints && constraints.presence && !constraints.presence.allowEmpty - $: console.log(field) - const save = () => { - // constraints.presence = required ? { allowEmpty: false } : false - // draft[field.name] = { type, constraints } - backendUiStore.actions.models.save($backendUiStore.draftModel) + backendUiStore.actions.models.save({ + instanceId: $backendUiStore.selectedDatabase._id, + model: $backendUiStore.draftModel + }) } diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte index 67a83f934f..81ed678edd 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte @@ -3,7 +3,7 @@ import { Button, Switcher } from "@budibase/bbui" import { store, backendUiStore } from "builderStore" import api from "builderStore/api" - import FieldView from "./FieldView.svelte" + import FieldView from "./FieldView.svelte"; const { open, close } = getContext("simple-modal") @@ -24,7 +24,6 @@ let selectedTab = "SETUP" - // TODO: draftModel undefined after save $: edited = $backendUiStore.draftModel.name !== $backendUiStore.selectedModel.name async function deleteModel() { @@ -41,7 +40,10 @@ } async function saveModel() { - await backendUiStore.actions.models.save($backendUiStore.draftModel) + await backendUiStore.actions.models.save({ + instanceId: $backendUiStore.selectedDatabase._id, + model: $backendUiStore.draftModel + }) } @@ -63,7 +65,12 @@
- + {/if} {:else if selectedTab === 'DELETE'}
From 5f8d6bbfe4868b621b968aae9370eff524e96e8d Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 17 Jun 2020 16:51:10 +0100 Subject: [PATCH 04/20] add new models and fields, delete models --- packages/builder/src/budibase.css | 3 +- .../builder/src/builderStore/store/backend.js | 29 +++-- .../common/LinkedRecordSelector.svelte | 68 ++++++++++++ .../ModelDataTable/ModelDataTable.svelte | 4 +- .../modals/CreateEditRecord.svelte | 15 ++- .../nav/ModelNavigator/ListItem.svelte | 4 +- .../nav/ModelNavigator/ModelNavigator.svelte | 12 +-- .../nav/ModelSetupNav/FieldView.svelte | 29 +++-- .../nav/ModelSetupNav/ModelSetupNav.svelte | 24 +++-- .../builder/src/constants/backend/index.js | 101 +++++++++++++++++- packages/builder/src/global.css | 1 - .../database/[selectedDatabase]/Block.svelte | 9 +- .../database/[selectedDatabase]/index.svelte | 5 +- .../[selectedDatabase]/newmodel.svelte | 51 +++++++-- 14 files changed, 295 insertions(+), 60 deletions(-) create mode 100644 packages/builder/src/components/common/LinkedRecordSelector.svelte diff --git a/packages/builder/src/budibase.css b/packages/builder/src/budibase.css index 3d880cbfa2..14a1be3083 100644 --- a/packages/builder/src/budibase.css +++ b/packages/builder/src/budibase.css @@ -77,7 +77,8 @@ .budibase__input { height: 35px; - width: 220px; + width: 100%; + max-width: 220px; border-radius: 3px; border: 1px solid var(--grey-dark); text-align: left; diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 32533f9420..2dff9db7d2 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -25,9 +25,7 @@ export const getBackendUiStore = () => { store.update(state => { state.selectedDatabase = db if (models && models.length > 0) { - state.selectedModel = models[0] - state.draftModel = models[0] - state.selectedView = `all_${models[0]._id}` + store.actions.models.select(models[0]); } state.breadcrumbs = [db.name] state.models = models @@ -56,14 +54,25 @@ export const getBackendUiStore = () => { models: { select: model => store.update(state => { state.selectedModel = model; - // TODO: prevent pointing to same obj state.draftModel = cloneDeep(model); - state.selectedField = null + state.selectedField = "" + state.selectedView = `all_${model._id}` return state; }), save: async ({ instanceId, model }) => { + const updatedModel = cloneDeep(model); + + // TODO: refactor + for (let key in updatedModel.schema) { + const field = updatedModel.schema[key] + if (field.name && field.name !== key) { + updatedModel.schema[field.name] = field + delete updatedModel.schema[key]; + } + } + const SAVE_MODEL_URL = `/api/${instanceId}/models` - const response = await api.post(SAVE_MODEL_URL, model) + const response = await api.post(SAVE_MODEL_URL, updatedModel) const savedModel = await response.json() store.update(state => { @@ -76,9 +85,7 @@ export const getBackendUiStore = () => { state.models = state.models } - state.selectedModel = savedModel - state.draftModel = savedModel - state.selectedView = `all_${savedModel._id}` + store.actions.models.select(savedModel) return state }) }, @@ -93,11 +100,11 @@ export const getBackendUiStore = () => { [field.name]: field } - state.selectedField = field + state.selectedField = field.name return state }); - } + }, }, views: { select: view => diff --git a/packages/builder/src/components/common/LinkedRecordSelector.svelte b/packages/builder/src/components/common/LinkedRecordSelector.svelte new file mode 100644 index 0000000000..18adfda61e --- /dev/null +++ b/packages/builder/src/components/common/LinkedRecordSelector.svelte @@ -0,0 +1,68 @@ + + +
+ {#each records as record} +
+

{record.name}

+
+ {#each Object.keys(record) as key} +
+ {key} +

{record[key]}

+
+ {/each} +
+
+ {/each} +
+ + \ No newline at end of file diff --git a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte index f1d49894a0..ec2d228978 100644 --- a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte +++ b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte @@ -68,10 +68,10 @@ } } - $: paginatedData = data.slice( + $: paginatedData = data ? data.slice( currentPage * ITEMS_PER_PAGE, currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE - ) + ) : [] onMount(() => { if (views.length) { diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte index 62688d58e3..abcc32b002 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte @@ -3,6 +3,7 @@ import { store, backendUiStore } from "builderStore" import { compose, map, get, flatten } from "lodash/fp" import ActionButton from "components/common/ActionButton.svelte" + import LinkedRecordSelector from "components/common/LinkedRecordSelector.svelte" import Select from "components/common/Select.svelte" import RecordFieldControl from "./RecordFieldControl.svelte" import * as api from "../api" @@ -73,11 +74,15 @@
{#each modelSchema as [key, meta]}
- + {#if meta.type === "link"} + + {:else} + + {/if}
{/each}
diff --git a/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte b/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte index 6452b3459d..d34f761834 100644 --- a/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte @@ -13,7 +13,7 @@ \ No newline at end of file From 7c4f24c1b4177cfd533086c552bdc9277daddf9d Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 18 Jun 2020 17:17:18 +0100 Subject: [PATCH 05/20] backend v1 - styling to do --- packages/builder/package.json | 2 +- packages/builder/src/budibase.css | 1 - .../builder/src/builderStore/store/backend.js | 16 +- .../common}/Block.svelte | 9 +- .../src/components/common/Checkbox.svelte | 2 +- .../src/components/common/NumberBox.svelte | 30 +- .../src/components/common/ValuesList.svelte | 2 +- .../ModelDataTable/ModelDataTable.svelte | 39 +- .../CreateEditModel/CreateEditModel.svelte | 156 ----- .../modals/CreateEditModel/FieldView.svelte | 104 --- .../modals/CreateEditRecord.svelte | 2 + .../database/ModelDataTable/modals/index.js | 1 - .../src/components/nav/BackendNav.svelte | 87 --- .../src/components/nav/HierarchyRow.svelte | 1 - .../nav/ModelNavigator/Block.svelte | 47 -- .../nav/ModelNavigator/BlockNavigator.svelte | 15 +- .../nav/ModelNavigator/EmptyModel.svelte} | 18 +- .../nav/ModelNavigator/ListItem.svelte | 4 +- .../nav/ModelNavigator/ModelNavigator.svelte | 43 +- .../nav/ModelSetupNav/FieldView.svelte | 63 -- .../nav/ModelSetupNav/ModelFieldEditor.svelte | 101 +++ .../nav/ModelSetupNav/ModelSetupNav.svelte | 57 +- .../nav/SchemaManagementDrawer.svelte | 143 ---- .../builder/src/constants/backend/index.js | 4 +- packages/builder/src/flowy.css | 647 ------------------ .../[selectedDatabase]/_layout.svelte | 1 + .../database/[selectedDatabase]/index.svelte | 31 +- 27 files changed, 251 insertions(+), 1375 deletions(-) rename packages/builder/src/{pages/[application]/backend/database/[selectedDatabase] => components/common}/Block.svelte (88%) delete mode 100644 packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/CreateEditModel.svelte delete mode 100644 packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/FieldView.svelte delete mode 100644 packages/builder/src/components/nav/BackendNav.svelte delete mode 100644 packages/builder/src/components/nav/ModelNavigator/Block.svelte rename packages/builder/src/{pages/[application]/backend/database/[selectedDatabase]/newmodel.svelte => components/nav/ModelNavigator/EmptyModel.svelte} (71%) delete mode 100644 packages/builder/src/components/nav/ModelSetupNav/FieldView.svelte create mode 100644 packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte delete mode 100644 packages/builder/src/components/nav/SchemaManagementDrawer.svelte delete mode 100644 packages/builder/src/flowy.css create mode 100644 packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/_layout.svelte diff --git a/packages/builder/package.json b/packages/builder/package.json index b2de1252b3..0a7cadc481 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -39,7 +39,7 @@ }, "dependencies": { "@beyonk/svelte-notifications": "^2.0.3", - "@budibase/bbui": "^1.4.1", + "@budibase/bbui": "^1.5.0", "@budibase/client": "^0.0.32", "@nx-js/compiler-util": "^2.0.0", "codemirror": "^5.51.0", diff --git a/packages/builder/src/budibase.css b/packages/builder/src/budibase.css index 14a1be3083..85425ba049 100644 --- a/packages/builder/src/budibase.css +++ b/packages/builder/src/budibase.css @@ -84,7 +84,6 @@ text-align: left; color: var(--ink); font-size: 14px; - padding-left: 12px; } .uk-text-right { diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 2dff9db7d2..16fd12ada4 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -4,13 +4,16 @@ import api from "../api" export const getBackendUiStore = () => { const INITIAL_BACKEND_UI_STATE = { - breadcrumbs: [], models: [], views: [], users: [], selectedDatabase: {}, selectedModel: {}, - draftModel: {} + draftModel: {}, + tabs: { + SETUP_PANEL: "SETUP", + NAVIGATION_PANEL: "NAVIGATE" + } } const store = writable(INITIAL_BACKEND_UI_STATE) @@ -27,7 +30,6 @@ export const getBackendUiStore = () => { if (models && models.length > 0) { store.actions.models.select(models[0]); } - state.breadcrumbs = [db.name] state.models = models state.views = views return state @@ -40,11 +42,6 @@ export const getBackendUiStore = () => { state.selectedView = state.selectedView return state }), - view: record => - store.update(state => { - state.breadcrumbs = [state.selectedDatabase.name, record._id] - return state - }), select: record => store.update(state => { state.selectedRecord = record @@ -57,6 +54,7 @@ export const getBackendUiStore = () => { state.draftModel = cloneDeep(model); state.selectedField = "" state.selectedView = `all_${model._id}` + state.tabs.SETUP_PANEL = "SETUP" return state; }), save: async ({ instanceId, model }) => { @@ -102,6 +100,8 @@ export const getBackendUiStore = () => { state.selectedField = field.name + state.tabs.NAVIGATION_PANEL = "NAVIGATE" + return state }); }, diff --git a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/Block.svelte b/packages/builder/src/components/common/Block.svelte similarity index 88% rename from packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/Block.svelte rename to packages/builder/src/components/common/Block.svelte index 23dc183a27..168834b5a8 100644 --- a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/Block.svelte +++ b/packages/builder/src/components/common/Block.svelte @@ -7,7 +7,6 @@ export let tertiary -
{title} @@ -15,8 +14,7 @@ diff --git a/packages/builder/src/components/common/Checkbox.svelte b/packages/builder/src/components/common/Checkbox.svelte index 9f777ca704..37eb385d79 100644 --- a/packages/builder/src/components/common/Checkbox.svelte +++ b/packages/builder/src/components/common/Checkbox.svelte @@ -3,8 +3,8 @@ export let label = "" - {label} + diff --git a/packages/builder/src/components/common/ValuesList.svelte b/packages/builder/src/components/common/ValuesList.svelte index 1d1e5ce33c..53a16455cc 100644 --- a/packages/builder/src/components/common/ValuesList.svelte +++ b/packages/builder/src/components/common/ValuesList.svelte @@ -24,7 +24,7 @@ diff --git a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte index ec2d228978..2f02db9a6d 100644 --- a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte +++ b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte @@ -1,18 +1,7 @@ - -
- {#if !showFieldView} - -

Create / Edit Model

- {:else} - -

Create / Edit Field

- {/if} -
-{#if !showFieldView} -
- {#if $store.errors && $store.errors.length > 0} - - {/if} -
- -
-
- Fields -
(showFieldView = true)}> - Add new field -
-
- - - - - - - - - - - {#each modelFields as [key, meta]} - - - - - - - {/each} - -
EditNameType -
- editField(meta)} /> - -
{key}
-
{meta.type} - deleteField(meta)} /> -
-
- Save -
-
-{:else} - (showFieldView = false)} /> -{/if} - - diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/FieldView.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/FieldView.svelte deleted file mode 100644 index fde876015d..0000000000 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditModel/FieldView.svelte +++ /dev/null @@ -1,104 +0,0 @@ - - -
- - - -
- - - - - - {#if type === 'string'} - - - {:else if type === 'datetime'} - - - {:else if type === 'number'} - - - {/if} - -
-
-
- Cancel -
- Save -
- - diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte index abcc32b002..7c31ea3bf3 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte @@ -1,6 +1,7 @@ - -
-
- {#if $backendUiStore.selectedDatabase._id} -
-
- -
- -
- -
- -
- {/if} -
- - diff --git a/packages/builder/src/components/nav/HierarchyRow.svelte b/packages/builder/src/components/nav/HierarchyRow.svelte index d57463cc20..22bff89b80 100644 --- a/packages/builder/src/components/nav/HierarchyRow.svelte +++ b/packages/builder/src/components/nav/HierarchyRow.svelte @@ -4,7 +4,6 @@ import { cloneDeep } from "lodash/fp" import getIcon from "../common/icon" import { - CreateEditModelModal, CreateEditViewModal, } from "components/database/ModelDataTable/modals" import api from "builderStore/api" diff --git a/packages/builder/src/components/nav/ModelNavigator/Block.svelte b/packages/builder/src/components/nav/ModelNavigator/Block.svelte deleted file mode 100644 index c9e7f67623..0000000000 --- a/packages/builder/src/components/nav/ModelNavigator/Block.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - -
- - {title} -
- - diff --git a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte index 5fa886c363..7ca8d56372 100644 --- a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte @@ -1,7 +1,7 @@ -
+
-

Create New Table

-

Before you can view your table, you need to set it up.

+

Create New Model

+

Before you can view your model, you need to set it up.

Fields -

Blocks are pre-made fields and help you build your table quicker.

+

Blocks are pre-made fields and help you build your model quicker.

{#each Object.values(FIELDS) as field} addNewField(field)} /> @@ -26,17 +27,17 @@
Blocks -

Blocks are pre-made fields and help you build your table quicker.

+

Blocks are pre-made fields and help you build your model quicker.

{#each Object.values(BLOCKS) as field} - + addNewField(field)} /> {/each}
Models -

Blocks are pre-made fields and help you build your table quicker.

+

Blocks are pre-made fields and help you build your model quicker.

{#each Object.values(MODELS) as model} @@ -74,6 +75,7 @@ .block-row .blocks { display: grid; grid-auto-flow: column; + grid-auto-columns: 110px; grid-gap: 20px; } \ No newline at end of file diff --git a/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte b/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte index d34f761834..ae1b46a90d 100644 --- a/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/ListItem.svelte @@ -18,7 +18,7 @@ div { padding: 0 10px 0 10px; - width: 260px; + width: 90%; height: 40px; border-radius: 3px; display: flex; @@ -27,6 +27,8 @@ color: var(--ink); font-weight: 500; font-size: 16px; + margin-top: 4px; + margin-bottom: 4px; } .selected { diff --git a/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte index ebe7372444..b0b0d9ca24 100644 --- a/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte @@ -1,11 +1,10 @@ - -
- - - - - - {#if field.type === 'string'} - - - {:else if field.type === 'datetime'} - - - {:else if field.type === 'number'} - - - {:else if field.type === 'link'} - - {/if} - - - - diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte new file mode 100644 index 0000000000..6e72fdb2fa --- /dev/null +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte @@ -0,0 +1,101 @@ + + +
+
+
Name
+ +
+
+ +
+
+
Type
+ {field.type} +
+
+ +
+
+ + +
+ + {#if field.type === 'string'} + + + {:else if field.type === 'datetime'} + + + {:else if field.type === 'number'} + + + {:else if field.type === 'link'} + + {/if} +
+ + diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte index 847c2c5a23..d82389ec66 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte @@ -4,7 +4,7 @@ import { notifier } from "@beyonk/svelte-notifications" import { store, backendUiStore } from "builderStore" import api from "builderStore/api" - import FieldView from "./FieldView.svelte"; + import ModelFieldEditor from "./ModelFieldEditor.svelte" const { open, close } = getContext("simple-modal") @@ -13,52 +13,57 @@ title: "Setup", key: "SETUP", }, - { - title: "Filter", - key: "FILTER", - }, { title: "Delete", key: "DELETE", }, ] - let selectedTab = "SETUP" + $: selectedTab = $backendUiStore.tabs.SETUP_PANEL - $: edited = $backendUiStore.draftModel.name !== $backendUiStore.selectedModel.name + $: edited = + $backendUiStore.draftModel.name !== $backendUiStore.selectedModel.name async function deleteModel() { - const modelToDelete = $backendUiStore.selectedModel - if ($backendUiStore.selectedField) { - delete modelToDelete[$backendUiStore.selectedField] + const model = $backendUiStore.selectedModel + const instanceId = $backendUiStore.selectedDatabase._id + const field = $backendUiStore.selectedField + + if (field) { + delete model.schema[field] + backendUiStore.actions.models.save({ model, instanceId }); + notifier.danger(`Field ${field} deleted.`); + return; } - const DELETE_MODEL_URL = `/api/${$backendUiStore.selectedDatabase._id}/models/${modelToDelete._id}/${modelToDelete._rev}` + const DELETE_MODEL_URL = `/api/${instanceId}/models/${model._id}/${model._rev}` const response = await api.delete(DELETE_MODEL_URL) backendUiStore.update(state => { state.selectedView = null state.models = state.models.filter( - model => model._id !== modelToDelete._id + ({ _id }) => _id !== model._id ) - notifier.danger(`${modelToDelete.name} deleted successfully.`) + notifier.danger(`${model.name} deleted successfully.`) return state }) } async function saveModel() { - await backendUiStore.actions.models.save({ + await backendUiStore.actions.models.save({ instanceId: $backendUiStore.selectedDatabase._id, - model: $backendUiStore.draftModel + model: $backendUiStore.draftModel, }) - notifier.success("Success! Your changes have been saved. Please continue on with your greatness."); + notifier.success( + "Success! Your changes have been saved. Please continue on with your greatness." + ) }
- + {#if selectedTab === 'SETUP'} {#if $backendUiStore.selectedField} - + {:else}
Name
@@ -71,13 +76,10 @@
Import Data
- {/if} +
+ +
{:else if selectedTab === 'DELETE'}
Danger Zone
@@ -92,6 +94,10 @@ font-weight: 500; } + footer { + width: 100%; + } + .items-root { padding: 20px; display: flex; @@ -102,9 +108,8 @@ } .titled-input { - padding: 20px; + padding: 12px; background: var(--light-grey); - margin-top: 20px; } .titled-input header { diff --git a/packages/builder/src/components/nav/SchemaManagementDrawer.svelte b/packages/builder/src/components/nav/SchemaManagementDrawer.svelte deleted file mode 100644 index cc9e5d86a7..0000000000 --- a/packages/builder/src/components/nav/SchemaManagementDrawer.svelte +++ /dev/null @@ -1,143 +0,0 @@ - - -
-
-
- -
- -
- {#each $backendUiStore.models as model} - - {/each} -
-
- -
-
- -
- -
- {#each $backendUiStore.views as view} - - {/each} -
-
-
- - diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 00057a5acd..3973b09238 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -50,9 +50,9 @@ export const FIELDS = { }, }, IMAGE: { - name: "Image", + name: "File", icon: "ri-image-line", - type: "image", + type: "file", constraints: { type: "string", presence: false, diff --git a/packages/builder/src/flowy.css b/packages/builder/src/flowy.css deleted file mode 100644 index 1fc6d12b3e..0000000000 --- a/packages/builder/src/flowy.css +++ /dev/null @@ -1,647 +0,0 @@ -body, html { - margin: 0px; - padding: 0px; - overflow: hidden; - background-repeat: repeat; - background-size: 30px 30px; - background-color: #FBFBFB; - height: 100%; -} -#navigation { - height: 71px; - background-color: #FFF; - border: 1px solid #E8E8EF; - width: 100%; - display: table; - box-sizing: border-box; - position: fixed; - top: 0; - z-index: 9 -} -#back { - width: 40px; - height: 40px; - border-radius: 100px; - background-color: #F1F4FC; - text-align: center; - display: inline-block; - vertical-align: top; - margin-top: 12px; - margin-right: 10px -} -#back img { - margin-top: 13px; -} -#names { - display: inline-block; - vertical-align: top; -} -#title { - font-family: Roboto; - font-weight: 500; - font-size: 16px; - color: #393C44; - margin-bottom: 0px; -} -#subtitle { - font-family: Roboto; - color: #808292; - font-size: 14px; - margin-top: 5px; -} -#leftside { - display: inline-block; - vertical-align: middle; - margin-left: 20px; -} -#centerswitch { - position: absolute; - width: 222px; - left: 50%; - margin-left: -111px; - top: 15px; -} -#leftswitch { - border: 1px solid #E8E8EF; - background-color: #FBFBFB; - width: 111px; - height: 39px; - line-height: 39px; - border-radius: 5px 0px 0px 5px; - font-family: Roboto; - color: #393C44; - display: inline-block; - font-size: 14px; - text-align: center; -} -#rightswitch { - font-family: Roboto; - color: #808292; - border-radius: 0px 5px 5px 0px; - border: 1px solid #E8E8EF; - height: 39px; - width: 102px; - display: inline-block; - font-size: 14px; - line-height: 39px; - text-align: center; - margin-left: -5px; -} -#discard { - font-family: Roboto; - font-weight: 500; - font-size: 14px; - color: #A6A6B3; - width: 95px; - height: 38px; - border: 1px solid #E8E8EF; - border-radius: 5px; - text-align: center; - line-height: 38px; - display: inline-block; - vertical-align: top; - transition: all .2s cubic-bezier(.05,.03,.35,1); -} -#discard:hover { - cursor: pointer; - opacity: .7; -} -#publish { - font-family: Roboto; - font-weight: 500; - font-size: 14px; - color: #FFF; - background-color: #217CE8; - border-radius: 5px; - width: 143px; - height: 38px; - margin-left: 10px; - display: inline-block; - vertical-align: top; - text-align: center; - line-height: 38px; - margin-right: 20px; - transition: all .2s cubic-bezier(.05,.03,.35,1); -} -#publish:hover { - cursor: pointer; - opacity: .7; -} -#buttonsright { - float: right; - margin-top: 15px; -} -#leftcard { - width: 363px; - background-color: #FFF; - border: 1px solid #E8E8EF; - box-sizing: border-box; - padding-top: 85px; - padding-left: 20px; - height: 100%; - position: absolute; - z-index: 2; -} -#search input { - width: 318px; - height: 40px; - background-color: #FFF; - border: 1px solid #E8E8EF; - box-sizing: border-box; - box-shadow: 0px 2px 8px rgba(34,34,87,0.05); - border-radius: 5px; - text-indent: 35px; - font-family: Roboto; - font-size: 16px; -} -::-webkit-input-placeholder { /* Edge */ - color: #C9C9D5; -} - -:-ms-input-placeholder { /* Internet Explorer 10-11 */ - color: #C9C9D5 -} - -::placeholder { - color: #C9C9D5; -} -#search img { - position: absolute; - margin-top: 10px; - width: 18px; - margin-left: 12px; -} -#header { - font-size: 20px; - font-family: Roboto; - font-weight: bold; - color: #393C44; -} -#subnav { - border-bottom: 1px solid #E8E8EF; - width: calc(100% + 20px); - margin-left: -20px; - margin-top: 10px; -} -.navdisabled { - transition: all .3s cubic-bezier(.05,.03,.35,1); -} -.navdisabled:hover { - cursor: pointer; - opacity: .5; -} -.navactive { - color: #393C44!important; -} -#triggers { - margin-left: 20px; - font-family: Roboto; - font-weight: 500; - font-size: 14px; - text-align: center; - color: #808292; - width: calc(88% / 3); - height: 48px; - line-height: 48px; - display: inline-block; - float: left; -} -.navactive:after { - display: block; - content: ""; - width: 100%; - height: 4px; - background-color: #217CE8; - margin-top: -4px; -} -#actions { - display: inline-block; - font-family: Roboto; - font-weight: 500; - color: #808292; - font-size: 14px; - height: 48px; - line-height: 48px; - width: calc(88% / 3); - text-align: center; - float: left; -} -#loggers { - width: calc(88% / 3); - display: inline-block; - font-family: Roboto; - font-weight: 500; - color: #808292; - font-size: 14px; - height: 48px; - line-height: 48px; - text-align: center; -} -#footer { - position: absolute; - left: 0; - padding-left: 20px; - line-height: 40px; - bottom: 0; - width: 362px; - border: 1px solid #E8E8EF; - height: 67px; - box-sizing: border-box; - background-color: #FFF; - font-family: Roboto; - font-size: 14px; -} -#footer a { - text-decoration: none; - color: #393C44; - transition: all .2s cubic-bezier(.05,.03,.35,1); -} -#footer a:hover { - opacity: .5; -} -#footer span { - color: #808292; -} -#footer p { - display: inline-block; - color: #808292; -} -#footer img { - margin-left: 5px; - margin-right: 5px; -} -.blockelem:first-child { - margin-top: 20px -} -.blockelem { - padding-top: 10px; - width: 318px; - border: 1px solid transparent; - transition-property: box-shadow, height; - transition-duration: .2s; - transition-timing-function: cubic-bezier(.05,.03,.35,1); - border-radius: 5px; - box-shadow: 0px 0px 30px rgba(22, 33, 74, 0); - box-sizing: border-box; -} -.blockelem:hover { - box-shadow: 0px 4px 30px rgba(22, 33, 74, 0.08); - border-radius: 5px; - background-color: #FFF; - cursor: pointer; -} -.grabme, .blockico { - display: inline-block; -} - -.grabme { - margin-top: 10px; - margin-left: 10px; - margin-bottom: -14px; - width: 15px; -} -#blocklist { - height: calc(100% - 220px); - overflow: auto; -} -#proplist { - height: calc(100% - 305px); - overflow: auto; - margin-top: -30px; - padding-top: 30px; -} -.blockin { - display: inline-block; - vertical-align: top; - margin-left: 12px; -} -.blockico { - width: 36px; - height: 36px; - background-color: #F1F4FC; - border-radius: 5px; - text-align: center; - white-space: nowrap; -} - -.blockico i { - font-size: 24px; - color: var(--dark-grey); -} - -.blockico span { - height: 100%; - width: 0px; - display: inline-block; - vertical-align: middle; -} -.blockico img { - vertical-align: middle; - margin-left: auto; - margin-right: auto; - display: inline-block; -} -.blocktext { - display: inline-block; - width: 220px; - vertical-align: top; - margin-left: 12px -} -.blocktitle { - margin: 0px!important; - padding: 0px!important; - font-family: Roboto; - font-weight: 500; - font-size: 16px; - color: #393C44; -} -.blockdesc { - margin-top: 5px; - font-family: Roboto; - color: #808292; - font-size: 14px; - line-height: 21px; -} -.blockdisabled { - background-color: #F0F2F9; - opacity: .5; -} -#closecard { - position: absolute; - margin-left: 340px; - background-color: #FFF; - border-radius: 0px 5px 5px 0px; - border-bottom: 1px solid #E8E8EF; - border-right: 1px solid #E8E8EF; - border-top: 1px solid #E8E8EF; - width: 53px; - height: 53px; - text-align: center; - z-index: 10; -} -#closecard img { - margin-top: 15px -} -#canvas { - border: 1px solid green; - position: absolute; - width: calc(100% - 361px); - height: calc(100% - 71px); - top: 71px; - left: 361px; - z-index: 0; - overflow: auto; -} -#propwrap { - position: absolute; - right: 0; - top: 0; - width: 311px; - height: 100%; - padding-left: 20px; - overflow: hidden; - z-index: -2; -} -#properties { - position: absolute; - height: 100%; - width: 311px; - background-color: #FFF; - right: -150px; - opacity: 0; - z-index: 2; - top: 0px; - box-shadow: -4px 0px 40px rgba(26, 26, 73, 0); - padding-left: 20px; - transition: all .25s cubic-bezier(.05,.03,.35,1); -} -.itson { - z-index: 2!important; -} -.expanded { - right: 0!important; - opacity: 1!important; - box-shadow: -4px 0px 40px rgba(26, 26, 73, 0.05); - z-index: 2; -} -#header2 { - font-size: 20px; - font-family: Roboto; - font-weight: bold; - color: #393C44; - margin-top: 101px; -} -#close { - margin-top: 100px; - position: absolute; - right: 20px; - z-index: 9999; - transition: all .25s cubic-bezier(.05,.03,.35,1); -} -#close:hover { - cursor: pointer; - opacity: .7; -} -#propswitch { - border-bottom: 1px solid #E8E8EF; - width: 331px; - margin-top: 10px; - margin-left: -20px; - margin-bottom: 30px; -} -#dataprop { - font-family: Roboto; - font-weight: 500; - font-size: 14px; - text-align: center; - color: #393C44; - width: calc(88% / 3); - height: 48px; - line-height: 48px; - display: inline-block; - float: left; - margin-left: 20px; -} -#dataprop:after { - display: block; - content: ""; - width: 100%; - height: 4px; - background-color: #217CE8; - margin-top: -4px; -} -#alertprop { - display: inline-block; - font-family: Roboto; - font-weight: 500; - color: #808292; - font-size: 14px; - height: 48px; - line-height: 48px; - width: calc(88% / 3); - text-align: center; - float: left; -} -#logsprop { - width: calc(88% / 3); - display: inline-block; - font-family: Roboto; - font-weight: 500; - color: #808292; - font-size: 14px; - height: 48px; - line-height: 48px; - text-align: center; -} -.inputlabel { - font-family: Roboto; - font-size: 14px; - color: #253134; -} -.dropme { - background-color: #FFF; - border-radius: 5px; - border: 1px solid #E8E8EF; - box-shadow: 0px 2px 8px rgba(34, 34, 87, 0.05); - font-family: Roboto; - font-size: 14px; - color: #253134; - text-indent: 20px; - height: 40px; - line-height: 40px; - width: 287px; - margin-bottom: 25px; -} -.dropme img { - margin-top: 17px; - float: right; - margin-right: 15px; -} -.checkus { - margin-bottom: 10px; -} -.checkus img { - display: inline-block; - vertical-align: middle; -} -.checkus p { - display: inline-block; - font-family: Roboto; - font-size: 14px; - vertical-align: middle; - margin-left: 10px; -} -#divisionthing { - height: 1px; - width: 100%; - background-color: #E8E8EF; - position: absolute; - right: 0px; - bottom: 80; -} -#removeblock { - border-radius: 5px; - position: absolute; - bottom: 20px; - font-family: Roboto; - font-size: 14px; - text-align: center; - width: 287px; - height: 38px; - line-height: 38px; - color: #253134; - border: 1px solid #E8E8EF; - transition: all .3s cubic-bezier(.05,.03,.35,1); -} -#removeblock:hover { - cursor: pointer; - opacity: .5; -} -.noselect { - -webkit-touch-callout: none; /* iOS Safari */ - -webkit-user-select: none; /* Safari */ - -khtml-user-select: none; /* Konqueror HTML */ - -moz-user-select: none; /* Old versions of Firefox */ - -ms-user-select: none; /* Internet Explorer/Edge */ - user-select: none; /* Non-prefixed version, currently - supported by Chrome, Opera and Firefox */ -} -.blockyname { - font-family: Roboto; - font-weight: 500; - color: #253134; - display: inline-block; - vertical-align: middle; - margin-left: 8px; - font-size: 16px; -} -.blockyleft img { - display: inline-block; - vertical-align: middle; -} -.blockyright { - display: inline-block; - float: right; - vertical-align: middle; - margin-right: 20px; - margin-top: 10px; - width: 28px; - height: 28px; - border-radius: 5px; - text-align: center; - background-color: #FFF; - transition: all .3s cubic-bezier(.05,.03,.35,1); - z-index: 10; -} -.blockyright:hover { - background-color: #F1F4FC; - cursor: pointer; -} -.blockyright img { - margin-top: 12px; -} -.blockyleft { - display: inline-block; - margin-left: 20px; -} -.blockydiv { - width: 100%; - height: 1px; - background-color: #E9E9EF; -} -.blockyinfo { - font-family: Roboto; - font-size: 14px; - color: #808292; - margin-top: 15px; - text-indent: 20px; - margin-bottom: 20px; -} -.blockyinfo span { - color: #253134; - font-weight: 500; - display: inline-block; - border-bottom: 1px solid #D3DCEA; - line-height: 20px; - text-indent: 0px; -} -.block { - background-color: #FFF; - margin-top: 0px!important; - box-shadow: 0px 4px 30px rgba(22, 33, 74, 0.05); -} -.selectedblock { - border: 2px solid #217CE8; - box-shadow: 0px 4px 30px rgba(22, 33, 74, 0.08); -} - -@media only screen and (max-width: 832px) { - #centerswitch { - display: none; - } -} -@media only screen and (max-width: 560px) { - #names { - display: none; - } -} \ No newline at end of file diff --git a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/_layout.svelte b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/_layout.svelte new file mode 100644 index 0000000000..0385342cef --- /dev/null +++ b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/_layout.svelte @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/index.svelte b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/index.svelte index 667d3e31fe..915c355cb8 100644 --- a/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/index.svelte +++ b/packages/builder/src/pages/[application]/backend/database/[selectedDatabase]/index.svelte @@ -1,6 +1,7 @@ -
-
{breadcrumbs}
- {#if $backendUiStore.selectedModel._id} - - Create new record - - {/if} -
-{#if $backendUiStore.selectedModel.schema && Object.keys($backendUiStore.selectedModel.schema).length === 0} - -{:else if $backendUiStore.selectedDatabase._id && $backendUiStore.selectedModel.name} +{#if selectedModel.schema && Object.keys(selectedModel.schema).length === 0} + +{:else if $backendUiStore.selectedDatabase._id && selectedModel.name} {:else} @@ -45,8 +34,8 @@ {/if} From d2fbddadd5af91494198abe139b74ace058e7562 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 18 Jun 2020 17:44:42 +0100 Subject: [PATCH 06/20] save button --- .../ModelDataTable/ModelDataTable.svelte | 10 ++ .../nav/ModelSetupNav/ModelFieldEditor.svelte | 24 +++-- .../nav/ModelSetupNav/ModelSetupNav.svelte | 21 +++-- .../builder/src/constants/backend/index.js | 92 +++++++++---------- 4 files changed, 86 insertions(+), 61 deletions(-) diff --git a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte index 2f02db9a6d..008c4eeed0 100644 --- a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte +++ b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte @@ -198,4 +198,14 @@ .no-data { padding: 20px; } + + .button-inner { + display: flex; + align-items: center; + } + + .button-inner i { + margin-right: 5px; + font-size: 20px; + } diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte index 6e72fdb2fa..d76e782ee7 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte @@ -39,7 +39,7 @@
-
+
@@ -66,12 +66,15 @@ label="Max Value" bind:value={field.constraints.numericality.lessThanOrEqualTo} /> {:else if field.type === 'link'} - +
+ + +
{/if}
@@ -87,10 +90,11 @@ font-size: 12px; } - .required-field { + .field { display: grid; align-items: center; grid-template-columns: 40% 1fr; + margin-top: 8px; } .field-box header { @@ -98,4 +102,8 @@ font-weight: 500; margin-bottom: 16px; } + + .field-box span { + font-weight: bold; + } diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte index d82389ec66..2407ee7f60 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte @@ -19,9 +19,13 @@ }, ] + let edited = false + $: selectedTab = $backendUiStore.tabs.SETUP_PANEL $: edited = + $backendUiStore.selectedField || + $backendUiStore.draftModel && $backendUiStore.draftModel.name !== $backendUiStore.selectedModel.name async function deleteModel() { @@ -31,18 +35,16 @@ if (field) { delete model.schema[field] - backendUiStore.actions.models.save({ model, instanceId }); - notifier.danger(`Field ${field} deleted.`); - return; + backendUiStore.actions.models.save({ model, instanceId }) + notifier.danger(`Field ${field} deleted.`) + return } const DELETE_MODEL_URL = `/api/${instanceId}/models/${model._id}/${model._rev}` const response = await api.delete(DELETE_MODEL_URL) backendUiStore.update(state => { state.selectedView = null - state.models = state.models.filter( - ({ _id }) => _id !== model._id - ) + state.models = state.models.filter(({ _id }) => _id !== model._id) notifier.danger(`${model.name} deleted successfully.`) return state }) @@ -78,7 +80,9 @@
{/if}
- +
{:else if selectedTab === 'DELETE'}
@@ -96,6 +100,8 @@ footer { width: 100%; + position: fixed; + bottom: 20px; } .items-root { @@ -110,6 +116,7 @@ .titled-input { padding: 12px; background: var(--light-grey); + margin-bottom: 5px; } .titled-input header { diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 3973b09238..7cd7aeae31 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -30,52 +30,52 @@ export const FIELDS = { presence: false, }, }, - OPTIONS: { - name: "Options", - icon: "ri-list-check-2", - type: "options", - constraints: { - type: "string", - presence: false, - }, - }, - DATETIME: { - name: "Date/Time", - icon: "ri-calendar-event-fill", - type: "datetime", - constraints: { - type: "date", - datetime: {}, - presence: false, - }, - }, - IMAGE: { - name: "File", - icon: "ri-image-line", - type: "file", - constraints: { - type: "string", - presence: false, - }, - }, - FILE: { - name: "Image", - icon: "ri-file-line", - type: "file", - constraints: { - type: "string", - presence: false, - }, - }, - DATA_LINK: { - name: "Data Links", - icon: "ri-link", - type: "link", - modelId: null, - constraints: { - type: "array", - } - }, + // OPTIONS: { + // name: "Options", + // icon: "ri-list-check-2", + // type: "options", + // constraints: { + // type: "string", + // presence: false, + // }, + // }, + // DATETIME: { + // name: "Date/Time", + // icon: "ri-calendar-event-fill", + // type: "datetime", + // constraints: { + // type: "date", + // datetime: {}, + // presence: false, + // }, + // }, + // IMAGE: { + // name: "File", + // icon: "ri-image-line", + // type: "file", + // constraints: { + // type: "string", + // presence: false, + // }, + // }, + // FILE: { + // name: "Image", + // icon: "ri-file-line", + // type: "file", + // constraints: { + // type: "string", + // presence: false, + // }, + // }, + // DATA_LINK: { + // name: "Data Links", + // icon: "ri-link", + // type: "link", + // modelId: null, + // constraints: { + // type: "array", + // } + // }, } export const BLOCKS = { From 9cdb6554a5b22c37ff9723239d1a78882cdc10cd Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 18 Jun 2020 17:49:34 +0100 Subject: [PATCH 07/20] typo --- packages/server/src/utilities/builder/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/utilities/builder/index.js b/packages/server/src/utilities/builder/index.js index 9a065642ad..7b9a6a69ec 100644 --- a/packages/server/src/utilities/builder/index.js +++ b/packages/server/src/utilities/builder/index.js @@ -41,7 +41,7 @@ const screenPath = (appPath, pageName, name) => module.exports.saveScreen = async (config, appname, pagename, screen) => { const appPath = appPackageFolder(config, appname) - const compPath = screenPath(appPath, pagename, screen.props._instanceName) + const compPath = screenPath(appPath, pagename, screen.name) await ensureDir(dirname(compPath)) if (screen._css) { delete screen._css From 099e394270911bd2d6faa9fca51bfb3b0fc3b5d3 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 18 Jun 2020 17:55:46 +0100 Subject: [PATCH 08/20] lint :sparkles: --- .../builder/src/builderStore/store/backend.js | 45 +-- .../src/components/common/Block.svelte | 3 +- .../common/LinkedRecordSelector.svelte | 6 +- .../modals/CreateEditRecord.svelte | 6 +- .../src/components/nav/HierarchyRow.svelte | 4 +- .../nav/ModelNavigator/BlockNavigator.svelte | 2 +- .../nav/ModelNavigator/EmptyModel.svelte | 24 +- .../nav/ModelNavigator/ModelNavigator.svelte | 16 +- .../nav/ModelSetupNav/ModelFieldEditor.svelte | 72 +++-- .../nav/ModelSetupNav/ModelSetupNav.svelte | 4 +- .../src/components/nav/ModelSetupNav/index.js | 2 +- .../Colorpicker/ButtonGroup.svelte | 26 +- .../Colorpicker/Colorpicker.svelte | 152 +++++----- .../Colorpicker/Colorpreview.svelte | 267 ++++++++++-------- .../Colorpicker/FlatButton.svelte | 8 +- .../userInterface/Colorpicker/Input.svelte | 10 +- .../userInterface/Colorpicker/Palette.svelte | 55 ++-- .../userInterface/Colorpicker/Slider.svelte | 61 ++-- .../userInterface/DesignView.svelte | 38 +-- .../userInterface/PropertyControl.svelte | 2 +- .../builder/src/constants/backend/index.js | 112 ++++---- .../[selectedDatabase]/_layout.svelte | 2 +- .../database/[selectedDatabase]/index.svelte | 4 +- 23 files changed, 479 insertions(+), 442 deletions(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 16fd12ada4..ddd0174c09 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -1,5 +1,5 @@ import { writable } from "svelte/store" -import { cloneDeep } from "lodash/fp"; +import { cloneDeep } from "lodash/fp" import api from "../api" export const getBackendUiStore = () => { @@ -12,8 +12,8 @@ export const getBackendUiStore = () => { draftModel: {}, tabs: { SETUP_PANEL: "SETUP", - NAVIGATION_PANEL: "NAVIGATE" - } + NAVIGATION_PANEL: "NAVIGATE", + }, } const store = writable(INITIAL_BACKEND_UI_STATE) @@ -28,7 +28,7 @@ export const getBackendUiStore = () => { store.update(state => { state.selectedDatabase = db if (models && models.length > 0) { - store.actions.models.select(models[0]); + store.actions.models.select(models[0]) } state.models = models state.views = views @@ -49,24 +49,25 @@ export const getBackendUiStore = () => { }), }, models: { - select: model => store.update(state => { - state.selectedModel = model; - state.draftModel = cloneDeep(model); - state.selectedField = "" - state.selectedView = `all_${model._id}` - state.tabs.SETUP_PANEL = "SETUP" - return state; - }), + select: model => + store.update(state => { + state.selectedModel = model + state.draftModel = cloneDeep(model) + state.selectedField = "" + state.selectedView = `all_${model._id}` + state.tabs.SETUP_PANEL = "SETUP" + return state + }), save: async ({ instanceId, model }) => { - const updatedModel = cloneDeep(model); + const updatedModel = cloneDeep(model) // TODO: refactor for (let key in updatedModel.schema) { const field = updatedModel.schema[key] - if (field.name && field.name !== key) { - updatedModel.schema[field.name] = field - delete updatedModel.schema[key]; - } + if (field.name && field.name !== key) { + updatedModel.schema[field.name] = field + delete updatedModel.schema[key] + } } const SAVE_MODEL_URL = `/api/${instanceId}/models` @@ -78,8 +79,10 @@ export const getBackendUiStore = () => { if (!model._id) { state.models = [...state.models, savedModel] } else { - const existingIdx = state.models.findIndex(({ _id }) => _id === model._id); - state.models.splice(existingIdx, 1, savedModel); + const existingIdx = state.models.findIndex( + ({ _id }) => _id === model._id + ) + state.models.splice(existingIdx, 1, savedModel) state.models = state.models } @@ -95,7 +98,7 @@ export const getBackendUiStore = () => { state.draftModel.schema = { ...state.draftModel.schema, - [field.name]: field + [field.name]: field, } state.selectedField = field.name @@ -103,7 +106,7 @@ export const getBackendUiStore = () => { state.tabs.NAVIGATION_PANEL = "NAVIGATE" return state - }); + }) }, }, views: { diff --git a/packages/builder/src/components/common/Block.svelte b/packages/builder/src/components/common/Block.svelte index 168834b5a8..0d4cb1b9e2 100644 --- a/packages/builder/src/components/common/Block.svelte +++ b/packages/builder/src/components/common/Block.svelte @@ -30,7 +30,7 @@ i { font-size: 30px; } - + span { font-size: 14px; text-align: center; @@ -53,5 +53,4 @@ .tertiary { background: var(--white); } - diff --git a/packages/builder/src/components/common/LinkedRecordSelector.svelte b/packages/builder/src/components/common/LinkedRecordSelector.svelte index 18adfda61e..b4787773b3 100644 --- a/packages/builder/src/components/common/LinkedRecordSelector.svelte +++ b/packages/builder/src/components/common/LinkedRecordSelector.svelte @@ -1,5 +1,5 @@ @@ -65,4 +65,4 @@ font-size: 14px; word-break: break-word; } - \ No newline at end of file + diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte index 7c31ea3bf3..f96e2530a6 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte @@ -1,7 +1,7 @@ @@ -20,7 +20,11 @@

Blocks are pre-made fields and help you build your model quicker.

{#each Object.values(FIELDS) as field} - addNewField(field)} /> + addNewField(field)} /> {/each}
@@ -30,7 +34,11 @@

Blocks are pre-made fields and help you build your model quicker.

{#each Object.values(BLOCKS) as field} - addNewField(field)} /> + addNewField(field)} /> {/each}
@@ -78,4 +86,4 @@ grid-auto-columns: 110px; grid-gap: 20px; } - \ No newline at end of file + diff --git a/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte index b0b0d9ca24..3d9aeb64fd 100644 --- a/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/ModelNavigator.svelte @@ -1,6 +1,6 @@ +
+ {#each colorFormats as text} + onclick(text)} /> + {/each} +
+ - -
- {#each colorFormats as text} - onclick(text)} /> - {/each} -
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte index 936756f403..9813c9ff28 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte @@ -1,123 +1,79 @@ - -
@@ -143,3 +99,47 @@
+ + diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte index fa880b6292..1f637f7483 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte @@ -1,143 +1,170 @@
- {#if !errorMsg} -
- {#if open} -
- -
-
open = false} class="overlay">
- {/if} - {:else} -
- × -
+ {#if !errorMsg} +
+ {#if open} +
+ +
+
(open = false)} class="overlay" /> {/if} + {:else} +
+ × +
+ {/if}
- - diff --git a/packages/builder/src/components/userInterface/Colorpicker/FlatButton.svelte b/packages/builder/src/components/userInterface/Colorpicker/FlatButton.svelte index af1ea5e945..48e2e12c30 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/FlatButton.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/FlatButton.svelte @@ -1,8 +1,10 @@ +
{text}
+ - -
{text}
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Input.svelte b/packages/builder/src/components/userInterface/Colorpicker/Input.svelte index 04966c1f30..4316204c84 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Input.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Input.svelte @@ -1,7 +1,11 @@ +
+ +
+ - -
- -
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte b/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte index 01a614124c..6454c84b92 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte @@ -1,41 +1,54 @@ +
+
+
+ - -
-
-
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte b/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte index ec8d99248d..761f2c7acb 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Slider.svelte @@ -1,36 +1,47 @@ +
handleClick(event.clientX)} + class="color-format-slider" + class:hue={type === 'hue'} + class:alpha={type === 'alpha'}> +
handleClick(e.detail)} + class="slider-thumb" + {style} /> +
+ - -
handleClick(event.clientX)} - class="color-format-slider" - class:hue={type === 'hue'} - class:alpha={type === 'alpha'}> -
handleClick(e.detail)} - class="slider-thumb" - {style} /> -
diff --git a/packages/builder/src/components/userInterface/DesignView.svelte b/packages/builder/src/components/userInterface/DesignView.svelte index 6826bddc5c..97cf9bb40f 100644 --- a/packages/builder/src/components/userInterface/DesignView.svelte +++ b/packages/builder/src/components/userInterface/DesignView.svelte @@ -31,26 +31,26 @@
-
-
- {#if propertyGroupNames.length > 0} - {#each propertyGroupNames as groupName} - - {/each} - {:else} -
- This component does not have any design properties -
- {/if} +
+
+ {#if propertyGroupNames.length > 0} + {#each propertyGroupNames as groupName} + + {/each} + {:else} +
+ This component does not have any design properties +
+ {/if} +
-
diff --git a/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte b/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte new file mode 100644 index 0000000000..c00fb53c3e --- /dev/null +++ b/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte @@ -0,0 +1,92 @@ + + +
+ (open = !open)}>{records.length} + {#if open} +
+

{header}

+ {#each records as record} +
+
+ {#each Object.keys(record).slice(0, 2) as key} +
+ {key} +

{record[key]}

+
+ {/each} +
+
+ {/each} +
+ {/if} +
+ + diff --git a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte index 008c4eeed0..0b13b3a7d4 100644 --- a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte +++ b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte @@ -4,6 +4,7 @@ import { Button } from "@budibase/bbui" import Select from "components/common/Select.svelte" import ActionButton from "components/common/ActionButton.svelte" + import LinkedRecord from "./LinkedRecord.svelte"; import TablePagination from "./TablePagination.svelte" import { DeleteRecordModal, CreateEditRecordModal } from "./modals" import * as api from "./api" @@ -41,6 +42,7 @@ let headers = [] let views = [] let currentPage = 0 + let search $: instanceId = $backendUiStore.selectedDatabase._id @@ -91,6 +93,10 @@
+ @@ -130,7 +136,13 @@ {#each headers as header} - + {/each} {/each} diff --git a/packages/builder/src/components/database/ModelDataTable/api.js b/packages/builder/src/components/database/ModelDataTable/api.js index cb98879567..3bd8a0b3e6 100644 --- a/packages/builder/src/components/database/ModelDataTable/api.js +++ b/packages/builder/src/components/database/ModelDataTable/api.js @@ -15,7 +15,7 @@ export async function createDatabase(appname, instanceName) { } export async function deleteRecord(record, instanceId) { - const DELETE_RECORDS_URL = `/api/${instanceId}/${record._modelId}/records/${record._id}/${record._rev}` + const DELETE_RECORDS_URL = `/api/${instanceId}/${record.modelId}/records/${record._id}/${record._rev}` const response = await api.delete(DELETE_RECORDS_URL) return response } diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte index f96e2530a6..7c94aa3a03 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte @@ -77,7 +77,7 @@ {#each modelSchema as [key, meta]}
{#if meta.type === 'link'} - + {:else} import ActionButton from "components/common/ActionButton.svelte" + import { notifier } from "@beyonk/svelte-notifications" import { store, backendUiStore } from "builderStore" import * as api from "../api" @@ -26,6 +27,7 @@ alert on:click={async () => { await api.deleteRecord(record, instanceId) + notifier.danger("Record deleted") backendUiStore.actions.records.delete(record) onClosed() }}> diff --git a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte index ed6e58ee54..3be5ebc715 100644 --- a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte @@ -1,6 +1,6 @@
@@ -48,7 +60,7 @@

Blocks are pre-made fields and help you build your model quicker.

{#each Object.values(MODELS) as model} - + createModel(model)}/> {/each}
diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 16749b3d9d..620cd4ad48 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -28,15 +28,15 @@ export const FIELDS = { presence: false, }, }, - OPTIONS: { - name: "Options", - icon: "ri-list-check-2", - type: "options", - constraints: { - type: "string", - presence: false, - }, - }, + // OPTIONS: { + // name: "Options", + // icon: "ri-list-check-2", + // type: "options", + // constraints: { + // type: "string", + // presence: false, + // }, + // }, DATETIME: { name: "Date/Time", icon: "ri-calendar-event-fill", @@ -47,24 +47,24 @@ export const FIELDS = { presence: false, }, }, - IMAGE: { - name: "File", - icon: "ri-image-line", - type: "file", - constraints: { - type: "string", - presence: false, - }, - }, - FILE: { - name: "Image", - icon: "ri-file-line", - type: "file", - constraints: { - type: "string", - presence: false, - }, - }, + // IMAGE: { + // name: "File", + // icon: "ri-image-line", + // type: "file", + // constraints: { + // type: "string", + // presence: false, + // }, + // }, + // FILE: { + // name: "Image", + // icon: "ri-file-line", + // type: "file", + // constraints: { + // type: "string", + // presence: false, + // }, + // }, DATA_LINK: { name: "Data Links", icon: "ri-link", @@ -106,16 +106,16 @@ export const BLOCKS = { presence: false, }, }, - PRIORITY: { - name: "Options", - icon: "ri-list-check-2", - type: "options", - constraints: { - type: "string", - presence: false, - inclusion: ["low", "medium", "high"], - }, - }, + // PRIORITY: { + // name: "Options", + // icon: "ri-list-check-2", + // type: "options", + // constraints: { + // type: "string", + // presence: false, + // inclusion: ["low", "medium", "high"], + // }, + // }, END_DATE: { name: "End Date", icon: "ri-calendar-event-fill", @@ -126,39 +126,29 @@ export const BLOCKS = { presence: false, }, }, - AVATAR: { - name: "Avatar", - icon: "ri-image-line", - type: "image", - constraints: { - type: "string", - presence: false, - }, - }, - PDF: { - name: "PDF", - icon: "ri-file-line", - type: "file", - constraints: { - type: "string", - presence: false, - }, - }, - DATA_LINK: { - name: "Data Links", - icon: "ri-link", - type: "link", - modelId: null, - constraints: { - type: "array", - }, - }, + // AVATAR: { + // name: "Avatar", + // icon: "ri-image-line", + // type: "image", + // constraints: { + // type: "string", + // presence: false, + // }, + // }, + // PDF: { + // name: "PDF", + // icon: "ri-file-line", + // type: "file", + // constraints: { + // type: "string", + // presence: false, + // }, + // }, } -// TODO: Needs more thought, need to come up with the constraints etc for each one export const MODELS = { CONTACTS: { - icon: "ri-link", + icon: "ri-contacts-book-line", name: "Contacts", schema: { Name: BLOCKS.NAME, @@ -170,7 +160,21 @@ export const MODELS = { name: "Recipes", schema: { Name: BLOCKS.NAME, - "Phone Number": BLOCKS.PHONE_NUMBER, + Cuisine: { + ...FIELDS.PLAIN_TEXT, + name: "Cuisine" + }, + }, + }, + SPORTS_TEAM: { + icon: "ri-basketball-line", + name: "Sports Team", + schema: { + Name: BLOCKS.NAME, + Championships: { + ...FIELDS.NUMBER, + name: "Championships" + } }, }, } diff --git a/packages/server/src/api/controllers/model.js b/packages/server/src/api/controllers/model.js index effd179e9d..0040ea6207 100644 --- a/packages/server/src/api/controllers/model.js +++ b/packages/server/src/api/controllers/model.js @@ -34,6 +34,7 @@ exports.save = async function(ctx) { // create the link field in the other model const linkedModel = await db.get(schema[key].modelId) linkedModel.schema[modelToSave.name] = { + name: modelToSave.name, type: "link", modelId: modelToSave._id, constraints: { diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index cf8eb27606..37b490a29d 100644 --- a/packages/server/src/api/controllers/record.js +++ b/packages/server/src/api/controllers/record.js @@ -1,6 +1,7 @@ const CouchDB = require("../../db") const validateJs = require("validate.js") const newid = require("../../db/newid") +const { link } = require("pouchdb-adapter-memory") exports.save = async function(ctx) { const db = new CouchDB(ctx.params.instanceId) @@ -43,6 +44,28 @@ exports.save = async function(ctx) { const response = await db.post(record) record._rev = response.rev + // create links in other tables + for (let key in record) { + // link + if (Array.isArray(record[key])) { + const linked = await db.allDocs({ + include_docs: true, + keys: record[key], + }) + + // add this record to the linked records in attached models + const linkedDocs = linked.rows.map(row => { + const doc = row.doc + return { + ...doc, + [model.name]: doc[model.name] ? [...doc[model.name], record._id] : [record._id] + } + }) + + await db.bulkDocs(linkedDocs) + } + } + ctx.eventEmitter && ctx.eventEmitter.emit(`record:save`, { record, diff --git a/packages/server/src/utilities/linkedRecords.js b/packages/server/src/utilities/linkedRecords.js new file mode 100644 index 0000000000..e69de29bb2 From afcc80ab9d303909fe7210605ca5d4ade761eaf9 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 23 Jun 2020 13:50:45 +0100 Subject: [PATCH 10/20] improvements to linked records --- .../builder/src/builderStore/store/backend.js | 6 +- .../common/LinkedRecordSelector.svelte | 42 +++-- .../ModelDataTable/LinkedRecord.svelte | 46 ++++-- .../modals/CreateEditRecord.svelte | 46 +++++- .../modals/RecordFieldControl.svelte | 13 ++ .../nav/ModelSetupNav/ModelSetupNav.svelte | 2 +- .../nav/SchemaManagementDrawer.svelte | 143 ------------------ .../Colorpicker/Colorpreview.svelte | 44 +----- 8 files changed, 131 insertions(+), 211 deletions(-) delete mode 100644 packages/builder/src/components/nav/SchemaManagementDrawer.svelte diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 3322e38e5c..71fa50acaa 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -58,7 +58,7 @@ export const getBackendUiStore = () => { state.tabs.SETUP_PANEL = "SETUP" return state }), - save: async ({ instanceId, model }) => { + save: async ({ model }) => { const updatedModel = cloneDeep(model) // TODO: refactor @@ -70,7 +70,7 @@ export const getBackendUiStore = () => { } } - const SAVE_MODEL_URL = `/api/${instanceId}/models` + const SAVE_MODEL_URL = `/api/models` const response = await api.post(SAVE_MODEL_URL, updatedModel) const savedModel = await response.json() @@ -86,6 +86,8 @@ export const getBackendUiStore = () => { state.models = state.models } + // TODO: fetch models + store.actions.models.select(savedModel) return state }) diff --git a/packages/builder/src/components/common/LinkedRecordSelector.svelte b/packages/builder/src/components/common/LinkedRecordSelector.svelte index 22fa383ec6..8bb64ca2e8 100644 --- a/packages/builder/src/components/common/LinkedRecordSelector.svelte +++ b/packages/builder/src/components/common/LinkedRecordSelector.svelte @@ -9,8 +9,13 @@ let records = [] + let linkedRecords = new Set(linked) + + $: linked = [...linkedRecords] + $: FIELDS_TO_HIDE = ["modelId", "type", "_id", "_rev", $backendUiStore.selectedModel.name] + async function fetchRecords() { - const FETCH_RECORDS_URL = `/api/${$backendUiStore.selectedDatabase._id}/${modelId}/records` + const FETCH_RECORDS_URL = `/api/${modelId}/records` const response = await api.get(FETCH_RECORDS_URL) records = await response.json() } @@ -19,17 +24,25 @@ fetchRecords() }) - function linkRecord(record) { - linked.push(record._id) + function linkRecord(id) { + if (linkedRecords.has(id)) { + linkedRecords.delete(id); + } else { + linkedRecords.add(id) + } + + linkedRecords = linkedRecords }
-

{linkName}

+
+

{linkName}

+
{#each records as record} -
linkRecord(record)}> -
- {#each Object.keys(record).slice(0, 2) as key} +
linkRecord(record._id)}> +
+ {#each Object.keys(record).filter(key => !FIELDS_TO_HIDE.includes(key)) as key}
{key}

{record[key]}

@@ -41,8 +54,15 @@
\ No newline at end of file diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte index 5f7275e0e5..40b12d527e 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte @@ -40,7 +40,7 @@ return } - const DELETE_MODEL_URL = `/api/${instanceId}/models/${model._id}/${model._rev}` + const DELETE_MODEL_URL = `/api/models/${model._id}/${model._rev}` const response = await api.delete(DELETE_MODEL_URL) backendUiStore.update(state => { state.selectedView = null diff --git a/packages/builder/src/components/nav/SchemaManagementDrawer.svelte b/packages/builder/src/components/nav/SchemaManagementDrawer.svelte deleted file mode 100644 index 9465c85140..0000000000 --- a/packages/builder/src/components/nav/SchemaManagementDrawer.svelte +++ /dev/null @@ -1,143 +0,0 @@ - - -
-
-
- -
- -
- {#each $backendUiStore.models as model} - - {/each} -
-
- -
-
- -
- -
- {#each $backendUiStore.views as view} - - {/each} -
-
-
- - diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte index 0bd68404f6..4e61b65902 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte @@ -85,42 +85,10 @@ dimensions = {top, left} } - }) - function openColorpicker(event) { - if (colorPreview) { - const { - top: spaceAbove, - width, - bottom, - right, - left: spaceLeft, - } = colorPreview.getBoundingClientRect() - const { innerHeight, innerWidth } = window - - const { offsetLeft, offsetTop } = colorPreview - //get the scrollTop value for all scrollable parent elements - let scrollTop = parentNodes.reduce( - (scrollAcc, el) => (scrollAcc += el.scrollTop), - 0 - ) - - const spaceBelow = innerHeight - spaceAbove - previewHeight - const top = - spaceAbove > spaceBelow - ? offsetTop - pickerHeight - scrollTop - : offsetTop + previewHeight - scrollTop - - //TOO: Testing and Scroll Awareness for x Scroll - const spaceRight = innerWidth - spaceLeft + previewWidth - const left = - spaceRight > spaceLeft - ? offsetLeft + previewWidth + pickerWidth - : offsetLeft - pickerWidth - - dimensions = { top, left } - - open = true + function onColorChange(color) { + value = color.detail; + dispatch("change", color.detail) } @@ -142,13 +110,9 @@ × {/if} - {:else} -
- × -
- {/if} + \ No newline at end of file + diff --git a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte index 3be5ebc715..61476849df 100644 --- a/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/BlockNavigator.svelte @@ -1,6 +1,6 @@ @@ -60,7 +59,11 @@

Blocks are pre-made fields and help you build your model quicker.

{#each Object.values(MODELS) as model} - createModel(model)}/> + createModel(model)} /> {/each}
diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte index 40b12d527e..6097210d51 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte @@ -30,12 +30,11 @@ async function deleteModel() { const model = $backendUiStore.selectedModel - const instanceId = $backendUiStore.selectedDatabase._id const field = $backendUiStore.selectedField if (field) { delete model.schema[field] - backendUiStore.actions.models.save({ model, instanceId }) + backendUiStore.actions.models.save({ model }) notifier.danger(`Field ${field} deleted.`) return } @@ -52,7 +51,6 @@ async function saveModel() { await backendUiStore.actions.models.save({ - instanceId: $backendUiStore.selectedDatabase._id, model: $backendUiStore.draftModel, }) notifier.success( diff --git a/packages/builder/src/components/userInterface/Colorpicker/CheckedBackground.svelte b/packages/builder/src/components/userInterface/Colorpicker/CheckedBackground.svelte index 19d54523b2..e612fb5393 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/CheckedBackground.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/CheckedBackground.svelte @@ -1,17 +1,20 @@ +
+ +
+ - -
- -
\ No newline at end of file diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte index 1bc7970124..aff8e22c91 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpicker.svelte @@ -1,9 +1,9 @@
@@ -174,6 +173,73 @@
+ +
+ +
+ +
+ +
+
+
+ +
+ +
+
+ setHue(hue.detail)} + on:dragend={dispatchValue} /> + + + setAlpha(alpha.detail, isDrag)} + on:dragend={dispatchValue} /> + + +
+
+ + {#if !disableSwatches} +
+ {#if swatches.length > 0} + {#each swatches as color, idx} + applySwatch(color)} + on:removeswatch={() => removeSwatch(idx)} /> + {/each} + {/if} + {#if swatches.length !== 12} +
+ + +
+ {/if} +
+ {/if} + +
+ + handleColorInput(event.target.value)} + on:change={dispatchInputChange} /> +
+
+
- -
- -
- -
- -
-
-
- -
- -
-
- setHue(hue.detail)} on:dragend={dispatchValue} /> - - - setAlpha(alpha.detail, isDrag)} - on:dragend={dispatchValue} - /> - - -
-
- - {#if !disableSwatches} -
- {#if swatches.length > 0} - {#each swatches as color, idx} - applySwatch(color)} on:removeswatch={() => removeSwatch(idx)} /> - {/each} - {/if} - {#if swatches.length !== 12} -
- + -
- {/if} -
- {/if} - -
- - handleColorInput(event.target.value)} on:change={dispatchInputChange} /> -
-
- -
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte b/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte index 4e61b65902..72da43181e 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Colorpreview.svelte @@ -1,151 +1,184 @@
- {#if !errorMsg} - -
- + {#if !errorMsg} + +
+ - {#if open} -
- -
-
open = false} class="overlay">
- {/if} - {:else} -
- × -
+ {#if open} +
+ +
+
(open = false)} class="overlay" /> {/if} + {:else} +
+ × +
+ {/if}
- diff --git a/packages/builder/src/components/userInterface/Colorpicker/Input.svelte b/packages/builder/src/components/userInterface/Colorpicker/Input.svelte index 5e0c3a2b3f..c148d6bf30 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Input.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Input.svelte @@ -5,6 +5,9 @@
+
+ +
- -
- -
diff --git a/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte b/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte index 4077086f87..78e9a24751 100644 --- a/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte +++ b/packages/builder/src/components/userInterface/Colorpicker/Palette.svelte @@ -1,5 +1,5 @@ +
+ +
(hovered = true)} + on:mouseleave={() => (hovered = false)}> + {#if hovered} +
dispatch('removeswatch')}> + dispatch('removeswatch')}>× +
+ {/if} +
+
+
+ - -
- -
hovered = true} on:mouseleave={() => hovered = false}> - {#if hovered} -
dispatch("removeswatch")}> - dispatch("removeswatch")}>× -
- {/if} -
-
-
\ No newline at end of file diff --git a/packages/builder/src/constants/backend/index.js b/packages/builder/src/constants/backend/index.js index 620cd4ad48..89861b8ac7 100644 --- a/packages/builder/src/constants/backend/index.js +++ b/packages/builder/src/constants/backend/index.js @@ -162,7 +162,7 @@ export const MODELS = { Name: BLOCKS.NAME, Cuisine: { ...FIELDS.PLAIN_TEXT, - name: "Cuisine" + name: "Cuisine", }, }, }, @@ -173,8 +173,8 @@ export const MODELS = { Name: BLOCKS.NAME, Championships: { ...FIELDS.NUMBER, - name: "Championships" - } + name: "Championships", + }, }, }, } diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index 4d6b353329..273175c2b1 100644 --- a/packages/server/src/api/controllers/record.js +++ b/packages/server/src/api/controllers/record.js @@ -1,7 +1,6 @@ const CouchDB = require("../../db") const validateJs = require("validate.js") const newid = require("../../db/newid") -const { link } = require("pouchdb-adapter-memory") exports.save = async function(ctx) { const db = new CouchDB(ctx.user.instanceId) @@ -46,7 +45,6 @@ exports.save = async function(ctx) { // create links in other tables for (let key in record) { - // link if (Array.isArray(record[key])) { const linked = await db.allDocs({ include_docs: true, @@ -58,7 +56,9 @@ exports.save = async function(ctx) { const doc = row.doc return { ...doc, - [model.name]: doc[model.name] ? [...doc[model.name], record._id] : [record._id] + [model.name]: doc[model.name] + ? [...doc[model.name], record._id] + : [record._id], } }) @@ -105,7 +105,7 @@ exports.find = async function(ctx) { const db = new CouchDB(ctx.user.instanceId) const record = await db.get(ctx.params.recordId) if (record.modelId !== ctx.params.modelId) { - ctx.throw(400, "Supplied modelId doe not match the record's modelId") + ctx.throw(400, "Supplied modelId does not match the records modelId") return } ctx.body = record diff --git a/packages/standard-components/src/Login.svelte b/packages/standard-components/src/Login.svelte index 0675c65f46..d09cd0ff2b 100644 --- a/packages/standard-components/src/Login.svelte +++ b/packages/standard-components/src/Login.svelte @@ -23,7 +23,10 @@ const login = async () => { loading = true - const response = await _bb.api.post("/api/authenticate", { username, password }) + const response = await _bb.api.post("/api/authenticate", { + username, + password, + }) if (response.status === 200) { const json = await response.json() localStorage.setItem("budibase:token", json.token) From 3c3104be7b28eafffb8b70bff91a7ceb45c45b5b Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 23 Jun 2020 23:26:54 +0100 Subject: [PATCH 12/20] enable renaming of records by using IDs --- .../builder/src/builderStore/store/backend.js | 28 +++++++++---------- .../common/LinkedRecordSelector.svelte | 9 +++--- .../ModelDataTable/LinkedRecord.svelte | 1 + .../ModelDataTable/ModelDataTable.svelte | 19 ++++++++----- .../modals/CreateEditRecord.svelte | 7 ++--- .../nav/ModelNavigator/EmptyModel.svelte | 10 ++++++- .../nav/ModelNavigator/ModelNavigator.svelte | 15 +++++----- .../nav/ModelSetupNav/ModelFieldEditor.svelte | 18 ++++++++++-- .../nav/ModelSetupNav/ModelSetupNav.svelte | 4 ++- .../server/src/api/controllers/application.js | 4 +-- packages/server/src/api/controllers/auth.js | 2 +- .../server/src/api/controllers/component.js | 2 +- .../server/src/api/controllers/instance.js | 2 +- packages/server/src/api/controllers/model.js | 4 +-- packages/server/src/api/controllers/record.js | 4 +-- packages/server/src/api/controllers/user.js | 2 +- packages/server/src/api/routes/model.js | 3 +- 17 files changed, 82 insertions(+), 52 deletions(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 71fa50acaa..83c241f818 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -1,5 +1,6 @@ import { writable } from "svelte/store" import { cloneDeep } from "lodash/fp" +import { uuid } from "builderStore/uuid" import api from "../api" export const getBackendUiStore = () => { @@ -61,14 +62,15 @@ export const getBackendUiStore = () => { save: async ({ model }) => { const updatedModel = cloneDeep(model) - // TODO: refactor - for (let key in updatedModel.schema) { - const field = updatedModel.schema[key] - if (field.name && field.name !== key) { - updatedModel.schema[field.name] = field - delete updatedModel.schema[key] - } - } + // // TODO: refactor + // for (let key in updatedModel.schema) { + // const field = updatedModel.schema[key] + // // TODO: use IDs + // if (field.name && field.name !== key) { + // updatedModel.schema[field.name] = field + // delete updatedModel.schema[key] + // } + // } const SAVE_MODEL_URL = `/api/models` const response = await api.post(SAVE_MODEL_URL, updatedModel) @@ -86,8 +88,6 @@ export const getBackendUiStore = () => { state.models = state.models } - // TODO: fetch models - store.actions.models.select(savedModel) return state }) @@ -98,13 +98,13 @@ export const getBackendUiStore = () => { state.draftModel.schema = {} } + const id = uuid() + state.draftModel.schema = { ...state.draftModel.schema, - [field.name]: field, + [id]: field, } - - state.selectedField = field.name - + state.selectedField = id state.tabs.NAVIGATION_PANEL = "NAVIGATE" return state diff --git a/packages/builder/src/components/common/LinkedRecordSelector.svelte b/packages/builder/src/components/common/LinkedRecordSelector.svelte index 4323ba6164..24c8d8f5d8 100644 --- a/packages/builder/src/components/common/LinkedRecordSelector.svelte +++ b/packages/builder/src/components/common/LinkedRecordSelector.svelte @@ -18,6 +18,7 @@ "_id", "_rev", $backendUiStore.selectedModel.name, + modelId ] async function fetchRecords() { @@ -26,10 +27,6 @@ records = await response.json() } - onMount(() => { - fetchRecords() - }) - function linkRecord(id) { if (linkedRecords.has(id)) { linkedRecords.delete(id) @@ -39,6 +36,10 @@ linkedRecords = linkedRecords } + + onMount(() => { + fetchRecords() + })
diff --git a/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte b/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte index 9402c26003..96e611ad27 100644 --- a/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte +++ b/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte @@ -15,6 +15,7 @@ "type", "_id", "_rev", + $backendUiStore.selectedModel._id, $backendUiStore.selectedModel.name, ] diff --git a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte index 8424c12048..27c9694cc1 100644 --- a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte +++ b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte @@ -48,9 +48,6 @@ if ($backendUiStore.selectedView) { api.fetchDataForView($backendUiStore.selectedView).then(records => { data = records || [] - headers = Object.keys($backendUiStore.selectedModel.schema).filter( - key => !INTERNAL_HEADERS.includes(key) - ) }) } } @@ -62,6 +59,12 @@ ) : [] + $: headers = Object.keys($backendUiStore.selectedModel.schema).filter( + id => !INTERNAL_HEADERS.includes(id) + ) + + $: schema = $backendUiStore.selectedModel.schema + const createNewRecord = () => { open( CreateEditRecordModal, @@ -94,7 +97,7 @@
{#each headers as header} - + {/each} @@ -129,9 +132,11 @@ {#each headers as header} {/each} diff --git a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte index 60f0cd9fa3..c988e5d762 100644 --- a/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte +++ b/packages/builder/src/components/database/ModelDataTable/modals/CreateEditRecord.svelte @@ -79,13 +79,13 @@ {#if meta.type === 'link'} {:else} {/if} @@ -101,7 +101,7 @@ header { margin-bottom: 40px; display: grid; - grid-gap: 5px; + grid-gap: 20px; grid-template-columns: 40px 1fr; align-items: center; } @@ -115,7 +115,6 @@ background: var(--secondary); color: var(--ink); font-size: 20px; - margin-right: 20px; border-radius: 3px; } diff --git a/packages/builder/src/components/nav/ModelNavigator/EmptyModel.svelte b/packages/builder/src/components/nav/ModelNavigator/EmptyModel.svelte index db424f8ef7..5feb5b3a57 100644 --- a/packages/builder/src/components/nav/ModelNavigator/EmptyModel.svelte +++ b/packages/builder/src/components/nav/ModelNavigator/EmptyModel.svelte @@ -1,5 +1,6 @@
@@ -66,10 +78,12 @@ {:else if field.type === 'link'}
- + {#if model._id !== $backendUiStore.draftModel._id} + + {/if} {/each}
diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte index 6097210d51..24a3079484 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelSetupNav.svelte @@ -43,6 +43,8 @@ const response = await api.delete(DELETE_MODEL_URL) backendUiStore.update(state => { state.selectedView = null + state.selectedModel = {} + state.draftModel = {} state.models = state.models.filter(({ _id }) => _id !== model._id) notifier.danger(`${model.name} deleted successfully.`) return state @@ -64,7 +66,7 @@ {#if selectedTab === 'SETUP'} {#if $backendUiStore.selectedField} - {:else} + {:else if $backendUiStore.draftModel.schema}
Name
clientId lookup - const masterDb = new CouchDB("clientAppLookup") + const masterDb = new CouchDB("client_app_lookup") await masterDb.put({ _id: appId, @@ -132,7 +132,7 @@ const createEmptyAppPackage = async (ctx, app) => { } const lookupClientId = async appId => { - const masterDb = new CouchDB("clientAppLookup") + const masterDb = new CouchDB("client_app_lookup") const { clientId } = await masterDb.get(appId) return clientId } diff --git a/packages/server/src/api/controllers/auth.js b/packages/server/src/api/controllers/auth.js index e9570e270f..4f0ddbf0d8 100644 --- a/packages/server/src/api/controllers/auth.js +++ b/packages/server/src/api/controllers/auth.js @@ -11,7 +11,7 @@ exports.authenticate = async ctx => { if (!username) ctx.throw(400, "Username Required.") if (!password) ctx.throw(400, "Password Required") - const masterDb = new CouchDB("clientAppLookup") + const masterDb = new CouchDB("client_app_lookup") const { clientId } = await masterDb.get(ctx.user.appId) diff --git a/packages/server/src/api/controllers/component.js b/packages/server/src/api/controllers/component.js index a3b4d9c2bb..3d631bcaec 100644 --- a/packages/server/src/api/controllers/component.js +++ b/packages/server/src/api/controllers/component.js @@ -7,7 +7,7 @@ const { } = require("../../utilities/budibaseDir") exports.fetchAppComponentDefinitions = async function(ctx) { - const masterDb = new CouchDB("clientAppLookup") + const masterDb = new CouchDB("client_app_lookup") const { clientId } = await masterDb.get(ctx.params.appId) const db = new CouchDB(ClientDb.name(clientId)) const app = await db.get(ctx.params.appId) diff --git a/packages/server/src/api/controllers/instance.js b/packages/server/src/api/controllers/instance.js index 903d3ff651..4bc22bd650 100644 --- a/packages/server/src/api/controllers/instance.js +++ b/packages/server/src/api/controllers/instance.js @@ -8,7 +8,7 @@ exports.create = async function(ctx) { const appShortId = appId.substring(0, 7) const instanceId = `inst_${appShortId}_${newid()}` - const masterDb = new CouchDB("clientAppLookup") + const masterDb = new CouchDB("client_app_lookup") const { clientId } = await masterDb.get(appId) const db = new CouchDB(instanceId) diff --git a/packages/server/src/api/controllers/model.js b/packages/server/src/api/controllers/model.js index 1bb507f08f..65bc367a08 100644 --- a/packages/server/src/api/controllers/model.js +++ b/packages/server/src/api/controllers/model.js @@ -16,7 +16,7 @@ exports.find = async function(ctx) { ctx.body = model } -exports.create = async function(ctx) { +exports.save = async function(ctx) { const db = new CouchDB(ctx.user.instanceId) const modelToSave = { type: "model", @@ -33,7 +33,7 @@ exports.create = async function(ctx) { if (schema[key].type === "link") { // create the link field in the other model const linkedModel = await db.get(schema[key].modelId) - linkedModel.schema[modelToSave.name] = { + linkedModel.schema[modelToSave._id] = { name: modelToSave.name, type: "link", modelId: modelToSave._id, diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index 273175c2b1..d4e70b3ed4 100644 --- a/packages/server/src/api/controllers/record.js +++ b/packages/server/src/api/controllers/record.js @@ -56,8 +56,8 @@ exports.save = async function(ctx) { const doc = row.doc return { ...doc, - [model.name]: doc[model.name] - ? [...doc[model.name], record._id] + [model._id]: doc[model._id] + ? [...doc[model._id], record._id] : [record._id], } }) diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index 71816f1c78..7805ad251d 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -41,7 +41,7 @@ exports.create = async function(ctx) { const response = await database.post(user) - const masterDb = new CouchDB("clientAppLookup") + const masterDb = new CouchDB("client_app_lookup") const { clientId } = await masterDb.get(appId) // the clientDB needs to store a map of users against the app diff --git a/packages/server/src/api/routes/model.js b/packages/server/src/api/routes/model.js index 10882aa057..00eb46d515 100644 --- a/packages/server/src/api/routes/model.js +++ b/packages/server/src/api/routes/model.js @@ -12,8 +12,7 @@ router authorized(READ_MODEL, ctx => ctx.params.id), modelController.find ) - .post("/api/models", authorized(BUILDER), modelController.create) - // .patch("/api/:instanceId/models", controller.update) + .post("/api/models", authorized(BUILDER), modelController.save) .delete( "/api/models/:modelId/:revId", authorized(BUILDER), From 01d7f80e7b8432eca7df6703f76f8ea59e92856d Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 24 Jun 2020 12:41:26 +0100 Subject: [PATCH 13/20] custom notifications, models + fields keyed by ID --- packages/builder/package.json | 1 - packages/builder/src/App.svelte | 21 +--- .../builder/src/builderStore/store/backend.js | 10 -- .../src/builderStore/store/notifications.js | 14 +++ .../components/common/AppNotification.svelte | 77 ------------ .../common/LinkedRecordSelector.svelte | 18 ++- .../src/components/common/Notification.svelte | 119 ++++++++++++++++++ .../ModelDataTable/LinkedRecord.svelte | 24 ++-- .../ModelDataTable/ModelDataTable.svelte | 2 +- .../modals/CreateEditRecord.svelte | 2 +- .../ModelDataTable/modals/DeleteRecord.svelte | 2 +- .../nav/ModelSetupNav/ModelSetupNav.svelte | 2 +- .../SetupPanel/DeleteWorkflowModal.svelte | 2 +- .../workflow/SetupPanel/SetupPanel.svelte | 2 +- .../WorkflowBuilder/WorkflowBuilder.svelte | 2 +- .../WorkflowList/CreateWorkflowModal.svelte | 2 +- .../WorkflowList/WorkflowList.svelte | 2 +- 17 files changed, 163 insertions(+), 139 deletions(-) create mode 100644 packages/builder/src/builderStore/store/notifications.js delete mode 100644 packages/builder/src/components/common/AppNotification.svelte create mode 100644 packages/builder/src/components/common/Notification.svelte diff --git a/packages/builder/package.json b/packages/builder/package.json index a6988dfd63..41ffe2ba91 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -50,7 +50,6 @@ ] }, "dependencies": { - "@beyonk/svelte-notifications": "^2.0.3", "@budibase/bbui": "^1.8.0", "@budibase/client": "^0.0.32", "@nx-js/compiler-util": "^2.0.0", diff --git a/packages/builder/src/App.svelte b/packages/builder/src/App.svelte index b19b8df5c7..7cf7fb864b 100644 --- a/packages/builder/src/App.svelte +++ b/packages/builder/src/App.svelte @@ -4,30 +4,11 @@ import { Router, basepath } from "@sveltech/routify" import { routes } from "../routify/routes" import { store, initialise } from "builderStore" - import AppNotification, { - showAppNotification, - } from "components/common/AppNotification.svelte" - import { NotificationDisplay } from "@beyonk/svelte-notifications" - - function showErrorBanner() { - showAppNotification({ - status: "danger", - message: - "Whoops! Looks like we're having trouble. Please refresh the page.", - }) - } - - onMount(async () => { - window.addEventListener("error", showErrorBanner) - window.addEventListener("unhandledrejection", showErrorBanner) - }) + import NotificationDisplay from "components/common/Notification.svelte"; $basepath = "/_builder" - - - diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 83c241f818..57cadb365a 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -62,16 +62,6 @@ export const getBackendUiStore = () => { save: async ({ model }) => { const updatedModel = cloneDeep(model) - // // TODO: refactor - // for (let key in updatedModel.schema) { - // const field = updatedModel.schema[key] - // // TODO: use IDs - // if (field.name && field.name !== key) { - // updatedModel.schema[field.name] = field - // delete updatedModel.schema[key] - // } - // } - const SAVE_MODEL_URL = `/api/models` const response = await api.post(SAVE_MODEL_URL, updatedModel) const savedModel = await response.json() diff --git a/packages/builder/src/builderStore/store/notifications.js b/packages/builder/src/builderStore/store/notifications.js new file mode 100644 index 0000000000..cb789b2aef --- /dev/null +++ b/packages/builder/src/builderStore/store/notifications.js @@ -0,0 +1,14 @@ +import { writable } from 'svelte/store' + +export const notificationStore = writable() + +export function send(message, type = 'default', timeout) { + notificationStore.set({ type, message, timeout }) +} + +export const notifier = { + danger: msg => send(msg, "danger"), + warning: msg => send(msg, "warning"), + info: msg => send(msg, "info"), + success: msg => send(msg, "success") +} \ No newline at end of file diff --git a/packages/builder/src/components/common/AppNotification.svelte b/packages/builder/src/components/common/AppNotification.svelte deleted file mode 100644 index 2e8723ab53..0000000000 --- a/packages/builder/src/components/common/AppNotification.svelte +++ /dev/null @@ -1,77 +0,0 @@ - - - diff --git a/packages/builder/src/components/common/LinkedRecordSelector.svelte b/packages/builder/src/components/common/LinkedRecordSelector.svelte index 24c8d8f5d8..bad03f436d 100644 --- a/packages/builder/src/components/common/LinkedRecordSelector.svelte +++ b/packages/builder/src/components/common/LinkedRecordSelector.svelte @@ -8,22 +8,20 @@ export let linked = [] let records = [] + let model = {} let linkedRecords = new Set(linked) $: linked = [...linkedRecords] - $: FIELDS_TO_HIDE = [ - "modelId", - "type", - "_id", - "_rev", - $backendUiStore.selectedModel.name, - modelId - ] + $: FIELDS_TO_HIDE = [$backendUiStore.selectedModel._id] + $: schema = $backendUiStore.selectedModel.schema async function fetchRecords() { const FETCH_RECORDS_URL = `/api/${modelId}/records` const response = await api.get(FETCH_RECORDS_URL) + const modelResponse = await api.get(`/api/models/${modelId}`) + + model = await modelResponse.json() records = await response.json() } @@ -49,9 +47,9 @@ {#each records as record}
linkRecord(record._id)}>
- {#each Object.keys(record).filter(key => !FIELDS_TO_HIDE.includes(key)) as key} + {#each Object.keys(model.schema).filter(key => !FIELDS_TO_HIDE.includes(key)) as key}
- {key} + {model.schema[key].name}

{record[key]}

{/each} diff --git a/packages/builder/src/components/common/Notification.svelte b/packages/builder/src/components/common/Notification.svelte new file mode 100644 index 0000000000..2503db0b8f --- /dev/null +++ b/packages/builder/src/components/common/Notification.svelte @@ -0,0 +1,119 @@ + + +
    + {#each notifications as toast (toast.id)} +
  • +
    {toast.msg}
    +
  • + {/each} +
+ + diff --git a/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte b/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte index 96e611ad27..8c7d064c0b 100644 --- a/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte +++ b/packages/builder/src/components/database/ModelDataTable/LinkedRecord.svelte @@ -5,25 +5,21 @@ import api from "builderStore/api" export let ids = [] - export let header + export let field let records = [] let open = false + let model - $: FIELDS_TO_HIDE = [ - "modelId", - "type", - "_id", - "_rev", - $backendUiStore.selectedModel._id, - $backendUiStore.selectedModel.name, - ] + $: FIELDS_TO_HIDE = [$backendUiStore.selectedModel._id, field.modelId] async function fetchRecords() { const response = await api.post("/api/records/search", { keys: ids, }) + const modelResponse = await api.get(`/api/models/${field.modelId}`) records = await response.json() + model = await modelResponse.json() } $: ids && fetchRecords() @@ -42,15 +38,15 @@ {#if open}
-

{header}

+

{field.name}

{#each records as record}
- {#each Object.keys(record).filter(key => !FIELDS_TO_HIDE.includes(key)) as key} + {#each Object.keys(model.schema).filter(key => !FIELDS_TO_HIDE.includes(key)) as key}
- {key} + {model.schema[key].name}

{record[key]}

{/each} @@ -62,6 +58,10 @@ diff --git a/packages/builder/src/components/common/Notification/NotificationDisplay.svelte b/packages/builder/src/components/common/Notification/NotificationDisplay.svelte new file mode 100644 index 0000000000..cfd39ad068 --- /dev/null +++ b/packages/builder/src/components/common/Notification/NotificationDisplay.svelte @@ -0,0 +1,61 @@ + + +
    + {#each $notificationStore.notifications as notification (notification.id)} +
  • +
    {notification.message}
    + {#if notification.icon} + + {/if} +
  • + {/each} +
+ + From 1f2c1a06aa7da9c878be5b18974488ecdc2d26fd Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 24 Jun 2020 16:12:55 +0100 Subject: [PATCH 15/20] lint :sparkles: --- packages/builder/src/App.svelte | 3 +-- .../src/builderStore/store/notifications.js | 15 +++++++++------ .../Notification/NotificationDisplay.svelte | 11 +++++++---- .../database/ModelDataTable/ModelDataTable.svelte | 6 ++---- .../nav/ModelSetupNav/ModelFieldEditor.svelte | 5 ++++- 5 files changed, 23 insertions(+), 17 deletions(-) diff --git a/packages/builder/src/App.svelte b/packages/builder/src/App.svelte index 76ef32a669..d10c04727f 100644 --- a/packages/builder/src/App.svelte +++ b/packages/builder/src/App.svelte @@ -4,11 +4,10 @@ import { Router, basepath } from "@sveltech/routify" import { routes } from "../routify/routes" import { store, initialise } from "builderStore" - import NotificationDisplay from "components/common/Notification/NotificationDisplay.svelte"; + import NotificationDisplay from "components/common/Notification/NotificationDisplay.svelte" $basepath = "/_builder" - diff --git a/packages/builder/src/builderStore/store/notifications.js b/packages/builder/src/builderStore/store/notifications.js index 201e13e4b9..85e708e92a 100644 --- a/packages/builder/src/builderStore/store/notifications.js +++ b/packages/builder/src/builderStore/store/notifications.js @@ -1,13 +1,16 @@ -import { writable } from 'svelte/store' +import { writable } from "svelte/store" import { generate } from "shortid" export const notificationStore = writable({ - notifications: [] + notifications: [], }) -export function send(message, type = 'default') { +export function send(message, type = "default") { notificationStore.update(state => { - state.notifications = [...state.notifications, { id: generate(), type, message }] + state.notifications = [ + ...state.notifications, + { id: generate(), type, message }, + ] return state }) } @@ -16,5 +19,5 @@ export const notifier = { danger: msg => send(msg, "danger"), warning: msg => send(msg, "warning"), info: msg => send(msg, "info"), - success: msg => send(msg, "success") -} \ No newline at end of file + success: msg => send(msg, "success"), +} diff --git a/packages/builder/src/components/common/Notification/NotificationDisplay.svelte b/packages/builder/src/components/common/Notification/NotificationDisplay.svelte index cfd39ad068..4abcffef57 100644 --- a/packages/builder/src/components/common/Notification/NotificationDisplay.svelte +++ b/packages/builder/src/components/common/Notification/NotificationDisplay.svelte @@ -16,17 +16,20 @@ $: if ($notificationStore.notifications.length) { setTimeout(() => { notificationStore.update(state => { - state.notifications.shift(); + state.notifications.shift() state.notifications = state.notifications - return state; + return state }) }, timeout) - } + }
    {#each $notificationStore.notifications as notification (notification.id)} -
  • +
  • {notification.message}
    {#if notification.icon} diff --git a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte index 896d3c39b7..d10c56799b 100644 --- a/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte +++ b/packages/builder/src/components/database/ModelDataTable/ModelDataTable.svelte @@ -132,11 +132,9 @@ {#each headers as header}
{/each} diff --git a/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte b/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte index d8af2b19cf..d9a61508b3 100644 --- a/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte +++ b/packages/builder/src/components/nav/ModelSetupNav/ModelFieldEditor.svelte @@ -78,7 +78,10 @@ {:else if field.type === 'link'}
-
{row[header]} + {#if Array.isArray(row[header])} + + {:else} + {row[header] || 0} + {/if} +
Edit{header}{$backendUiStore.selectedModel.schema[header].name}
- {#if Array.isArray(row[header])} - - {:else}{row[header] || 0}{/if} + {#if schema[header].type === "link"} + + {:else} + {row[header]} + {/if}
- {#if schema[header].type === "link"} + {#if schema[header].type === 'link'} - {:else} - {row[header]} - {/if} + {:else}{row[header]}{/if}