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; +}  | 
