[export] export to svg working
This commit is contained in:
parent
e28c564639
commit
8e45278303
48
dist/frappe-charts.esm.js
vendored
48
dist/frappe-charts.esm.js
vendored
@ -1276,6 +1276,8 @@ function runSMILAnimation(parent, svgElement, elementsToAnimate) {
|
|||||||
}, REPLACE_ALL_NEW_DUR);
|
}, REPLACE_ALL_NEW_DUR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CSSTEXT = ".chart-container{position:relative;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.graph-svg-tip{position:absolute;z-index:99999;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.graph-svg-tip ul{padding-left:0;display:flex}.graph-svg-tip ol{padding-left:0;display:flex}.graph-svg-tip ul.data-point-list li{min-width:90px;flex:1;font-weight:600}.graph-svg-tip strong{color:#dfe2e5;font-weight:600}.graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:' ';border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}";
|
||||||
|
|
||||||
class BaseChart {
|
class BaseChart {
|
||||||
constructor(parent, options) {
|
constructor(parent, options) {
|
||||||
|
|
||||||
@ -1599,6 +1601,42 @@ class BaseChart {
|
|||||||
window.removeEventListener('resize', () => this.draw(true));
|
window.removeEventListener('resize', () => this.draw(true));
|
||||||
window.removeEventListener('orientationchange', () => this.draw(true));
|
window.removeEventListener('orientationchange', () => this.draw(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export() {
|
||||||
|
let chartSvg = this.prepareForExport();
|
||||||
|
this.downloadFile(this.title || 'Chart', [chartSvg]);
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadFile(filename, data) {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.style = "display: none";
|
||||||
|
var blob = new Blob(data, {type: "image/svg+xml; charset=utf-8"});
|
||||||
|
var url = window.URL.createObjectURL(blob);
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
setTimeout(function(){
|
||||||
|
document.body.removeChild(a);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareForExport() {
|
||||||
|
let clone = this.svg.cloneNode(true);
|
||||||
|
clone.classList.add('chart-container');
|
||||||
|
clone.setAttribute('xmlns', "http://www.w3.org/2000/svg");
|
||||||
|
clone.setAttribute('xmlns:xlink', "http://www.w3.org/1999/xlink");
|
||||||
|
let styleEl = $.create('style', {
|
||||||
|
'innerHTML': CSSTEXT
|
||||||
|
});
|
||||||
|
clone.insertBefore(styleEl, clone.firstChild);
|
||||||
|
|
||||||
|
let container = $.create('div');
|
||||||
|
container.appendChild(clone);
|
||||||
|
|
||||||
|
return container.innerHTML;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AggregationChart extends BaseChart {
|
class AggregationChart extends BaseChart {
|
||||||
@ -3594,6 +3632,8 @@ class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const chartTypes = {
|
const chartTypes = {
|
||||||
|
bar: AxisChart,
|
||||||
|
line: AxisChart,
|
||||||
// multiaxis: MultiAxisChart,
|
// multiaxis: MultiAxisChart,
|
||||||
percentage: PercentageChart,
|
percentage: PercentageChart,
|
||||||
heatmap: Heatmap,
|
heatmap: Heatmap,
|
||||||
@ -3601,13 +3641,7 @@ const chartTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function getChartByType(chartType = 'line', parent, options) {
|
function getChartByType(chartType = 'line', parent, options) {
|
||||||
if(chartType === 'line') {
|
if (chartType === 'axis-mixed') {
|
||||||
options.type = 'line';
|
|
||||||
return new AxisChart(parent, options);
|
|
||||||
} else if (chartType === 'bar') {
|
|
||||||
options.type = 'bar';
|
|
||||||
return new AxisChart(parent, options);
|
|
||||||
} else if (chartType === 'axis-mixed') {
|
|
||||||
options.type = 'line';
|
options.type = 'line';
|
||||||
return new AxisChart(parent, options);
|
return new AxisChart(parent, options);
|
||||||
}
|
}
|
||||||
|
|||||||
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.css
vendored
2
dist/frappe-charts.min.css
vendored
@ -1 +1 @@
|
|||||||
.chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;position:relative}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.graph-svg-tip ol,.graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.graph-svg-tip strong{color:#dfe2e5;font-weight:600}.graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}
|
.chart-container{position:relative;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.graph-svg-tip ol,.graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.graph-svg-tip strong{color:#dfe2e5;font-weight:600}.graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}
|
||||||
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
@ -88,6 +88,8 @@ Array.prototype.slice.call(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
aggrChart.export();
|
||||||
|
|
||||||
// Update values chart
|
// Update values chart
|
||||||
// ================================================================================
|
// ================================================================================
|
||||||
let updateDataAllLabels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue",
|
let updateDataAllLabels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue",
|
||||||
@ -105,7 +107,7 @@ let getUpdateData = (source_array, length=10) => {
|
|||||||
return indices.map((index) => source_array[index]);
|
return indices.map((index) => source_array[index]);
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_data = {
|
let updateData = {
|
||||||
labels: getUpdateData(updateDataAllLabels),
|
labels: getUpdateData(updateDataAllLabels),
|
||||||
datasets: [{
|
datasets: [{
|
||||||
"values": getUpdateData(updateDataAllValues)
|
"values": getUpdateData(updateDataAllValues)
|
||||||
@ -126,8 +128,8 @@ let update_data = {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
let update_chart = new Chart("#chart-update", {
|
let updateChart = new Chart("#chart-update", {
|
||||||
data: update_data,
|
data: updateData,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
height: 250,
|
height: 250,
|
||||||
colors: ['#ff6c03'],
|
colors: ['#ff6c03'],
|
||||||
@ -137,9 +139,9 @@ let update_chart = new Chart("#chart-update", {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
let chart_update_buttons = document.querySelector('.chart-update-buttons');
|
let chartUpdateButtons = document.querySelector('.chart-update-buttons');
|
||||||
|
|
||||||
chart_update_buttons.querySelector('[data-update="random"]').addEventListener("click", () => {
|
chartUpdateButtons.querySelector('[data-update="random"]').addEventListener("click", () => {
|
||||||
shuffle(updateDataAllIndices);
|
shuffle(updateDataAllIndices);
|
||||||
let value = getRandom();
|
let value = getRandom();
|
||||||
let start = getRandom();
|
let start = getRandom();
|
||||||
@ -162,19 +164,19 @@ chart_update_buttons.querySelector('[data-update="random"]').addEventListener("c
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
update_chart.update(data);
|
updateChart.update(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
chart_update_buttons.querySelector('[data-update="add"]').addEventListener("click", () => {
|
chartUpdateButtons.querySelector('[data-update="add"]').addEventListener("click", () => {
|
||||||
let index = update_chart.state.datasetLength; // last index to add
|
let index = updateChart.state.datasetLength; // last index to add
|
||||||
if(index >= updateDataAllIndices.length) return;
|
if(index >= updateDataAllIndices.length) return;
|
||||||
update_chart.addDataPoint(
|
updateChart.addDataPoint(
|
||||||
updateDataAllLabels[index], [updateDataAllValues[index]]
|
updateDataAllLabels[index], [updateDataAllValues[index]]
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
chart_update_buttons.querySelector('[data-update="remove"]').addEventListener("click", () => {
|
chartUpdateButtons.querySelector('[data-update="remove"]').addEventListener("click", () => {
|
||||||
update_chart.removeDataPoint();
|
updateChart.removeDataPoint();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Trends Chart
|
// Trends Chart
|
||||||
|
|||||||
33
docs/assets/js/index.min.js
vendored
33
docs/assets/js/index.min.js
vendored
@ -49,12 +49,6 @@ var HEATMAP_COLORS_YELLOW = ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001
|
|||||||
|
|
||||||
// Universal constants
|
// Universal constants
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the value of a number upto 2 decimal places.
|
|
||||||
* @param {Number} d Any number
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not two given arrays are equal.
|
* Returns whether or not two given arrays are equal.
|
||||||
* @param {Array} arr1 First array
|
* @param {Array} arr1 First array
|
||||||
@ -124,6 +118,7 @@ var MONTH_NAMES_SHORT = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// https://stackoverflow.com/a/11252167/6495043
|
||||||
|
|
||||||
|
|
||||||
function clone(date) {
|
function clone(date) {
|
||||||
@ -164,8 +159,6 @@ function addDays(date, numberOfDays) {
|
|||||||
date.setDate(date.getDate() + numberOfDays);
|
date.setDate(date.getDate() + numberOfDays);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Composite Chart
|
|
||||||
// ================================================================================
|
|
||||||
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 = {
|
||||||
@ -385,6 +378,8 @@ Array.prototype.slice.call(document.querySelectorAll('.aggr-type-buttons button'
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
aggrChart.export();
|
||||||
|
|
||||||
// Update values chart
|
// Update values chart
|
||||||
// ================================================================================
|
// ================================================================================
|
||||||
var updateDataAllLabels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon"];
|
var updateDataAllLabels = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun", "Mon"];
|
||||||
@ -408,7 +403,7 @@ var getUpdateData = function getUpdateData(source_array) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var update_data = {
|
var updateData = {
|
||||||
labels: getUpdateData(updateDataAllLabels),
|
labels: getUpdateData(updateDataAllLabels),
|
||||||
datasets: [{
|
datasets: [{
|
||||||
"values": getUpdateData(updateDataAllValues)
|
"values": getUpdateData(updateDataAllValues)
|
||||||
@ -425,8 +420,8 @@ var update_data = {
|
|||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
var update_chart = new Chart("#chart-update", {
|
var updateChart = new Chart("#chart-update", {
|
||||||
data: update_data,
|
data: updateData,
|
||||||
type: 'line',
|
type: 'line',
|
||||||
height: 250,
|
height: 250,
|
||||||
colors: ['#ff6c03'],
|
colors: ['#ff6c03'],
|
||||||
@ -436,9 +431,9 @@ var update_chart = new Chart("#chart-update", {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var chart_update_buttons = document.querySelector('.chart-update-buttons');
|
var chartUpdateButtons = document.querySelector('.chart-update-buttons');
|
||||||
|
|
||||||
chart_update_buttons.querySelector('[data-update="random"]').addEventListener("click", function () {
|
chartUpdateButtons.querySelector('[data-update="random"]').addEventListener("click", function () {
|
||||||
shuffle(updateDataAllIndices);
|
shuffle(updateDataAllIndices);
|
||||||
var value = getRandom();
|
var value = getRandom();
|
||||||
var start = getRandom();
|
var start = getRandom();
|
||||||
@ -457,17 +452,17 @@ chart_update_buttons.querySelector('[data-update="random"]').addEventListener("c
|
|||||||
end: end
|
end: end
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
update_chart.update(data);
|
updateChart.update(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
chart_update_buttons.querySelector('[data-update="add"]').addEventListener("click", function () {
|
chartUpdateButtons.querySelector('[data-update="add"]').addEventListener("click", function () {
|
||||||
var index = update_chart.state.datasetLength; // last index to add
|
var index = updateChart.state.datasetLength; // last index to add
|
||||||
if (index >= updateDataAllIndices.length) return;
|
if (index >= updateDataAllIndices.length) return;
|
||||||
update_chart.addDataPoint(updateDataAllLabels[index], [updateDataAllValues[index]]);
|
updateChart.addDataPoint(updateDataAllLabels[index], [updateDataAllValues[index]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
chart_update_buttons.querySelector('[data-update="remove"]').addEventListener("click", function () {
|
chartUpdateButtons.querySelector('[data-update="remove"]').addEventListener("click", function () {
|
||||||
update_chart.removeDataPoint();
|
updateChart.removeDataPoint();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Trends Chart
|
// Trends Chart
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@ -100,6 +100,7 @@
|
|||||||
<button type="button" class="btn btn-sm btn-secondary" data-type='pie'>Pie Chart</button>
|
<button type="button" class="btn btn-sm btn-secondary" data-type='pie'>Pie Chart</button>
|
||||||
<button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button>
|
<button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button>
|
||||||
</div>
|
</div>
|
||||||
|
<button type="button" class="btn btn-sm btn-tertiary" data-type='export'>Export</button>
|
||||||
<!-- <p class="text-muted">
|
<!-- <p class="text-muted">
|
||||||
<a target="_blank" href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts">Why Percentage?</a>
|
<a target="_blank" href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts">Why Percentage?</a>
|
||||||
</p> -->
|
</p> -->
|
||||||
|
|||||||
8615
package-lock.json
generated
Normal file
8615
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -33,16 +33,22 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/frappe/charts#readme",
|
"homepage": "https://github.com/frappe/charts#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"autoprefixer": "^8.2.0",
|
||||||
"babel-core": "^6.26.0",
|
"babel-core": "^6.26.0",
|
||||||
"babel-plugin-external-helpers": "^6.22.0",
|
"babel-plugin-external-helpers": "^6.22.0",
|
||||||
"babel-preset-env": "^1.6.1",
|
"babel-preset-env": "^1.6.1",
|
||||||
"babel-preset-latest": "^6.24.1",
|
"babel-preset-latest": "^6.24.1",
|
||||||
|
"clean-css": "^4.1.11",
|
||||||
"cssnano": "^3.10.0",
|
"cssnano": "^3.10.0",
|
||||||
|
"eslint": "^4.18.2",
|
||||||
|
"fs": "0.0.1-security",
|
||||||
"livereload": "^0.6.3",
|
"livereload": "^0.6.3",
|
||||||
"node-sass": "^4.7.2",
|
"node-sass": "^4.7.2",
|
||||||
"npm-run-all": "^4.1.1",
|
"npm-run-all": "^4.1.1",
|
||||||
|
"postcss": "^6.0.21",
|
||||||
"postcss-cssnext": "^3.0.2",
|
"postcss-cssnext": "^3.0.2",
|
||||||
"postcss-nested": "^2.1.2",
|
"postcss-nested": "^2.1.2",
|
||||||
|
"precss": "^3.1.2",
|
||||||
"rollup": "^0.50.0",
|
"rollup": "^0.50.0",
|
||||||
"rollup-plugin-babel": "^3.0.2",
|
"rollup-plugin-babel": "^3.0.2",
|
||||||
"rollup-plugin-eslint": "^4.0.0",
|
"rollup-plugin-eslint": "^4.0.0",
|
||||||
@ -51,10 +57,7 @@
|
|||||||
"rollup-plugin-replace": "^2.0.0",
|
"rollup-plugin-replace": "^2.0.0",
|
||||||
"rollup-plugin-uglify": "^2.0.1",
|
"rollup-plugin-uglify": "^2.0.1",
|
||||||
"rollup-plugin-uglify-es": "0.0.1",
|
"rollup-plugin-uglify-es": "0.0.1",
|
||||||
"rollup-watch": "^4.3.1",
|
"rollup-watch": "^4.3.1"
|
||||||
"eslint": "^4.18.2"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,42 @@
|
|||||||
|
import pkg from './package.json';
|
||||||
|
|
||||||
// Rollup plugins
|
// Rollup plugins
|
||||||
import babel from 'rollup-plugin-babel';
|
import babel from 'rollup-plugin-babel';
|
||||||
import eslint from 'rollup-plugin-eslint';
|
import eslint from 'rollup-plugin-eslint';
|
||||||
import replace from 'rollup-plugin-replace';
|
import replace from 'rollup-plugin-replace';
|
||||||
import uglify from 'rollup-plugin-uglify-es';
|
import uglify from 'rollup-plugin-uglify-es';
|
||||||
import sass from 'node-sass';
|
import sass from 'node-sass';
|
||||||
import postcss from 'rollup-plugin-postcss';
|
|
||||||
|
|
||||||
// PostCSS plugins
|
// PostCSS plugins
|
||||||
|
import postcssPlugin from 'rollup-plugin-postcss';
|
||||||
import nested from 'postcss-nested';
|
import nested from 'postcss-nested';
|
||||||
import cssnext from 'postcss-cssnext';
|
import cssnext from 'postcss-cssnext';
|
||||||
import cssnano from 'cssnano';
|
import cssnano from 'cssnano';
|
||||||
|
|
||||||
import pkg from './package.json';
|
import postcss from 'postcss';
|
||||||
|
import precss from 'precss';
|
||||||
|
import CleanCSS from 'clean-css';
|
||||||
|
import autoprefixer from 'autoprefixer';
|
||||||
|
import fs from 'fs';
|
||||||
|
import { HEATMAP_LEFT_MARGIN } from './src/js/utils/constants';
|
||||||
|
|
||||||
|
fs.readFile('src/css/charts.scss', (err, css) => {
|
||||||
|
postcss([precss, autoprefixer])
|
||||||
|
.process(css, { from: 'src/css/charts.scss', to: 'src/css/charts.css' })
|
||||||
|
.then(result => {
|
||||||
|
let options = {
|
||||||
|
level: {
|
||||||
|
1: {
|
||||||
|
removeQuotes: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let output = new CleanCSS(options).minify(result.css);
|
||||||
|
let res = JSON.stringify(output.styles).replace(/"/g, "'");
|
||||||
|
let js = `export const CSSTEXT = "${res.slice(1, -1)}";`;
|
||||||
|
fs.writeFile('src/css/chartsCss.js', js);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
@ -29,7 +54,7 @@ export default [
|
|||||||
],
|
],
|
||||||
name: 'frappe',
|
name: 'frappe',
|
||||||
plugins: [
|
plugins: [
|
||||||
postcss({
|
postcssPlugin({
|
||||||
preprocessor: (content, id) => new Promise((resolve, reject) => {
|
preprocessor: (content, id) => new Promise((resolve, reject) => {
|
||||||
const result = sass.renderSync({ file: id })
|
const result = sass.renderSync({ file: id })
|
||||||
resolve({ code: result.css.toString() })
|
resolve({ code: result.css.toString() })
|
||||||
@ -43,7 +68,7 @@ export default [
|
|||||||
}),
|
}),
|
||||||
eslint({
|
eslint({
|
||||||
exclude: [
|
exclude: [
|
||||||
'src/scss/**'
|
'src/css/**'
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
babel({
|
babel({
|
||||||
@ -67,7 +92,7 @@ export default [
|
|||||||
],
|
],
|
||||||
name: 'frappe',
|
name: 'frappe',
|
||||||
plugins: [
|
plugins: [
|
||||||
postcss({
|
postcssPlugin({
|
||||||
preprocessor: (content, id) => new Promise((resolve, reject) => {
|
preprocessor: (content, id) => new Promise((resolve, reject) => {
|
||||||
const result = sass.renderSync({ file: id })
|
const result = sass.renderSync({ file: id })
|
||||||
resolve({ code: result.css.toString() })
|
resolve({ code: result.css.toString() })
|
||||||
@ -81,7 +106,7 @@ export default [
|
|||||||
}),
|
}),
|
||||||
eslint({
|
eslint({
|
||||||
exclude: [
|
exclude: [
|
||||||
'src/scss/**'
|
'src/css/**'
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
babel({
|
babel({
|
||||||
@ -106,7 +131,7 @@ export default [
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
postcss({
|
postcssPlugin({
|
||||||
preprocessor: (content, id) => new Promise((resolve, reject) => {
|
preprocessor: (content, id) => new Promise((resolve, reject) => {
|
||||||
const result = sass.renderSync({ file: id })
|
const result = sass.renderSync({ file: id })
|
||||||
resolve({ code: result.css.toString() })
|
resolve({ code: result.css.toString() })
|
||||||
@ -120,7 +145,7 @@ export default [
|
|||||||
}),
|
}),
|
||||||
eslint({
|
eslint({
|
||||||
exclude: [
|
exclude: [
|
||||||
'src/scss/**',
|
'src/css/**',
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
babel({
|
babel({
|
||||||
@ -142,7 +167,7 @@ export default [
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
plugins: [
|
plugins: [
|
||||||
postcss({
|
postcssPlugin({
|
||||||
preprocessor: (content, id) => new Promise((resolve, reject) => {
|
preprocessor: (content, id) => new Promise((resolve, reject) => {
|
||||||
const result = sass.renderSync({ file: id })
|
const result = sass.renderSync({ file: id })
|
||||||
resolve({ code: result.css.toString() })
|
resolve({ code: result.css.toString() })
|
||||||
@ -157,7 +182,7 @@ export default [
|
|||||||
}),
|
}),
|
||||||
eslint({
|
eslint({
|
||||||
exclude: [
|
exclude: [
|
||||||
'src/scss/**',
|
'src/css/**',
|
||||||
]
|
]
|
||||||
}),
|
}),
|
||||||
replace({
|
replace({
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
.chart-container {
|
.chart-container {
|
||||||
// https://www.smashingmagazine.com/2015/11/using-system-ui-fonts-practical-guide/
|
position: relative; /* for absolutely positioned tooltip */
|
||||||
font-family: -apple-system, BlinkMacSystemFont,
|
|
||||||
"Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",
|
|
||||||
"Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
|
|
||||||
|
|
||||||
position: relative;
|
/* https://www.smashingmagazine.com/2015/11/using-system-ui-fonts-practical-guide/ */
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont,
|
||||||
|
'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell',
|
||||||
|
'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
|
||||||
.axis, .chart-label {
|
.axis, .chart-label {
|
||||||
fill: #555b51;
|
fill: #555b51;
|
||||||
@ -36,13 +36,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
line.dashed {
|
line.dashed {
|
||||||
stroke-dasharray: 5,3;
|
stroke-dasharray: 5, 3;
|
||||||
}
|
}
|
||||||
.axis-line {
|
.axis-line {
|
||||||
// &.x-axis-label {
|
|
||||||
// display: block;
|
|
||||||
// }
|
|
||||||
// TODO: hack dy attr to be settable via styles
|
|
||||||
.specific-value {
|
.specific-value {
|
||||||
text-anchor: start;
|
text-anchor: start;
|
||||||
}
|
}
|
||||||
@ -87,7 +83,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
height: 5px;
|
height: 5px;
|
||||||
margin: 0 0 0 -5px;
|
margin: 0 0 0 -5px;
|
||||||
content: " ";
|
content: ' ';
|
||||||
border: 5px solid transparent;
|
border: 5px solid transparent;
|
||||||
border-top-color: rgba(0, 0, 0, 0.8);
|
border-top-color: rgba(0, 0, 0, 0.8);
|
||||||
}
|
}
|
||||||
1
src/css/chartsCss.js
Normal file
1
src/css/chartsCss.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const CSSTEXT = ".chart-container{position:relative;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI','Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.graph-svg-tip{position:absolute;z-index:99999;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.graph-svg-tip ul{padding-left:0;display:flex}.graph-svg-tip ol{padding-left:0;display:flex}.graph-svg-tip ul.data-point-list li{min-width:90px;flex:1;font-weight:600}.graph-svg-tip strong{color:#dfe2e5;font-weight:600}.graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:' ';border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}";
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import '../scss/charts.scss';
|
import '../css/charts.scss';
|
||||||
|
|
||||||
// import MultiAxisChart from './charts/MultiAxisChart';
|
// import MultiAxisChart from './charts/MultiAxisChart';
|
||||||
import PercentageChart from './charts/PercentageChart';
|
import PercentageChart from './charts/PercentageChart';
|
||||||
@ -7,6 +7,8 @@ import Heatmap from './charts/Heatmap';
|
|||||||
import AxisChart from './charts/AxisChart';
|
import AxisChart from './charts/AxisChart';
|
||||||
|
|
||||||
const chartTypes = {
|
const chartTypes = {
|
||||||
|
bar: AxisChart,
|
||||||
|
line: AxisChart,
|
||||||
// multiaxis: MultiAxisChart,
|
// multiaxis: MultiAxisChart,
|
||||||
percentage: PercentageChart,
|
percentage: PercentageChart,
|
||||||
heatmap: Heatmap,
|
heatmap: Heatmap,
|
||||||
@ -14,13 +16,7 @@ const chartTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function getChartByType(chartType = 'line', parent, options) {
|
function getChartByType(chartType = 'line', parent, options) {
|
||||||
if(chartType === 'line') {
|
if (chartType === 'axis-mixed') {
|
||||||
options.type = 'line';
|
|
||||||
return new AxisChart(parent, options);
|
|
||||||
} else if (chartType === 'bar') {
|
|
||||||
options.type = 'bar';
|
|
||||||
return new AxisChart(parent, options);
|
|
||||||
} else if (chartType === 'axis-mixed') {
|
|
||||||
options.type = 'line';
|
options.type = 'line';
|
||||||
return new AxisChart(parent, options);
|
return new AxisChart(parent, options);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import { BASE_CHART_TOP_MARGIN, BASE_CHART_LEFT_MARGIN,
|
|||||||
import { getColor, isValidColor } from '../utils/colors';
|
import { getColor, isValidColor } from '../utils/colors';
|
||||||
import { runSMILAnimation } from '../utils/animation';
|
import { runSMILAnimation } from '../utils/animation';
|
||||||
import { Chart } from '../chart';
|
import { Chart } from '../chart';
|
||||||
|
import { CSSTEXT } from '../../css/chartsCss';
|
||||||
|
|
||||||
export default class BaseChart {
|
export default class BaseChart {
|
||||||
constructor(parent, options) {
|
constructor(parent, options) {
|
||||||
@ -331,4 +332,40 @@ export default class BaseChart {
|
|||||||
window.removeEventListener('resize', () => this.draw(true));
|
window.removeEventListener('resize', () => this.draw(true));
|
||||||
window.removeEventListener('orientationchange', () => this.draw(true));
|
window.removeEventListener('orientationchange', () => this.draw(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export() {
|
||||||
|
let chartSvg = this.prepareForExport();
|
||||||
|
this.downloadFile(this.title || 'Chart', [chartSvg]);
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadFile(filename, data) {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
a.style = "display: none";
|
||||||
|
var blob = new Blob(data, {type: "image/svg+xml; charset=utf-8"});
|
||||||
|
var url = window.URL.createObjectURL(blob);
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
setTimeout(function(){
|
||||||
|
document.body.removeChild(a);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareForExport() {
|
||||||
|
let clone = this.svg.cloneNode(true);
|
||||||
|
clone.classList.add('chart-container');
|
||||||
|
clone.setAttribute('xmlns', "http://www.w3.org/2000/svg");
|
||||||
|
clone.setAttribute('xmlns:xlink', "http://www.w3.org/1999/xlink");
|
||||||
|
let styleEl = $.create('style', {
|
||||||
|
'innerHTML': CSSTEXT
|
||||||
|
});
|
||||||
|
clone.insertBefore(styleEl, clone.firstChild);
|
||||||
|
|
||||||
|
let container = $.create('div');
|
||||||
|
container.appendChild(clone);
|
||||||
|
|
||||||
|
return container.innerHTML;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user