[heatmap] fix update incr, col issues; discrete, add month names
This commit is contained in:
parent
cf5985fd9a
commit
3877357bb3
235
dist/frappe-charts.esm.js
vendored
235
dist/frappe-charts.esm.js
vendored
@ -627,6 +627,7 @@ function makeText(className, x, y, content, fontSize = FONT_SIZE) {
|
|||||||
y: y,
|
y: y,
|
||||||
dy: (fontSize / 2) + 'px',
|
dy: (fontSize / 2) + 'px',
|
||||||
'font-size': fontSize + 'px',
|
'font-size': fontSize + 'px',
|
||||||
|
fill: FONT_FILL,
|
||||||
innerHTML: content
|
innerHTML: content
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1650,6 +1651,85 @@ class AggregationChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Playing around with dates
|
||||||
|
|
||||||
|
const NO_OF_YEAR_MONTHS = 12;
|
||||||
|
const NO_OF_DAYS_IN_WEEK = 7;
|
||||||
|
|
||||||
|
const NO_OF_MILLIS = 1000;
|
||||||
|
const SEC_IN_DAY = 86400;
|
||||||
|
|
||||||
|
const MONTH_NAMES = ["January", "February", "March", "April", "May", "June",
|
||||||
|
"July", "August", "September", "October", "November", "December"];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/11252167/6495043
|
||||||
|
function treatAsUtc(date) {
|
||||||
|
let result = new Date(date);
|
||||||
|
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getYyyyMmDd(date) {
|
||||||
|
let dd = date.getDate();
|
||||||
|
let mm = date.getMonth() + 1; // getMonth() is zero-based
|
||||||
|
return [
|
||||||
|
date.getFullYear(),
|
||||||
|
(mm>9 ? '' : '0') + mm,
|
||||||
|
(dd>9 ? '' : '0') + dd
|
||||||
|
].join('-');
|
||||||
|
}
|
||||||
|
|
||||||
|
function clone(date) {
|
||||||
|
return new Date(date.getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function getWeeksBetween(startDate, endDate) {
|
||||||
|
let weekStartDate = setDayToSunday(startDate);
|
||||||
|
return Math.ceil(getDaysBetween(weekStartDate, endDate) / NO_OF_DAYS_IN_WEEK);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDaysBetween(startDate, endDate) {
|
||||||
|
let millisecondsPerDay = SEC_IN_DAY * NO_OF_MILLIS;
|
||||||
|
return (treatAsUtc(endDate) - treatAsUtc(startDate)) / millisecondsPerDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
function areInSameMonth(startDate, endDate) {
|
||||||
|
return startDate.getMonth() === endDate.getMonth()
|
||||||
|
&& startDate.getFullYear() === endDate.getFullYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMonthName(i, short=false) {
|
||||||
|
let monthName = MONTH_NAMES[i];
|
||||||
|
return short ? monthName.slice(0, 3) : monthName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLastDateInMonth (month, year) {
|
||||||
|
return new Date(year, month + 1, 0); // 0: last day in previous month
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutates
|
||||||
|
function setDayToSunday(date) {
|
||||||
|
let newDate = clone(date);
|
||||||
|
const day = newDate.getDay();
|
||||||
|
if(day !== 0) {
|
||||||
|
addDays(newDate, (-1) * day);
|
||||||
|
}
|
||||||
|
return newDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mutates
|
||||||
|
function addDays(date, numberOfDays) {
|
||||||
|
date.setDate(date.getDate() + numberOfDays);
|
||||||
|
}
|
||||||
|
|
||||||
class ChartComponent {
|
class ChartComponent {
|
||||||
constructor({
|
constructor({
|
||||||
layerClass = '',
|
layerClass = '',
|
||||||
@ -1669,6 +1749,7 @@ class ChartComponent {
|
|||||||
this.animateElements = animateElements;
|
this.animateElements = animateElements;
|
||||||
|
|
||||||
this.store = [];
|
this.store = [];
|
||||||
|
this.labels = [];
|
||||||
|
|
||||||
this.layerClass = layerClass;
|
this.layerClass = layerClass;
|
||||||
this.layerClass = typeof(this.layerClass) === 'function'
|
this.layerClass = typeof(this.layerClass) === 'function'
|
||||||
@ -1697,6 +1778,9 @@ class ChartComponent {
|
|||||||
this.store.forEach(element => {
|
this.store.forEach(element => {
|
||||||
this.layer.appendChild(element);
|
this.layer.appendChild(element);
|
||||||
});
|
});
|
||||||
|
this.labels.forEach(element => {
|
||||||
|
this.layer.appendChild(element);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
update(animate = true) {
|
update(animate = true) {
|
||||||
@ -1873,12 +1957,18 @@ let componentConfigs = {
|
|||||||
heatDomain: {
|
heatDomain: {
|
||||||
layerClass: function() { return 'heat-domain domain-' + this.constants.index; },
|
layerClass: function() { return 'heat-domain domain-' + this.constants.index; },
|
||||||
makeElements(data) {
|
makeElements(data) {
|
||||||
let {colWidth, rowHeight, squareSize, xTranslate} = this.constants;
|
let {index, colWidth, rowHeight, squareSize, xTranslate, discreteDomains} = this.constants;
|
||||||
let x = xTranslate, y = 0;
|
let monthNameHeight = 12;
|
||||||
|
let x = xTranslate, y = monthNameHeight;
|
||||||
|
|
||||||
this.serializedSubDomains = [];
|
this.serializedSubDomains = [];
|
||||||
|
|
||||||
data.cols.map(week => {
|
data.cols.map((week, weekNo) => {
|
||||||
|
if(weekNo === 1) {
|
||||||
|
this.labels.push(
|
||||||
|
makeText('domain-name', x, 0, getMonthName(index, true), 11)
|
||||||
|
);
|
||||||
|
}
|
||||||
week.map((day, i) => {
|
week.map((day, i) => {
|
||||||
if(day.fill) {
|
if(day.fill) {
|
||||||
let data = {
|
let data = {
|
||||||
@ -1891,7 +1981,7 @@ let componentConfigs = {
|
|||||||
}
|
}
|
||||||
y += rowHeight;
|
y += rowHeight;
|
||||||
});
|
});
|
||||||
y = 0;
|
y = monthNameHeight;
|
||||||
x += colWidth;
|
x += colWidth;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2279,85 +2369,6 @@ class PieChart extends AggregationChart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Playing around with dates
|
|
||||||
|
|
||||||
const NO_OF_YEAR_MONTHS = 12;
|
|
||||||
const NO_OF_DAYS_IN_WEEK = 7;
|
|
||||||
|
|
||||||
const NO_OF_MILLIS = 1000;
|
|
||||||
const SEC_IN_DAY = 86400;
|
|
||||||
|
|
||||||
const MONTH_NAMES = ["January", "February", "March", "April", "May", "June",
|
|
||||||
"July", "August", "September", "October", "November", "December"];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/11252167/6495043
|
|
||||||
function treatAsUtc(date) {
|
|
||||||
let result = new Date(date);
|
|
||||||
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getYyyyMmDd(date) {
|
|
||||||
let dd = date.getDate();
|
|
||||||
let mm = date.getMonth() + 1; // getMonth() is zero-based
|
|
||||||
return [
|
|
||||||
date.getFullYear(),
|
|
||||||
(mm>9 ? '' : '0') + mm,
|
|
||||||
(dd>9 ? '' : '0') + dd
|
|
||||||
].join('-');
|
|
||||||
}
|
|
||||||
|
|
||||||
function clone(date) {
|
|
||||||
return new Date(date.getTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function getWeeksBetween(startDate, endDate) {
|
|
||||||
let weekStartDate = setDayToSunday(startDate);
|
|
||||||
return Math.ceil(getDaysBetween(weekStartDate, endDate) / NO_OF_DAYS_IN_WEEK);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getDaysBetween(startDate, endDate) {
|
|
||||||
let millisecondsPerDay = SEC_IN_DAY * NO_OF_MILLIS;
|
|
||||||
return (treatAsUtc(endDate) - treatAsUtc(startDate)) / millisecondsPerDay;
|
|
||||||
}
|
|
||||||
|
|
||||||
function areInSameMonth(startDate, endDate) {
|
|
||||||
return startDate.getMonth() === endDate.getMonth()
|
|
||||||
&& startDate.getFullYear() === endDate.getFullYear();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getMonthName(i, short=false) {
|
|
||||||
let monthName = MONTH_NAMES[i];
|
|
||||||
return short ? monthName.slice(0, 3) : monthName;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLastDateInMonth (month, year) {
|
|
||||||
return new Date(year, month + 1, 0); // 0: last day in previous month
|
|
||||||
}
|
|
||||||
|
|
||||||
// mutates
|
|
||||||
function setDayToSunday(date) {
|
|
||||||
let newDate = clone(date);
|
|
||||||
const day = newDate.getDay();
|
|
||||||
if(day !== 0) {
|
|
||||||
addDays(newDate, (-1) * day);
|
|
||||||
}
|
|
||||||
return newDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
||||||
@ -2583,6 +2594,8 @@ function getMaxCheckpoint(value, distribution) {
|
|||||||
|
|
||||||
const COL_WIDTH = HEATMAP_SQUARE_SIZE + HEATMAP_GUTTER_SIZE;
|
const COL_WIDTH = HEATMAP_SQUARE_SIZE + HEATMAP_GUTTER_SIZE;
|
||||||
const ROW_HEIGHT = COL_WIDTH;
|
const ROW_HEIGHT = COL_WIDTH;
|
||||||
|
// const DAY_INCR = 1;
|
||||||
|
|
||||||
class Heatmap extends BaseChart {
|
class Heatmap extends BaseChart {
|
||||||
constructor(parent, options) {
|
constructor(parent, options) {
|
||||||
super(parent, options);
|
super(parent, options);
|
||||||
@ -2634,8 +2647,8 @@ class Heatmap extends BaseChart {
|
|||||||
calc() {
|
calc() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
|
|
||||||
s.start = this.data.start;
|
s.start = clone(this.data.start);
|
||||||
s.end = this.data.end;
|
s.end = clone(this.data.end);
|
||||||
|
|
||||||
s.firstWeekStart = setDayToSunday(s.start);
|
s.firstWeekStart = setDayToSunday(s.start);
|
||||||
s.noOfWeeks = getWeeksBetween(s.start, s.end);
|
s.noOfWeeks = getWeeksBetween(s.start, s.end);
|
||||||
@ -2648,16 +2661,18 @@ class Heatmap extends BaseChart {
|
|||||||
setupComponents() {
|
setupComponents() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
|
|
||||||
|
let lessCol = this.discreteDomains ? 0 : 1;
|
||||||
|
|
||||||
let componentConfigs = s.domainConfigs.map((config, i) => [
|
let componentConfigs = s.domainConfigs.map((config, i) => [
|
||||||
'heatDomain',
|
'heatDomain',
|
||||||
{
|
{
|
||||||
index: i,
|
index: config.index,
|
||||||
colWidth: COL_WIDTH,
|
colWidth: COL_WIDTH,
|
||||||
rowHeight: ROW_HEIGHT,
|
rowHeight: ROW_HEIGHT,
|
||||||
squareSize: HEATMAP_SQUARE_SIZE,
|
squareSize: HEATMAP_SQUARE_SIZE,
|
||||||
xTranslate: s.domainConfigs
|
xTranslate: s.domainConfigs
|
||||||
.filter((config, j) => j < i)
|
.filter((config, j) => j < i)
|
||||||
.map(config => config.cols.length - 1)
|
.map(config => config.cols.length - lessCol)
|
||||||
.reduce((a, b) => a + b, 0)
|
.reduce((a, b) => a + b, 0)
|
||||||
* COL_WIDTH
|
* COL_WIDTH
|
||||||
},
|
},
|
||||||
@ -2667,8 +2682,6 @@ class Heatmap extends BaseChart {
|
|||||||
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// console.log(s.domainConfigs)
|
|
||||||
|
|
||||||
this.components = new Map(componentConfigs
|
this.components = new Map(componentConfigs
|
||||||
.map((args, i) => {
|
.map((args, i) => {
|
||||||
let component = getComponent(...args);
|
let component = getComponent(...args);
|
||||||
@ -2680,31 +2693,35 @@ class Heatmap extends BaseChart {
|
|||||||
if(!data) {
|
if(!data) {
|
||||||
console.error('No data to update.');
|
console.error('No data to update.');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data = this.prepareData(data);
|
this.data = this.prepareData(data);
|
||||||
this.draw();
|
this.draw();
|
||||||
this.bindTooltip();
|
this.bindTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindTooltip() {
|
bindTooltip() {
|
||||||
Array.prototype.slice.call(
|
this.container.addEventListener('mousemove', (e) => {
|
||||||
document.querySelectorAll(".data-group .day")
|
this.components.forEach(comp => {
|
||||||
).map(el => {
|
let daySquares = comp.store;
|
||||||
el.addEventListener('mouseenter', (e) => {
|
let daySquare = e.target;
|
||||||
let count = e.target.getAttribute('data-value');
|
if(daySquares.includes(daySquare)) {
|
||||||
let dateParts = e.target.getAttribute('data-date').split('-');
|
|
||||||
|
|
||||||
let month = getMonthName(parseInt(dateParts[1])-1, true);
|
let count = daySquare.getAttribute('data-value');
|
||||||
|
let dateParts = daySquare.getAttribute('data-date').split('-');
|
||||||
|
|
||||||
let gOff = this.container.getBoundingClientRect(), pOff = e.target.getBoundingClientRect();
|
let month = getMonthName(parseInt(dateParts[1])-1, true);
|
||||||
|
|
||||||
let width = parseInt(e.target.getAttribute('width'));
|
let gOff = this.container.getBoundingClientRect(), pOff = daySquare.getBoundingClientRect();
|
||||||
let x = pOff.left - gOff.left + (width+2)/2;
|
|
||||||
let y = pOff.top - gOff.top - (width+2)/2;
|
|
||||||
let value = count + ' ' + this.countLabel;
|
|
||||||
let name = ' on ' + month + ' ' + dateParts[0] + ', ' + dateParts[2];
|
|
||||||
|
|
||||||
this.tip.setValues(x, y, {name: name, value: value, valueFirst: 1}, []);
|
let width = parseInt(e.target.getAttribute('width'));
|
||||||
this.tip.showTip();
|
let x = pOff.left - gOff.left + (width+2)/2;
|
||||||
|
let y = pOff.top - gOff.top - (width+2)/2;
|
||||||
|
let value = count + ' ' + this.countLabel;
|
||||||
|
let name = ' on ' + month + ' ' + dateParts[0] + ', ' + dateParts[2];
|
||||||
|
|
||||||
|
this.tip.setValues(x, y, {name: name, value: value, valueFirst: 1}, []);
|
||||||
|
this.tip.showTip();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -2736,7 +2753,7 @@ class Heatmap extends BaseChart {
|
|||||||
|
|
||||||
getDomainConfig(startDate, endDate='') {
|
getDomainConfig(startDate, endDate='') {
|
||||||
let [month, year] = [startDate.getMonth(), startDate.getFullYear()];
|
let [month, year] = [startDate.getMonth(), startDate.getFullYear()];
|
||||||
let startOfWeek = setDayToSunday(startDate);
|
let startOfWeek = setDayToSunday(startDate); // TODO: Monday as well
|
||||||
endDate = clone(endDate) || getLastDateInMonth(month, year);
|
endDate = clone(endDate) || getLastDateInMonth(month, year);
|
||||||
|
|
||||||
let domainConfig = {
|
let domainConfig = {
|
||||||
@ -2744,18 +2761,19 @@ class Heatmap extends BaseChart {
|
|||||||
cols: []
|
cols: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
addDays(endDate, 1);
|
||||||
let noOfMonthWeeks = getWeeksBetween(startOfWeek, endDate);
|
let noOfMonthWeeks = getWeeksBetween(startOfWeek, endDate);
|
||||||
|
|
||||||
let cols = [];
|
let cols = [], col;
|
||||||
for(var i = 0; i < noOfMonthWeeks; i++) {
|
for(var i = 0; i < noOfMonthWeeks; i++) {
|
||||||
const col = this.getCol(startOfWeek, month);
|
col = this.getCol(startOfWeek, month);
|
||||||
cols.push(col);
|
cols.push(col);
|
||||||
|
|
||||||
startOfWeek = new Date(col[NO_OF_DAYS_IN_WEEK - 1].yyyyMmDd);
|
startOfWeek = new Date(col[NO_OF_DAYS_IN_WEEK - 1].yyyyMmDd);
|
||||||
addDays(startOfWeek, 1);
|
addDays(startOfWeek, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(startOfWeek.getDay() === this.startSubDomainIndex) {
|
if(col[NO_OF_DAYS_IN_WEEK - 1].dataValue) {
|
||||||
addDays(startOfWeek, 1);
|
addDays(startOfWeek, 1);
|
||||||
cols.push(this.getCol(startOfWeek, month, true));
|
cols.push(this.getCol(startOfWeek, month, true));
|
||||||
}
|
}
|
||||||
@ -3065,7 +3083,6 @@ class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAllYValues() {
|
getAllYValues() {
|
||||||
// TODO: yMarkers, regions, sums, every Y value ever
|
|
||||||
let key = 'values';
|
let key = 'values';
|
||||||
|
|
||||||
if(this.barOptions.stacked) {
|
if(this.barOptions.stacked) {
|
||||||
|
|||||||
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
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
3
docs/assets/js/index.min.js
vendored
3
docs/assets/js/index.min.js
vendored
@ -96,7 +96,6 @@ 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) {
|
function clone(date) {
|
||||||
@ -272,8 +271,6 @@ var heatmapData = {
|
|||||||
end: end
|
end: end
|
||||||
};
|
};
|
||||||
|
|
||||||
// ================================================================================
|
|
||||||
|
|
||||||
var c1 = document.querySelector("#chart-composite-1");
|
var c1 = document.querySelector("#chart-composite-1");
|
||||||
var c2 = document.querySelector("#chart-composite-2");
|
var c2 = document.querySelector("#chart-composite-2");
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -156,7 +156,6 @@ export default class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getAllYValues() {
|
getAllYValues() {
|
||||||
// TODO: yMarkers, regions, sums, every Y value ever
|
|
||||||
let key = 'values';
|
let key = 'values';
|
||||||
|
|
||||||
if(this.barOptions.stacked) {
|
if(this.barOptions.stacked) {
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import BaseChart from './BaseChart';
|
import BaseChart from './BaseChart';
|
||||||
import { makeSVGGroup, makeText } from '../utils/draw';
|
|
||||||
import { getComponent } from '../objects/ChartComponents';
|
import { getComponent } from '../objects/ChartComponents';
|
||||||
import { addDays, areInSameMonth, getLastDateInMonth, setDayToSunday, getYyyyMmDd, getWeeksBetween, getMonthName, clone,
|
import { addDays, areInSameMonth, getLastDateInMonth, setDayToSunday, getYyyyMmDd, 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';
|
||||||
@ -9,7 +8,7 @@ import { HEATMAP_DISTRIBUTION_SIZE, HEATMAP_SQUARE_SIZE,
|
|||||||
|
|
||||||
const COL_WIDTH = HEATMAP_SQUARE_SIZE + HEATMAP_GUTTER_SIZE;
|
const COL_WIDTH = HEATMAP_SQUARE_SIZE + HEATMAP_GUTTER_SIZE;
|
||||||
const ROW_HEIGHT = COL_WIDTH;
|
const ROW_HEIGHT = COL_WIDTH;
|
||||||
const DAY_INCR = 1;
|
// const DAY_INCR = 1;
|
||||||
|
|
||||||
export default class Heatmap extends BaseChart {
|
export default class Heatmap extends BaseChart {
|
||||||
constructor(parent, options) {
|
constructor(parent, options) {
|
||||||
@ -62,8 +61,8 @@ export default class Heatmap extends BaseChart {
|
|||||||
calc() {
|
calc() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
|
|
||||||
s.start = this.data.start;
|
s.start = clone(this.data.start);
|
||||||
s.end = this.data.end;
|
s.end = clone(this.data.end);
|
||||||
|
|
||||||
s.firstWeekStart = setDayToSunday(s.start);
|
s.firstWeekStart = setDayToSunday(s.start);
|
||||||
s.noOfWeeks = getWeeksBetween(s.start, s.end);
|
s.noOfWeeks = getWeeksBetween(s.start, s.end);
|
||||||
@ -76,16 +75,18 @@ export default class Heatmap extends BaseChart {
|
|||||||
setupComponents() {
|
setupComponents() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
|
|
||||||
|
let lessCol = this.discreteDomains ? 0 : 1;
|
||||||
|
|
||||||
let componentConfigs = s.domainConfigs.map((config, i) => [
|
let componentConfigs = s.domainConfigs.map((config, i) => [
|
||||||
'heatDomain',
|
'heatDomain',
|
||||||
{
|
{
|
||||||
index: i,
|
index: config.index,
|
||||||
colWidth: COL_WIDTH,
|
colWidth: COL_WIDTH,
|
||||||
rowHeight: ROW_HEIGHT,
|
rowHeight: ROW_HEIGHT,
|
||||||
squareSize: HEATMAP_SQUARE_SIZE,
|
squareSize: HEATMAP_SQUARE_SIZE,
|
||||||
xTranslate: s.domainConfigs
|
xTranslate: s.domainConfigs
|
||||||
.filter((config, j) => j < i)
|
.filter((config, j) => j < i)
|
||||||
.map(config => config.cols.length - 1)
|
.map(config => config.cols.length - lessCol)
|
||||||
.reduce((a, b) => a + b, 0)
|
.reduce((a, b) => a + b, 0)
|
||||||
* COL_WIDTH
|
* COL_WIDTH
|
||||||
},
|
},
|
||||||
@ -93,9 +94,7 @@ export default class Heatmap extends BaseChart {
|
|||||||
return s.domainConfigs[i];
|
return s.domainConfigs[i];
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
|
|
||||||
])
|
]);
|
||||||
|
|
||||||
// console.log(s.domainConfigs)
|
|
||||||
|
|
||||||
this.components = new Map(componentConfigs
|
this.components = new Map(componentConfigs
|
||||||
.map((args, i) => {
|
.map((args, i) => {
|
||||||
@ -108,31 +107,35 @@ export default class Heatmap extends BaseChart {
|
|||||||
if(!data) {
|
if(!data) {
|
||||||
console.error('No data to update.');
|
console.error('No data to update.');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.data = this.prepareData(data);
|
this.data = this.prepareData(data);
|
||||||
this.draw();
|
this.draw();
|
||||||
this.bindTooltip();
|
this.bindTooltip();
|
||||||
}
|
}
|
||||||
|
|
||||||
bindTooltip() {
|
bindTooltip() {
|
||||||
Array.prototype.slice.call(
|
this.container.addEventListener('mousemove', (e) => {
|
||||||
document.querySelectorAll(".data-group .day")
|
this.components.forEach(comp => {
|
||||||
).map(el => {
|
let daySquares = comp.store;
|
||||||
el.addEventListener('mouseenter', (e) => {
|
let daySquare = e.target;
|
||||||
let count = e.target.getAttribute('data-value');
|
if(daySquares.includes(daySquare)) {
|
||||||
let dateParts = e.target.getAttribute('data-date').split('-');
|
|
||||||
|
|
||||||
let month = getMonthName(parseInt(dateParts[1])-1, true);
|
let count = daySquare.getAttribute('data-value');
|
||||||
|
let dateParts = daySquare.getAttribute('data-date').split('-');
|
||||||
|
|
||||||
let gOff = this.container.getBoundingClientRect(), pOff = e.target.getBoundingClientRect();
|
let month = getMonthName(parseInt(dateParts[1])-1, true);
|
||||||
|
|
||||||
let width = parseInt(e.target.getAttribute('width'));
|
let gOff = this.container.getBoundingClientRect(), pOff = daySquare.getBoundingClientRect();
|
||||||
let x = pOff.left - gOff.left + (width+2)/2;
|
|
||||||
let y = pOff.top - gOff.top - (width+2)/2;
|
|
||||||
let value = count + ' ' + this.countLabel;
|
|
||||||
let name = ' on ' + month + ' ' + dateParts[0] + ', ' + dateParts[2];
|
|
||||||
|
|
||||||
this.tip.setValues(x, y, {name: name, value: value, valueFirst: 1}, []);
|
let width = parseInt(e.target.getAttribute('width'));
|
||||||
this.tip.showTip();
|
let x = pOff.left - gOff.left + (width+2)/2;
|
||||||
|
let y = pOff.top - gOff.top - (width+2)/2;
|
||||||
|
let value = count + ' ' + this.countLabel;
|
||||||
|
let name = ' on ' + month + ' ' + dateParts[0] + ', ' + dateParts[2];
|
||||||
|
|
||||||
|
this.tip.setValues(x, y, {name: name, value: value, valueFirst: 1}, []);
|
||||||
|
this.tip.showTip();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -164,27 +167,27 @@ export default class Heatmap extends BaseChart {
|
|||||||
|
|
||||||
getDomainConfig(startDate, endDate='') {
|
getDomainConfig(startDate, endDate='') {
|
||||||
let [month, year] = [startDate.getMonth(), startDate.getFullYear()];
|
let [month, year] = [startDate.getMonth(), startDate.getFullYear()];
|
||||||
let startOfWeek = setDayToSunday(startDate);
|
let startOfWeek = setDayToSunday(startDate); // TODO: Monday as well
|
||||||
endDate = clone(endDate) || getLastDateInMonth(month, year);
|
endDate = clone(endDate) || getLastDateInMonth(month, year);
|
||||||
|
|
||||||
let s = this.state;
|
|
||||||
let domainConfig = {
|
let domainConfig = {
|
||||||
index: month,
|
index: month,
|
||||||
cols: []
|
cols: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
addDays(endDate, 1);
|
||||||
let noOfMonthWeeks = getWeeksBetween(startOfWeek, endDate);
|
let noOfMonthWeeks = getWeeksBetween(startOfWeek, endDate);
|
||||||
|
|
||||||
let cols = [];
|
let cols = [], col;
|
||||||
for(var i = 0; i < noOfMonthWeeks; i++) {
|
for(var i = 0; i < noOfMonthWeeks; i++) {
|
||||||
const col = this.getCol(startOfWeek, month);
|
col = this.getCol(startOfWeek, month);
|
||||||
cols.push(col);
|
cols.push(col);
|
||||||
|
|
||||||
startOfWeek = new Date(col[NO_OF_DAYS_IN_WEEK - 1].yyyyMmDd);
|
startOfWeek = new Date(col[NO_OF_DAYS_IN_WEEK - 1].yyyyMmDd);
|
||||||
addDays(startOfWeek, 1);
|
addDays(startOfWeek, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(startOfWeek.getDay() === this.startSubDomainIndex) {
|
if(col[NO_OF_DAYS_IN_WEEK - 1].dataValue) {
|
||||||
addDays(startOfWeek, 1);
|
addDays(startOfWeek, 1);
|
||||||
cols.push(this.getCol(startOfWeek, month, true));
|
cols.push(this.getCol(startOfWeek, month, true));
|
||||||
}
|
}
|
||||||
@ -219,7 +222,7 @@ export default class Heatmap extends BaseChart {
|
|||||||
yyyyMmDd: yyyyMmDd,
|
yyyyMmDd: yyyyMmDd,
|
||||||
dataValue: dataValue || 0,
|
dataValue: dataValue || 0,
|
||||||
fill: this.colors[getMaxCheckpoint(dataValue, this.state.distribution)]
|
fill: this.colors[getMaxCheckpoint(dataValue, this.state.distribution)]
|
||||||
}
|
};
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { makeSVGGroup } from '../utils/draw';
|
import { makeSVGGroup } from '../utils/draw';
|
||||||
import { makePath, xLine, yLine, yMarker, yRegion, datasetBar, datasetDot, percentageBar, getPaths, heatSquare } from '../utils/draw';
|
import { makeText, makePath, xLine, yLine, yMarker, yRegion, datasetBar, datasetDot, percentageBar, getPaths, heatSquare } from '../utils/draw';
|
||||||
import { equilizeNoOfElements } from '../utils/draw-utils';
|
import { equilizeNoOfElements } from '../utils/draw-utils';
|
||||||
import { translateHoriLine, translateVertLine, animateRegion, animateBar,
|
import { translateHoriLine, translateVertLine, animateRegion, animateBar,
|
||||||
animateDot, animatePath, animatePathStr } from '../utils/animate';
|
animateDot, animatePath, animatePathStr } from '../utils/animate';
|
||||||
|
import { getMonthName } from '../utils/date-utils';
|
||||||
|
|
||||||
class ChartComponent {
|
class ChartComponent {
|
||||||
constructor({
|
constructor({
|
||||||
@ -23,6 +24,7 @@ class ChartComponent {
|
|||||||
this.animateElements = animateElements;
|
this.animateElements = animateElements;
|
||||||
|
|
||||||
this.store = [];
|
this.store = [];
|
||||||
|
this.labels = [];
|
||||||
|
|
||||||
this.layerClass = layerClass;
|
this.layerClass = layerClass;
|
||||||
this.layerClass = typeof(this.layerClass) === 'function'
|
this.layerClass = typeof(this.layerClass) === 'function'
|
||||||
@ -51,6 +53,9 @@ class ChartComponent {
|
|||||||
this.store.forEach(element => {
|
this.store.forEach(element => {
|
||||||
this.layer.appendChild(element);
|
this.layer.appendChild(element);
|
||||||
});
|
});
|
||||||
|
this.labels.forEach(element => {
|
||||||
|
this.layer.appendChild(element);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
update(animate = true) {
|
update(animate = true) {
|
||||||
@ -227,12 +232,18 @@ let componentConfigs = {
|
|||||||
heatDomain: {
|
heatDomain: {
|
||||||
layerClass: function() { return 'heat-domain domain-' + this.constants.index; },
|
layerClass: function() { return 'heat-domain domain-' + this.constants.index; },
|
||||||
makeElements(data) {
|
makeElements(data) {
|
||||||
let {colWidth, rowHeight, squareSize, xTranslate} = this.constants;
|
let {index, colWidth, rowHeight, squareSize, xTranslate, discreteDomains} = this.constants;
|
||||||
let x = xTranslate, y = 0;
|
let monthNameHeight = 12;
|
||||||
|
let x = xTranslate, y = monthNameHeight;
|
||||||
|
|
||||||
this.serializedSubDomains = [];
|
this.serializedSubDomains = [];
|
||||||
|
|
||||||
data.cols.map(week => {
|
data.cols.map((week, weekNo) => {
|
||||||
|
if(weekNo === 1) {
|
||||||
|
this.labels.push(
|
||||||
|
makeText('domain-name', x, 0, getMonthName(index, true), 11)
|
||||||
|
);
|
||||||
|
}
|
||||||
week.map((day, i) => {
|
week.map((day, i) => {
|
||||||
if(day.fill) {
|
if(day.fill) {
|
||||||
let data = {
|
let data = {
|
||||||
@ -245,7 +256,7 @@ let componentConfigs = {
|
|||||||
}
|
}
|
||||||
y += rowHeight;
|
y += rowHeight;
|
||||||
})
|
})
|
||||||
y = 0;
|
y = monthNameHeight;
|
||||||
x += colWidth;
|
x += colWidth;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -237,6 +237,7 @@ export function makeText(className, x, y, content, fontSize = FONT_SIZE) {
|
|||||||
y: y,
|
y: y,
|
||||||
dy: (fontSize / 2) + 'px',
|
dy: (fontSize / 2) + 'px',
|
||||||
'font-size': fontSize + 'px',
|
'font-size': fontSize + 'px',
|
||||||
|
fill: FONT_FILL,
|
||||||
innerHTML: content
|
innerHTML: content
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user