diff options
Diffstat (limited to 'web/source/settings/components')
-rw-r--r-- | web/source/settings/components/authorization/index.tsx | 7 | ||||
-rw-r--r-- | web/source/settings/components/authorization/login.tsx | 15 | ||||
-rw-r--r-- | web/source/settings/components/check-list.tsx (renamed from web/source/settings/components/check-list.jsx) | 46 | ||||
-rw-r--r-- | web/source/settings/components/form/inputs.tsx (renamed from web/source/settings/components/form/inputs.jsx) | 106 | ||||
-rw-r--r-- | web/source/settings/components/user-logout-card.jsx | 14 |
5 files changed, 130 insertions, 58 deletions
diff --git a/web/source/settings/components/authorization/index.tsx b/web/source/settings/components/authorization/index.tsx index 321bb03eb..22a0d24b7 100644 --- a/web/source/settings/components/authorization/index.tsx +++ b/web/source/settings/components/authorization/index.tsx @@ -25,6 +25,7 @@ import React from "react"; import Login from "./login"; import Loading from "../loading"; import { Error } from "../error"; +import { NoArg } from "../../lib/types/query"; export function Authorization({ App }) { const { loginState, expectingRedirect } = store.getState().oauth; @@ -35,15 +36,15 @@ export function Authorization({ App }) { isSuccess, data: account, error, - } = useVerifyCredentialsQuery(null, { skip: skip }); + } = useVerifyCredentialsQuery(NoArg, { skip: skip }); let showLogin = true; - let content = null; + let content: React.JSX.Element | null = null; if (isLoading) { showLogin = false; - let loadingInfo; + let loadingInfo = ""; if (loginState == "callback") { loadingInfo = "Processing OAUTH callback."; } else if (loginState == "login") { diff --git a/web/source/settings/components/authorization/login.tsx b/web/source/settings/components/authorization/login.tsx index 76bfccf43..870e9c343 100644 --- a/web/source/settings/components/authorization/login.tsx +++ b/web/source/settings/components/authorization/login.tsx @@ -22,26 +22,21 @@ import React from "react"; import { useAuthorizeFlowMutation } from "../../lib/query/oauth"; import { useTextInput, useValue } from "../../lib/form"; import useFormSubmit from "../../lib/form/submit"; -import { TextInput } from "../form/inputs"; import MutationButton from "../form/mutation-button"; import Loading from "../loading"; +import { TextInput } from "../form/inputs"; export default function Login({ }) { const form = { instance: useTextInput("instance", { defaultValue: window.location.origin }), - scopes: useValue("scopes", "user admin") + scopes: useValue("scopes", "user admin"), }; - const [formSubmit, result] = useFormSubmit( - form, - useAuthorizeFlowMutation(), - { - changedOnly: false, - onFinish: undefined, - } - ); + const [formSubmit, result] = useFormSubmit(form, useAuthorizeFlowMutation(), { + changedOnly: false, + }); if (result.isLoading) { return ( diff --git a/web/source/settings/components/check-list.jsx b/web/source/settings/components/check-list.tsx index de42a56a5..aec57e758 100644 --- a/web/source/settings/components/check-list.jsx +++ b/web/source/settings/components/check-list.tsx @@ -17,21 +17,31 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -const React = require("react"); +import React from "react"; -module.exports = function CheckList({ field, header = "All", EntryComponent, getExtraProps }) { +import { memo, useDeferredValue, useCallback, useMemo } from "react"; +import { Checkable, ChecklistInputHook } from "../lib/form/types"; + +interface CheckListProps { + field: ChecklistInputHook; + header: string | React.JSX.Element; + EntryComponent: React.FunctionComponent; + getExtraProps; +} + +export default function CheckList({ field, header = "All", EntryComponent, getExtraProps }: CheckListProps) { return ( <div className="checkbox-list list"> <CheckListHeader toggleAll={field.toggleAll}> {header}</CheckListHeader> <CheckListEntries - entries={field.value} + entries={field.value ?? {}} updateValue={field.onChange} EntryComponent={EntryComponent} getExtraProps={getExtraProps} /> </div> ); -}; +} function CheckListHeader({ toggleAll, children }) { return ( @@ -45,9 +55,16 @@ function CheckListHeader({ toggleAll, children }) { ); } -const CheckListEntries = React.memo( - function CheckListEntries({ entries, updateValue, EntryComponent, getExtraProps }) { - const deferredEntries = React.useDeferredValue(entries); +interface CheckListEntriesProps { + entries: { [_: string]: Checkable }, + updateValue, + EntryComponent, + getExtraProps, +} + +const CheckListEntries = memo( + function CheckListEntries({ entries, updateValue, EntryComponent, getExtraProps }: CheckListEntriesProps) { + const deferredEntries = useDeferredValue(entries); return Object.values(deferredEntries).map((entry) => ( <CheckListEntry @@ -61,19 +78,26 @@ const CheckListEntries = React.memo( } ); +interface CheckListEntryProps { + entry: Checkable, + updateValue, + getExtraProps, + EntryComponent, +} + /* React.memo is a performance optimization that only re-renders a CheckListEntry when it's props actually change, instead of every time anything in the list (CheckListEntries) updates */ -const CheckListEntry = React.memo( - function CheckListEntry({ entry, updateValue, getExtraProps, EntryComponent }) { - const onChange = React.useCallback( +const CheckListEntry = memo( + function CheckListEntry({ entry, updateValue, getExtraProps, EntryComponent }: CheckListEntryProps) { + const onChange = useCallback( (value) => updateValue(entry.key, value), [updateValue, entry.key] ); - const extraProps = React.useMemo(() => getExtraProps?.(entry), [getExtraProps, entry]); + const extraProps = useMemo(() => getExtraProps?.(entry), [getExtraProps, entry]); return ( <label className="entry"> diff --git a/web/source/settings/components/form/inputs.jsx b/web/source/settings/components/form/inputs.tsx index f7a6beeda..1e0d8eaab 100644 --- a/web/source/settings/components/form/inputs.jsx +++ b/web/source/settings/components/form/inputs.tsx @@ -17,9 +17,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -const React = require("react"); +import React from "react"; + +import type { + ReactNode, + RefObject, +} from "react"; + +import type { + FileFormInputHook, + RadioFormInputHook, + TextFormInputHook, +} from "../../lib/form/types"; + +export interface TextInputProps extends React.DetailedHTMLProps< + React.InputHTMLAttributes<HTMLInputElement>, + HTMLInputElement +> { + label?: string; + field: TextFormInputHook; +} -function TextInput({ label, field, ...inputProps }) { +export function TextInput({label, field, ...props}: TextInputProps) { const { onChange, value, ref } = field; return ( @@ -27,16 +46,25 @@ function TextInput({ label, field, ...inputProps }) { <label> {label} <input - type="text" - {...{ onChange, value, ref }} - {...inputProps} + onChange={onChange} + value={value} + ref={ref as RefObject<HTMLInputElement>} + {...props} /> </label> </div> ); } -function TextArea({ label, field, ...inputProps }) { +export interface TextAreaProps extends React.DetailedHTMLProps< + React.TextareaHTMLAttributes<HTMLTextAreaElement>, + HTMLTextAreaElement +> { + label?: string; + field: TextFormInputHook; +} + +export function TextArea({label, field, ...props}: TextAreaProps) { const { onChange, value, ref } = field; return ( @@ -44,16 +72,25 @@ function TextArea({ label, field, ...inputProps }) { <label> {label} <textarea - type="text" - {...{ onChange, value, ref }} - {...inputProps} + onChange={onChange} + value={value} + ref={ref as RefObject<HTMLTextAreaElement>} + {...props} /> </label> </div> ); } -function FileInput({ label, field, ...inputProps }) { +export interface FileInputProps extends React.DetailedHTMLProps< + React.InputHTMLAttributes<HTMLInputElement>, + HTMLInputElement +> { + label?: string; + field: FileFormInputHook; +} + +export function FileInput({ label, field, ...props }: FileInputProps) { const { onChange, ref, infoComponent } = field; return ( @@ -66,15 +103,16 @@ function FileInput({ label, field, ...inputProps }) { <input type="file" className="hidden" - {...{ onChange, ref }} - {...inputProps} + onChange={onChange} + ref={ref ? ref as RefObject<HTMLInputElement> : undefined} + {...props} /> </label> </div> ); } -function Checkbox({ label, field, ...inputProps }) { +export function Checkbox({ label, field, ...inputProps }) { const { onChange, value } = field; return ( @@ -91,16 +129,29 @@ function Checkbox({ label, field, ...inputProps }) { ); } -function Select({ label, field, options, children, ...inputProps }) { +export interface SelectProps extends React.DetailedHTMLProps< + React.SelectHTMLAttributes<HTMLSelectElement>, + HTMLSelectElement +> { + label?: string; + field: TextFormInputHook; + children?: ReactNode; + options: React.JSX.Element; +} + +export function Select({ label, field, children, options, ...props }: SelectProps) { const { onChange, value, ref } = field; return ( <div className="form-field select"> <label> - {label} {children} + {label} + {children} <select - {...{ onChange, value, ref }} - {...inputProps} + onChange={onChange} + value={value} + ref={ref as RefObject<HTMLSelectElement>} + {...props} > {options} </select> @@ -109,7 +160,15 @@ function Select({ label, field, options, children, ...inputProps }) { ); } -function RadioGroup({ field, label, ...inputProps }) { +export interface RadioGroupProps extends React.DetailedHTMLProps< + React.InputHTMLAttributes<HTMLInputElement>, + HTMLInputElement +> { + label?: string; + field: RadioFormInputHook; +} + +export function RadioGroup({ label, field, ...props }: RadioGroupProps) { return ( <div className="form-field radio"> {Object.entries(field.options).map(([value, radioLabel]) => ( @@ -120,7 +179,7 @@ function RadioGroup({ field, label, ...inputProps }) { value={value} checked={field.value == value} onChange={field.onChange} - {...inputProps} + {...props} /> {radioLabel} </label> @@ -129,12 +188,3 @@ function RadioGroup({ field, label, ...inputProps }) { </div> ); } - -module.exports = { - TextInput, - TextArea, - FileInput, - Checkbox, - Select, - RadioGroup -};
\ No newline at end of file diff --git a/web/source/settings/components/user-logout-card.jsx b/web/source/settings/components/user-logout-card.jsx index de77f0485..9d88642a5 100644 --- a/web/source/settings/components/user-logout-card.jsx +++ b/web/source/settings/components/user-logout-card.jsx @@ -18,15 +18,17 @@ */ const React = require("react"); - -const query = require("../lib/query"); - const Loading = require("./loading"); +const { + useVerifyCredentialsQuery, + useLogoutMutation, +} = require("../lib/query/oauth"); +const { useInstanceV1Query } = require("../lib/query"); module.exports = function UserLogoutCard() { - const { data: profile, isLoading } = query.useVerifyCredentialsQuery(); - const { data: instance } = query.useInstanceQuery(); - const [logoutQuery] = query.useLogoutMutation(); + const { data: profile, isLoading } = useVerifyCredentialsQuery(); + const { data: instance } = useInstanceV1Query(); + const [logoutQuery] = useLogoutMutation(); if (isLoading) { return <Loading />; |