diff --git a/public/locales/en-US.json b/public/locales/en-US.json index 9c78dc71d..17c423ba2 100644 --- a/public/locales/en-US.json +++ b/public/locales/en-US.json @@ -103,6 +103,8 @@ "granularity_weekly": "Weekly", "granularity_monthly": "Monthly", "granularity_quarterly": "Quarterly", + "granularityRange": "{{context}}", + "granularityRange_current": "This month", "slaNone": "No SLA", "slaPremium": "Premium", "slaSelfSupport": "Self-Support", diff --git a/src/common/__tests__/__snapshots__/dateHelpers.test.js.snap b/src/common/__tests__/__snapshots__/dateHelpers.test.js.snap index dd60c1128..45125af93 100644 --- a/src/common/__tests__/__snapshots__/dateHelpers.test.js.snap +++ b/src/common/__tests__/__snapshots__/dateHelpers.test.js.snap @@ -12,6 +12,7 @@ Object { }, "getCurrentDate": [Function], "getRangedDateTime": [Function], + "getRangedMonthDateTime": [Function], "monthlyDateTime": Object { "endDate": 2019-07-01T23:59:59.999Z, "startDate": 2018-07-01T00:00:00.000Z, @@ -20,6 +21,10 @@ Object { "endDate": 2019-07-01T23:59:59.999Z, "startDate": 2016-07-01T00:00:00.000Z, }, + "rangedYearDateTime": Object { + "endDate": 2019-07-31T23:59:59.999Z, + "startDate": 2018-08-01T00:00:00.000Z, + }, "setRangedDateTime": [Function], "timestampDayFormats": Object { "long": "MMMM D", @@ -46,6 +51,333 @@ Object { } `; +exports[`DateHelpers should return a predictable object and list of months based on a year range: get a specific month by name 1`] = ` +Object { + "_title": "april", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"April\\"})", + "value": Object { + "endDate": 2019-04-30T23:59:59.999Z, + "startDate": 2019-04-01T00:00:00.000Z, + }, +} +`; + +exports[`DateHelpers should return a predictable object and list of months based on a year range: get a specific month by number 1`] = ` +Object { + "_title": "march", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"March\\"})", + "value": Object { + "endDate": 2019-03-31T23:59:59.999Z, + "startDate": 2019-03-01T00:00:00.000Z, + }, +} +`; + +exports[`DateHelpers should return a predictable object and list of months based on a year range: getRangedYearDateTime 1`] = ` +Object { + "keyDateTimeRanges": Object { + "1": Object { + "_title": "january", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"January\\"})", + "value": Object { + "endDate": 2019-01-31T23:59:59.999Z, + "startDate": 2019-01-01T00:00:00.000Z, + }, + }, + "10": Object { + "_title": "october", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"October 2018\\"})", + "value": Object { + "endDate": 2018-10-31T23:59:59.999Z, + "startDate": 2018-10-01T00:00:00.000Z, + }, + }, + "11": Object { + "_title": "november", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"November 2018\\"})", + "value": Object { + "endDate": 2018-11-30T23:59:59.999Z, + "startDate": 2018-11-01T00:00:00.000Z, + }, + }, + "12": Object { + "_title": "december", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"December 2018\\"})", + "value": Object { + "endDate": 2018-12-31T23:59:59.999Z, + "startDate": 2018-12-01T00:00:00.000Z, + }, + }, + "2": Object { + "_title": "february", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"February\\"})", + "value": Object { + "endDate": 2019-02-28T23:59:59.999Z, + "startDate": 2019-02-01T00:00:00.000Z, + }, + }, + "3": Object { + "_title": "march", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"March\\"})", + "value": Object { + "endDate": 2019-03-31T23:59:59.999Z, + "startDate": 2019-03-01T00:00:00.000Z, + }, + }, + "4": Object { + "_title": "april", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"April\\"})", + "value": Object { + "endDate": 2019-04-30T23:59:59.999Z, + "startDate": 2019-04-01T00:00:00.000Z, + }, + }, + "5": Object { + "_title": "may", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"May\\"})", + "value": Object { + "endDate": 2019-05-31T23:59:59.999Z, + "startDate": 2019-05-01T00:00:00.000Z, + }, + }, + "6": Object { + "_title": "june", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"June\\"})", + "value": Object { + "endDate": 2019-06-30T23:59:59.999Z, + "startDate": 2019-06-01T00:00:00.000Z, + }, + }, + "7": Object { + "_title": "july", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"July\\"})", + "value": Object { + "endDate": 2019-07-31T23:59:59.999Z, + "startDate": 2019-07-01T00:00:00.000Z, + }, + }, + "8": Object { + "_title": "august", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"August 2018\\"})", + "value": Object { + "endDate": 2018-08-31T23:59:59.999Z, + "startDate": 2018-08-01T00:00:00.000Z, + }, + }, + "9": Object { + "_title": "september", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"September 2018\\"})", + "value": Object { + "endDate": 2018-09-30T23:59:59.999Z, + "startDate": 2018-09-01T00:00:00.000Z, + }, + }, + "april": Object { + "_title": "april", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"April\\"})", + "value": Object { + "endDate": 2019-04-30T23:59:59.999Z, + "startDate": 2019-04-01T00:00:00.000Z, + }, + }, + "august": Object { + "_title": "august", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"August 2018\\"})", + "value": Object { + "endDate": 2018-08-31T23:59:59.999Z, + "startDate": 2018-08-01T00:00:00.000Z, + }, + }, + "current": Object { + "_title": "current", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"current\\"})", + "value": Object { + "endDate": 2019-07-31T23:59:59.999Z, + "startDate": 2019-07-01T00:00:00.000Z, + }, + }, + "december": Object { + "_title": "december", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"December 2018\\"})", + "value": Object { + "endDate": 2018-12-31T23:59:59.999Z, + "startDate": 2018-12-01T00:00:00.000Z, + }, + }, + "february": Object { + "_title": "february", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"February\\"})", + "value": Object { + "endDate": 2019-02-28T23:59:59.999Z, + "startDate": 2019-02-01T00:00:00.000Z, + }, + }, + "january": Object { + "_title": "january", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"January\\"})", + "value": Object { + "endDate": 2019-01-31T23:59:59.999Z, + "startDate": 2019-01-01T00:00:00.000Z, + }, + }, + "july": Object { + "_title": "july", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"July\\"})", + "value": Object { + "endDate": 2019-07-31T23:59:59.999Z, + "startDate": 2019-07-01T00:00:00.000Z, + }, + }, + "june": Object { + "_title": "june", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"June\\"})", + "value": Object { + "endDate": 2019-06-30T23:59:59.999Z, + "startDate": 2019-06-01T00:00:00.000Z, + }, + }, + "march": Object { + "_title": "march", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"March\\"})", + "value": Object { + "endDate": 2019-03-31T23:59:59.999Z, + "startDate": 2019-03-01T00:00:00.000Z, + }, + }, + "may": Object { + "_title": "may", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"May\\"})", + "value": Object { + "endDate": 2019-05-31T23:59:59.999Z, + "startDate": 2019-05-01T00:00:00.000Z, + }, + }, + "november": Object { + "_title": "november", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"November 2018\\"})", + "value": Object { + "endDate": 2018-11-30T23:59:59.999Z, + "startDate": 2018-11-01T00:00:00.000Z, + }, + }, + "october": Object { + "_title": "october", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"October 2018\\"})", + "value": Object { + "endDate": 2018-10-31T23:59:59.999Z, + "startDate": 2018-10-01T00:00:00.000Z, + }, + }, + "september": Object { + "_title": "september", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"September 2018\\"})", + "value": Object { + "endDate": 2018-09-30T23:59:59.999Z, + "startDate": 2018-09-01T00:00:00.000Z, + }, + }, + }, + "listDateTimeRanges": Array [ + Object { + "_title": "current", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"current\\"})", + "value": Object { + "endDate": 2019-07-31T23:59:59.999Z, + "startDate": 2019-07-01T00:00:00.000Z, + }, + }, + Object { + "_title": "june", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"June\\"})", + "value": Object { + "endDate": 2019-06-30T23:59:59.999Z, + "startDate": 2019-06-01T00:00:00.000Z, + }, + }, + Object { + "_title": "may", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"May\\"})", + "value": Object { + "endDate": 2019-05-31T23:59:59.999Z, + "startDate": 2019-05-01T00:00:00.000Z, + }, + }, + Object { + "_title": "april", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"April\\"})", + "value": Object { + "endDate": 2019-04-30T23:59:59.999Z, + "startDate": 2019-04-01T00:00:00.000Z, + }, + }, + Object { + "_title": "march", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"March\\"})", + "value": Object { + "endDate": 2019-03-31T23:59:59.999Z, + "startDate": 2019-03-01T00:00:00.000Z, + }, + }, + Object { + "_title": "february", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"February\\"})", + "value": Object { + "endDate": 2019-02-28T23:59:59.999Z, + "startDate": 2019-02-01T00:00:00.000Z, + }, + }, + Object { + "_title": "january", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"January\\"})", + "value": Object { + "endDate": 2019-01-31T23:59:59.999Z, + "startDate": 2019-01-01T00:00:00.000Z, + }, + }, + Object { + "_title": "december", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"December 2018\\"})", + "value": Object { + "endDate": 2018-12-31T23:59:59.999Z, + "startDate": 2018-12-01T00:00:00.000Z, + }, + }, + Object { + "_title": "november", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"November 2018\\"})", + "value": Object { + "endDate": 2018-11-30T23:59:59.999Z, + "startDate": 2018-11-01T00:00:00.000Z, + }, + }, + Object { + "_title": "october", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"October 2018\\"})", + "value": Object { + "endDate": 2018-10-31T23:59:59.999Z, + "startDate": 2018-10-01T00:00:00.000Z, + }, + }, + Object { + "_title": "september", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"September 2018\\"})", + "value": Object { + "endDate": 2018-09-30T23:59:59.999Z, + "startDate": 2018-09-01T00:00:00.000Z, + }, + }, + Object { + "_title": "august", + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"August 2018\\"})", + "value": Object { + "endDate": 2018-08-31T23:59:59.999Z, + "startDate": 2018-08-01T00:00:00.000Z, + }, + }, + ], +} +`; + exports[`DateHelpers should return a predictable range based on granularity: granularity range of time 1`] = ` Array [ Object { diff --git a/src/common/__tests__/dateHelpers.test.js b/src/common/__tests__/dateHelpers.test.js index 6e89d32ab..0ce3cee2c 100644 --- a/src/common/__tests__/dateHelpers.test.js +++ b/src/common/__tests__/dateHelpers.test.js @@ -1,4 +1,10 @@ -import { dateHelpers, getCurrentDate, setRangedDateTime, getRangedDateTime } from '../dateHelpers'; +import { + dateHelpers, + getCurrentDate, + setRangedDateTime, + getRangedDateTime, + getRangedMonthDateTime +} from '../dateHelpers'; import { RHSM_API_QUERY_GRANULARITY_TYPES as GRANULARITY_TYPES } from '../../types/rhsmApiTypes'; describe('DateHelpers', () => { @@ -18,6 +24,9 @@ describe('DateHelpers', () => { expect(dateHelpers.quarterlyDateTime.startDate.constructor).toBe(Date); expect(dateHelpers.quarterlyDateTime.endDate.constructor).toBe(Date); + + expect(dateHelpers.rangedYearDateTime.startDate.constructor).toBe(Date); + expect(dateHelpers.rangedYearDateTime.endDate.constructor).toBe(Date); }); it('should return a predictable range of time', () => { @@ -38,4 +47,10 @@ describe('DateHelpers', () => { expect(rangesOfDatesTimes).toMatchSnapshot('granularity range of time'); }); + + it('should return a predictable object and list of months based on a year range', () => { + expect(getRangedMonthDateTime()).toMatchSnapshot('getRangedYearDateTime'); + expect(getRangedMonthDateTime('april')).toMatchSnapshot('get a specific month by name'); + expect(getRangedMonthDateTime(3)).toMatchSnapshot('get a specific month by number'); + }); }); diff --git a/src/common/dateHelpers.js b/src/common/dateHelpers.js index 9050acd00..9b74eea89 100644 --- a/src/common/dateHelpers.js +++ b/src/common/dateHelpers.js @@ -1,6 +1,7 @@ import moment from 'moment/moment'; import { helpers } from './helpers'; import { RHSM_API_QUERY_GRANULARITY_TYPES as GRANULARITY_TYPES } from '../types/rhsmApiTypes'; +import { translate } from '../components/i18n/i18n'; /** * Return a date. @@ -17,11 +18,12 @@ const getCurrentDate = () => * @param {Date} params.date Start date, typically the current date. * @param {number} params.subtract Number of granularity type to subtract from the current date. * @param {string} params.measurement Granularity type. + * @param {string} params.endOfMeasurement Granularity type. * @returns {{endDate: Date, startDate: Date}} */ -const setRangedDateTime = ({ date, subtract, measurement }) => ({ +const setRangedDateTime = ({ date, subtract, measurement, endOfMeasurement = 'days' }) => ({ startDate: moment.utc(date).startOf(measurement).subtract(subtract, measurement).toDate(), - endDate: moment.utc(date).startOf(measurement).endOf('days').toDate() + endDate: moment.utc(date).startOf(measurement).endOf(endOfMeasurement).toDate() }); const currentDateTime = setRangedDateTime({ date: getCurrentDate(), subtract: 1, measurement: 'days' }); @@ -29,6 +31,12 @@ const defaultDateTime = setRangedDateTime({ date: getCurrentDate(), subtract: 30 const weeklyDateTime = setRangedDateTime({ date: getCurrentDate(), subtract: 12, measurement: 'weeks' }); const monthlyDateTime = setRangedDateTime({ date: getCurrentDate(), subtract: 12, measurement: 'months' }); const quarterlyDateTime = setRangedDateTime({ date: getCurrentDate(), subtract: 36, measurement: 'months' }); +const rangedYearDateTime = setRangedDateTime({ + date: getCurrentDate(), + subtract: 11, + measurement: 'months', + endOfMeasurement: 'months' +}); /** * Return a range of time based on known granularity types. @@ -52,6 +60,61 @@ const getRangedDateTime = granularity => { } }; +/** + * Generate a list of months for use in a select list. + * + * @param {string} month + * @returns {{keyDateTimeRanges: {}, listDateTimeRanges: *[]}|*} + */ +const getRangedMonthDateTime = month => { + const currentYear = Number.parseInt(moment.utc(getCurrentDate()).year(), 10); + const { startDate, endDate } = { ...rangedYearDateTime }; + const keyDateTimeRanges = {}; + let listDateTimeRanges = []; + + const startDateUpdated = moment.utc(startDate); + const endDateUpdated = moment.utc(endDate); + + while (endDateUpdated > startDateUpdated || startDateUpdated.format('M') === endDateUpdated.format('M')) { + const dateTime = { + value: { + startDate: startDateUpdated.toDate() + } + }; + + const titleYear = startDateUpdated.format('MMMM YYYY'); + const title = startDateUpdated.format('MMMM'); + const titleIndex = startDateUpdated.format('M'); + const isNextYear = currentYear !== Number.parseInt(startDateUpdated.year(), 10); + + dateTime.title = (isNextYear && titleYear) || title; + dateTime._title = title.toLowerCase(); + dateTime.value.endDate = moment.utc(startDateUpdated).endOf('month').toDate(); + + startDateUpdated.add(1, 'month'); + + dateTime.title = translate('curiosity-toolbar.granularityRange', { context: dateTime.title }); + keyDateTimeRanges[title.toLowerCase()] = { ...dateTime }; + keyDateTimeRanges[titleIndex] = { ...dateTime }; + listDateTimeRanges.push(dateTime); + } + + listDateTimeRanges = listDateTimeRanges.reverse(); + listDateTimeRanges[0] = { + ...listDateTimeRanges[0], + _title: 'current', + title: translate('curiosity-toolbar.granularityRange', { context: 'current' }) + }; + + keyDateTimeRanges.current = { ...listDateTimeRanges[0] }; + + if (month) { + return keyDateTimeRanges?.[month] || undefined; + } + + return { keyDateTimeRanges, listDateTimeRanges }; +}; + /** * Consistent timestamp day formats. * @@ -87,6 +150,7 @@ const timestampQuarterFormats = { const dateHelpers = { getCurrentDate, + getRangedMonthDateTime, getRangedDateTime, setRangedDateTime, currentDateTime, @@ -94,6 +158,7 @@ const dateHelpers = { monthlyDateTime, quarterlyDateTime, weeklyDateTime, + rangedYearDateTime, timestampDayFormats, timestampMonthFormats, timestampQuarterFormats @@ -102,6 +167,7 @@ const dateHelpers = { export { dateHelpers as default, getCurrentDate, + getRangedMonthDateTime, getRangedDateTime, setRangedDateTime, currentDateTime, @@ -110,6 +176,7 @@ export { monthlyDateTime, quarterlyDateTime, weeklyDateTime, + rangedYearDateTime, timestampDayFormats, timestampMonthFormats, timestampQuarterFormats diff --git a/src/components/form/__tests__/__snapshots__/select.test.js.snap b/src/components/form/__tests__/__snapshots__/select.test.js.snap index d1f7425bf..cdd7d815c 100644 --- a/src/components/form/__tests__/__snapshots__/select.test.js.snap +++ b/src/components/form/__tests__/__snapshots__/select.test.js.snap @@ -111,6 +111,7 @@ exports[`Select Component should allow being disabled with missing options: no o isGrouped={false} isOpen={false} isPlain={false} + maxHeight={null} menuAppendTo="inline" noResultsFoundText="No results found" onClear={[Function]} @@ -152,6 +153,7 @@ exports[`Select Component should allow being disabled with missing options: opti isGrouped={false} isOpen={false} isPlain={false} + maxHeight={null} menuAppendTo="inline" noResultsFoundText="No results found" onClear={[Function]} @@ -274,6 +276,7 @@ exports[`Select Component should allow being disabled with missing options: opti isGrouped={false} isOpen={false} isPlain={false} + maxHeight={null} menuAppendTo="inline" noResultsFoundText="No results found" onClear={[Function]} @@ -368,6 +371,7 @@ exports[`Select Component should disable toggle text: disabled text 1`] = ` isGrouped={false} isOpen={false} isPlain={false} + maxHeight={null} menuAppendTo="inline" noResultsFoundText="No results found" onClear={[Function]} @@ -540,6 +544,7 @@ exports[`Select Component should render a expanded select: expanded 1`] = ` id="test" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ @@ -575,6 +580,7 @@ exports[`Select Component should render a expanded select: expanded 1`] = ` isGrouped={false} isOpen={true} isPlain={false} + maxHeight={null} menuAppendTo="inline" noResultsFoundText="No results found" onClear={[Function]} @@ -857,6 +863,7 @@ exports[`Select Component should render a expanded select: expanded 1`] = ` aria-labelledby="" isGrouped={false} keyHandler={[Function]} + maxHeight={null} openedOnEnter={false} sendRef={[Function]} > @@ -939,7 +946,7 @@ exports[`Select Component should render a expanded select: expanded 1`] = ` isExpanded={false} isGrouped={false} keyHandler={[Function]} - maxHeight="" + maxHeight={null} openedOnEnter={false} selected="" sendRef={[Function]} diff --git a/src/components/form/select.js b/src/components/form/select.js index b6ab23e0c..3a381bf65 100644 --- a/src/components/form/select.js +++ b/src/components/form/select.js @@ -182,9 +182,11 @@ class Select extends React.Component { */ render() { const { options, selected, isExpanded } = this.state; - const { ariaLabel, className, isDisabled, isToggleText, placeholder, toggleIcon, variant } = this.props; + const { ariaLabel, className, isDisabled, isToggleText, maxHeight, placeholder, toggleIcon, variant } = this.props; - const pfSelectOptions = {}; + const pfSelectOptions = { + maxHeight + }; // FixMe: investigate "isDisabled", PFReact quirks? if (!options || !options.length || isDisabled) { @@ -240,6 +242,7 @@ Select.propTypes = { id: PropTypes.string, isDisabled: PropTypes.bool, isToggleText: PropTypes.bool, + maxHeight: PropTypes.number, name: PropTypes.string, onSelect: PropTypes.func, options: PropTypes.oneOfType([ @@ -278,6 +281,7 @@ Select.defaultProps = { id: helpers.generateId(), isDisabled: false, isToggleText: true, + maxHeight: null, name: null, onSelect: helpers.noop, options: [], diff --git a/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap b/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap index c89ec5b8b..9a9cb94a3 100644 --- a/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap +++ b/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap @@ -13,6 +13,19 @@ exports[`I18n Component should attempt to perform translate with a node: transla exports[`I18n Component should generate a predictable locale key output snapshot: key output 1`] = ` Array [ + Object { + "file": "./src/common/dateHelpers.js", + "keys": Array [ + Object { + "key": "curiosity-toolbar.granularityRange", + "match": "translate('curiosity-toolbar.granularityRange', { context: dateTime.title })", + }, + Object { + "key": "curiosity-toolbar.granularityRange", + "match": "translate('curiosity-toolbar.granularityRange', { context: 'current' })", + }, + ], + }, Object { "file": "./src/components/authentication/authentication.js", "keys": Array [ @@ -404,6 +417,23 @@ Array [ }, ], }, + Object { + "file": "./src/components/toolbar/toolbarFieldRangedMonthly.js", + "keys": Array [ + Object { + "key": "curiosity-toolbar.placeholder", + "match": "t('curiosity-toolbar.placeholder', { context: 'granularity' })", + }, + Object { + "key": "curiosity-toolbar.placeholder", + "match": "t('curiosity-toolbar.placeholder', { context: 'granularity' })", + }, + Object { + "key": "curiosity-toolbar.granularityRange", + "match": "translate('curiosity-toolbar.granularityRange', { context: 'current' })", + }, + ], + }, Object { "file": "./src/components/toolbar/toolbarFieldUom.js", "keys": Array [ diff --git a/src/components/toolbar/__tests__/__snapshots__/toolbar.test.js.snap b/src/components/toolbar/__tests__/__snapshots__/toolbar.test.js.snap index 9778c2842..5ae8bd7e2 100644 --- a/src/components/toolbar/__tests__/__snapshots__/toolbar.test.js.snap +++ b/src/components/toolbar/__tests__/__snapshots__/toolbar.test.js.snap @@ -544,6 +544,7 @@ exports[`Toolbar Component should render a non-connected component: non-connecte id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ @@ -588,6 +589,7 @@ exports[`Toolbar Component should render a non-connected component: non-connecte id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ @@ -630,6 +632,7 @@ exports[`Toolbar Component should render a non-connected component: non-connecte id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ @@ -697,6 +700,7 @@ exports[`Toolbar Component should render filters when props are populated: props id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ @@ -745,6 +749,7 @@ exports[`Toolbar Component should render filters when props are populated: props id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ @@ -791,6 +796,7 @@ exports[`Toolbar Component should render filters when props are populated: props id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ @@ -864,6 +870,7 @@ exports[`Toolbar Component should render specific filters when the filterOptions id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ diff --git a/src/components/toolbar/__tests__/__snapshots__/toolbarFieldGranularity.test.js.snap b/src/components/toolbar/__tests__/__snapshots__/toolbarFieldGranularity.test.js.snap index c4df334a8..c73e8e1ab 100644 --- a/src/components/toolbar/__tests__/__snapshots__/toolbarFieldGranularity.test.js.snap +++ b/src/components/toolbar/__tests__/__snapshots__/toolbarFieldGranularity.test.js.snap @@ -57,6 +57,7 @@ exports[`ToolbarFieldGranularity Component should render a non-connected compone id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ diff --git a/src/components/toolbar/__tests__/__snapshots__/toolbarFieldRangedMonthly.test.js.snap b/src/components/toolbar/__tests__/__snapshots__/toolbarFieldRangedMonthly.test.js.snap new file mode 100644 index 000000000..732682c90 --- /dev/null +++ b/src/components/toolbar/__tests__/__snapshots__/toolbarFieldRangedMonthly.test.js.snap @@ -0,0 +1,398 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ToolbarFieldGranularity Component should export select options: toolbarFieldOptions 1`] = ` +Array [ + Object { + "_title": "current", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"current\\"})", + "value": Object { + "endDate": 2019-07-31T23:59:59.999Z, + "startDate": 2019-07-01T00:00:00.000Z, + }, + }, + Object { + "_title": "june", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"June\\"})", + "value": Object { + "endDate": 2019-06-30T23:59:59.999Z, + "startDate": 2019-06-01T00:00:00.000Z, + }, + }, + Object { + "_title": "may", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"May\\"})", + "value": Object { + "endDate": 2019-05-31T23:59:59.999Z, + "startDate": 2019-05-01T00:00:00.000Z, + }, + }, + Object { + "_title": "april", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"April\\"})", + "value": Object { + "endDate": 2019-04-30T23:59:59.999Z, + "startDate": 2019-04-01T00:00:00.000Z, + }, + }, + Object { + "_title": "march", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"March\\"})", + "value": Object { + "endDate": 2019-03-31T23:59:59.999Z, + "startDate": 2019-03-01T00:00:00.000Z, + }, + }, + Object { + "_title": "february", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"February\\"})", + "value": Object { + "endDate": 2019-02-28T23:59:59.999Z, + "startDate": 2019-02-01T00:00:00.000Z, + }, + }, + Object { + "_title": "january", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"January\\"})", + "value": Object { + "endDate": 2019-01-31T23:59:59.999Z, + "startDate": 2019-01-01T00:00:00.000Z, + }, + }, + Object { + "_title": "december", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"December 2018\\"})", + "value": Object { + "endDate": 2018-12-31T23:59:59.999Z, + "startDate": 2018-12-01T00:00:00.000Z, + }, + }, + Object { + "_title": "november", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"November 2018\\"})", + "value": Object { + "endDate": 2018-11-30T23:59:59.999Z, + "startDate": 2018-11-01T00:00:00.000Z, + }, + }, + Object { + "_title": "october", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"October 2018\\"})", + "value": Object { + "endDate": 2018-10-31T23:59:59.999Z, + "startDate": 2018-10-01T00:00:00.000Z, + }, + }, + Object { + "_title": "september", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"September 2018\\"})", + "value": Object { + "endDate": 2018-09-30T23:59:59.999Z, + "startDate": 2018-09-01T00:00:00.000Z, + }, + }, + Object { + "_title": "august", + "selected": false, + "title": "t(curiosity-toolbar.granularityRange, {\\"context\\":\\"August 2018\\"})", + "value": Object { + "endDate": 2018-08-31T23:59:59.999Z, + "startDate": 2018-08-01T00:00:00.000Z, + }, + }, +] +`; + +exports[`ToolbarFieldGranularity Component should handle selecting an option directly: selected option 1`] = ` + +`; diff --git a/src/components/toolbar/__tests__/__snapshots__/toolbarFieldUom.test.js.snap b/src/components/toolbar/__tests__/__snapshots__/toolbarFieldUom.test.js.snap index 16cb4ac49..ca6b6f551 100644 --- a/src/components/toolbar/__tests__/__snapshots__/toolbarFieldUom.test.js.snap +++ b/src/components/toolbar/__tests__/__snapshots__/toolbarFieldUom.test.js.snap @@ -40,6 +40,7 @@ exports[`ToolbarFieldUom Component should render a non-connected component: non- id="generatedid-" isDisabled={false} isToggleText={true} + maxHeight={null} name={null} onSelect={[Function]} options={ diff --git a/src/components/toolbar/__tests__/toolbarFieldRangedMonthly.test.js b/src/components/toolbar/__tests__/toolbarFieldRangedMonthly.test.js new file mode 100644 index 000000000..a007f859b --- /dev/null +++ b/src/components/toolbar/__tests__/toolbarFieldRangedMonthly.test.js @@ -0,0 +1,48 @@ +import React from 'react'; +import { mount, shallow } from 'enzyme'; +import { ToolbarFieldRangedMonthly, toolbarFieldOptions } from '../toolbarFieldRangedMonthly'; +import { store } from '../../../redux/store'; + +describe('ToolbarFieldGranularity Component', () => { + let mockDispatch; + + beforeEach(() => { + mockDispatch = jest.spyOn(store, 'dispatch').mockImplementation((type, data) => ({ type, data })); + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should render a non-connected component', () => { + const props = {}; + const component = shallow(); + + expect(component).toMatchSnapshot('non-connected'); + }); + + it('should export select options', () => { + expect(toolbarFieldOptions).toMatchSnapshot('toolbarFieldOptions'); + }); + + it('should handle selecting an option directly', () => { + const props = { + value: '2018-08-01T00:00:00.000Z' + }; + const component = shallow(); + + expect(component).toMatchSnapshot('selected option'); + }); + + it('should handle updating granularity through redux state', () => { + const props = {}; + + const component = mount(); + + component.find('button').simulate('click'); + component.update(); + component.find('button.pf-c-select__menu-item').first().simulate('click'); + + expect(mockDispatch.mock.calls).toMatchSnapshot('dispatch date range'); + }); +}); diff --git a/src/components/toolbar/toolbarFieldRangedMonthly.js b/src/components/toolbar/toolbarFieldRangedMonthly.js new file mode 100644 index 000000000..29063f8cf --- /dev/null +++ b/src/components/toolbar/toolbarFieldRangedMonthly.js @@ -0,0 +1,111 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { reduxTypes, store, useSelector } from '../../redux'; +import { Select } from '../form/select'; +import { RHSM_API_QUERY_GRANULARITY_TYPES as FIELD_TYPES, RHSM_API_QUERY_TYPES } from '../../types/rhsmApiTypes'; +import { dateHelpers } from '../../common'; +import { translate } from '../i18n/i18n'; + +/** + * Select field options. + * + * @type {{title: (string|Node), value: string, selected: boolean}[]} + */ +const toolbarFieldOptions = dateHelpers.getRangedMonthDateTime().listDateTimeRanges.map(dateTime => ({ + ...dateTime, + selected: false +})); + +/** + * Display a granularity field with options. + * + * @fires onSelect + * @param {object} props + * @param {Array} props.options + * @param {Function} props.t + * @param {string} props.value + * @param {string} props.viewId + * @returns {Node} + */ +const ToolbarFieldRangedMonthly = ({ options, t, value, viewId }) => { + const updatedValue = useSelector( + ({ view }) => view.graphTallyQuery?.[viewId]?.[RHSM_API_QUERY_TYPES.START_DATE], + value + ); + + const updatedOptions = options.map(option => ({ + ...option, + selected: option.title === updatedValue || option.value.startDate.toISOString() === updatedValue + })); + + /** + * On select, dispatch type. + * + * @event onSelect + * @param {object} event + * @returns {void} + */ + const onSelect = event => { + const { startDate, endDate } = event.value; + store.dispatch([ + { + type: reduxTypes.query.SET_QUERY_RHSM_TYPES[RHSM_API_QUERY_TYPES.GRANULARITY], + viewId, + [RHSM_API_QUERY_TYPES.GRANULARITY]: FIELD_TYPES.DAILY + }, + { + type: reduxTypes.query.SET_QUERY_RHSM_TYPES[RHSM_API_QUERY_TYPES.START_DATE], + viewId, + [RHSM_API_QUERY_TYPES.START_DATE]: startDate.toISOString() + }, + { + type: reduxTypes.query.SET_QUERY_RHSM_TYPES[RHSM_API_QUERY_TYPES.END_DATE], + viewId, + [RHSM_API_QUERY_TYPES.END_DATE]: endDate.toISOString() + } + ]); + }; + + return ( +