Skip to content

Commit

Permalink
Ability to inject times outside of default time interval (Hacker0x01#…
Browse files Browse the repository at this point in the history
…1329)

* Allow specific times outside of intervals to be injected into time list

* Update docs-site

* Update docs

* Add tests

* More specs
  • Loading branch information
jimmynguyc authored and martijnrusschen committed Mar 26, 2018
1 parent f715f15 commit ed55d2b
Show file tree
Hide file tree
Showing 10 changed files with 440 additions and 257 deletions.
515 changes: 261 additions & 254 deletions docs-site/src/example_components.jsx

Large diffs are not rendered by default.

59 changes: 59 additions & 0 deletions docs-site/src/examples/inject_times.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from "react";
import DatePicker from "react-datepicker";
import moment from "moment";

export default class InjectTimes extends React.Component {
state = {
startDate: moment()
.hours(16)
.minutes(30)
};

handleChange = date => {
this.setState({
startDate: date
});
};

render() {
return (
<div className="row">
<pre className="column example__code">
<code className="jsx">
{`
<DatePicker
selected={this.state.startDate}
onChange={this.handleChange}`}
<br />
<strong>{` showTimeSelect
timeFormat="HH:mm"
injectTimes={[moment().hours(0).minutes(1), moment().hours(12).minutes(5), moment().hours(23).minutes(59)]}
dateFormat="LLL"
/>
`}</strong>
</code>
</pre>
<div className="column">
<DatePicker
selected={this.state.startDate}
onChange={this.handleChange}
showTimeSelect
timeFormat="HH:mm"
injectTimes={[
moment()
.hours(0)
.minutes(1),
moment()
.hours(12)
.minutes(5),
moment()
.hours(23)
.minutes(59)
]}
dateFormat="LLL"
/>
</div>
</div>
);
}
}
1 change: 1 addition & 0 deletions docs/datepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ General datepicker component.
| `id` | `string` | | |
| `includeDates` | `array` | | |
| `includeTimes` | `array` | | |
| `injectTimes` | `array` | | |
| `inline` | `bool` | | |
| `isClearable` | `bool` | | |
| `locale` | `string` | | |
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ General datepicker component.
| `id` | `string` | | |
| `includeDates` | `array` | | |
| `includeTimes` | `array` | | |
| `injectTimes` | `array` | | |
| `inline` | `bool` | | |
| `isClearable` | `bool` | | |
| `locale` | `string` | | |
Expand Down
1 change: 1 addition & 0 deletions docs/time.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
| `excludeTimes` | `array` | | |
| `format` | `string` | | |
| `includeTimes` | `array` | | |
| `injectTimes` | `array` | | |
| `intervals` | `number` | `30` | |
| `maxTime` | `object` | | |
| `minTime` | `object` | | |
Expand Down
2 changes: 2 additions & 0 deletions src/calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export default class Calendar extends React.Component {
highlightDates: PropTypes.instanceOf(Map),
includeDates: PropTypes.array,
includeTimes: PropTypes.array,
injectTimes: PropTypes.array,
inline: PropTypes.bool,
locale: PropTypes.string,
maxDate: PropTypes.object,
Expand Down Expand Up @@ -545,6 +546,7 @@ export default class Calendar extends React.Component {
showYearDropdown={this.props.showYearDropdown}
withPortal={this.props.withPortal}
monthRef={this.state.monthContainer}
injectTimes={this.props.injectTimes}
/>
);
}
Expand Down
30 changes: 30 additions & 0 deletions src/date_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ export function addMinutes(date, amount) {
return add(date, amount, "minutes");
}

export function addHours(date, amount) {
return add(date, amount, "hours");
}

export function addDays(date, amount) {
return add(date, amount, "days");
}
Expand Down Expand Up @@ -490,3 +494,29 @@ export function getHightLightDaysMap(

return dateClasses;
}

export function timeToInjectAfter(
startOfDay,
currentTime,
currentMultiplier,
intervals,
injectedTimes
) {
const l = injectedTimes.length;
for (let i = 0; i < l; i++) {
const injectedTime = addMinutes(
addHours(cloneDate(startOfDay), getHour(injectedTimes[i])),
getMinute(injectedTimes[i])
);
const nextTime = addMinutes(
cloneDate(startOfDay),
(currentMultiplier + 1) * intervals
);

if (injectedTime.isBetween(currentTime, nextTime)) {
return injectedTimes[i];
}
}

return false;
}
2 changes: 2 additions & 0 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export default class DatePicker extends React.Component {
id: PropTypes.string,
includeDates: PropTypes.array,
includeTimes: PropTypes.array,
injectTimes: PropTypes.array,
inline: PropTypes.bool,
isClearable: PropTypes.bool,
locale: PropTypes.string,
Expand Down Expand Up @@ -506,6 +507,7 @@ export default class DatePicker extends React.Component {
highlightDates={this.state.highlightDates}
includeDates={this.props.includeDates}
includeTimes={this.props.includeTimes}
injectTimes={this.props.injectTimes}
inline={this.props.inline}
peekNextMonth={this.props.peekNextMonth}
showMonthDropdown={this.props.showMonthDropdown}
Expand Down
28 changes: 25 additions & 3 deletions src/time.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
cloneDate,
formatDate,
isTimeInDisabledRange,
isTimeDisabled
isTimeDisabled,
timeToInjectAfter
} from "./date_utils";

export default class Time extends React.Component {
Expand All @@ -24,7 +25,8 @@ export default class Time extends React.Component {
maxTime: PropTypes.object,
excludeTimes: PropTypes.array,
monthRef: PropTypes.object,
timeCaption: PropTypes.string
timeCaption: PropTypes.string,
injectTimes: PropTypes.array
};

static get defaultProps() {
Expand Down Expand Up @@ -76,6 +78,12 @@ export default class Time extends React.Component {
) {
classes.push("react-datepicker__time-list-item--disabled");
}
if (
this.props.injectTimes &&
(getHour(time) * 60 + getMinute(time)) % this.props.intervals !== 0
) {
classes.push("react-datepicker__time-list-item--injected");
}

return classes.join(" ");
};
Expand All @@ -90,7 +98,21 @@ export default class Time extends React.Component {
let base = getStartOfDay(newDate());
const multiplier = 1440 / intervals;
for (let i = 0; i < multiplier; i++) {
times.push(addMinutes(cloneDate(base), i * intervals));
const currentTime = addMinutes(cloneDate(base), i * intervals);
times.push(currentTime);

if (this.props.injectTimes) {
const timeToInject = timeToInjectAfter(
base,
currentTime,
i,
intervals,
this.props.injectTimes
);
if (timeToInject) {
times.push(timeToInject);
}
}
}

return times.map((time, i) => (
Expand Down
58 changes: 58 additions & 0 deletions test/inject_times_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from "react";
import { mount } from "enzyme";
import * as utils from "../src/date_utils";
import { setTime, cloneDate, newDate } from "../src/date_utils";
import TimeComponent from "../src/time";

function cloneDateWithTime(date, time) {
return setTime(cloneDate(date), time);
}

describe("TimeComponent", () => {
let sandbox;

beforeEach(() => {
sandbox = sinon.sandbox.create();
});

afterEach(() => {
sandbox.restore();
});

it("should show times specified in injectTimes props", () => {
const today = utils.getStartOfDay(utils.newDate());
const timeComponent = mount(
<TimeComponent
injectTimes={[
utils.addMinutes(cloneDate(today), 1),
utils.addMinutes(cloneDate(today), 725),
utils.addMinutes(cloneDate(today), 1439)
]}
/>
);

const disabledItems = timeComponent.find(
".react-datepicker__time-list-item--injected"
);
expect(disabledItems).to.have.length(3);
});

it("should not affect existing time intervals", () => {
const today = utils.getStartOfDay(utils.newDate());
const timeComponent = mount(
<TimeComponent
timeIntervals={60}
injectTimes={[
utils.addMinutes(cloneDate(today), 0),
utils.addMinutes(cloneDate(today), 60),
utils.addMinutes(cloneDate(today), 1440)
]}
/>
);

const disabledItems = timeComponent.find(
".react-datepicker__time-list-item--injected"
);
expect(disabledItems).to.have.length(0);
});
});

0 comments on commit ed55d2b

Please sign in to comment.