[heatmap] set flow and state
This commit is contained in:
parent
3d4e5c106f
commit
a66b85a4af
130
dist/frappe-charts.esm.js
vendored
130
dist/frappe-charts.esm.js
vendored
@ -268,10 +268,6 @@ const DEFAULT_COLORS = {
|
|||||||
heatmap: HEATMAP_COLORS
|
heatmap: HEATMAP_COLORS
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of a number upto 2 decimal places.
|
|
||||||
* @param {Number} d Any number
|
|
||||||
*/
|
|
||||||
function floatTwo(d) {
|
function floatTwo(d) {
|
||||||
return parseFloat(d.toFixed(2));
|
return parseFloat(d.toFixed(2));
|
||||||
}
|
}
|
||||||
@ -1280,8 +1276,8 @@ class BaseChart {
|
|||||||
bindTooltip() {}
|
bindTooltip() {}
|
||||||
|
|
||||||
draw(onlyWidthChange=false, init=false) {
|
draw(onlyWidthChange=false, init=false) {
|
||||||
this.updateWidth();
|
|
||||||
this.calc(onlyWidthChange);
|
this.calc(onlyWidthChange);
|
||||||
|
this.updateWidth();
|
||||||
this.makeChartArea();
|
this.makeChartArea();
|
||||||
this.setupComponents();
|
this.setupComponents();
|
||||||
|
|
||||||
@ -2143,7 +2139,9 @@ class PieChart extends AggregationChart {
|
|||||||
|
|
||||||
const NO_OF_YEAR_MONTHS = 12;
|
const NO_OF_YEAR_MONTHS = 12;
|
||||||
const NO_OF_DAYS_IN_WEEK = 7;
|
const NO_OF_DAYS_IN_WEEK = 7;
|
||||||
|
|
||||||
const NO_OF_MILLIS = 1000;
|
const NO_OF_MILLIS = 1000;
|
||||||
|
const SEC_IN_DAY = 86400;
|
||||||
|
|
||||||
const MONTH_NAMES = ["January", "February", "March", "April", "May", "June",
|
const MONTH_NAMES = ["January", "February", "March", "April", "May", "June",
|
||||||
"July", "August", "September", "October", "November", "December"];
|
"July", "August", "September", "October", "November", "December"];
|
||||||
@ -2151,8 +2149,8 @@ const MONTH_NAMES = ["January", "February", "March", "April", "May", "June",
|
|||||||
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/11252167/6495043
|
// https://stackoverflow.com/a/11252167/6495043
|
||||||
function treatAsUtc(dateStr) {
|
function treatAsUtc(date) {
|
||||||
let result = new Date(dateStr);
|
let result = new Date(date);
|
||||||
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -2167,20 +2165,21 @@ function getDdMmYyyy(date) {
|
|||||||
].join('-');
|
].join('-');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clone(date) {
|
||||||
|
return new Date(date.getTime());
|
||||||
function getWeeksBetween(startDateStr, endDateStr) {
|
|
||||||
return Math.ceil(getDaysBetween(startDateStr, endDateStr) / 7);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDaysBetween(startDateStr, endDateStr) {
|
|
||||||
let millisecondsPerDay = 24 * 60 * 60 * 1000;
|
|
||||||
return (treatAsUtc(endDateStr) - treatAsUtc(startDateStr)) / millisecondsPerDay;
|
|
||||||
|
|
||||||
|
function getWeeksBetween(startDate, endDate) {
|
||||||
|
return Math.ceil(getDaysBetween(startDate, endDate) / NO_OF_DAYS_IN_WEEK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mutates
|
function getDaysBetween(startDate, endDate) {
|
||||||
function addDays(date, numberOfDays) {
|
let millisecondsPerDay = SEC_IN_DAY * NO_OF_MILLIS;
|
||||||
date.setDate(date.getDate() + numberOfDays);
|
return (treatAsUtc(endDate) - treatAsUtc(startDate)) / millisecondsPerDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMonthName(i, short=false) {
|
function getMonthName(i, short=false) {
|
||||||
@ -2188,6 +2187,20 @@ function getMonthName(i, short=false) {
|
|||||||
return short ? monthName.slice(0, 3) : monthName;
|
return short ? monthName.slice(0, 3) : monthName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mutates
|
||||||
|
function setDayToSunday(date) {
|
||||||
|
const day = date.getDay();
|
||||||
|
if(day !== NO_OF_DAYS_IN_WEEK) {
|
||||||
|
addDays(date, (-1) * day);
|
||||||
|
}
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutates
|
||||||
|
function addDays(date, numberOfDays) {
|
||||||
|
date.setDate(date.getDate() + numberOfDays);
|
||||||
|
}
|
||||||
|
|
||||||
function normalize(x) {
|
function normalize(x) {
|
||||||
// Calculates mantissa and exponent of a number
|
// Calculates mantissa and exponent of a number
|
||||||
// Returns normalized number and exponent
|
// Returns normalized number and exponent
|
||||||
@ -2413,30 +2426,8 @@ class Heatmap extends BaseChart {
|
|||||||
this.setup();
|
this.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(args) {
|
|
||||||
super.configure(args);
|
|
||||||
|
|
||||||
this.start = args.data.start;
|
|
||||||
|
|
||||||
this.today = new Date();
|
|
||||||
|
|
||||||
if(!this.start) {
|
|
||||||
this.start = new Date();
|
|
||||||
this.start.setFullYear( this.start.getFullYear() - 1 );
|
|
||||||
}
|
|
||||||
this.firstWeekStart = new Date(this.start.toDateString());
|
|
||||||
this.lastWeekStart = new Date(this.today.toDateString());
|
|
||||||
if(this.firstWeekStart.getDay() !== NO_OF_DAYS_IN_WEEK) {
|
|
||||||
addDays(this.firstWeekStart, (-1) * this.firstWeekStart.getDay());
|
|
||||||
}
|
|
||||||
if(this.lastWeekStart.getDay() !== NO_OF_DAYS_IN_WEEK) {
|
|
||||||
addDays(this.lastWeekStart, (-1) * this.lastWeekStart.getDay());
|
|
||||||
}
|
|
||||||
this.no_of_cols = getWeeksBetween(this.firstWeekStart + '', this.lastWeekStart + '') + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateWidth() {
|
updateWidth() {
|
||||||
this.baseWidth = (this.no_of_cols + 99) * COL_SIZE;
|
this.baseWidth = (this.state.noOfWeeks + 99) * COL_SIZE;
|
||||||
|
|
||||||
if(this.discreteDomains) {
|
if(this.discreteDomains) {
|
||||||
this.baseWidth += (COL_SIZE * NO_OF_YEAR_MONTHS);
|
this.baseWidth += (COL_SIZE * NO_OF_YEAR_MONTHS);
|
||||||
@ -2448,32 +2439,54 @@ class Heatmap extends BaseChart {
|
|||||||
this.domainLabelGroup = makeSVGGroup(this.drawArea,
|
this.domainLabelGroup = makeSVGGroup(this.drawArea,
|
||||||
'domain-label-group chart-label');
|
'domain-label-group chart-label');
|
||||||
|
|
||||||
this.dataGroups = makeSVGGroup(this.drawArea,
|
this.colGroups = makeSVGGroup(this.drawArea,
|
||||||
'data-groups',
|
'data-groups',
|
||||||
`translate(0, 20)`
|
`translate(0, 20)`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepareData(data=this.data) {
|
||||||
|
if(data.start && data.end && data.start > data.end) {
|
||||||
|
throw new Error('Start date cannot be greater than end date.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!data.start) {
|
||||||
|
data.start = new Date();
|
||||||
|
data.start.setFullYear( data.start.getFullYear() - 1 );
|
||||||
|
}
|
||||||
|
if(!data.end) { data.end = new Date(); }
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
calc() {
|
calc() {
|
||||||
this.distribution = calcDistribution(
|
let s = this.state;
|
||||||
|
|
||||||
|
s.start = this.data.start;
|
||||||
|
s.end = this.data.end;
|
||||||
|
|
||||||
|
s.firstWeekStart = setDayToSunday(clone(s.start));
|
||||||
|
s.noOfWeeks = getWeeksBetween(s.firstWeekStart, s.end);
|
||||||
|
s.distribution = calcDistribution(
|
||||||
Object.values(this.dataPoints), HEATMAP_DISTRIBUTION_SIZE);
|
Object.values(this.dataPoints), HEATMAP_DISTRIBUTION_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(data=this.data) {
|
update(data=this.data) {
|
||||||
this.data = this.prepareData(data);
|
this.data = this.prepareData(data);
|
||||||
this.draw();
|
this.draw();
|
||||||
|
this.bindTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.renderAllWeeksAndStoreXValues(this.no_of_cols);
|
this.renderAllWeeksAndStoreXValues(this.state.noOfWeeks);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAllWeeksAndStoreXValues(no_of_weeks) {
|
renderAllWeeksAndStoreXValues(no_of_weeks) {
|
||||||
// renderAllWeeksAndStoreXValues
|
// renderAllWeeksAndStoreXValues
|
||||||
this.domainLabelGroup.textContent = '';
|
this.domainLabelGroup.textContent = '';
|
||||||
this.dataGroups.textContent = '';
|
this.colGroups.textContent = '';
|
||||||
|
|
||||||
let currentWeekSunday = new Date(this.firstWeekStart);
|
let currentWeekSunday = new Date(this.state.firstWeekStart);
|
||||||
this.weekCol = 0;
|
this.weekCol = 0;
|
||||||
this.currentMonth = currentWeekSunday.getMonth();
|
this.currentMonth = currentWeekSunday.getMonth();
|
||||||
|
|
||||||
@ -2482,11 +2495,11 @@ class Heatmap extends BaseChart {
|
|||||||
this.monthWeeks[this.currentMonth] = 0;
|
this.monthWeeks[this.currentMonth] = 0;
|
||||||
|
|
||||||
for(var i = 0; i < no_of_weeks; i++) {
|
for(var i = 0; i < no_of_weeks; i++) {
|
||||||
let dataGroup, monthChange = 0;
|
let colGroup, monthChange = 0;
|
||||||
let day = new Date(currentWeekSunday);
|
let day = new Date(currentWeekSunday);
|
||||||
|
|
||||||
[dataGroup, monthChange] = this.getWeekSquaresGroup(day, this.weekCol);
|
[colGroup, monthChange] = this.getWeekSquaresGroup(day, this.weekCol);
|
||||||
this.dataGroups.appendChild(dataGroup);
|
this.colGroups.appendChild(colGroup);
|
||||||
this.weekCol += 1 + parseInt(this.discreteDomains && monthChange);
|
this.weekCol += 1 + parseInt(this.discreteDomains && monthChange);
|
||||||
this.monthWeeks[this.currentMonth]++;
|
this.monthWeeks[this.currentMonth]++;
|
||||||
if(monthChange) {
|
if(monthChange) {
|
||||||
@ -2501,12 +2514,15 @@ class Heatmap extends BaseChart {
|
|||||||
|
|
||||||
getWeekSquaresGroup(currentDate, index) {
|
getWeekSquaresGroup(currentDate, index) {
|
||||||
const step = 1;
|
const step = 1;
|
||||||
const todayTime = this.today.getTime();
|
|
||||||
|
let today = new Date();
|
||||||
|
|
||||||
|
const todayTime = today.getTime();
|
||||||
|
|
||||||
let monthChange = 0;
|
let monthChange = 0;
|
||||||
let weekColChange = 0;
|
let weekColChange = 0;
|
||||||
|
|
||||||
let dataGroup = makeSVGGroup(this.dataGroups, 'data-group');
|
let colGroup = makeSVGGroup(this.colGroups, 'data-group');
|
||||||
|
|
||||||
for(var y = 0, i = 0; i < NO_OF_DAYS_IN_WEEK; i += step, y += COL_SIZE) {
|
for(var y = 0, i = 0; i < NO_OF_DAYS_IN_WEEK; i += step, y += COL_SIZE) {
|
||||||
let dataValue = 0;
|
let dataValue = 0;
|
||||||
@ -2524,7 +2540,7 @@ class Heatmap extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(dataValue) {
|
if(dataValue) {
|
||||||
colorIndex = getMaxCheckpoint(dataValue, this.distribution);
|
colorIndex = getMaxCheckpoint(dataValue, this.state.distribution);
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = (index + weekColChange) * COL_SIZE;
|
let x = (index + weekColChange) * COL_SIZE;
|
||||||
@ -2538,7 +2554,7 @@ class Heatmap extends BaseChart {
|
|||||||
let heatSquare = makeHeatSquare('day', x, y, HEATMAP_SQUARE_SIZE,
|
let heatSquare = makeHeatSquare('day', x, y, HEATMAP_SQUARE_SIZE,
|
||||||
this.colors[colorIndex], dataAttr);
|
this.colors[colorIndex], dataAttr);
|
||||||
|
|
||||||
dataGroup.appendChild(heatSquare);
|
colGroup.appendChild(heatSquare);
|
||||||
|
|
||||||
let nextDate = new Date(currentDate);
|
let nextDate = new Date(currentDate);
|
||||||
addDays(nextDate, 1);
|
addDays(nextDate, 1);
|
||||||
@ -2556,12 +2572,12 @@ class Heatmap extends BaseChart {
|
|||||||
currentDate = nextDate;
|
currentDate = nextDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [dataGroup, monthChange];
|
return [colGroup, monthChange];
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMonthLabels() {
|
renderMonthLabels() {
|
||||||
// this.first_month_label = 1;
|
// this.first_month_label = 1;
|
||||||
// if (this.firstWeekStart.getDate() > 8) {
|
// if (this.state.firstWeekStart.getDate() > 8) {
|
||||||
// this.first_month_label = 0;
|
// this.first_month_label = 0;
|
||||||
// }
|
// }
|
||||||
// this.last_month_label = 1;
|
// this.last_month_label = 1;
|
||||||
@ -2609,11 +2625,6 @@ class Heatmap extends BaseChart {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
update(data) {
|
|
||||||
super.update(data);
|
|
||||||
this.bindTooltip();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function dataPrep(data, type) {
|
function dataPrep(data, type) {
|
||||||
@ -3285,7 +3296,6 @@ class AxisChart extends BaseChart {
|
|||||||
// removeDataPoint(index = 0) {}
|
// removeDataPoint(index = 0) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// import MultiAxisChart from './charts/MultiAxisChart';
|
|
||||||
const chartTypes = {
|
const chartTypes = {
|
||||||
// multiaxis: MultiAxisChart,
|
// multiaxis: MultiAxisChart,
|
||||||
percentage: PercentageChart,
|
percentage: PercentageChart,
|
||||||
|
|||||||
2
dist/frappe-charts.min.cjs.js
vendored
2
dist/frappe-charts.min.cjs.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.esm.js
vendored
2
dist/frappe-charts.min.esm.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.iife.js
vendored
2
dist/frappe-charts.min.iife.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.iife.js.map
vendored
2
dist/frappe-charts.min.iife.js.map
vendored
File diff suppressed because one or more lines are too long
@ -1,4 +1,4 @@
|
|||||||
import { MONTH_NAMES_SHORT } from '../../../src/js/utils/date-utils';
|
import { DAYS_IN_YEAR, SEC_IN_DAY, MONTH_NAMES_SHORT, clone, timestampToMidnight, timestampSec } from '../../../src/js/utils/date-utils';
|
||||||
|
|
||||||
// Composite Chart
|
// Composite Chart
|
||||||
// ================================================================================
|
// ================================================================================
|
||||||
@ -175,18 +175,22 @@ export const moonData = {
|
|||||||
// ================================================================================
|
// ================================================================================
|
||||||
|
|
||||||
let today = new Date();
|
let today = new Date();
|
||||||
let start = new Date(today.getTime());
|
let start = clone(today);
|
||||||
let end = new Date(today.getTime());
|
let end = clone(today);
|
||||||
start.setFullYear( start.getFullYear() - 2 );
|
start.setFullYear( start.getFullYear() - 2 );
|
||||||
end.setFullYear( start.getFullYear() - 1 );
|
end.setFullYear( end.getFullYear() - 1 );
|
||||||
|
|
||||||
export let dataPoints = {};
|
export let dataPoints = {};
|
||||||
let current_date = new Date();
|
|
||||||
let timestamp = current_date.getTime()/1000;
|
let startTs = timestampSec(start);
|
||||||
timestamp = Math.floor(timestamp - (timestamp % 86400)).toFixed(1); // convert to midnight
|
let endTs = timestampSec(end);
|
||||||
for (var i = 0; i< 375; i++) {
|
|
||||||
dataPoints[parseInt(timestamp)] = Math.floor(Math.random() * 5);
|
startTs = timestampToMidnight(startTs);
|
||||||
timestamp = Math.floor(timestamp - 86400).toFixed(1);
|
endTs = timestampToMidnight(endTs, true);
|
||||||
|
|
||||||
|
while (startTs < endTs) {
|
||||||
|
dataPoints[parseInt(startTs)] = Math.floor(Math.random() * 5);
|
||||||
|
startTs += SEC_IN_DAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const heatmapData = {
|
export const heatmapData = {
|
||||||
|
|||||||
2
docs/assets/js/frappe-charts.min.js
vendored
2
docs/assets/js/frappe-charts.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
48
docs/assets/js/index.min.js
vendored
48
docs/assets/js/index.min.js
vendored
@ -81,14 +81,33 @@ function shuffle(array) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var NO_OF_MILLIS = 1000;
|
||||||
|
var SEC_IN_DAY = 86400;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var MONTH_NAMES_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
var MONTH_NAMES_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||||
|
|
||||||
// https://stackoverflow.com/a/11252167/6495043
|
|
||||||
|
|
||||||
|
|
||||||
|
function clone(date) {
|
||||||
|
return new Date(date.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
function timestampSec(date) {
|
||||||
|
return date.getTime() / NO_OF_MILLIS;
|
||||||
|
}
|
||||||
|
|
||||||
|
function timestampToMidnight(timestamp) {
|
||||||
|
var roundAhead = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
|
||||||
|
|
||||||
|
var midnightTs = Math.floor(timestamp - timestamp % SEC_IN_DAY);
|
||||||
|
if (roundAhead) {
|
||||||
|
return midnightTs + SEC_IN_DAY;
|
||||||
|
}
|
||||||
|
return midnightTs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -97,8 +116,9 @@ var MONTH_NAMES_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
|
|||||||
|
|
||||||
// mutates
|
// mutates
|
||||||
|
|
||||||
// Composite Chart
|
|
||||||
// ================================================================================
|
// mutates
|
||||||
|
|
||||||
var reportCountList = [152, 222, 199, 287, 534, 709, 1179, 1256, 1632, 1856, 1850];
|
var reportCountList = [152, 222, 199, 287, 534, 709, 1179, 1256, 1632, 1856, 1850];
|
||||||
|
|
||||||
var lineCompositeData = {
|
var lineCompositeData = {
|
||||||
@ -209,18 +229,22 @@ var moonData = {
|
|||||||
// ================================================================================
|
// ================================================================================
|
||||||
|
|
||||||
var today = new Date();
|
var today = new Date();
|
||||||
var start = new Date(today.getTime());
|
var start = clone(today);
|
||||||
var end = new Date(today.getTime());
|
var end = clone(today);
|
||||||
start.setFullYear(start.getFullYear() - 2);
|
start.setFullYear(start.getFullYear() - 2);
|
||||||
end.setFullYear(start.getFullYear() - 1);
|
end.setFullYear(end.getFullYear() - 1);
|
||||||
|
|
||||||
var dataPoints = {};
|
var dataPoints = {};
|
||||||
var current_date = new Date();
|
|
||||||
var timestamp = current_date.getTime() / 1000;
|
var startTs = timestampSec(start);
|
||||||
timestamp = Math.floor(timestamp - timestamp % 86400).toFixed(1); // convert to midnight
|
var endTs = timestampSec(end);
|
||||||
for (var i = 0; i < 375; i++) {
|
|
||||||
dataPoints[parseInt(timestamp)] = Math.floor(Math.random() * 5);
|
startTs = timestampToMidnight(startTs);
|
||||||
timestamp = Math.floor(timestamp - 86400).toFixed(1);
|
endTs = timestampToMidnight(endTs, true);
|
||||||
|
|
||||||
|
while (startTs < endTs) {
|
||||||
|
dataPoints[parseInt(startTs)] = Math.floor(Math.random() * 5);
|
||||||
|
startTs += SEC_IN_DAY;
|
||||||
}
|
}
|
||||||
|
|
||||||
var heatmapData = {
|
var heatmapData = {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -112,8 +112,8 @@ export default class BaseChart {
|
|||||||
bindTooltip() {}
|
bindTooltip() {}
|
||||||
|
|
||||||
draw(onlyWidthChange=false, init=false) {
|
draw(onlyWidthChange=false, init=false) {
|
||||||
this.updateWidth();
|
|
||||||
this.calc(onlyWidthChange);
|
this.calc(onlyWidthChange);
|
||||||
|
this.updateWidth();
|
||||||
this.makeChartArea();
|
this.makeChartArea();
|
||||||
this.setupComponents();
|
this.setupComponents();
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import BaseChart from './BaseChart';
|
import BaseChart from './BaseChart';
|
||||||
import { makeSVGGroup, makeHeatSquare, makeText } from '../utils/draw';
|
import { makeSVGGroup, makeHeatSquare, makeText } from '../utils/draw';
|
||||||
import { addDays, getDdMmYyyy, getWeeksBetween, getMonthName, clone,
|
import { addDays, setDayToSunday, getDdMmYyyy, getWeeksBetween, getMonthName, clone,
|
||||||
NO_OF_MILLIS, NO_OF_YEAR_MONTHS, NO_OF_DAYS_IN_WEEK } from '../utils/date-utils';
|
NO_OF_MILLIS, NO_OF_YEAR_MONTHS, NO_OF_DAYS_IN_WEEK } from '../utils/date-utils';
|
||||||
import { calcDistribution, getMaxCheckpoint } from '../utils/intervals';
|
import { calcDistribution, getMaxCheckpoint } from '../utils/intervals';
|
||||||
import { HEATMAP_DISTRIBUTION_SIZE, HEATMAP_SQUARE_SIZE,
|
import { HEATMAP_DISTRIBUTION_SIZE, HEATMAP_SQUARE_SIZE,
|
||||||
@ -20,30 +20,8 @@ export default class Heatmap extends BaseChart {
|
|||||||
this.setup();
|
this.setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(args) {
|
|
||||||
super.configure(args);
|
|
||||||
|
|
||||||
this.start = args.data.start;
|
|
||||||
|
|
||||||
this.today = new Date();
|
|
||||||
|
|
||||||
if(!this.start) {
|
|
||||||
this.start = new Date();
|
|
||||||
this.start.setFullYear( this.start.getFullYear() - 1 );
|
|
||||||
}
|
|
||||||
this.firstWeekStart = new Date(this.start.toDateString());
|
|
||||||
this.lastWeekStart = new Date(this.today.toDateString());
|
|
||||||
if(this.firstWeekStart.getDay() !== NO_OF_DAYS_IN_WEEK) {
|
|
||||||
addDays(this.firstWeekStart, (-1) * this.firstWeekStart.getDay());
|
|
||||||
}
|
|
||||||
if(this.lastWeekStart.getDay() !== NO_OF_DAYS_IN_WEEK) {
|
|
||||||
addDays(this.lastWeekStart, (-1) * this.lastWeekStart.getDay());
|
|
||||||
}
|
|
||||||
this.no_of_cols = getWeeksBetween(this.firstWeekStart + '', this.lastWeekStart + '') + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateWidth() {
|
updateWidth() {
|
||||||
this.baseWidth = (this.no_of_cols + 99) * COL_SIZE;
|
this.baseWidth = (this.state.noOfWeeks + 99) * COL_SIZE;
|
||||||
|
|
||||||
if(this.discreteDomains) {
|
if(this.discreteDomains) {
|
||||||
this.baseWidth += (COL_SIZE * NO_OF_YEAR_MONTHS);
|
this.baseWidth += (COL_SIZE * NO_OF_YEAR_MONTHS);
|
||||||
@ -55,32 +33,54 @@ export default class Heatmap extends BaseChart {
|
|||||||
this.domainLabelGroup = makeSVGGroup(this.drawArea,
|
this.domainLabelGroup = makeSVGGroup(this.drawArea,
|
||||||
'domain-label-group chart-label');
|
'domain-label-group chart-label');
|
||||||
|
|
||||||
this.dataGroups = makeSVGGroup(this.drawArea,
|
this.colGroups = makeSVGGroup(this.drawArea,
|
||||||
'data-groups',
|
'data-groups',
|
||||||
`translate(0, 20)`
|
`translate(0, 20)`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepareData(data=this.data) {
|
||||||
|
if(data.start && data.end && data.start > data.end) {
|
||||||
|
throw new Error('Start date cannot be greater than end date.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!data.start) {
|
||||||
|
data.start = new Date();
|
||||||
|
data.start.setFullYear( data.start.getFullYear() - 1 );
|
||||||
|
}
|
||||||
|
if(!data.end) { data.end = new Date(); }
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
calc() {
|
calc() {
|
||||||
this.distribution = calcDistribution(
|
let s = this.state;
|
||||||
|
|
||||||
|
s.start = this.data.start;
|
||||||
|
s.end = this.data.end;
|
||||||
|
|
||||||
|
s.firstWeekStart = setDayToSunday(clone(s.start));
|
||||||
|
s.noOfWeeks = getWeeksBetween(s.firstWeekStart, s.end);
|
||||||
|
s.distribution = calcDistribution(
|
||||||
Object.values(this.dataPoints), HEATMAP_DISTRIBUTION_SIZE);
|
Object.values(this.dataPoints), HEATMAP_DISTRIBUTION_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(data=this.data) {
|
update(data=this.data) {
|
||||||
this.data = this.prepareData(data);
|
this.data = this.prepareData(data);
|
||||||
this.draw();
|
this.draw();
|
||||||
|
this.bindTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
this.renderAllWeeksAndStoreXValues(this.no_of_cols);
|
this.renderAllWeeksAndStoreXValues(this.state.noOfWeeks);
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAllWeeksAndStoreXValues(no_of_weeks) {
|
renderAllWeeksAndStoreXValues(no_of_weeks) {
|
||||||
// renderAllWeeksAndStoreXValues
|
// renderAllWeeksAndStoreXValues
|
||||||
this.domainLabelGroup.textContent = '';
|
this.domainLabelGroup.textContent = '';
|
||||||
this.dataGroups.textContent = '';
|
this.colGroups.textContent = '';
|
||||||
|
|
||||||
let currentWeekSunday = new Date(this.firstWeekStart);
|
let currentWeekSunday = new Date(this.state.firstWeekStart);
|
||||||
this.weekCol = 0;
|
this.weekCol = 0;
|
||||||
this.currentMonth = currentWeekSunday.getMonth();
|
this.currentMonth = currentWeekSunday.getMonth();
|
||||||
|
|
||||||
@ -90,11 +90,11 @@ export default class Heatmap extends BaseChart {
|
|||||||
this.monthWeeks[this.currentMonth] = 0;
|
this.monthWeeks[this.currentMonth] = 0;
|
||||||
|
|
||||||
for(var i = 0; i < no_of_weeks; i++) {
|
for(var i = 0; i < no_of_weeks; i++) {
|
||||||
let dataGroup, monthChange = 0;
|
let colGroup, monthChange = 0;
|
||||||
let day = new Date(currentWeekSunday);
|
let day = new Date(currentWeekSunday);
|
||||||
|
|
||||||
[dataGroup, monthChange] = this.getWeekSquaresGroup(day, this.weekCol);
|
[colGroup, monthChange] = this.getWeekSquaresGroup(day, this.weekCol);
|
||||||
this.dataGroups.appendChild(dataGroup);
|
this.colGroups.appendChild(colGroup);
|
||||||
this.weekCol += 1 + parseInt(this.discreteDomains && monthChange);
|
this.weekCol += 1 + parseInt(this.discreteDomains && monthChange);
|
||||||
this.monthWeeks[this.currentMonth]++;
|
this.monthWeeks[this.currentMonth]++;
|
||||||
if(monthChange) {
|
if(monthChange) {
|
||||||
@ -109,12 +109,15 @@ export default class Heatmap extends BaseChart {
|
|||||||
|
|
||||||
getWeekSquaresGroup(currentDate, index) {
|
getWeekSquaresGroup(currentDate, index) {
|
||||||
const step = 1;
|
const step = 1;
|
||||||
const todayTime = this.today.getTime();
|
|
||||||
|
let today = new Date();
|
||||||
|
|
||||||
|
const todayTime = today.getTime();
|
||||||
|
|
||||||
let monthChange = 0;
|
let monthChange = 0;
|
||||||
let weekColChange = 0;
|
let weekColChange = 0;
|
||||||
|
|
||||||
let dataGroup = makeSVGGroup(this.dataGroups, 'data-group');
|
let colGroup = makeSVGGroup(this.colGroups, 'data-group');
|
||||||
|
|
||||||
for(var y = 0, i = 0; i < NO_OF_DAYS_IN_WEEK; i += step, y += COL_SIZE) {
|
for(var y = 0, i = 0; i < NO_OF_DAYS_IN_WEEK; i += step, y += COL_SIZE) {
|
||||||
let dataValue = 0;
|
let dataValue = 0;
|
||||||
@ -132,7 +135,7 @@ export default class Heatmap extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(dataValue) {
|
if(dataValue) {
|
||||||
colorIndex = getMaxCheckpoint(dataValue, this.distribution);
|
colorIndex = getMaxCheckpoint(dataValue, this.state.distribution);
|
||||||
}
|
}
|
||||||
|
|
||||||
let x = (index + weekColChange) * COL_SIZE;
|
let x = (index + weekColChange) * COL_SIZE;
|
||||||
@ -146,7 +149,7 @@ export default class Heatmap extends BaseChart {
|
|||||||
let heatSquare = makeHeatSquare('day', x, y, HEATMAP_SQUARE_SIZE,
|
let heatSquare = makeHeatSquare('day', x, y, HEATMAP_SQUARE_SIZE,
|
||||||
this.colors[colorIndex], dataAttr);
|
this.colors[colorIndex], dataAttr);
|
||||||
|
|
||||||
dataGroup.appendChild(heatSquare);
|
colGroup.appendChild(heatSquare);
|
||||||
|
|
||||||
let nextDate = new Date(currentDate);
|
let nextDate = new Date(currentDate);
|
||||||
addDays(nextDate, 1);
|
addDays(nextDate, 1);
|
||||||
@ -164,12 +167,12 @@ export default class Heatmap extends BaseChart {
|
|||||||
currentDate = nextDate;
|
currentDate = nextDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [dataGroup, monthChange];
|
return [colGroup, monthChange];
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMonthLabels() {
|
renderMonthLabels() {
|
||||||
// this.first_month_label = 1;
|
// this.first_month_label = 1;
|
||||||
// if (this.firstWeekStart.getDate() > 8) {
|
// if (this.state.firstWeekStart.getDate() > 8) {
|
||||||
// this.first_month_label = 0;
|
// this.first_month_label = 0;
|
||||||
// }
|
// }
|
||||||
// this.last_month_label = 1;
|
// this.last_month_label = 1;
|
||||||
@ -217,9 +220,4 @@ export default class Heatmap extends BaseChart {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
update(data) {
|
|
||||||
super.update(data);
|
|
||||||
this.bindTooltip();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
export const NO_OF_YEAR_MONTHS = 12;
|
export const NO_OF_YEAR_MONTHS = 12;
|
||||||
export const NO_OF_DAYS_IN_WEEK = 7;
|
export const NO_OF_DAYS_IN_WEEK = 7;
|
||||||
|
export const DAYS_IN_YEAR = 375;
|
||||||
export const NO_OF_MILLIS = 1000;
|
export const NO_OF_MILLIS = 1000;
|
||||||
|
export const SEC_IN_DAY = 86400;
|
||||||
|
|
||||||
export const MONTH_NAMES = ["January", "February", "March", "April", "May", "June",
|
export const MONTH_NAMES = ["January", "February", "March", "April", "May", "June",
|
||||||
"July", "August", "September", "October", "November", "December"];
|
"July", "August", "September", "October", "November", "December"];
|
||||||
@ -10,8 +12,8 @@ export const MONTH_NAMES = ["January", "February", "March", "April", "May", "Jun
|
|||||||
export const MONTH_NAMES_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
export const MONTH_NAMES_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
||||||
|
|
||||||
// https://stackoverflow.com/a/11252167/6495043
|
// https://stackoverflow.com/a/11252167/6495043
|
||||||
function treatAsUtc(dateStr) {
|
function treatAsUtc(date) {
|
||||||
let result = new Date(dateStr);
|
let result = new Date(date);
|
||||||
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -30,21 +32,42 @@ export function clone(date) {
|
|||||||
return new Date(date.getTime());
|
return new Date(date.getTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWeeksBetween(startDateStr, endDateStr) {
|
export function timestampSec(date) {
|
||||||
return Math.ceil(getDaysBetween(startDateStr, endDateStr) / 7);
|
return date.getTime()/NO_OF_MILLIS;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDaysBetween(startDateStr, endDateStr) {
|
export function timestampToMidnight(timestamp, roundAhead = false) {
|
||||||
let millisecondsPerDay = 24 * 60 * 60 * 1000;
|
let midnightTs = Math.floor(timestamp - (timestamp % SEC_IN_DAY));
|
||||||
return (treatAsUtc(endDateStr) - treatAsUtc(startDateStr)) / millisecondsPerDay;
|
if(roundAhead) {
|
||||||
|
return midnightTs + SEC_IN_DAY;
|
||||||
|
}
|
||||||
|
return midnightTs;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mutates
|
export function getWeeksBetween(startDate, endDate) {
|
||||||
export function addDays(date, numberOfDays) {
|
return Math.ceil(getDaysBetween(startDate, endDate) / NO_OF_DAYS_IN_WEEK);
|
||||||
date.setDate(date.getDate() + numberOfDays);
|
}
|
||||||
|
|
||||||
|
export function getDaysBetween(startDate, endDate) {
|
||||||
|
let millisecondsPerDay = SEC_IN_DAY * NO_OF_MILLIS;
|
||||||
|
return (treatAsUtc(endDate) - treatAsUtc(startDate)) / millisecondsPerDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMonthName(i, short=false) {
|
export function getMonthName(i, short=false) {
|
||||||
let monthName = MONTH_NAMES[i];
|
let monthName = MONTH_NAMES[i];
|
||||||
return short ? monthName.slice(0, 3) : monthName;
|
return short ? monthName.slice(0, 3) : monthName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mutates
|
||||||
|
export function setDayToSunday(date) {
|
||||||
|
const day = date.getDay();
|
||||||
|
if(day !== NO_OF_DAYS_IN_WEEK) {
|
||||||
|
addDays(date, (-1) * day);
|
||||||
|
}
|
||||||
|
return date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutates
|
||||||
|
export function addDays(date, numberOfDays) {
|
||||||
|
date.setDate(date.getDate() + numberOfDays);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user