Skip to content

Commit

Permalink
Merge branch 'master' of github.com:IBM/carbon-addons-iot-react into …
Browse files Browse the repository at this point in the history
…filter-tags
  • Loading branch information
davidicus committed Aug 19, 2020
2 parents d45ff28 + ba657a2 commit 92aa34f
Show file tree
Hide file tree
Showing 19 changed files with 5,551 additions and 4,267 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@
},
"dependencies": {
"@babel/runtime": "^7.10.2",
"@carbon/charts": "^0.34.9",
"@carbon/charts-react": "^0.34.9",
"@carbon/charts": "^0.34.10",
"@carbon/charts-react": "^0.34.10",
"@carbon/colors": "10.8.0",
"@carbon/icons-react": "10.11.0",
"@carbon/layout": "10.7.1",
Expand Down
1 change: 1 addition & 0 deletions src/components/BarChartCard/BarChartCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ const BarChartCard = ({
top: {
enabled: zoomBar.enabled,
initialZoomDomain: zoomBar.initialZoomDomain,
type: zoomBar.view || 'slider_view', // default to slider view
},
},
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/BarChartCard/BarChartCard.story.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ storiesOf('Watson IoT/BarChartCard', module)
zoomBar: {
enabled: true,
axes: 'top',
// initialZoomDomain: []
view: select('view', ['slider_view', 'graph_view'], 'slider_view'),
},
})}
values={barChartData.timestamps}
Expand Down
2 changes: 2 additions & 0 deletions src/components/Card/Card.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ const Card = props => {
id,
tooltip,
timeRange,
timeRangeOptions,
onCardAction,
availableActions,
breakpoint,
Expand Down Expand Up @@ -293,6 +294,7 @@ const Card = props => {
isEditable={isEditable}
isExpanded={isExpanded}
timeRange={timeRange}
timeRangeOptions={timeRangeOptions}
onCardAction={cachedOnCardAction}
/>
) : null;
Expand Down
34 changes: 32 additions & 2 deletions src/components/Card/Card.story.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
import { text, select, boolean } from '@storybook/addon-knobs';
import { text, select, boolean, object } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';

import { CARD_SIZES } from '../../constants/LayoutConstants';
Expand Down Expand Up @@ -69,7 +69,6 @@ storiesOf('Watson IoT/Card', module)
</div>
);
})

.add('basic with render prop', () => {
const size = select('size', Object.keys(CARD_SIZES), CARD_SIZES.MEDIUM);
return (
Expand Down Expand Up @@ -134,6 +133,37 @@ storiesOf('Watson IoT/Card', module)
</div>
);
})
.add('with custom range selector', () => {
const size = select('size', Object.keys(CARD_SIZES), CARD_SIZES.MEDIUM);
return (
<div style={{ width: `${getCardMinSize('lg', size).x}px`, margin: 20 }}>
<Card
title={text('title', 'Card Title')}
id="facilitycard-with-loading"
size={size}
isLoading={boolean('isLoading', false)}
isEmpty={boolean('isEmpty', false)}
isEditable={boolean('isEditable', false)}
isExpanded={boolean('isExpanded', false)}
breakpoint="lg"
onCardAction={action('onCardAction')}
availableActions={{
range: true,
}}
timeRangeOptions={object('timeRangeOptions', {
last8Hours: 'Last 8 Hours',
last4Hours: 'Last 4 Hours',
last2Hours: 'Last 2 Hours',
lastHour: 'Last Hour',
this8Hours: 'This 8 Hours',
this4Hours: 'This 4 Hours',
this2Hours: 'This 2 Hours',
thisHour: 'This Hour',
})}
/>
</div>
);
})
.add('is editable', () => {
const size = select('size', Object.keys(CARD_SIZES), CARD_SIZES.MEDIUM);
return (
Expand Down
50 changes: 19 additions & 31 deletions src/components/Card/CardRangePicker.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,18 @@ import { ToolbarItem, OverflowMenu, OverflowMenuItem } from 'carbon-components-r
import classnames from 'classnames';
import isNil from 'lodash/isNil';

import { TimeRangeOptionsPropTypes } from '../../constants/CardPropTypes';
import { settings } from '../../constants/Settings';

const { iotPrefix } = settings;

export const CardRangePickerPropTypes = {
/** Optional range to pass at the card level */
timeRange: PropTypes.oneOf([
'last24Hours',
'last7Days',
'lastMonth',
'lastQuarter',
'lastYear',
'thisWeek',
'thisMonth',
'thisQuarter',
'thisYear',
'',
]),
/** Optional selected range to pass at the card level */
timeRange: PropTypes.string,
/** Generates the available time range selection options. Each option should include 'this' or 'last'.
* i.e. { thisWeek: 'This week', lastWeek: 'Last week'}
*/
timeRangeOptions: TimeRangeOptionsPropTypes, // eslint-disable-line react/require-default-props
/** callback to handle interactions with the range picker */
onCardAction: PropTypes.func.isRequired,
/** set of internationalized labels */
Expand All @@ -37,20 +31,14 @@ const defaultProps = {
cardWidth: undefined,
};

const CardRangePicker = ({ i18n, timeRange: timeRangeProp, onCardAction, cardWidth }) => {
const CardRangePicker = ({
i18n,
timeRange: timeRangeProp,
timeRangeOptions,
onCardAction,
cardWidth,
}) => {
const [timeRange, setTimeRange] = useState(timeRangeProp);
// maps the timebox internal label to a translated string
const timeBoxLabels = {
last24Hours: i18n.last24HoursLabel,
last7Days: i18n.last7DaysLabel,
lastMonth: i18n.lastMonthLabel,
lastQuarter: i18n.lastQuarterLabel,
lastYear: i18n.lastYearLabel,
thisWeek: i18n.thisWeekLabel,
thisMonth: i18n.thisMonthLabel,
thisQuarter: i18n.thisQuarterLabel,
thisYear: i18n.thisYearLabel,
};

const handleTimeRange = useCallback(
value => {
Expand All @@ -65,7 +53,7 @@ const CardRangePicker = ({ i18n, timeRange: timeRangeProp, onCardAction, cardWid
<ToolbarItem>
{cardWidth > 400 ? (
<div id="timeRange" className={`${iotPrefix}--card--toolbar-timerange-label`}>
{timeBoxLabels[timeRange] || i18n.defaultLabel}
{timeRangeOptions[timeRange] || i18n.defaultLabel}
</div>
) : null}

Expand All @@ -87,27 +75,27 @@ const CardRangePicker = ({ i18n, timeRange: timeRangeProp, onCardAction, cardWid
})}
primaryFocus
/>
{Object.keys(timeBoxLabels)
{Object.keys(timeRangeOptions)
.filter(i => i.includes('last'))
.map((i, index) => (
<OverflowMenuItem
key={i}
hasDivider={index === 0}
onClick={() => handleTimeRange(i)}
itemText={timeBoxLabels[i]}
itemText={timeRangeOptions[i]}
className={classnames({
[`${iotPrefix}--card--overflow-menuitem-active`]: timeRange === i,
})}
/>
))}
{Object.keys(timeBoxLabels)
{Object.keys(timeRangeOptions)
.filter(i => i.includes('this'))
.map((i, index) => (
<OverflowMenuItem
key={i}
hasDivider={index === 0}
onClick={() => handleTimeRange(i)}
itemText={timeBoxLabels[i]}
itemText={timeRangeOptions[i]}
className={classnames({
[`${iotPrefix}--card--overflow-menuitem-active`]: timeRange === i,
})}
Expand Down
52 changes: 52 additions & 0 deletions src/components/Card/CardRangePicker.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ describe('CardRangePicker', () => {
const last24HoursLabel = 'Last 24 Hours';
const thisWeekLabel = 'This week';

const defaultTimeRangeOptions = {
last24Hours: last24HoursLabel,
last7Days: 'Last 7 days',
lastMonth: 'Last month',
lastQuarter: 'Last quarter',
lastYear: 'Last year',
thisWeek: thisWeekLabel,
thisMonth: 'This month',
thisQuarter: 'This quarter',
thisYear: 'This year',
};

it('card editable actions', async () => {
render(
<CardRangePicker
Expand All @@ -25,6 +37,7 @@ describe('CardRangePicker', () => {
last24HoursLabel,
thisWeekLabel,
}}
timeRangeOptions={defaultTimeRangeOptions}
onCardAction={mockOnCardAction}
/>
);
Expand Down Expand Up @@ -64,6 +77,7 @@ describe('CardRangePicker', () => {
onCardAction={mockOnCardAction}
cardWidth={500}
timeRange="thisWeek"
timeRangeOptions={defaultTimeRangeOptions}
/>
);
expect(wrapper.find(`.${iotPrefix}--card--toolbar-timerange-label`)).toHaveLength(1);
Expand All @@ -76,8 +90,46 @@ describe('CardRangePicker', () => {
onCardAction={mockOnCardAction}
cardWidth={229}
timeRange="thisWeek"
timeRangeOptions={defaultTimeRangeOptions}
/>
);
expect(wrapper2.find(`.${iotPrefix}--card--toolbar-timerange-label`)).toHaveLength(0);
});

it('should show custom time range options', async () => {
const last2hoursLabel = 'Last 2 Hours';
const customTimeRangeOptions = {
last8Hours: 'Last 8 Hours',
last4Hours: 'Last 4 Hours',
last2Hours: last2hoursLabel,
lastHour: 'Last Hour',
this8Hours: 'This 8 Hours',
this4Hours: 'This 4 Hours',
this2Hours: 'This 2 Hours',
thisHour: 'This Hour',
};

render(
<CardRangePicker
i18n={{
selectTimeRangeLabel,
defaultLabel,
last24HoursLabel,
thisWeekLabel,
}}
timeRangeOptions={customTimeRangeOptions}
onCardAction={mockOnCardAction}
/>
);

// first click the CardRangePicker
fireEvent.click(screen.getAllByTitle(selectTimeRangeLabel)[0]);
// then find the options
const last2hours = await screen.findByText(last2hoursLabel);
fireEvent.click(last2hours);
expect(mockOnCardAction).toHaveBeenCalledWith(CARD_ACTIONS.CHANGE_TIME_RANGE, {
range: 'last2Hours',
});
mockOnCardAction.mockClear();
});
});
42 changes: 41 additions & 1 deletion src/components/Card/CardToolbar.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import React, { useMemo } from 'react';
import PropTypes from 'prop-types';
import omit from 'lodash/omit';
import { Close16, Popup16 } from '@carbon/icons-react';
import { OverflowMenu, OverflowMenuItem, Button } from 'carbon-components-react';
import classnames from 'classnames';

import { settings } from '../../constants/Settings';
import { TimeRangeOptionsPropTypes } from '../../constants/CardPropTypes';
import { CARD_ACTIONS } from '../../constants/LayoutConstants';

import CardRangePicker, { CardRangePickerPropTypes } from './CardRangePicker';
Expand Down Expand Up @@ -35,22 +36,60 @@ const propTypes = {
isExpanded: PropTypes.bool,
className: PropTypes.string,
...omit(CardRangePickerPropTypes, 'onClose'),
/** Generates the available time range selection options. Each option should include 'this' or 'last'.
* i.e. { thisWeek: 'This week', lastWeek: 'Last week'}
*/
timeRangeOptions: TimeRangeOptionsPropTypes, // eslint-disable-line react/require-default-props
};

const defaultProps = {
isEditable: false,
isExpanded: false,
className: null,
timeRangeOptions: null,
};

const CardToolbar = ({
i18n,
width,
isEditable,
isExpanded,
availableActions,
timeRange,
timeRangeOptions: timeRangeOptionsProp,
onCardAction,
className,
}) => {
// maps the timebox internal label to a translated string
// Need the default here in case that the CardToolbar is used by multiple different components
// Also needs to reassign itself if i18n changes
const timeRangeOptions = useMemo(
() =>
timeRangeOptionsProp || {
last24Hours: i18n.last24HoursLabel,
last7Days: i18n.last7DaysLabel,
lastMonth: i18n.lastMonthLabel,
lastQuarter: i18n.lastQuarterLabel,
lastYear: i18n.lastYearLabel,
thisWeek: i18n.thisWeekLabel,
thisMonth: i18n.thisMonthLabel,
thisQuarter: i18n.thisQuarterLabel,
thisYear: i18n.thisYearLabel,
},
[
i18n.last24HoursLabel,
i18n.last7DaysLabel,
i18n.lastMonthLabel,
i18n.lastQuarterLabel,
i18n.lastYearLabel,
i18n.thisMonthLabel,
i18n.thisQuarterLabel,
i18n.thisWeekLabel,
i18n.thisYearLabel,
timeRangeOptionsProp,
]
);

return isEditable ? (
<div className={classnames(className, `${iotPrefix}--card--toolbar`)}>
{(availableActions.edit || availableActions.clone || availableActions.delete) && (
Expand Down Expand Up @@ -91,6 +130,7 @@ const CardToolbar = ({
width={width}
i18n={i18n}
timeRange={timeRange}
timeRangeOptions={timeRangeOptions}
onCardAction={onCardAction}
cardWidth={width}
/>
Expand Down
Loading

0 comments on commit 92aa34f

Please sign in to comment.