Skip to content

Commit

Permalink
feat(calendar): init support for multiple years
Browse files Browse the repository at this point in the history
  • Loading branch information
Raphael Benitte committed May 10, 2016
1 parent a0473e4 commit 1bbb2b0
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 49 deletions.
2 changes: 2 additions & 0 deletions src/components/charts/calendar/Calendar.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Calendar extends Component {

render() {
const {
from, to,
direction,
daySpacing, dayBorderWidth, dayBorderColor,
monthBorderWidth, monthBorderColor,
Expand All @@ -34,6 +35,7 @@ class Calendar extends Component {

const { days, months } = this.calendarLayout.compute({
width, height,
from, to,
direction,
daySpacing
});
Expand Down
37 changes: 16 additions & 21 deletions src/components/charts/calendar/CalendarD3.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@ import { findDOMNode } from 'react-dom';
import d3 from 'd3';
import _ from 'lodash';
import Nivo from '../../../Nivo';
import decoratorsFromReactChildren from '../../../lib/decoratorsFromReactChildren';
import CalendarLayout from '../../../lib/charts/calendar/CalendarLayout';
import { calendarPropTypes, calendarDefaultProps } from './CalendarProps';


const color = d3.scale.category20();
const color = d3.scale.category20b();

class CalendarD3 extends Component {
constructor(props) {
Expand All @@ -27,7 +26,9 @@ class CalendarD3 extends Component {

renderD3(props) {
const {
from, to,
direction,
yearSpacing,
daySpacing, dayBorderWidth, dayBorderColor,
monthBorderWidth, monthBorderColor,
transitionDuration, transitionEasing, transitionStaggering
Expand All @@ -49,29 +50,30 @@ class CalendarD3 extends Component {

const { days, months } = this.calendarLayout.compute({
width, height,
from, to,
direction,
yearSpacing,
daySpacing
});

const dayNodes = wrapper.selectAll('.nivo_calendar_day').data(days, d => d.date);

const rects = wrapper.selectAll('.nivo_calendar_day').data(days, d => d.date);

rects
dayNodes
.enter().append('rect')
.attr('class', 'nivo_calendar_day')
.attr('class', d => `nivo_calendar_day nivo_calendar_day-month-${d.date.getMonth()}`)
.attr('width', d => d.size)
.attr('height', d => d.size)
.attr('x', 0)
.attr('y', 0)
.style({
opacity: 0,
fill: d => color(d.date.getMonth()),
fill: d => color(`${d.date.getFullYear()}.${d.date.getMonth()}`),
stroke: dayBorderColor,
'stroke-width': dayBorderWidth,
})
;

rects
dayNodes
.transition()
.duration(transitionDuration)
.ease(transitionEasing)
Expand All @@ -82,16 +84,16 @@ class CalendarD3 extends Component {
.attr('y', d => d.y)
.style({
opacity: 1,
fill: d => color(d.date.getMonth()),
fill: d => color(`${d.date.getFullYear()}.${d.date.getMonth()}`),
stroke: dayBorderColor,
'stroke-width': dayBorderWidth,
})
;

return;
const monthNodes = wrapper.selectAll('.nivo_calendar_month').data(months, d => d.date);

const paths = wrapper.selectAll('.nivo_calendar_month').data(months, d => d.date);

paths.enter().append('path')
monthNodes.enter().append('path')
.attr('class', 'nivo_calendar_month')
.style({
fill: 'none',
Expand All @@ -101,37 +103,30 @@ class CalendarD3 extends Component {
.attr('d', d => d.path)
;

paths
monthNodes
.transition()
.duration(transitionDuration)
.ease(transitionEasing)
.delay((d, i) => i * 30 * transitionStaggering)
.delay(d => (d.date.getMonth() + 1) * 30 * transitionStaggering)
.style({
stroke: monthBorderColor,
'stroke-width': monthBorderWidth,
})
.attr('d', d => d.path)
;

this.decorators.forEach(decorator => {
});
}

componentWillMount() {
this.calendarLayout = CalendarLayout();
}

shouldComponentUpdate(nextProps, nextState) {
this.decorators = decoratorsFromReactChildren(nextProps.children, 'decorateCalendar');

this.renderD3(nextProps, nextState);

return false;
}

componentDidMount() {
this.decorators = decoratorsFromReactChildren(this.props.children, 'decorateCalendar');

this.renderD3(this.props, this.state);
}

Expand Down
6 changes: 5 additions & 1 deletion src/components/charts/calendar/CalendarProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
} from '../../../constants/directions';


const { object, number, string, any, func, oneOf } = PropTypes;
const { number, string, oneOf, oneOfType, instanceOf } = PropTypes;


/**
Expand All @@ -29,6 +29,9 @@ export const calendarPropTypes = {
width: number.isRequired,
height: number.isRequired,
margin,
from: oneOfType([string, instanceOf(Date)]).isRequired,
to: oneOfType([string, instanceOf(Date)]).isRequired,
yearSpacing: number.isRequired,
direction: oneOf([DIRECTION_HORIZONTAL, DIRECTION_VERTICAL]),
// days
daySpacing: number.isRequired,
Expand All @@ -54,6 +57,7 @@ export const calendarPropTypes = {
export const calendarDefaultProps = {
margin: Nivo.defaults.margin,
direction: DIRECTION_HORIZONTAL,
yearSpacing: 20,
// days
daySpacing: 0,
dayBorderWidth: 1,
Expand Down
76 changes: 49 additions & 27 deletions src/lib/charts/calendar/CalendarLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,58 +50,80 @@ const monthPathGenerator = (date, cellSize, daySpacing, direction) => {
const CalendarLayout = () => {
return {
/**
* @param {number} width
* @param {number} height
* @param {string} direction
* @param {number} daySpacing
* @param {number} width
* @param {number} height
* @param {string|Date} from
* @param {string|Date} to
* @param {string} direction
* @param {number} yearSpacing
* @param {number} daySpacing
* @returns {object}
*/
compute({
width, height,
from, to,
direction,
yearSpacing,
daySpacing
}) {

// time related data
const startDate = new Date(2005, 0, 1);
const endDate = new Date(2006, 0, 1);
const days = d3.time.days(startDate, endDate);
const months = d3.time.months(startDate, endDate);
const weekCount = d3.time.weekOfYear(days[days.length - 1]);
const fromDate = _.isDate(from) ? from : new Date(from);
const toDate = _.isDate(to) ? to : new Date(to);
let years = d3.range(fromDate.getFullYear(), toDate.getFullYear() + 1);
const maxWeeks = d3.max(years, year => d3.time.weeks(new Date(year, 0, 1), new Date(year + 1, 0, 1)).length) + 1;

let cellSize;
if (direction === DIRECTION_HORIZONTAL) {
cellSize = (width - daySpacing * (weekCount + 2)) / (weekCount + 1);
const hCellSize = (width - daySpacing * (maxWeeks + 1)) / maxWeeks;
const vCellSize = (height - (years.length - 1) * yearSpacing - years.length * (8 * daySpacing)) / (years.length * 7);
cellSize = Math.min(hCellSize, vCellSize);
} else {
cellSize = (height - daySpacing * (weekCount + 2)) / (weekCount + 1);
cellSize = (height - daySpacing * (maxWeeks + 1)) / maxWeeks;
}

let cellPosition;
if (direction === DIRECTION_HORIZONTAL) {
cellPosition = d => ({
cellPosition = (d, yearIndex) => ({
x: d3.time.weekOfYear(d) * (cellSize + daySpacing) + daySpacing / 2,
y: d.getDay() * (cellSize + daySpacing) + daySpacing / 2,
y: d.getDay() * (cellSize + daySpacing) + daySpacing / 2 + yearIndex * (yearSpacing + 7 * cellSize + 8 * daySpacing),
});
} else {
cellPosition = d => ({
x: d.getDay() * (cellSize + daySpacing) + daySpacing / 2,
cellPosition = (d, yearIndex) => ({
x: d.getDay() * (cellSize + daySpacing) + daySpacing / 2 + yearIndex * (yearSpacing + 7 * cellSize + 8 * daySpacing),
y: d3.time.weekOfYear(d) * (cellSize + daySpacing) + daySpacing / 2,
});
}

let dayNodes = [];
let monthNodes = [];

years = years.forEach((year, i) => {
const yearStart = new Date(year, 0, 1);
const yearEnd = new Date(year + 1, 0, 1);

dayNodes = dayNodes.concat(d3.time.days(yearStart, yearEnd)
.map(dayDate => {
return _.assign({
date: dayDate,
size: cellSize,
}, cellPosition(dayDate, i));
})
);

monthNodes = monthNodes.concat(d3.time.months(yearStart, yearEnd)
.map(monthDate => {
return {
date: monthDate,
path: monthPathGenerator(monthDate, cellSize, daySpacing, direction),
};
})
);
});

return {
days: days.map(dayDate => {
return _.assign({
date: dayDate,
size: cellSize,
}, cellPosition(dayDate));
}),
months: months.map(monthDate => {
return {
date: monthDate,
path: monthPathGenerator(monthDate, cellSize, daySpacing, direction),
}
})
days: dayNodes,
months: monthNodes,
};
}
}
Expand Down

0 comments on commit 1bbb2b0

Please sign in to comment.