diff --git a/src/components/grid/grid.tsx b/src/components/grid/grid.tsx index 5bcc9ac..edba912 100644 --- a/src/components/grid/grid.tsx +++ b/src/components/grid/grid.tsx @@ -1,6 +1,7 @@ import { Accessor, createContext, createEffect, createMemo, createSignal, JSX, useContext } from "solid-js"; import { Mutation } from "~/utilities"; -import { SelectionMode, Table, Column as TableColumn, TableApi, DataSet, CellRenderer as TableCellRenderer } from "~/components/table"; +import { SelectionMode, Table, Column as TableColumn, TableApi, CellRenderer as TableCellRenderer } from "~/components/table"; +import { DataSet } from "~/features/dataset"; import css from './grid.module.css'; export interface CellRenderer, K extends keyof T> { diff --git a/src/components/table/index.tsx b/src/components/table/index.tsx index b4aabe5..b06de34 100644 --- a/src/components/table/index.tsx +++ b/src/components/table/index.tsx @@ -1,5 +1,3 @@ export type { Column, TableApi, CellRenderer, CellRenderers } from './table'; -export type { DataSet, DataSetGroupNode, DataSetRowNode, DataSetNode, SortingFunction, SortOptions, GroupingFunction, GroupOptions } from './dataset'; -export { SelectionMode, Table } from './table'; -export { createDataSet } from './dataset'; \ No newline at end of file +export { SelectionMode, Table } from './table'; \ No newline at end of file diff --git a/src/components/table/table.tsx b/src/components/table/table.tsx index 115a987..10ffc0c 100644 --- a/src/components/table/table.tsx +++ b/src/components/table/table.tsx @@ -1,6 +1,6 @@ import { Accessor, createContext, createEffect, createMemo, createSignal, For, JSX, Match, Show, Switch, useContext } from "solid-js"; import { selectable, SelectionItem, SelectionProvider, useSelection } from "~/features/selectable"; -import { DataSetRowNode, DataSetNode, DataSet } from './dataset'; +import { DataSetRowNode, DataSetNode, DataSet } from '~/features/dataset'; import { FaSolidAngleDown, FaSolidSort, FaSolidSortDown, FaSolidSortUp } from "solid-icons/fa"; import css from './table.module.css'; diff --git a/src/components/table/dataset.spec.ts b/src/features/dataset/index.spec.ts similarity index 96% rename from src/components/table/dataset.spec.ts rename to src/features/dataset/index.spec.ts index e2fade5..13ffea9 100644 --- a/src/components/table/dataset.spec.ts +++ b/src/features/dataset/index.spec.ts @@ -1,16 +1,17 @@ import { describe, expect, it } from "bun:test"; -import { createDataSet } from "./dataset"; +import { createDataSet } from "./index"; +import { createSignal } from "solid-js"; interface DataEntry { id: string; name: string; amount: number; }; -const defaultData: DataEntry[] = [ +const [defaultData] = createSignal([ { id: '1', name: 'a first name', amount: 30 }, { id: '2', name: 'a second name', amount: 20 }, { id: '3', name: 'a third name', amount: 10 }, -]; +]); describe('dataset', () => { describe('createDataset', () => { diff --git a/src/components/table/dataset.ts b/src/features/dataset/index.ts similarity index 66% rename from src/components/table/dataset.ts rename to src/features/dataset/index.ts index a46034e..b69ec03 100644 --- a/src/components/table/dataset.ts +++ b/src/features/dataset/index.ts @@ -1,8 +1,7 @@ -import { Accessor, createEffect, createMemo } from "solid-js"; -import { createStore, NotWrappable, produce, StoreSetter, unwrap } from "solid-js/store"; +import { Accessor, createEffect, createMemo, untrack } from "solid-js"; +import { createStore, produce } from "solid-js/store"; import { CustomPartial } from "solid-js/store/types/store.js"; -import { deepCopy, deepDiff, Mutation } from "~/utilities"; - +import { deepCopy, deepDiff, MutarionKind, Mutation } from "~/utilities"; export type DataSetRowNode = { kind: 'row', key: K, value: T } export type DataSetGroupNode = { kind: 'group', key: K, groupedBy: keyof T, nodes: DataSetNode[] }; @@ -37,7 +36,6 @@ export type Setter = | ((prevState: T) => T | CustomPartial); export interface DataSet> { - data: T[]; nodes: Accessor[]>; mutations: Accessor; readonly value: (T | undefined)[]; @@ -59,10 +57,10 @@ function defaultGroupingFunction(groupBy: keyof T): GroupingFunction ({ kind: 'group', key, groupedBy: groupBy, nodes: nodes! } as DataSetGroupNode)); } -export const createDataSet = >(data: T[], initialOptions?: { sort?: SortOptions, group?: GroupOptions }): DataSet => { +export const createDataSet = >(data: Accessor, initialOptions?: { sort?: SortOptions, group?: GroupOptions }): DataSet => { const [state, setState] = createStore>({ - value: deepCopy(data), - snapshot: data, + value: deepCopy(data()), + snapshot: data(), sorting: initialOptions?.sort, grouping: initialOptions?.group, }); @@ -101,8 +99,79 @@ export const createDataSet = >(data: T[], initialO return deepDiff(state.snapshot, state.value).toArray(); }); + const apply = (data: T[], mutations: Mutation[]) => { + for (const mutation of mutations) { + const path = mutation.key.split('.'); + + switch (mutation.kind) { + case MutarionKind.Create: { + let v: any = data; + for (const part of path.slice(0, -1)) { + if (v[part] === undefined) { + v[part] = {}; + } + + v = v[part]; + } + + v[path.at(-1)!] = mutation.value; + + break; + } + + case MutarionKind.Delete: { + let v: any = data; + for (const part of path.slice(0, -1)) { + if (v === undefined) { + break; + } + + v = v[part]; + } + + if (v !== undefined) { + delete v[path.at(-1)!]; + } + + break; + } + + case MutarionKind.Update: { + let v: any = data; + for (const part of path.slice(0, -1)) { + if (v === undefined) { + break; + } + + v = v[part]; + } + + if (v !== undefined) { + v[path.at(-1)!] = mutation.value; + } + + break; + } + } + } + + return data; + }; + + createEffect(() => { + const next = data(); + const nextValue = apply(deepCopy(next), untrack(() => mutations())); + + setState('value', nextValue); + setState('snapshot', next); + ; + }); + + createEffect(() => { + console.log('dataset', mutations()); + }); + const set: DataSet = { - data, nodes, get value() { return state.value; @@ -148,5 +217,5 @@ export const createDataSet = >(data: T[], initialO }, }; - return set + return set; }; \ No newline at end of file diff --git a/src/features/file/grid.tsx b/src/features/file/grid.tsx index 93e118d..01859b4 100644 --- a/src/features/file/grid.tsx +++ b/src/features/file/grid.tsx @@ -1,7 +1,7 @@ -import { Accessor, Component, createEffect, createMemo, createSignal, JSX } from "solid-js"; +import { Accessor, Component, createEffect, createMemo, createSignal, JSX, untrack } from "solid-js"; import { decode, Mutation } from "~/utilities"; import { Column, GridApi as GridCompApi, Grid as GridComp } from "~/components/grid"; -import { createDataSet, DataSetNode, DataSetRowNode } from "~/components/table"; +import { createDataSet, DataSetNode, DataSetRowNode } from "~/features/dataset"; import { SelectionItem } from "../selectable"; import { useI18n } from "../i18n"; import { debounce } from "@solid-primitives/scheduled"; @@ -35,7 +35,7 @@ export function Grid(props: { class?: string, rows: Entry[], locales: string[], const { t } = useI18n(); const [addedLocales, setAddedLocales] = createSignal([]); - const rows = createMemo(() => createDataSet(props.rows, { group: { by: 'key', with: groupBy } })); + const rows = createDataSet(() => props.rows, { group: { by: 'key', with: groupBy } }); const locales = createMemo(() => [...props.locales, ...addedLocales()]); const columns = createMemo[]>(() => [ { @@ -47,7 +47,7 @@ export function Grid(props: { class?: string, rows: Entry[], locales: string[], id: lang, label: lang, renderer: ({ row, column, value, mutate }) => { - const entry = rows().value[row]!; + const entry = rows.value[row]!; return