Merge remote-tracking branch 'upstream/master' into feature/builder-organization

This commit is contained in:
kevmodrome 2020-04-02 08:56:10 +02:00
commit f5dfb5e437
10 changed files with 83 additions and 7 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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,
@ -279,4 +284,7 @@ export default {
fieldReversesReferenceToNode,
fieldReversesReferenceToIndex,
getFlattenedHierarchy,
isTopLevelIndex,
isTopLevelRecord,
nodeNameFromNodeKey,
}

View File

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

View File

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

View File

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

View File

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

View File

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