Skip to content

Commit 527f8df

Browse files
IRSA-6571: Cleanup and refactor HydraLanding
IRSA-6571: Cleanup topSection logic in HydraApps Move icon from topSection to bottomSection IRSA-6571: Replace setIfUndefined with defaultsDeep for readability IRSA-6571: Separate defaultProps logic into functions
1 parent 565ba6b commit 527f8df

File tree

2 files changed

+78
-53
lines changed

2 files changed

+78
-53
lines changed

src/firefly/js/templates/fireflyviewer/LandingPage.jsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function LandingPage({slotProps={}, sx, ...props}) {
2424
const defSlotProps = {
2525
tabsMenuHint: {appTitle, id: APP_HINT_IDS.TABS_MENU, hintText: 'Choose a tab to search for or upload data.', sx: { left: '16rem' }},
2626
bgMonitorHint: {appTitle, id: APP_HINT_IDS.BG_MONITOR, hintText: 'Load job results from background monitor', tipPlacement: 'end', sx: { right: 8 }},
27-
topSection: { appTitle },
27+
topSection: { title: `Welcome to ${appTitle}` },
2828
bottomSection: {
2929
icon: <QueryStats sx={{ width: '6rem', height: '6rem' }} />,
3030
text: 'Getting Started',
@@ -57,7 +57,7 @@ export function LandingPage({slotProps={}, sx, ...props}) {
5757
},
5858
}}>
5959
<Stack justifyContent='space-between' width={1} spacing={1}>
60-
<Box display={'flex'} flexGrow={1} {...slotProps?.bgContainer}>
60+
<Box {...slotProps?.bgContainer}>
6161
<Stack spacing={2} width={1} px={4} py={3} {...slotProps?.contentSection}>
6262
<Slot component={DefaultAppBranding} {...defSlotProps.topSection} slotProps={slotProps?.topSection}/>
6363
<Slot component={EmptyResults} {...defSlotProps.bottomSection} slotProps={slotProps?.bottomSection}/>
@@ -71,11 +71,11 @@ export function LandingPage({slotProps={}, sx, ...props}) {
7171
}
7272

7373

74-
function DefaultAppBranding({appTitle, appDescription}) {
74+
function DefaultAppBranding({title, desc}) {
7575
return (
7676
<Stack spacing={.25} alignItems='center'>
77-
<Typography fontSize='xl3' color='neutral'>{`Welcome to ${appTitle}`}</Typography>
78-
{appDescription && <Typography level={'body-md'}>{appDescription}</Typography>}
77+
<Typography fontSize='xl3' color='neutral'>{title}</Typography>
78+
{desc && <Typography level='body-md' textAlign='center'>{desc}</Typography>}
7979
</Stack>
8080
);
8181
}
@@ -201,8 +201,8 @@ LandingPage.propTypes = {
201201

202202

203203
DefaultAppBranding.propTypes = {
204-
appTitle: string,
205-
appDescription: string,
204+
title: string,
205+
desc: string,
206206
};
207207

208208

src/firefly/js/templates/hydra/HydraViewer.jsx

Lines changed: 71 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44

55

66
import React, {useEffect} from 'react';
7-
import PropTypes, {element, node, object, shape, string} from 'prop-types';
7+
import PropTypes, {node, object, shape, string} from 'prop-types';
88
import {Divider, Typography} from '@mui/joy';
9-
import {cloneDeep} from 'lodash/lang.js';
9+
import {cloneDeep, defaultsDeep} from 'lodash';
1010

1111
import {
1212
dispatchSetMenu,
@@ -153,69 +153,94 @@ function closeExpanded() {
153153
dispatchSetLayoutMode(LO_MODE.expanded, LO_VIEW.none);
154154
}
155155

156-
export function HydraLanding({icon, title, desc, bgImage, slotProps={}, ...props} ) {
157-
158-
const Greetings = () => (
159-
<Stacker startDecorator={icon} direction='column' alignItems='start'>
160-
<Typography level='h4'>{title || 'Welcome message here'}</Typography>
161-
<Typography level='body-md'>{desc || 'Additional description of this application'}</Typography>
162-
</Stacker>
163-
);
164-
165-
const mSlotProps = cloneDeep(slotProps || {});
166-
setIfUndefined(mSlotProps,'bgMonitorHint.sx.right', 50);
167-
168-
if (bgImage) {
169-
setIfUndefined(mSlotProps, 'bgContainer', {
170-
// TODO: move it to Landing page?
171-
sx: {backgroundImage: `url(${bgImage})`, backgroundSize: 'cover', backgroundPosition: 'center',},
172-
});
173-
setIfUndefined(mSlotProps, 'contentSection.sx', (theme) => {
156+
const HydraAppBranding = ({title, desc}) => (
157+
<Stacker direction='column' alignItems='start'>
158+
<Typography level='h4'>{title || 'Welcome message here'}</Typography>
159+
<Typography level='body-md'>{desc || 'Additional description of this application'}</Typography>
160+
</Stacker>
161+
);
162+
163+
const defaultCommonProps = ({title, desc}) => ({
164+
bgMonitorHint: { sx: { right: 50 } },
165+
topSection: { title, desc }
166+
});
167+
168+
169+
const defaultPropsWithoutBgImage = ({icon}) => ({
170+
contentSection: { sx: { maxWidth: '80rem', mx: 'auto' } },
171+
topSection: { component: HydraAppBranding }, // use custom topSection instead of DefaultAppBranding
172+
bottomSection: { icon }
173+
});
174+
175+
const defaultPropsWithBgImage = ({bgImage}) => ({
176+
// visually combine topSection & bottomSection into contentSection that can contrast with the bgContainer
177+
bgContainer: {
178+
sx: {
179+
display: 'flex', flexGrow: 1,
180+
backgroundImage: `url(${bgImage})`, backgroundSize: 'cover', backgroundPosition: 'center'
181+
}
182+
},
183+
contentSection: {
184+
sx: (theme) => {
174185
// background image will remain same in both the theme modes, and we need text to contrast with the image,
175-
// so we create a dark overlay and put text over it as if it's dark theme
186+
// so we create a translucent dark overlay and put text over it as if it's dark theme
176187
const darkPalette = theme.colorSchemes.dark.palette;
177188
return {
178189
maxWidth: '56rem', m: 'auto',
179-
backgroundColor: hexColorWithAlpha(darkPalette.background.surface.split(', ')?.[1]?.slice(0,-1) ?? '#000', 0.6),
180-
backdropFilter: 'blur(1px)', // for glass-effect
181-
'.MuiTypography-body-md, .MuiTypography-body-lg' : {color: darkPalette.text.secondary},
182-
'.MuiTypography-h2': {color: darkPalette.text.primary},
183-
'.MuiTypography-colorPrimary': {color: `rgb(${darkPalette.primary.mainChannel})`},
184-
'.MuiDivider-root': {backgroundColor: darkPalette.neutral.solidBg},
190+
backgroundColor: hexColorWithAlpha(darkPalette.background.surface.split(', ')?.[1]?.slice(0, -1) ?? '#000', 0.6),
191+
backdropFilter: 'blur(1px)',
192+
'.MuiTypography-body-md, .MuiTypography-body-lg': { color: darkPalette.text.secondary },
193+
'.MuiTypography-h2': { color: darkPalette.text.primary },
194+
'.MuiTypography-colorPrimary': { color: `rgb(${darkPalette.primary.mainChannel})` },
195+
'.MuiDivider-root': { backgroundColor: darkPalette.neutral.solidBg }
185196
};
186-
});
187-
setIfUndefined(mSlotProps, 'contentSection.divider', (<Divider sx={{width: '4rem', alignSelf: 'center'}}/>));
188-
// TODO: need to adjust top section vs greetings logic
189-
setIfUndefined(mSlotProps, 'topSection.appTitle', title);
190-
setIfUndefined(mSlotProps, 'topSection.appDescription', desc);
191-
setIfUndefined(mSlotProps, 'bottomSection', {icon: false, slotProps: {
192-
root: {sx: {py: 4, pb: 0, backgroundColor: 'transparent'}}
193-
}});
194-
}
195-
else {
196-
setIfUndefined(mSlotProps, 'topSection.component', Greetings); // use custom topSection
197-
setIfUndefined(mSlotProps, 'contentSection.sx', {maxWidth: '80em', mx: 'auto'}); // limit page's width
197+
},
198+
divider: <Divider sx={{ width: '4rem', alignSelf: 'center' }} />
199+
},
200+
bottomSection: {
201+
icon: false, // to prevent default being applied (on undefined)
202+
slotProps: {
203+
root: { sx: { py: 4, pb: 0, backgroundColor: 'transparent' } }
204+
}
198205
}
206+
});
207+
208+
209+
export function HydraLanding({icon, title, desc, bgImage, slotProps={}, ...props} ) {
210+
const mSlotProps = cloneDeep(slotProps);
211+
defaultsDeep(mSlotProps, defaultCommonProps({title, desc}));
212+
213+
bgImage
214+
? defaultsDeep(mSlotProps, defaultPropsWithBgImage({bgImage}))
215+
: defaultsDeep(mSlotProps, defaultPropsWithoutBgImage({icon}));
199216

200217
return <LandingPage slotProps={mSlotProps} {...props}/>;
201218
}
202219

203220
HydraLanding.propTypes = {
204-
icon: element,
221+
icon: node,
205222
title: string,
206223
desc: node,
224+
bgImage: string,
207225
...LandingPage.propTypes,
208226
};
209227

210228

211229
export function applyLayoutFix({slotProps, props}) {
212230
const mSlotProps = cloneDeep(slotProps || {});
231+
defaultsDeep(mSlotProps, {
232+
banner: {
233+
slotProps: {
234+
// Adjust banner for appIcon
235+
icon: {
236+
style: { marginTop: -40 }, // Won't take precedence if defined in sx
237+
sx: { color: 'primary.softActiveColor' } // Same as active tab's font color
238+
},
239+
tabs: { pl: '120px' }
240+
}
241+
},
242+
landing: { title: props?.appTitle }
243+
});
213244

214-
// adjust banner for appIcon
215-
setIfUndefined(mSlotProps,'banner.slotProps.icon.style.marginTop', -40); //won't take precedence if defined in sx
216-
setIfUndefined(mSlotProps,'banner.slotProps.icon.sx', {color: 'primary.softActiveColor'}); //same as active tab's font color
217-
setIfUndefined(mSlotProps,'banner.slotProps.tabs.pl', '120px');
218-
219-
setIfUndefined(mSlotProps,'landing.title', props?.appTitle);
220245
return mSlotProps;
221246
}

0 commit comments

Comments
 (0)