diff options
author | 2024-01-16 18:28:56 +0100 | |
---|---|---|
committer | 2024-01-16 18:28:56 +0100 | |
commit | 486585890d674ce3e160d2a8f1e6835e181b0b08 (patch) | |
tree | a0d954f5a71f71ddfd4a243152dab10f14397f6e /web/source/settings/lib | |
parent | [feature] Account alias / move API + db models (#2518) (diff) | |
download | gotosocial-486585890d674ce3e160d2a8f1e6835e181b0b08.tar.xz |
[feature] Move + alias account via settings panel (#2519)
* [feature] Move + alias account via settings panel
* lint
* type a bit more diligently
Diffstat (limited to 'web/source/settings/lib')
-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 | ||||
-rw-r--r-- | web/source/settings/lib/query/user/index.ts | 30 | ||||
-rw-r--r-- | web/source/settings/lib/types/migration.ts | 27 |
7 files changed, 172 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. diff --git a/web/source/settings/lib/query/user/index.ts b/web/source/settings/lib/query/user/index.ts index a7cdad2fd..8cf64197b 100644 --- a/web/source/settings/lib/query/user/index.ts +++ b/web/source/settings/lib/query/user/index.ts @@ -19,6 +19,10 @@ import { replaceCacheOnMutation } from "../query-modifiers"; import { gtsApi } from "../gts-api"; +import type { + MoveAccountFormData, + UpdateAliasesFormData +} from "../../types/migration"; const extended = gtsApi.injectEndpoints({ endpoints: (build) => ({ @@ -38,6 +42,30 @@ const extended = gtsApi.injectEndpoints({ url: `/api/v1/user/password_change`, body: data }) + }), + aliasAccount: build.mutation<any, UpdateAliasesFormData>({ + async queryFn(formData, _api, _extraOpts, fetchWithBQ) { + // Pull entries out from the hooked form. + const entries: String[] = []; + formData.also_known_as_uris.forEach(entry => { + if (entry) { + entries.push(entry); + } + }); + + return fetchWithBQ({ + method: "POST", + url: `/api/v1/accounts/alias`, + body: { also_known_as_uris: entries }, + }); + } + }), + moveAccount: build.mutation<any, MoveAccountFormData>({ + query: (data) => ({ + method: "POST", + url: `/api/v1/accounts/move`, + body: data + }) }) }) }); @@ -45,4 +73,6 @@ const extended = gtsApi.injectEndpoints({ export const { useUpdateCredentialsMutation, usePasswordChangeMutation, + useAliasAccountMutation, + useMoveAccountMutation, } = extended; diff --git a/web/source/settings/lib/types/migration.ts b/web/source/settings/lib/types/migration.ts new file mode 100644 index 000000000..e66887a83 --- /dev/null +++ b/web/source/settings/lib/types/migration.ts @@ -0,0 +1,27 @@ +/* + 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/>. +*/ + +export interface UpdateAliasesFormData { + also_known_as_uris: string[]; +} + +export interface MoveAccountFormData { + moved_to_uri: string; + password: string; +} |