diff options
Diffstat (limited to 'web/source/settings/lib/form')
-rw-r--r-- | web/source/settings/lib/form/array.ts | 92 | ||||
-rw-r--r-- | web/source/settings/lib/form/field-array.tsx | 2 | ||||
-rw-r--r-- | web/source/settings/lib/form/get-form-mutations.ts | 9 | ||||
-rw-r--r-- | web/source/settings/lib/form/index.ts | 5 | ||||
-rw-r--r-- | web/source/settings/lib/form/types.ts | 13 |
5 files changed, 115 insertions, 6 deletions
diff --git a/web/source/settings/lib/form/array.ts b/web/source/settings/lib/form/array.ts new file mode 100644 index 000000000..7ddf9499c --- /dev/null +++ b/web/source/settings/lib/form/array.ts @@ -0,0 +1,92 @@ +/* + GoToSocial + Copyright (C) GoToSocial Authors admin@gotosocial.org + SPDX-License-Identifier: AGPL-3.0-or-later + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +import { useRef, useMemo } from "react"; + +import type { + CreateHookNames, + HookOpts, + ArrayInputHook, + HookedForm, +} from "./types"; +import getFormMutations from "./get-form-mutations"; + +function parseFields(entries: HookedForm[], length: number): HookedForm[] { + const fields: HookedForm[] = []; + + for (let i = 0; i < length; i++) { + if (entries[i] != undefined) { + fields[i] = Object.assign({}, entries[i]); + } else { + fields[i] = {}; + } + } + + return fields; +} + +export default function useArrayInput( + { name }: CreateHookNames, + { + initialValue, + length = 0, + }: HookOpts, +): ArrayInputHook { + const _default: HookedForm[] = Array(length); + const fields = useRef<HookedForm[]>(_default); + + const value = useMemo( + () => parseFields(initialValue, length), + [initialValue, length], + ); + + function hasUpdate() { + return Object.values(fields.current).some((fieldSet) => { + const { updatedFields } = getFormMutations(fieldSet, { changedOnly: true }); + return updatedFields.length > 0; + }); + } + + return { + _default, + name, + Name: "", + value, + ctx: fields.current, + maxLength: length, + hasChanged: hasUpdate, + selectedValues() { + if (hasUpdate()) { + return Object.values(fields.current) + // Extract all form fields. + .flatMap((fieldSet) => { + return getFormMutations( + fieldSet, + { changedOnly: false }, + ).updatedFields; + }) + // Get just value from each + // field, discarding name. + .map((field) => field.value); + } else { + return []; + } + } + }; +} diff --git a/web/source/settings/lib/form/field-array.tsx b/web/source/settings/lib/form/field-array.tsx index 275bf2b1b..1239f033e 100644 --- a/web/source/settings/lib/form/field-array.tsx +++ b/web/source/settings/lib/form/field-array.tsx @@ -42,7 +42,7 @@ function parseFields(entries: HookedForm[], length: number): HookedForm[] { return fields; } -export default function useArrayInput( +export default function useFieldArrayInput( { name }: CreateHookNames, { initialValue, diff --git a/web/source/settings/lib/form/get-form-mutations.ts b/web/source/settings/lib/form/get-form-mutations.ts index a3dc36601..0959fcf95 100644 --- a/web/source/settings/lib/form/get-form-mutations.ts +++ b/web/source/settings/lib/form/get-form-mutations.ts @@ -22,7 +22,12 @@ import { FormInputHook, HookedForm } from "./types"; export default function getFormMutations( form: HookedForm, { changedOnly }: { changedOnly: boolean }, -) { +): { + updatedFields: FormInputHook<any>[]; + mutationData: { + [k: string]: any; + }; +} { const updatedFields: FormInputHook[] = []; const mutationData: Array<[string, any]> = []; @@ -34,7 +39,7 @@ export default function getFormMutations( } if ("selectedValues" in field) { - // FieldArrayInputHook. + // (Field)ArrayInputHook. const selected = field.selectedValues(); if (!changedOnly || selected.length > 0) { updatedFields.push(field); diff --git a/web/source/settings/lib/form/index.ts b/web/source/settings/lib/form/index.ts index 20de33eda..409ef0328 100644 --- a/web/source/settings/lib/form/index.ts +++ b/web/source/settings/lib/form/index.ts @@ -26,6 +26,7 @@ import bool from "./bool"; import radio from "./radio"; import combobox from "./combo-box"; import checklist from "./check-list"; +import array from "./array"; import fieldarray from "./field-array"; import type { @@ -37,8 +38,9 @@ import type { FileFormInputHook, BoolFormInputHook, ComboboxFormInputHook, - FieldArrayInputHook, ChecklistInputHook, + FieldArrayInputHook, + ArrayInputHook, } from "./types"; function capitalizeFirst(str: string) { @@ -110,5 +112,6 @@ export const useBoolInput = inputHook(bool) as (_name: string, _opts?: HookOpts< export const useRadioInput = inputHook(radio) as (_name: string, _opts?: HookOpts<string>) => RadioFormInputHook; export const useComboBoxInput = inputHook(combobox) as (_name: string, _opts?: HookOpts<string>) => ComboboxFormInputHook; export const useCheckListInput = inputHook(checklist) as (_name: string, _opts?: HookOpts<boolean>) => ChecklistInputHook; +export const useArrayInput = inputHook(array) as (_name: string, _opts?: HookOpts<string[]>) => ArrayInputHook; export const useFieldArrayInput = inputHook(fieldarray) as (_name: string, _opts?: HookOpts<string>) => FieldArrayInputHook; export const useValue = value as <T>(_name: string, _initialValue: T) => FormInputHook<T>; diff --git a/web/source/settings/lib/form/types.ts b/web/source/settings/lib/form/types.ts index 8ea194df7..17fbec53a 100644 --- a/web/source/settings/lib/form/types.ts +++ b/web/source/settings/lib/form/types.ts @@ -141,6 +141,10 @@ interface _withNew { } interface _withSelectedValues { + selectedValues: () => string[]; +} + +interface _withSelectedFieldValues { selectedValues: () => { [_: string]: any; }[] @@ -200,11 +204,16 @@ export interface ComboboxFormInputHook extends FormInputHook<string>, _withNew, _withReset {} -export interface FieldArrayInputHook extends FormInputHook<HookedForm[]>, +export interface ArrayInputHook extends FormInputHook<HookedForm[]>, _withSelectedValues, _withMaxLength, _withCtx {} +export interface FieldArrayInputHook extends FormInputHook<HookedForm[]>, + _withSelectedFieldValues, + _withMaxLength, + _withCtx {} + export interface Checkable { key: string; checked?: boolean; @@ -213,7 +222,7 @@ export interface Checkable { export interface ChecklistInputHook<T = Checkable> extends FormInputHook<{[k: string]: T}>, _withReset, _withToggleAll, - _withSelectedValues, + _withSelectedFieldValues, _withSomeSelected, _withUpdateMultiple { // Uses its own funky onChange handler. |