Schema change 230933223
parent
95e346558c
commit
906a62596f
|
@ -0,0 +1,31 @@
|
|||
import { FolderNode } from "../constants";
|
||||
import { ingest } from "../data_transfer";
|
||||
|
||||
// const MOCKUP_SEQUENCES: Record<number, string> = {
|
||||
// 1: "Another sequence",
|
||||
// 2: "Some random sequence",
|
||||
// 3: "Planting seeds",
|
||||
// 4: "Purple rain",
|
||||
// 5: "Make it rain",
|
||||
// };
|
||||
|
||||
const FOLDERS: FolderNode[] = [
|
||||
{ id: 1, color: "blue", name: "Water stuff", parent_id: undefined },
|
||||
{ id: 2, color: "green", name: "Folder for growing things", parent_id: undefined },
|
||||
{ id: 3, color: "yellow", name: "subfolder", parent_id: 2 },
|
||||
{ id: 4, color: "gray", name: "tests", parent_id: undefined },
|
||||
{ id: 5, color: "pink", name: "deeply nested directory", parent_id: 3 }
|
||||
];
|
||||
|
||||
describe("data transfer", () => {
|
||||
it("converts flat data into hierarchical data", () => {
|
||||
const x = ingest(FOLDERS);
|
||||
const { folders } = x;
|
||||
expect(folders.length).toEqual(3);
|
||||
const names = folders.map(x => x.name);
|
||||
["Water stuff", "Folder for growing things", "tests"].map(name => {
|
||||
expect(names).toContain(name);
|
||||
});
|
||||
fail("Next task: Populate `medial` and `terminal` nodes.");
|
||||
});
|
||||
});
|
|
@ -2,7 +2,7 @@ import { Color } from "farmbot/dist/corpus";
|
|||
|
||||
interface SFile { uuid: string; }
|
||||
|
||||
interface FolderNode {
|
||||
interface FolderUI {
|
||||
name: string;
|
||||
content: SFile[];
|
||||
color?: Color;
|
||||
|
@ -10,20 +10,20 @@ interface FolderNode {
|
|||
}
|
||||
|
||||
/** A top-level directory */
|
||||
interface FolderNodeInitial extends FolderNode {
|
||||
interface FolderNodeInitial extends FolderUI {
|
||||
kind: "initial";
|
||||
children: (FolderNodeMedial | FolderNodeTerminal)[];
|
||||
}
|
||||
|
||||
/** A mid-level directory. */
|
||||
interface FolderNodeMedial extends FolderNode {
|
||||
interface FolderNodeMedial extends FolderUI {
|
||||
kind: "medial";
|
||||
children: FolderNodeTerminal;
|
||||
}
|
||||
|
||||
/** A leaf node on the directory tree.
|
||||
* Never has a child */
|
||||
interface FolderNodeTerminal extends FolderNode {
|
||||
interface FolderNodeTerminal extends FolderUI {
|
||||
kind: "terminal";
|
||||
children?: never[];
|
||||
}
|
||||
|
@ -33,42 +33,9 @@ export interface RootFolderNode {
|
|||
}
|
||||
|
||||
/** === THIS WILL LIVE ON THE API === */
|
||||
export interface FlatNode {
|
||||
export interface FolderNode {
|
||||
id: number;
|
||||
name_id: number;
|
||||
color: Color;
|
||||
sequence_ids: number[];
|
||||
}
|
||||
|
||||
/** === THIS WILL LIVE ON THE API === */
|
||||
export interface FlatNodeName {
|
||||
id: number;
|
||||
value: string;
|
||||
parent_id?: number;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export const MOCKUP_SEQUENCES: Record<number, string> = {
|
||||
1: "Another sequence",
|
||||
2: "Some random sequence",
|
||||
3: "Planting seeds",
|
||||
4: "Purple rain",
|
||||
5: "Make it rain",
|
||||
};
|
||||
|
||||
export const MOCKUP_NODE_NAMES: FlatNodeName[] = [
|
||||
{ id: 1, value: "Water stuff", parent_id: undefined },
|
||||
{ id: 2, value: "Folder for growing things", parent_id: undefined },
|
||||
{ id: 3, value: "subfolder", parent_id: 2 },
|
||||
{ id: 4, value: "tests", parent_id: undefined }
|
||||
];
|
||||
|
||||
export const MOCKUP_FLAT_NODES: FlatNode[] = [
|
||||
{ id: 1, name_id: 1, color: "red", sequence_ids: [] },
|
||||
{ id: 1, name_id: 2, color: "red", sequence_ids: [] },
|
||||
{ id: 1, name_id: 3, color: "red", sequence_ids: [5, 4] },
|
||||
{ id: 1, name_id: 4, color: "red", sequence_ids: [] },
|
||||
];
|
||||
|
||||
export const MOCKUP_TREE: RootFolderNode = {
|
||||
folders: []
|
||||
};
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
import {
|
||||
FlatNode,
|
||||
FlatNodeName,
|
||||
RootFolderNode
|
||||
} from "./constants";
|
||||
import { RootFolderNode, FolderNode } from "./constants";
|
||||
|
||||
type NodeName = Required<FlatNodeName>;
|
||||
type NodeNameIndex = Record<number, NodeName[]>;
|
||||
type FoldersIndexedByParentId = Record<number, FolderNode[]>;
|
||||
|
||||
const z: Readonly<NodeNameIndex> = {};
|
||||
|
||||
const mapper =
|
||||
(x: FlatNodeName): NodeName => ({ ...x, parent_id: x.parent_id || -1 });
|
||||
|
||||
const reducer = (accum: NodeNameIndex, item: NodeName): NodeNameIndex => {
|
||||
const { parent_id } = item;
|
||||
const list = (accum[parent_id] || []);
|
||||
|
||||
return { ...accum, [parent_id]: [...list, item] };
|
||||
/** Set empty `parent_id` to -1 to increase index simplicity. */
|
||||
const setDefaultParentId = (input: FolderNode): Required<FolderNode> => {
|
||||
return { ...input, parent_id: input.parent_id || -1 };
|
||||
};
|
||||
|
||||
export function ingest(_folders: FlatNode[], names: FlatNodeName[]): RootFolderNode {
|
||||
const output = { folders: [] };
|
||||
// const nameIndex =
|
||||
names.map(mapper).reduce(reducer, z);
|
||||
// const keys: keyof typeof nameIndex =
|
||||
// Object.keys(nameIndex).map(x => parseInt(x, 10)).sort();
|
||||
// keys.
|
||||
const addToIndex =
|
||||
(accumulator: FoldersIndexedByParentId, item: Required<FolderNode>) => {
|
||||
const key = item.parent_id;
|
||||
const value = accumulator[key] || [];
|
||||
|
||||
return { ...accumulator, [key]: [...value, item] };
|
||||
};
|
||||
|
||||
const emptyIndex: FoldersIndexedByParentId = {};
|
||||
|
||||
export function ingest(input: FolderNode[]): RootFolderNode {
|
||||
const output: RootFolderNode = { folders: [] };
|
||||
const index = input.map(setDefaultParentId).reduce(addToIndex, emptyIndex);
|
||||
(index[-1] || []).map(y => output.folders.push({
|
||||
...y,
|
||||
kind: "initial",
|
||||
children: [],
|
||||
content: []
|
||||
}));
|
||||
return output;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue