diff --git a/src/customViewApi.ts b/src/customViewApi.ts index a41416cd..5cb62865 100644 --- a/src/customViewApi.ts +++ b/src/customViewApi.ts @@ -4,6 +4,8 @@ import type { ProjectDefinition, ViewId } from "./settings/settings"; export interface DataQueryResult { data: DataFrame; + hasSort: boolean; + hasFilter: boolean; } /** @@ -18,6 +20,8 @@ export interface ProjectViewProps> { viewApi: ViewApi; readonly: boolean; getRecordColor: (record: DataRecord) => string | null; + sortRecords: (records: ReadonlyArray) => DataRecord[]; + getRecord: (id: string) => DataRecord | undefined; } /** diff --git a/src/lib/datasources/helpers.ts b/src/lib/datasources/helpers.ts index 166e5350..aa97b3b8 100644 --- a/src/lib/datasources/helpers.ts +++ b/src/lib/datasources/helpers.ts @@ -56,6 +56,20 @@ export function parseRecords( return records; } +/** + * Merges a new version of `values` into a copy of data record. + * + * @param {Readonly} record - the original data record + * @param {Readonly} values - the values to merge into the original record + * @return {DataRecord} a new data record with the merged values + */ +export function updateRecordValues( + record: Readonly, + values: Readonly +): DataRecord { + return { ...record, values: { ...record.values, ...values } }; +} + export function detectFields(records: DataRecord[]): DataField[] { const valuesByField: Record[]> = {}; diff --git a/src/lib/helpers.ts b/src/lib/helpers.ts index 8ca11362..e13233bb 100644 --- a/src/lib/helpers.ts +++ b/src/lib/helpers.ts @@ -3,6 +3,7 @@ import { get } from "svelte/store"; import { app } from "src/lib/stores/obsidian"; import type { ProjectDefinition, ViewDefinition } from "src/settings/settings"; +import { getContext, setContext } from "svelte"; import type { DataField } from "./dataframe/dataframe"; /** @@ -88,3 +89,15 @@ export function getNameFromPath(path: string) { const end: number = path.lastIndexOf("."); return path.substring(start, end); } + +export type Context = Readonly<{ + get: () => T; + set: (value: T) => void; +}>; +export function makeContext(): Context { + const key = Symbol(); + return { + get: () => getContext(key), + set: (value: T) => setContext(key, value), + }; +} diff --git a/src/lib/stores/translations/en.json b/src/lib/stores/translations/en.json index d15345c0..b2f7561c 100644 --- a/src/lib/stores/translations/en.json +++ b/src/lib/stores/translations/en.json @@ -292,6 +292,10 @@ "column-width": { "name": "Column width", "description": "Width of each column in pixels." + }, + "order-sync-field": { + "name": "Sync card order with field", + "description": "Field to store the position of cards in the board." } }, "note": { diff --git a/src/lib/stores/translations/zh-CN.json b/src/lib/stores/translations/zh-CN.json index ab184feb..4fe9482c 100644 --- a/src/lib/stores/translations/zh-CN.json +++ b/src/lib/stores/translations/zh-CN.json @@ -292,6 +292,10 @@ "column-width": { "name": "列宽度", "description": "调整每列的像素宽度。" + }, + "order-sync-field": { + "name": "卡片顺序同步字段", + "description": "该字段将用于存储卡片在看板列中的位置顺序信息。" } }, "note": { @@ -447,4 +451,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/ui/app/View.svelte b/src/ui/app/View.svelte index 92834456..91f74196 100644 --- a/src/ui/app/View.svelte +++ b/src/ui/app/View.svelte @@ -5,13 +5,14 @@ import type { ProjectDefinition, ProjectId, + SortDefinition, ViewDefinition, ViewId, } from "src/settings/settings"; import { applyFilter, matchesCondition } from "./filterFunctions"; import { useView } from "./useView"; - import { applySort } from "./viewSort"; + import { applySort, sortRecords } from "./viewSort"; /** * Specify the project. @@ -74,9 +75,21 @@ $: viewFilter = view.filter ?? { conditions: [] }; $: filteredFrame = applyFilter(frame, viewFilter); - $: viewSort = view.sort ?? { criteria: [] }; + $: viewSort = + view.sort.criteria.length > 0 + ? view.sort + : ({ + criteria: [{ field: "path", order: "asc", enabled: true }], + } satisfies SortDefinition); + $: sortedFrame = applySort(filteredFrame, viewSort); + let recordCache: Record; + $: { + frame; + recordCache = {}; + } + function getRecordColor(record: DataRecord): string | null { const colorFilter = view.colors ?? { conditions: [] }; for (const cond of colorFilter.conditions) { @@ -88,6 +101,19 @@ } return null; } + + const applyViewSortToRecords = ( + records: ReadonlyArray + ): Array => { + return sortRecords([...records], viewSort); + }; + + const getRecord = (id: string) => { + return ( + recordCache[id] ?? + (recordCache[id] = frame.records.find((record) => record.id === id)) + ); + };