From 3a9c7c146ef3b5ab9650fbb83e1a338eec73ee3a Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 13 Dec 2020 20:44:04 +0200 Subject: Update question types and interface to match changes in backend --- src/api/question.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/api/question.ts b/src/api/question.ts index e051459..bdd6b99 100644 --- a/src/api/question.ts +++ b/src/api/question.ts @@ -1,11 +1,17 @@ export enum QuestionType { - Text, - Checkbox, - Radio, - Code + TextArea = "textarea", + Checkbox = "checkbox", + Radio = "radio", + Code = "code", + Select = "select", + ShortText = "short_text", + Range = "range", + Section = "section" } export interface Question { + id: string, name: string, - type: QuestionType + type: QuestionType, + data: { [key: string]: any } } -- cgit v1.2.3 From 296ee9774e53d990f73bf7f56edc5ec351f0609f Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Sun, 13 Dec 2020 20:44:28 +0200 Subject: Update form interface and add features --- src/api/forms.ts | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/src/api/forms.ts b/src/api/forms.ts index a4a4981..c20a587 100644 --- a/src/api/forms.ts +++ b/src/api/forms.ts @@ -1,17 +1,22 @@ import { Question, QuestionType } from "./question" -export interface AllFormsForm { - title: string, - id: string, - description: string, - open: boolean +export enum FormFeatures { + Discoverable = "DISCOVERABLE", + RequiresLogin = "REQUIRES_LOGIN", + Open = "OPEN", + CollectEmail = "COLLECT_EMAIL", + DisableAntispam = "DISABLE_ANTISPAM" } -export interface Form extends AllFormsForm { - questions: Array +export interface Form { + id: string, + features: Array, + questions: Array, + name: string, + description: string } -export function getForms(): AllFormsForm[] { +export function getForms(): Form[] { return [ { title: "Ban Appeals", @@ -36,14 +41,16 @@ export function getForms(): AllFormsForm[] { export function getForm(id: string): Promise
{ const data: Form = { - title: "Ban Appeals", + name: "Ban Appeals", id: "ban-appeals", description: "Appealing bans from the Discord server", - open: true, + features: [FormFeatures.Discoverable, FormFeatures.Open], questions: [ { + id: "how-spanish-are-you", name: "How Spanish are you?", - type: QuestionType.Text + type: QuestionType.ShortText, + data: {} } ] } -- cgit v1.2.3 From 59250aa45eef3c633bbb22d0ecd5fc21f6bf7f44 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 10:49:13 +0200 Subject: Install Axios dependency --- package.json | 1 + yarn.lock | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/package.json b/package.json index ba58f62..e93d18d 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "@types/react-transition-group": "^4.4.0", "@typescript-eslint/eslint-plugin": "^2.10.0", "@typescript-eslint/parser": "^2.10.0", + "axios": "^0.21.0", "copy-webpack-plugin": "^6.2.1", "eslint": "^6.6.0", "eslint-config-react-app": "^5.2.1", diff --git a/yarn.lock b/yarn.lock index 608cd3d..0ea5831 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2749,6 +2749,13 @@ axios@^0.18.0: follow-redirects "1.5.10" is-buffer "^2.0.2" +axios@^0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.0.tgz#26df088803a2350dff2c27f96fef99fe49442aca" + integrity sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw== + dependencies: + follow-redirects "^1.10.0" + axobject-query@^2.0.2: version "2.2.0" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" @@ -5311,6 +5318,11 @@ follow-redirects@^1.0.0: resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== +follow-redirects@^1.10.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7" + integrity sha512-SSG5xmZh1mkPGyKzjZP8zLjltIfpW32Y5QpdNJyjcfGxK3qo3NDDkZOZSFiGn1A6SclQxY9GzEwAHQ3dmYRWpg== + for-in@^0.1.3: version "0.1.8" resolved "https://registry.yarnpkg.com/for-in/-/for-in-0.1.8.tgz#d8773908e31256109952b1fdb9b3fa867d2775e1" -- cgit v1.2.3 From 1ee5c3b2e5c9339492bd3aa7ef5d0769d554f48c Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 10:49:39 +0200 Subject: Create Axios client for backend --- src/api/client.ts | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/api/client.ts diff --git a/src/api/client.ts b/src/api/client.ts new file mode 100644 index 0000000..6d1491a --- /dev/null +++ b/src/api/client.ts @@ -0,0 +1,6 @@ +import axios from "axios"; + + +export default axios.create({ + baseURL: process.env.BACKEND_URL || "https://forms-api.pythondiscord.com/" +}) -- cgit v1.2.3 From 8aa3be64c1723bb39a7c580472a3ec81f7956125 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 10:50:08 +0200 Subject: Move loading to different component --- src/components/Loading.tsx | 17 +++++++++++++++++ src/pages/FormPage.tsx | 14 ++------------ 2 files changed, 19 insertions(+), 12 deletions(-) create mode 100644 src/components/Loading.tsx diff --git a/src/components/Loading.tsx b/src/components/Loading.tsx new file mode 100644 index 0000000..48dcdbc --- /dev/null +++ b/src/components/Loading.tsx @@ -0,0 +1,17 @@ +/** @jsx jsx */ +import { jsx } from "@emotion/core"; + +import { HashLoader } from "react-spinners"; + +import HeaderBar from "../components/HeaderBar"; + +function Loading() { + return
+ +
+ +
+
+} + +export default Loading; diff --git a/src/pages/FormPage.tsx b/src/pages/FormPage.tsx index a675f8e..ad746c7 100644 --- a/src/pages/FormPage.tsx +++ b/src/pages/FormPage.tsx @@ -2,26 +2,16 @@ import { jsx } from "@emotion/core"; import { Link } from "react-router-dom"; -import { HashLoader } from "react-spinners"; - import { useParams } from "react-router"; import HeaderBar from "../components/HeaderBar"; import { useEffect, useState } from "react"; import { Form, getForm } from "../api/forms"; +import Loading from "../components/Loading"; interface PathParams { id: string } -function Loading() { - return
- -
- -
-
-} - function FormPage() { const { id } = useParams(); @@ -38,7 +28,7 @@ function FormPage() { } return
- +

{form.description}

Return home -- cgit v1.2.3 From 8e2b2764b136b9e742f75f7b4a3621cb56238bc6 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 10:50:43 +0200 Subject: Update getForms function to fetch data from API --- src/api/forms.ts | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/api/forms.ts b/src/api/forms.ts index c20a587..724d6b7 100644 --- a/src/api/forms.ts +++ b/src/api/forms.ts @@ -1,4 +1,5 @@ import { Question, QuestionType } from "./question" +import ApiClient from "./client"; export enum FormFeatures { Discoverable = "DISCOVERABLE", @@ -16,27 +17,9 @@ export interface Form { description: string } -export function getForms(): Form[] { - return [ - { - title: "Ban Appeals", - id: "ban-appeals", - description: "Appealing bans from the Discord server", - open: true - }, - { - title: "Insights 2020", - id: "insights-2020", - description: "Insights about the Python Discord community", - open: false - }, - { - title: "Code Jam 2099 Sign Ups", - id: "code-jam-2099-sign-up", - description: "Signing up for Python Discord's millionth code jam!", - open: false - } - ] +export async function getForms(): Promise { + const resp = await ApiClient.get("forms/discoverable"); + return resp.data; } export function getForm(id: string): Promise { -- cgit v1.2.3 From 42782aa26d9f87d0d6a1967d8bc4caf5d7a5ea2d Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 10:51:51 +0200 Subject: Update FormListing component to match with new forms interface --- src/components/FormListing.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/FormListing.tsx b/src/components/FormListing.tsx index 2493608..c53cf67 100644 --- a/src/components/FormListing.tsx +++ b/src/components/FormListing.tsx @@ -9,15 +9,15 @@ import Tag from "./Tag"; import colors from "../colors"; -import { AllFormsForm } from "../api/forms"; +import { Form, FormFeatures } from "../api/forms"; interface FormListingProps { - form: AllFormsForm + form: Form } function FormListing({ form }: FormListingProps) { const listingStyle = css` - background-color: ${form.open ? colors.success : colors.darkButNotBlack}; + background-color: ${form.features.includes(FormFeatures.Open) ? colors.success : colors.darkButNotBlack}; width: 60%; padding: 20px; margin-top: 20px; @@ -39,13 +39,13 @@ function FormListing({ form }: FormListingProps) { let closedTag; - if (!form.open) { + if (!form.features.includes(FormFeatures.Open)) { closedTag = }; return
-

{closedTag}{form.title}

+

{closedTag}{form.name}

{form.description}

-- cgit v1.2.3 From ba72b3c5f4c44d45a5eeaf5212b1ec50db747968 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 10:52:14 +0200 Subject: Update LandingPage to use forms from API --- src/pages/LandingPage.tsx | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/pages/LandingPage.tsx b/src/pages/LandingPage.tsx index 2e2bfd6..127f166 100644 --- a/src/pages/LandingPage.tsx +++ b/src/pages/LandingPage.tsx @@ -1,13 +1,28 @@ /** @jsx jsx */ import { css, jsx } from "@emotion/core"; +import { useEffect, useState } from "react"; import HeaderBar from "../components/HeaderBar"; import FormListing from "../components/FormListing"; -import { getForms } from "../api/forms"; +import { getForms, Form } from "../api/forms"; import OAuth2Button from "../components/OAuth2Button"; +import Loading from "../components/Loading"; function LandingPage() { + const [forms, setForms] = useState(); + + useEffect(() => { + const fetchForms = async () => { + setForms(await getForms()); + } + fetchForms(); + }); + + if (!forms) { + return ; + } + return
@@ -22,7 +37,7 @@ function LandingPage() { - {getForms().map(form => ( + {forms.map(form => ( ))}
-- cgit v1.2.3 From a43fa25ffb3c32a58f6619423bb33eb64c7d2d45 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 13:49:14 +0200 Subject: Update tests to match with changes in discovery --- src/tests/api/forms.test.ts | 6 +----- src/tests/components/FormListing.test.tsx | 31 ++++++++++++++++++++++++------- src/tests/pages/LandingPage.test.tsx | 21 +++++++++++++++++++++ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/src/tests/api/forms.test.ts b/src/tests/api/forms.test.ts index 7c851a7..6e63965 100644 --- a/src/tests/api/forms.test.ts +++ b/src/tests/api/forms.test.ts @@ -1,11 +1,7 @@ import { getForm, getForms } from "../../api/forms"; -test('fetch a list of all forms', () => { - expect(getForms()).toBeInstanceOf(Array); -}); - test('fetch a specific form', () => { - expect(getForm("ban-appeals")).resolves.toHaveProperty("title", "Ban Appeals") + 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 5062a95..0afe10c 100644 --- a/src/tests/components/FormListing.test.tsx +++ b/src/tests/components/FormListing.test.tsx @@ -4,20 +4,37 @@ import '@testing-library/jest-dom/extend-expect'; import FormListing from "../../components/FormListing"; import { BrowserRouter as Router } from 'react-router-dom'; -import { AllFormsForm } from '../../api/forms'; +import { Form, FormFeatures } from '../../api/forms'; +import { QuestionType } from '../../api/question'; -const openFormListing: AllFormsForm = { - title: "Example form listing", +const openFormListing: Form = { + name: "Example form listing", id: "example-form-listing", description: "My form listing", - open: true + features: [FormFeatures.Discoverable, FormFeatures.Open], + questions: [ + { + "id": "my-question", + "name": "My question", + "type": QuestionType.ShortText, + "data": {} + } + ] } -const closedFormListing: AllFormsForm = { - title: "Example form listing", +const closedFormListing: Form = { + name: "Example form listing", id: "example-form-listing", description: "My form listing", - open: false + features: [FormFeatures.Discoverable], + questions: [ + { + "id": "what-should-i-ask", + "name": "What should I ask?", + "type": QuestionType.ShortText, + "data": {} + } + ] } test('renders form listing with specified title', () => { diff --git a/src/tests/pages/LandingPage.test.tsx b/src/tests/pages/LandingPage.test.tsx index ba32bab..23195bd 100644 --- a/src/tests/pages/LandingPage.test.tsx +++ b/src/tests/pages/LandingPage.test.tsx @@ -2,10 +2,31 @@ 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'; + +const testingForm: forms.Form = { + "id": "testing-form", + "name": "Testing Form", + "description": "Meant for testing", + "features": [forms.FormFeatures.Discoverable], + "questions": [ + { + "id": "my-question", + "name": "My Question", + "type": QuestionType.ShortText, + "data": {} + } + ] +} 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]); const { getByText } = render(); // If we rendered the headerbar we rendered the landing page. let headerBar = getByText(/Python Discord Forms/); -- cgit v1.2.3 From 0ef1dee81c44df8e7d37f446c0d5385e2aedad03 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 21:15:42 +0200 Subject: Add BACKEND_URL env variable for build --- webpack.config.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/webpack.config.js b/webpack.config.js index babea35..d2bf5aa 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -88,7 +88,8 @@ module.exports = (env) => { REACT_APP_SHA: "development", REACT_APP_SENTRY_DSN: "https://false@notreal.ingest.sentry.io/1234", REACT_APP_BRANCH: "development", - REACT_APP_OAUTH2_CLIENT_ID: "0" + REACT_APP_OAUTH2_CLIENT_ID: "0", + BACKEND_URL: "https://forms-api.pythondiscord.com/" }), new HtmlWebpackPlugin({ inject: true, -- cgit v1.2.3 From 41dc7ef649227673fa0015a1acd923d3be33d470 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Mon, 14 Dec 2020 21:17:10 +0200 Subject: Simplify Axios client baseURL definition Co-authored-by: Joe Banks --- src/api/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/client.ts b/src/api/client.ts index 6d1491a..32c1993 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -2,5 +2,5 @@ import axios from "axios"; export default axios.create({ - baseURL: process.env.BACKEND_URL || "https://forms-api.pythondiscord.com/" + baseURL: process.env.BACKEND_URL }) -- cgit v1.2.3