From 84d145026ba7c89d873c608467aa0c53787a6cb6 Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Thu, 2 Apr 2020 06:21:52 +0100 Subject: [PATCH 1/4] bugfix: database upgrade broken when field added --- packages/core/src/transactions/execute.js | 12 +++++-- .../core/test/templateApi.upgradeData.spec.js | 36 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/core/src/transactions/execute.js b/packages/core/src/transactions/execute.js index 54bf019463..9b90a66041 100644 --- a/packages/core/src/transactions/execute.js +++ b/packages/core/src/transactions/execute.js @@ -44,18 +44,22 @@ import { } from "../templateApi/hierarchy" import { getRecordInfo } from "../recordApi/recordInfo" import { getIndexDir } from "../indexApi/getIndexDir" +import { _deleteIndex } from "../indexApi/delete" import { initialiseIndex } from "../indexing/initialiseIndex" export const executeTransactions = app => async transactions => { const recordsByShard = mappedRecordsByIndexShard(app.hierarchy, transactions) for (const shard of keys(recordsByShard)) { - if (recordsByShard[shard].isRebuild) + if (recordsByShard[shard].isRebuild) { + if (await app.datastore.exists(shard)) + await app.datastore.deleteFile(shard) await initialiseIndex( app.datastore, getParentKey(recordsByShard[shard].indexDir), recordsByShard[shard].indexNode ) + } await applyToShard( app.hierarchy, app.datastore, @@ -76,7 +80,11 @@ const mappedRecordsByIndexShard = (hierarchy, transactions) => { const indexBuild = getBuildIndexTransactionsByShard(hierarchy, transactions) - const toRemove = [...deletes, ...updates.toRemove, ...indexBuild.toRemove] + const toRemove = [ + ...deletes, + ...updates.toRemove, + ...indexBuild.toRemove, + ] const toWrite = [...created, ...updates.toWrite, ...indexBuild.toWrite] diff --git a/packages/core/test/templateApi.upgradeData.spec.js b/packages/core/test/templateApi.upgradeData.spec.js index 945c5e0f43..8118180121 100644 --- a/packages/core/test/templateApi.upgradeData.spec.js +++ b/packages/core/test/templateApi.upgradeData.spec.js @@ -240,6 +240,40 @@ describe("upgradeData", () => { }) +it("should rebuild affected index when field is removed", async () => { + const { oldSetup, newSetup, records } = await configure() + newSetup.contact.fields = newSetup.contact.fields.filter(f => f.name !== "status") + + let itemsInIndex = await _listItems(oldSetup.app, "/contact_index") + expect(itemsInIndex.length).toBe(2) + expect(itemsInIndex[0].status).toBeDefined() + expect(itemsInIndex[0].status).toBe(records.contact1.status) + + await upgradeData(oldSetup.app)(newSetup.root) + + itemsInIndex = await _listItems(newSetup.app, "/contact_index") + expect(itemsInIndex.length).toBe(2) + expect(itemsInIndex[0].status).toBeUndefined() +}) + +it("should rebuild affected index when field is added", async () => { + const { oldSetup, newSetup, records } = await configure() + + const aliveField = newSetup.templateApi.getNewField("string") + aliveField.name = "isalive" + newSetup.templateApi.addField(newSetup.contact, aliveField) + + let itemsInIndex = await _listItems(oldSetup.app, "/contact_index") + expect(itemsInIndex.length).toBe(2) + expect(itemsInIndex[0].isalive).toBeUndefined() + + await upgradeData(oldSetup.app)(newSetup.root) + + itemsInIndex = await _listItems(newSetup.app, "/contact_index") + expect(itemsInIndex.length).toBe(2) + expect(itemsInIndex[0].isalive).toBe(null) +}) + const configure = async () => { const oldSetup = await setup() @@ -256,8 +290,10 @@ const configure = async () => { const createSomeRecords = async recordApi => { const contact1 = recordApi.getNew("/contacts", "contact") contact1.name = "bobby" + contact1.status = "New" const contact2 = recordApi.getNew("/contacts", "contact") contact2.name = "poppy" + contact2.status = "Complete" await recordApi.save(contact1) await recordApi.save(contact2) From ecc649180f7bfb56ed459b3395ceb9c48ea3c12b Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Thu, 2 Apr 2020 06:29:31 +0100 Subject: [PATCH 2/4] better naming of default child view --- packages/builder/src/builderStore/store/backend.js | 5 ++++- packages/core/src/templateApi/hierarchy.js | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/builder/src/builderStore/store/backend.js b/packages/builder/src/builderStore/store/backend.js index 65f012e34c..9f6eb25d63 100644 --- a/packages/builder/src/builderStore/store/backend.js +++ b/packages/builder/src/builderStore/store/backend.js @@ -198,7 +198,10 @@ export const saveCurrentNode = store => () => { const defaultIndex = templateApi(state.hierarchy).getNewIndexTemplate( cloned.parent() ) - defaultIndex.name = `all_${cloned.name}s` + defaultIndex.name = hierarchyFunctions.isTopLevelIndex(cloned) + ? `all_${cloned.name}s` + : `${cloned.parent().name}_${cloned.name}s` + defaultIndex.allowedRecordNodeIds = [cloned.nodeId] } diff --git a/packages/core/src/templateApi/hierarchy.js b/packages/core/src/templateApi/hierarchy.js index 6136a7c38b..25e5162ff0 100644 --- a/packages/core/src/templateApi/hierarchy.js +++ b/packages/core/src/templateApi/hierarchy.js @@ -279,4 +279,6 @@ export default { fieldReversesReferenceToNode, fieldReversesReferenceToIndex, getFlattenedHierarchy, + isTopLevelIndex, + isTopLevelRecord, } From 5209c6443ca424863edbc433a1365ad010b092b4 Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Thu, 2 Apr 2020 06:30:20 +0100 Subject: [PATCH 3/4] datatable: terminology updated: index > view --- .../materialdesign-components/src/Templates/indexDatatable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/materialdesign-components/src/Templates/indexDatatable.js b/packages/materialdesign-components/src/Templates/indexDatatable.js index 8c0ba95b47..f242e7d8d6 100644 --- a/packages/materialdesign-components/src/Templates/indexDatatable.js +++ b/packages/materialdesign-components/src/Templates/indexDatatable.js @@ -1,6 +1,6 @@ export default ({ indexes, helpers }) => indexes.map(i => ({ - name: `Table based on index: ${i.name} `, + name: `Table based on view: ${i.name} `, props: tableProps( i, helpers.indexSchema(i).filter(c => !excludedColumns.includes(c.name)) From f771db5915335c88d7b12bb1fb306339e8076f9d Mon Sep 17 00:00:00 2001 From: Michael Shanks Date: Thu, 2 Apr 2020 06:55:11 +0100 Subject: [PATCH 4/4] bugfix: records&indexs badly named in UI (due to previous collectionName change) --- .../builder/src/accessLevels/AccessLevelView.svelte | 6 ++++-- packages/builder/src/common/core.js | 1 + packages/core/src/templateApi/createNodes.js | 6 ++++++ packages/core/src/templateApi/hierarchy.js | 6 ++++++ .../core/test/templateApi.constructHeirarchy.spec.js | 12 ++++++++++++ .../src/Templates/recordForm.js | 2 +- 6 files changed, 30 insertions(+), 3 deletions(-) diff --git a/packages/builder/src/accessLevels/AccessLevelView.svelte b/packages/builder/src/accessLevels/AccessLevelView.svelte index e5423db018..9936fba566 100644 --- a/packages/builder/src/accessLevels/AccessLevelView.svelte +++ b/packages/builder/src/accessLevels/AccessLevelView.svelte @@ -5,7 +5,7 @@ import ButtonGroup from "../common/ButtonGroup.svelte" import Button from "../common/Button.svelte" import ActionButton from "../common/ActionButton.svelte" - import { validateAccessLevels } from "../common/core" + import { validateAccessLevels, nodeNameFromNodeKey } from "../common/core" import ErrorsBox from "../common/ErrorsBox.svelte" export let level @@ -38,7 +38,9 @@ ) const getPermissionName = perm => - perm.nodeKey ? `${perm.type} - ${perm.nodeKey}` : perm.type + perm.nodeKey + ? `${perm.type} - ${nodeNameFromNodeKey(hierarchy, perm.nodeKey)}` + : perm.type const save = () => { const newLevels = isNew diff --git a/packages/builder/src/common/core.js b/packages/builder/src/common/core.js index 78be9aaa4b..3304b00231 100644 --- a/packages/builder/src/common/core.js +++ b/packages/builder/src/common/core.js @@ -79,6 +79,7 @@ export const getPotentialReferenceIndexes = (hierarchy, record) => export const isIndex = hierarchyFunctions.isIndex export const isRecord = hierarchyFunctions.isRecord +export const nodeNameFromNodeKey = hierarchyFunctions.nodeNameFromNodeKey export const getDefaultTypeOptions = type => !type ? {} : allTypes[type].getDefaultOptions() diff --git a/packages/core/src/templateApi/createNodes.js b/packages/core/src/templateApi/createNodes.js index 804445b4e9..a9a45617a2 100644 --- a/packages/core/src/templateApi/createNodes.js +++ b/packages/core/src/templateApi/createNodes.js @@ -48,6 +48,11 @@ const nodeKeyMaker = node => () => [defaultCase, n => joinKey(node.parent().nodeKey(), n.name)] )(node) +const nodeNameMaker = node => () => + isRoot(node) + ? "/" + : joinKey(node.parent().nodeName(), node.name) + const validate = parent => node => { if ( isIndex(node) && @@ -71,6 +76,7 @@ const validate = parent => node => { const construct = parent => node => { node.nodeKey = nodeKeyMaker(node) + node.nodeName = nodeNameMaker(node) node.pathRegx = pathRegxMaker(node) node.parent = constant(parent) node.isRoot = () => diff --git a/packages/core/src/templateApi/hierarchy.js b/packages/core/src/templateApi/hierarchy.js index 25e5162ff0..3843da79df 100644 --- a/packages/core/src/templateApi/hierarchy.js +++ b/packages/core/src/templateApi/hierarchy.js @@ -244,6 +244,11 @@ export const fieldReversesReferenceToIndex = indexNode => field => intersection(field.typeOptions.reverseIndexNodeKeys)([indexNode.nodeKey()]) .length > 0 +export const nodeNameFromNodeKey = (hierarchy, nodeKey) => { + const node = getNode(hierarchy, nodeKey) + return node ? node.nodeName() : "" +} + export default { getLastPartInKey, getNodesInPath, @@ -281,4 +286,5 @@ export default { getFlattenedHierarchy, isTopLevelIndex, isTopLevelRecord, + nodeNameFromNodeKey, } diff --git a/packages/core/test/templateApi.constructHeirarchy.spec.js b/packages/core/test/templateApi.constructHeirarchy.spec.js index 1435f5dbec..1bd238e224 100644 --- a/packages/core/test/templateApi.constructHeirarchy.spec.js +++ b/packages/core/test/templateApi.constructHeirarchy.spec.js @@ -13,6 +13,7 @@ describe("hierarchy node creation", () => { expect(root.parent).toBeDefined() expect(root.isRoot()).toBeTruthy() expect(root.indexes).toEqual([]) + expect(root.nodeName()).toBe("/") }) it("> getNewRecordTemplate > should be initialise with correct members", async () => { @@ -33,6 +34,7 @@ describe("hierarchy node creation", () => { expect(record.collectionNodeKey()).toBe("/records") expect(record.collectionPathRegx()).toBe("/records") expect(record.nodeKey()).toBe(`/records/${record.nodeId}-{id}`) + expect(record.nodeName()).toBe(`/${record.name}`) expect(record.pathRegx()).toBe(`/records/${record.nodeId}-[a-zA-Z0-9_\-]+`) }) @@ -60,6 +62,16 @@ describe("hierarchy node creation", () => { expect(parentRecord.children[0]).toBe(record) }) + it("> getNewrecordTemplate > child should get correct nodeName ", async () => { + const { templateApi } = await getMemoryTemplateApi() + const root = templateApi.getNewRootLevel() + const parentRecord = templateApi.getNewRecordTemplate(root) + parentRecord.name = "parent" + const record = templateApi.getNewRecordTemplate(parentRecord) + record.name = "child" + expect(record.nodeName()).toBe(`/${parentRecord.name}/${record.name}`) + }) + it("> getNewrecordTemplate > should add itself to parents's default index allowedNodeIds", async () => { const { templateApi } = await getMemoryTemplateApi() const root = templateApi.getNewRootLevel() diff --git a/packages/materialdesign-components/src/Templates/recordForm.js b/packages/materialdesign-components/src/Templates/recordForm.js index 70354a5e4d..38ab602a8e 100644 --- a/packages/materialdesign-components/src/Templates/recordForm.js +++ b/packages/materialdesign-components/src/Templates/recordForm.js @@ -1,6 +1,6 @@ export default ({ records }) => records.map(r => ({ - name: `Form for Record: ${r.nodeKey()}`, + name: `Form for Record: ${r.nodeName()}`, props: outerContainer(r), }))