From 9d27379b2560d6036b3cb9ed2474f4c50cb4f366 Mon Sep 17 00:00:00 2001 From: Jed Fox <git@jedfox.com> Date: Fri, 4 Aug 2023 11:03:16 -0700 Subject: [PATCH] Move big input component into Input.js, port some of the manager app to TS (#1431) --- .../{ServerContext.js => ServerContext.tsx} | 28 +++++++++++++----- .../src/components/common/Input.tsx | 24 ++++++++++++--- .../{ConfigServer.js => ConfigServer.tsx} | 27 +++++++++-------- .../manager/{ServerURL.js => ServerURL.tsx} | 2 +- .../manager/subscribe/ConfirmPasswordForm.tsx | 7 ++--- .../components/manager/subscribe/Login.tsx | 5 ++-- .../components/manager/subscribe/common.tsx | 29 ++----------------- .../loot-core/src/types/server-handlers.d.ts | 7 +++-- upcoming-release-notes/1431.md | 6 ++++ 9 files changed, 74 insertions(+), 61 deletions(-) rename packages/desktop-client/src/components/{ServerContext.js => ServerContext.tsx} (65%) rename packages/desktop-client/src/components/manager/{ConfigServer.js => ConfigServer.tsx} (89%) rename packages/desktop-client/src/components/manager/{ServerURL.js => ServerURL.tsx} (91%) create mode 100644 upcoming-release-notes/1431.md diff --git a/packages/desktop-client/src/components/ServerContext.js b/packages/desktop-client/src/components/ServerContext.tsx similarity index 65% rename from packages/desktop-client/src/components/ServerContext.js rename to packages/desktop-client/src/components/ServerContext.tsx index ae0fb1b43..86c0bf8d6 100644 --- a/packages/desktop-client/src/components/ServerContext.js +++ b/packages/desktop-client/src/components/ServerContext.tsx @@ -4,25 +4,39 @@ import React, { useCallback, useEffect, useContext, + type ReactNode, } from 'react'; import { send } from 'loot-core/src/platform/client/fetch'; -const ServerContext = createContext({}); +type ServerContextValue = { + url: string | null; + version: string; + setURL: ( + url: string, + opts?: { validate?: boolean }, + ) => Promise<{ error?: string }>; +}; + +const ServerContext = createContext<ServerContextValue>({ + url: null, + version: '', + setURL: () => Promise.reject(new Error('ServerContext not initialized')), +}); export const useServerURL = () => useContext(ServerContext).url; export const useServerVersion = () => useContext(ServerContext).version; export const useSetServerURL = () => useContext(ServerContext).setURL; async function getServerVersion() { - let { error, version } = await send('get-server-version'); - if (error) { - return ''; + let result = await send('get-server-version'); + if ('version' in result) { + return result.version; } - return version; + return ''; } -export function ServerProvider({ children }) { +export function ServerProvider({ children }: { children: ReactNode }) { let [serverURL, setServerURL] = useState(''); let [version, setVersion] = useState(''); @@ -35,7 +49,7 @@ export function ServerProvider({ children }) { }, []); let setURL = useCallback( - async (url, opts = {}) => { + async (url: string, opts: { validate?: boolean } = {}) => { let { error } = await send('set-server-url', { ...opts, url }); if (!error) { setServerURL(await send('get-server-url')); diff --git a/packages/desktop-client/src/components/common/Input.tsx b/packages/desktop-client/src/components/common/Input.tsx index 08e9fcf33..2b09d772a 100644 --- a/packages/desktop-client/src/components/common/Input.tsx +++ b/packages/desktop-client/src/components/common/Input.tsx @@ -23,14 +23,14 @@ type InputProps = HTMLPropsWithStyle<HTMLInputElement> & { focused?: boolean; }; -const Input = ({ +export default function Input({ style, inputRef, onEnter, onUpdate, focused, ...nativeProps -}: InputProps) => { +}: InputProps) { let ref = useRef(); useProperFocus(ref, focused); @@ -68,6 +68,22 @@ const Input = ({ }} /> ); -}; +} -export default Input; +export function BigInput(props: InputProps) { + return ( + <Input + {...props} + style={[ + { + padding: 10, + fontSize: 15, + border: 'none', + ...styles.shadow, + ':focus': { border: 'none', ...styles.shadow }, + }, + props.style, + ]} + /> + ); +} diff --git a/packages/desktop-client/src/components/manager/ConfigServer.js b/packages/desktop-client/src/components/manager/ConfigServer.tsx similarity index 89% rename from packages/desktop-client/src/components/manager/ConfigServer.js rename to packages/desktop-client/src/components/manager/ConfigServer.tsx index 0c7d7f759..b12d4790e 100644 --- a/packages/desktop-client/src/components/manager/ConfigServer.js +++ b/packages/desktop-client/src/components/manager/ConfigServer.tsx @@ -1,26 +1,25 @@ import React, { useState, useEffect } from 'react'; -import { useDispatch } from 'react-redux'; import { useNavigate } from 'react-router-dom'; -import { createBudget } from 'loot-core/src/client/actions/budgets'; -import { signOut, loggedIn } from 'loot-core/src/client/actions/user'; import { isNonProductionEnvironment, isElectron, } from 'loot-core/src/shared/environment'; +import { useActions } from '../../hooks/useActions'; import { useSetThemeColor } from '../../hooks/useSetThemeColor'; import { colors } from '../../style'; import Button, { ButtonWithLoading } from '../common/Button'; +import { BigInput } from '../common/Input'; import Text from '../common/Text'; import View from '../common/View'; import { useServerURL, useSetServerURL } from '../ServerContext'; -import { Title, Input } from './subscribe/common'; +import { Title } from './subscribe/common'; export default function ConfigServer() { useSetThemeColor(colors.p5); - let dispatch = useDispatch(); + let { createBudget, signOut, loggedIn } = useActions(); let navigate = useNavigate(); let [url, setUrl] = useState(''); let currentUrl = useServerURL(); @@ -29,9 +28,9 @@ export default function ConfigServer() { setUrl(currentUrl); }, [currentUrl]); let [loading, setLoading] = useState(false); - let [error, setError] = useState(null); + let [error, setError] = useState<string | null>(null); - function getErrorMessage(error) { + function getErrorMessage(error: string) { switch (error) { case 'network-failure': return 'Server is not running at this URL. Make sure you have HTTPS set up properly.'; @@ -59,7 +58,7 @@ export default function ConfigServer() { setUrl('https://' + url); setError(error); } else { - await dispatch(signOut()); + await signOut(); navigate('/'); } setLoading(false); @@ -68,7 +67,7 @@ export default function ConfigServer() { setError(error); } else { setLoading(false); - await dispatch(signOut()); + await signOut(); navigate('/'); } } @@ -79,13 +78,13 @@ export default function ConfigServer() { async function onSkip() { await setServerUrl(null); - await dispatch(loggedIn()); + await loggedIn(); navigate('/'); } async function onCreateTestFile() { await setServerUrl(null); - await dispatch(createBudget({ testMode: true })); + await createBudget({ testMode: true }); window.__navigate('/'); } @@ -134,11 +133,11 @@ export default function ConfigServer() { onSubmit(); }} > - <Input + <BigInput autoFocus={true} - placeholder={'https://example.com'} + placeholder="https://example.com" value={url || ''} - onChange={e => setUrl(e.target.value)} + onUpdate={setUrl} style={{ flex: 1, marginRight: 10 }} /> <ButtonWithLoading diff --git a/packages/desktop-client/src/components/manager/ServerURL.js b/packages/desktop-client/src/components/manager/ServerURL.tsx similarity index 91% rename from packages/desktop-client/src/components/manager/ServerURL.js rename to packages/desktop-client/src/components/manager/ServerURL.tsx index e90873a9c..3d62e31ab 100644 --- a/packages/desktop-client/src/components/manager/ServerURL.js +++ b/packages/desktop-client/src/components/manager/ServerURL.tsx @@ -30,7 +30,7 @@ export default function ServerURL() { <strong>No server configured</strong> )} </Text> - <AnchorLink bare to="/config-server" style={{ marginLeft: 15 }}> + <AnchorLink to="/config-server" style={{ marginLeft: 15 }}> Change </AnchorLink> </View> diff --git a/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx b/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx index 645c73e44..b0d5b3622 100644 --- a/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx +++ b/packages/desktop-client/src/components/manager/subscribe/ConfirmPasswordForm.tsx @@ -1,10 +1,9 @@ import React, { type ChangeEvent, useState } from 'react'; import { ButtonWithLoading } from '../../common/Button'; +import { BigInput } from '../../common/Input'; import View from '../../common/View'; -import { Input } from './common'; - export function ConfirmPasswordForm({ buttons, onSetPassword, onError }) { let [password1, setPassword1] = useState(''); let [password2, setPassword2] = useState(''); @@ -40,7 +39,7 @@ export function ConfirmPasswordForm({ buttons, onSetPassword, onError }) { }} onSubmit={onSubmit} > - <Input + <BigInput autoFocus={true} placeholder="Password" type={showPassword ? 'text' : 'password'} @@ -50,7 +49,7 @@ export function ConfirmPasswordForm({ buttons, onSetPassword, onError }) { } onEnter={onSubmit} /> - <Input + <BigInput placeholder="Confirm password" type={showPassword ? 'text' : 'password'} value={password2} diff --git a/packages/desktop-client/src/components/manager/subscribe/Login.tsx b/packages/desktop-client/src/components/manager/subscribe/Login.tsx index 6303627e5..1571bc06f 100644 --- a/packages/desktop-client/src/components/manager/subscribe/Login.tsx +++ b/packages/desktop-client/src/components/manager/subscribe/Login.tsx @@ -7,10 +7,11 @@ import { send } from 'loot-core/src/platform/client/fetch'; import { colors } from '../../../style'; import Button, { ButtonWithLoading } from '../../common/Button'; +import { BigInput } from '../../common/Input'; import Text from '../../common/Text'; import View from '../../common/View'; -import { useBootstrapped, Title, Input } from './common'; +import { useBootstrapped, Title } from './common'; export default function Login() { let dispatch = useDispatch(); @@ -88,7 +89,7 @@ export default function Login() { style={{ display: 'flex', flexDirection: 'row', marginTop: 30 }} onSubmit={onSubmit} > - <Input + <BigInput autoFocus={true} placeholder="Password" type="password" diff --git a/packages/desktop-client/src/components/manager/subscribe/common.tsx b/packages/desktop-client/src/components/manager/subscribe/common.tsx index 8a993c84e..562ec0e4e 100644 --- a/packages/desktop-client/src/components/manager/subscribe/common.tsx +++ b/packages/desktop-client/src/components/manager/subscribe/common.tsx @@ -1,15 +1,9 @@ -import React, { - type ComponentProps, - forwardRef, - useEffect, - useState, -} from 'react'; +import React, { useEffect, useState } from 'react'; import { useNavigate, useLocation } from 'react-router-dom'; import { send } from 'loot-core/src/platform/client/fetch'; -import { colors, styles } from '../../../style'; -import BaseInput from '../../common/Input'; +import { colors } from '../../../style'; import { useSetServerURL } from '../../ServerContext'; // There are two URLs that dance with each other: `/login` and @@ -92,22 +86,3 @@ export function Title({ text }: TitleProps) { </h1> ); } - -type InputProps = ComponentProps<typeof BaseInput>; -export const Input = forwardRef<HTMLInputElement, InputProps>((props, ref) => { - return ( - <BaseInput - {...props} - style={[ - { - padding: 10, - fontSize: 15, - border: 'none', - ...styles.shadow, - ':focus': { border: 'none', ...styles.shadow }, - }, - props.style, - ]} - /> - ); -}); diff --git a/packages/loot-core/src/types/server-handlers.d.ts b/packages/loot-core/src/types/server-handlers.d.ts index 8ce437c00..e5875a77d 100644 --- a/packages/loot-core/src/types/server-handlers.d.ts +++ b/packages/loot-core/src/types/server-handlers.d.ts @@ -282,9 +282,12 @@ export interface ServerHandlers { 'get-server-version': () => Promise<{ error?: string } | { version: string }>; - 'get-server-url': () => Promise<unknown>; + 'get-server-url': () => Promise<string | null>; - 'set-server-url': (arg: { url; validate }) => Promise<unknown>; + 'set-server-url': (arg: { + url: string; + validate?: boolean; + }) => Promise<{ error?: string }>; sync: () => Promise< | { error: { message: string; reason: string; meta: unknown } } diff --git a/upcoming-release-notes/1431.md b/upcoming-release-notes/1431.md new file mode 100644 index 000000000..82b214713 --- /dev/null +++ b/upcoming-release-notes/1431.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [j-f1] +--- + +Move big input component into Input.js, port some of the manager app to TS -- GitLab