diff --git a/src/settings/base/settings.ts b/src/settings/base/settings.ts index 812fde87..2e3a4c6d 100644 --- a/src/settings/base/settings.ts +++ b/src/settings/base/settings.ts @@ -1,3 +1,7 @@ +import { writable } from 'svelte/store'; +export const searchText = writable(""); +export const searchField = writable(""); + export type ProjectId = string; export type ViewId = string; diff --git a/src/ui/app/View.svelte b/src/ui/app/View.svelte index edcaf788..ffbe70bf 100644 --- a/src/ui/app/View.svelte +++ b/src/ui/app/View.svelte @@ -9,11 +9,13 @@ ViewDefinition, ViewId, } from "src/settings/settings"; - import { applyFilter, matchesCondition } from "./filterFunctions"; + import { applyFilter, matchesCondition, applySearch } from "./filterFunctions"; import { useView } from "./useView"; import { applySort, sortRecords } from "./viewSort"; + import { searchText, searchField } from "src/settings/settings"; + /** * Specify the project. */ @@ -76,6 +78,16 @@ $: viewFilter = view.filter ?? { conjunction: "and", conditions: [] }; $: filteredFrame = applyFilter(frame, viewFilter); + // initialize search field and frame + let filteredAndSearchedFrame = frame; + $searchField = "name"; + + $: if ($searchText !== '') { + filteredAndSearchedFrame = applySearch(filteredFrame, { conjunction: "and", conditions: [{field: $searchField, operator: "contains", value: $searchText, enabled: true}] }); + } else { + filteredAndSearchedFrame = filteredFrame; + } + $: viewSort = view.sort.criteria.length > 0 ? view.sort @@ -83,7 +95,7 @@ criteria: [{ field: "path", order: "asc", enabled: true }], } satisfies SortDefinition); - $: sortedFrame = applySort(filteredFrame, viewSort); + $: sortedFrame = applySort(filteredAndSearchedFrame, viewSort); let recordCache: Record; $: { diff --git a/src/ui/app/filterFunctions.ts b/src/ui/app/filterFunctions.ts index 4463ffba..f07d53ef 100644 --- a/src/ui/app/filterFunctions.ts +++ b/src/ui/app/filterFunctions.ts @@ -96,6 +96,44 @@ export function applyFilter( }); } +export function matchesConditionSearch( + cond: FilterCondition, + record: DataRecord +): boolean { + const { operator } = cond; + + const value: Optional = record.values[cond.field]; + + if (isStringFilterOperator(operator) && cond.value !== undefined) { + return stringFns[operator](value?.toString().toLowerCase() ?? "", cond.value.toLowerCase()); + } + return false; +} + +export function matchesSearchConditions( + filter: FilterDefinition, + record: DataRecord +) { + const validConds = filter.conditions.filter((cond) => { + return cond?.enabled ?? true; + }); + + if (!validConds.length) return true; + + return validConds.every((cond) => matchesConditionSearch(cond, record)); +} + +export function applySearch( + frame: DataFrame, + filter: FilterDefinition +): DataFrame { + return produce(frame, (draft) => { + draft.records = draft.records.filter((record) => + matchesSearchConditions(filter, record) + ); + }); +} + export const baseFns: Record< BaseFilterOperator, (value: Optional) => boolean diff --git a/src/ui/views/Board/BoardOptionsProvider.svelte b/src/ui/views/Board/BoardOptionsProvider.svelte index 3849356a..feee2dba 100644 --- a/src/ui/views/Board/BoardOptionsProvider.svelte +++ b/src/ui/views/Board/BoardOptionsProvider.svelte @@ -11,6 +11,9 @@ import { BoardSettingsModal } from "./settings/settingsModal"; import { app } from "src/lib/stores/obsidian"; + import { Select } from "obsidian-svelte"; + import { searchText, searchField } from "src/settings/settings"; + export let config: BoardConfig; export let onConfigChange: (cfg: BoardConfig) => void; @@ -47,6 +50,19 @@ + + + +