Merge remote-tracking branch 'upstream/master' into feature/builder-organization
This commit is contained in:
commit
f5dfb5e437
|
@ -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]
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 = () =>
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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),
|
||||
}))
|
||||
|
||||
|
|
Loading…
Reference in New Issue