diff --git a/web/account/log-in-form.css b/web/account/log-in-form.css new file mode 100644 index 000000000..9b0230e25 --- /dev/null +++ b/web/account/log-in-form.css @@ -0,0 +1,144 @@ +div.modal-body { + padding: 6px 6px; + width: 100%; + box-sizing: border-box; + background-color: var(--modal-bg); + border-bottom-left-radius: 15px; + border-bottom-right-radius: 15px; + flex: 1; + display: flex; + flex-direction: column; +} +div.resized-modal-body { + min-height: 250px; +} +div.modal-body p { + padding: 1px 3px 4px 3px; + font-size: 14px; + text-align: center; +} +div.modal-body p.form-pre-footer { + padding-top: 5px; + font-size: 12px; + font-style: italic; +} +div.modal-body textarea { + margin: 3px; +} +div.modal-body textarea { + font-size: 14px; + padding: 1px; + width: 175px; +} +div.large-modal-container div.modal-body textarea { + width: 275px; +} +div.modal-body p.confirm-account-password { + color: #777777; + margin-bottom: 4px; + color: var(--fg); +} +div.modal-body div.form-footer { + display: flex; + flex-direction: row-reverse; + justify-content: space-between; + padding-top: 8px; +} +div.modal-body div.form-footer div.modal-form-error { + font-size: 12px; + color: red; + font-style: italic; + padding-left: 6px; + align-self: center; +} +div.modal-body div.form-footer div.modal-form-error ol { + padding-left: 20px; +} +div.modal-body div.form-title { + display: inline-block; + text-align: right; + padding-right: 5px; + padding-top: 5px; + font-size: 14px; + font-weight: 600; + vertical-align: top; + width: 110px; + color: var(--fg); +} +div.large-modal-container div.modal-body div.form-title { + width: 140px; +} +div.modal-body div.form-content { + display: inline-block; + font-family: var(--font-stack); + color: var(--fg); +} +div.modal-body div.form-content input { + margin-bottom: 4px; +} +div.modal-body div.form-subtitle { + font-size: 12px; + padding-left: 4px; + font-style: italic; +} + +div.form-text { + display: flex; + align-items: baseline; +} +div.form-text > div.form-title { + vertical-align: initial; + flex-shrink: 0; +} +div.form-text > div.form-content { + margin-left: 3px; + margin-bottom: 3px; + word-break: break-word; +} + +div.form-text > div.form-float-title { + float: left; + text-align: right; + padding-right: 5px; + font-size: 14px; + font-weight: 600; + width: 110px; +} +div.form-text > div.form-float-content { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-size: 14px; + padding: 1px 20px 3px 4px; + margin-top: 5px; +} + +.italic { + font-style: italic; + color: var(--fg); +} + +ul.tab-panel { + background-color: var(--modal-bg); + padding-left: 10px; + padding-top: 5px; +} +ul.tab-panel > li { + display: inline-block; + list-style-type: none; + font-size: 13px; + font-weight: 600; + cursor: pointer; + padding: 3px 10px 3px 10px; +} +ul.tab-panel > li > a { + color: #555555; +} +ul.tab-panel > li.delete-tab > a { + color: #ff0000 !important; +} + +div.user-settings-current-password { + padding-top: 4px; + margin-top: 5px; +} diff --git a/web/account/log-in-form.react.js b/web/account/log-in-form.react.js index 1aa7a79ad..9beca6595 100644 --- a/web/account/log-in-form.react.js +++ b/web/account/log-in-form.react.js @@ -1,155 +1,155 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { logInActionTypes, logIn } from 'lib/actions/user-actions'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors'; import { oldValidUsernameRegex, validEmailRegex, } from 'lib/shared/account-utils'; import type { LogInExtraInfo, LogInStartingPayload, } from 'lib/types/account-types'; import { useDispatchActionPromise, useServerCall, } from 'lib/utils/action-utils'; import Button from '../components/button.react'; -import css from '../modals/account/user-settings-modal.css'; import Input from '../modals/input.react'; import { useModalContext } from '../modals/modal-provider.react'; import { useSelector } from '../redux/redux-utils'; import { webLogInExtraInfoSelector } from '../selectors/account-selectors'; +import css from './log-in-form.css'; const loadingStatusSelector = createLoadingStatusSelector(logInActionTypes); function LoginForm(): React.Node { const inputDisabled = useSelector(loadingStatusSelector) === 'loading'; const loginExtraInfo = useSelector(webLogInExtraInfoSelector); const callLogIn = useServerCall(logIn); const dispatchActionPromise = useDispatchActionPromise(); const modalContext = useModalContext(); const [username, setUsername] = React.useState(''); const [password, setPassword] = React.useState(''); const [errorMessage, setErrorMessage] = React.useState(''); const usernameInputRef = React.useRef(); const passwordInputRef = React.useRef(); React.useEffect(() => { usernameInputRef.current?.focus(); }, []); const onUsernameChange = React.useCallback(e => { invariant(e.target instanceof HTMLInputElement, 'target not input'); setUsername(e.target.value); }, []); const onPasswordChange = React.useCallback(e => { invariant(e.target instanceof HTMLInputElement, 'target not input'); setPassword(e.target.value); }, []); const logInAction = React.useCallback( async (extraInfo: LogInExtraInfo) => { try { const result = await callLogIn({ username, password, ...extraInfo, }); modalContext.clearModal(); return result; } catch (e) { if (e.message === 'invalid_parameters') { setUsername(''); setErrorMessage(`user doesn't exist`); usernameInputRef.current?.focus(); } else if (e.message === 'invalid_credentials') { setPassword(''); setErrorMessage('wrong password'); passwordInputRef.current?.focus(); } else { setUsername(''); setPassword(''); setErrorMessage('unknown error'); usernameInputRef.current?.focus(); } throw e; } }, [callLogIn, modalContext, password, username], ); const onSubmit = React.useCallback( (event: SyntheticEvent) => { event.preventDefault(); if (username.search(validEmailRegex) > -1) { setUsername(''); setErrorMessage('usernames only, not emails'); usernameInputRef.current?.focus(); return; } else if (username.search(oldValidUsernameRegex) === -1) { setUsername(''); setErrorMessage('alphanumeric usernames only'); usernameInputRef.current?.focus(); return; } const extraInfo = loginExtraInfo(); dispatchActionPromise( logInActionTypes, logInAction(extraInfo), undefined, ({ calendarQuery: extraInfo.calendarQuery }: LogInStartingPayload), ); }, [dispatchActionPromise, logInAction, loginExtraInfo, username], ); return (
Username
Password
{errorMessage}
); } export default LoginForm; diff --git a/web/splash/splash.css b/web/splash/splash.css index 1f501a13e..013a0fbc7 100644 --- a/web/splash/splash.css +++ b/web/splash/splash.css @@ -1,5 +1,10 @@ -div.loginContainer { +div.splashContainer { display: flex; justify-content: center; - color: white; + align-items: center; + height: 100%; +} + +div.loginContainer { + display: flex; } diff --git a/web/splash/splash.react.js b/web/splash/splash.react.js index cbecd2839..73c049f0f 100644 --- a/web/splash/splash.react.js +++ b/web/splash/splash.react.js @@ -1,15 +1,18 @@ // @flow import * as React from 'react'; import LoginForm from '../account/log-in-form.react'; +import css from './splash.css'; function Splash(): React.Node { return ( -
- +
+
+ +
); } export default Splash;