diff --git a/eq-author-api/schema/resolvers/base.js b/eq-author-api/schema/resolvers/base.js index b24b6fa186..e12f4b4b58 100644 --- a/eq-author-api/schema/resolvers/base.js +++ b/eq-author-api/schema/resolvers/base.js @@ -1030,7 +1030,7 @@ const Resolvers = { }; }), createList: createMutation(async (root, _, ctx) => { - const list = createList(); + const list = createList(ctx); if (!ctx.questionnaire.collectionLists) { ctx.questionnaire.collectionLists = { id: uuidv4(), diff --git a/eq-author-api/schema/tests/lists.test.js b/eq-author-api/schema/tests/lists.test.js index d87625914c..afa5974da6 100644 --- a/eq-author-api/schema/tests/lists.test.js +++ b/eq-author-api/schema/tests/lists.test.js @@ -38,6 +38,9 @@ describe("Lists", () => { const { lists } = await createList(ctx); expect(lists[0].listName).toBeNull(); expect(ctx.questionnaire.collectionLists.lists.length).toEqual(1); + //TODO: previewQuestions + expect(ctx.questionnaire.introduction.previewQuestions).toBe(false); + expect(ctx.questionnaire.introduction.disallowPreviewQuestions).toBe(true); }); it("Can update a list", async () => { @@ -55,6 +58,9 @@ describe("Lists", () => { expect(ctx.questionnaire.collectionLists.lists.length).toEqual(1); await deleteList(ctx, input); expect(ctx.questionnaire.collectionLists.lists.length).toEqual(0); + //TODO: previewQuestions + expect(ctx.questionnaire.introduction.previewQuestions).toBe(false); + expect(ctx.questionnaire.introduction.disallowPreviewQuestions).toBe(false); }); it("Can add an answer to a list", async () => { diff --git a/eq-author-api/schema/typeDefs.js b/eq-author-api/schema/typeDefs.js index 8a29b26a9a..d7bd6f9f52 100644 --- a/eq-author-api/schema/typeDefs.js +++ b/eq-author-api/schema/typeDefs.js @@ -715,6 +715,7 @@ type QuestionnaireIntroduction { tertiaryTitle: String! tertiaryDescription: String! previewQuestions: Boolean + disallowPreviewQuestions: Boolean questionnaire: Questionnaire validationErrorInfo: ValidationErrorInfo comments: [Comment] diff --git a/eq-author-api/src/businessLogic/createList.js b/eq-author-api/src/businessLogic/createList.js index 37785bd447..105a3aa465 100644 --- a/eq-author-api/src/businessLogic/createList.js +++ b/eq-author-api/src/businessLogic/createList.js @@ -1,9 +1,13 @@ const { v4: uuidv4 } = require("uuid"); -const createList = () => ({ - id: uuidv4(), - listName: null, - answers: [], -}); +const createList = (ctx) => { + ctx.questionnaire.introduction.previewQuestions = false; + ctx.questionnaire.introduction.disallowPreviewQuestions = true; + return { + id: uuidv4(), + listName: null, + answers: [], + }; +}; module.exports = createList; diff --git a/eq-author-api/src/businessLogic/onListDeleted.js b/eq-author-api/src/businessLogic/onListDeleted.js index de976d0e04..e962e1f185 100644 --- a/eq-author-api/src/businessLogic/onListDeleted.js +++ b/eq-author-api/src/businessLogic/onListDeleted.js @@ -22,4 +22,11 @@ module.exports = (ctx, list) => { onAnswerDeleted(ctx, list, answer, pages); }); } + + if ( + ctx.questionnaire.lists === undefined || + ctx.questionnaire.lists.length === 0 + ) { + ctx.questionnaire.introduction.disallowPreviewQuestions = false; + } }; diff --git a/eq-author-api/utils/createQuestionnaireIntroduction.js b/eq-author-api/utils/createQuestionnaireIntroduction.js index cea3f0bbdc..dd3a3f5bfd 100644 --- a/eq-author-api/utils/createQuestionnaireIntroduction.js +++ b/eq-author-api/utils/createQuestionnaireIntroduction.js @@ -26,7 +26,8 @@ module.exports = (metadata) => { "", legalBasis: NOTICE_1, // TODO: previewQuestions - // previewQuestions: true, + previewQuestions: false, + disallowPreviewQuestions: false, secondaryTitle: "

Information you need

", secondaryDescription: "

You can select the dates of the period you are reporting for, if the given dates are not appropriate.

", diff --git a/eq-author/src/App/introduction/Design/IntroductionEditor/CollapsiblesEditor/CollapsibleEditor/index.js b/eq-author/src/App/introduction/Design/IntroductionEditor/CollapsiblesEditor/CollapsibleEditor/index.js index 94ccd85360..c128cf98bb 100644 --- a/eq-author/src/App/introduction/Design/IntroductionEditor/CollapsiblesEditor/CollapsibleEditor/index.js +++ b/eq-author/src/App/introduction/Design/IntroductionEditor/CollapsiblesEditor/CollapsibleEditor/index.js @@ -28,6 +28,7 @@ const Detail = styled.div` position: relative; `; + const DetailHeader = styled.div` position: absolute; top: 0.5em; diff --git a/eq-author/src/App/introduction/Design/IntroductionEditor/__snapshots__/index.test.js.snap b/eq-author/src/App/introduction/Design/IntroductionEditor/__snapshots__/index.test.js.snap index f361879cd6..55e02ee5fd 100644 --- a/eq-author/src/App/introduction/Design/IntroductionEditor/__snapshots__/index.test.js.snap +++ b/eq-author/src/App/introduction/Design/IntroductionEditor/__snapshots__/index.test.js.snap @@ -44,6 +44,7 @@ exports[`IntroductionEditor should render 1`] = ` withoutMargin={true} /> Legal basis - + The legal basis can be changed on the Settings page - + + + + + + + + + + + Each section is represented as a collapsible element, allowing users to show and hide its respective questions. + + + Adding a collection list will automatically turn off and disable this setting. + diff --git a/eq-author/src/App/introduction/Design/IntroductionEditor/index.js b/eq-author/src/App/introduction/Design/IntroductionEditor/index.js index 2ea539e239..94c626a339 100644 --- a/eq-author/src/App/introduction/Design/IntroductionEditor/index.js +++ b/eq-author/src/App/introduction/Design/IntroductionEditor/index.js @@ -12,7 +12,7 @@ import { buildSettingsPath } from "utils/UrlUtils"; import RichTextEditor from "components/RichTextEditor"; import ValidationError from "components/ValidationError"; -import { InformationPanel } from "components/Panel"; + import { Field, Input, Label } from "components/Forms"; import ToggleSwitch from "components/buttons/ToggleSwitch"; import Panel from "components-themed/panels"; @@ -64,6 +64,7 @@ const InlineField = styled(Field)` > * { margin-bottom: 0; } + pointer-events: ${({ disabled }) => (disabled ? "none" : "auto")}; `; const HorizontalSeparator = styled.hr` @@ -102,8 +103,8 @@ const IntroductionEditor = ({ introduction, history }) => { contactDetailsIncludeRuRef, additionalGuidancePanel, additionalGuidancePanelSwitch, - // TODO: previewQuestions - // previewQuestions, + previewQuestions, + disallowPreviewQuestions, secondaryTitle, secondaryDescription, tertiaryTitle, @@ -130,8 +131,6 @@ const IntroductionEditor = ({ introduction, history }) => { }; const params = useParams(); - - // TODO: previewQuestions return ( <> @@ -173,7 +172,10 @@ const IntroductionEditor = ({ introduction, history }) => { testSelector="txt-intro-title" withoutMargin /> - + You can have this page display on the Hub via the  Settings page @@ -345,15 +347,29 @@ const IntroductionEditor = ({ introduction, history }) => { /> Legal basis - + The legal basis can be changed on the Settings page - + - {/*
+ {/* //TODO: previewQuestions */} +
- - + + { checked={previewQuestions} /> - - This displays a link on the introduction page that takes respondents - to a preview of all the questions on one page in a collapsible - format. + + Each section is represented as a collapsible element, allowing users + to show and hide its respective questions. + {previewQuestions ? ( + + Adding a collection list will automatically turn off and disable + this setting. + + ) : disallowPreviewQuestions ? ( + + A link for previewing the questions cannot be provided for + questionnaires that contain list collector question patterns. + + ) : null} -
*/} +
diff --git a/eq-author/src/App/introduction/Design/IntroductionEditor/index.test.js b/eq-author/src/App/introduction/Design/IntroductionEditor/index.test.js index 5a8d4227d0..40c5c0ce65 100644 --- a/eq-author/src/App/introduction/Design/IntroductionEditor/index.test.js +++ b/eq-author/src/App/introduction/Design/IntroductionEditor/index.test.js @@ -30,7 +30,8 @@ describe("IntroductionEditor", () => { contactDetailsEmailSubject: "Change of details", contactDetailsIncludeRuRef: false, additionalGuidancePanelSwitch: false, - previewQuestions: true, + previewQuestions: false, + disallowPreviewQuestions: true, additionalGuidancePanel: "additionalGuidancePanel", description: "description", secondaryTitle: "secondary title", @@ -57,7 +58,16 @@ describe("IntroductionEditor", () => { const { PHONE_NOT_ENTERED, EMAIL_NOT_ENTERED } = introductionErrors; it("should render", () => { - expect(shallow()).toMatchSnapshot(); + const propsWithPreviewQuestions = { + ...props, + introduction: { + ...props.introduction, + previewQuestions: true, + }, + }; + expect( + shallow() + ).toMatchSnapshot(); }); it("should toggle the additional guidance panel", () => { @@ -159,18 +169,80 @@ describe("IntroductionEditor", () => { expect(mockUseMutation).toHaveBeenCalledTimes(3); }); - // TODO: previewQuestions - // it("should toggle preview questions", () => { - // const mockUseMutation = jest.fn(); - // useMutation.mockImplementationOnce(jest.fn(() => [mockUseMutation])); - - // const wrapper = shallow(); - // expect( - // wrapper.find('[name="toggle-preview-questions"]').exists() - // ).toBeTruthy(); - // wrapper - // .find("#toggle-preview-questions") - // .simulate("change", { target: { checked: false } }); - // expect(mockUseMutation).toHaveBeenCalledTimes(1); - // }); + //TODO: previewQuestions; + describe("previewingQuestions", () => { + it("Should render previewQuestions section", () => { + const wrapper = shallow(); + expect(wrapper.find('[name="previewQuestions-section"]')).toBeTruthy(); + }); + + it("Should render previewQuestions toggle in off state", () => { + const wrapper = shallow(); + expect( + wrapper.find('[name="toggle-preview-questions"]').prop("checked") + ).toBe(false); + }); + + it("Should toggle preview questions", () => { + const mockUseMutation = jest.fn(); + useMutation.mockImplementationOnce(jest.fn(() => [mockUseMutation])); + + const wrapper = shallow(); + expect( + wrapper.find('[name="toggle-preview-questions"]').exists() + ).toBeTruthy(); + wrapper + .find("#toggle-preview-questions") + .simulate("change", { target: { checked: false } }); + expect(mockUseMutation).toHaveBeenCalledTimes(1); + }); + + it("Should render the warning panel when previewQuestions is true", () => { + const propsWithPreviewQuestions = { + ...props, + introduction: { + ...props.introduction, + previewQuestions: true, + }, + }; + const wrapper = shallow( + + ); + expect( + wrapper.find('[data-testid="preview-questions-warn-panel"]').exists() + ).toBeTruthy(); + }); + + it("Should render the disallow info panel when disallowPreviewQuestions is true", () => { + const propsWithDisallowPreviewQuestions = { + ...props, + introduction: { + ...props.introduction, + disallowPreviewQuestions: true, + }, + }; + const wrapper = shallow( + + ); + expect( + wrapper.find('[data-testid="preview-questions-info-panel"]').exists() + ).toBeTruthy(); + }); + + it("should not render the warning panel when previewQuestions is false", () => { + const propsWithPreviewQuestions = { + ...props, + introduction: { + ...props.introduction, + previewQuestions: false, + }, + }; + const wrapper = shallow( + + ); + expect( + wrapper.find('[data-testid="preview-questions-warn-panel"]').exists() + ).toBeFalsy(); + }); + }); }); diff --git a/eq-author/src/graphql/fragments/introduction.graphql b/eq-author/src/graphql/fragments/introduction.graphql index ab5bf9dac7..043b3bdee1 100644 --- a/eq-author/src/graphql/fragments/introduction.graphql +++ b/eq-author/src/graphql/fragments/introduction.graphql @@ -14,6 +14,7 @@ fragment Introduction on QuestionnaireIntroduction { secondaryTitle secondaryDescription previewQuestions + disallowPreviewQuestions collapsibles { ...CollapsibleEditor } diff --git a/eq-author/src/graphql/updateQuestionnaireIntroduction.graphql b/eq-author/src/graphql/updateQuestionnaireIntroduction.graphql index be1cecd758..30ae4149fd 100644 --- a/eq-author/src/graphql/updateQuestionnaireIntroduction.graphql +++ b/eq-author/src/graphql/updateQuestionnaireIntroduction.graphql @@ -14,6 +14,7 @@ mutation UpdateQuestionnaireIntroduction( additionalGuidancePanel description previewQuestions + disallowPreviewQuestions secondaryTitle secondaryDescription showOnHub