summaryrefslogtreecommitdiff
path: root/web/source/settings/lib
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2024-01-16 18:28:56 +0100
committerLibravatar GitHub <noreply@github.com>2024-01-16 18:28:56 +0100
commit486585890d674ce3e160d2a8f1e6835e181b0b08 (patch)
treea0d954f5a71f71ddfd4a243152dab10f14397f6e /web/source/settings/lib
parent[feature] Account alias / move API + db models (#2518) (diff)
downloadgotosocial-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.ts92
-rw-r--r--web/source/settings/lib/form/field-array.tsx2
-rw-r--r--web/source/settings/lib/form/get-form-mutations.ts9
-rw-r--r--web/source/settings/lib/form/index.ts5
-rw-r--r--web/source/settings/lib/form/types.ts13
-rw-r--r--web/source/settings/lib/query/user/index.ts30
-rw-r--r--web/source/settings/lib/types/migration.ts27
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;
+}