Skip to content

Commit

Permalink
Merge pull request #2552 from bcgov/DESENG-642-survey-data-router-fea…
Browse files Browse the repository at this point in the history
…tures

[To Main] DESENG-642: Survey data router features
  • Loading branch information
NatSquared authored Jul 10, 2024
2 parents 9c158c6 + ebcde44 commit 11a4acc
Show file tree
Hide file tree
Showing 37 changed files with 1,003 additions and 1,322 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## July 9, 2024

- **Task** Add data router features to survey pages [DESENG-642](https://citz-gdx.atlassian.net/browse/DESENG-642)
- Remove "ActionContext" files and fetches to survey service
- Replace with SurveyLoader on the survey parent route that creates survey data promises
- Restructure survey pages to use \<Suspense> / \<Await> for data loading
- Add useBlocker() call to the survey authoring and survey submission pages to prevent users from navigating away from the page while in the middle of creating or submitting a survey

## June 28, 2024
- **Task** Improve screen reader support for home/engagement search page [DESENG-617](https://citz-gdx.atlassian.net/browse/DESENG-617)

Expand Down
12 changes: 8 additions & 4 deletions met-api/src/met_api/resources/email_verification.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class EmailVerification(Resource):
# @TRACER.trace()
@cross_origin(origins=allowedorigins())
def get(token):
"""Fetch a email verification matching the provided token."""
"""Fetch an email verification matching the provided token."""
try:
email_verification = EmailVerificationService().get_active(token)
if email_verification:
Expand All @@ -54,7 +54,7 @@ def get(token):
# @TRACER.trace()
@cross_origin(origins=allowedorigins())
def put(token):
"""Fetch a email verification matching the provided token."""
"""Update an email verification matching the provided token."""
try:
email_verification = EmailVerificationService().verify(token, None, None, None)
if email_verification:
Expand All @@ -69,7 +69,7 @@ def put(token):
@cors_preflight('POST, OPTIONS')
@API.route('/')
class EmailVerifications(Resource):
"""Resource for managing email verifications."""
"""Resource for managing email verifications for survey submissions."""

@staticmethod
# @TRACER.trace()
Expand All @@ -80,6 +80,8 @@ def post():
requestjson = request.get_json()
email_verification = EmailVerificationSchema().load(requestjson)
created_email_verification = EmailVerificationService().create(email_verification)
# don't return the verification token when creating a new email verification
created_email_verification.pop('verification_token')
return created_email_verification, HTTPStatus.OK
except KeyError as err:
return str(err), HTTPStatus.INTERNAL_SERVER_ERROR
Expand All @@ -90,7 +92,7 @@ def post():
@cors_preflight('POST, OPTIONS')
@API.route('/<string:subscription_type>/subscribe')
class SubscribeEmailVerifications(Resource):
"""Resource for managing email verifications."""
"""Resource for managing email verifications for subscriptions."""

@staticmethod
# @TRACER.trace()
Expand All @@ -101,6 +103,8 @@ def post(subscription_type):
requestjson = request.get_json()
email_verification = EmailVerificationSchema().load(requestjson)
created_email_verification = EmailVerificationService().create(email_verification, subscription_type)
# don't return the verification token when creating a new email verification
created_email_verification.pop('verification_token')
return created_email_verification, HTTPStatus.OK
except KeyError as err:
return str(err), HTTPStatus.INTERNAL_SERVER_ERROR
Expand Down
6 changes: 3 additions & 3 deletions met-api/src/met_api/services/email_verification_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ def create(cls, email_verification: EmailVerificationSchema,
email_verification['created_by'] = email_verification.get(
'participant_id')
verification_token = uuid.uuid4()
EmailVerification.create({**email_verification, 'verification_token': verification_token}, session)
email_verification['verification_token'] = verification_token
EmailVerification.create(email_verification, session)

# TODO: remove this once email logic is brought over from submission service to here
if email_verification.get('type', None) != EmailVerificationType.RejectedComment:
cls._send_verification_email(
{**email_verification, 'verification_token': verification_token}, subscription_type)
cls._send_verification_email(email_verification, subscription_type)

return email_verification

Expand Down
1 change: 1 addition & 0 deletions met-web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ const App = () => {
[
{
element: <PublicLayout />,
errorElement: <NotFound />,
children: createRoutesFromElements(UnauthenticatedRoutes()),
},
],
Expand Down
2 changes: 1 addition & 1 deletion met-web/src/components/Form/formio.scss
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ i.fa.fa-question-circle.text-muted {
.nav-link {
text-decoration: none;
}
.active {
.active:not(.MuiLink-root, .MuiPaper-root) {
background-color: #fff;
}
.active-tab {
Expand Down
2 changes: 2 additions & 0 deletions met-web/src/components/common/Input/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { isDarkColor } from 'utils';
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { styled } from '@mui/system';
import { RouterLinkRenderer } from '../Navigation/Link';

const buttonStyles = {
borderRadius: '16px',
Expand Down Expand Up @@ -251,6 +252,7 @@ export const Button = ({
}: ButtonProps & {
variant?: 'primary' | 'secondary' | 'tertiary';
}) => {
props.LinkComponent = props.LinkComponent || RouterLinkRenderer;
switch (variant) {
case 'primary':
return <PrimaryButton {...props} />;
Expand Down
2 changes: 1 addition & 1 deletion met-web/src/components/common/Input/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export type TextFieldProps = {
counter?: boolean;
maxLength?: number;
clearable?: boolean;
onChange: (value: string, name?: string) => void;
onChange?: (value: string, name?: string) => void;
} & Omit<FormFieldProps, 'children' | 'onChange'> &
Omit<TextInputProps, 'fullWidth' | 'error' | 'onChange'>;

Expand Down
1 change: 0 additions & 1 deletion met-web/src/components/common/Typography/Headers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ export const Header1 = ({
marginBottom: '2rem',
marginTop: '1.5rem',
fontWeight: fontWeight(weight),
color: '#292929',
...props.sx,
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export const EngagementHero = () => {
</Grid>
<Button
href={engagement.cta_url || '#cta-section'}
LinkComponent={'a'}
variant="primary"
size="large"
icon={<FontAwesomeIcon fontSize={24} icon={faChevronRight} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { faChevronRight } from '@fortawesome/pro-regular-svg-icons';
import { Switch, Case } from 'react-if';
import { useAppSelector, useAppTranslation } from 'hooks';
import EmailModal from 'components/engagement/view/EmailModal';
import { RouterLinkRenderer } from 'components/common/Navigation/Link';

const gridContainerStyles = {
width: '100%',
Expand Down Expand Up @@ -150,7 +149,6 @@ export const EngagementSurveyBlock = () => {
? `/engagements/${engagement.id}/dashboard/public`
: `/engagements/${engagement.id}/dashboard/public/${language}`
}
LinkComponent={RouterLinkRenderer}
>
{translate('buttonText.viewFeedback')}
</Button>
Expand Down
6 changes: 5 additions & 1 deletion met-web/src/components/engagement/view/EmailPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@ import { INTERNAL_EMAIL_DOMAIN } from 'constants/emailVerification';
import { Editor } from 'react-draft-wysiwyg';
import { getEditorStateFromRaw } from 'components/common/RichTextEditor/utils';
import { Button, CustomTextField } from 'components/common/Input';
import { useAsyncValue } from 'react-router-dom';
import { Engagement } from 'models/engagement';

const EmailPanel = ({ email, checkEmail, handleClose, updateEmail, isSaving, isInternal }: EmailPanelProps) => {
const loadedEngagement = useAsyncValue() as [Engagement] | undefined;
const { savedEngagement } = useContext(ActionContext);
const engagement = loadedEngagement ? loadedEngagement[0] : savedEngagement;
const [checked, setChecked] = useState(false);
const [emailFormError, setEmailFormError] = useState({
terms: false,
Expand Down Expand Up @@ -79,7 +83,7 @@ const EmailPanel = ({ email, checkEmail, handleClose, updateEmail, isSaving, isI
<Grid item xs={12}>
<MetDisclaimer>
<Editor
editorState={getEditorStateFromRaw(savedEngagement.consent_message)}
editorState={getEditorStateFromRaw(engagement.consent_message)}
readOnly={true}
toolbarHidden
/>
Expand Down
33 changes: 33 additions & 0 deletions met-web/src/components/survey/building/SurveyLoader.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Params, defer } from 'react-router-dom';
import { getEmailVerification } from 'services/emailVerificationService';
import { getEngagement } from 'services/engagementService';
import { getEngagementIdBySlug, getSlugByEngagementId } from 'services/engagementSlugService';
import { getSubmissionByToken } from 'services/submissionService';
import { getSurvey } from 'services/surveyService';
import { fetchSurveyReportSettings } from 'services/surveyService/reportSettingsService';

export const SurveyLoader = async ({ params }: { params: Params<string> }) => {
const { surveyId, token, language, engagementId, slug: urlSlug } = params;
if (isNaN(Number(surveyId)) && !isNaN(Number(engagementId)) && !urlSlug) throw new Error('Invalid survey ID');
const verification = getEmailVerification(token ?? '').catch(() => null);
const getSurveyPromise = () => {
if (!isNaN(Number(surveyId))) return getSurvey(Number(surveyId));
if (urlSlug)
return getEngagementIdBySlug(urlSlug ?? '').then((response) =>
getEngagement(response.engagement_id).then((response) => Promise.resolve(response.surveys[0])),
);
return getEngagement(Number(engagementId)).then((response) => Promise.resolve(response.surveys[0]));
};
const survey = getSurveyPromise();

const submission = verification.then(
(response) => response && getSubmissionByToken(response?.verification_token ?? ''),
);
const reportSettings = survey.then((response) => fetchSurveyReportSettings(response.id.toString()));
const engagement = survey.then((response) => {
if (!response.engagement_id) return null;
return getEngagement(response.engagement_id);
});
const slug = engagement.then((response) => response && getSlugByEngagementId(response.id));
return defer({ engagement, language, reportSettings, slug, submission, survey, surveyId, token, verification });
};
Loading

0 comments on commit 11a4acc

Please sign in to comment.