From d4802b25243c4e43161e456ac067c1406dedef52 Mon Sep 17 00:00:00 2001 From: st4ng Date: Wed, 14 Feb 2024 00:34:42 +0100 Subject: [PATCH] Add board custom card order (#586, #652) --- src/lib/stores/translations/en.json | 4 + src/ui/app/onboarding/demoProject.ts | 2 +- .../views/Board/BoardOptionsProvider.svelte | 2 +- src/ui/views/Board/BoardView.svelte | 182 ++++++++++++++++-- src/ui/views/Board/board.ts | 82 +++++--- src/ui/views/Board/boardView.ts | 8 +- .../views/Board/components/Board/Board.svelte | 35 ++-- .../Board/components/Board/BoardColumn.svelte | 12 +- .../Board/components/Board/CardList.svelte | 51 +++-- src/ui/views/Board/components/Board/types.ts | 32 +++ .../views/Board/settings/BoardSettings.svelte | 56 ++++-- src/ui/views/Board/settings/settingsModal.ts | 3 + src/ui/views/Board/types.ts | 3 +- styles.css | 11 ++ 14 files changed, 382 insertions(+), 101 deletions(-) create mode 100644 src/ui/views/Board/components/Board/types.ts 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/ui/app/onboarding/demoProject.ts b/src/ui/app/onboarding/demoProject.ts index bd8c161e..3856b296 100644 --- a/src/ui/app/onboarding/demoProject.ts +++ b/src/ui/app/onboarding/demoProject.ts @@ -84,7 +84,7 @@ export async function createDemoProject(vault: Vault) { const boardConfig: BoardConfig = { groupByField: "status", - priorityField: "weight", + orderSyncField: "weight", }; const calendarConfig: CalendarConfig = { diff --git a/src/ui/views/Board/BoardOptionsProvider.svelte b/src/ui/views/Board/BoardOptionsProvider.svelte index abd43f0d..ecafa9fc 100644 --- a/src/ui/views/Board/BoardOptionsProvider.svelte +++ b/src/ui/views/Board/BoardOptionsProvider.svelte @@ -48,7 +48,7 @@ includedFields={config.includeFields ?? []} onIncludedFieldsChange={handleIncludedFieldsChange} onSettings={() => { - new BoardSettingsModal($app, config, (value) => { + new BoardSettingsModal($app, config, fields, (value) => { onConfigChange(value); }).open(); }} diff --git a/src/ui/views/Board/BoardView.svelte b/src/ui/views/Board/BoardView.svelte index 7632de8f..719314f4 100644 --- a/src/ui/views/Board/BoardView.svelte +++ b/src/ui/views/Board/BoardView.svelte @@ -1,59 +1,192 @@ diff --git a/src/ui/views/Board/components/Board/CardList.svelte b/src/ui/views/Board/components/Board/CardList.svelte index 985eb511..b7b56186 100644 --- a/src/ui/views/Board/components/Board/CardList.svelte +++ b/src/ui/views/Board/components/Board/CardList.svelte @@ -5,34 +5,54 @@ type DataField, type DataRecord, } from "src/lib/dataframe/dataframe"; - import { dndzone } from "svelte-dnd-action"; - import { getDisplayName } from "./boardHelpers"; import { app } from "src/lib/stores/obsidian"; - import { flip } from "svelte/animate"; - import { getRecordColorContext } from "src/ui/views/helpers"; + import { settings } from "src/lib/stores/settings"; import CardMetadata from "src/ui/components/CardMetadata/CardMetadata.svelte"; import ColorItem from "src/ui/components/ColorItem/ColorItem.svelte"; - import { settings } from "src/lib/stores/settings"; + import { + getRecordColorContext, + sortRecordsContext, + } from "src/ui/views/helpers"; + import { + SHADOW_ITEM_MARKER_PROPERTY_NAME, + TRIGGERS, + dndzone, + } from "svelte-dnd-action"; + import { flip } from "svelte/animate"; + import { getDisplayName } from "./boardHelpers"; + import type { DropTrigger, OnRecordClick, OnRecordDrop } from "./types"; export let items: DataRecord[]; - export let onRecordClick: (record: DataRecord) => void; - export let onDrop: (records: DataRecord[]) => void = () => {}; + export let onRecordClick: OnRecordClick; + export let onDrop: OnRecordDrop; export let includeFields: DataField[]; + const getRecordColor = getRecordColorContext.get(); + const sortRecords = sortRecordsContext.get(); + const flipDurationMs = 200; - function handleDndConsider(e: CustomEvent>) { - items = e.detail.items; + let dragItem: DataRecord | undefined; + function handleDndConsider({ detail }: CustomEvent>) { + items = sortRecords(detail.items); + if (detail.info.trigger === TRIGGERS.DRAG_STARTED) { + dragItem = items.find((item) => item.id === detail.info.id); + } } - function handleDndFinalize(e: CustomEvent>) { - items = e.detail.items; - if (onDrop) { - onDrop(e.detail.items); + function handleDndFinalize({ detail }: CustomEvent>) { + items = sortRecords(detail.items); + if (detail.info.trigger === TRIGGERS.DROPPED_INTO_ZONE) { + dragItem = items.find((item) => item.id === detail.info.id); + } + if (dragItem) { + onDrop(dragItem, items, detail.info.trigger as DropTrigger); + dragItem = undefined; } } - const getRecordColor = getRecordColorContext.get(); + const isPlaceholder = (item: DataRecord) => + !!(item as any)[SHADOW_ITEM_MARKER_PROPERTY_NAME];
onRecordClick(item)} animate:flip={{ duration: flipDurationMs }} diff --git a/src/ui/views/Board/components/Board/types.ts b/src/ui/views/Board/components/Board/types.ts new file mode 100644 index 00000000..a86d2766 --- /dev/null +++ b/src/ui/views/Board/components/Board/types.ts @@ -0,0 +1,32 @@ +import type { DataRecord } from "src/lib/dataframe/dataframe"; +import type { TRIGGERS } from "svelte-dnd-action"; + +export type Column = { + id: string; + records: DataRecord[]; +}; + +export type OnRecordClick = (record: DataRecord) => void; +export type OnRecordAdd = (column: string) => void; +export type OnRecordDrop = ( + record: DataRecord, + records: DataRecord[], + trigger: DropTrigger +) => void; +export type DropTrigger = + | TRIGGERS.DROPPED_INTO_ANOTHER + | TRIGGERS.DROPPED_INTO_ZONE + | TRIGGERS.DROPPED_OUTSIDE_OF_ANY; + +export type OnRecordUpdate = ( + record: DataRecord, + column: Column, + trigger: RecordUpdateTrigger +) => void; + +export type RecordUpdateTrigger = "addToColumn" | "removeFromColumn"; + +export type OnSortColumns = (names: string[]) => void; +export type OnSortRecords = ( + records: ReadonlyArray +) => DataRecord[]; diff --git a/src/ui/views/Board/settings/BoardSettings.svelte b/src/ui/views/Board/settings/BoardSettings.svelte index b9c525ea..24111f3a 100644 --- a/src/ui/views/Board/settings/BoardSettings.svelte +++ b/src/ui/views/Board/settings/BoardSettings.svelte @@ -1,18 +1,40 @@ @@ -24,16 +46,22 @@ - onSave( - produce(config, (draft) => { - const { columnWidth, ...rest } = draft; - if (!columnWidthValue) { - return rest; - } - return { ...rest, columnWidth: columnWidthValue }; - }) - )} + on:blur={() => updateConfig("columnWidth", columnWidthValue)} + /> + + +