mirror of
https://github.com/aljazceru/satshkd-vercel.git
synced 2025-12-17 05:04:24 +01:00
Replace MetricsGraphics with Chart.js v4 for improved performance
- Replaced MetricsGraphics library with Chart.js v4 for faster chart rendering - Removed dependencies: MetricsGraphics, D3.js v4, and jQuery - Added Chart.js v4 with date-fns adapter and annotation plugin - Maintained all original chart features: - Logarithmic Y-axis scale - Time-series area chart with EUR/sats data - Historical event markers (QE1, QE2, QE3, QH1, QH2, QE4, QH3) - Custom pattern fill with 100 EUR image - Responsive height calculation - Y-axis units formatting - Improved chart performance with modern Canvas-based rendering - Replaced D3 JSON loading with native fetch API
This commit is contained in:
20
public/static/chart.min.js
vendored
Normal file
20
public/static/chart.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
public/static/chartjs-adapter-date-fns.min.js
vendored
Normal file
7
public/static/chartjs-adapter-date-fns.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
public/static/chartjs-plugin-annotation.min.js
vendored
Normal file
7
public/static/chartjs-plugin-annotation.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/static/d3.v4.min.js
vendored
2
public/static/d3.v4.min.js
vendored
File diff suppressed because one or more lines are too long
4
public/static/jquery.min.js
vendored
4
public/static/jquery.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,548 +0,0 @@
|
|||||||
.mg-active-datapoint {
|
|
||||||
fill: black;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
font-weight: 400;
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area-color {
|
|
||||||
fill: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area1-color {
|
|
||||||
fill: #0000ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area2-color {
|
|
||||||
fill: #05b378;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area3-color {
|
|
||||||
fill: #db4437;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area4-color {
|
|
||||||
fill: #f8b128;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area5-color {
|
|
||||||
fill: #5c5c5c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area6-color {
|
|
||||||
fill: steelblue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area7-color {
|
|
||||||
fill: #f673bf;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area8-color {
|
|
||||||
fill: #0b73b0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area9-color {
|
|
||||||
fill: #006400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-area10-color {
|
|
||||||
fill: #92514f;
|
|
||||||
}
|
|
||||||
|
|
||||||
text.mg-barplot-group-label {
|
|
||||||
font-weight:900;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-barplot rect.mg-bar {
|
|
||||||
shape-rendering: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-barplot rect.mg-bar.default-bar {
|
|
||||||
fill: #b6b6fc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-barplot rect.mg-bar.default-active {
|
|
||||||
fill: #9e9efc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-barplot .mg-bar-prediction {
|
|
||||||
fill: #5b5b5b;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-barplot .mg-bar-baseline {
|
|
||||||
stroke: #5b5b5b;
|
|
||||||
stroke-width: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-bar-target-element {
|
|
||||||
font-size:11px;
|
|
||||||
padding-left:5px;
|
|
||||||
padding-right:5px;
|
|
||||||
font-weight:300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-baselines line {
|
|
||||||
opacity: 1;
|
|
||||||
shape-rendering: auto;
|
|
||||||
stroke: #b3b2b2;
|
|
||||||
stroke-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-baselines text {
|
|
||||||
fill: black;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
opacity: 0.6;
|
|
||||||
stroke: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-baselines-small text {
|
|
||||||
font-size: 0.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-category-guides line {
|
|
||||||
stroke: #b3b2b2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-header {
|
|
||||||
cursor: default;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-header .mg-chart-description {
|
|
||||||
fill: #ccc;
|
|
||||||
font-family: FontAwesome;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-header .mg-warning {
|
|
||||||
fill: #ccc;
|
|
||||||
font-family: FontAwesome;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-points circle {
|
|
||||||
opacity: 0.65;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-popover {
|
|
||||||
font-size: 0.95rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-popover-content {
|
|
||||||
cursor: auto;
|
|
||||||
line-height: 17px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-data-table {
|
|
||||||
margin-top: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-data-table thead tr th {
|
|
||||||
border-bottom: 1px solid darkgray;
|
|
||||||
cursor: default;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
font-weight: normal;
|
|
||||||
padding: 5px 5px 8px 5px;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-data-table thead tr th .fa {
|
|
||||||
color: #ccc;
|
|
||||||
padding-left: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-data-table thead tr th .popover {
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-data-table .secondary-title {
|
|
||||||
color: darkgray;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-data-table tbody tr td {
|
|
||||||
margin: 2px;
|
|
||||||
padding: 5px;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-data-table tbody tr td.table-text {
|
|
||||||
opacity: 0.8;
|
|
||||||
padding-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-y-axis line.mg-extended-yax-ticks {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-x-axis line.mg-extended-xax-ticks {
|
|
||||||
opacity: 0.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-histogram .axis path,
|
|
||||||
.mg-histogram .axis line {
|
|
||||||
fill: none;
|
|
||||||
opacity: 0.7;
|
|
||||||
shape-rendering: auto;
|
|
||||||
stroke: #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
tspan.hist-symbol {
|
|
||||||
fill: #9e9efc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-histogram .mg-bar rect {
|
|
||||||
fill: #b6b6fc;
|
|
||||||
shape-rendering: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-histogram .mg-bar rect.active {
|
|
||||||
fill: #9e9efc;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-least-squares-line {
|
|
||||||
stroke: red;
|
|
||||||
stroke-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-lowess-line {
|
|
||||||
fill: none;
|
|
||||||
stroke: red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-rollover-rect * {
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-khtml-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line-color {
|
|
||||||
stroke: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line-color {
|
|
||||||
fill: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line1-color {
|
|
||||||
stroke: #4040e8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line1-color {
|
|
||||||
fill: #4040e8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line2-color {
|
|
||||||
stroke: #05b378;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line2-color {
|
|
||||||
fill: #05b378;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line3-color {
|
|
||||||
stroke: #db4437;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line3-color {
|
|
||||||
fill: #db4437;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line4-color {
|
|
||||||
stroke: #f8b128;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line4-color {
|
|
||||||
fill: #f8b128;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line5-color {
|
|
||||||
stroke: #5c5c5c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line5-color {
|
|
||||||
fill: #5c5c5c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line6-color {
|
|
||||||
stroke: steelblue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line6-color {
|
|
||||||
fill: steelblue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line7-color {
|
|
||||||
stroke: #f673bf;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line7-color {
|
|
||||||
fill: #f673bf;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line8-color {
|
|
||||||
stroke: #0b73b0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line8-color {
|
|
||||||
fill: #0b73b0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line9-color {
|
|
||||||
stroke: #006400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line9-color {
|
|
||||||
fill: #006400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line10-color {
|
|
||||||
stroke: #92514f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-hover-line10-color {
|
|
||||||
fill: #92514f ;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line-legend text {
|
|
||||||
font-size: 0.9rem;
|
|
||||||
font-weight: 300;
|
|
||||||
stroke: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line-legend-color {
|
|
||||||
color: #000;
|
|
||||||
fill: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line1-legend-color {
|
|
||||||
color: #4040e8;
|
|
||||||
fill: #4040e8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line2-legend-color {
|
|
||||||
color: #05b378;
|
|
||||||
fill: #05b378;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line3-legend-color {
|
|
||||||
color: #db4437;
|
|
||||||
fill: #db4437;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line4-legend-color {
|
|
||||||
color: #f8b128;
|
|
||||||
fill: #f8b128;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line5-legend-color {
|
|
||||||
color: #5c5c5c;
|
|
||||||
fill: #5c5c5c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line6-legend-color {
|
|
||||||
color: steelblue;
|
|
||||||
fill: steelblue;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line7-legend-color {
|
|
||||||
color: #f673bf;
|
|
||||||
fill: #f673bf;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line8-legend-color {
|
|
||||||
color: #0b73b0;
|
|
||||||
fill: #0b73b0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line9-legend-color {
|
|
||||||
color: #006400;
|
|
||||||
fill: #006400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-line10-legend-color {
|
|
||||||
color: #92514f;
|
|
||||||
fill: #92514f;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-main-area-solid svg .mg-main-area {
|
|
||||||
fill: #ccccff;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-markers line {
|
|
||||||
opacity: 1;
|
|
||||||
shape-rendering: auto;
|
|
||||||
stroke: #b3b2b2;
|
|
||||||
stroke-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-markers text {
|
|
||||||
fill: black;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-missing-text {
|
|
||||||
opacity: 0.9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-missing-background {
|
|
||||||
stroke: blue;
|
|
||||||
fill: none;
|
|
||||||
stroke-dasharray: 10,5;
|
|
||||||
stroke-opacity: 0.05;
|
|
||||||
stroke-width: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-missing .mg-main-line {
|
|
||||||
opacity: 0.1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-missing .mg-main-area {
|
|
||||||
opacity: 0.03;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.mg-main-area {
|
|
||||||
opacity: 0.2;
|
|
||||||
stroke: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.mg-confidence-band {
|
|
||||||
fill: #ccc;
|
|
||||||
opacity: 0.4;
|
|
||||||
stroke: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
path.mg-main-line {
|
|
||||||
fill: none;
|
|
||||||
opacity: 0.8;
|
|
||||||
stroke-width: 1.1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-points circle {
|
|
||||||
fill-opacity: 0.4;
|
|
||||||
stroke-opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
circle.mg-points-mono {
|
|
||||||
fill: #0000ff;
|
|
||||||
stroke: #0000ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
tspan.mg-points-mono {
|
|
||||||
fill: #0000ff;
|
|
||||||
stroke: #0000ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* a selected point in a scatterplot */
|
|
||||||
.mg-points circle.selected {
|
|
||||||
fill-opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-highlight circle {
|
|
||||||
fill-opacity: 0;
|
|
||||||
stroke-width: 4px;
|
|
||||||
stroke-opacity: 0.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-voronoi path {
|
|
||||||
fill: none;
|
|
||||||
pointer-events: all;
|
|
||||||
stroke: none;
|
|
||||||
stroke-opacity: 0.1;
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-khtml-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-x-rug-mono,
|
|
||||||
.mg-y-rug-mono {
|
|
||||||
stroke: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-x-axis line,
|
|
||||||
.mg-y-axis line {
|
|
||||||
opacity: 1;
|
|
||||||
shape-rendering: auto;
|
|
||||||
stroke: #b3b2b2;
|
|
||||||
stroke-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-x-axis text,
|
|
||||||
.mg-y-axis text,
|
|
||||||
.mg-histogram .axis text {
|
|
||||||
fill: black;
|
|
||||||
font-size: 0.9rem;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-x-axis .label,
|
|
||||||
.mg-y-axis .label,
|
|
||||||
.mg-axis .label {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-x-axis-small text,
|
|
||||||
.mg-y-axis-small text,
|
|
||||||
.mg-active-datapoint-small {
|
|
||||||
font-size: 0.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-x-axis-small .label,
|
|
||||||
.mg-y-axis-small .label {
|
|
||||||
font-size: 0.65rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-european-hours {
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-year-marker text {
|
|
||||||
fill: black;
|
|
||||||
font-size: 0.7rem;
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-year-marker line {
|
|
||||||
opacity: 1;
|
|
||||||
shape-rendering: auto;
|
|
||||||
stroke: #b3b2b2;
|
|
||||||
stroke-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-year-marker-small text {
|
|
||||||
font-size: 0.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-brush-container {
|
|
||||||
cursor: crosshair;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-brush-container .mg-brushing {
|
|
||||||
cursor: ew-resize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-brushed, .mg-brushed * {
|
|
||||||
cursor: zoom-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-brush rect.mg-extent {
|
|
||||||
fill: rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mg-brushing-in-progress {
|
|
||||||
-webkit-touch-callout: none;
|
|
||||||
-webkit-user-select: none;
|
|
||||||
-khtml-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
273
views/sats.hbs
273
views/sats.hbs
@@ -7,23 +7,18 @@
|
|||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/skeleton.css">
|
<link rel="stylesheet" type="text/css" href="/static/skeleton.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/normalize.css">
|
<link rel="stylesheet" type="text/css" href="/static/normalize.css">
|
||||||
<link rel="stylesheet" type="text/css" href="/static/metricsgraphics.css">
|
|
||||||
<link rel="shortcut icon" type="image/png" href="/static/favicon.png" />
|
<link rel="shortcut icon" type="image/png" href="/static/favicon.png" />
|
||||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans|Raleway&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Open+Sans|Raleway&display=swap" rel="stylesheet">
|
||||||
<script src="/static/jquery.min.js"></script>
|
<script src="/static/chart.min.js"></script>
|
||||||
<script src="/static/d3.v4.min.js"></script>
|
<script src="/static/chartjs-adapter-date-fns.min.js"></script>
|
||||||
<script src="/static/metricsgraphics.js"></script>
|
<script src="/static/chartjs-plugin-annotation.min.js"></script>
|
||||||
<script async src="https://analytics.umami.is/script.js" data-website-id="d35ba036-3531-422c-be04-74711c97799c"></script>
|
<script async src="https://analytics.umami.is/script.js" data-website-id="d35ba036-3531-422c-be04-74711c97799c"></script>
|
||||||
<!-- JavaScript Bundle with Popper -->
|
<!-- JavaScript Bundle with Popper -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-p34f1UUtsS3wqzfto5wAAmdvj+osOnFyQFpp4Ua3gs/ZVWx6oOypYoCJhGGScy+8" crossorigin="anonymous"></script>
|
||||||
<style>
|
<style>
|
||||||
#historical svg {
|
#historical {
|
||||||
overflow: visible !important;
|
position: relative;
|
||||||
}
|
width: 100%;
|
||||||
@media screen and (min-width: 393px) and (max-width: 393px) {
|
|
||||||
.mg-y-axis text {
|
|
||||||
transform: translateX(5px);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@@ -135,6 +130,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id='historical'>
|
<div id='historical'>
|
||||||
|
<canvas id="chart"></canvas>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@@ -164,103 +160,198 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
d3.json('/{{ data_file }}', function(data) {
|
// Load data and initialize chart
|
||||||
data = MG.convert.date(data, 'date');
|
fetch('/{{ data_file }}')
|
||||||
|
.then(response => response.json())
|
||||||
var windowWidth = $(window).width();
|
.then(data => {
|
||||||
|
// Convert date strings to Date objects
|
||||||
|
data = data.map(d => ({
|
||||||
|
...d,
|
||||||
|
date: new Date(d.date)
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Calculate responsive height
|
||||||
|
const windowWidth = window.innerWidth;
|
||||||
|
let graphHeight;
|
||||||
if (windowWidth < 550) {
|
if (windowWidth < 550) {
|
||||||
var graphHeight = windowWidth / 1.9047;
|
graphHeight = windowWidth / 1.9047;
|
||||||
} else if (windowWidth < 1200) {
|
} else if (windowWidth < 1200) {
|
||||||
var graphHeight = windowWidth * 0.8 / 1.9047;
|
graphHeight = windowWidth * 0.8 / 1.9047;
|
||||||
} else {
|
} else {
|
||||||
var graphHeight = 500;
|
graphHeight = 500;
|
||||||
}
|
}
|
||||||
console.log("graph height: " , graphHeight)
|
console.log("graph height: ", graphHeight);
|
||||||
|
|
||||||
var qhLink = function() {
|
// Event markers configuration
|
||||||
window.open('https://en.bitcoin.it/wiki/Controlled_supply', '_blank');
|
const qhLink = () => window.open('https://en.bitcoin.it/wiki/Controlled_supply', '_blank');
|
||||||
};
|
const qeLink = () => window.open('https://en.wikipedia.org/wiki/Quantitative_easing', '_blank');
|
||||||
|
|
||||||
var qeLink = function() {
|
const markers = [{
|
||||||
window.open('https://en.wikipedia.org/wiki/Quantitative_easing', '_blank');
|
date: new Date('2008-11-25T00:00:00.000Z'),
|
||||||
};
|
label: 'QE1',
|
||||||
|
click: qeLink,
|
||||||
var markers = [{
|
|
||||||
'date': new Date('2008-11-25T00:00:00.000Z'),
|
|
||||||
'label': 'QE1',
|
|
||||||
'click': qeLink,
|
|
||||||
}, {
|
}, {
|
||||||
'date': new Date('2010-11-03T00:00:00.000Z'),
|
date: new Date('2010-11-03T00:00:00.000Z'),
|
||||||
'label': 'QE2',
|
label: 'QE2',
|
||||||
'click': qeLink,
|
click: qeLink,
|
||||||
}, {
|
}, {
|
||||||
'date': new Date('2012-09-13T00:00:00.000Z'),
|
date: new Date('2012-09-13T00:00:00.000Z'),
|
||||||
'label': 'QE3',
|
label: 'QE3',
|
||||||
'click': qeLink,
|
click: qeLink,
|
||||||
}, {
|
}, {
|
||||||
'date': new Date('2012-11-28T00:00:00.000Z'),
|
date: new Date('2012-11-28T00:00:00.000Z'),
|
||||||
'label': 'QH1',
|
label: 'QH1',
|
||||||
'click': qhLink,
|
click: qhLink,
|
||||||
}, {
|
}, {
|
||||||
'date': new Date('2016-07-09T00:00:00.000Z'),
|
date: new Date('2016-07-09T00:00:00.000Z'),
|
||||||
'label': 'QH2',
|
label: 'QH2',
|
||||||
'click': qhLink,
|
click: qhLink,
|
||||||
}, {
|
}, {
|
||||||
'date': new Date('2019-10-11T00:00:00.000Z'),
|
date: new Date('2019-10-11T00:00:00.000Z'),
|
||||||
'label': 'QE4',
|
label: 'QE4',
|
||||||
'click': qeLink,
|
click: qeLink,
|
||||||
}, {
|
}, {
|
||||||
'date': new Date('2020-05-11T00:00:00.000Z'),
|
date: new Date('2020-05-11T00:00:00.000Z'),
|
||||||
'label': 'QH3',
|
label: 'QH3',
|
||||||
'click': qhLink,
|
click: qhLink,
|
||||||
}];
|
}];
|
||||||
|
|
||||||
MG.data_graphic({
|
// Create pattern fill
|
||||||
title: '{{ subtitle }}',
|
const canvas = document.getElementById('chart');
|
||||||
data: data,
|
canvas.height = graphHeight;
|
||||||
full_width: true,
|
const ctx = canvas.getContext('2d');
|
||||||
height: graphHeight,
|
|
||||||
left: 0,
|
// Load the 100 EUR image for pattern fill
|
||||||
area: true,
|
const patternImage = new Image();
|
||||||
color: '#FF9900',
|
patternImage.src = '/static/assets/100eur.jpg';
|
||||||
markers: markers,
|
|
||||||
target: document.getElementById('historical'),
|
patternImage.onload = function() {
|
||||||
xax_count: 16,
|
const pattern = ctx.createPattern(patternImage, 'repeat');
|
||||||
yax_count: 12,
|
|
||||||
x_accessor: 'date',
|
// Initialize Chart.js
|
||||||
y_accessor: '{{ rate_field }}',
|
const chart = new Chart(ctx, {
|
||||||
y_scale_type: 'log',
|
type: 'line',
|
||||||
y_extended_ticks: true,
|
data: {
|
||||||
yax_units: ' sats',
|
labels: data.map(d => d.date),
|
||||||
yax_units_append: true,
|
datasets: [{
|
||||||
max_y: 1000000000,
|
label: '{{ subtitle }}',
|
||||||
|
data: data.map(d => d['{{ rate_field }}']),
|
||||||
|
borderColor: 'green',
|
||||||
|
backgroundColor: pattern,
|
||||||
|
fill: true,
|
||||||
|
tension: 0.1,
|
||||||
|
borderWidth: 2,
|
||||||
|
pointRadius: 0,
|
||||||
|
pointHoverRadius: 4,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: '{{ subtitle }}',
|
||||||
|
font: {
|
||||||
|
size: 16
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
mode: 'index',
|
||||||
|
intersect: false,
|
||||||
|
callbacks: {
|
||||||
|
label: function(context) {
|
||||||
|
return context.parsed.y.toLocaleString() + ' sats';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
annotation: {
|
||||||
|
annotations: markers.reduce((acc, marker, idx) => {
|
||||||
|
acc['line' + idx] = {
|
||||||
|
type: 'line',
|
||||||
|
xMin: marker.date,
|
||||||
|
xMax: marker.date,
|
||||||
|
borderColor: 'rgba(255, 99, 132, 0.5)',
|
||||||
|
borderWidth: 2,
|
||||||
|
borderDash: [5, 5],
|
||||||
|
label: {
|
||||||
|
display: true,
|
||||||
|
content: marker.label,
|
||||||
|
position: 'start',
|
||||||
|
backgroundColor: 'rgba(255, 99, 132, 0.8)',
|
||||||
|
color: 'white',
|
||||||
|
font: {
|
||||||
|
size: 10,
|
||||||
|
weight: 'bold'
|
||||||
|
},
|
||||||
|
padding: 4
|
||||||
|
},
|
||||||
|
click: function() {
|
||||||
|
marker.click();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: 'time',
|
||||||
|
time: {
|
||||||
|
unit: 'year',
|
||||||
|
displayFormats: {
|
||||||
|
year: 'yyyy'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
maxTicksLimit: 16
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
display: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
type: 'logarithmic',
|
||||||
|
max: 1000000000,
|
||||||
|
ticks: {
|
||||||
|
callback: function(value) {
|
||||||
|
return value.toLocaleString() + ' sats';
|
||||||
|
},
|
||||||
|
maxTicksLimit: 12
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
display: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
interaction: {
|
||||||
|
mode: 'nearest',
|
||||||
|
axis: 'x',
|
||||||
|
intersect: false
|
||||||
|
},
|
||||||
|
onClick: function(event, elements, chart) {
|
||||||
|
// Handle marker clicks
|
||||||
|
const canvasPosition = Chart.helpers.getRelativePosition(event, chart);
|
||||||
|
const dataX = chart.scales.x.getValueForPixel(canvasPosition.x);
|
||||||
|
|
||||||
|
// Check if click is near any marker
|
||||||
|
markers.forEach(marker => {
|
||||||
|
const markerX = marker.date.getTime();
|
||||||
|
const tolerance = 365 * 24 * 60 * 60 * 1000; // 1 year tolerance
|
||||||
|
|
||||||
|
if (Math.abs(dataX - markerX) < tolerance) {
|
||||||
|
marker.click();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
$(document).ready(function() {
|
|
||||||
d3.select('svg')
|
|
||||||
.data(data)
|
|
||||||
.append('defs')
|
|
||||||
|
|
||||||
.append('pattern')
|
|
||||||
.attr('id', 'losermoney')
|
|
||||||
.attr('patternUnits', 'userSpaceOnUse')
|
|
||||||
.attr('width', '100%')
|
|
||||||
.attr('height', '100%')
|
|
||||||
|
|
||||||
.append('image')
|
|
||||||
.attr('width', '100%')
|
|
||||||
.attr('height', '100%')
|
|
||||||
.attr('xlink:href', '/static/assets/100eur.jpg');
|
|
||||||
|
|
||||||
$('svg path')
|
|
||||||
.css('opacity', 1)
|
|
||||||
.css('stroke', 'green')
|
|
||||||
.attr('fill', 'url(#losermoney)');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error loading chart data:', error));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user