From 8afbf12021db448f8db1c7ce9aa3b11b753a8d0d Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Tue, 24 Mar 2020 16:12:46 +0000 Subject: [PATCH 1/9] allow all conde snippets to be either blocks or expressions --- packages/core/src/actionsApi/initialise.js | 4 +-- packages/core/src/common/compileCode.js | 29 +++++++++---------- packages/core/src/indexApi/aggregates.js | 4 +-- packages/core/src/indexing/evaluate.js | 6 ++-- packages/core/src/indexing/sharding.js | 2 +- packages/core/src/recordApi/validate.js | 4 +-- packages/core/src/templateApi/validate.js | 6 ++-- .../core/src/templateApi/validateAggregate.js | 2 +- 8 files changed, 28 insertions(+), 29 deletions(-) diff --git a/packages/core/src/actionsApi/initialise.js b/packages/core/src/actionsApi/initialise.js index 6df15994dd..90b27ac2b1 100644 --- a/packages/core/src/actionsApi/initialise.js +++ b/packages/core/src/actionsApi/initialise.js @@ -9,7 +9,7 @@ import { reduce, find, } from "lodash/fp" -import { compileExpression, compileCode } from "../common/compileCode" +import { compileCode } from "../common/compileCode" import { $ } from "../common" import { _executeAction } from "./execute" import { BadRequestError, NotFoundError } from "../common/errors" @@ -49,7 +49,7 @@ const subscribeTriggers = ( const shouldRunTrigger = (trigger, eventContext) => { if (!trigger.condition) return true - const shouldRun = compileExpression(trigger.condition) + const shouldRun = compileCode(trigger.condition) return shouldRun({ context: eventContext }) } diff --git a/packages/core/src/common/compileCode.js b/packages/core/src/common/compileCode.js index 3447d45b5c..8c570d626f 100644 --- a/packages/core/src/common/compileCode.js +++ b/packages/core/src/common/compileCode.js @@ -1,13 +1,25 @@ import { - compileExpression as cExp, compileCode as cCode, } from "@nx-js/compiler-util" +import { includes } from "lodash/fp" + export const compileCode = code => { let func + let safeCode + + if (includes("return ")(code)) { + safeCode = code + } else { + let trimmed = code.trim() + trimmed = trimmed.endsWith(";") + ? trimmed.substring(0, trimmed.length - 1) + : trimmed + safeCode = `return (${trimmed})` + } try { - func = cCode(code) + func = cCode(safeCode) } catch (e) { e.message = `Error compiling code : ${code} : ${e.message}` throw e @@ -15,16 +27,3 @@ export const compileCode = code => { return func } - -export const compileExpression = code => { - let func - - try { - func = cExp(code) - } catch (e) { - e.message = `Error compiling expression : ${code} : ${e.message}` - throw e - } - - return func -} diff --git a/packages/core/src/indexApi/aggregates.js b/packages/core/src/indexApi/aggregates.js index 94344d6ad4..178f37f45a 100644 --- a/packages/core/src/indexApi/aggregates.js +++ b/packages/core/src/indexApi/aggregates.js @@ -1,5 +1,5 @@ import { has, isNumber, isUndefined } from "lodash/fp" -import { compileExpression, compileCode } from "@nx-js/compiler-util" +import { compileCode } from "../common/compileCode" import { safeKey, apiWrapper, events, isNonEmptyString } from "../common" import { iterateIndex } from "../indexing/read" import { @@ -147,7 +147,7 @@ const applyItemToAggregateResult = (indexNode, result, item) => { const thisGroupResult = result[aggGroup.name] if (isNonEmptyString(aggGroup.condition)) { - if (!compileExpression(aggGroup.condition)({ record: item })) { + if (!compileCode(aggGroup.condition)({ record: item })) { continue } } diff --git a/packages/core/src/indexing/evaluate.js b/packages/core/src/indexing/evaluate.js index db7f0d0236..ec9180ffbc 100644 --- a/packages/core/src/indexing/evaluate.js +++ b/packages/core/src/indexing/evaluate.js @@ -1,5 +1,5 @@ -import { compileExpression, compileCode } from "@nx-js/compiler-util" -import { isUndefined, keys, cloneDeep, isFunction } from "lodash/fp" +import { compileCode } from "../common/compileCode" +import { isUndefined, keys, cloneDeep, isFunction, includes } from "lodash/fp" import { defineError } from "../common" export const filterEval = "FILTER_EVALUATE" @@ -16,7 +16,7 @@ const getEvaluateResult = () => ({ result: null, }) -export const compileFilter = index => compileExpression(index.filter) +export const compileFilter = index => compileCode(index.filter) export const compileMap = index => compileCode(index.map) diff --git a/packages/core/src/indexing/sharding.js b/packages/core/src/indexing/sharding.js index a9b5ded1d7..0b8eaaf97e 100644 --- a/packages/core/src/indexing/sharding.js +++ b/packages/core/src/indexing/sharding.js @@ -1,4 +1,4 @@ -import { compileCode } from "@nx-js/compiler-util" +import { compileCode } from "../common/compileCode" import { filter, includes, map, last } from "lodash/fp" import { getActualKeyOfParent, diff --git a/packages/core/src/recordApi/validate.js b/packages/core/src/recordApi/validate.js index b2949b5bf2..052a92680e 100644 --- a/packages/core/src/recordApi/validate.js +++ b/packages/core/src/recordApi/validate.js @@ -1,5 +1,5 @@ import { map, reduce, filter, isEmpty, flatten, each } from "lodash/fp" -import { compileExpression } from "@nx-js/compiler-util" +import { compileCode } from "../common/compileCode" import _ from "lodash" import { getExactNodeForKey } from "../templateApi/hierarchy" import { validateFieldParse, validateTypeConstraints } from "../types" @@ -35,7 +35,7 @@ const validateAllTypeConstraints = async (record, recordNode, context) => { const runRecordValidationRules = (record, recordNode) => { const runValidationRule = rule => { - const isValid = compileExpression(rule.expressionWhenValid) + const isValid = compileCode(rule.expressionWhenValid) const expressionContext = { record, _ } return isValid(expressionContext) ? { valid: true } diff --git a/packages/core/src/templateApi/validate.js b/packages/core/src/templateApi/validate.js index 1b3afa84d1..14e4edbba9 100644 --- a/packages/core/src/templateApi/validate.js +++ b/packages/core/src/templateApi/validate.js @@ -11,7 +11,7 @@ import { isEmpty, has, } from "lodash/fp" -import { compileExpression, compileCode } from "@nx-js/compiler-util" +import { compileCode } from "../common/compileCode" import { $, isSomething, @@ -73,7 +73,7 @@ const aggregateGroupRules = [ "condition does not compile", a => isEmpty(a.condition) || - executesWithoutException(() => compileExpression(a.condition)) + executesWithoutException(() => compileCode(a.condition)) ), ] @@ -196,7 +196,7 @@ const triggerRules = actions => [ t => { if (!t.condition) return true try { - compileExpression(t.condition) + compileCode(t.condition) return true } catch (_) { return false diff --git a/packages/core/src/templateApi/validateAggregate.js b/packages/core/src/templateApi/validateAggregate.js index 1e790d624a..e0fc4e9a94 100644 --- a/packages/core/src/templateApi/validateAggregate.js +++ b/packages/core/src/templateApi/validateAggregate.js @@ -1,5 +1,5 @@ import { flatten, map, isEmpty } from "lodash/fp" -import { compileCode } from "@nx-js/compiler-util" +import { compileCode } from "../common/compileCode" import { isNonEmptyString, executesWithoutException, $ } from "../common" import { applyRuleSet, makerule } from "../common/validationCommon" From e20bb608dd4407a7a4fefac92acab8a54a6fdfbc Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Wed, 25 Mar 2020 08:56:34 +0000 Subject: [PATCH 2/9] bugfix: nav items text background grey on windows --- packages/builder/src/nav/DatabasesList.svelte | 1 + packages/builder/src/nav/UsersList.svelte | 1 + packages/builder/src/userInterface/ComponentsPaneSwitcher.svelte | 1 + packages/builder/src/userInterface/PagesList.svelte | 1 + 4 files changed, 4 insertions(+) diff --git a/packages/builder/src/nav/DatabasesList.svelte b/packages/builder/src/nav/DatabasesList.svelte index a1406745a8..c58ac23c84 100644 --- a/packages/builder/src/nav/DatabasesList.svelte +++ b/packages/builder/src/nav/DatabasesList.svelte @@ -59,6 +59,7 @@ font-size: 0.8rem; outline: none; cursor: pointer; + background: rgba(0,0,0,0); } .active { diff --git a/packages/builder/src/nav/UsersList.svelte b/packages/builder/src/nav/UsersList.svelte index fa6925e6e2..4654c0dd5e 100644 --- a/packages/builder/src/nav/UsersList.svelte +++ b/packages/builder/src/nav/UsersList.svelte @@ -65,6 +65,7 @@ font-size: 0.8rem; outline: none; cursor: pointer; + background: rgba(0,0,0,0); } .active { diff --git a/packages/builder/src/userInterface/ComponentsPaneSwitcher.svelte b/packages/builder/src/userInterface/ComponentsPaneSwitcher.svelte index 12c0206407..e86aa4800d 100644 --- a/packages/builder/src/userInterface/ComponentsPaneSwitcher.svelte +++ b/packages/builder/src/userInterface/ComponentsPaneSwitcher.svelte @@ -75,6 +75,7 @@ font-weight: 400; text-transform: uppercase; color: var(--secondary60); + background: rgba(0,0,0,0); } .switcher > .selected { diff --git a/packages/builder/src/userInterface/PagesList.svelte b/packages/builder/src/userInterface/PagesList.svelte index 1c57a00c41..0fd7718ef3 100644 --- a/packages/builder/src/userInterface/PagesList.svelte +++ b/packages/builder/src/userInterface/PagesList.svelte @@ -70,6 +70,7 @@ font-size: 0.8rem; outline: none; cursor: pointer; + background: rgba(0,0,0,0); } .active { From bcd8b602b399a0a15aed3235b16ee84bfecf62ea Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Wed, 25 Mar 2020 10:45:11 +0000 Subject: [PATCH 3/9] collection name uses nodeId by default, and field is removed --- packages/builder/src/database/ModelView.svelte | 6 +----- packages/core/src/templateApi/createNodes.js | 5 +++-- packages/core/test/templateApi.constructHeirarchy.spec.js | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/builder/src/database/ModelView.svelte b/packages/builder/src/database/ModelView.svelte index 4d34d35c59..8bdefb32fc 100644 --- a/packages/builder/src/database/ModelView.svelte +++ b/packages/builder/src/database/ModelView.svelte @@ -101,12 +101,8 @@

Settings

- -
- {#if !record.isSingle} - - {/if} +
diff --git a/packages/core/src/templateApi/createNodes.js b/packages/core/src/templateApi/createNodes.js index 113c6ff0ea..804445b4e9 100644 --- a/packages/core/src/templateApi/createNodes.js +++ b/packages/core/src/templateApi/createNodes.js @@ -160,16 +160,17 @@ export const getNewRootLevel = () => }) const _getNewRecordTemplate = (parent, name, createDefaultIndex, isSingle) => { + const nodeId = getNodeId(parent) const node = constructNode(parent, { name, type: "record", fields: [], children: [], validationRules: [], - nodeId: getNodeId(parent), + nodeId: nodeId, indexes: [], estimatedRecordCount: isRecord(parent) ? 500 : 1000000, - collectionName: "", + collectionName: (nodeId || "").toString(), isSingle, }) diff --git a/packages/core/test/templateApi.constructHeirarchy.spec.js b/packages/core/test/templateApi.constructHeirarchy.spec.js index 44991ed403..1435f5dbec 100644 --- a/packages/core/test/templateApi.constructHeirarchy.spec.js +++ b/packages/core/test/templateApi.constructHeirarchy.spec.js @@ -25,7 +25,7 @@ describe("hierarchy node creation", () => { expect(record.validationRules).toEqual([]) expect(record.indexes).toEqual([]) expect(record.parent()).toBe(root) - expect(record.collectionName).toBe("") + expect(record.collectionName).toBe(record.nodeId.toString()) expect(record.estimatedRecordCount).toBe(1000000) expect(record.isSingle).toBe(false) From 7274d44fd982b921d94a0df0963bb400fe0e062e Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Wed, 25 Mar 2020 11:11:28 +0000 Subject: [PATCH 4/9] canDelete methods for index and record --- .../core/src/templateApi/canDeleteRecord.js | 7 +++-- .../core/test/templateApi.canDelete.spec.js | 29 +++++++++++++++++-- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/core/src/templateApi/canDeleteRecord.js b/packages/core/src/templateApi/canDeleteRecord.js index c438bfb58d..1601afa0cf 100644 --- a/packages/core/src/templateApi/canDeleteRecord.js +++ b/packages/core/src/templateApi/canDeleteRecord.js @@ -20,8 +20,7 @@ export const canDeleteRecord = recordNode => { ]) const belongsToAncestor = i => - ancestors.includes(i.parent()) - + ancestors.includes(i.parent()) const errorsForNode = node => { const errorsThisNode = $(flatHierarchy, [ @@ -40,5 +39,7 @@ export const canDeleteRecord = recordNode => { return errorsThisNode } - return errorsForNode(recordNode) + const errors = errorsForNode(recordNode) + + return { errors, canDelete: errors.length === 0 } } \ No newline at end of file diff --git a/packages/core/test/templateApi.canDelete.spec.js b/packages/core/test/templateApi.canDelete.spec.js index 69fff08f7a..8751068ba3 100644 --- a/packages/core/test/templateApi.canDelete.spec.js +++ b/packages/core/test/templateApi.canDelete.spec.js @@ -2,6 +2,7 @@ import { setupApphierarchy, basicAppHierarchyCreator_WithFields, stubEventHandler, + basicAppHierarchyCreator_WithFields_AndIndexes, } from "./specHelpers" import { canDeleteIndex } from "../src/templateApi/canDeleteIndex" import { canDeleteRecord } from "../src/templateApi/canDeleteRecord" @@ -49,15 +50,37 @@ describe("canDeleteIndex", () => { describe("canDeleteRecord", () => { - it("should return no errors when deletion is valid", () => { + it("should return no errors when deletion is valid", async () => { const { appHierarchy } = await setupApphierarchy( basicAppHierarchyCreator_WithFields ) - appHierarchy.root. - const result = canDeleteIndex(appHierarchy.customerRecord) + appHierarchy.root.indexes = appHierarchy.root.indexes.filter(i => !i.allowedRecordNodeIds.includes(appHierarchy.customerRecord.nodeId)) + const result = canDeleteRecord(appHierarchy.customerRecord) expect(result.canDelete).toBe(true) expect(result.errors).toEqual([]) }) + + it("should return errors when record is referenced by hierarchal index", async () => { + const { appHierarchy } = await setupApphierarchy( + basicAppHierarchyCreator_WithFields + ) + + const result = canDeleteRecord(appHierarchy.customerRecord) + + expect(result.canDelete).toBe(false) + expect(result.errors.some(e => e.includes("customer_index"))).toBe(true) + }) + + it("should return errors when record has a child which cannot be deleted", async () => { + const { appHierarchy } = await setupApphierarchy( + basicAppHierarchyCreator_WithFields_AndIndexes + ) + + const result = canDeleteRecord(appHierarchy.customerRecord) + + expect(result.canDelete).toBe(false) + expect(result.errors.some(e => e.includes("Outstanding Invoices"))).toBe(true) + }) }) \ No newline at end of file From 9e6e471a383ca27db3d10cf46ced4fc72511eb76 Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Wed, 25 Mar 2020 11:18:13 +0000 Subject: [PATCH 5/9] bugfix: dont put 'IsNew' into index --- packages/core/src/indexing/evaluate.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/core/src/indexing/evaluate.js b/packages/core/src/indexing/evaluate.js index ec9180ffbc..aaa2e6f44a 100644 --- a/packages/core/src/indexing/evaluate.js +++ b/packages/core/src/indexing/evaluate.js @@ -46,6 +46,9 @@ export const mapRecord = (record, index) => { if (isFunction(mapped[key])) { delete mapped[key] } + if (key === "IsNew") { + delete mapped.IsNew + } } mapped.key = record.key From f3a9d138d7e279117662e134e3a8cfe68cbe2f20 Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Wed, 25 Mar 2020 11:31:58 +0000 Subject: [PATCH 6/9] default index name - dont use collectionName (collectionName is now a number) --- packages/builder/src/builderStore/store/backend.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index ded766e755..f6051dd4ba 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -183,7 +183,7 @@ export const saveCurrentNode = store => () => { const defaultIndex = templateApi(state.hierarchy).getNewIndexTemplate( cloned.parent() ) - defaultIndex.name = `all_${cloned.collectionName}` + defaultIndex.name = `all_${cloned.name}` defaultIndex.allowedRecordNodeIds = [cloned.nodeId] } From 5af53922ed4a6958802ab2623bc9f63e4a98100f Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Wed, 25 Mar 2020 12:38:04 +0000 Subject: [PATCH 7/9] evict packages from cache on SaveBackend --- .../builder/src/builderStore/store/backend.js | 2 +- packages/server/middleware/routers.js | 1 + packages/server/utilities/createAppPackage.js | 18 +++++++++++++++--- packages/server/utilities/masterAppInternal.js | 8 +++++++- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index f6051dd4ba..e93fbe4733 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -183,7 +183,7 @@ export const saveCurrentNode = store => () => { const defaultIndex = templateApi(state.hierarchy).getNewIndexTemplate( cloned.parent() ) - defaultIndex.name = `all_${cloned.name}` + defaultIndex.name = `all_${cloned.name}s` defaultIndex.allowedRecordNodeIds = [cloned.nodeId] } diff --git a/packages/server/middleware/routers.js b/packages/server/middleware/routers.js index 00e2deff9c..b41fdeeb52 100644 --- a/packages/server/middleware/routers.js +++ b/packages/server/middleware/routers.js @@ -171,6 +171,7 @@ module.exports = (config, app) => { ctx.request.body.appDefinition, ctx.request.body.accessLevels ) + ctx.master.deleteLatestPackageFromCache(ctx.params.appname) ctx.response.status = StatusCodes.OK }) .post("/_builder/api/:appname/pages/:pageName", async ctx => { diff --git a/packages/server/utilities/createAppPackage.js b/packages/server/utilities/createAppPackage.js index 3aaa6ce09f..9a993a4ae4 100644 --- a/packages/server/utilities/createAppPackage.js +++ b/packages/server/utilities/createAppPackage.js @@ -5,12 +5,16 @@ const { getRuntimePackageDirectory } = require("../utilities/runtimePackages") const injectPlugins = require("./injectedPlugins") const { cwd } = require("process") +const appDefinitionPath = appPath => join(appPath, "appDefinition.json") +const pluginsPath = appPath => join(appPath, "plugins.js") +const accessLevelsPath = appPath => join(appPath, "access_levels.json") + const createAppPackage = (context, appPath) => { - const appDefModule = require(join(appPath, "appDefinition.json")) + const appDefModule = require(appDefinitionPath(appPath)) - const pluginsModule = require(join(appPath, "plugins.js")) + const pluginsModule = require(pluginsPath(appPath)) - const accessLevels = require(join(appPath, "access_levels.json")) + const accessLevels = require(accessLevelsPath(appPath)) return { appDefinition: appDefModule, @@ -87,3 +91,11 @@ module.exports.applictionVersionPackage = async ( await injectPlugins(pkg, context.master, appname, instanceKey) return pkg } + +module.exports.deleteCachedPackage = (context, appname, versionId) => { + const appPath = applictionVersionPath(context, appname, versionId) + + delete require.cache[resolve(appDefinitionPath(appPath))] + delete require.cache[resolve(pluginsPath(appPath))] + delete require.cache[resolve(accessLevelsPath(appPath))] +} diff --git a/packages/server/utilities/masterAppInternal.js b/packages/server/utilities/masterAppInternal.js index 88a7bdfb75..e02862f61c 100644 --- a/packages/server/utilities/masterAppInternal.js +++ b/packages/server/utilities/masterAppInternal.js @@ -11,8 +11,9 @@ const { masterAppPackage, applictionVersionPackage, applictionVersionPublicPaths, + deleteCachedPackage, } = require("../utilities/createAppPackage") -const { determineVersionId } = require("./runtimePackages") +const { determineVersionId, LATEST_VERSIONID } = require("./runtimePackages") const isMaster = appname => appname === "_master" @@ -345,6 +346,10 @@ module.exports = async context => { await bb.recordApi.save(userInMaster) } + const deleteLatestPackageFromCache = (appname) => { + deleteCachedPackage(context, appname, LATEST_VERSIONID) + } + const listApplications = () => values(applications) return { @@ -364,5 +369,6 @@ module.exports = async context => { getFullAccessApiForInstanceId, getFullAccessApiForMaster, getApplicationWithInstances, + deleteLatestPackageFromCache, } } From 0c9d6abbf0e0371cb8849e8759f54e474ee3a9b1 Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Wed, 25 Mar 2020 16:10:39 +0000 Subject: [PATCH 8/9] bugfix: user not getting created --- .../src/database/ModelDataTable/modals/CreateUser.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/builder/src/database/ModelDataTable/modals/CreateUser.svelte b/packages/builder/src/database/ModelDataTable/modals/CreateUser.svelte index cc7e00d1d9..7382c6eab8 100644 --- a/packages/builder/src/database/ModelDataTable/modals/CreateUser.svelte +++ b/packages/builder/src/database/ModelDataTable/modals/CreateUser.svelte @@ -20,7 +20,7 @@ const response = await api.createUser( password, { - username, + name:username, accessLevels, enabled: true, temporaryAccessId: "" From 3cc5773fdea3a2e145052f0d3cd899a1646dbd00 Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Wed, 25 Mar 2020 16:57:04 +0000 Subject: [PATCH 9/9] validation for delete index and records --- .../builder/src/builderStore/store/backend.js | 23 +++++++++++++++---- packages/builder/src/common/ErrorsBox.svelte | 21 ++++------------- packages/builder/src/common/core.js | 2 ++ .../builder/src/database/ActionsHeader.svelte | 3 --- .../builder/src/database/IndexView.svelte | 6 ++++- .../builder/src/database/ModelView.svelte | 6 +++++ .../core/src/templateApi/canDeleteIndex.js | 4 ++-- .../core/src/templateApi/canDeleteRecord.js | 2 +- 8 files changed, 40 insertions(+), 27 deletions(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index e93fbe4733..153cba784f 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -13,6 +13,8 @@ import { constructHierarchy, templateApi, isIndex, + canDeleteIndex, + canDeleteRecord } from "../../common/core" export const getBackendUiStore = () => { @@ -202,14 +204,27 @@ export const deleteCurrentNode = store => () => { ? state.hierarchy.children.find(node => node !== state.currentNode) : nodeToDelete.parent() - const recordOrIndexKey = hierarchyFunctions.isRecord(nodeToDelete) ? "children" : "indexes"; + const isRecord = hierarchyFunctions.isRecord(nodeToDelete) + + const check = isRecord + ? canDeleteRecord(nodeToDelete) + : canDeleteIndex(nodeToDelete) + + if (!check.canDelete) { + state.errors = check.errors.map(e => ({ error: e })) + return state + } + + const recordOrIndexKey = isRecord ? "children" : "indexes" // remove the selected record or index - nodeToDelete.parent()[recordOrIndexKey] = remove( - nodeToDelete.parent()[recordOrIndexKey], - node => node.nodeId === nodeToDelete.nodeId + const newCollection = remove( + node => node.nodeId === nodeToDelete.nodeId, + nodeToDelete.parent()[recordOrIndexKey] ) + nodeToDelete.parent()[recordOrIndexKey] = newCollection + state.errors = [] saveBackend(state) return state diff --git a/packages/builder/src/common/ErrorsBox.svelte b/packages/builder/src/common/ErrorsBox.svelte index 9ddea77a49..117f3aae5a 100644 --- a/packages/builder/src/common/ErrorsBox.svelte +++ b/packages/builder/src/common/ErrorsBox.svelte @@ -5,25 +5,14 @@ {#if hasErrors} -
+
{#each errors as error} -
+
{error.field ? `${error.field}: ` : ''}{error.error}
{/each} -
+
+ + {/if} - diff --git a/packages/builder/src/common/core.js b/packages/builder/src/common/core.js index dbdd186aa3..2274d9d028 100644 --- a/packages/builder/src/common/core.js +++ b/packages/builder/src/common/core.js @@ -9,6 +9,8 @@ import { find, filter, keyBy, flatten, map } from "lodash/fp" import { generateSchema } from "../../../core/src/indexing/indexSchemaCreator" import { generate } from "shortid" +export { canDeleteIndex } from "../../../core/src/templateApi/canDeleteIndex" +export { canDeleteRecord } from "../../../core/src/templateApi/canDeleteRecord" export { userWithFullAccess } from "../../../core/src/index" export const pipe = common.$ diff --git a/packages/builder/src/database/ActionsHeader.svelte b/packages/builder/src/database/ActionsHeader.svelte index c763abc359..f012bd2bb3 100644 --- a/packages/builder/src/database/ActionsHeader.svelte +++ b/packages/builder/src/database/ActionsHeader.svelte @@ -31,9 +31,6 @@
- {#if $store.errors && $store.errors.length > 0} - - {/if}