diff options
| author | 2022-07-19 13:58:34 +0200 | |
|---|---|---|
| committer | 2022-07-19 13:58:34 +0200 | |
| commit | 191581e287f78ba325fdd7681c83586309b59df2 (patch) | |
| tree | 72331f121c3d5baa6f449e6c1ad362a98d35b5c8 | |
| parent | Clear Authorization On Error (diff) | |
Simplify Navigation Component
Extract the styles from the navigation component to common styles, and
convert it to a function component.
Signed-off-by: Hassan Abouelela <[email protected]>
| -rw-r--r-- | src/commonStyles.tsx | 61 | ||||
| -rw-r--r-- | src/components/OAuth2Button.tsx | 6 | ||||
| -rw-r--r-- | src/pages/FormPage/ErrorPage.tsx | 29 | ||||
| -rw-r--r-- | src/pages/FormPage/Navigation.tsx | 111 | ||||
| -rw-r--r-- | src/pages/FormPage/SuccessPage.tsx | 10 | ||||
| -rw-r--r-- | src/tests/components/OAuth2Button.test.tsx | 4 | 
6 files changed, 101 insertions, 120 deletions
| diff --git a/src/commonStyles.tsx b/src/commonStyles.tsx index bfae17e..b4989da 100644 --- a/src/commonStyles.tsx +++ b/src/commonStyles.tsx @@ -51,8 +51,7 @@ const textInputs = css`    border-radius: 8px;  `; -const submitStyles = css` -  text-align: right; +const actionButtonStyles = css`    white-space: nowrap;    button:disabled { @@ -61,6 +60,7 @@ const submitStyles = css`    }    button { +    width: 100%;      cursor: pointer;      border: none; @@ -91,12 +91,65 @@ const invalidStyles = css`    }  `; +const mainTextStyles = css` +  margin: auto; +  width: 50%; + +  text-align: center; +  font-size: 1.5rem; + +  > div { +    margin: 2rem auto; +  } + +  @media (max-width: 800px) { +    width: 80%; +  } +`; + +const navigationStyles = css` +  display: flex; +  flex-direction: row; +  justify-content: space-around; +  align-items: center; +  flex-wrap: wrap; + +  column-gap: 20px; +  row-gap: 20px; +   +  > * { +    // Make all elements the same size +    flex: 0 1 16rem; +  } +`; + +const returnButtonStyles = css` +  font-size: 1.5rem; +  text-align: center; + +  color: white; +  text-decoration: none; +  background-color: ${colors.greyple}; + +  padding: 0.5rem 0; +  border-radius: 8px; + +  transition: background-color 300ms; + +  :hover { +    background-color: ${colors.darkerGreyple}; +  } +`; +  export {      selectable,      unselectable,      hiddenInput,      multiSelectInput,      textInputs, -    submitStyles, -    invalidStyles +    actionButtonStyles, +    invalidStyles, +    mainTextStyles, +    returnButtonStyles, +    navigationStyles,  }; diff --git a/src/components/OAuth2Button.tsx b/src/components/OAuth2Button.tsx index 885c080..be8d160 100644 --- a/src/components/OAuth2Button.tsx +++ b/src/components/OAuth2Button.tsx @@ -11,7 +11,7 @@ import { selectable } from "../commonStyles";  interface OAuth2ButtonProps {      scopes?: OAuthScopes[], -    rerender: () => void +    rerender?: () => void  }  const iconStyles = css` @@ -59,7 +59,7 @@ async function login(props: OAuth2ButtonProps, errorDialog: React.RefObject<HTML          throw reason.Error;      }); -    if (checkScopes(props.scopes)) { +    if (checkScopes(props.scopes) && props.rerender) {          props.rerender();      }  } @@ -71,7 +71,7 @@ function OAuth2Button(props: OAuth2ButtonProps): JSX.Element {      return <span>          <button disabled={disabled} onClick={() => login(props, errorDialog, setDisabled)}>              <FontAwesomeIcon icon={faDiscord} css={iconStyles}/> -            <span css={textStyles}>Discord Login</span> +            <span css={textStyles}>Login To Submit</span>          </button>          <div css={[errorStyles, selectable]} ref={errorDialog}/>      </span>; diff --git a/src/pages/FormPage/ErrorPage.tsx b/src/pages/FormPage/ErrorPage.tsx index da336cf..351170b 100644 --- a/src/pages/FormPage/ErrorPage.tsx +++ b/src/pages/FormPage/ErrorPage.tsx @@ -7,9 +7,7 @@ import HeaderBar from "../../components/HeaderBar";  import {Form} from "../../api/forms";  import {clearAuth} from "../../api/auth"; -import {selectable, submitStyles, unselectable} from "../../commonStyles"; - -import Navigation from "./Navigation"; +import * as styles from "../../commonStyles";  interface ErrorProps { @@ -28,19 +26,18 @@ export default function ErrorPage(props: ErrorProps): JSX.Element {      return (          <div>              <HeaderBar title={props.form.name} description={props.form.description}/> -            <div css={[unselectable, Navigation.containerStyles]}> -                <h3 css={selectable}>{props.message}</h3> -                <div className={ "return_button" }> -                    <Link to="/" css={Navigation.returnStyles}>Return Home</Link> -                </div> -                <br css={Navigation.separatorStyles}/> -                <div css={submitStyles}> -                    <button -                        type="button" css={refreshStyles} -                        onClick={location.reload.bind(window.location)} // TODO: State should probably be saved here -                    > -                        Refresh -                    </button> +            <div css={[styles.unselectable, styles.mainTextStyles]}> +                <h3 css={styles.selectable}>{props.message}</h3> +                <div css={styles.navigationStyles}> +                    <Link css={styles.returnButtonStyles} to="/">Return Home</Link> +                    <div css={styles.actionButtonStyles}> +                        <button +                            type="button" css={refreshStyles} +                            onClick={location.reload.bind(window.location)} // TODO: State should probably be saved here +                        > +                            Refresh +                        </button> +                    </div>                  </div>              </div>          </div> diff --git a/src/pages/FormPage/Navigation.tsx b/src/pages/FormPage/Navigation.tsx index 52cd47e..20c7dce 100644 --- a/src/pages/FormPage/Navigation.tsx +++ b/src/pages/FormPage/Navigation.tsx @@ -1,12 +1,9 @@  /** @jsx jsx */ -import {jsx, css} from "@emotion/react"; - -import React from "react"; +import {jsx} from "@emotion/react"; +import React, {useState} from "react";  import {Link} from "react-router-dom"; -import colors from "../../colors"; -import {submitStyles, unselectable} from "../../commonStyles"; - +import * as styles from "../../commonStyles";  import {checkScopes, OAuthScopes} from "../../api/auth";  import OAuth2Button from "../../components/OAuth2Button"; @@ -16,92 +13,28 @@ interface NavigationProps {      scopes: OAuthScopes[]  } -export default class Navigation extends React.Component<NavigationProps> { -    static containerStyles = css` -      margin: auto; -      width: 50%; - -      text-align: center; -      font-size: 1.5rem; - -      > div { -        display: inline-block; -        margin: 2rem auto; -        width: 50%; -      } - -      @media (max-width: 870px) { -        width: 100%; - -        > div { -          display: flex; -          justify-content: center; - -          margin: 0 auto; +export default function Navigation(props: NavigationProps): JSX.Element { +    const [authorized, setAuth] = useState<boolean>(!( +        props.scopes.includes(OAuthScopes.Identify) && !checkScopes(props.scopes) +    )); + +    let submit = null; +    if (props.form_state) { +        let innerElement; +        if (!authorized) { +            innerElement = <OAuth2Button rerender={() => setAuth(true)} scopes={props.scopes}/>; +        } else { +            innerElement = <button form="form" type="submit">Submit</button>;          } -      } - -      .return_button { -        text-align: left; -      } - -      .return_button.closed { -        text-align: center; -      } -    `; - -    static separatorStyles = css` -      height: 0; -      display: none; - -      @media (max-width: 870px) { -        display: block; -      } -    `; - -    static returnStyles = css` -      padding: 0.5rem 2.2rem; -      border-radius: 8px; - -      color: white; -      text-decoration: none; -      white-space: nowrap; - -      background-color: ${colors.greyple}; -      transition: background-color 300ms; - -      :hover { -        background-color: ${colors.darkerGreyple}; -      } -    `; - -    constructor(props: NavigationProps) { -        super(props); -        this.state = {"logged_in": false}; +        submit = <div css={styles.actionButtonStyles}>{innerElement}</div>;      } -    render(): JSX.Element { -        let submit = null; - -        if (this.props.form_state) { -            let inner_submit; -            if (this.props.scopes.includes(OAuthScopes.Identify) && !checkScopes(this.props.scopes)) { -                // Render OAuth button if login is required, and the scopes needed are not available -                inner_submit = <OAuth2Button scopes={this.props.scopes} rerender={() => this.setState({"logged_in": true})}/>; -            } else { -                inner_submit = <button form="form" type="submit">Submit</button>; -            } -            submit = <div css={submitStyles}>{ inner_submit }</div>; -        } - -        return ( -            <div css={[unselectable, Navigation.containerStyles]}> -                <div className={ "return_button" + (this.props.form_state ? "" : " closed") }> -                    <Link to="/" css={Navigation.returnStyles}>Return Home</Link> -                </div> -                <br css={Navigation.separatorStyles}/> +    return ( +        <div css={[styles.unselectable, styles.mainTextStyles]}> +            <div css={styles.navigationStyles}> +                <Link to="/" css={styles.returnButtonStyles}>Return Home</Link>                  { submit }              </div> -        ); -    } +        </div> +    );  } diff --git a/src/pages/FormPage/SuccessPage.tsx b/src/pages/FormPage/SuccessPage.tsx index e35bd4d..e83ca0d 100644 --- a/src/pages/FormPage/SuccessPage.tsx +++ b/src/pages/FormPage/SuccessPage.tsx @@ -4,9 +4,7 @@ import {Link} from "react-router-dom";  import {Form} from "../../api/forms";  import HeaderBar from "../../components/HeaderBar"; -import {unselectable} from "../../commonStyles"; - -import Navigation from "./Navigation"; +import {returnButtonStyles, navigationStyles, unselectable, mainTextStyles} from "../../commonStyles";  interface SuccessProps { @@ -34,10 +32,10 @@ export default function Success(props: SuccessProps): JSX.Element {      return (          <div>              <HeaderBar title={props.form.name} description={props.form.description}/> -            <div css={[unselectable, Navigation.containerStyles, divStyle]}> +            <div css={[unselectable, mainTextStyles, divStyle]}>                  <h3 css={thanksStyle}>{submitted_text}</h3> -                <div className={"return_button closed"}> -                    <Link to="/" css={Navigation.returnStyles}>Return Home</Link> +                <div css={navigationStyles}> +                    <Link to="/" css={returnButtonStyles}>Return Home</Link>                  </div>              </div>          </div> diff --git a/src/tests/components/OAuth2Button.test.tsx b/src/tests/components/OAuth2Button.test.tsx index a773686..2a67f98 100644 --- a/src/tests/components/OAuth2Button.test.tsx +++ b/src/tests/components/OAuth2Button.test.tsx @@ -3,8 +3,8 @@ import { render } from "@testing-library/react";  import OAuth2Button from "../../components/OAuth2Button";  test("renders oauth2 sign in button text", () => { -    const { getByText } = render(<OAuth2Button />); -    const button = getByText(/Discord Login/i); +    const { getByText } = render(<OAuth2Button/>); +    const button = getByText(/Login To Submit/i);      expect(button).toBeInTheDocument();  }); | 
