Skip to content

Commit

Permalink
Merge pull request Hacker0x01#2420 from saltire/filterTime
Browse files Browse the repository at this point in the history
Add filterTime property
  • Loading branch information
martijnrusschen authored Oct 9, 2020
2 parents 57c9788 + 7a909ca commit 99d45b9
Show file tree
Hide file tree
Showing 12 changed files with 133 additions and 20 deletions.
5 changes: 5 additions & 0 deletions docs-site/src/components/Examples/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import ShowTimeOnly from "../../examples/showTimeOnly";
import ExcludeTimes from "../../examples/excludeTimes";
import IncludeTimes from "../../examples/includeTimes";
import InjectTimes from "../../examples/injectTimes";
import FilterTimes from "../../examples/filterTimes";
import ExcludeTimePeriod from "../../examples/excludeTimePeriod";
import CustomDateFormat from "../../examples/customDateFormat";
import CustomClassName from "../../examples/customClassName";
Expand Down Expand Up @@ -195,6 +196,10 @@ export default class exampleComponents extends React.Component {
title: "Filter dates",
component: FilterDates
},
{
title: "Filter times",
component: FilterTimes
},
{
title: "Fixed height of Calendar",
component: FixedCalendar
Expand Down
1 change: 1 addition & 0 deletions docs-site/src/examples/.eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"useState": false,
"render": false,
"DatePicker": false,
"getHours": false,
"setHours": false,
"setMinutes": false,
"getDate": false,
Expand Down
18 changes: 18 additions & 0 deletions docs-site/src/examples/filterTimes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
() => {
const [startDate, setStartDate] = useState(
setHours(setMinutes(new Date(), 0), 9)
);
const from9to5 = time => {
const hour = getHours(time);
return hour >= 9 && hour < 17;
}
return (
<DatePicker
selected={startDate}
onChange={date => setStartDate(date)}
showTimeSelect
filterTime={from9to5}
dateFormat="MMMM d, yyyy h:mm aa"
/>
);
};
1 change: 1 addition & 0 deletions docs/datepicker.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ General datepicker component.
| `excludeTimes` | `array` | | |
| `excludeScrollbar` | `array` | | |
| `filterDate` | `func` | | |
| `filterTime` | `func` | | |
| `fixedHeight` | `bool` | | |
| `forceShowMonthNavigation` | `bool` | | |
| `formatWeekNumber` | `func` | | |
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
|`excludeScrollbar`|`bool`|`true`||
|`excludeTimes`|`array`|||
|`filterDate`|`func`|||
|`filterTime`|`func`|||
|`fixedHeight`|`bool`|||
|`focusSelectedMonth`|`bool`|`false`||
|`forceShowMonthNavigation`|`bool`|||
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 @@
| name | type | default value | description |
|---|---|---|---|
|`excludeTimes`|`array`|||
|`filterTime`|`func`|||
|`format`|`string`|||
|`includeTimes`|`array`|||
|`injectTimes`|`array`|||
Expand Down
2 changes: 2 additions & 0 deletions src/calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export default class Calendar extends React.Component {
minTime: PropTypes.instanceOf(Date),
maxTime: PropTypes.instanceOf(Date),
excludeTimes: PropTypes.array,
filterTime: PropTypes.func,
timeCaption: PropTypes.string,
openToDate: PropTypes.instanceOf(Date),
peekNextMonth: PropTypes.bool,
Expand Down Expand Up @@ -866,6 +867,7 @@ export default class Calendar extends React.Component {
minTime={this.props.minTime}
maxTime={this.props.maxTime}
excludeTimes={this.props.excludeTimes}
filterTime={this.props.filterTime}
timeCaption={this.props.timeCaption}
todayButton={this.props.todayButton}
showMonthDropdown={this.props.showMonthDropdown}
Expand Down
26 changes: 14 additions & 12 deletions src/date_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ export { addMinutes, addDays, addWeeks, addMonths, addYears };

// *** Subtraction ***

export { subMinutes, subHours, subDays, subWeeks, subMonths, subYears };
export { addHours, subMinutes, subHours, subDays, subWeeks, subMonths, subYears };

// ** Date Comparison **

Expand Down Expand Up @@ -475,18 +475,20 @@ export function isOutOfBounds(day, { minDate, maxDate } = {}) {
);
}

export function isTimeDisabled(time, disabledTimes) {
const l = disabledTimes.length;
for (let i = 0; i < l; i++) {
if (
getHours(disabledTimes[i]) === getHours(time) &&
getMinutes(disabledTimes[i]) === getMinutes(time)
) {
return true;
}
}
export function isTimeInList(time, times) {
return times.some(listTime => (
getHours(listTime) === getHours(time) &&
getMinutes(listTime) === getMinutes(time)
));
}

return false;
export function isTimeDisabled(time, { excludeTimes, includeTimes, filterTime } = {}) {
return (
(excludeTimes && isTimeInList(time, excludeTimes)) ||
(includeTimes && !isTimeInList(time, includeTimes)) ||
(filterTime && !filterTime(time)) ||
false
);
}

export function isTimeInDisabledRange(time, { minTime, maxTime }) {
Expand Down
2 changes: 2 additions & 0 deletions src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ export default class DatePicker extends React.Component {
minTime: PropTypes.instanceOf(Date),
maxTime: PropTypes.instanceOf(Date),
excludeTimes: PropTypes.array,
filterTime: PropTypes.func,
useShortMonthInDropdown: PropTypes.bool,
clearButtonTitle: PropTypes.string,
previousMonthButtonLabel: PropTypes.oneOfType([
Expand Down Expand Up @@ -847,6 +848,7 @@ export default class DatePicker extends React.Component {
minTime={this.props.minTime}
maxTime={this.props.maxTime}
excludeTimes={this.props.excludeTimes}
filterTime={this.props.filterTime}
timeCaption={this.props.timeCaption}
className={this.props.calendarClassName}
container={this.props.calendarContainer}
Expand Down
13 changes: 5 additions & 8 deletions src/time.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default class Time extends React.Component {
minTime: PropTypes.instanceOf(Date),
maxTime: PropTypes.instanceOf(Date),
excludeTimes: PropTypes.array,
filterTime: PropTypes.func,
monthRef: PropTypes.object,
timeCaption: PropTypes.string,
injectTimes: PropTypes.array,
Expand Down Expand Up @@ -77,10 +78,8 @@ export default class Time extends React.Component {
if (
((this.props.minTime || this.props.maxTime) &&
isTimeInDisabledRange(time, this.props)) ||
(this.props.excludeTimes &&
isTimeDisabled(time, this.props.excludeTimes)) ||
(this.props.includeTimes &&
!isTimeDisabled(time, this.props.includeTimes))
((this.props.excludeTimes || this.props.includeTimes || this.props.filterTime) &&
isTimeDisabled(time, this.props))
) {
return;
}
Expand All @@ -105,10 +104,8 @@ export default class Time extends React.Component {
if (
((this.props.minTime || this.props.maxTime) &&
isTimeInDisabledRange(time, this.props)) ||
(this.props.excludeTimes &&
isTimeDisabled(time, this.props.excludeTimes)) ||
(this.props.includeTimes &&
!isTimeDisabled(time, this.props.includeTimes))
((this.props.excludeTimes || this.props.includeTimes || this.props.filterTime) &&
isTimeDisabled(time, this.props))
) {
classes.push("react-datepicker__time-list-item--disabled");
}
Expand Down
55 changes: 55 additions & 0 deletions test/date_utils_test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
newDate,
addHours,
addDays,
subDays,
isEqual,
Expand All @@ -18,6 +19,7 @@ import {
getEffectiveMinDate,
getEffectiveMaxDate,
addZero,
isTimeDisabled,
isTimeInDisabledRange,
isDayInRange,
parseDate,
Expand Down Expand Up @@ -550,6 +552,59 @@ describe("date_utils", function() {
});
});

describe("isTimeDisabled", function() {
it("should be enabled by default", () => {
const date = newDate();
const time = setHours(setMinutes(date, 30), 1);
expect(isTimeDisabled(time)).to.be.false;
});

it("should be disabled if in excluded times", () => {
const date = newDate();
const time = setHours(setMinutes(date, 30), 1);
expect(isTimeDisabled(time, { excludeTimes: [time] })).to.be.true;
});

it("should be enabled if in included times", () => {
const date = newDate();
const time = setHours(setMinutes(date, 30), 1);
expect(isTimeDisabled(time, { includeTimes: [time] })).to.be.false;
});

it("should be disabled if not in included times", () => {
const date = newDate();
const time = setHours(setMinutes(date, 30), 1);
const includeTimes = [addHours(time, 1)];
expect(isTimeDisabled(time, { includeTimes })).to.be.true;
});

it("should be enabled if time filter returns true", () => {
const date = newDate();
const time = setHours(setMinutes(date, 30), 1);
const filterTime = t => isEqual(t, time);
expect(isTimeDisabled(time, { filterTime })).to.be.false;
});

it("should be disabled if time filter returns false", () => {
const date = newDate();
const time = setHours(setMinutes(date, 30), 1);
const filterTime = t => !isEqual(t, time);
expect(isTimeDisabled(time, { filterTime })).to.be.true;
});

it("should not allow time filter to modify input time", () => {
const date = newDate();
const time = setHours(setMinutes(date, 30), 1);
const timeClone = newDate(time);
const filterTime = t => {
addHours(t, 1);
return true;
};
isTimeDisabled(time, { filterTime });
expect(isEqual(time, timeClone)).to.be.true;
});
});

describe("isTimeInDisabledRange", () => {
it("should tell if time is in disabled range", () => {
const date = newDate("2016-03-15");
Expand Down
28 changes: 28 additions & 0 deletions test/filter_times_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
import { mount } from "enzyme";
import { getHours } from "../src/date_utils";
import DatePicker from "../src/index.jsx";
import TimeComponent from "../src/time";

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

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

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

it("should disable times matched by filterTime prop", () => {
const timeComponent = mount(
<TimeComponent
filterTime={time => getHours(time) !== 17}
/>
);

expect(timeComponent.find(".react-datepicker__time-list-item--disabled"))
.to.have.length(2);
});
});

0 comments on commit 99d45b9

Please sign in to comment.