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

fix: improves form timer (old) #4340

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c54961d
Adds check to use group option for form timer
thiessenp-cds Sep 26, 2024
5ad2e08
Merge branch 'develop' into fix/4252
thiessenp-cds Oct 3, 2024
39f2257
Updates Form element count to use group history
thiessenp-cds Oct 3, 2024
f6ee848
Updates a comment
thiessenp-cds Oct 3, 2024
6c4e876
Moves questions calculation into SubmitButton
thiessenp-cds Oct 3, 2024
56e8b63
Adds a temporary log message to make testing easier
thiessenp-cds Oct 7, 2024
fbcfd2d
Merge branch 'develop' into fix/4252
thiessenp-cds Oct 7, 2024
cbca535
Merge branch 'develop' into fix/4252
thiessenp-cds Oct 7, 2024
9b22579
Merge branch 'develop' into fix/4252
thiessenp-cds Oct 7, 2024
aa38193
Merge branch 'develop' into fix/4252
thiessenp-cds Oct 7, 2024
f4f82b9
Merge branch 'develop' into fix/4252
thiessenp-cds Oct 8, 2024
8d2d783
Updates to add a unit test part 1
thiessenp-cds Oct 8, 2024
ad71e6d
Updates from PR 2
thiessenp-cds Oct 8, 2024
8e8aad7
Updates from PR 3
thiessenp-cds Oct 8, 2024
28b4e2d
Updates from PR 4
thiessenp-cds Oct 8, 2024
52f7f8a
Merge branch 'develop' into fix/4252
thiessenp-cds Oct 9, 2024
0d48737
Adds form timer functions to the formContext
thiessenp-cds Oct 9, 2024
ea619c3
Removes debug buttons so tests can pass
thiessenp-cds Oct 10, 2024
d30e59e
Fixes build error
thiessenp-cds Oct 10, 2024
a23f32c
Add a form start timer and updates calculation
thiessenp-cds Oct 10, 2024
42c38ec
Adds some unit tests
thiessenp-cds Oct 11, 2024
aff528b
Updates to differentiate between forms with and without groups
thiessenp-cds Oct 11, 2024
60829ed
Updates comments
thiessenp-cds Oct 11, 2024
686d4af
Adds a wrapper function for convenience
thiessenp-cds Oct 15, 2024
1e064c1
Merge branch 'develop' into fix/4252
thiessenp-cds Oct 15, 2024
5f079f7
Simplifies delay functions
thiessenp-cds Oct 15, 2024
044c087
Updates how groups are checked
thiessenp-cds Oct 15, 2024
aeaf36b
Updates how groups are checked
thiessenp-cds Oct 15, 2024
fb707f3
Adds a ticket number to todos
thiessenp-cds Oct 15, 2024
2e00a03
Updates from PR
thiessenp-cds Oct 15, 2024
b52682f
Updates from PR comments
thiessenp-cds Oct 15, 2024
a41af0d
Merge branch 'main' into fix/4252
thiessenp-cds Oct 15, 2024
72a57ae
Updates coments
thiessenp-cds Oct 16, 2024
ff135a3
Merge branch 'main' into fix/4252
thiessenp-cds Oct 16, 2024
8e63cdd
Merge branch 'main' into fix/4252
thiessenp-cds Oct 16, 2024
b915887
Merge branch 'main' into fix/4252
bryan-robitaille Oct 17, 2024
ebaad21
Updates default delay to no countdown delay
thiessenp-cds Oct 18, 2024
302fa25
Updates another function to default to no delay
thiessenp-cds Oct 18, 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
75 changes: 63 additions & 12 deletions components/clientComponents/forms/Form/Form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { submitForm } from "app/(gcforms)/[locale]/(form filler)/id/[...props]/a
import useFormTimer from "@lib/hooks/useFormTimer";
import { useFormValuesChanged } from "@lib/hooks/useValueChanged";
import { useGCFormsContext } from "@lib/hooks/useGCFormContext";
import { Review } from "../Review/Review";
import { getReviewItemElements, Review } from "../Review/Review";
import { LockedSections } from "@formBuilder/components/shared/right-panel/treeview/types";
import { BackButton } from "@formBuilder/[id]/preview/BackButton";
import { Language } from "@lib/types/form-builder-types";
Expand All @@ -25,17 +25,17 @@ import {
removeFormContextValues,
getInputHistoryValues,
} from "@lib/utils/form-builder/groupsHistory";
import { filterShownElements, filterValuesByShownElements } from "@lib/formContext";
import { filterShownElements, filterValuesByShownElements, Group } from "@lib/formContext";
import { formHasGroups } from "@lib/utils/form-builder/formHasGroups";
import { showReviewPage } from "@lib/utils/form-builder/showReviewPage";

interface SubmitButtonProps {
numberOfRequiredQuestions: number;
getNumberOfRequiredQuestions: () => number;
formID: string;
formTitle: string;
}
const SubmitButton: React.FC<SubmitButtonProps> = ({
numberOfRequiredQuestions,
getNumberOfRequiredQuestions,
formID,
formTitle,
}) => {
Expand All @@ -44,15 +44,28 @@ const SubmitButton: React.FC<SubmitButtonProps> = ({
const [submitTooEarly, setSubmitTooEarly] = useState(false);
const screenReaderRemainingTime = useRef(formTimerState.remainingTime);

// TODO: may want to consider a maximum delay

// calculate initial delay for submit timer
const secondsBaseDelay = 2;
const secondsPerFormElement = 2;
const submitDelaySeconds = secondsBaseDelay + numberOfRequiredQuestions * secondsPerFormElement;

const formTimerEnabled = process.env.NEXT_PUBLIC_APP_ENV !== "test";

// If the timer hasn't started yet, start the timer
if (!formTimerState.timerDelay && formTimerEnabled) startTimer(submitDelaySeconds);
if (!formTimerState.timerDelay && formTimerEnabled) {
// Calculated here to avoid being called on each checkTimer interval (every second)
const submitDelaySeconds =
thiessenp-cds marked this conversation as resolved.
Show resolved Hide resolved
secondsBaseDelay + getNumberOfRequiredQuestions() * secondsPerFormElement;

// TEMP START: For easier testing, to be removed before merge
thiessenp-cds marked this conversation as resolved.
Show resolved Hide resolved
logMessage.info(
`Submit delay, Number of Required Questions=${getNumberOfRequiredQuestions()}. Total delay=${submitDelaySeconds} seconds`
);
// TEMP END: For easier testing, to be removed before merge

startTimer(submitDelaySeconds);
}

useEffect(() => {
if (!formTimerEnabled && !formTimerState.canSubmit) {
Expand Down Expand Up @@ -155,7 +168,15 @@ const InnerForm: React.FC<InnerFormProps> = (props) => {
const [canFocusOnError, setCanFocusOnError] = useState(false);
const [lastSubmitCount, setLastSubmitCount] = useState(-1);

const { currentGroup, groupsCheck, getGroupTitle } = useGCFormsContext();
const {
currentGroup,
groupsCheck,
getGroupTitle,
matchedIds,
getGroupHistory,
getValues,
groups,
} = useGCFormsContext();
const isGroupsCheck = groupsCheck(props.allowGrouping);
const isShowReviewPage = showReviewPage(form);
const showIntro = isGroupsCheck ? currentGroup === LockedSections.START : true;
Expand Down Expand Up @@ -189,9 +210,39 @@ const InnerForm: React.FC<InnerFormProps> = (props) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [formStatusError, errorList, lastSubmitCount, canFocusOnError]);

const numberOfRequiredQuestions = form.elements.filter(
(element) => element.properties.validation?.required === true
).length;
// Done in a callback to allow calling when the submit button is clicked. Otherwise the block
// below would be called very time the form values change. Similar reason why useMemo is not used.
const getNumberOfRequriedQuestions = () => {
thiessenp-cds marked this conversation as resolved.
Show resolved Hide resolved
const FALLBACK_QUESTIONS_COUNT = 4;
try {
const hasGroups = formHasGroups(form) && props.allowGrouping;
const formValues = getValues() || {};
const groupHistory = getGroupHistory();
const groupHistoryElements = groupHistory
.map((groupId) => {
if (!groups) return [];
const group: Group = groups[groupId as keyof typeof groups] || {};
const reviewElements = getReviewItemElements(
group.elements,
form.elements,
matchedIds,
formValues,
language
);
return reviewElements.map((reviewElement) => reviewElement.element);
})
.flat();

const filterByTheseElements = hasGroups ? groupHistoryElements : form.elements;
return (
filterByTheseElements.filter((element) => element?.properties.validation?.required === true)
.length || FALLBACK_QUESTIONS_COUNT
);
} catch (err) {
// This should never happen
return FALLBACK_QUESTIONS_COUNT;
}
};

return status === "submitting" ? (
<>
Expand Down Expand Up @@ -299,7 +350,7 @@ const InnerForm: React.FC<InnerFormProps> = (props) => {
)}
<div className="inline-block">
<SubmitButton
numberOfRequiredQuestions={numberOfRequiredQuestions}
getNumberOfRequiredQuestions={getNumberOfRequriedQuestions}
formID={formID}
formTitle={form.titleEn}
/>
Expand All @@ -310,7 +361,7 @@ const InnerForm: React.FC<InnerFormProps> = (props) => {
})
) : (
<SubmitButton
numberOfRequiredQuestions={numberOfRequiredQuestions}
getNumberOfRequiredQuestions={getNumberOfRequriedQuestions}
formID={formID}
formTitle={form.titleEn}
/>
Expand Down
3 changes: 2 additions & 1 deletion components/clientComponents/forms/Review/Review.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ function formatElementValues(element: ReviewElement) {
return String(element.values);
}

function getReviewItemElements(
// TODO: move into a helper file?
export function getReviewItemElements(
thiessenp-cds marked this conversation as resolved.
Show resolved Hide resolved
groupElements: string[],
formElements: FormElement[],
matchedIds: string[],
Expand Down
Loading