From f08ce873381fca903425c6fe0d8cd7b622d1349d Mon Sep 17 00:00:00 2001 From: Anthony Williams Date: Mon, 4 Jul 2022 20:25:47 +0100 Subject: [PATCH] Add feedback form with FeedbackBlock - Adds a feedback form allowing visitors to enter their name and e-mail, and optionally their company. Data will be submitted to an API (pending). - Adds a Sentiment component which allows visitors to select how they feed about the page. - Moves EmoticonButton into the Sentiment module since it's unlikely to be used elsewhere. Ideally, I think I'd like to lift the calls to `fetch` out to a parent component for both Sentiment and SubscriptionForm, but for now this feels like a nice and simple way of doing what we need. --- README.md | 7 +- frontend/.env.example | 1 + frontend/.eslintrc.json | 6 +- frontend/README.md | 8 +- frontend/components/Buttons/Button.test.js | 6 +- frontend/components/Buttons/HolonButton.js | 19 +- .../FeedbackBlock/ButtonLoadingIcon.js | 73 + .../Sentiment}/EmoticonButton.js | 54 +- .../FeedbackBlock/Sentiment/index.js | 49 + .../FeedbackBlock/Sentiment/index.test.js | 50 + .../FeedbackBlock/SubscriptionForm.js | 154 + .../FeedbackBlock/SubscriptionForm.test.js | 89 + frontend/components/FeedbackBlock/index.js | 16 + frontend/jest.config.js | 2 +- frontend/jest.setup.js | 1 + frontend/package-lock.json | 13830 ---------------- frontend/package.json | 3 + frontend/pages/feedback.js | 18 + frontend/pages/holon-style.js | 2 +- frontend/yarn.lock | 4301 +++++ 20 files changed, 4821 insertions(+), 13868 deletions(-) create mode 100644 frontend/.env.example create mode 100644 frontend/components/FeedbackBlock/ButtonLoadingIcon.js rename frontend/components/{Buttons => FeedbackBlock/Sentiment}/EmoticonButton.js (51%) create mode 100644 frontend/components/FeedbackBlock/Sentiment/index.js create mode 100644 frontend/components/FeedbackBlock/Sentiment/index.test.js create mode 100644 frontend/components/FeedbackBlock/SubscriptionForm.js create mode 100644 frontend/components/FeedbackBlock/SubscriptionForm.test.js create mode 100644 frontend/components/FeedbackBlock/index.js delete mode 100644 frontend/package-lock.json create mode 100644 frontend/pages/feedback.js create mode 100644 frontend/yarn.lock diff --git a/README.md b/README.md index d646d1cc1..81f8c13a3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,12 @@ Prototype of the Holon web application ## First setup / Start the application First copy the .env.example to .env.local. You don't have to change anything inside -the .env file. +the .env file: + +```bash +cp frontend/.env.example frontend/.env.local +cp backend/.env.example backend/.env.local +``` - note: If you decide to make some changes to the .env files, restart the docker containers. diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 000000000..04fe2efd4 --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1 @@ +NEXT_PUBLIC_BACKEND_URL=http://localhost:8000 diff --git a/frontend/.eslintrc.json b/frontend/.eslintrc.json index 7d9c5af0a..247a7b4d9 100755 --- a/frontend/.eslintrc.json +++ b/frontend/.eslintrc.json @@ -1,6 +1,6 @@ { "extends": [ - "next/core-web-vitals", + "next/core-web-vitals", "plugin:react/recommended" ], "parserOptions": { @@ -11,5 +11,7 @@ "sourceType": "module" }, "plugins": ["react"], - "rules": {} + "rules": { + "react/react-in-jsx-scope": "off" + } } diff --git a/frontend/README.md b/frontend/README.md index b12f3e33e..840c99565 100755 --- a/frontend/README.md +++ b/frontend/README.md @@ -2,7 +2,13 @@ This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next ## Getting Started -First, run the development server: +Copy the .env.sample file to .env.local: + +```bash +cp .env.example .env.local +``` + +Next run the development server: ```bash npm run dev diff --git a/frontend/components/Buttons/Button.test.js b/frontend/components/Buttons/Button.test.js index 3d8f6e82d..34f2e5a87 100644 --- a/frontend/components/Buttons/Button.test.js +++ b/frontend/components/Buttons/Button.test.js @@ -88,14 +88,18 @@ describe("Button", () => { }); describe("rendering an Icon outside of a button", () => { + afterAll(jest.restoreAllMocks); + it("throws an error", () => { + jest.spyOn(console, "error").mockImplementation(() => jest.fn()); + expect(() => { render(
Something
); - }).toThrow(/must be used within a Button/); + }).toThrow(); }); }); }); diff --git a/frontend/components/Buttons/HolonButton.js b/frontend/components/Buttons/HolonButton.js index 19a2c595c..ee5a99611 100644 --- a/frontend/components/Buttons/HolonButton.js +++ b/frontend/components/Buttons/HolonButton.js @@ -1,21 +1,22 @@ import React, { createContext, useContext } from "react"; +import PropTypes from "prop-types"; const variants = { darkmode: - "border-white text-white bg-holon-blue-900 shadow-holon-white hover:translate-x-holon-bh-x hover:translate-y-holon-bh-y hover:bg-holon-blue-500 hover:shadow-holon-white-hover", - gold: "bg-holon-gold-200 border-holon-blue-900 shadow-holon-blue hover:translate-x-holon-bh-x hover:translate-y-holon-bh-y hover:bg-holon-gold-600 hover:shadow-holon-blue-hover", - blue: "bg-holon-blue-200 border-holon-blue-900 shadow-holon-blue hover:translate-x-holon-bh-x hover:translate-y-holon-bh-y hover:bg-holon-blue-500 hover:shadow-holon-blue-hover hover:text-white", + "border-white text-white bg-holon-blue-900 shadow-holon-white enabled:hover:bg-holon-blue-500 enabled:active:shadow-holon-white-hover", + gold: "bg-holon-gold-200 border-holon-blue-900 shadow-holon-blue hover:bg-holon-gold-600 active:shadow-holon-blue-hover", + blue: "bg-holon-blue-200 border-holon-blue-900 shadow-holon-blue hover:bg-holon-blue-500 active:shadow-holon-blue-hover hover:text-white", darkblue: - "text-white bg-holon-blue-500 border-holon-blue-900 shadow-holon-blue hover:translate-x-holon-bh-x hover:translate-y-holon-bh-y hover:bg-holon-blue-900 hover:shadow-holon-blue-hover", + "text-white bg-holon-blue-500 border-holon-blue-900 shadow-holon-blue hover:bg-holon-blue-900 active:shadow-holon-blue-hover", }; const ButtonContext = createContext(); -export default function Button({ children, variant = "darkmode", ...rest }) { +export default function Button({ children, className, variant = "darkmode", ...rest }) { const colorClasses = variants[variant] || variants.darkmode; return (