Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Val -> Prod #139765

Merged
merged 29 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0e8e6af
update architecture diagram
braxex Aug 30, 2024
3dbba17
Ensure Section 2 tables populate for admins (#139757)
gmrabian Sep 6, 2024
a7d6486
Update datagrid patterns (#139760)
gmrabian Sep 9, 2024
e70e079
Pull previous year value for 3c fields (#139761)
gmrabian Sep 9, 2024
5ceb795
Adding destroy action notification for slack (#139759)
dwhitestratiform Sep 10, 2024
26eed16
[CMDCT-3976] <11 Print View Fix (#139751)
ntsummers1 Sep 12, 2024
302182a
Main -> Val (#139764)
ntsummers1 Sep 17, 2024
0805577
BUGFIG: Remove parseInt() for previous year value to allow non-number…
gmrabian Sep 18, 2024
80c6ccd
Bugfix: Section 3c Part 5 Question 2 (#139768)
ntsummers1 Sep 19, 2024
ff74b23
fix admin print section bug (#139766)
britt-mo Sep 19, 2024
36af6a0
Main -> Val (#139769)
ntsummers1 Sep 20, 2024
eadb715
update macfc security hub github action (#139770)
gmrabian Sep 20, 2024
679cc36
Upgrade vite version for snyk (#139772)
gmrabian Sep 20, 2024
9d2ff75
e2e bug: add wait after submitting (#139773)
gmrabian Sep 23, 2024
56ef3e3
Wrap synthesize value calls in useEffect (#139774)
gmrabian Sep 24, 2024
f4cbb13
Revert "Wrap synthesize value calls in useEffect" (#139776)
ntsummers1 Sep 24, 2024
598cf7b
Rollback to Arch Diagram (#139777)
ntsummers1 Sep 24, 2024
0dd1f6b
Revert "Rollback to Arch Diagram (#139777)" (#139779)
ntsummers1 Sep 24, 2024
03ba3d7
Rollback to before rework (#139781)
ntsummers1 Sep 25, 2024
ed88eb2
Revert "Rollback to before rework" (#139782)
ntsummers1 Sep 25, 2024
cbcafe6
Create base for new 2024 template (#139754)
ntsummers1 Sep 27, 2024
8501f12
Main -> Val (#139783)
ntsummers1 Sep 27, 2024
78fc5c4
Redux: put functions formerly in mapState back in useSelector (#139784)
gmrabian Oct 2, 2024
84b04d5
Revert "Redux: put functions formerly in mapState back in useSelector…
gmrabian Oct 2, 2024
77b91b2
Remove section 1's question 9 accidental carryover (#139787)
ntsummers1 Oct 2, 2024
9e14b58
Main -> Val (#139789)
ntsummers1 Oct 2, 2024
5eaaa1d
update aws-sdk dependencies (#139790)
gmrabian Oct 3, 2024
9ad04ff
Fix typo and upload 2024 template (#139794)
bangbay-bluetiger Oct 9, 2024
18c4a91
Main -> Val (#139795)
ntsummers1 Oct 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .github/workflows/destroy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,18 @@ jobs:
inputs: '{ "topics": "mgmt.connect.cms-carts-seds.carts-bigmac-streams-${{env.BRANCH_NAME}}.config,mgmt.connect.cms-carts-seds.carts-bigmac-streams-${{env.BRANCH_NAME}}.offsets,mgmt.connect.cms-carts-seds.carts-bigmac-streams-${{env.BRANCH_NAME}}.status"}'
ref: refs/heads/master # Otherwise workflow-dispatch tries to operate off of our default name
- name: Destroy
run: ./run destroy --stage $STAGE_PREFIX$branch_name --verify false
run: ./run destroy --stage $STAGE_PREFIX$branch_name --verify false

# Notify the integrations channel when a destroy action fails
notify_on_destroy_failure:
runs-on: ubuntu-latest
needs:
- destroy
if: ${{ failure() }}
steps:
- name: Slack Notification
uses: rtCamp/action-slack-notify@v2
env:
SLACK_TITLE: ":boom: A destroy action has failed on ${{ github.repository }}."
MSG_MINIMAL: true
SLACK_WEBHOOK: ${{ secrets.INTEGRATIONS_SLACK_WEBHOOK }}
2 changes: 1 addition & 1 deletion .images/architecture.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions services/app-api/libs/validation/backend-section.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ export const sectionSchema = {
hint: {
type: "string",
},
mask: {
type: "string",
},
questions: {
type: "array",
items: {
Expand Down
14,633 changes: 3,693 additions & 10,940 deletions services/database/data/seed-local/seed-section.json

Large diffs are not rendered by default.

19 changes: 6 additions & 13 deletions services/ui-src/src/components/fields/DataGrid.jsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import PropTypes from "prop-types";
import Question from "./Question";
import { connect, useDispatch } from "react-redux";
import { ADD_TO_TOTAL, FINISH_CALCULATION } from "../../store/lastYearTotals";

const DataGrid = ({ question, lastYearFormData }) => {
const DataGrid = ({ question, printView }) => {
const [renderQuestions, setRenderQuestions] = useState([]);
const [questionsToSet, setQuestionsToSet] = useState([]);
const lastYearFormData = useSelector((state) => state.lastYearFormData);
const dispatch = useDispatch();

const rowStyle =
Expand Down Expand Up @@ -138,6 +139,7 @@ const DataGrid = ({ question, lastYearFormData }) => {
hideNumber={question.type !== "fieldset"}
question={question.question}
prevYear={question.prevYear}
printView={printView}
/>
</div>
);
Expand All @@ -148,16 +150,7 @@ const DataGrid = ({ question, lastYearFormData }) => {

DataGrid.propTypes = {
question: PropTypes.object.isRequired,
year: PropTypes.number.isRequired,
state: PropTypes.string.isRequired,
lastYearFormData: PropTypes.object.isRequired,
printView: PropTypes.bool,
};

const mapStateToProps = (state) => ({
year: state.formData[0].contents.section.year,
state: state.formData[0].contents.section.state,
lastYearFormData: state.lastYearFormData,
lastYearTotals: state.lastYearTotals,
});

export default connect(mapStateToProps)(DataGrid);
export default DataGrid;
86 changes: 66 additions & 20 deletions services/ui-src/src/components/fields/Integer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,54 @@ import { TextField } from "@cmsgov/design-system";
import { useSelector } from "react-redux";
import { generateQuestionNumber } from "../utils/helperFunctions";

const Integer = ({ onChange, question, prevYear, ...props }) => {
const getPrevYearValue = (question, lastYearFormData) => {
let prevYearValue;

// Split and create array from id
const splitID = question.id.split("-");

// the subquestion id (a, b, c, etc)
const questionId = splitID[5];

// Custom handling for -03-c-05 and -03-c-06
if (
splitID[1] === "03" &&
splitID[2] === "c" &&
(splitID[3] === "05" || splitID[3] === "06") &&
questionId === "a" &&
parseInt(splitID[4]) > 2 &&
parseInt(splitID[4]) < 10
) {
// Set year to last year
splitID[0] = parseInt(splitID[0]) - 1;
splitID.pop();

const fieldsetId = splitID.join("-");
const partIndex = parseInt(splitID[3]) - 1;

// Get questions from last years JSON
const questions =
lastYearFormData[3].contents.section.subsections[2].parts[partIndex]
.questions;

// Filter down to this question
const matchingQuestion = questions.filter(
(question) => fieldsetId === question?.fieldset_info?.id
);

// The first will always be correct
if (matchingQuestion[0]) {
prevYearValue = parseInt(matchingQuestion[0].questions[0].answer?.entry);
}
}
return prevYearValue;
};

const Integer = ({ onChange, question, prevYear, printView, ...props }) => {
const [error, setError] = useState(false);
const [answer, setAnswer] = useState(question.answer.entry);
const lastYearTotals = useSelector((state) => state.lastYearTotals);
const prevYearNumber =
lastYearTotals[question.id.substring(0, question.id.length - 2)];
const lastYearFormData = useSelector((state) => state.lastYearFormData);

const change = ({ target: { name, value } }) => {
const stripped = value.replace(/[^0-9]+/g, "");
const parsed = parseFloat(stripped);
Expand All @@ -25,22 +67,26 @@ const Integer = ({ onChange, question, prevYear, ...props }) => {
}
};

if (prevYearNumber && question.id.indexOf("-a") > -1) {
const isLessThanElevenMask = (value) => {
return (
<TextField
className="ds-c-input"
errorMessage={error}
label={`${generateQuestionNumber(question.id)} ${question.label}`}
hint={question.hint}
name={question.id}
numeric
onChange={change}
value={prevYearNumber}
{...props}
/>
printView &&
question.mask === "lessThanEleven" &&
value <= 10 &&
value > 0
);
}
const renderAnswer = (val) => (val || Number.isInteger(val) ? val : ""); // may attempt to rerender string on page load, so both val || isInteger
};

const renderAnswer = () => {
if (answer === null) {
const value =
getPrevYearValue(question, lastYearFormData) ?? prevYear?.value;
if (isLessThanElevenMask(value)) return "<11";
return value;
} else {
if (isLessThanElevenMask(answer)) return "<11";
return answer || Number.isInteger(answer) ? answer : "";
}
};
return (
<TextField
className="ds-c-input"
Expand All @@ -50,7 +96,7 @@ const Integer = ({ onChange, question, prevYear, ...props }) => {
name={question.id}
numeric
onChange={change}
value={answer != null ? renderAnswer(answer) : prevYear && prevYear.value}
value={renderAnswer()}
{...props}
/>
);
Expand All @@ -59,7 +105,7 @@ Integer.propTypes = {
onChange: PropTypes.func.isRequired,
question: PropTypes.object.isRequired,
prevYear: PropTypes.object,
printView: PropTypes.bool,
};

export { Integer };
export default Integer;
105 changes: 101 additions & 4 deletions services/ui-src/src/components/fields/Integer.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,48 @@ import Integer from "./Integer";
import { screen, render, fireEvent } from "@testing-library/react";

const mockStore = configureMockStore();
const store = mockStore({ lastYearTotals: { 2022: [] } });
const lastYearFormData = [
{},
{},
{},
{
contents: {
section: {
subsections: [
{},
{},
{
parts: [
{},
{},
{},
{},
{
questions: [
{
fieldset_info: {
id: "2022-03-c-05-03",
},
questions: [{ answer: { entry: 3000 } }],
},
],
},
],
},
],
},
},
},
];
const store = mockStore({ lastYearTotals: { 2022: [] }, lastYearFormData });
const buildInteger = (intProps) => {
return (
<Provider store={store}>
<Integer onChange={() => {}} {...intProps} />
</Provider>
);
};

describe("<Integer />", () => {
it("should render correctly", () => {
const props = { question: { id: "2023-00-a-01-01", answer: 1 } };
Expand All @@ -29,7 +63,7 @@ describe("<Integer />", () => {
const props = {
question: {
id: "2023-00-a-01-01",
label: "How many lightbulbs does it take to change a man?",
label: "Example Question",
answer: { entry: 123 },
},
};
Expand All @@ -45,7 +79,7 @@ describe("<Integer />", () => {
const props = {
question: {
id: "2023-00-a-01-01",
label: "How many lightbulbs does it take to change a man?",
label: "Example Question",
answer: { entry: 123 },
},
};
Expand All @@ -61,7 +95,7 @@ describe("<Integer />", () => {
const props = {
question: {
id: "2023-00-a-01-01",
label: "How many lightbulbs does it take to change a man?",
label: "Example Question",
answer: { entry: "hope" },
},
};
Expand All @@ -73,4 +107,67 @@ describe("<Integer />", () => {
expect(screen.queryByDisplayValue("raw text")).not.toBeInTheDocument();
expect(screen.getByRole("alert")).toBeInTheDocument();
});

it("should show <11 if passed >0 and <=10 with printView and lessThanEleven", () => {
const props = {
question: {
id: "2023-00-a-01-01",
label: "Example Question",
answer: { entry: "5" },
mask: "lessThanEleven",
},
printView: true,
};

render(buildInteger(props));
expect(screen.getByDisplayValue("<11")).toBeInTheDocument();
expect(screen.queryByDisplayValue("5")).not.toBeInTheDocument();
});

it("should show original answer if passed >=11 with printView and lessThanEleven mask", () => {
const props = {
question: {
id: "2023-00-a-01-01",
label: "Example Question",
answer: { entry: "12" },
mask: "lessThanEleven",
},
printView: true,
};

render(buildInteger(props));
expect(screen.getByDisplayValue("12")).toBeInTheDocument();
});

it("should show original answer if passed 0 with printView and lessThanEleven mask", () => {
const props = {
question: {
id: "2023-00-a-01-01",
label: "Example Question",
answer: { entry: "0" },
mask: "lessThanEleven",
},
printView: true,
};

render(buildInteger(props));
expect(screen.getByDisplayValue("0")).toBeInTheDocument();
});

it("should render previous year value for appropriate 3c part 5 or 6 questions", () => {
const props = {
question: {
id: "2023-03-c-05-03-a",
label: "How much?",
answer: { entry: null },
},
};

render(buildInteger(props));

expect(screen.getByDisplayValue("3000")).toBeInTheDocument();
const input = screen.getByRole("textbox");
fireEvent.change(input, { target: { value: 234 } });
expect(screen.getByDisplayValue("234")).toBeInTheDocument();
});
});
2 changes: 1 addition & 1 deletion services/ui-src/src/components/fields/Money.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import PropTypes from "prop-types";
import { Integer } from "./Integer";
import Integer from "./Integer";

const Money = ({ ...props }) => {
return <Integer {...props} inputMode="currency" mask="currency" />;
Expand Down
6 changes: 3 additions & 3 deletions services/ui-src/src/components/fields/Objective.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import { AccordionButton, AccordionPanel } from "@reach/accordion";

import Question from "./Question";

const Objective = ({ headerRef, objective, objectiveNumber }) => {
const Objective = ({ headerRef, objective, objectiveNumber, printView }) => {
const first = objective.questions[0].answer.readonly === true;
const name = first
? objective.questions[0].answer.default_entry
: objective.questions[0].answer.entry;

const children = first ? objective.questions.slice(1) : objective.questions;

return (
<>
<div className="accordion-header" ref={headerRef}>
Expand All @@ -27,7 +26,7 @@ const Objective = ({ headerRef, objective, objectiveNumber }) => {
<AccordionPanel>
{children.map((q) => (
<div className="ds-c-choice__checkedChild">
<Question key={q.id} question={q} />
<Question key={q.id} question={q} printView={printView} />
</div>
))}
</AccordionPanel>
Expand All @@ -38,6 +37,7 @@ Objective.propTypes = {
headerRef: PropTypes.func.isRequired,
objective: PropTypes.object.isRequired,
objectiveNumber: PropTypes.number.isRequired,
printView: PropTypes.bool,
};

export { Objective };
Expand Down
Loading