From a64b8a495cd61a0e35bb96e73573f7cac960e7c4 Mon Sep 17 00:00:00 2001 From: Danielo Rodriguez Date: Sun, 23 Jun 2024 07:32:40 +0200 Subject: [PATCH 01/21] WIP: condition schema --- src/core/findInputDefinitionSchema.ts | 6 ++--- src/core/formDefinition.test.ts | 4 ++-- src/core/formDefinition.ts | 10 ++++---- src/core/formDefinitionSchema.ts | 24 +++++++++---------- src/core/index.ts | 2 +- src/core/{ => input}/InputDefinitionSchema.ts | 2 +- src/core/input/dependentFields.ts | 17 +++++++++++++ src/core/input/index.ts | 2 ++ src/views/components/MultiSelectModel.ts | 2 +- 9 files changed, 44 insertions(+), 25 deletions(-) rename src/core/{ => input}/InputDefinitionSchema.ts (98%) create mode 100644 src/core/input/dependentFields.ts create mode 100644 src/core/input/index.ts diff --git a/src/core/findInputDefinitionSchema.ts b/src/core/findInputDefinitionSchema.ts index db8ccb68..4a114703 100644 --- a/src/core/findInputDefinitionSchema.ts +++ b/src/core/findInputDefinitionSchema.ts @@ -1,9 +1,9 @@ import { A, NonEmptyArray, ParsingFn, parse, pipe } from "@std"; import * as E from "fp-ts/Either"; -import { ValiError, BaseSchema } from "valibot"; -import { FieldMinimal, FieldMinimalSchema } from "./formDefinitionSchema"; +import { BaseSchema, ValiError } from "valibot"; import { AllFieldTypes } from "./formDefinition"; -import { InputTypeToParserMap } from "./InputDefinitionSchema"; +import { FieldMinimal, FieldMinimalSchema } from "./formDefinitionSchema"; +import { InputTypeToParserMap } from "./input/InputDefinitionSchema"; export function stringifyIssues(error: ValiError): NonEmptyArray { return error.issues.map( diff --git a/src/core/formDefinition.test.ts b/src/core/formDefinition.test.ts index 4351b33c..618820c8 100644 --- a/src/core/formDefinition.test.ts +++ b/src/core/formDefinition.test.ts @@ -1,4 +1,4 @@ -import { MultiselectSchema } from "./InputDefinitionSchema"; +import { parse } from "valibot"; import { isDataViewSource, isInputNoteFromFolder, @@ -6,7 +6,7 @@ import { isInputSlider, isSelectFromNotes, } from "./formDefinition"; -import { parse } from "valibot"; +import { MultiselectSchema } from "./input/InputDefinitionSchema"; describe("isDataViewSource", () => { it("should return true for valid inputDataviewSource objects", () => { diff --git a/src/core/formDefinition.ts b/src/core/formDefinition.ts index 22723f52..902e8450 100644 --- a/src/core/formDefinition.ts +++ b/src/core/formDefinition.ts @@ -1,13 +1,13 @@ -import { type Output, is, safeParse } from "valibot"; +import { A, O, pipe } from "@std"; +import { Simplify } from "type-fest"; +import { is, safeParse, type Output } from "valibot"; import { FieldDefinitionSchema, - FormDefinitionLatestSchema, FieldListSchema, FormDefinitionBasicSchema, + FormDefinitionLatestSchema, MigrationError, } from "./formDefinitionSchema"; -import { A, O, pipe } from "@std"; -import { Simplify } from "type-fest"; import { InputBasicSchema, InputDataviewSourceSchema, @@ -25,7 +25,7 @@ import { inputType, multiselect, selectFromNotes, -} from "./InputDefinitionSchema"; +} from "./input/InputDefinitionSchema"; export const InputTypeReadable: Record = { text: "Text", diff --git a/src/core/formDefinitionSchema.ts b/src/core/formDefinitionSchema.ts index 72c1a542..49135002 100644 --- a/src/core/formDefinitionSchema.ts +++ b/src/core/formDefinitionSchema.ts @@ -1,23 +1,23 @@ +import { parse, pipe } from "@std"; import * as E from "fp-ts/Either"; -import { pipe, parse } from "@std"; import { - object, - literal, - type Output, - is, + ValiError, array, - string, - optional, + boolean, + is, + literal, merge, - unknown, - ValiError, + object, + optional, passthrough, - boolean, + string, + unknown, + type Output, } from "valibot"; -import { FormDefinition } from "./formDefinition"; import { findFieldErrors, stringifyIssues } from "./findInputDefinitionSchema"; +import { FormDefinition } from "./formDefinition"; +import { InputTypeSchema, nonEmptyString } from "./input/InputDefinitionSchema"; import { ParsedTemplateSchema } from "./template/templateSchema"; -import { InputTypeSchema, nonEmptyString } from "./InputDefinitionSchema"; /** * Here are the core logic around the main domain of the plugin, diff --git a/src/core/index.ts b/src/core/index.ts index 18bae0a7..17c74051 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -1 +1 @@ -export * as input from "./InputDefinitionSchema"; +export * as input from "./input"; diff --git a/src/core/InputDefinitionSchema.ts b/src/core/input/InputDefinitionSchema.ts similarity index 98% rename from src/core/InputDefinitionSchema.ts rename to src/core/input/InputDefinitionSchema.ts index 841e26ad..5dfe0f08 100644 --- a/src/core/InputDefinitionSchema.ts +++ b/src/core/input/InputDefinitionSchema.ts @@ -16,7 +16,7 @@ import { toTrimmed, union, } from "valibot"; -import { AllFieldTypes, AllSources } from "./formDefinition"; +import { AllFieldTypes, AllSources } from "../formDefinition"; /** * Here are the definition for the input types. diff --git a/src/core/input/dependentFields.ts b/src/core/input/dependentFields.ts new file mode 100644 index 00000000..bca0b6eb --- /dev/null +++ b/src/core/input/dependentFields.ts @@ -0,0 +1,17 @@ +import * as v from "valibot"; +const isSet = v.object({ field: v.string(), type: v.literal("isSet") }); +const booleanValue = v.object({ + field: v.string(), + type: v.literal("boolean"), + value: v.boolean(), +}); +const startsWith = v.object({ + field: v.string(), + type: v.literal("startsWith"), + value: v.string(), +}); +const above = v.object({ field: v.string(), type: v.literal("above"), value: v.number() }); +const below = v.object({ field: v.string(), type: v.literal("below"), value: v.number() }); +const condition = v.union([isSet, booleanValue, startsWith, above, below]); + +export type Condition = v.Output; diff --git a/src/core/input/index.ts b/src/core/input/index.ts new file mode 100644 index 00000000..1bac8008 --- /dev/null +++ b/src/core/input/index.ts @@ -0,0 +1,2 @@ +export * from "./InputDefinitionSchema"; +export * from "./dependentFields"; diff --git a/src/views/components/MultiSelectModel.ts b/src/views/components/MultiSelectModel.ts index b0288475..89be3404 100644 --- a/src/views/components/MultiSelectModel.ts +++ b/src/views/components/MultiSelectModel.ts @@ -1,7 +1,7 @@ import { A, pipe } from "@std"; import { absurd } from "fp-ts/function"; import { App } from "obsidian"; -import { inputTag, multiselect } from "src/core/InputDefinitionSchema"; +import { inputTag, multiselect } from "src/core/input/InputDefinitionSchema"; import { executeSandboxedDvQuery, sandboxedDvQuery } from "src/suggesters/SafeDataviewQuery"; import { StringSuggest } from "src/suggesters/StringSuggest"; import { FileSuggest } from "src/suggesters/suggestFile"; From be4367179b3706d5a4c83cbe9e6639cbe68105a4 Mon Sep 17 00:00:00 2001 From: Danielo Rodriguez Date: Sun, 23 Jun 2024 07:45:49 +0200 Subject: [PATCH 02/21] chore: available conditions for input --- src/core/input/InputDefinitionSchema.ts | 2 ++ src/core/input/dependentFields.ts | 34 ++++++++++++++++++++++++- src/store/formStore.ts | 2 +- tsconfig.json | 25 +++++++++++++++--- 4 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/core/input/InputDefinitionSchema.ts b/src/core/input/InputDefinitionSchema.ts index 5dfe0f08..fe80b070 100644 --- a/src/core/input/InputDefinitionSchema.ts +++ b/src/core/input/InputDefinitionSchema.ts @@ -142,6 +142,8 @@ export const InputTypeSchema = union([ DocumentBlock, ]); +export type Input = Output; + export const InputTypeToParserMap: Record> = { number: parseC(InputBasicSchema), text: parseC(InputBasicSchema), diff --git a/src/core/input/dependentFields.ts b/src/core/input/dependentFields.ts index bca0b6eb..70a611cd 100644 --- a/src/core/input/dependentFields.ts +++ b/src/core/input/dependentFields.ts @@ -1,4 +1,6 @@ +import { absurd } from "fp-ts/function"; import * as v from "valibot"; +import { FieldDefinition } from "../formDefinition"; const isSet = v.object({ field: v.string(), type: v.literal("isSet") }); const booleanValue = v.object({ field: v.string(), @@ -7,7 +9,7 @@ const booleanValue = v.object({ }); const startsWith = v.object({ field: v.string(), - type: v.literal("startsWith"), + type: v.enumType(["startsWith", "contains"]), value: v.string(), }); const above = v.object({ field: v.string(), type: v.literal("above"), value: v.number() }); @@ -15,3 +17,33 @@ const below = v.object({ field: v.string(), type: v.literal("below"), value: v.n const condition = v.union([isSet, booleanValue, startsWith, above, below]); export type Condition = v.Output; +export type ConditionType = Condition["type"]; + +export function availableConditionsForInput(input: FieldDefinition["input"]): ConditionType[] { + switch (input.type) { + case "text": + case "textarea": + case "email": + case "folder": + case "note": + case "tel": + return ["isSet", "startsWith", "contains"]; + case "slider": + case "number": + return ["isSet", "above", "below"]; + case "toggle": + return ["boolean"]; + case "date": + case "time": + case "datetime": + return ["isSet"]; + case "select": + case "multiselect": + case "tag": + case "dataview": + case "document_block": + return []; + default: + return absurd(input); + } +} diff --git a/src/store/formStore.ts b/src/store/formStore.ts index a44c790d..4af6294f 100644 --- a/src/store/formStore.ts +++ b/src/store/formStore.ts @@ -2,6 +2,7 @@ import * as R from "fp-ts/Record"; // This is the store that represents a runtime form. It is a writable store that contains the current state of the form // and the errors that are present in the form. It is used by the Form component to render the form and to update the +import { input } from "@core"; import { NonEmptyArray, flow, pipe } from "@std"; import * as A from "fp-ts/Array"; import * as E from "fp-ts/Either"; @@ -9,7 +10,6 @@ import * as O from "fp-ts/Option"; import { Option } from "fp-ts/Option"; import { fromEntries, toEntries } from "fp-ts/Record"; import { absurd } from "fp-ts/function"; -import { input } from "src/core"; import { FieldDefinition } from "src/core/formDefinition"; import { Readable, Writable, derived, get, writable } from "svelte/store"; diff --git a/tsconfig.json b/tsconfig.json index 0091189f..85d3af87 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -15,10 +15,25 @@ "verbatimModuleSyntax": false, "strict": true, "noUncheckedIndexedAccess": true, - "types": ["jest", "node", "svelte"], - "lib": ["DOM", "ES5", "ES6", "ES7"], + "types": [ + "jest", + "node", + "svelte" + ], + "lib": [ + "DOM", + "ES5", + "ES6", + "ES7" + ], + "noErrorTruncation": true, "paths": { - "@std": ["src/std"] + "@std": [ + "src/std" + ], + "@core": [ + "src/core" + ], }, "plugins": [ { @@ -79,5 +94,7 @@ } ] }, - "include": ["src/**/*"] + "include": [ + "src/**/*" + ] } From 9ee5a5ee8da865bee84ec0257e2ffa8726910dad Mon Sep 17 00:00:00 2001 From: Danielo Rodriguez Date: Sat, 29 Jun 2024 08:13:05 +0200 Subject: [PATCH 03/21] chore: namespaced input stuff --- src/views/components/InputBuilderSelect.svelte | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/views/components/InputBuilderSelect.svelte b/src/views/components/InputBuilderSelect.svelte index 7ba37b87..e6de7a4d 100644 --- a/src/views/components/InputBuilderSelect.svelte +++ b/src/views/components/InputBuilderSelect.svelte @@ -5,8 +5,8 @@ */ type option = { label: string; value: string } | string; + import { input } from "@core"; import { App, setIcon } from "obsidian"; - import { canAllowUnknownValues } from "src/core/InputDefinitionSchema"; import { AllSources } from "src/core/formDefinition"; import FormRow from "./FormRow.svelte"; import InputFolder from "./InputBuilderFolder.svelte"; @@ -23,7 +23,8 @@ export let is_multi: boolean; $: id = `builder_select_${index}`; $: options_id = `builder_select_options_btn_${index}`; - $: showAllowUnknownValuesOption = is_multi && canAllowUnknownValues("multiselect", source); + $: showAllowUnknownValuesOption = + is_multi && input.canAllowUnknownValues("multiselect", source); function moveOption(from: number, direction: "up" | "down") { const to = direction === "up" ? from - 1 : from + 1; From aef0038b0ab816ea27a2ac5907d8ff47d23bfce1 Mon Sep 17 00:00:00 2001 From: Danielo Rodriguez Date: Sat, 29 Jun 2024 08:49:35 +0200 Subject: [PATCH 04/21] chore: namespacing --- src/views/components/Form/ObsidianDropdown.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/views/components/Form/ObsidianDropdown.svelte b/src/views/components/Form/ObsidianDropdown.svelte index a27a9124..bc8f64a2 100644 --- a/src/views/components/Form/ObsidianDropdown.svelte +++ b/src/views/components/Form/ObsidianDropdown.svelte @@ -1,11 +1,11 @@