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`] = `
+
+`;
+
+exports[`ToolbarFieldGranularity Component should handle updating granularity through redux state: dispatch date range 1`] = `
+Array [
+ Array [
+ Array [
+ Object {
+ "granularity": "daily",
+ "type": "SET_QUERY_RHSM_granularity",
+ "viewId": "toolbarFieldRangeGranularity",
+ },
+ Object {
+ "beginning": "2019-07-01T00:00:00.000Z",
+ "type": "SET_QUERY_RHSM_beginning",
+ "viewId": "toolbarFieldRangeGranularity",
+ },
+ Object {
+ "ending": "2019-07-31T23:59:59.999Z",
+ "type": "SET_QUERY_RHSM_ending",
+ "viewId": "toolbarFieldRangeGranularity",
+ },
+ ],
+ ],
+]
+`;
+
+exports[`ToolbarFieldGranularity Component should render a non-connected component: non-connected 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 (
+
+ );
+};
+
+/**
+ * Prop types.
+ *
+ * @type {{viewId: string, t: Function, options: Array, value: string}}
+ */
+ToolbarFieldRangedMonthly.propTypes = {
+ options: PropTypes.arrayOf(
+ PropTypes.shape({
+ title: PropTypes.node,
+ value: PropTypes.any,
+ selected: PropTypes.bool
+ })
+ ),
+ t: PropTypes.func,
+ value: PropTypes.string,
+ viewId: PropTypes.string
+};
+
+/**
+ * Default props.
+ *
+ * @type {{viewId: string, t: translate, options: Array, value: string}}
+ */
+ToolbarFieldRangedMonthly.defaultProps = {
+ options: toolbarFieldOptions,
+ t: translate,
+ value: translate('curiosity-toolbar.granularityRange', { context: 'current' }),
+ viewId: 'toolbarFieldRangeGranularity'
+};
+
+export { ToolbarFieldRangedMonthly as default, ToolbarFieldRangedMonthly, toolbarFieldOptions };