Skip to content

Commit

Permalink
Implement showDoubleView prop (#248)
Browse files Browse the repository at this point in the history
* Implement showDoubleView

* Fix tests for Navigation component

* Add unit tests for showDoubleView
  • Loading branch information
wojtekmaj authored Sep 26, 2019
1 parent 0fff2fd commit a046efd
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 48 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ Displays a complete, interactive calendar.
|prev2AriaLabel|`aria-label` attribute of the "previous on higher level" button on the navigation pane.|n/a|`"Jump backwards"`|
|prev2Label|Content of the "previous on higher level" button on the navigation pane.| `"«"`|<ul><li>String: `"«"`</li><li>React element: `<DoublePreviousIcon />`</li></ul>|
|returnValue|Which dates shall be passed by the calendar to the onChange function and onClick{Period} functions. Can be `"start"`, `"end"` or `"range"`. The latter will cause an array with start and end values to be passed.|`"start"`|`"range"`|
|showDoubleView|Whether to show two months/years/… at a time instead of one. Forces `showFixedNumberOfWeeks` prop to be `true`.|`false`|`true`|
|showFixedNumberOfWeeks|Whether to always show fixed number of weeks (6). Forces `showNeighboringMonth` prop to be `true`.|`false`|`true`|
|showNavigation|Whether a navigation bar with arrows and title shall be rendered.|`true`|`false`|
|showNeighboringMonth|Whether days from previous or next month shall be rendered if the month doesn't start on the first day of the week or doesn't end on the last day of the week, respectively.|`true`|`false`|
Expand Down
24 changes: 19 additions & 5 deletions src/Calendar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import DecadeView from './DecadeView';
import YearView from './YearView';
import MonthView from './MonthView';

import { getBegin, getEnd, getValueRange } from './shared/dates';
import {
getBegin, getBeginNext, getEnd, getValueRange,
} from './shared/dates';
import {
isCalendarType, isClassName, isMaxDate, isMinDate, isValue, isView,
} from './shared/propTypes';
Expand Down Expand Up @@ -352,9 +354,9 @@ export default class Calendar extends Component {
this.setState({ hover: null });
}

renderContent() {
renderContent(next) {
const {
activeStartDate,
activeStartDate: currentActiveStartDate,
onMouseOver,
valueType,
value,
Expand All @@ -373,6 +375,12 @@ export default class Calendar extends Component {
} = this.props;
const { hover } = this;

const activeStartDate = (
next
? getBeginNext(view, currentActiveStartDate)
: currentActiveStartDate
);

const commonProps = {
activeStartDate,
hover,
Expand Down Expand Up @@ -428,6 +436,7 @@ export default class Calendar extends Component {
formatShortWeekday,
onClickDay,
onClickWeekNumber,
showDoubleView,
showFixedNumberOfWeeks,
showNeighboringMonth,
showWeekNumbers,
Expand All @@ -441,7 +450,7 @@ export default class Calendar extends Component {
onClick={mergeFunctions(clickAction, onClickDay)}
onClickWeekNumber={onClickWeekNumber}
onMouseLeave={onMouseLeave}
showFixedNumberOfWeeks={showFixedNumberOfWeeks}
showFixedNumberOfWeeks={showFixedNumberOfWeeks || showDoubleView}
showNeighboringMonth={showNeighboringMonth}
showWeekNumbers={showWeekNumbers}
{...commonProps}
Expand Down Expand Up @@ -479,6 +488,7 @@ export default class Calendar extends Component {
prev2Label,
prevAriaLabel,
prevLabel,
showDoubleView,
} = this.props;

return (
Expand All @@ -501,14 +511,15 @@ export default class Calendar extends Component {
prevAriaLabel={prevAriaLabel}
prevLabel={prevLabel}
setActiveStartDate={this.setActiveStartDate}
showDoubleView={showDoubleView}
view={view}
views={getLimitedViews(minDetail, maxDetail)}
/>
);
}

render() {
const { className, selectRange } = this.props;
const { className, selectRange, showDoubleView } = this.props;
const { onMouseLeave, value } = this;
const valueArray = [].concat(value);

Expand All @@ -517,6 +528,7 @@ export default class Calendar extends Component {
className={mergeClassNames(
baseClassName,
selectRange && valueArray.length === 1 && `${baseClassName}--selectRange`,
showDoubleView && `${baseClassName}--doubleView`,
className,
)}
>
Expand All @@ -527,6 +539,7 @@ export default class Calendar extends Component {
onMouseLeave={selectRange ? onMouseLeave : null}
>
{this.renderContent()}
{showDoubleView && this.renderContent(true)}
</div>
</div>
);
Expand Down Expand Up @@ -586,6 +599,7 @@ Calendar.propTypes = {
renderChildren: PropTypes.func, // For backwards compatibility
returnValue: PropTypes.oneOf(['start', 'end', 'range']),
selectRange: PropTypes.bool,
showDoubleView: PropTypes.bool,
showFixedNumberOfWeeks: PropTypes.bool,
showNavigation: PropTypes.bool,
showNeighboringMonth: PropTypes.bool,
Expand Down
14 changes: 14 additions & 0 deletions src/Calendar.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@
font-family: Arial, Helvetica, sans-serif;
line-height: 1.125em;

&--doubleView {
width: 700px;

.react-calendar__viewContainer {
display: flex;
margin: -.5em;

> * {
width: 50%;
margin: .5em;
}
}
}

&, & *, & *:before, & *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
Expand Down
67 changes: 43 additions & 24 deletions src/Calendar/Navigation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { isView, isViews } from '../shared/propTypes';
const className = 'react-calendar__navigation';

export default function Navigation({
activeStartDate: date,
activeStartDate,
drillUp,
formatMonthYear,
formatYear,
Expand All @@ -38,30 +38,34 @@ export default function Navigation({
prevAriaLabel,
prevLabel,
setActiveStartDate,
showDoubleView,
view,
views,
}) {
const drillUpAvailable = views.indexOf(view) > 0;
const shouldShowPrevNext2Buttons = view !== 'century';

const previousActiveStartDate = getBeginPrevious(view, date);
const previousActiveStartDate2 = shouldShowPrevNext2Buttons && getBeginPrevious2(view, date);
const nextActiveStartDate = getBeginNext(view, date);
const nextActiveStartDate2 = shouldShowPrevNext2Buttons && getBeginNext2(view, date);
const previousActiveStartDate = getBeginPrevious(view, activeStartDate);
const previousActiveStartDate2 = (
shouldShowPrevNext2Buttons
&& getBeginPrevious2(view, activeStartDate)
);
const nextActiveStartDate = getBeginNext(view, activeStartDate);
const nextActiveStartDate2 = shouldShowPrevNext2Buttons && getBeginNext2(view, activeStartDate);

const prevButtonDisabled = (() => {
if (previousActiveStartDate.getFullYear() < 1000) {
return true;
}
const previousActiveEndDate = getEndPrevious(view, date);
const previousActiveEndDate = getEndPrevious(view, activeStartDate);
return minDate && minDate >= previousActiveEndDate;
})();

const prev2ButtonDisabled = shouldShowPrevNext2Buttons && (() => {
if (previousActiveStartDate2.getFullYear() < 1000) {
return true;
}
const previousActiveEndDate = getEndPrevious2(view, date);
const previousActiveEndDate = getEndPrevious2(view, activeStartDate);
return minDate && minDate >= previousActiveEndDate;
})();

Expand Down Expand Up @@ -89,20 +93,28 @@ export default function Navigation({
setActiveStartDate(nextActiveStartDate2);
}

const label = (() => {
switch (view) {
case 'century':
return getCenturyLabel(locale, formatYear, date);
case 'decade':
return getDecadeLabel(locale, formatYear, date);
case 'year':
return formatYear(locale, date);
case 'month':
return formatMonthYear(locale, date);
default:
throw new Error(`Invalid view: ${view}.`);
}
})();
function renderLabel(date) {
const label = (() => {
switch (view) {
case 'century':
return getCenturyLabel(locale, formatYear, date);
case 'decade':
return getDecadeLabel(locale, formatYear, date);
case 'year':
return formatYear(locale, date);
case 'month':
return formatMonthYear(locale, date);
default:
throw new Error(`Invalid view: ${view}.`);
}
})();

return (
navigationLabel
? navigationLabel({ date, view, label })
: label
);
}

return (
<div
Expand Down Expand Up @@ -137,9 +149,15 @@ export default function Navigation({
style={{ flexGrow: 1 }}
type="button"
>
{navigationLabel
? navigationLabel({ date, view, label })
: label}
{renderLabel(activeStartDate)}
{showDoubleView && (
<>
{' '}
{' '}
{renderLabel(nextActiveStartDate)}
</>
)}
</button>
<button
aria-label={nextAriaLabel}
Expand Down Expand Up @@ -198,6 +216,7 @@ Navigation.propTypes = {
prevAriaLabel: PropTypes.string,
prevLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
setActiveStartDate: PropTypes.func.isRequired,
showDoubleView: PropTypes.bool,
view: isView.isRequired,
views: isViews.isRequired,
};
37 changes: 27 additions & 10 deletions src/Calendar/__tests__/Navigation.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ describe('Navigation', () => {
/>
);

const [, , drillUp] = component.children();
const drillUp = component.find('.react-calendar__navigation__label');

expect(drillUp.props.children.toString()).toBe('January 2017');
expect(drillUp.text()).toBe('January 2017');
});

it('displays proper title for year view', () => {
Expand All @@ -79,9 +79,9 @@ describe('Navigation', () => {
/>
);

const [, , drillUp] = component.children();
const drillUp = component.find('.react-calendar__navigation__label');

expect(drillUp.props.children.toString()).toBe('2017');
expect(drillUp.text()).toBe('2017');
});

it('displays proper title for decade view', () => {
Expand All @@ -95,9 +95,9 @@ describe('Navigation', () => {
/>
);

const [, , drillUp] = component.children();
const drillUp = component.find('.react-calendar__navigation__label');

expect(drillUp.props.children.toString()).toBe('2011 – 2020');
expect(drillUp.text()).toBe('2011 – 2020');
});

it('displays proper title for century view', () => {
Expand All @@ -111,9 +111,26 @@ describe('Navigation', () => {
/>
);

const [, drillUp] = component.children();
const drillUp = component.find('.react-calendar__navigation__label');

expect(drillUp.props.children.toString()).toBe('2001 – 2100');
expect(drillUp.text()).toBe('2001 – 2100');
});

it('displays proper title for month view given showDouble flags is set to true', () => {
const component = shallow(
<Navigation
activeStartDate={new Date(2017, 0, 1)}
drillUp={jest.fn()}
setActiveStartDate={jest.fn()}
showDoubleView
view="month"
views={allViews}
/>
);

const drillUp = component.find('.react-calendar__navigation__label');

expect(drillUp.text()).toBe('January 2017 – February 2017');
});

it('displays proper user-defined labels on prev2, prev, next and next2 buttons', () => {
Expand Down Expand Up @@ -522,9 +539,9 @@ describe('Navigation', () => {
/>
);

const [, , drillUp] = component.children();
const drillUp = component.find('.react-calendar__navigation__label');

expect(navigationLabel).toHaveBeenCalledWith({ date, view, label: 'January 2017' });
expect(drillUp.props.children.toString()).toBe(label);
expect(drillUp.text()).toBe(label);
});
});
Loading

0 comments on commit a046efd

Please sign in to comment.