diff options
Diffstat (limited to 'src')
26 files changed, 362 insertions, 360 deletions
| diff --git a/src/App.tsx b/src/App.tsx index b1b2184..523e583 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,9 +4,9 @@ import React, { Suspense } from "react";  import { jsx, css, Global } from "@emotion/react";  import { -  BrowserRouter as Router, -  Route, -  Switch +    BrowserRouter as Router, +    Route, +    Switch  } from "react-router-dom";  import { PropagateLoader } from "react-spinners"; @@ -20,48 +20,48 @@ const FormPage = React.lazy(() => import("./pages/FormPage"));  const CallbackPage = React.lazy(() => import("./pages/CallbackPage"));  const routes = [ -  { path: "/", Component: LandingPage }, -  { path: "/form/:id", Component: FormPage}, -  { path: "/callback", Component: CallbackPage } -] +    { path: "/", Component: LandingPage }, +    { path: "/form/:id", Component: FormPage}, +    { path: "/callback", Component: CallbackPage } +];  function PageLoading() { -  return <div css={css` +    return <div css={css`      display: flex;      justify-content: center;      margin-top: 50px;    `}> -    <PropagateLoader color="white" size={100}/> -  </div> +        <PropagateLoader color="white" size={100}/> +    </div>;  } -function App() { -  return ( -    <div> -      <Global styles={globalStyles}/> -      <Router> -        <Route render={({ location }) => ( -          <TransitionGroup> -            <CSSTransition -              key={location.pathname} -              classNames="fade" -              timeout={300} -            > -              <Switch location={location}> -                {routes.map(({path, Component}) => ( -                  <Route exact key={path} path={path}> -                    <Suspense fallback={<PageLoading/>}> -                      <Component/> -                    </Suspense> -                  </Route> -                ))} -              </Switch> -            </CSSTransition> -          </TransitionGroup> -        )}/> -      </Router> -    </div> -  ); -}; +function App(): JSX.Element { +    return ( +        <div> +            <Global styles={globalStyles}/> +            <Router> +                <Route render={({ location }) => ( +                    <TransitionGroup> +                        <CSSTransition +                            key={location.pathname} +                            classNames="fade" +                            timeout={300} +                        > +                            <Switch location={location}> +                                {routes.map(({path, Component}) => ( +                                    <Route exact key={path} path={path}> +                                        <Suspense fallback={<PageLoading/>}> +                                            <Component/> +                                        </Suspense> +                                    </Route> +                                ))} +                            </Switch> +                        </CSSTransition> +                    </TransitionGroup> +                )}/> +            </Router> +        </div> +    ); +}  export default App; diff --git a/src/api/client.ts b/src/api/client.ts index 32c1993..b534938 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -3,4 +3,4 @@ import axios from "axios";  export default axios.create({      baseURL: process.env.BACKEND_URL -}) +}); diff --git a/src/api/forms.ts b/src/api/forms.ts index 724d6b7..aec4b99 100644 --- a/src/api/forms.ts +++ b/src/api/forms.ts @@ -1,4 +1,4 @@ -import { Question, QuestionType } from "./question" +import { Question, QuestionType } from "./question";  import ApiClient from "./client";  export enum FormFeatures { @@ -36,8 +36,8 @@ export function getForm(id: string): Promise<Form> {                  data: {}              }          ] -    } +    };      return new Promise((resolve) => { -        setTimeout(() => resolve(data), 1500) -    }) +        setTimeout(() => resolve(data), 1500); +    });  }  diff --git a/src/colors.ts b/src/colors.ts index 2107987..e9c74b1 100644 --- a/src/colors.ts +++ b/src/colors.ts @@ -1,8 +1,8 @@  export default { -  blurple: '#7289DA', -  darkButNotBlack: '#2C2F33', -  notQuiteBlack: '#23272A', -  greyple: '#99AAB5', -  error: '#f04747', -  success: '#43b581' -} +    blurple: "#7289DA", +    darkButNotBlack: "#2C2F33", +    notQuiteBlack: "#23272A", +    greyple: "#99AAB5", +    error: "#f04747", +    success: "#43b581" +}; diff --git a/src/components/FormListing.tsx b/src/components/FormListing.tsx index f53efe2..0905903 100644 --- a/src/components/FormListing.tsx +++ b/src/components/FormListing.tsx @@ -2,7 +2,7 @@  import { css, jsx } from "@emotion/react";  import { Link } from "react-router-dom"; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";  import { faArrowRight } from "@fortawesome/free-solid-svg-icons";  import Tag from "./Tag"; @@ -15,8 +15,8 @@ interface FormListingProps {    form: Form  } -function FormListing({ form }: FormListingProps) { -  const listingStyle = css` +function FormListing({ form }: FormListingProps): JSX.Element { +    const listingStyle = css`      background-color: ${form.features.includes(FormFeatures.Open) ? colors.success : colors.darkButNotBlack};      width: 60%;      padding: 20px; @@ -37,18 +37,18 @@ function FormListing({ form }: FormListingProps) {      }    `; -  let closedTag; +    let closedTag; -  if (!form.features.includes(FormFeatures.Open)) { -    closedTag = <Tag text="CLOSED" color={colors.error}/> -  }; +    if (!form.features.includes(FormFeatures.Open)) { +        closedTag = <Tag text="CLOSED" color={colors.error}/>; +    } -  return <Link to={`/form/${form.id}`} css={listingStyle}> -    <div> -      <h3 css={{fontSize: "1.5em", marginBottom: "0"}}>{closedTag}{form.name} <FontAwesomeIcon icon={faArrowRight} css={{fontSize: "0.75em", paddingBottom: "1px"}}/></h3> -      <p css={{marginTop: "5px"}}>{form.description}</p> -    </div> -  </Link> +    return <Link to={`/form/${form.id}`} css={listingStyle}> +        <div> +            <h3 css={{fontSize: "1.5em", marginBottom: "0"}}>{closedTag}{form.name} <FontAwesomeIcon icon={faArrowRight} css={{fontSize: "0.75em", paddingBottom: "1px"}}/></h3> +            <p css={{marginTop: "5px"}}>{form.description}</p> +        </div> +    </Link>;  }  export default FormListing; diff --git a/src/components/HeaderBar/index.tsx b/src/components/HeaderBar/index.tsx index b789ddb..dfe3957 100644 --- a/src/components/HeaderBar/index.tsx +++ b/src/components/HeaderBar/index.tsx @@ -16,17 +16,17 @@ width: 100%;  transition: height 1s;  `; -function HeaderBar({ title }: HeaderBarProps) { -  if (!title) { -    title = "Python Discord Forms"; -  }; +function HeaderBar({ title }: HeaderBarProps): JSX.Element { +    if (!title) { +        title = "Python Discord Forms"; +    } -  return <div> -    <div> -      <Header1 css={headerImageStyles}/> -      <Header2 css={headerImageStyles}/> -    </div> -    <h1 css={css` +    return <div> +        <div> +            <Header1 css={headerImageStyles}/> +            <Header2 css={headerImageStyles}/> +        </div> +        <h1 css={css`        font-size: 4vw;        margin: 0;        margin-top: 30px; @@ -51,9 +51,9 @@ function HeaderBar({ title }: HeaderBarProps) {          margin-left: 0;        }      `}> -      {title} -    </h1> -  </div> +            {title} +        </h1> +    </div>;  }  export default HeaderBar; diff --git a/src/components/Loading.tsx b/src/components/Loading.tsx index 8454366..8dd5474 100644 --- a/src/components/Loading.tsx +++ b/src/components/Loading.tsx @@ -5,13 +5,13 @@ import { PropagateLoader } from "react-spinners";  import HeaderBar from "../components/HeaderBar"; -function Loading() { +function Loading(): JSX.Element {      return <div>          <HeaderBar title={"Loading..."}/>          <div css={{display: "flex", justifyContent: "center", paddingTop: "40px"}}>              <PropagateLoader color="white"/>          </div> -    </div> +    </div>;  }  export default Loading; diff --git a/src/components/OAuth2Button.tsx b/src/components/OAuth2Button.tsx index c364369..4fa3f61 100644 --- a/src/components/OAuth2Button.tsx +++ b/src/components/OAuth2Button.tsx @@ -1,7 +1,7 @@  /** @jsx jsx */  import { css, jsx } from "@emotion/react"; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";  import { faDiscord } from "@fortawesome/free-brands-svg-icons";  import colors from "../colors"; @@ -40,49 +40,49 @@ span {  `;  function doLogin(disableFunction: (newState: boolean) => void) { -  disableFunction(true); +    disableFunction(true); -  const redirectURI = encodeURIComponent(document.location.protocol + "//" + document.location.host + "/callback"); +    const redirectURI = encodeURIComponent(document.location.protocol + "//" + document.location.host + "/callback"); -  const windowRef = window.open( -    `https://discord.com/api/oauth2/authorize?client_id=${OAUTH2_CLIENT_ID}&response_type=code&scope=identify&redirect_uri=${redirectURI}&prompt=none`, -    "Discord_OAuth2", -    "height=700,width=500,location=no,menubar=no,resizable=no,status=no,titlebar=no,left=300,top=300" -  ) +    const windowRef = window.open( +        `https://discord.com/api/oauth2/authorize?client_id=${OAUTH2_CLIENT_ID}&response_type=code&scope=identify&redirect_uri=${redirectURI}&prompt=none`, +        "Discord_OAuth2", +        "height=700,width=500,location=no,menubar=no,resizable=no,status=no,titlebar=no,left=300,top=300" +    ); -  const interval = setInterval(() => { -    if (windowRef?.closed) { -      clearInterval(interval); -      disableFunction(false); -    } -  }, 500) +    const interval = setInterval(() => { +        if (windowRef?.closed) { +            clearInterval(interval); +            disableFunction(false); +        } +    }, 500); -  window.onmessage = (code: MessageEvent) => { -    if (code.data.source) { -      // React DevTools has a habit of sending messages, ignore them. -      return; -    } +    window.onmessage = (code: MessageEvent) => { +        if (code.data.source) { +            // React DevTools has a habit of sending messages, ignore them. +            return; +        } -    if (code.isTrusted) { -      windowRef?.close(); +        if (code.isTrusted) { +            windowRef?.close(); -      console.log("Code received:", code.data); +            console.log("Code received:", code.data); -      disableFunction(false); -      clearInterval(interval); +            disableFunction(false); +            clearInterval(interval); -      window.onmessage = null; -    } -  }; +            window.onmessage = null; +        } +    };  } -function OAuth2Button() { -  const [disabled, setDisabled] = useState<boolean>(false); +function OAuth2Button(): JSX.Element { +    const [disabled, setDisabled] = useState<boolean>(false); -  return <button disabled={disabled} onClick={() => doLogin(setDisabled)} css={buttonStyling}> -    <span css={{marginRight: "10px"}}><FontAwesomeIcon icon={faDiscord} css={{fontSize: "2em", marginTop: "3px"}}/></span> -    <span>Sign in with Discord</span> -  </button>; +    return <button disabled={disabled} onClick={() => doLogin(setDisabled)} css={buttonStyling}> +        <span css={{marginRight: "10px"}}><FontAwesomeIcon icon={faDiscord} css={{fontSize: "2em", marginTop: "3px"}}/></span> +        <span>Sign in with Discord</span> +    </button>;  }  export default OAuth2Button; diff --git a/src/components/Tag.tsx b/src/components/Tag.tsx index 0c55348..3e5b1f5 100644 --- a/src/components/Tag.tsx +++ b/src/components/Tag.tsx @@ -7,7 +7,7 @@ interface TagProps {      fontSize?: string  } -function Tag(props: TagProps) { +function Tag(props: TagProps): JSX.Element {      return <span css={css`          font-size: ${props.fontSize ? props.fontSize : "0.75em"};          background-color: ${props.color}; diff --git a/src/index.tsx b/src/index.tsx index 73e8120..871eb40 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,50 +1,52 @@ -import React from 'react'; -import ReactDOM from 'react-dom'; -import App from './App'; -import * as serviceWorker from './serviceWorker'; +import React from "react"; +import ReactDOM from "react-dom"; +import App from "./App"; +import * as serviceWorker from "./serviceWorker";  import * as Sentry from "@sentry/react";  import colors from "./colors";  if (process.env.NODE_ENV === "production") { -  Sentry.init({ -    dsn: process.env.REACT_APP_SENTRY_DSN, -    tracesSampleRate: 0.25, -    release: `forms-frontend@${process.env.REACT_APP_SHA}`, -    environment: process.env.CONTEXT -  }); +    Sentry.init({ +        dsn: process.env.REACT_APP_SENTRY_DSN, +        tracesSampleRate: 0.25, +        release: `forms-frontend@${process.env.REACT_APP_SHA}`, +        environment: process.env.CONTEXT +    });  } -console.log("%c  Python Discord Forms  ", `font-size: 6em; font-family: "Hind", "Arial"; font-weight: 900; background-color: ${colors.blurple}; border-radius: 10px;`) -console.log("%cWelcome to Python Discord Forms", `font-size: 3em; font-family: "Hind", "Arial";`) +console.log("%c  Python Discord Forms  ", `font-size: 6em; font-family: "Hind", "Arial"; font-weight: 900; background-color: ${colors.blurple}; border-radius: 10px;`); +console.log("%cWelcome to Python Discord Forms", "font-size: 3em; font-family: \"Hind\", \"Arial\";"); -console.log(`   Environment: %c ${process.env.NODE_ENV} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.NODE_ENV === "production" ? colors.success : colors.error}`) -console.log(`   Context: %c ${process.env.CONTEXT} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.CONTEXT === "production" ? colors.success : colors.error}`) -console.log(`   Location: %c ${document.location.pathname + document.location.search + document.location.hash} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`) -console.log(`   User Agent: %c ${navigator.userAgent} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`) -console.log(`   Branch: %c ${process.env.REACT_APP_BRANCH} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.REACT_APP_BRANCH === "main" ? colors.success : colors.error}`) -console.log(`   SHA: %c ${process.env.REACT_APP_SHA} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`) +console.log(`   Environment: %c ${process.env.NODE_ENV} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.NODE_ENV === "production" ? colors.success : colors.error}`); +console.log(`   Context: %c ${process.env.CONTEXT} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.CONTEXT === "production" ? colors.success : colors.error}`); +console.log(`   Location: %c ${document.location.pathname + document.location.search + document.location.hash} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`); +console.log(`   User Agent: %c ${navigator.userAgent} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`); +console.log(`   Branch: %c ${process.env.REACT_APP_BRANCH} `, `padding: 2px; border-radius: 5px; background-color: ${process.env.REACT_APP_BRANCH === "main" ? colors.success : colors.error}`); +console.log(`   SHA: %c ${process.env.REACT_APP_SHA} `, `padding: 2px; border-radius: 5px; background-color: ${colors.success}`); -console.log("%cCome join us on Discord! https://discord.gg/python", `font-size: 1.5em; font-family: "Hind", "Arial"; color: ${colors.blurple}`) +console.log("%cCome join us on Discord! https://discord.gg/python", `font-size: 1.5em; font-family: "Hind", "Arial"; color: ${colors.blurple}`); +/* eslint-disable react/react-in-jsx-scope */  ReactDOM.render( -  <React.StrictMode> -    <Sentry.ErrorBoundary -      fallback={<p>An error has occurred with Python Discord Forms. Please let us know in the Discord server at <a href="https://discord.gg/python">discord.gg/python</a></p>} -      showDialog={true} -      dialogOptions={{ -        title: "You've found a bug in PyDis forms!" -      }} -      onError={(err) => { -        if(process.env.NODE_ENV === "development") -          console.log(err) -      }} -    > -      <App /> -    </Sentry.ErrorBoundary> -  </React.StrictMode>, -  document.getElementById('root') +    <React.StrictMode> +        <Sentry.ErrorBoundary +            fallback={<p>An error has occurred with Python Discord Forms. Please let us know in the Discord server at <a href="https://discord.gg/python">discord.gg/python</a></p>} +            showDialog={true} +            dialogOptions={{ +                title: "You've found a bug in PyDis forms!" +            }} +            onError={(err) => { +                if(process.env.NODE_ENV === "development") +                    console.log(err); +            }} +        > +            <App /> +        </Sentry.ErrorBoundary> +    </React.StrictMode>, +    document.getElementById("root")  ); +/* eslint-enable react/react-in-jsx-scope */  serviceWorker.unregister(); diff --git a/src/pages/CallbackPage.tsx b/src/pages/CallbackPage.tsx index 691a3e4..fab2086 100644 --- a/src/pages/CallbackPage.tsx +++ b/src/pages/CallbackPage.tsx @@ -2,7 +2,7 @@  import { jsx } from "@emotion/react";  import { useState } from "react"; -export default function CallbackPage() { +export default function CallbackPage(): JSX.Element {      const [hasSent, setHasSent] = useState(false);      const params = new URLSearchParams(location.search); diff --git a/src/pages/FormPage.tsx b/src/pages/FormPage.tsx index 97ff24d..1805897 100644 --- a/src/pages/FormPage.tsx +++ b/src/pages/FormPage.tsx @@ -12,7 +12,7 @@ interface PathParams {      id: string  } -function FormPage() { +function FormPage(): JSX.Element {      const { id } = useParams<PathParams>();      const [form, setForm] = useState<Form>(); @@ -20,11 +20,11 @@ function FormPage() {      useEffect(() => {          getForm(id).then(form => {              setForm(form); -        }) -    }) +        }); +    });      if (!form) { -        return <Loading/> +        return <Loading/>;      }      return <div> @@ -33,7 +33,7 @@ function FormPage() {              <h1>{form.description}</h1>              <Link to="/" css={{color: "white"}}>Return home</Link>          </div> -    </div> +    </div>;  }  export default FormPage; diff --git a/src/pages/LandingPage.tsx b/src/pages/LandingPage.tsx index 1320c14..124bbcf 100644 --- a/src/pages/LandingPage.tsx +++ b/src/pages/LandingPage.tsx @@ -9,40 +9,40 @@ import { getForms, Form } from "../api/forms";  import OAuth2Button from "../components/OAuth2Button";  import Loading from "../components/Loading"; -function LandingPage() { -  const [forms, setForms] = useState<Form[]>(); - -  useEffect(() => { -    const fetchForms = async () => { -      setForms(await getForms()); +function LandingPage(): JSX.Element { +    const [forms, setForms] = useState<Form[]>(); + +    useEffect(() => { +        const fetchForms = async () => { +            setForms(await getForms()); +        }; +        fetchForms(); +    }, []); + +    if (!forms) { +        return <Loading/>;      } -    fetchForms(); -  }, []); - -  if (!forms) { -    return <Loading/>; -  } -  return <div> -    <HeaderBar/> -    <div> +    return <div> +        <HeaderBar/> +        <div> -      <div css={css` +            <div css={css`          display: flex;          align-items: center;          flex-direction: column;        `}> -        <h1>Available Forms</h1> +                <h1>Available Forms</h1> -        <OAuth2Button/> +                <OAuth2Button/> -        {forms.map(form => ( -          <FormListing key={form.id} form={form}/> -        ))} -      </div> -    </div> -  </div> +                {forms.map(form => ( +                    <FormListing key={form.id} form={form}/> +                ))} +            </div> +        </div> +    </div>;  }  export default LandingPage; diff --git a/src/react-app-env.d.ts b/src/react-app-env.d.ts index 981cd73..d7e3ac4 100644 --- a/src/react-app-env.d.ts +++ b/src/react-app-env.d.ts @@ -1,46 +1,46 @@ -/// <reference types="node" /> -/// <reference types="react" /> -/// <reference types="react-dom" /> +import("node"); +import("react"); +import("react-dom");  declare namespace NodeJS {    interface ProcessEnv { -    readonly NODE_ENV: 'development' | 'production' | 'test'; +    readonly NODE_ENV: "development" | "production" | "test";      readonly PUBLIC_URL: string;    }  } -declare module '*.bmp' { +declare module "*.bmp" {    const src: string;    export default src;  } -declare module '*.gif' { +declare module "*.gif" {    const src: string;    export default src;  } -declare module '*.jpg' { +declare module "*.jpg" {    const src: string;    export default src;  } -declare module '*.jpeg' { +declare module "*.jpeg" {    const src: string;    export default src;  } -declare module '*.png' { +declare module "*.png" {    const src: string;    export default src;  } -declare module '*.webp' { +declare module "*.webp" {      const src: string;      export default src;  } -declare module '*.svg' { -  import * as React from 'react'; +declare module "*.svg" { +  import * as React from "react";    export const ReactComponent: React.FunctionComponent<React.SVGProps<      SVGSVGElement @@ -50,17 +50,17 @@ declare module '*.svg' {    export default src;  } -declare module '*.module.css' { +declare module "*.module.css" {    const classes: { readonly [key: string]: string };    export default classes;  } -declare module '*.module.scss' { +declare module "*.module.scss" {    const classes: { readonly [key: string]: string };    export default classes;  } -declare module '*.module.sass' { +declare module "*.module.sass" {    const classes: { readonly [key: string]: string };    export default classes;  } diff --git a/src/serviceWorker.ts b/src/serviceWorker.ts index 2b4d2b5..600d89d 100644 --- a/src/serviceWorker.ts +++ b/src/serviceWorker.ts @@ -1,10 +1,10 @@  const isLocalhost = Boolean( -  window.location.hostname === 'localhost' || +    window.location.hostname === "localhost" ||      // [::1] is the IPv6 localhost address. -    window.location.hostname === '[::1]' || +    window.location.hostname === "[::1]" ||      // 127.0.0.0/8 are considered localhost for IPv4.      window.location.hostname.match( -      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ +        /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/      )  ); @@ -13,125 +13,125 @@ type Config = {    onUpdate?: (registration: ServiceWorkerRegistration) => void;  }; -export function register(config?: Config) { -  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { +export function register(config?: Config): void { +    if (process.env.NODE_ENV === "production" && "serviceWorker" in navigator) {      // The URL constructor is available in all browsers that support SW. -    const publicUrl = new URL( -      process.env.PUBLIC_URL, -      window.location.href -    ); -    if (publicUrl.origin !== window.location.origin) { -      // Our service worker won't work if PUBLIC_URL is on a different origin -      // from what our page is served on. This might happen if a CDN is used to -      // serve assets; see https://github.com/facebook/create-react-app/issues/2374 -      return; -    } +        const publicUrl = new URL( +            process.env.PUBLIC_URL, +            window.location.href +        ); +        if (publicUrl.origin !== window.location.origin) { +            // Our service worker won't work if PUBLIC_URL is on a different origin +            // from what our page is served on. This might happen if a CDN is used to +            // serve assets; see https://github.com/facebook/create-react-app/issues/2374 +            return; +        } -    window.addEventListener('load', () => { -      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; +        window.addEventListener("load", () => { +            const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; -      if (isLocalhost) { -        // This is running on localhost. Let's check if a service worker still exists or not. -        checkValidServiceWorker(swUrl, config); +            if (isLocalhost) { +                // This is running on localhost. Let's check if a service worker still exists or not. +                checkValidServiceWorker(swUrl, config); -        // Add some additional logging to localhost, pointing developers to the -        // service worker/PWA documentation. -        navigator.serviceWorker.ready.then(() => { -          console.log( -            'This web app is being served cache-first by a service ' + -              'worker. To learn more, visit https://bit.ly/CRA-PWA' -          ); +                // Add some additional logging to localhost, pointing developers to the +                // service worker/PWA documentation. +                navigator.serviceWorker.ready.then(() => { +                    console.log( +                        "This web app is being served cache-first by a service " + +              "worker. To learn more, visit https://bit.ly/CRA-PWA" +                    ); +                }); +            } else { +                // Is not localhost. Just register service worker +                registerValidSW(swUrl, config); +            }          }); -      } else { -        // Is not localhost. Just register service worker -        registerValidSW(swUrl, config); -      } -    }); -  } +    }  }  function registerValidSW(swUrl: string, config?: Config) { -  navigator.serviceWorker -    .register(swUrl) -    .then(registration => { -      registration.onupdatefound = () => { -        const installingWorker = registration.installing; -        if (installingWorker == null) { -          return; -        } -        installingWorker.onstatechange = () => { -          if (installingWorker.state === 'installed') { -            if (navigator.serviceWorker.controller) { -              // At this point, the updated precached content has been fetched, -              // but the previous service worker will still serve the older -              // content until all client tabs are closed. -              console.log( -                'New content is available and will be used when all ' + -                  'tabs for this page are closed. See https://bit.ly/CRA-PWA.' -              ); +    navigator.serviceWorker +        .register(swUrl) +        .then(registration => { +            registration.onupdatefound = () => { +                const installingWorker = registration.installing; +                if (installingWorker == null) { +                    return; +                } +                installingWorker.onstatechange = () => { +                    if (installingWorker.state === "installed") { +                        if (navigator.serviceWorker.controller) { +                            // At this point, the updated precached content has been fetched, +                            // but the previous service worker will still serve the older +                            // content until all client tabs are closed. +                            console.log( +                                "New content is available and will be used when all " + +                  "tabs for this page are closed. See https://bit.ly/CRA-PWA." +                            ); -              // Execute callback -              if (config && config.onUpdate) { -                config.onUpdate(registration); -              } -            } else { -              // At this point, everything has been precached. -              // It's the perfect time to display a -              // "Content is cached for offline use." message. -              console.log('Content is cached for offline use.'); +                            // Execute callback +                            if (config && config.onUpdate) { +                                config.onUpdate(registration); +                            } +                        } else { +                            // At this point, everything has been precached. +                            // It's the perfect time to display a +                            // "Content is cached for offline use." message. +                            console.log("Content is cached for offline use."); -              // Execute callback -              if (config && config.onSuccess) { -                config.onSuccess(registration); -              } -            } -          } -        }; -      }; -    }) -    .catch(error => { -      console.error('Error during service worker registration:', error); -    }); +                            // Execute callback +                            if (config && config.onSuccess) { +                                config.onSuccess(registration); +                            } +                        } +                    } +                }; +            }; +        }) +        .catch(error => { +            console.error("Error during service worker registration:", error); +        });  }  function checkValidServiceWorker(swUrl: string, config?: Config) { -  // Check if the service worker can be found. If it can't reload the page. -  fetch(swUrl, { -    headers: { 'Service-Worker': 'script' } -  }) -    .then(response => { -      // Ensure service worker exists, and that we really are getting a JS file. -      const contentType = response.headers.get('content-type'); -      if ( -        response.status === 404 || -        (contentType != null && contentType.indexOf('javascript') === -1) -      ) { -        // No service worker found. Probably a different app. Reload the page. -        navigator.serviceWorker.ready.then(registration => { -          registration.unregister().then(() => { -            window.location.reload(); -          }); -        }); -      } else { -        // Service worker found. Proceed as normal. -        registerValidSW(swUrl, config); -      } +    // Check if the service worker can be found. If it can't reload the page. +    fetch(swUrl, { +        headers: { "Service-Worker": "script" }      }) -    .catch(() => { -      console.log( -        'No internet connection found. App is running in offline mode.' -      ); -    }); +        .then(response => { +            // Ensure service worker exists, and that we really are getting a JS file. +            const contentType = response.headers.get("content-type"); +            if ( +                response.status === 404 || +        (contentType != null && contentType.indexOf("javascript") === -1) +            ) { +                // No service worker found. Probably a different app. Reload the page. +                navigator.serviceWorker.ready.then(registration => { +                    registration.unregister().then(() => { +                        window.location.reload(); +                    }); +                }); +            } else { +                // Service worker found. Proceed as normal. +                registerValidSW(swUrl, config); +            } +        }) +        .catch(() => { +            console.log( +                "No internet connection found. App is running in offline mode." +            ); +        });  } -export function unregister() { -  if ('serviceWorker' in navigator) { -    navigator.serviceWorker.ready -      .then(registration => { -        registration.unregister(); -      }) -      .catch(error => { -        console.error(error.message); -      }); -  } +export function unregister(): void { +    if ("serviceWorker" in navigator) { +        navigator.serviceWorker.ready +            .then(registration => { +                registration.unregister(); +            }) +            .catch(error => { +                console.error(error.message); +            }); +    }  } diff --git a/src/setupTests.ts b/src/setupTests.ts index 4dc2c73..5018a42 100644 --- a/src/setupTests.ts +++ b/src/setupTests.ts @@ -1,2 +1,2 @@ -import '@testing-library/jest-dom/extend-expect'; +import "@testing-library/jest-dom/extend-expect"; diff --git a/src/tests/App.test.tsx b/src/tests/App.test.tsx index e050d4f..4765f87 100644 --- a/src/tests/App.test.tsx +++ b/src/tests/App.test.tsx @@ -1,9 +1,9 @@ -import React from 'react'; -import { render } from '@testing-library/react'; +import React from "react"; +import { render } from "@testing-library/react";  import App from "../App"; -test('renders app to body', () => { +test("renders app to body", () => {      const { container } = render(<App />);      expect(container).toBeInTheDocument();  }); diff --git a/src/tests/api/forms.test.ts b/src/tests/api/forms.test.ts index 6e63965..10ccaa3 100644 --- a/src/tests/api/forms.test.ts +++ b/src/tests/api/forms.test.ts @@ -1,7 +1,7 @@ -import { getForm, getForms } from "../../api/forms"; +import { getForm } from "../../api/forms"; -test('fetch a specific form', () => { -    expect(getForm("ban-appeals")).resolves.toHaveProperty("name", "Ban Appeals") +test("fetch a specific form", () => { +    expect(getForm("ban-appeals")).resolves.toHaveProperty("name", "Ban Appeals");  });  export default null; diff --git a/src/tests/components/FormListing.test.tsx b/src/tests/components/FormListing.test.tsx index 0afe10c..ad76381 100644 --- a/src/tests/components/FormListing.test.tsx +++ b/src/tests/components/FormListing.test.tsx @@ -1,11 +1,11 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import '@testing-library/jest-dom/extend-expect'; +import React from "react"; +import { render } from "@testing-library/react"; +import "@testing-library/jest-dom/extend-expect";  import FormListing from "../../components/FormListing"; -import { BrowserRouter as Router } from 'react-router-dom'; -import { Form, FormFeatures } from '../../api/forms'; -import { QuestionType } from '../../api/question'; +import { BrowserRouter as Router } from "react-router-dom"; +import { Form, FormFeatures } from "../../api/forms"; +import { QuestionType } from "../../api/question";  const openFormListing: Form = {      name: "Example form listing", @@ -20,7 +20,7 @@ const openFormListing: Form = {              "data": {}          }      ] -} +};  const closedFormListing: Form = {      name: "Example form listing", @@ -35,28 +35,28 @@ const closedFormListing: Form = {              "data": {}          }      ] -} +}; -test('renders form listing with specified title', () => { +test("renders form listing with specified title", () => {      const { getByText } = render(<Router><FormListing form={openFormListing} /></Router>);      const formListing = getByText(/Example form listing/i);      expect(formListing).toBeInTheDocument();  }); -test('renders form listing with specified description', () => { +test("renders form listing with specified description", () => {      const { getByText } = render(<Router><FormListing form={openFormListing} /></Router>);      const formListing = getByText(/My form listing/i);      expect(formListing).toBeInTheDocument();  }); -test('renders form listing with background green colour for open', () => { +test("renders form listing with background green colour for open", () => {      const { container } = render(<Router><FormListing form={openFormListing} /></Router>);      const elem = container.querySelector("a");      const style = window.getComputedStyle(elem);      expect(style.backgroundColor).toBe("rgb(67, 181, 129)");  }); -test('renders form listing with background dark colour for closed', () => { +test("renders form listing with background dark colour for closed", () => {      const { container } = render(<Router><FormListing form={closedFormListing} /></Router>);      const elem = container.querySelector("a");      const style = window.getComputedStyle(elem); diff --git a/src/tests/components/HeaderBar.test.tsx b/src/tests/components/HeaderBar.test.tsx index 6963859..9c232ad 100644 --- a/src/tests/components/HeaderBar.test.tsx +++ b/src/tests/components/HeaderBar.test.tsx @@ -1,15 +1,15 @@ -import React from 'react'; -import { render } from '@testing-library/react'; -import '@testing-library/jest-dom/extend-expect' +import React from "react"; +import { render } from "@testing-library/react"; +import "@testing-library/jest-dom/extend-expect";  import HeaderBar from "../../components/HeaderBar"; -test('renders header bar with title', () => { +test("renders header bar with title", () => {      const { getByText } = render(<HeaderBar />);      const formListing = getByText(/Python Discord Forms/i);      expect(formListing).toBeInTheDocument();  }); -test('renders header bar with custom title', () => { +test("renders header bar with custom title", () => {      const { getByText } = render(<HeaderBar title="Testing title"/>);      const formListing = getByText(/Testing title/i);      expect(formListing).toBeInTheDocument(); diff --git a/src/tests/components/OAuth2Button.test.tsx b/src/tests/components/OAuth2Button.test.tsx index 53875dc..f05159f 100644 --- a/src/tests/components/OAuth2Button.test.tsx +++ b/src/tests/components/OAuth2Button.test.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import { render } from '@testing-library/react'; +import React from "react"; +import { render } from "@testing-library/react";  import OAuth2Button from "../../components/OAuth2Button"; -test('renders oauth2 sign in button text', () => { +test("renders oauth2 sign in button text", () => {      const { getByText } = render(<OAuth2Button />);      const button = getByText(/Sign in with Discord/i);      expect(button).toBeInTheDocument(); @@ -10,6 +10,6 @@ test('renders oauth2 sign in button text', () => {  test("renders fontawesome discord icon", () => {      const { container } = render(<OAuth2Button/>); -    const icon = container.querySelector(`[data-icon="discord"]`) +    const icon = container.querySelector("[data-icon=\"discord\"]");      expect(icon).toBeInTheDocument(); -}) +}); diff --git a/src/tests/components/Tag.test.tsx b/src/tests/components/Tag.test.tsx index 67f2a85..50b3b0e 100644 --- a/src/tests/components/Tag.test.tsx +++ b/src/tests/components/Tag.test.tsx @@ -1,28 +1,28 @@ -import React from 'react'; -import { render } from '@testing-library/react'; +import React from "react"; +import { render } from "@testing-library/react";  import Tag from "../../components/Tag"; -test('renders tag with specified text', () => { +test("renders tag with specified text", () => {      const { getByText } = render(<Tag text="Test" color="#f0f0f0" />);      const tag = getByText(/Test/i);      expect(tag).toBeInTheDocument();  }); -test('renders tag with specified color', () => { +test("renders tag with specified color", () => {      const { getByText } = render(<Tag text="Test" color="#f0f0f0" />);      const tag = getByText(/Test/i);      const style = window.getComputedStyle(tag);      expect(style.backgroundColor).toBe("rgb(240, 240, 240)");  }); -test('renders tag with specified font size', () => { +test("renders tag with specified font size", () => {      const { getByText } = render(<Tag text="Test" color="#f0f0f0" fontSize="2em" />);      const tag = getByText(/Test/i);      const style = window.getComputedStyle(tag);      expect(style.fontSize).toBe("2em");  }); -test('defaults to 0.75em when no tag font size is passed', () => { +test("defaults to 0.75em when no tag font size is passed", () => {      const { getByText } = render(<Tag text="Test" color="#f0f0f0" />);      const tag = getByText(/Test/i);      const style = window.getComputedStyle(tag); diff --git a/src/tests/globalStyles.test.ts b/src/tests/globalStyles.test.ts index d44cc51..a7017c8 100644 --- a/src/tests/globalStyles.test.ts +++ b/src/tests/globalStyles.test.ts @@ -2,4 +2,4 @@ import globalStyles from "../globalStyles";  test("global styles emotion css compiles", () => {      expect(globalStyles.styles).not.toBeUndefined(); -}) +}); diff --git a/src/tests/pages/CallbackPage.test.tsx b/src/tests/pages/CallbackPage.test.tsx index e878577..9049ca3 100644 --- a/src/tests/pages/CallbackPage.test.tsx +++ b/src/tests/pages/CallbackPage.test.tsx @@ -1,23 +1,23 @@ -import React from 'react'; -import { render } from '@testing-library/react'; +import React from "react"; +import { render } from "@testing-library/react"; -import CallbackPage from '../../pages/CallbackPage'; +import CallbackPage from "../../pages/CallbackPage"; -test('callback page renders provided code', () => { +test("callback page renders provided code", () => {      global.opener = {          postMessage: jest.fn() -    } +    }; -    let mockLocation = new URL("https://forms.pythondiscord.com/authorize?code=abcdef"); +    const mockLocation = new URL("https://forms.pythondiscord.com/authorize?code=abcdef"); -    Object.defineProperty(global, "location", {value: mockLocation}) +    Object.defineProperty(global, "location", {value: mockLocation}); -    let comp = <CallbackPage />; +    const comp = <CallbackPage />;      const { getByText } = render(comp); -    let codeText = getByText(/Code is abcdef/); +    const codeText = getByText(/Code is abcdef/);      expect(codeText).toBeInTheDocument(); -    expect(global.opener.postMessage).toBeCalledTimes(1) +    expect(global.opener.postMessage).toBeCalledTimes(1);  }); diff --git a/src/tests/pages/FormPage.test.tsx b/src/tests/pages/FormPage.test.tsx index 7bfc763..f7ecc32 100644 --- a/src/tests/pages/FormPage.test.tsx +++ b/src/tests/pages/FormPage.test.tsx @@ -1,28 +1,28 @@ -import React from 'react'; -import { render } from '@testing-library/react'; +import React from "react"; +import { render } from "@testing-library/react";  import { createMemoryHistory } from "history";  import { Route, BrowserRouter as Router } from "react-router-dom"; -import FormPage from '../../pages/FormPage'; +import FormPage from "../../pages/FormPage";  import * as forms from "../../api/forms"; -test('renders specific form page with loading bar', () => { +test("renders specific form page with loading bar", () => {      const history = createMemoryHistory();      history.push("/form/route");      const { getByText } = render(<Router><Route history={history} ><FormPage /></Route></Router>);      // If we rendered the headerbar we rendered the forms page. -    let headerBar = getByText(/Loading.../); +    const headerBar = getByText(/Loading.../);      expect(headerBar).toBeInTheDocument();  }); -test('calls api method to load form', () => { +test("calls api method to load form", () => {      const history = createMemoryHistory();      history.push("/form/ban-appeals"); -    let oldImpl = forms.getForm; +    const oldImpl = forms.getForm;      Object.defineProperty(forms, "getForm", {value: jest.fn(oldImpl)}); diff --git a/src/tests/pages/LandingPage.test.tsx b/src/tests/pages/LandingPage.test.tsx index 23195bd..5635e63 100644 --- a/src/tests/pages/LandingPage.test.tsx +++ b/src/tests/pages/LandingPage.test.tsx @@ -1,11 +1,11 @@ -import React from 'react'; -import { render } from '@testing-library/react'; +import React from "react"; +import { render } from "@testing-library/react";  import LandingPage from "../../pages/LandingPage";  import * as forms from "../../api/forms";  import { BrowserRouter as Router } from "react-router-dom"; -import { QuestionType } from '../../api/question'; +import { QuestionType } from "../../api/question";  const testingForm: forms.Form = {      "id": "testing-form", @@ -20,15 +20,15 @@ const testingForm: forms.Form = {              "data": {}          }      ] -} +}; -test('renders landing page', () => { +test("renders landing page", () => {      const setForms = jest.fn(() => [testingForm]);      Object.defineProperty(forms, "getForms", setForms);      const handleForms = jest.spyOn(React, "useState"); -    handleForms.mockImplementation(_value => [[testingForm], setForms]); +    handleForms.mockImplementation(() => [[testingForm], setForms]);      const { getByText } = render(<Router><LandingPage /></Router>);      // If we rendered the headerbar we rendered the landing page. -    let headerBar = getByText(/Python Discord Forms/); +    const headerBar = getByText(/Python Discord Forms/);      expect(headerBar).toBeInTheDocument();  }); | 
