diff --git a/src/components/DashboardEditor/DashboardEditor.jsx b/src/components/DashboardEditor/DashboardEditor.jsx index cdbc1fe4b3..fc909ab98d 100644 --- a/src/components/DashboardEditor/DashboardEditor.jsx +++ b/src/components/DashboardEditor/DashboardEditor.jsx @@ -21,6 +21,13 @@ const propTypes = { }), /** supported card types */ supportedCardTypes: PropTypes.arrayOf(PropTypes.string), + /** if enabled, renders a ContentSwitcher with IconSwitches that allow for manually changing the breakpoint, + * regardless of the screen width + */ + breakpointSwitcher: PropTypes.shape({ + enabled: PropTypes.bool, + initialValue: PropTypes.string, + }), /** if provided, renders header content above preview */ renderHeader: PropTypes.func, /** if provided, is used to render cards in dashboard */ @@ -62,6 +69,7 @@ const defaultProps = { layouts: {}, }, supportedCardTypes: [CARD_TYPES.BAR, CARD_TYPES.TIMESERIES, CARD_TYPES.VALUE, CARD_TYPES.TABLE], + breakpointSwitcher: null, renderHeader: null, renderCardPreview: () => null, headerBreadcrumbs: null, @@ -87,17 +95,18 @@ const defaultProps = { }, }; -const BREAKPOINTS = { - TABLET: 1, - LAPTOP: 2, - SCREEN: 3, - FIT_TO_SCREEN: 0, +const LAYOUTS = { + FIT_TO_SCREEN: { breakpoint: 'max', index: 0 }, + TABLET: { breakpoint: 'md', index: 1 }, + LAPTOP: { breakpoint: 'lg', index: 2 }, + SCREEN: { breakpoint: 'xk', index: 3 }, }; const DashboardEditor = ({ title, initialValue, supportedCardTypes, + breakpointSwitcher, renderHeader, renderCardPreview, headerBreadcrumbs, @@ -117,13 +126,22 @@ const DashboardEditor = ({ // show the gallery if no card is being edited const [dashboardJson, setDashboardJson] = useState(initialValue); const [selectedCardId, setSelectedCardId] = useState(); - const [selectedBreakpoint, setSelectedBreakpoint] = useState(BREAKPOINTS.FIT_TO_SCREEN); + const [selectedBreakpointIndex, setSelectedBreakpointIndex] = useState( + breakpointSwitcher?.initialValue + ? LAYOUTS[breakpointSwitcher.initialValue].index + : LAYOUTS.FIT_TO_SCREEN.index + ); + const [currentBreakpoint, setCurrentBreakpoint] = useState( + breakpointSwitcher?.initialValue + ? LAYOUTS[breakpointSwitcher.initialValue].breakpoint + : LAYOUTS.FIT_TO_SCREEN.breakpoint + ); useEffect( () => { window.dispatchEvent(new Event('resize')); }, - [selectedBreakpoint] + [selectedBreakpointIndex] ); const addCard = type => { @@ -167,46 +185,72 @@ const DashboardEditor = ({ onSubmit={onSubmit} i18n={mergedI18N} dashboardJson={dashboardJson} - selectedBreakpoint={selectedBreakpoint} - setSelectedBreakpoint={setSelectedBreakpoint} + selectedBreakpointIndex={selectedBreakpointIndex} + setSelectedBreakpointIndex={setSelectedBreakpointIndex} + breakpointSwitcher={breakpointSwitcher} /> )} {notification} -
- {}} - onLayoutChange={(newLayout, newLayouts) => - setDashboardJson({ - ...dashboardJson, - layouts: newLayouts, - }) - } - className={classNames({ - [`${baseClassName}--preview-tablet`]: selectedBreakpoint === BREAKPOINTS.TABLET, - [`${baseClassName}--preview-laptop`]: selectedBreakpoint === BREAKPOINTS.LAPTOP, - [`${baseClassName}--preview-screen`]: selectedBreakpoint === BREAKPOINTS.SCREEN, - })} - > - {dashboardJson.cards.map(cardData => { - const isSelected = selectedCardId === cardData.id; - const onSelectCard = id => setSelectedCardId(id); - const onDuplicateCard = id => duplicateCard(id); - const onRemoveCard = id => removeCard(id); - - // if function not defined, or it returns falsy, render default preview - return ( - renderCardPreview( - cardData, - isSelected, - onSelectCard, - onDuplicateCard, - onRemoveCard - ) ?? - getCardPreview(cardData, isSelected, onSelectCard, onDuplicateCard, onRemoveCard) - ); - })} - +
+ {breakpointSwitcher?.enabled && ( +
+
+ Edit dashboard layout at medium breakpoint +
+ { + setCurrentBreakpoint(newBreakpoint); + }} + onLayoutChange={(newLayout, newLayouts) => + setDashboardJson({ + ...dashboardJson, + layouts: newLayouts, + }) + } + > + {dashboardJson.cards.map(cardData => { + const isSelected = selectedCardId === cardData.id; + const onSelectCard = id => setSelectedCardId(id); + const onDuplicateCard = id => duplicateCard(id); + const onRemoveCard = id => removeCard(id); + + // if function not defined, or it returns falsy, render default preview + return ( + renderCardPreview( + cardData, + isSelected, + onSelectCard, + onDuplicateCard, + onRemoveCard + ) ?? + getCardPreview( + cardData, + isSelected, + onSelectCard, + onDuplicateCard, + onRemoveCard + ) + ); + })} + +
+ )} + {/*
{JSON.stringify(dashboardData, null, 4)}
*/}
diff --git a/src/components/DashboardEditor/DashboardEditor.story.jsx b/src/components/DashboardEditor/DashboardEditor.story.jsx index 0afbbea731..a0a6adabff 100644 --- a/src/components/DashboardEditor/DashboardEditor.story.jsx +++ b/src/components/DashboardEditor/DashboardEditor.story.jsx @@ -229,6 +229,32 @@ storiesOf('Watson IoT Experimental/DashboardEditor', module) /> )) + .add('with breakpointSwitcher', () => ( +
+ Dashboard library, + Favorites, + ]} + breakpointSwitcher={{ enabled: true }} + /> +
+ )) .add('wrapped in SuiteHeader', () => (
{ const baseClassName = `${iotPrefix}--dashboard-editor-header`; const extraContent = ( @@ -98,15 +108,19 @@ const DashboardEditorHeader = ({ {/* Last updated: XYZ */}
- setSelectedBreakpoint(e.index)} - selectedIndex={selectedBreakpoint} - > - - - - - + {breakpointSwitcher?.enabled && ( + setSelectedBreakpointIndex(e.index)} + selectedIndex={selectedBreakpointIndex} + className={`${baseClassName}--bottom__switcher`} + > + + + + + + )} + {// FileUploaderButton isn't a true button so extra styling is needed to make it look like a iconOnly button onImport && (