Skip to content

Commit

Permalink
Feature/deseng657: Implemented language selector in engagement creati…
Browse files Browse the repository at this point in the history
…on wizard (#2560)

* feature/deseng657: Added language picker to engagement creation wizard.

* feature/deseng657: made language selector code more dynamic and other misc fixes as per Nat's review.
  • Loading branch information
jareth-whitney authored Jul 22, 2024
1 parent 085451b commit ce13757
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.MD
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
## July 17, 2024

- **Feature** Admin authoring experience - language selector [🎟️ DESENG-657](https://citz-gdx.atlassian.net/browse/DESENG-657)
- Created loader for engagement creation wizard
- Created language selector field in engagement creation wizard

- **Hotfix** Fix MET-web CI build errors [🎟️ DESENG-665](https://citz-gdx.atlassian.net/browse/DESENG-665)
- Update the `npm install` command in CI for the web app to use `--legacy-peer-deps`, resolving a dependency issue that was causing the build to fail

Expand Down
73 changes: 69 additions & 4 deletions met-web/src/components/engagement/new/create/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from 'react';
import React, { Suspense } from 'react';
import { DetailsContainer, Detail, ResponsiveContainer } from 'components/common/Layout';
import { BodyText, Header1, Header2 } from 'components/common/Typography';
import { Button, TextField } from 'components/common/Input';
import ConfirmModal from 'components/common/Modals/ConfirmModal';
import { Form, useNavigate, useFetcher } from 'react-router-dom';
import { Box, Modal } from '@mui/material';
import { Form, useNavigate, useFetcher, useLoaderData, Await } from 'react-router-dom';
import { Box, Modal, Checkbox, Grid, Skeleton } from '@mui/material';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faInfoCircle, faConstruction } from '@fortawesome/pro-regular-svg-icons';
import { Dayjs } from 'dayjs';
Expand All @@ -14,6 +14,7 @@ import { colors } from 'styles/Theme';
import EngagementVisibilityControl from './EngagementVisibilityControl';
import UnsavedWorkConfirmation from 'components/common/Navigation/UnsavedWorkConfirmation';
import { AutoBreadcrumbs } from 'components/common/Navigation/Breadcrumb';
import { Language } from 'models/language';
import { UserManager } from './UserManager';
import { User } from 'models/user';

Expand Down Expand Up @@ -49,6 +50,7 @@ const EngagementCreationWizard = () => {
const [open, setOpen] = React.useState(true);
const navigate = useNavigate();
const fetcher = useFetcher();
const { languages } = useLoaderData() as { languages: Language[] };

const engagementCreationForm = useForm<EngagementCreationData>({
defaultValues: {
Expand Down Expand Up @@ -85,6 +87,61 @@ const EngagementCreationWizard = () => {
formState: { errors, isDirty, isValid, isSubmitting },
} = engagementCreationForm;

const handleLanguages = (languages: Language[]) => {
const column1: Language[] = [];
const column2: Language[] = [];
const column3: Language[] = [];
const itemsPerColumn = languages.length / 3;
languages.map((language: Language, index: number) => {
if (itemsPerColumn > index) {
column1.push(language);
} else if (itemsPerColumn * 2 > index) {
column2.push(language);
} else {
column3.push(language);
}
});
// If column 1 has more values than column 2, they should be equal in length.
if (column1.length > column2.length) {
column2.push(column3[0]);
column3.splice(0, 1);
}
return (
<Grid container id="all-language-columns" direction="row">
<Grid id="language-column1" columns={12} lg={4} xs={12} direction="column">
{handleLanguageEntries(column1)}
</Grid>
<Grid id="language-column2" columns={12} lg={4} xs={12} direction="column">
{handleLanguageEntries(column2)}
</Grid>
<Grid id="language-column3" columns={12} lg={4} xs={12} direction="column">
{handleLanguageEntries(column3)}
</Grid>
</Grid>
);
};

const handleLanguageEntries = (languages: Language[]) => {
return languages.map((language) => {
const languageWithDirection =
true === language.right_to_left ? language.name.split('').reverse().join('') : language.name;
return (
<>
<span>
<Checkbox
defaultChecked={Boolean('English' === language.name)}
disabled={Boolean('English' === language.name)}
value={language.code}
sx={{ pl: 0 }}
/>
{'English' === language.name ? language.name + ' (Required)' : languageWithDirection}
</span>
<br />
</>
);
});
};

return (
<ResponsiveContainer>
<AutoBreadcrumbs />
Expand Down Expand Up @@ -149,7 +206,15 @@ const EngagementCreationWizard = () => {
All engagements must be offered in English, but you may also add content in additional
languages if you select multi-language.
</BodyText>
{_TemporaryConstructionNotice}
<Suspense
fallback={<Skeleton variant="rectangular" sx={{ width: '100%', height: '288px' }} />}
>
<Await resolve={languages}>
{(languageResponse) => {
return handleLanguages(languageResponse);
}}
</Await>
</Suspense>
</Detail>
<Detail>
<BodyText bold size="large">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { getTenantLanguages } from 'services/languageService';
import { defer } from 'react-router-dom';

export const languageLoader = async () => {
const tenantId = sessionStorage.getItem('tenantId');
const languages = getTenantLanguages(tenantId ?? '').then((response) => response);
return defer({ languages });
};
2 changes: 2 additions & 0 deletions met-web/src/routes/AuthenticatedRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import Language from 'components/language';
import { Tenant } from 'models/tenant';
import { getAllTenants, getTenant } from 'services/tenantService';
import { SurveyLoader } from 'components/survey/building/SurveyLoader';
import { languageLoader } from 'components/engagement/new/create/languageLoader';
import { userSearchLoader } from 'components/userManagement/userSearchLoader';
import EngagementCreationWizard from 'components/engagement/new/create';
import engagementCreateAction from 'components/engagement/new/create/engagementCreateAction';
Expand Down Expand Up @@ -70,6 +71,7 @@ const AuthenticatedRoutes = () => {
path="wizard"
handle={{ crumb: () => ({ name: 'New Engagement' }) }}
element={<EngagementCreationWizard />}
loader={languageLoader}
/>
</Route>
<Route element={<AuthGate allowedRoles={[USER_ROLES.EDIT_ENGAGEMENT]} />}>
Expand Down

0 comments on commit ce13757

Please sign in to comment.