backup yo

This commit is contained in:
Michael Shanks 2019-11-22 06:28:12 +00:00
parent fd8341aaf6
commit 2580b6d362
15 changed files with 607 additions and 511 deletions

View File

@ -5,8 +5,9 @@ import {
events, joinKey,
} from '../common';
import { _deleteRecord } from '../recordApi/delete';
import { getAllIdsIterator, getAllIdsShardKey } from '../indexing/allIds';
import { getAllIdsIterator, getAllIdsShardKey, folderStructureArray } from '../indexing/allIds';
import { permission } from '../authApi/permissions';
import { getRecordInfo } from "../recordApi/recordInfo";
export const deleteCollection = (app, disableCleanup = false) => async key => apiWrapper(
app,
@ -18,19 +19,16 @@ export const deleteCollection = (app, disableCleanup = false) => async key => ap
export const _deleteCollection = async (app, key, disableCleanup) => {
key = safeKey(key);
const node = getNodeForCollectionPath(app.hierarchy)(key);
await deleteRecords(app, key);
await deleteAllIdsFolders(app, node, key);
await deleteCollectionFolder(app, key);
const recordInfo = getRecordInfo(key);
await app.datastore.deleteFolder(recordInfo)
if (!disableCleanup) { await app.cleanupTransactions(); }
};
const deleteCollectionFolder = async (app, key) => await app.datastore.deleteFolder(key);
const deleteAllIdsFolders = async (app, node, key) => {
const deleteShardFolders = async (app, node, key) => {
await app.datastore.deleteFolder(
joinKey(
key, 'allids',
@ -43,37 +41,4 @@ const deleteAllIdsFolders = async (app, node, key) => {
);
};
const deleteRecords = async (app, key) => {
const deletedAllIdsShards = [];
const deleteAllIdsShard = async (recordId) => {
const shardKey = getAllIdsShardKey(
app.hierarchy, key, recordId,
);
if (includes(shardKey)(deletedAllIdsShards)) {
return;
}
deletedAllIdsShards.push(shardKey);
await app.datastore.deleteFile(shardKey);
};
const iterate = await getAllIdsIterator(app)(key);
let ids = await iterate();
while (!ids.done) {
if (ids.result.collectionKey === key) {
for (const id of ids.result.ids) {
await _deleteRecord(
app,
joinKey(key, id),
true,
);
await deleteAllIdsShard(id);
}
}
ids = await iterate();
}
};

View File

@ -7,19 +7,9 @@ import {
} from '../templateApi/hierarchy';
import { $, allTrue, joinKey } from '../common';
const ensureCollectionIsInitialised = async (datastore, node, parentKey) => {
if (!await datastore.exists(parentKey)) {
await datastore.createFolder(parentKey);
await datastore.createFolder(
joinKey(parentKey, 'allids'),
);
await datastore.createFolder(
joinKey(
parentKey,
'allids',
node.nodeId.toString(),
),
);
const ensureCollectionIsInitialised = async (datastore, node, dir) => {
if (!await datastore.exists(dir)) {
await datastore.createFolder(dir);
}
};
@ -44,9 +34,8 @@ export const initialiseRootCollections = async (datastore, hierarchy) => {
}
};
export const initialiseChildCollections = async (app, recordKey) => {
const childCollectionRecords = $(recordKey, [
getExactNodeForPath(app.hierarchy),
export const initialiseChildCollections = async (app, recordInfo) => {
const childCollectionRecords = $(recordInfo.recordNode, [
n => n.children,
filter(isCollectionRecord),
]);
@ -55,7 +44,7 @@ export const initialiseChildCollections = async (app, recordKey) => {
await ensureCollectionIsInitialised(
app.datastore,
child,
joinKey(recordKey, child.collectionName),
recordInfo.child(child.collectionName),
);
}
};

View File

@ -1,23 +1,19 @@
import {
join, pull,
map, flatten, orderBy,
filter, find,
join, flatten, orderBy,
filter
} from 'lodash/fp';
import {
getParentKey,
getFlattenedHierarchy,
getCollectionNodeByKeyOrNodeKey, getNodeForCollectionPath,
getCollectionNodeByKeyOrNodeKey,
isCollectionRecord, isAncestor,
} from '../templateApi/hierarchy';
import { joinKey, safeKey, $, getFileFromKey } from '../common';
import { joinKey, safeKey, $ } from '../common';
const RECORDS_PER_FOLDER = 1000;
const allIdChars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
const _new_getShardPath = (recordNode, key) => {
const id = getFileFromKey(key);
export const RECORDS_PER_FOLDER = 1000;
export const allIdChars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
// this should never be changed - ever
// - existing databases depend on the order of chars this string
/**
* folderStructureArray should return an array like
@ -27,7 +23,7 @@ const _new_getShardPath = (recordNode, key) => {
* - [64, 64, 10] = all records fit into 64 * 64 * 10 folder
* (there are 64 possible chars in allIsChars)
*/
const folderStructureArray = (currentArray=[], currentFolderPosition=0) => {
export const folderStructureArray = (recordNode, currentArray=[], currentFolderPosition=0) => {
const maxRecords = currentFolderPosition === 0
? RECORDS_PER_FOLDER
: currentFolderPosition * 64 * RECORDS_PER_FOLDER;
@ -42,61 +38,6 @@ const _new_getShardPath = (recordNode, key) => {
}
}
const folderStructure = folderStructureArray();
}
const allIdsStringsForFactor = (collectionNode) => {
const factor = collectionNode.allidsShardFactor;
const charRangePerShard = 64 / factor;
const allIdStrings = [];
let index = 0;
let currentIdsShard = '';
while (index < 64) {
currentIdsShard += allIdChars[index];
if ((index + 1) % charRangePerShard === 0) {
allIdStrings.push(currentIdsShard);
currentIdsShard = '';
}
index++;
}
return allIdStrings;
};
export const getAllIdsShardNames = (appHierarchy, collectionKey) => {
const collectionRecordNode = getNodeForCollectionPath(appHierarchy)(collectionKey);
return $(collectionRecordNode, [
c => [c.nodeId],
map(i => map(c => _allIdsShardKey(collectionKey, i, c))(allIdsStringsForFactor(collectionRecordNode))),
flatten,
]);
};
const _allIdsShardKey = (collectionKey, childNo, shardKey) => joinKey(
collectionKey,
'allids',
childNo,
shardKey,
);
export const getAllIdsShardKey = (appHierarchy, collectionKey, recordId) => {
const indexOfFirstDash = recordId.indexOf('-');
const collectionNode = getNodeForCollectionPath(appHierarchy)(collectionKey);
const idFirstChar = recordId[indexOfFirstDash + 1];
const allIdsShardId = $(collectionNode, [
allIdsStringsForFactor,
find(i => i.includes(idFirstChar)),
]);
return _allIdsShardKey(
collectionKey,
recordId.slice(0, indexOfFirstDash),
allIdsShardId,
);
};
export const getAllIdsIterator = app => async (collection_Key_or_NodeKey) => {
collection_Key_or_NodeKey = safeKey(collection_Key_or_NodeKey);
@ -105,29 +46,97 @@ export const getAllIdsIterator = app => async (collection_Key_or_NodeKey) => {
collection_Key_or_NodeKey,
);
const getAllIdsIteratorForCollectionKey = async (collectionKey) => {
const all_allIdsKeys = getAllIdsShardNames(app.hierarchy, collectionKey);
let shardIndex = 0;
const getAllIdsIteratorForCollectionKey = async (recordNode, collectionKey) => {
const allIdsFromShardIterator = async () => {
if (shardIndex === all_allIdsKeys.length) { return ({ done: true, result: { ids: [], collectionKey } }); }
const folderStructure = folderStructureArray(recordNode)
const shardKey = all_allIdsKeys[shardIndex];
let currentFolderContents = [];
let currentFolderIndexes = [];
let currentSubPath = [];
const allIds = await getAllIdsFromShard(app.datastore, shardKey);
const basePath = joinKey(
collectionKey, recordNode.nodeId.toString());
shardIndex++;
return ({
let folderLevel = 0;
const levels = folderStructure.length;
const topLevel = levels -1;
const lastPathHasContent = () =>
folderLevel === 0
|| currentFolderContents[folderLevel - 1].length > 0;
while (folderLevel < folderStructure.length && lastPathHasContent()) {
if(folderLevel < topLevel) {
const contentsThisLevel =
await app.datastore.getFolderContents(
join(basePath, ...currentSubPath));
currentFolderContents.push(contentsThisLevel);
currentFolderIndexes.push(0);
currentSubPath.push(currentFolderContents[0])
} else {
// placesholders only for the top level (which will be populated by nextFolder())
currentFolderContents.push([])
currentFolderIndexes.push(-1);
currentSubPath.push("");
}
folderLevel+=1;
}
const nextFolder = async (lev=-1) => {
lev = (lev === -1) ? topLevel : lev;
if(currentFolderIndexes[lev] !== currentFolderContents[lev].length - 1){
const folderIndexThisLevel = currentFolderIndexes[lev] + 1;
currentFolderIndexes[lev] = folderIndexThisLevel;
currentSubPath[lev] = currentFolderContents[folderIndexThisLevel]
if(lev < topLevel) {
let loopLev = lev + 1;
while(loopLev <= topLevel) {
currentFolderContents[loopLev] =
await app.datastore.getFolderContents(join(basePath, ...currentSubPath));
loopLev+=1;
}
}
return false; // not complete
} else {
if(lev === 0) return true; // complete
return await nextFolder(lev - 1);
}
}
const fininshedResult = ({ done: true, result: { ids: [], collectionKey } });
const getIdsFromCurrentfolder = async () => {
if(currentFolderIndexes.length < folderStructure)
return fininshedResult;
const hasMore = await nextFolder();
if(!hasMore) return fininshedResult;
const result = ({
result: {
ids: allIds,
collectionKey,
ids: await app.datastore.getFolderContents(
joinKey(basePath, currentSubPath)),
collectionKey
},
done: false,
});
};
done:false
})
return result;
}
return getIdsFromCurrentfolder;
return allIdsFromShardIterator;
};
const ancestors = $(getFlattenedHierarchy(app.hierarchy), [
@ -146,11 +155,13 @@ export const getAllIdsIterator = app => async (collection_Key_or_NodeKey) => {
if (currentNode.nodeKey() === recordNode.nodeKey()) {
return [
await getAllIdsIteratorForCollectionKey(
currentNode,
currentCollectionKey,
)];
}
const allIterators = [];
const currentIterator = await getAllIdsIteratorForCollectionKey(
currentNode,
currentCollectionKey,
);

View File

@ -2,8 +2,8 @@ import { isShardedIndex } from '../templateApi/hierarchy';
import { joinKey } from '../common';
import { getShardMapKey, getUnshardedIndexDataKey, createIndexFile } from './sharding';
export const initialiseIndex = async (datastore, parentKey, index) => {
const indexKey = joinKey(parentKey, index.name);
export const initialiseIndex = async (datastore, dir, index) => {
const indexKey = joinKey(dir, index.name);
await datastore.createFolder(indexKey);

View File

@ -1,15 +1,11 @@
import {
safeKey, apiWrapper,
events, joinKey,
events,
} from '../common';
import { _load, getRecordFileName } from './load';
import { _deleteCollection } from '../collectionApi/delete';
import {
getExactNodeForPath
} from '../templateApi/hierarchy';
import { _deleteIndex } from '../indexApi/delete';
import { _loadFromInfo } from './load';
import { transactionForDeleteRecord } from '../transactions/create';
import { permission } from '../authApi/permissions';
import { getRecordInfo } from "./recordInfo";
export const deleteRecord = (app, disableCleanup = false) => async key => {
key = safeKey(key);
@ -24,71 +20,17 @@ export const deleteRecord = (app, disableCleanup = false) => async key => {
// called deleteRecord because delete is a keyword
export const _deleteRecord = async (app, key, disableCleanup) => {
key = safeKey(key);
const node = getExactNodeForPath(app.hierarchy)(key);
const recordInfo = getRecordInfo(app, key);
key = recordInfo.key;
const record = await _load(app, key);
const record = await _loadFromInfo(app, recordInfo);
await transactionForDeleteRecord(app, record);
for (const collectionRecord of node.children) {
const collectionKey = joinKey(
key, collectionRecord.collectionName,
);
await _deleteCollection(app, collectionKey, true);
}
await app.datastore.deleteFile(
getRecordFileName(key),
);
await deleteFiles(app, key);
await app.datastore.deleteFolder(recordInfo.dir);
if (!disableCleanup) { await app.cleanupTransactions(); }
await app.datastore.deleteFolder(key);
await deleteIndexes(app, key);
};
const deleteIndexes = async (app, key) => {
const node = getExactNodeForPath(app.hierarchy)(key);
/* const reverseIndexKeys = $(app.hierarchy, [
getFlattenedHierarchy,
map(n => n.fields),
flatten,
filter(isSomething),
filter(fieldReversesReferenceToNode(node)),
map(f => $(f.typeOptions.reverseIndexNodeKeys, [
map(n => getNode(
app.hierarchy,
n))
])
),
flatten,
map(n => joinKey(key, n.name))
]);
for(let i of reverseIndexKeys) {
await _deleteIndex(app, i, true);
} */
for (const index of node.indexes) {
const indexKey = joinKey(key, index.name);
await _deleteIndex(app, indexKey, true);
}
};
const deleteFiles = async (app, key) => {
const filesFolder = joinKey(key, 'files');
const allFiles = await app.datastore.getFolderContents(
filesFolder,
);
for (const file of allFiles) {
await app.datastore.deleteFile(file);
}
await app.datastore.deleteFolder(
joinKey(key, 'files'),
);
};

View File

@ -10,6 +10,7 @@ import {
} from '../common';
import { mapRecord } from '../indexing/evaluate';
import { permission } from '../authApi/permissions';
import { getRecordInfo } from "./recordInfo";
export const getRecordFileName = key => joinKey(key, 'record.json');
@ -24,12 +25,10 @@ export const load = app => async key => {
);
}
export const _load = async (app, key, keyStack = []) => {
key = safeKey(key);
const recordNode = getExactNodeForPath(app.hierarchy)(key);
const storedData = await app.datastore.loadJson(
getRecordFileName(key),
);
export const _loadFromInfo = async (app, recordInfo, keyStack = []) => {
const key = recordInfo.key;
const {recordNode, recordJson} = recordInfo;
const storedData = await app.datastore.loadJson(recordJson);
const loadedRecord = $(recordNode.fields, [
keyBy('name'),
@ -70,4 +69,11 @@ export const _load = async (app, key, keyStack = []) => {
return loadedRecord;
};
export const _load = async (app, key, keyStack = []) =>
_loadFromInfo(
app,
getRecordInfo(app, key),
keyStack);
export default load;

View File

@ -0,0 +1,87 @@
import {
getExactNodeForPath, getActualKeyOfParent, isRoot
} from '../templateApi/hierarchy';
import {
map, reduce
} from 'lodash/fp';
import {
$, getDirFomKey, getFileFromKey, joinKey, safeKey
} from '../common';
import {
folderStructureArray, allIdChars
} from "../indexing/allIds";
export const getRecordInfo = (app, key) => {
const recordNode = getExactNodeForPath(app.hierarchy)(key);
const pathInfo = getRecordDirectory(recordNode, key);
const dir = joinKey(pathInfo.base, ...pathInfo.subdirs);
return {
recordJson: recordJson(dir),
files: files(dir),
child:(name) => joinKey(dir, name),
key: safeKey(key),
recordNode, pathInfo, dir
};
}
const recordJson = (dir) =>
joinKey(dir, "record.json")
const files = (dir) =>
joinKey(dir, "files")
const getRecordDirectory = (recordNode, key) => {
const id = getFileFromKey(key);
const traverseParentKeys = (n, keys=[]) => {
if(isRoot(n)) return keys;
const k = getActualKeyOfParent(n, key);
}
return ({
base:getDirFomKey(key),
subdirs: [recordNode.nodeId.toString(), ...subfolders]
});
}
const recordRelativeDirectory = (recordNode, id) => {
const folderStructure = folderStructureArray(recordNode);
const subfolders = $(folderStructure, [
reduce((result, currentCount) => {
result.folders.push(
folderForChar(id[result.level], currentCount)
);
return {level:result.level+1, folders:result.folders}
}, {level:0, folders:[]}),
map(f => f.folders),
]);
return [recordNode.nodeId.toString(), ...subfolders]
}
const folderForChar = (char, folderCount) =>
folderCount === 1 ? ""
: $(folderCount, [
idFoldersForFolderCount,
find(f => f.includes(char))
]);
const idFoldersForFolderCount = (folderCount) => {
const charRangePerShard = 64 / folderCount;
const idFolders = [];
let index = 0;
let currentIdsShard = '';
while (index < 64) {
currentIdsShard += allIdChars[index];
if ((index + 1) % charRangePerShard === 0) {
idFolders.push(currentIdsShard);
currentIdsShard = '';
}
index++;
}
return idFolders;
};

View File

@ -1,11 +1,10 @@
import {
cloneDeep,
flatten,
map,
filter} from 'lodash/fp';
cloneDeep, take, takeRight,
flatten, map, filter
} from 'lodash/fp';
import { initialiseChildCollections } from '../collectionApi/initialise';
import { validate } from './validate';
import { _load, getRecordFileName } from './load';
import { _loadFromInfo, getRecordFileName } from './load';
import {
apiWrapper, events, $, joinKey,
} from '../common';
@ -20,6 +19,7 @@ import {
import { permission } from '../authApi/permissions';
import { initialiseIndex } from '../indexing/initialiseIndex';
import { BadRequestError } from '../common/errors';
import { getRecordInfo } from "./recordInfo";
export const save = app => async (record, context) => apiWrapper(
app,
@ -42,8 +42,14 @@ export const _save = async (app, record, context, skipValidation = false) => {
}
}
const recordInfo = getRecordInfo(app.record.key);
const {
recordNode, pathInfo,
recordJson, files,
} = recordInfo;
if (recordClone.isNew) {
const recordNode = getExactNodeForPath(app.hierarchy)(record.key);
if(!recordNode)
throw new Error("Cannot find node for " + record.key);
@ -51,28 +57,23 @@ export const _save = async (app, record, context, skipValidation = false) => {
app, recordClone,
);
recordClone.transactionId = transaction.id;
await app.datastore.createFolder(recordClone.key);
await app.datastore.createFolder(
joinKey(recordClone.key, 'files'),
);
await app.datastore.createJson(
getRecordFileName(recordClone.key),
recordClone,
);
await initialiseReverseReferenceIndexes(app, record);
await initialiseAncestorIndexes(app, record);
await initialiseChildCollections(app, recordClone.key);
await createRecordFolderPath(app.datastore, pathInfo);
await app.datastore.createFolder(files);
await app.datastore.createJson(recordJson, recordClone);
await initialiseReverseReferenceIndexes(app, recordInfo);
await initialiseAncestorIndexes(app, recordInfo);
await initialiseChildCollections(app, recordInfo);
await app.publish(events.recordApi.save.onRecordCreated, {
record: recordClone,
});
} else {
const oldRecord = await _load(app, recordClone.key);
const oldRecord = await _loadFromInfo(app, recordInfo);
const transaction = await transactionForUpdateRecord(
app, oldRecord, recordClone,
);
recordClone.transactionId = transaction.id;
await app.datastore.updateJson(
getRecordFileName(recordClone.key),
recordJson,
recordClone,
);
await app.publish(events.recordApi.save.onRecordUpdated, {
@ -88,19 +89,16 @@ export const _save = async (app, record, context, skipValidation = false) => {
return returnedClone;
};
const initialiseAncestorIndexes = async (app, record) => {
const recordNode = getExactNodeForPath(app.hierarchy)(record.key);
for (const index of recordNode.indexes) {
const indexKey = joinKey(record.key, index.name);
if (!await app.datastore.exists(indexKey)) { await initialiseIndex(app.datastore, record.key, index); }
const initialiseAncestorIndexes = async (app, recordInfo) => {
for (const index of recordInfo.recordNode.indexes) {
const indexKey = recordInfo.child(index.name);
if (!await app.datastore.exists(indexKey)) { await initialiseIndex(app.datastore, recordInfo.dir, index); }
}
};
const initialiseReverseReferenceIndexes = async (app, record) => {
const recordNode = getExactNodeForPath(app.hierarchy)(record.key);
const initialiseReverseReferenceIndexes = async (app, recordInfo) => {
const indexNodes = $(fieldsThatReferenceThisRecord(app, recordNode), [
const indexNodes = $(fieldsThatReferenceThisRecord(app, recordInfo.recordNode), [
map(f => $(f.typeOptions.reverseIndexNodeKeys, [
map(n => getNode(
app.hierarchy,
@ -112,7 +110,7 @@ const initialiseReverseReferenceIndexes = async (app, record) => {
for (const indexNode of indexNodes) {
await initialiseIndex(
app.datastore, record.key, indexNode,
app.datastore, recordInfo.dir, indexNode,
);
}
};
@ -125,6 +123,37 @@ const fieldsThatReferenceThisRecord = (app, recordNode) => $(app.hierarchy, [
filter(fieldReversesReferenceToNode(recordNode)),
]);
const recordFolderPath = (recordNode, key) => {
const createRecordFolderPath = async (datastore, pathInfo) => {
const recursiveCreateFolder = async (subdirs, dirsThatNeedCreated=[]) => {
// iterate backwards through directory hierachy
// until we get to a folder that exists, then create the rest
// e.g
// - some/folder/here
// - some/folder
// - some
const thisFolder = joinKey(pathInfo.base, ...subdirs);
if(await datastore.exists(thisFolder)) {
let creationFolder = thisFolder;
for(let nextDir of dirsThatNeedCreated) {
creationFolder = joinKey(creationFolder, nextDir);
await datastore.createFolder(creationFolder);
}
} else if(dirsThatNeedCreated.length > 0) {
await recursiveCreateFolder(
take(subdirs.length - 1)(subdirs),
[...takeRight(1)(subdirs), ...dirsThatNeedCreated]
);
}
}
await recursiveCreateFolder(pathInfo.subdirs);
return joinKey(pathInfo.base, ...pathInfo.subdirs);
}

View File

@ -0,0 +1,93 @@
import {setupApphierarchy, basicAppHierarchyCreator_WithFields,
getNewFieldAndAdd} from "./specHelpers";
import {isNonEmptyString} from "../src/common";
import { isBoolean } from "util";
import {permission} from "../src/authApi/permissions";
import { _getNew } from "../src/recordApi/getNew";
describe("recordApi > getNew", () => {
it("should get object with generated id and key (full path)", async () => {
const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const record = recordApi.getNew("/customers", "customer");
expect(record.id).toBeDefined();
expect(isNonEmptyString(record.id)).toBeTruthy();
expect(record.key).toBeDefined();
expect(isNonEmptyString(record.key)).toBeTruthy();
expect(record.key).toBe(`/customers/${record.id}`);
});
it("should create object with all declared fields, using default values", async () => {
const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const newRecord = recordApi.getNew("/customers", "customer")
expect(newRecord.surname).toBe(null);
expect(newRecord.isalive).toBe(true);
expect(newRecord.createddate).toBe(null);
expect(newRecord.age).toBe(null);
});
it("should create object with all declared fields, and use inital values", async () => {
const {recordApi} = await setupApphierarchy(templateApi => {
const hierarchy = basicAppHierarchyCreator_WithFields(templateApi);
const {customerRecord} = hierarchy;
customerRecord.fields = [];
const newField = getNewFieldAndAdd(templateApi, customerRecord);
newField("surname", "string", "hello");
newField("isalive", "bool", "true");
newField("age", "number", "999");
return hierarchy;
});
const newRecord = recordApi.getNew("/customers", "customer")
expect(newRecord.surname).toBe("hello");
expect(newRecord.isalive).toBe(true);
expect(newRecord.age).toBe(999);
});
it("should add a function 'isNew' which always returns true", async () => {
const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const record = recordApi.getNew("/customers", "customer");
expect(record.isNew).toBeDefined();
expect(isBoolean(record.isNew)).toBeTruthy();
expect(record.isNew).toBeTruthy();
});
it("should add a function 'type' returns type", async () => {
const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const record = recordApi.getNew("/customers", "customer");
expect(record.type).toBeDefined();
expect(isNonEmptyString(record.type)).toBeTruthy();
expect(record.type).toBe("customer");
});
it("should throw error, user user does not have permission", async () => {
const {recordApi, app, appHierarchy} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
app.removePermission(permission.createRecord.get(appHierarchy.customerRecord.nodeKey()));
expect(() => recordApi.getNew("/customers", "customer")).toThrow(/Unauthorized/);
});
it("should not depend on having any other permissions", async () => {
const {recordApi, app, appHierarchy} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
app.withOnlyThisPermission(permission.createRecord.get(appHierarchy.customerRecord.nodeKey()));
recordApi.getNew("/customers", "customer");
});
it("for 'single record' type, should create with key ending in node name", async () => {
const {appHierarchy} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const {settingsRecord} = appHierarchy;
const result = _getNew(settingsRecord, "");
expect(result.key).toBe("/settings")
})
});

View File

@ -1,94 +1,8 @@
import {setupApphierarchy, basicAppHierarchyCreator_WithFields,
getNewFieldAndAdd, stubEventHandler} from "./specHelpers";
stubEventHandler} from "./specHelpers";
import {events, isNonEmptyString} from "../src/common";
import { isBoolean } from "util";
import {permission} from "../src/authApi/permissions";
import { _getNew } from "../src/recordApi/getNew";
describe("recordApi > getNew", () => {
it("should get object with generated id and key (full path)", async () => {
const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const record = recordApi.getNew("/customers", "customer");
expect(record.id).toBeDefined();
expect(isNonEmptyString(record.id)).toBeTruthy();
expect(record.key).toBeDefined();
expect(isNonEmptyString(record.key)).toBeTruthy();
expect(record.key).toBe(`/customers/${record.id}`);
});
it("should create object with all declared fields, using default values", async () => {
const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const newRecord = recordApi.getNew("/customers", "customer")
expect(newRecord.surname).toBe(null);
expect(newRecord.isalive).toBe(true);
expect(newRecord.createddate).toBe(null);
expect(newRecord.age).toBe(null);
});
it("should create object with all declared fields, and use inital values", async () => {
const {recordApi} = await setupApphierarchy(templateApi => {
const hierarchy = basicAppHierarchyCreator_WithFields(templateApi);
const {customerRecord} = hierarchy;
customerRecord.fields = [];
const newField = getNewFieldAndAdd(templateApi, customerRecord);
newField("surname", "string", "hello");
newField("isalive", "bool", "true");
newField("age", "number", "999");
return hierarchy;
});
const newRecord = recordApi.getNew("/customers", "customer")
expect(newRecord.surname).toBe("hello");
expect(newRecord.isalive).toBe(true);
expect(newRecord.age).toBe(999);
});
it("should add a function 'isNew' which always returns true", async () => {
const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const record = recordApi.getNew("/customers", "customer");
expect(record.isNew).toBeDefined();
expect(isBoolean(record.isNew)).toBeTruthy();
expect(record.isNew).toBeTruthy();
});
it("should add a function 'type' returns type", async () => {
const {recordApi} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const record = recordApi.getNew("/customers", "customer");
expect(record.type).toBeDefined();
expect(isNonEmptyString(record.type)).toBeTruthy();
expect(record.type).toBe("customer");
});
it("should throw error, user user does not have permission", async () => {
const {recordApi, app, appHierarchy} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
app.removePermission(permission.createRecord.get(appHierarchy.customerRecord.nodeKey()));
expect(() => recordApi.getNew("/customers", "customer")).toThrow(/Unauthorized/);
});
it("should not depend on having any other permissions", async () => {
const {recordApi, app, appHierarchy} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
app.withOnlyThisPermission(permission.createRecord.get(appHierarchy.customerRecord.nodeKey()));
recordApi.getNew("/customers", "customer");
});
it("for 'single record' type, should create with key ending in node name", async () => {
const {appHierarchy} = await setupApphierarchy(basicAppHierarchyCreator_WithFields);
const {settingsRecord} = appHierarchy;
const result = _getNew(settingsRecord, "");
expect(result.key).toBe("/settings")
})
});
describe('recordApi > save then load', () => {
@ -292,7 +206,7 @@ describe("save", () => {
const record = recordApi.getNew("/customers", "customer");
record.surname = "Ledog";
const savedRecord = await recordApi.save(record);
await recordApi.save(record);
expect(await recordApi._storeHandle.exists(`${record.key}/invoice_index/index.csv`)).toBeTruthy()
expect(await recordApi._storeHandle.exists(`${record.key}/invoice_index`)).toBeTruthy()
expect(await recordApi._storeHandle.exists(`${record.key}/invoices`)).toBeTruthy()
@ -313,7 +227,7 @@ describe("save", () => {
const record = recordApi.getNew("/customers", "customer");
record.surname = "Ledog";
const savedRecord = await recordApi.save(record);
await recordApi.save(record);
expect(await recordApi._storeHandle.exists(`${record.key}`)).toBeTruthy();
expect(await recordApi._storeHandle.exists(`${record.key}/record.json`)).toBeTruthy();
});

File diff suppressed because one or more lines are too long

View File

@ -9,41 +9,41 @@ h4.svelte-sqtlby{margin-top:20px}
.root.svelte-apja7r{height:100%;position:relative}.actions-header.svelte-apja7r{flex:0 1 auto}.node-view.svelte-apja7r{overflow-y:auto;flex:1 1 auto}
.items-root.svelte-19lmivt{display:flex;flex-direction:column;max-height:100%;height:100%;background-color:var(--secondary5)}.nav-group-header.svelte-19lmivt{display:grid;grid-template-columns:[icon] auto [title] 1fr [button] auto;padding:2rem 1rem 0rem 1rem;font-size:.9rem;font-weight:bold}.nav-group-header.svelte-19lmivt>div.svelte-19lmivt:nth-child(1){padding:0rem .7rem 0rem 0rem;vertical-align:bottom;grid-column-start:icon;margin-right:5px}.nav-group-header.svelte-19lmivt>div.svelte-19lmivt:nth-child(2){margin-left:5px;vertical-align:bottom;grid-column-start:title;margin-top:auto}.nav-group-header.svelte-19lmivt>div.svelte-19lmivt:nth-child(3){vertical-align:bottom;grid-column-start:button;cursor:pointer;color:var(--primary75)}.nav-group-header.svelte-19lmivt>div.svelte-19lmivt:nth-child(3):hover{color:var(--primary75)}.hierarchy-title.svelte-19lmivt{flex:auto 1 1}.hierarchy.svelte-19lmivt{display:flex;flex-direction:column;flex:1 0 auto;height:100px}.hierarchy-items-container.svelte-19lmivt{flex:1 1 auto;overflow-y:auto}
.root.svelte-nd1yft{height:100%;position:relative;padding:1.5rem}
.root.svelte-wfv60d{height:100%;position:relative;padding:1.5rem}.actions-header.svelte-wfv60d{flex:0 1 auto}.node-view.svelte-wfv60d{overflow-y:auto;flex:1 1 auto}
.uk-modal-dialog.svelte-vwwrf9{border-radius:.3rem}
.root.svelte-1r2dipt{color:var(--secondary50);font-size:.9rem;font-weight:bold}.hierarchy-item.svelte-1r2dipt{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-1r2dipt:hover{color:var(--secondary)}.component.svelte-1r2dipt{margin-left:5px}.currentfolder.svelte-1r2dipt{color:var(--secondary100)}.selected.svelte-1r2dipt{color:var(--primary100);font-weight:bold}.title.svelte-1r2dipt{margin-left:10px}
.root.svelte-117bbrk{padding-bottom:10px;padding-left:10px;font-size:.9rem;color:var(--secondary50);font-weight:bold}.hierarchy-item.svelte-117bbrk{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-117bbrk:hover{color:var(--secondary100)}.component.svelte-117bbrk{margin-left:5px}.selected.svelte-117bbrk{color:var(--primary100);font-weight:bold}.title.svelte-117bbrk{margin-left:10px}
.section-container.svelte-yk1mmr{padding:15px;border-style:dotted;border-width:1px;border-color:var(--lightslate);border-radius:2px}.section-container.svelte-yk1mmr:nth-child(1){margin-bottom:15px}.row-text.svelte-yk1mmr{margin-right:15px;color:var(--primary100)}input.svelte-yk1mmr{margin-right:15px}p.svelte-yk1mmr>span.svelte-yk1mmr{margin-left:30px}.header.svelte-yk1mmr{display:grid;grid-template-columns:[title] 1fr [icon] auto}.header.svelte-yk1mmr>div.svelte-yk1mmr:nth-child(1){grid-column-start:title}.header.svelte-yk1mmr>div.svelte-yk1mmr:nth-child(2){grid-column-start:icon}
.root.svelte-wfv60d{height:100%;position:relative;padding:1.5rem}.actions-header.svelte-wfv60d{flex:0 1 auto}.node-view.svelte-wfv60d{overflow-y:auto;flex:1 1 auto}
.root.svelte-1r2dipt{color:var(--secondary50);font-size:.9rem;font-weight:bold}.hierarchy-item.svelte-1r2dipt{cursor:pointer;padding:5px 0px}.hierarchy-item.svelte-1r2dipt:hover{color:var(--secondary)}.component.svelte-1r2dipt{margin-left:5px}.currentfolder.svelte-1r2dipt{color:var(--secondary100)}.selected.svelte-1r2dipt{color:var(--primary100);font-weight:bold}.title.svelte-1r2dipt{margin-left:10px}
h1.svelte-16jkjx9{font-size:1.2em}
.component-container.svelte-teqoiq{grid-row-start:middle;grid-column-start:middle;position:relative;overflow:hidden;padding-top:56.25%;margin:auto}.component-container.svelte-teqoiq iframe.svelte-teqoiq{border:0;height:100%;left:0;position:absolute;top:0;width:100%}
.uk-modal-dialog.svelte-vwwrf9{border-radius:.3rem}
.section-container.svelte-yk1mmr{padding:15px;border-style:dotted;border-width:1px;border-color:var(--lightslate);border-radius:2px}.section-container.svelte-yk1mmr:nth-child(1){margin-bottom:15px}.row-text.svelte-yk1mmr{margin-right:15px;color:var(--primary100)}input.svelte-yk1mmr{margin-right:15px}p.svelte-yk1mmr>span.svelte-yk1mmr{margin-left:30px}.header.svelte-yk1mmr{display:grid;grid-template-columns:[title] 1fr [icon] auto}.header.svelte-yk1mmr>div.svelte-yk1mmr:nth-child(1){grid-column-start:title}.header.svelte-yk1mmr>div.svelte-yk1mmr:nth-child(2){grid-column-start:icon}
.root.svelte-1ersoxu{padding:15px}.help-text.svelte-1ersoxu{color:var(--slate);font-size:10pt}
.component-container.svelte-teqoiq{grid-row-start:middle;grid-column-start:middle;position:relative;overflow:hidden;padding-top:56.25%;margin:auto}.component-container.svelte-teqoiq iframe.svelte-teqoiq{border:0;height:100%;left:0;position:absolute;top:0;width:100%}
.root.svelte-1abif7s{height:100%;display:flex;flex-direction:column}.padding.svelte-1abif7s{padding:1rem 1rem 0rem 1rem}.info-text.svelte-1abif7s{color:var(--secondary100);font-size:.8rem !important;font-weight:bold}.title.svelte-1abif7s{padding:2rem 1rem 1rem 1rem;display:grid;grid-template-columns:[name] 1fr [actions] auto;color:var(--secondary100);font-size:.9rem;font-weight:bold}.title.svelte-1abif7s>div.svelte-1abif7s:nth-child(1){grid-column-start:name;color:var(--secondary100)}.title.svelte-1abif7s>div.svelte-1abif7s:nth-child(2){grid-column-start:actions}.section-header.svelte-1abif7s{display:grid;grid-template-columns:[name] 1fr [actions] auto;color:var(--secondary50);font-size:.9rem;font-weight:bold;vertical-align:middle}.component-props-container.svelte-1abif7s{flex:1 1 auto;overflow-y:auto}
.root.svelte-ehsf0i{display:block;font-size:.9rem;width:100%;cursor:pointer;font-weight:bold}.title.svelte-ehsf0i{font:var(--fontblack);padding-top:10px;padding-right:5px;padding-bottom:10px;color:var(--secondary100)}.title.svelte-ehsf0i:hover{background-color:var(--secondary10)}
.root.svelte-18xd5y3{height:100%;padding:2rem}.settings-title.svelte-18xd5y3{font-weight:700}.title.svelte-18xd5y3{margin:3rem 0rem 0rem 0rem;font-weight:700}.recordkey.svelte-18xd5y3{font-size:14px;font-weight:600;color:var(--primary100)}.fields-table.svelte-18xd5y3{margin:1rem 1rem 0rem 0rem;border-collapse:collapse}.add-field-button.svelte-18xd5y3{cursor:pointer}.edit-button.svelte-18xd5y3{cursor:pointer;color:var(--secondary25)}.edit-button.svelte-18xd5y3:hover{cursor:pointer;color:var(--secondary75)}th.svelte-18xd5y3{text-align:left}td.svelte-18xd5y3{padding:1rem 5rem 1rem 0rem;margin:0;font-size:14px;font-weight:500}.field-label.svelte-18xd5y3{font-size:14px;font-weight:500}thead.svelte-18xd5y3>tr.svelte-18xd5y3{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--secondary75);margin-bottom:20px}tbody.svelte-18xd5y3>tr.svelte-18xd5y3{border-width:0px 0px 1px 0px;border-style:solid;border-color:var(--primary10)}tbody.svelte-18xd5y3>tr.svelte-18xd5y3:hover{background-color:var(--primary10)}tbody.svelte-18xd5y3>tr:hover .edit-button.svelte-18xd5y3{color:var(--secondary75)}.index-container.svelte-18xd5y3{border-style:solid;border-width:0 0 1px 0;border-color:var(--secondary25);padding:10px;margin-bottom:5px}.index-label.svelte-18xd5y3{color:var(--slate)}.index-name.svelte-18xd5y3{font-weight:bold;color:var(--primary100)}.index-container.svelte-18xd5y3 code.svelte-18xd5y3{margin:0;display:inline;background-color:var(--primary10);color:var(--secondary100);padding:3px}.index-field-row.svelte-18xd5y3{margin:1rem 0rem 0rem 0rem}.no-indexes.svelte-18xd5y3{margin:1rem 0rem 0rem 0rem;font-family:var(--fontnormal);font-size:14px}
.root.svelte-pq2tmv{height:100%;padding:15px}.allowed-records.svelte-pq2tmv{margin:20px 0px}.allowed-records.svelte-pq2tmv>span.svelte-pq2tmv{margin-right:30px}
.root.svelte-wgyofl{padding:1.5rem;width:100%;align-items:right}
.dropdown-background.svelte-11ifkop{position:fixed;top:0;left:0;width:100vw;height:100vh}.root.svelte-11ifkop{cursor:pointer;z-index:1}.dropdown-content.svelte-11ifkop{position:absolute;background-color:var(--white);min-width:160px;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);z-index:1;font-weight:normal;border-style:solid;border-width:1px;border-color:var(--secondary10)}.dropdown-content.svelte-11ifkop:not(:focus){display:none}.action-row.svelte-11ifkop{padding:7px 10px;cursor:pointer}.action-row.svelte-11ifkop:hover{background-color:var(--primary100);color:var(--white)}
.root.svelte-pq2tmv{height:100%;padding:15px}.allowed-records.svelte-pq2tmv{margin:20px 0px}.allowed-records.svelte-pq2tmv>span.svelte-pq2tmv{margin-right:30px}
.root.svelte-17ju2r{display:block;font-size:.9rem;width:100%;cursor:pointer;color:var(--secondary50);font-weight:500}.title.svelte-17ju2r{padding-top:.5rem;padding-right:.5rem}.title.svelte-17ju2r:hover{background-color:var(--secondary10)}.active.svelte-17ju2r{background-color:var(--primary10)}
.nav-item.svelte-1i5jqm7{padding:1.5rem 1rem 0rem 1rem;font-size:.9rem;font-weight:bold;cursor:pointer;flex:0 0 auto}.nav-item.svelte-1i5jqm7:hover{background-color:var(--primary10)}.active.svelte-1i5jqm7{background-color:var(--primary10)}
.root.svelte-x3bf9z{display:flex}.root.svelte-x3bf9z:last-child{border-radius:0 var(--borderradius) var(--borderradius) 0}.root.svelte-x3bf9z:first-child{border-radius:var(--borderradius) 0 0 var(--borderradius)}.root.svelte-x3bf9z:not(:first-child):not(:last-child){border-radius:0}
.edit-button.svelte-zm41av{cursor:pointer;color:var(--secondary25)}.title.svelte-zm41av{margin:3rem 0rem 0rem 0rem;font-weight:700}.table-content.svelte-zm41av{font-weight:500;font-size:.9rem}tr.svelte-zm41av:hover .edit-button.svelte-zm41av{color:var(--secondary75)}
.nav-item.svelte-1i5jqm7{padding:1.5rem 1rem 0rem 1rem;font-size:.9rem;font-weight:bold;cursor:pointer;flex:0 0 auto}.nav-item.svelte-1i5jqm7:hover{background-color:var(--primary10)}.active.svelte-1i5jqm7{background-color:var(--primary10)}
.edit-button.svelte-lhfdtn{cursor:pointer;color:var(--secondary25)}tr.svelte-lhfdtn:hover .edit-button.svelte-lhfdtn{color:var(--secondary75)}.title.svelte-lhfdtn{margin:3rem 0rem 0rem 0rem;font-weight:700}.table-content.svelte-lhfdtn{font-weight:500;font-size:.9rem}
.info-text.svelte-1gx0gkl{font-size:0.7rem;color:var(--secondary50)}
.root.svelte-47ohpz{font-size:10pt}.padding.svelte-47ohpz{padding:0 10px}.inherited-title.svelte-47ohpz{padding:1rem 1rem 1rem 1rem;display:grid;grid-template-columns:[name] 1fr [actions] auto;color:var(--secondary100);font-size:.9rem;font-weight:bold}.inherited-title.svelte-47ohpz>div.svelte-47ohpz:nth-child(1){grid-column-start:name;color:var(--secondary50)}.inherited-title.svelte-47ohpz>div.svelte-47ohpz:nth-child(2){grid-column-start:actions;color:var(--secondary100)}
.library-header.svelte-chhyel{font-size:1.1em;border-color:var(--primary25);border-width:1px 0px;border-style:solid;background-color:var(--primary10);padding:5px 0}.library-container.svelte-chhyel{padding:0 0 10px 10px}.inner-header.svelte-chhyel{font-size:0.9em;font-weight:bold;margin-top:7px;margin-bottom:3px}.component.svelte-chhyel{padding:2px 0px;cursor:pointer}.component.svelte-chhyel:hover{background-color:var(--lightslate)}.component.svelte-chhyel>.name.svelte-chhyel{color:var(--secondary100);display:inline-block}.component.svelte-chhyel>.description.svelte-chhyel{font-size:0.8em;color:var(--secondary75);display:inline-block;margin-left:10px}
.edit-button.svelte-zm41av{cursor:pointer;color:var(--secondary25)}.title.svelte-zm41av{margin:3rem 0rem 0rem 0rem;font-weight:700}.table-content.svelte-zm41av{font-weight:500;font-size:.9rem}tr.svelte-zm41av:hover .edit-button.svelte-zm41av{color:var(--secondary75)}
.component.svelte-3sgo90{padding:5px 0}.component.svelte-3sgo90 .title.svelte-3sgo90{width:300px
}.component.svelte-3sgo90>.description.svelte-3sgo90{font-size:0.8em;color:var(--secondary75)}.button-container.svelte-3sgo90{text-align:right;margin-top:20px}.error.svelte-3sgo90{font-size:10pt;color:red}
.root.svelte-47ohpz{font-size:10pt}.padding.svelte-47ohpz{padding:0 10px}.inherited-title.svelte-47ohpz{padding:1rem 1rem 1rem 1rem;display:grid;grid-template-columns:[name] 1fr [actions] auto;color:var(--secondary100);font-size:.9rem;font-weight:bold}.inherited-title.svelte-47ohpz>div.svelte-47ohpz:nth-child(1){grid-column-start:name;color:var(--secondary50)}.inherited-title.svelte-47ohpz>div.svelte-47ohpz:nth-child(2){grid-column-start:actions;color:var(--secondary100)}
.info-text.svelte-1gx0gkl{font-size:0.7rem;color:var(--secondary50)}
.library-header.svelte-chhyel{font-size:1.1em;border-color:var(--primary25);border-width:1px 0px;border-style:solid;background-color:var(--primary10);padding:5px 0}.library-container.svelte-chhyel{padding:0 0 10px 10px}.inner-header.svelte-chhyel{font-size:0.9em;font-weight:bold;margin-top:7px;margin-bottom:3px}.component.svelte-chhyel{padding:2px 0px;cursor:pointer}.component.svelte-chhyel:hover{background-color:var(--lightslate)}.component.svelte-chhyel>.name.svelte-chhyel{color:var(--secondary100);display:inline-block}.component.svelte-chhyel>.description.svelte-chhyel{font-size:0.8em;color:var(--secondary75);display:inline-block;margin-left:10px}
.title.svelte-dhe1ge{padding:3px;background-color:white;color:var(--secondary100);border-style:solid;border-width:1px 0 0 0;border-color:var(--lightslate)}.title.svelte-dhe1ge>span.svelte-dhe1ge{margin-left:10px}
textarea.svelte-di7k4b{padding:3px;margin-top:5px;margin-bottom:10px;background:var(--lightslate);color:var(--white);font-family:'Courier New', Courier, monospace;width:95%;height:100px;border-radius:5px}
.error-container.svelte-ole1mk{padding:10px;border-style:solid;border-color:var(--deletion100);border-radius:var(--borderradiusall);background:var(--deletion75)}.error-row.svelte-ole1mk{padding:5px 0px}
input.svelte-9fre0g{margin-right:7px}
.error-container.svelte-ole1mk{padding:10px;border-style:solid;border-color:var(--deletion100);border-radius:var(--borderradiusall);background:var(--deletion75)}.error-row.svelte-ole1mk{padding:5px 0px}
.root.svelte-ogh8o0{display:grid;grid-template-columns:[name] 1fr [actions] auto}.root.svelte-ogh8o0>div.svelte-ogh8o0:nth-child(1){grid-column-start:name;color:var(--secondary50)}.root.svelte-ogh8o0>div.svelte-ogh8o0:nth-child(2){grid-column-start:actions}.selectedname.svelte-ogh8o0{font-weight:bold;color:var(--secondary)}
.root.svelte-16sjty9{padding:2rem;border-radius:2rem}.uk-grid-small.svelte-16sjty9{padding:1rem}.option-container.svelte-16sjty9{border-style:dotted;border-width:1px;border-color:var(--primary75);padding:3px;margin-right:5px}
.root.svelte-1v0yya9{padding:1rem 1rem 0rem 1rem}.prop-label.svelte-1v0yya9{font-size:0.8rem;color:var(--secondary100);font-weight:bold}
.root.svelte-ogh8o0{display:grid;grid-template-columns:[name] 1fr [actions] auto}.root.svelte-ogh8o0>div.svelte-ogh8o0:nth-child(1){grid-column-start:name;color:var(--secondary50)}.root.svelte-ogh8o0>div.svelte-ogh8o0:nth-child(2){grid-column-start:actions}.selectedname.svelte-ogh8o0{font-weight:bold;color:var(--secondary)}
textarea.svelte-1kv2xk7{width:300px;height:200px}
.addelement-container.svelte-r1ft9p{cursor:pointer;padding:3px 0px;text-align:center}.addelement-container.svelte-r1ft9p:hover{background-color:var(--primary25);margin-top:5px}.control-container.svelte-r1ft9p{padding-left:3px;background:var(--secondary10)}.separator.svelte-r1ft9p{width:60%;margin:10px auto;border-style:solid;border-width:1px 0 0 0;border-color:var(--primary25)}
.unbound-container.svelte-jubmd5{display:flex;margin:.5rem 0rem .5rem 0rem}.unbound-container.svelte-jubmd5>.svelte-jubmd5:nth-child(1){width:auto;flex:1 0 auto;font-size:0.8rem;color:var(--secondary100);border-radius:.2rem}.bound-header.svelte-jubmd5{display:flex}.bound-header.svelte-jubmd5>div.svelte-jubmd5:nth-child(1){flex:1 0 auto;width:30px;color:var(--secondary50);padding-left:5px}.binding-prop-label.svelte-jubmd5{color:var(--secondary50)}
.addelement-container.svelte-199q8jr{cursor:pointer;padding:3px 0px;text-align:center}.addelement-container.svelte-199q8jr:hover{background-color:var(--primary25)}.item-container.svelte-199q8jr{padding-left:3px;background:var(--secondary10)}
.unbound-container.svelte-jubmd5{display:flex;margin:.5rem 0rem .5rem 0rem}.unbound-container.svelte-jubmd5>.svelte-jubmd5:nth-child(1){width:auto;flex:1 0 auto;font-size:0.8rem;color:var(--secondary100);border-radius:.2rem}.bound-header.svelte-jubmd5{display:flex}.bound-header.svelte-jubmd5>div.svelte-jubmd5:nth-child(1){flex:1 0 auto;width:30px;color:var(--secondary50);padding-left:5px}.binding-prop-label.svelte-jubmd5{color:var(--secondary50)}
.addelement-container.svelte-r1ft9p{cursor:pointer;padding:3px 0px;text-align:center}.addelement-container.svelte-r1ft9p:hover{background-color:var(--primary25);margin-top:5px}.control-container.svelte-r1ft9p{padding-left:3px;background:var(--secondary10)}.separator.svelte-r1ft9p{width:60%;margin:10px auto;border-style:solid;border-width:1px 0 0 0;border-color:var(--primary25)}
.type-selector-container.svelte-1b6pj9u{display:flex}.type-selector.svelte-1b6pj9u{border-color:var(--primary50);border-radius:2px;width:50px;flex:1 0 auto}
/*# sourceMappingURL=bundle.css.map */

File diff suppressed because one or more lines are too long

View File

@ -21231,7 +21231,9 @@
]);
record.id = `${recordNode.nodeId}-${shortid_1()}`;
record.key = joinKey(collectionKey, record.id);
record.key = isSingleRecord(recordNode)
? joinKey(collectionKey, recordNode.name)
: joinKey(collectionKey, record.id);
record.isNew = true;
record.type = recordNode.name;
return record;
@ -26873,7 +26875,15 @@
if (isIndex(obj))
// Q: why are indexes not children ?
// A: because they cannot have children of their own.
{ parent.indexes.push(obj); } else if (isaggregateGroup(obj)) { parent.aggregateGroups.push(obj); } else { parent.children.push(obj); }
{
parent.indexes.push(obj);
}
else if (isaggregateGroup(obj))
{
parent.aggregateGroups.push(obj);
} else {
parent.children.push(obj);
}
if (isRecord(obj)) {
const defaultIndex = lodash_15(
@ -29329,6 +29339,13 @@
fp_52(newIndexOfchild)
]);
if(!existingNode && s.currentNode.type === "record") {
const defaultIndex = templateApi(s.hierarchy)
.getNewIndexTemplate(cloned.parent());
defaultIndex.name = `all_${cloned.collectionName}`;
defaultIndex.allowedRecordNodeIds = [cloned.nodeId];
}
s.currentNodeIsNew = false;
savePackage(store, s);
@ -49170,7 +49187,7 @@
return child_ctx;
}
// (74:8) {#each events as ev}
// (75:8) {#each events as ev}
function create_each_block_1$4(ctx) {
var option, t_value = ctx.ev.name + "", t, option_value_value;
@ -49180,7 +49197,7 @@
t = text(t_value);
option.__value = option_value_value = ctx.ev.name;
option.value = option.__value;
add_location(option, file$e, 74, 8, 1965);
add_location(option, file$e, 75, 8, 1992);
},
m: function mount(target, anchor) {
@ -49206,11 +49223,11 @@
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block_1$4.name, type: "each", source: "(74:8) {#each events as ev}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block_1$4.name, type: "each", source: "(75:8) {#each events as ev}", ctx });
return block;
}
// (85:0) {#if parameters}
// (86:0) {#if parameters}
function create_if_block$6(ctx) {
var each_1_anchor, current;
@ -49297,11 +49314,11 @@
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block$6.name, type: "if", source: "(85:0) {#if parameters}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block$6.name, type: "if", source: "(86:0) {#if parameters}", ctx });
return block;
}
// (86:0) {#each parameters as p, index}
// (87:0) {#each parameters as p, index}
function create_each_block$6(ctx) {
var div, t0_value = ctx.p.name + "", t0, t1, current;
@ -49319,7 +49336,7 @@
t0 = text(t0_value);
t1 = space();
statebindingcontrol.$$.fragment.c();
add_location(div, file$e, 87, 0, 2206);
add_location(div, file$e, 88, 0, 2233);
},
m: function mount(target, anchor) {
@ -49361,12 +49378,12 @@
destroy_component(statebindingcontrol, detaching);
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block$6.name, type: "each", source: "(86:0) {#each parameters as p, index}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block$6.name, type: "each", source: "(87:0) {#each parameters as p, index}", ctx });
return block;
}
function create_fragment$d(ctx) {
var div, select, select_value_value, t0, t1, if_block_anchor, current, dispose;
var div, select, option, select_value_value, t0, t1, if_block_anchor, current, dispose;
let each_value_1 = ctx.events;
@ -49388,6 +49405,7 @@
c: function create() {
div = element("div");
select = element("select");
option = element("option");
for (let i_1 = 0; i_1 < each_blocks.length; i_1 += 1) {
each_blocks[i_1].c();
@ -49398,6 +49416,9 @@
t1 = space();
if (if_block) if_block.c();
if_block_anchor = empty();
option.__value = "";
option.value = option.__value;
add_location(option, file$e, 73, 8, 1935);
attr_dev(select, "class", "type-selector uk-select uk-form-small svelte-1b6pj9u");
add_location(select, file$e, 72, 4, 1823);
attr_dev(div, "class", "type-selector-container svelte-1b6pj9u");
@ -49412,6 +49433,7 @@
m: function mount(target, anchor) {
insert_dev(target, div, anchor);
append_dev(div, select);
append_dev(select, option);
for (let i_1 = 0; i_1 < each_blocks.length; i_1 += 1) {
each_blocks[i_1].m(select, null);
@ -49419,10 +49441,10 @@
select_value_value = ctx.eventType;
for (var i = 0; i < select.options.length; i += 1) {
var option = select.options[i];
var option_1 = select.options[i];
if (option.__value === select_value_value) {
option.selected = true;
if (option_1.__value === select_value_value) {
option_1.selected = true;
break;
}
}
@ -49460,10 +49482,10 @@
if ((!current || changed.eventType) && select_value_value !== (select_value_value = ctx.eventType)) {
for (var i = 0; i < select.options.length; i += 1) {
var option = select.options[i];
var option_1 = select.options[i];
if (option.__value === select_value_value) {
option.selected = true;
if (option_1.__value === select_value_value) {
option_1.selected = true;
break;
}
}
@ -52435,10 +52457,10 @@
attr_dev(div0, "class", "uk-modal-dialog uk-modal-body svelte-vwwrf9");
attr_dev(div0, "uk-overflow-auto", "");
add_location(div0, file$k, 28, 4, 487);
add_location(div0, file$k, 28, 4, 500);
attr_dev(div1, "uk-modal", "");
attr_dev(div1, "id", ctx.id);
add_location(div1, file$k, 27, 0, 443);
add_location(div1, file$k, 27, 0, 456);
},
l: function claim(nodes) {
@ -52535,11 +52557,12 @@
};
$$self.$$.update = ($$dirty = { ukModal: 1, listenerAdded: 1, onClosed: 1, isOpen: 1 }) => {
if ($$dirty.ukModal || $$dirty.listenerAdded || $$dirty.onClosed) { if(ukModal && !listenerAdded) {
if ($$dirty.ukModal || $$dirty.listenerAdded || $$dirty.onClosed || $$dirty.isOpen) { {
if(ukModal && !listenerAdded) {
$$invalidate('listenerAdded', listenerAdded = true);
ukModal.addEventListener("hide", onClosed);
} }
if ($$dirty.ukModal || $$dirty.isOpen) { {
}
if(ukModal) {
if(isOpen) {
uikit.modal(ukModal).show();
@ -55814,7 +55837,7 @@
return child_ctx;
}
// (60:12) {#each $store.hierarchy.children as record}
// (83:12) {#each $store.hierarchy.children as record}
function create_each_block_1$8(ctx) {
var current;
@ -55855,11 +55878,11 @@
destroy_component(hierarchyrow, detaching);
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block_1$8.name, type: "each", source: "(60:12) {#each $store.hierarchy.children as record}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block_1$8.name, type: "each", source: "(83:12) {#each $store.hierarchy.children as record}", ctx });
return block;
}
// (65:12) {#each $store.hierarchy.indexes as index}
// (88:12) {#each $store.hierarchy.indexes as index}
function create_each_block$d(ctx) {
var current;
@ -55900,7 +55923,7 @@
destroy_component(hierarchyrow, detaching);
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block$d.name, type: "each", source: "(65:12) {#each $store.hierarchy.indexes as index}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block$d.name, type: "each", source: "(88:12) {#each $store.hierarchy.indexes as index}", ctx });
return block;
}
@ -55982,19 +56005,19 @@
t6 = space();
navitem1.$$.fragment.c();
attr_dev(div0, "class", "svelte-19lmivt");
add_location(div0, file$u, 52, 16, 1390);
add_location(div0, file$u, 75, 16, 1728);
attr_dev(div1, "class", "hierarchy-title svelte-19lmivt");
add_location(div1, file$u, 53, 16, 1450);
add_location(div1, file$u, 76, 16, 1788);
attr_dev(div2, "class", "nav-group-header svelte-19lmivt");
add_location(div2, file$u, 51, 12, 1343);
add_location(div2, file$u, 74, 12, 1681);
attr_dev(div3, "class", "components-list-container");
add_location(div3, file$u, 50, 8, 1291);
add_location(div3, file$u, 73, 8, 1629);
attr_dev(div4, "class", "hierarchy-items-container svelte-19lmivt");
add_location(div4, file$u, 58, 8, 1614);
add_location(div4, file$u, 81, 8, 1952);
attr_dev(div5, "class", "hierarchy svelte-19lmivt");
add_location(div5, file$u, 49, 4, 1259);
add_location(div5, file$u, 72, 4, 1597);
attr_dev(div6, "class", "items-root svelte-19lmivt");
add_location(div6, file$u, 48, 0, 1230);
add_location(div6, file$u, 71, 0, 1568);
},
l: function claim(nodes) {
@ -56154,33 +56177,56 @@
const newRootRecord = () => {
store.newRootRecord();
};
const newRootIndex = () => {
store.newRootIndex();
};
const newChildRecord = () => {
store.newChildRecord();
};
const newChildIndex = () => {
store.newChildIndex();
};
const defaultNewChildActions = [
{
label:"New Root Index",
onclick: store.newRootIndex
label:"New Root Record",
onclick: newRootRecord
},
{
label:"New Root Record",
onclick: store.newRootRecord
label:"New Root Index",
onclick: newRootIndex
}
];
let newChildActions = defaultNewChildActions;
store.subscribe(db => {
if(!db.currentNode || hierarchyFunctions.isIndex(db.currentNode)) {
$$invalidate('newChildActions', newChildActions = defaultNewChildActions);
} else {
$$invalidate('newChildActions', newChildActions = [
{label:"New Root Record",
onclick: store.newRootRecord},
{label: `New Child Record of ${db.currentNode.name}`,
onclick: store.newChildRecord},
{label:"New Root Index",
onclick: store.newRootIndex},
{label: `New Index on ${db.currentNode.name}`,
onclick: store.newChildIndex}
{
label:"New Root Record",
onclick: newRootRecord
},
{
label:"New Root Index",
onclick: newRootIndex
},
{
label: `New Child Record of ${db.currentNode.name}`,
onclick: newChildRecord
},
{
label: `New Index on ${db.currentNode.name}`,
onclick: newChildIndex
}
]);
}
});
@ -60809,7 +60855,7 @@
return child_ctx;
}
// (93:8) {#if !record.isSingle}
// (99:8) {#if !record.isSingle}
function create_if_block_3$3(ctx) {
var updating_text, t, updating_text_1, current;
@ -60894,11 +60940,11 @@
destroy_component(textbox1, detaching);
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block_3$3.name, type: "if", source: "(93:8) {#if !record.isSingle}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block_3$3.name, type: "if", source: "(99:8) {#if !record.isSingle}", ctx });
return block;
}
// (131:4) {:else}
// (137:4) {:else}
function create_else_block_1$1(ctx) {
var t;
@ -60919,11 +60965,11 @@
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_else_block_1$1.name, type: "else", source: "(131:4) {:else}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_else_block_1$1.name, type: "else", source: "(137:4) {:else}", ctx });
return block;
}
// (104:4) {#if record.fields.length > 0}
// (110:4) {#if record.fields.length > 0}
function create_if_block_2$5(ctx) {
var table, thead, tr, th0, t1, th1, t3, th2, t5, th3, t6, tbody;
@ -60957,21 +61003,21 @@
each_blocks[i].c();
}
attr_dev(th0, "class", "svelte-18xd5y3");
add_location(th0, file$A, 107, 16, 2954);
add_location(th0, file$A, 113, 16, 3154);
attr_dev(th1, "class", "svelte-18xd5y3");
add_location(th1, file$A, 108, 16, 2984);
add_location(th1, file$A, 114, 16, 3184);
attr_dev(th2, "class", "svelte-18xd5y3");
add_location(th2, file$A, 109, 16, 3014);
add_location(th2, file$A, 115, 16, 3214);
attr_dev(th3, "class", "svelte-18xd5y3");
add_location(th3, file$A, 110, 16, 3047);
add_location(th3, file$A, 116, 16, 3247);
attr_dev(tr, "class", "svelte-18xd5y3");
add_location(tr, file$A, 106, 12, 2933);
add_location(tr, file$A, 112, 12, 3133);
attr_dev(thead, "class", "svelte-18xd5y3");
add_location(thead, file$A, 105, 8, 2913);
add_location(thead, file$A, 111, 8, 3113);
attr_dev(tbody, "class", "svelte-18xd5y3");
add_location(tbody, file$A, 113, 8, 3100);
add_location(tbody, file$A, 119, 8, 3300);
attr_dev(table, "class", "fields-table uk-table svelte-18xd5y3");
add_location(table, file$A, 104, 4, 2867);
add_location(table, file$A, 110, 4, 3067);
},
m: function mount(target, anchor) {
@ -61025,11 +61071,11 @@
destroy_each(each_blocks, detaching);
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block_2$5.name, type: "if", source: "(104:4) {#if record.fields.length > 0}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block_2$5.name, type: "if", source: "(110:4) {#if record.fields.length > 0}", ctx });
return block;
}
// (115:12) {#each record.fields as field}
// (121:12) {#each record.fields as field}
function create_each_block_1$9(ctx) {
var tr, td0, div0, t0_value = ctx.field.label + "", t0, t1, div1, t2_value = ctx.field.name + "", t2, t3, td1, t4_value = ctx.field.type + "", t4, t5, td2, raw0_value = ctx.getTypeOptions(ctx.field.typeOptions) + "", t6, td3, span0, raw1_value = getIcon("edit") + "", t7, span1, raw2_value = getIcon("trash") + "", t8, dispose;
@ -61062,24 +61108,24 @@
span1 = element("span");
t8 = space();
attr_dev(div0, "class", "field-label svelte-18xd5y3");
add_location(div0, file$A, 117, 20, 3210);
add_location(div0, file$A, 123, 20, 3410);
set_style(div1, "font-size", "0.8em");
set_style(div1, "color", "var(--slate)");
add_location(div1, file$A, 118, 20, 3275);
add_location(div1, file$A, 124, 20, 3475);
attr_dev(td0, "class", "svelte-18xd5y3");
add_location(td0, file$A, 116, 16, 3184);
add_location(td0, file$A, 122, 16, 3384);
attr_dev(td1, "class", "svelte-18xd5y3");
add_location(td1, file$A, 120, 16, 3383);
add_location(td1, file$A, 126, 16, 3583);
attr_dev(td2, "class", "svelte-18xd5y3");
add_location(td2, file$A, 121, 16, 3422);
add_location(td2, file$A, 127, 16, 3622);
attr_dev(span0, "class", "edit-button svelte-18xd5y3");
add_location(span0, file$A, 123, 20, 3515);
add_location(span0, file$A, 129, 20, 3715);
attr_dev(span1, "class", "edit-button svelte-18xd5y3");
add_location(span1, file$A, 124, 20, 3626);
add_location(span1, file$A, 130, 20, 3826);
attr_dev(td3, "class", "svelte-18xd5y3");
add_location(td3, file$A, 122, 16, 3490);
add_location(td3, file$A, 128, 16, 3690);
attr_dev(tr, "class", "svelte-18xd5y3");
add_location(tr, file$A, 115, 12, 3163);
add_location(tr, file$A, 121, 12, 3363);
dispose = [
listen_dev(span0, "click", click_handler),
@ -61138,11 +61184,11 @@
run_all(dispose);
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block_1$9.name, type: "each", source: "(115:12) {#each record.fields as field}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block_1$9.name, type: "each", source: "(121:12) {#each record.fields as field}", ctx });
return block;
}
// (135:4) {#if editingField}
// (141:4) {#if editingField}
function create_if_block_1$8(ctx) {
var updating_isOpen, current;
@ -61198,11 +61244,11 @@
destroy_component(modal, detaching);
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block_1$8.name, type: "if", source: "(135:4) {#if editingField}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block_1$8.name, type: "if", source: "(141:4) {#if editingField}", ctx });
return block;
}
// (136:4) <Modal bind:isOpen={editingField}>
// (142:4) <Modal bind:isOpen={editingField}>
function create_default_slot$6(ctx) {
var current;
@ -61251,11 +61297,11 @@
destroy_component(fieldview, detaching);
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_default_slot$6.name, type: "slot", source: "(136:4) <Modal bind:isOpen={editingField}>", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_default_slot$6.name, type: "slot", source: "(142:4) <Modal bind:isOpen={editingField}>", ctx });
return block;
}
// (171:4) {:else}
// (177:4) {:else}
function create_else_block$6(ctx) {
var div;
@ -61264,7 +61310,7 @@
div = element("div");
div.textContent = "No indexes added.\n ";
attr_dev(div, "class", "no-indexes svelte-18xd5y3");
add_location(div, file$A, 171, 4, 5114);
add_location(div, file$A, 177, 4, 5314);
},
m: function mount(target, anchor) {
@ -61277,11 +61323,11 @@
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_else_block$6.name, type: "else", source: "(171:4) {:else}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_else_block$6.name, type: "else", source: "(177:4) {:else}", ctx });
return block;
}
// (164:8) {#if index.filter}
// (170:8) {#if index.filter}
function create_if_block$i(ctx) {
var div, span, t1, code, t2_value = ctx.index.filter + "", t2;
@ -61294,11 +61340,11 @@
code = element("code");
t2 = text(t2_value);
attr_dev(span, "class", "index-label svelte-18xd5y3");
add_location(span, file$A, 165, 12, 4953);
add_location(span, file$A, 171, 12, 5153);
attr_dev(code, "class", "index-mapfilter svelte-18xd5y3");
add_location(code, file$A, 166, 12, 5006);
add_location(code, file$A, 172, 12, 5206);
attr_dev(div, "class", "index-field-row svelte-18xd5y3");
add_location(div, file$A, 164, 8, 4911);
add_location(div, file$A, 170, 8, 5111);
},
m: function mount(target, anchor) {
@ -61321,11 +61367,11 @@
}
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block$i.name, type: "if", source: "(164:8) {#if index.filter}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_if_block$i.name, type: "if", source: "(170:8) {#if index.filter}", ctx });
return block;
}
// (148:4) {#each record.indexes as index}
// (154:4) {#each record.indexes as index}
function create_each_block$f(ctx) {
var div3, div0, t0_value = ctx.index.name + "", t0, t1, span0, raw_value = getIcon("edit") + "", t2, div1, span1, t4, span2, t5_value = ctx.getIndexAllowedRecords(ctx.index) + "", t5, t6, span3, t8, span4, t9_value = ctx.index.indexType + "", t9, t10, div2, span5, t12, code, t13_value = ctx.index.map + "", t13, t14, t15, dispose;
@ -61366,26 +61412,26 @@
if (if_block) if_block.c();
t15 = space();
set_style(span0, "margin-left", "7px");
add_location(span0, file$A, 151, 12, 4306);
add_location(span0, file$A, 157, 12, 4506);
attr_dev(div0, "class", "index-name svelte-18xd5y3");
add_location(div0, file$A, 149, 8, 4244);
add_location(div0, file$A, 155, 8, 4444);
attr_dev(span1, "class", "index-label svelte-18xd5y3");
add_location(span1, file$A, 154, 12, 4467);
add_location(span2, file$A, 155, 12, 4531);
add_location(span1, file$A, 160, 12, 4667);
add_location(span2, file$A, 161, 12, 4731);
attr_dev(span3, "class", "index-label svelte-18xd5y3");
set_style(span3, "margin-left", "15px");
add_location(span3, file$A, 156, 12, 4588);
add_location(span4, file$A, 157, 12, 4666);
add_location(span3, file$A, 162, 12, 4788);
add_location(span4, file$A, 163, 12, 4866);
attr_dev(div1, "class", "index-field-row svelte-18xd5y3");
add_location(div1, file$A, 153, 8, 4425);
add_location(div1, file$A, 159, 8, 4625);
attr_dev(span5, "class", "index-label svelte-18xd5y3");
add_location(span5, file$A, 160, 12, 4762);
add_location(span5, file$A, 166, 12, 4962);
attr_dev(code, "class", "index-mapfilter svelte-18xd5y3");
add_location(code, file$A, 161, 12, 4812);
add_location(code, file$A, 167, 12, 5012);
attr_dev(div2, "class", "index-field-row svelte-18xd5y3");
add_location(div2, file$A, 159, 8, 4720);
add_location(div2, file$A, 165, 8, 4920);
attr_dev(div3, "class", "index-container svelte-18xd5y3");
add_location(div3, file$A, 148, 4, 4206);
add_location(div3, file$A, 154, 4, 4406);
dispose = listen_dev(span0, "click", click_handler_2);
},
@ -61459,7 +61505,7 @@
dispose();
}
};
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block$f.name, type: "each", source: "(148:4) {#each record.indexes as index}", ctx });
dispatch_dev("SvelteRegisterBlock", { block, id: create_each_block$f.name, type: "each", source: "(154:4) {#each record.indexes as index}", ctx });
return block;
}
@ -61479,6 +61525,7 @@
var textbox = new Textbox({ props: textbox_props, $$inline: true });
binding_callbacks.push(() => bind(textbox, 'text', textbox_text_binding));
textbox.$on("change", ctx.nameChanged);
var if_block0 = (!ctx.record.isSingle) && create_if_block_3$3(ctx);
@ -61537,19 +61584,19 @@
each_blocks[i].c();
}
attr_dev(h30, "class", "settings-title svelte-18xd5y3");
add_location(h30, file$A, 87, 8, 2306);
add_location(h30, file$A, 93, 8, 2479);
attr_dev(div0, "class", "recordkey svelte-18xd5y3");
add_location(div0, file$A, 96, 8, 2636);
add_location(div0, file$A, 102, 8, 2836);
attr_dev(form, "class", "uk-form-horizontal");
add_location(form, file$A, 86, 4, 2264);
add_location(form, file$A, 92, 4, 2437);
attr_dev(span, "class", "add-field-button svelte-18xd5y3");
add_location(span, file$A, 100, 15, 2735);
add_location(span, file$A, 106, 15, 2935);
attr_dev(h31, "class", "title svelte-18xd5y3");
add_location(h31, file$A, 99, 4, 2701);
add_location(h31, file$A, 105, 4, 2901);
attr_dev(h32, "class", "title svelte-18xd5y3");
add_location(h32, file$A, 143, 4, 4119);
add_location(h32, file$A, 149, 4, 4319);
attr_dev(div1, "class", "root svelte-18xd5y3");
add_location(div1, file$A, 84, 0, 2240);
add_location(div1, file$A, 90, 0, 2413);
dispose = listen_dev(span, "click", ctx.newField);
},
@ -61798,6 +61845,13 @@
fp_41("<br>")
]);
const nameChanged = ev => {
const pluralName = n => `${n}s`;
if(record.collectionName === "") {
$$invalidate('record', record.collectionName = pluralName(ev.target.value), record);
}
};
function textbox_text_binding(value) {
record.name = value;
$$invalidate('record', record);
@ -61855,6 +61909,7 @@
onFinishedFieldEdit,
editIndex,
getTypeOptions,
nameChanged,
$store,
textbox_text_binding,
textbox0_text_binding,

File diff suppressed because one or more lines are too long