Skip to content

Commit a423741

Browse files
authoredJan 21, 2019
Merge pull request #271 from Adphorus/feature/support-for-customizable-static-range-labels
Support for customizable static range labels
2 parents 2ffa7c8 + 5e4eb44 commit a423741

File tree

8 files changed

+1562
-9
lines changed

8 files changed

+1562
-9
lines changed
 

‎. eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/node_modules/*
22
/lib/*
33
/dist/*
4+
**/*.snap

‎CONTRIBUTING.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@ Make sure your issue or feature doesn't have any related issue at [react-date-ra
1010

1111
3. Run `yarn` to install the dependencies.
1212

13-
4. Run `yarn dev` to start development server.
13+
4. Run `yarn run dev` to start development server.
1414

1515
## Building
1616

17-
. Run `run test` and `run lint` for make sure tests passes and linter doesn't throw any error.
17+
. Run `yarn run test` and `yarn run lint` for make sure tests passes and linter doesn't throw any error.
1818

19-
. Run `yarn build` compile the library and demo source.
19+
. Run `yarn run build` compile the library and demo source.
2020

2121
. Push your changes and create a PR and apply code review decisions.
2222

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ showPreview(DateRange) | bool | true | visibility
129129
dragSelectionEnabled(Calendar) | bool | true | whether dates can be selected via drag n drop
130130
onPreviewChange(DateRange) | Object | | Callback function for preview changes
131131
dateDisplayFormat(DateRange) | String | `MMM D, YYYY` | selected range preview formatter. Check out [date-fns's format option](https://date-fns.org/v2.0.0-alpha.7/docs/format)
132+
renderStaticRangeLabel(`DefinedRange`)| Function | | Callback function to be triggered for the static range configurations that have `hasCustomRendering: true` on them. Instead of rendering `staticRange.label`, return value of this callback will be rendered.
132133
staticRanges(`DefinedRange`, `DateRangePicker`) | Array | [default preDefined ranges](https://github.com/Adphorus/react-date-range/blob/master/src/defaultRanges.js) | -
133134
inputRanges(`DefinedRange`, `DateRangePicker`) | Array | [default input ranges](https://github.com/Adphorus/react-date-range/blob/master/src/defaultRanges.js) | -
134135

‎demo/src/components/Main.js

+83-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,51 @@ import * as rdrLocales from '../../../src/locale';
44
import { format, addDays } from 'date-fns';
55
import Section from './Section';
66

7+
function renderStaticRangeLabel(staticRange) {
8+
return (
9+
<CustomStaticRangeLabelContent text={'This is a custom label content: '}/>
10+
);
11+
}
12+
13+
class CustomStaticRangeLabelContent extends React.Component {
14+
constructor(props) {
15+
super(props);
16+
17+
this.state = {
18+
currentDateString: Date(),
19+
};
20+
21+
this.intervalId = setInterval(
22+
() => {
23+
this.setState({
24+
currentDateString: Date(),
25+
});
26+
},
27+
1000
28+
);
29+
}
30+
31+
componentWillUnmount() {
32+
if (this.intervalId) {
33+
clearInterval(this.intervalId);
34+
}
35+
}
36+
37+
render() {
38+
const { currentDateString } = this.state;
39+
const { text } = this.props;
40+
41+
return (
42+
<span>
43+
<i>{text}</i>
44+
<span className={'random-date-string'}>
45+
<b>{currentDateString}</b>
46+
</span>
47+
</span>
48+
);
49+
}
50+
}
51+
752
const nameMapper = {
853
ar: 'Arabic (Modern Standard Arabic - Al-fussha)',
954
bg: 'Bulgarian',
@@ -135,6 +180,7 @@ export default class Main extends Component {
135180
[which]: payload,
136181
});
137182
}
183+
138184
handleRangeChange(which, payload) {
139185
console.log(which, payload);
140186
this.setState({
@@ -217,7 +263,7 @@ export default class Main extends Component {
217263
readOnly
218264
value={formatDateDisplay(this.state.multipleRanges.selection1.endDate, 'Continuous')}
219265
/>
220-
<div className={'newLine'} />
266+
<div className={'newLine'}/>
221267

222268
<label className={'label'}>Selection2 Start:</label>
223269
<input
@@ -231,7 +277,7 @@ export default class Main extends Component {
231277
readOnly
232278
value={formatDateDisplay(this.state.multipleRanges.selection2.endDate, 'Continuous')}
233279
/>
234-
<div className={'newLine'} />
280+
<div className={'newLine'}/>
235281

236282
<label className={'label'}>Selection3 Start:</label>
237283
<input
@@ -319,9 +365,24 @@ export default class Main extends Component {
319365

320366
<DefinedRange
321367
ranges={[this.state.definedRange.selection]}
368+
renderStaticRangeLabel={renderStaticRangeLabel}
369+
staticRanges={[{
370+
label: "Hoy",
371+
hasCustomRendering: true,
372+
range: () => ({
373+
startDate: new Date(),
374+
endDate: new Date(),
375+
}),
376+
isSelected() {
377+
return (
378+
true
379+
);
380+
},
381+
}]}
322382
onChange={this.handleRangeChange.bind(this, 'definedRange')}
323383
className={'centered'}
324-
/>
384+
>
385+
</DefinedRange>
325386
</Section>
326387
<Section title="RangePicker with disabled dates">
327388
<div>
@@ -348,6 +409,25 @@ export default class Main extends Component {
348409
disabledDates={[new Date(), addDays(new Date(), 3)]}
349410
minDate={addDays(new Date(), -3)}
350411
/>
412+
413+
<DefinedRange
414+
ranges={[this.state.definedRange.selection]}
415+
renderStaticRangeLabel={renderStaticRangeLabel}
416+
staticRanges={[{
417+
hasCustomRendering: true,
418+
range: () => ({
419+
startDate: new Date(),
420+
endDate: new Date(),
421+
}),
422+
isSelected() {
423+
return (
424+
true
425+
);
426+
},
427+
}]}
428+
onChange={this.handleRangeChange.bind(this, 'definedRange')}
429+
className={'centered'}
430+
/>
351431
</Section>
352432
</main>
353433
);

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
],
2323
"contributors": [
2424
"Burak Can <neoberg@gmail.com> (https://github.com/burakcan)",
25-
"Mehmet Kamil Morcay <mehmetmorcay@gmail.com> (https://github.com/mkg0)"
25+
"Mehmet Kamil Morcay <mehmetmorcay@gmail.com> (https://github.com/mkg0)",
26+
"Engin Semih Basmacı <semih.basmaci@gmail.com> (https://github.com/mortargrind)"
2627
],
2728
"license": "MIT",
2829
"repository": {

‎src/components/DefinedRange.js

+15-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class DefinedRanges extends Component {
1414
};
1515
this.handleRangeChange = this.handleRangeChange.bind(this);
1616
}
17+
1718
handleRangeChange(range) {
1819
const { onChange, ranges, focusedRange } = this.props;
1920
const selectedRange = ranges[focusedRange[0]];
@@ -22,6 +23,7 @@ class DefinedRanges extends Component {
2223
[selectedRange.key || `range${focusedRange[0] + 1}`]: { ...selectedRange, ...range },
2324
});
2425
}
26+
2527
getSelectedRange(ranges, staticRange) {
2628
const focusedRangeIndex = ranges.findIndex(range => {
2729
if (!range.startDate || !range.endDate || range.disabled) return false;
@@ -30,14 +32,24 @@ class DefinedRanges extends Component {
3032
const selectedRange = ranges[focusedRangeIndex];
3133
return { selectedRange, focusedRangeIndex };
3234
}
35+
3336
render() {
34-
const { onPreviewChange, ranges, rangeColors, className } = this.props;
37+
const { onPreviewChange, ranges, renderStaticRangeLabel, rangeColors, className } = this.props;
38+
3539
return (
3640
<div className={cx(styles.definedRangesWrapper, className)}>
3741
{this.props.headerContent}
3842
<div className={styles.staticRanges}>
3943
{this.props.staticRanges.map((staticRange, i) => {
4044
const { selectedRange, focusedRangeIndex } = this.getSelectedRange(ranges, staticRange);
45+
let labelContent;
46+
47+
if (staticRange.hasCustomRendering) {
48+
labelContent = renderStaticRangeLabel(staticRange);
49+
} else {
50+
labelContent = staticRange.label;
51+
}
52+
4153
return (
4254
<button
4355
type="button"
@@ -59,7 +71,7 @@ class DefinedRanges extends Component {
5971
this.props.onPreviewChange && this.props.onPreviewChange();
6072
}}>
6173
<span tabIndex={-1} className={styles.staticRangeLabel}>
62-
{staticRange.label}
74+
{labelContent}
6375
</span>
6476
</button>
6577
);
@@ -106,6 +118,7 @@ DefinedRanges.propTypes = {
106118
headerContent: PropTypes.any,
107119
rangeColors: PropTypes.arrayOf(PropTypes.string),
108120
className: PropTypes.string,
121+
renderStaticRangeLabel: PropTypes.func,
109122
};
110123

111124
DefinedRanges.defaultProps = {

‎src/components/DefinedRange.test.js

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import React from 'react';
2+
import { mount, shallow } from 'enzyme';
3+
4+
import DefinedRange from './DefinedRange';
5+
import { isSameDay } from 'date-fns';
6+
7+
describe('DefinedRange tests', () => {
8+
test('Should call "renderStaticRangeLabel" callback correct amount of times according to the "hasCustomRendering" option', () => {
9+
const renderStaticRangeLabel = jest.fn();
10+
11+
mount(
12+
<DefinedRange
13+
staticRanges={[
14+
{
15+
label: 'Dynamic Label',
16+
range: {},
17+
isSelected(range) {
18+
const definedRange = this.range();
19+
return (
20+
isSameDay(range.startDate, definedRange.startDate) &&
21+
isSameDay(range.endDate, definedRange.endDate)
22+
);
23+
},
24+
hasCustomRendering: true,
25+
},
26+
{
27+
label: 'Static Label',
28+
range: {},
29+
isSelected(range) {
30+
const definedRange = this.range();
31+
return (
32+
isSameDay(range.startDate, definedRange.startDate) &&
33+
isSameDay(range.endDate, definedRange.endDate)
34+
);
35+
},
36+
},
37+
{
38+
label: 'Hede',
39+
range: {},
40+
isSelected(range) {
41+
const definedRange = this.range();
42+
return (
43+
isSameDay(range.startDate, definedRange.startDate) &&
44+
isSameDay(range.endDate, definedRange.endDate)
45+
);
46+
},
47+
hasCustomRendering: true,
48+
},
49+
]}
50+
renderStaticRangeLabel={renderStaticRangeLabel}
51+
/>
52+
);
53+
54+
expect(renderStaticRangeLabel).toHaveBeenCalledTimes(2);
55+
});
56+
57+
test('Should render dynamic static label contents correctly', () => {
58+
const renderItalicLabelContent = () => (
59+
<i className={'italic-label-content'}>{'Italic Content'}</i>
60+
);
61+
const renderBoldLabelContent = () => <b className={'bold-label-content'}>{'Bold Content'}</b>;
62+
const renderSomethingElse = () => <img className={'random-image'} />;
63+
64+
const renderStaticRangeLabel = function(staticRange) {
65+
let result;
66+
67+
if (staticRange.id === 'italic') {
68+
result = renderItalicLabelContent();
69+
} else if (staticRange.id === 'bold') {
70+
result = renderBoldLabelContent();
71+
} else {
72+
result = renderSomethingElse();
73+
}
74+
75+
return result;
76+
};
77+
78+
const wrapper = shallow(
79+
<DefinedRange
80+
staticRanges={[
81+
{
82+
id: 'italic',
83+
range: {},
84+
isSelected(range) {
85+
const definedRange = this.range();
86+
return (
87+
isSameDay(range.startDate, definedRange.startDate) &&
88+
isSameDay(range.endDate, definedRange.endDate)
89+
);
90+
},
91+
hasCustomRendering: true,
92+
},
93+
{
94+
label: 'Static Label',
95+
range: {},
96+
isSelected(range) {
97+
const definedRange = this.range();
98+
return (
99+
isSameDay(range.startDate, definedRange.startDate) &&
100+
isSameDay(range.endDate, definedRange.endDate)
101+
);
102+
},
103+
},
104+
{
105+
id: 'whatever',
106+
range: {},
107+
isSelected(range) {
108+
const definedRange = this.range();
109+
return (
110+
isSameDay(range.startDate, definedRange.startDate) &&
111+
isSameDay(range.endDate, definedRange.endDate)
112+
);
113+
},
114+
hasCustomRendering: true,
115+
},
116+
{
117+
id: 'bold',
118+
range: {},
119+
isSelected(range) {
120+
const definedRange = this.range();
121+
return (
122+
isSameDay(range.startDate, definedRange.startDate) &&
123+
isSameDay(range.endDate, definedRange.endDate)
124+
);
125+
},
126+
hasCustomRendering: true,
127+
},
128+
]}
129+
renderStaticRangeLabel={renderStaticRangeLabel}
130+
/>
131+
);
132+
133+
expect(wrapper).toMatchSnapshot();
134+
});
135+
});

‎src/components/__snapshots__/DefinedRange.test.js.snap

+1,322
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.