Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement showDoubleView prop #248

Merged
merged 3 commits into from
Sep 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wojtekmaj thanks for the great lib!
why was showFixedNumberOfWeeks forced to true in double view?
mind if I PR to remove this?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because otherwise the UI would look quite bad with different amount of rows on each side.

Copy link
Contributor

@frankleng frankleng Jul 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wojtekmaj got it. so it's subjective. ex. priceline.com implements a dual view without locking down # of weeks.
are you open to a PR to remove this?

we can make showFixedNumberOfWeeks default to true when showDoubleView is true. but can be overridden explicitly. so it won't be a breaking change.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea.

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