Skip to content

Commit

Permalink
Release/3.0.4
Browse files Browse the repository at this point in the history
  • Loading branch information
bryan-robitaille authored May 5, 2023
2 parents e9358eb + 4da0eff commit 805fcd1
Show file tree
Hide file tree
Showing 25 changed files with 219 additions and 262 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [3.0.4] 2023-05-05

### Fixed

- Expanding question inputs in form builder
- Language toggle not appearing on first page visit

## [3.0.3] 2023-05-03

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.0.3
3.0.4
2 changes: 1 addition & 1 deletion components/form-builder/app/SetResponseDelivery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ export const SetResponseDelivery = () => {
{t("settingsResponseDelivery.selectClassification")}
</p>
<p className="inline-block mb-5 p-3 bg-purple-200 font-bold text-sm">
{t("beforePublishMessage")}
{t("settingsResponseDelivery.beforePublishMessage")}
</p>
<select
disabled={isPublished}
Expand Down
22 changes: 13 additions & 9 deletions components/form-builder/app/edit/Edit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,15 +95,19 @@ export const Edit = () => {
<label htmlFor="formTitle" className="visually-hidden" {...getLocalizationAttribute()}>
{t("formTitle")}
</label>
<ExpandingInput
id="formTitle"
ref={titleInput}
placeholder={t("placeHolderFormTitle")}
value={value}
onChange={updateValue}
onBlur={updateName}
{...getLocalizationAttribute()}
/>
<div className="mb-4 my-2">
<ExpandingInput
id="formTitle"
wrapperClassName="w-full laptop:w-3/4 mt-2 laptop:mt-0 font-bold laptop:text-3xl"
className="font-bold laptop:text-3xl"
ref={titleInput}
placeholder={t("placeHolderFormTitle")}
value={value}
onChange={updateValue}
onBlur={updateName}
{...getLocalizationAttribute()}
/>
</div>
<p className="text-sm mb-4">{t("startFormIntro")}</p>
</>
}
Expand Down
4 changes: 2 additions & 2 deletions components/form-builder/app/edit/RefsContext.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { createContext, useContext, useRef, RefObject } from "react";

interface RefsContextType {
refs?: RefObject<HTMLInputElement[]> | undefined;
refs?: RefObject<HTMLTextAreaElement[]> | undefined;
}

const RefsContext = createContext<RefsContextType>({});

export function RefsProvider({ children }: { children: React.ReactNode }) {
const refs = useRef<HTMLInputElement[]>([]);
const refs = useRef<HTMLTextAreaElement[]>([]);

return <RefsContext.Provider value={{ refs }}>{children}</RefsContext.Provider>;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useState } from "react";
import { useTranslation } from "next-i18next";
import debounce from "lodash.debounce";

import { Input } from "@formbuilder/app/shared";
import { ExpandingInput } from "@formbuilder/app/shared";
import { Language } from "@formbuilder/types";
import { useTemplateStore } from "@formbuilder/store";
import { useRefsContext } from "@formbuilder/app/edit/RefsContext";
Expand All @@ -24,7 +24,7 @@ export const QuestionInput = ({
const [value, setValue] = useState(initialValue);

const { refs } = useRefsContext();
const getRef = (element: HTMLInputElement) => {
const getRef = (element: HTMLTextAreaElement) => {
if (!refs || !refs.current || !element || !id) {
return;
}
Expand Down Expand Up @@ -73,17 +73,17 @@ export const QuestionInput = ({
);

return (
<Input
<ExpandingInput
ref={getRef}
type="text"
id={`item-${id}`}
name={`item${index}`}
placeholder={t("question")}
className="w-full"
wrapperClassName="w-full font-bold text-base"
className="font-bold text-base"
value={value}
describedBy={describedById ?? undefined}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => updateValue(index, e.target.value)}
theme="title"
onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => updateValue(index, e.target.value)}
{...getLocalizationAttribute()}
/>
);
Expand Down
8 changes: 6 additions & 2 deletions components/form-builder/app/shared/ExpandingInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ interface Props {
id: string;
name?: string;
type?: string;
wrapperClassName?: string;
className?: string;
placeholder?: string;
describedBy?: string;
value: string | number;
Expand All @@ -29,18 +31,20 @@ const ExpandingInput = React.forwardRef<Ref, Props>((props, ref) => {
isInvalid = false,
lang,
onBlur,
wrapperClassName,
className,
} = props;

return (
<div
className="input-sizer stacked w-full laptop:w-3/4 mt-2 laptop:mt-0 mb-4 my-2 "
className={`input-sizer stacked border-solid border-black border-b-1.5 ${wrapperClassName}`}
data-value={value}
>
<textarea
rows={1}
maxLength={2000}
id={id}
className="text-base font-bold border-b-1.5 border-black-default border-solid focus:bg-gray-default focus:outline-0 !font-sans"
className={` focus:bg-gray-default focus:outline-0 !font-sans ${className} overflow-y-visible`}
name={name}
aria-describedby={describedBy}
aria-invalid={isInvalid ? true : false}
Expand Down
6 changes: 2 additions & 4 deletions components/form-builder/app/translate/Translate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,10 @@ export const Translate = () => {
<LanguageLabel id="form-title-en-language" lang={primaryLanguage}>
<>{t(primaryLanguage)}</>
</LanguageLabel>
<input
<textarea
className="w-full p-4 h-full focus:outline-blue-focus"
id="form-title-en"
aria-describedby="form-title-en-language"
type="text"
value={form[localizeField(LocalizedFormProperties.TITLE, primaryLanguage)]}
onChange={(e) => {
updateField(
Expand All @@ -157,11 +156,10 @@ export const Translate = () => {
<LanguageLabel id="form-title-fr-language" lang={secondaryLanguage}>
<>{t(secondaryLanguage)}</>
</LanguageLabel>
<input
<textarea
className="w-full p-4 h-full focus:outline-blue-focus"
id="form-title-fr"
aria-describedby="form-title-fr-language"
type="text"
value={form[localizeField(LocalizedFormProperties.TITLE, secondaryLanguage)]}
onChange={(e) => {
updateField(
Expand Down
15 changes: 3 additions & 12 deletions components/globals/LanguageToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,16 @@
import React, { useEffect, useRef } from "react";
import React from "react";
import { useTranslation } from "next-i18next";
import { useRouter } from "next/router";
import { StyledLink } from "./StyledLink/StyledLink";

const LanguageToggle = () => {
const { t, i18n } = useTranslation("common");
const locale = i18n.language;
const loading = useRef(true);
const { isReady, asPath } = useRouter();

useEffect(() => {
if (isReady) {
loading.current = false;
}
}, [isReady]);

if (loading.current) return null;
const { pathname } = useRouter();

return (
<StyledLink
href={asPath}
href={pathname}
className="text-base text-right"
locale={locale === "en" ? "fr" : "en"}
ariaLabel={`${t("lang-toggle")}: ${locale == "en" ? "Français" : "English"}`}
Expand Down
36 changes: 9 additions & 27 deletions cypress/e2e/form-builder/add-elements.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ describe("Test FormBuilder Add Elements", () => {
cy.get('[data-testid="textField"]').click();
cy.get("button").contains("Select block").click();

cy.get('[id="item-1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Question");
cy.get('[id="item-1"]').should("have.attr", "placeholder", "Question");

cy.get(".example-text").should("contain", "Short answer");
});
Expand All @@ -54,9 +52,7 @@ describe("Test FormBuilder Add Elements", () => {
cy.get('[data-testid="textArea"]').click();
cy.get("button").contains("Select block").click();

cy.get('[id="item-1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Question");
cy.get('[id="item-1"]').should("have.attr", "placeholder", "Question");

cy.get(".example-text").should("contain", "Long answer text");
});
Expand All @@ -68,9 +64,7 @@ describe("Test FormBuilder Add Elements", () => {
cy.get('[data-testid="radio"]').click();
cy.get("button").contains("Select block").click();

cy.get('[id="item-1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Question");
cy.get('[id="item-1"]').should("have.attr", "placeholder", "Question");

cy.get('[id="option--1--1"]')
.should("have.attr", "type", "text")
Expand All @@ -86,13 +80,9 @@ describe("Test FormBuilder Add Elements", () => {
cy.get('[data-testid="checkbox"]').click();
cy.get("button").contains("Select block").click();

cy.get('[id="item-1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Question");
cy.get('[id="item-1"]').should("have.attr", "placeholder", "Question");

cy.get('[id="option--1--1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Option 1");
cy.get('[id="option--1--1"]').should("have.attr", "placeholder", "Option 1");

cy.get(".example-text").should("contain", "Multiple choice");
});
Expand All @@ -104,13 +94,9 @@ describe("Test FormBuilder Add Elements", () => {
cy.get('[data-testid="dropdown"]').click();
cy.get("button").contains("Select block").click();

cy.get('[id="item-1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Question");
cy.get('[id="item-1"]').should("have.attr", "placeholder", "Question");

cy.get('[id="option--1--1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Option 1");
cy.get('[id="option--1--1"]').should("have.attr", "placeholder", "Option 1");

cy.get(".example-text").should("contain", "Dropdown");
});
Expand All @@ -122,9 +108,7 @@ describe("Test FormBuilder Add Elements", () => {
cy.get('[data-testid="date"]').click();
cy.get("button").contains("Select block").click();

cy.get('[id="item-1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Question");
cy.get('[id="item-1"]').should("have.attr", "placeholder", "Question");

cy.get('[data-testid="description-text"]').should(
"contain",
Expand All @@ -140,9 +124,7 @@ describe("Test FormBuilder Add Elements", () => {
cy.get('[data-testid="number"]').click();
cy.get("button").contains("Select block").click();

cy.get('[id="item-1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Question");
cy.get('[id="item-1"]').should("have.attr", "placeholder", "Question");

cy.get('[data-testid="description-text"]').should("contain", "Only enter numbers");
cy.get('[data-testid="number"]').should("contain", "0123456789");
Expand Down
6 changes: 2 additions & 4 deletions cypress/e2e/form-builder/autocomplete.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,14 @@ describe("Test FormBuilder autocomplete props", () => {
});

autocompleteOptions.forEach((option) => {
it(`Adds a TextInput with ${option[0]} autocomplete`, () => {
it(`Adds a TextAreaInput with ${option[0]} autocomplete`, () => {
cy.visit("/form-builder/edit");
cy.get("button").contains("Add").click();

cy.get('[data-testid="textField"]').click();
cy.get("button").contains("Select block").click();

cy.get('[id="item-1"]')
.should("have.attr", "type", "text")
.should("have.attr", "placeholder", "Question");
cy.get('[id="item-1"]').should("have.attr", "placeholder", "Question");

cy.get(".example-text").should("contain", "Short answer");

Expand Down
2 changes: 1 addition & 1 deletion lib/middleware/cors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const cors = ({
return { next: true };
} catch (e) {
logMessage.error(e as Error);
res.status(500).json({ error: "Malformed API Request" });
res.status(400).json({ error: "Malformed API Request" });
return { next: false };
}
};
Expand Down
31 changes: 13 additions & 18 deletions lib/middleware/csrfProtected.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,22 @@ import { getCsrfToken } from "next-auth/react";

export const csrfProtected = (protectedMethods: string[]): MiddlewareRequest => {
return async (req: NextApiRequest, res: NextApiResponse): Promise<MiddlewareReturn> => {
try {
if (isProtected(req, protectedMethods)) {
// Need to remove body from NextApiRequest due to Next-Auth bug
// Next-Auth sets the method Call based on if a Body is present on the request.
// This causes issues with CSRF protection so only required arguments are passed.
const clonedReq = { body: undefined, headers: req.headers };
if (isProtected(req, protectedMethods)) {
// Need to remove body from NextApiRequest due to Next-Auth bug
// Next-Auth sets the method Call based on if a Body is present on the request.
// This causes issues with CSRF protection so only required arguments are passed.
const clonedReq = { body: undefined, headers: req.headers };

const csrfToken = await getCsrfToken({ req: clonedReq });
if (csrfToken && csrfToken === req.headers["x-csrf-token"]) {
return { next: true };
} else {
res.status(403).json({ error: "Access Denied" });
return { next: false };
}
} else {
//allow unrestricted method
const csrfToken = await getCsrfToken({ req: clonedReq }).catch(() => null);
if (csrfToken && csrfToken === req.headers["x-csrf-token"]) {
return { next: true };
} else {
res.status(403).json({ error: "Access Denied" });
return { next: false };
}
} catch (error) {
res.status(500).json({ error: "Malformed API Request" });
return { next: false };
} else {
//allow unrestricted method
return { next: true };
}
};
};
Expand Down
Loading

0 comments on commit 805fcd1

Please sign in to comment.