-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature/deseng668: Added authoring side nav and bottom nav, modified …
…routing, added authoring context, added base page for banner (#2581) * Router restructuring for engagement detail tabs * Fixes to links between routes * feature/deseng668: Integrated side nav, bottom nav, context, and base page for authoring section. * feature/deseng668: Revised some routing code after merge, fixed conflicting action names, changed some data fetches. * feature/deseng668: Revised routes and authoring components as per PR comments. * feature/deseng668: Added authoring template and skeletons. * feature/deseng668: Revised for accessibility, made some merge fixes. * feature/deseng668: Added further screen reader support. * feature/deseng668: Set image picker back to original design. --------- Co-authored-by: NatSquared <[email protected]>
- Loading branch information
1 parent
69524c5
commit 9e5a4f8
Showing
29 changed files
with
2,620 additions
and
83 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
313 changes: 313 additions & 0 deletions
313
met-web/src/components/engagement/admin/create/authoring/AuthoringBanner.tsx
Large diffs are not rendered by default.
Oops, something went wrong.
209 changes: 209 additions & 0 deletions
209
met-web/src/components/engagement/admin/create/authoring/AuthoringBottomNav.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
import React from 'react'; | ||
import { AppBar, Theme, ThemeProvider, Box, useMediaQuery, Select, MenuItem, SelectChangeEvent } from '@mui/material'; | ||
import { Palette, colors, DarkTheme, BaseTheme } from 'styles/Theme'; | ||
import { When, Unless } from 'react-if'; | ||
import { BodyText } from 'components/common/Typography'; | ||
import { elevations } from 'components/common'; | ||
import { Button } from 'components/common/Input'; | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||
import { faCheck } from '@fortawesome/pro-regular-svg-icons'; | ||
import { StatusCircle } from '../../view/AuthoringTab'; | ||
import pagePreview from 'assets/images/pagePreview.png'; | ||
import { AuthoringBottomNavProps, LanguageSelectorProps } from './types'; | ||
import { getLanguageValue } from './AuthoringTemplate'; | ||
|
||
const AuthoringBottomNav = ({ | ||
isDirty, | ||
isValid, | ||
isSubmitting, | ||
currentLanguage, | ||
setCurrentLanguage, | ||
languages, | ||
pageTitle, | ||
}: AuthoringBottomNavProps) => { | ||
const isMediumScreenOrLarger = useMediaQuery((theme: Theme) => theme.breakpoints.up('md')); | ||
const padding = { xs: '1rem 1rem', md: '1rem 1.5rem 1rem 2rem', lg: '1rem 3rem 1rem 2rem' }; | ||
|
||
const buttonStyles = { | ||
height: '2.6rem', | ||
borderRadius: '8px', | ||
border: 'none', | ||
padding: '0 1rem', | ||
minWidth: '8.125rem', | ||
fontSize: '0.9rem', | ||
}; | ||
|
||
return ( | ||
<AppBar | ||
component={'nav'} | ||
position="fixed" | ||
sx={{ | ||
backgroundColor: 'transparent', | ||
borderTopRightRadius: '16px', | ||
minHeight: '5rem', | ||
backgroundClip: 'padding-box', | ||
overflow: 'hidden', | ||
top: 'auto', | ||
left: 0, | ||
bottom: 0, | ||
boxShadow: elevations.default, | ||
}} | ||
data-testid="appbar-authoring-bottom-nav" | ||
> | ||
<Box | ||
sx={{ | ||
background: colors.surface.blue[90], | ||
minHeight: '5rem', | ||
justifyContent: 'flex-start', | ||
padding: padding, | ||
display: 'flex', | ||
alignItems: 'center', | ||
flexWrap: isMediumScreenOrLarger ? 'nowrap' : 'wrap', | ||
}} | ||
> | ||
<ThemeProvider theme={DarkTheme}> | ||
<Box | ||
sx={{ | ||
width: '18.8rem', | ||
minWidth: '18.8rem', | ||
marginBottom: isMediumScreenOrLarger ? '0' : '1rem', | ||
}} | ||
> | ||
<BodyText bold>Currently Authoring</BodyText> | ||
<BodyText sx={{ fontSize: '0.7rem', alignItems: 'center', marginTop: '-5px', display: 'flex' }}> | ||
<span>{pageTitle}</span> | ||
<span style={{ fontSize: '0.4rem', paddingLeft: '0.4rem', paddingRight: '0.4rem' }}> | ||
{'\u2B24'} | ||
</span> | ||
{getLanguageValue(currentLanguage, languages)} | ||
</BodyText> | ||
</Box> | ||
<Box | ||
sx={{ | ||
width: '43.75rem', | ||
justifyContent: 'flex-start', | ||
display: 'flex', | ||
}} | ||
> | ||
<ThemeProvider theme={BaseTheme}> | ||
<LanguageSelector | ||
currentLanguage={currentLanguage} | ||
setCurrentLanguage={setCurrentLanguage} | ||
languages={languages} | ||
isDirty={isDirty} | ||
isSubmitting={isSubmitting} | ||
/> | ||
</ThemeProvider> | ||
|
||
<Button | ||
disabled={!isValid || !isDirty || isSubmitting} | ||
type="submit" | ||
name="request_type" | ||
value="update" | ||
sx={{ | ||
...buttonStyles, | ||
margin: '0 1.2rem', | ||
}} | ||
> | ||
Save Section | ||
</Button> | ||
<Button | ||
disabled={!isValid || !isDirty || isSubmitting} | ||
type="submit" | ||
name="request_type" | ||
value="preview" | ||
sx={{ | ||
...buttonStyles, | ||
marginLeft: 'auto', | ||
}} | ||
> | ||
<img | ||
style={{ | ||
paddingRight: '0.3rem', | ||
filter: !isValid || !isDirty || isSubmitting ? 'opacity(40%)' : 'opacity(100%)', | ||
}} | ||
src={pagePreview} | ||
alt="" | ||
aria-hidden="true" | ||
/> | ||
Preview | ||
</Button> | ||
</Box> | ||
<Box style={{ width: '25rem', display: 'flex' }}></Box> | ||
</ThemeProvider> | ||
</Box> | ||
</AppBar> | ||
); | ||
}; | ||
|
||
const LanguageSelector = ({ | ||
currentLanguage, | ||
setCurrentLanguage, | ||
languages, | ||
isDirty, | ||
isSubmitting, | ||
}: LanguageSelectorProps) => { | ||
const handleSelectChange = (event: SelectChangeEvent<string>) => { | ||
const newLanguageCode = event.target.value; | ||
if (isDirty && !isSubmitting) | ||
// todo: Replace this message with our stylized modal message. | ||
window.confirm( | ||
`Are you sure you want to switch to ${ | ||
getLanguageValue(newLanguageCode, languages) || 'another language' | ||
}? You have unsaved changes for the ${ | ||
getLanguageValue(currentLanguage, languages) || 'current' | ||
} language.`, | ||
); | ||
setCurrentLanguage(newLanguageCode); | ||
}; | ||
return ( | ||
<Select | ||
value={currentLanguage} | ||
onChange={handleSelectChange} | ||
sx={{ | ||
height: '2.6rem', | ||
borderRadius: '8px', | ||
width: '9.375rem', | ||
backgroundColor: colors.surface.gray[10], | ||
border: 'none', | ||
color: Palette.text.primary, | ||
fontSize: '0.9rem', | ||
cursor: 'pointer', | ||
'& .MuiSelect-icon': { | ||
color: Palette.text.primary, | ||
}, | ||
}} | ||
renderValue={(value) => { | ||
const completed = false; // todo: Replace with real "completed" boolean value once it is available. | ||
return ( | ||
<span> | ||
<When condition={completed}> | ||
<FontAwesomeIcon style={{ marginRight: '0.3rem' }} icon={faCheck} /> | ||
</When> | ||
{languages.find((language) => language.code === value)?.name} | ||
<Unless condition={completed}> | ||
<StatusCircle required={true} /> | ||
</Unless> | ||
</span> | ||
); | ||
}} | ||
> | ||
{languages.map((language) => { | ||
const completed = false; // todo: Replace with the real "completed" boolean values once they are available. | ||
return ( | ||
<MenuItem value={language.code} key={language.code}> | ||
<When condition={completed}> | ||
<FontAwesomeIcon style={{ marginRight: '0.3rem' }} icon={faCheck} /> | ||
</When> | ||
{language.name} | ||
<Unless condition={completed}> | ||
<StatusCircle required={true} /> | ||
</Unless> | ||
</MenuItem> | ||
); | ||
})} | ||
</Select> | ||
); | ||
}; | ||
|
||
export default AuthoringBottomNav; |
96 changes: 96 additions & 0 deletions
96
met-web/src/components/engagement/admin/create/authoring/AuthoringContext.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import React from 'react'; | ||
import dayjs, { Dayjs } from 'dayjs'; | ||
import { FormProvider, useForm } from 'react-hook-form'; | ||
import { createSearchParams, useFetcher, Outlet } from 'react-router-dom'; | ||
|
||
export interface EngagementUpdateData { | ||
id: number; | ||
status_id: number; | ||
taxon_id: number; | ||
content_id: number; | ||
name: string; | ||
start_date: Dayjs; | ||
end_date: Dayjs; | ||
description: string; | ||
rich_description: string; | ||
banner_filename: string; | ||
status_block: string[]; | ||
title: string; | ||
icon_name: string; | ||
metadata_value: string; | ||
send_report: boolean; | ||
slug: string; | ||
request_type: string; | ||
} | ||
|
||
export const AuthoringContext = () => { | ||
const fetcher = useFetcher(); | ||
const locationArray = window.location.href.split('/'); | ||
const slug = locationArray[locationArray.length - 1]; | ||
const defaultDateValue = dayjs(new Date(1970, 0, 1)); | ||
const engagementUpdateForm = useForm<EngagementUpdateData>({ | ||
defaultValues: { | ||
id: 0, | ||
status_id: 0, | ||
taxon_id: 0, | ||
content_id: 0, | ||
name: '', | ||
start_date: defaultDateValue, | ||
end_date: defaultDateValue, | ||
description: '', | ||
rich_description: '', | ||
banner_filename: '', | ||
status_block: [], | ||
title: '', | ||
icon_name: '', | ||
metadata_value: '', | ||
send_report: undefined, | ||
slug: '', | ||
request_type: '', | ||
}, | ||
mode: 'onSubmit', | ||
reValidateMode: 'onChange', | ||
}); | ||
const onSubmit = async (data: EngagementUpdateData) => { | ||
fetcher.submit( | ||
createSearchParams({ | ||
id: 0 === data.id ? '' : data.id.toString(), | ||
status_id: 0 === data.status_id ? '' : data.status_id.toString(), | ||
taxon_id: 0 === data.taxon_id ? '' : data.taxon_id.toString(), | ||
content_id: 0 === data.content_id ? '' : data.content_id.toString(), | ||
name: data.name, | ||
start_date: | ||
'1970-01-01' === data.start_date.format('YYYY-MM-DD') ? '' : data.start_date.format('YYYY-MM-DD'), | ||
end_date: | ||
'1970-01-01' === data.start_date.format('YYYY-MM-DD') ? '' : data.end_date.format('YYYY-MM-DD'), | ||
description: data.description, | ||
rich_description: data.rich_description, | ||
banner_filename: data.banner_filename, | ||
status_block: data.status_block, | ||
title: data.title, | ||
icon_name: data.icon_name, | ||
metadata_value: data.metadata_value, | ||
send_report: getSendReportValue(data.send_report), | ||
slug: data.slug, | ||
request_type: data.request_type, | ||
}), | ||
{ | ||
method: 'post', | ||
action: `/engagements/${data.id}/details/authoring/${slug}`, | ||
}, | ||
); | ||
}; | ||
|
||
const getSendReportValue = (valueToInterpret: boolean) => { | ||
if (undefined === valueToInterpret) { | ||
return ''; | ||
} | ||
return valueToInterpret ? 'true' : 'false'; | ||
}; | ||
|
||
return ( | ||
<FormProvider {...engagementUpdateForm}> | ||
<Outlet context={{ onSubmit }} /> | ||
</FormProvider> | ||
); | ||
}; |
Oops, something went wrong.