Timeline Chart, support for min, max and multiple entries.
Hi,
I'm the one talking about timeline chart from the slack channel the other day.
I'm looking for a way to support the following:
<!-- saved from url=(0014)about:internet -->
<!DOCTYPE html>
<html><!-- HEAD --><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="revised" content="2020-11-12 23:52:36"><title>Charts - TimeLine</title><!-- JS Apex Charts START --><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/classList.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/findIndex.min.js"></script><script type="text/javascript" src="https://cdn.jsdelivr.net/npm/[email protected]/dist/apexcharts.min.js"></script><!-- JS Apex Charts END --><!-- CSS ResourceCSS-nKTMPYAe START --><style>body { font-family: Roboto Condensed, Helvetica Neue, sans-serif; font-size: 8pt; margin: 0;}input { font-size: 8pt;}.defaultHeader { padding: 5px; margin: 0px 0px 0px 0px; font-weight: bold;}.defaultFooter { padding-right: 5em; text-align: right;}.container { padding: 2px 16px;}.header { background-color: #616a6b; color: #f7f9f9;}hr { height: 4px; background-color: #6Cf; border: 0px; width: 100%;}.card:hover { box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2);}.col { padding: 20px; margin: 1%; flex: 1;}</style><!-- CSS ResourceCSS-nKTMPYAe END --><!-- CSS ResourceCSS-yUpvzhDv START --><style>.overflowHidden { overflow: hidden; overflow-x: hidden; overflow-y: hidden;}.flexParent { display: flex; justify-content: space-between;}.flexParentInvisible { display: flex; justify-content: space-between;}.flexElement { flex-basis: 100%;}.flexPanel { flex-basis: 100%;}.flex-grid { display: flex;}</style><!-- CSS ResourceCSS-yUpvzhDv END --><!-- CSS ResourceCSS-DaYyvZFC START --><style>.logos { display: flex;}.leftLogo { flex-basis: 100%; border: 0px; padding-left: 0px; vertical-align: middle;}.rightLogo { flex-basis: 100%; border: 0px; padding-right: 5em; text-align: right; vertical-align: middle;}img { border-radius: 5px 5px 0 0;}</style><!-- CSS ResourceCSS-DaYyvZFC END --><!-- CSS ResourceCSS-QpxasKDI START --><style>a.alink:link { color: #007bff; text-decoration: none; font-size: 120%;}a.alink:visited { color: #ff8400; text-decoration: none; font-size: 120%;}a.alink:hover { text-decoration: underline; font-size: 130%;}a.paginate_button { color: #000000 !important; font-size: 10px;}a.current { color: #000000 !important;}</style><!-- CSS ResourceCSS-QpxasKDI END --><!-- CSS Default fonts START --><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto|Hammersmith+One|Questrial|Oswald" type="text/css"/><!-- CSS Default fonts END --><!-- CSS Default fonts icons START --><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.14.0/css/all.css" type="text/css"/><!-- CSS Default fonts icons END --><!-- CSS Always Required Default Visual Settings START --><style>@media all and (-ms-high-contrast:active) {.defaultSection { display: flex;}}.defaultSection { flex-direction: column; border: 1px solid #bbbbbb; padding-bottom: 0px; margin: 5px; width: calc(100% - 10px); box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); transition: 0.3s; border-radius: 5px;}.defaultSectionHead { display: flex; justify-content: center; padding: 5px; margin: 0px 0px 0px 0px; font-weight: bold; background-color: #00bfff; color: #ffffff;}.defaultSectionText { text-align: center;}.defaultPanel { box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); transition: 0.3s; border-radius: 5px; margin: 5px;}</style><!-- CSS Always Required Default Visual Settings END --><!-- CSS Always Required Default Headings START --><style type="text/css">h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Hammersmith One', sans-serif;
}
h1 {
font-size: 30px;
line-height: 20px;
margin: 1em 0 .6em 0;
font-weight: normal;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4);
position: relative;
color: #6Cf;
margin: 10px 10px 10px 10px;
}
h2 {
margin: 1em 0 .6em 0;
padding: 0 0 0 20px;
font-weight: normal;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4);
position: relative;
font-size: 25px;
line-height: 20px;
margin: 10px 10px 10px 10px;
}
h3 {
margin: 1em 0 .6em 0;
padding: 0 0 0 20px;
font-weight: normal;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4);
position: relative;
font-size: 24px;
line-height: 20px;
margin: 10px 10px 10px 10px;
}
h4 {
margin: 1em 0 .6em 0;
padding: 0 0 0 20px;
font-weight: normal;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4);
position: relative;
font-size: 18px;
line-height: 16px;
margin: 10px 10px 10px 10px;
}
h5 {
margin: 1em 0 .6em 0;
padding: 0 0 0 20px;
font-weight: normal;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4);
position: relative;
font-size: 14px;
line-height: 16px;
margin: 10px 10px 10px 10px;
}
h6 {
margin: 1em 0 .6em 0;
padding: 0 0 0 20px;
font-weight: normal;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.4);
position: relative;
font-size: 10px;
line-height: 12px;
margin: 10px 10px 10px 10px;
}</style><!-- CSS Always Required Default Headings END --></head><!-- END HEAD --><!-- BODY --><body><div class="main-section"><div class="flexParentInvisible flexElement overflowHidden defaultSectionContent"><div class="flexParentInvisible flexElement overflowHidden defaultSectionContent"><div class="flexPanel overflowHidden defaultPanel" id="anchor-2ohf4ny"><div class="flexElement" id="ChartID-vij63t4f"></div></div></div></div><script>var options = {
"chart": {
"type": "rangeBar",
"height": 350
},
"title": {
"text": "Incidents Reported vs Solved",
"align": "center"
},
"subtitle": {
"offsetX": 0,
"style": {
"cssClass": "apexcharts-yaxis-title",
"fontSize": "0px"
}
},
"plotOptions": {
"bar": {
"dataLabels": {
"hideOverflowingLabels": false
},
"horizontal": true,
"distributed": true
}
},
"tooltip": {
"enabled": true,
"x": {
"show": true,
"format": "HH:mm:ss",
},
"y": {
"title": {
"formatter": function (seriesName) {
return '';
}
},
}
},
"xaxis": {
"type": "datetime",
"min": new Date('2020-11-11 00:00:00 GMT+00:00').getTime(),
"max": new Date('2020-11-11 23:59:59 GMT+00:00').getTime()
},
"series": [
{
"data": [
{
"x": "Test 0",
"y": [
new Date('2020-11-11 10:52:36 GMT+00:00').getTime(),
new Date('2020-11-11 11:52:36 GMT+00:00').getTime()
],
"fillColor": "#ff00f0",
"id": "1"
},
{
"x": "Test 0",
"y": [
new Date('2020-11-11 12:52:36 GMT+00:00').getTime(),
new Date('2020-11-11 13:52:36 GMT+00:00').getTime()
],
"fillColor": "#ff00f0",
"id": "1"
},
{
"x": "Test 1",
"y": [
new Date('2020-11-11 11:52:36 GMT+00:00').getTime(),
new Date('2020-11-11 12:52:36 GMT+00:00').getTime()
],
"fillColor": "#ff0000",
"id": "1"
},
{
"x": "Test 1",
"y": [
new Date('2020-11-11 13:52:36 GMT+00:00').getTime(),
new Date('2020-11-11 14:52:36 GMT+00:00').getTime()
],
"fillColor": "#ff0000",
"id": "1"
},
{
"x": "Test 2",
"y": [
new Date('2020-11-11 12:52:36 GMT+00:00').getTime(),
new Date('2020-11-11 18:52:36 GMT+00:00').getTime()
],
"fillColor": "#ffff00",
"id": "1"
}
]
}
]
}
var chart = new ApexCharts(document.querySelector('#ChartID-vij63t4f'),
options
);
chart.render();
</script></div><footer><!-- FOOTER --><!-- END FOOTER --></footer><!-- END BODY --></body></html>

As said - I want to help out and give you a hand with anything we need to implement, for this to be solvable. Let me know how we can take it from here.
I believe we need to modify: New-ChartAxisX which controls the X Axis and it has minValue/maxValue but we need to make sure it accepts an object and based on type of the $min it does proper conversion
https://github.com/EvotecIT/PSWriteHTML/blob/bd9848ecd7077f87e179336be7b9ccc6bb6249f5/Public/New-ChartAxisX.ps1#L1-L28
We also need to modify New-CHartTimeLine
https://github.com/EvotecIT/PSWriteHTML/blob/bd9848ecd7077f87e179336be7b9ccc6bb6249f5/Public/New-ChartTimeLine.ps1#L1-L17
And let user pick $DateTimeFormat (with predefined format preset) - default value.
Then I guess we will want to control tooltip which doesn't seem to have cmdlet. We need to create one and add it to all charts.
The concept would be:
New-HTMLChart -Title 'Incidents Reported vs Solved' -TitleAlignment center {
New-ChartAxisX -MinValue Get-Date -MaxValue Get-Date # requires work
New-ChartToolTip # requires adding
$From = (Get-Date).AddDays(-1)
$To = (Get-Date)
New-ChartTimeLine -DateFrom $From -DateTo $To -Name 'Test 0'
$From = (Get-Date).AddDays(-1)
$To = (Get-Date)
New-ChartTimeLine -DateFrom $From -DateTo $To -Name 'Test 1' -Color Red
$From = (Get-Date).AddDays(0)
$To = (Get-Date).AddDays(2)
New-ChartTimeLine -DateFrom $From -DateTo $To -Name 'Test 2' -Color Yellow
$From = (Get-Date).AddDays(-5)
$To = (Get-Date).AddDays(11)
New-ChartTimeLine -DateFrom $From -DateTo $To -Name 'Test 3' -Color Beige
$From = (Get-Date).AddDays(-5)
$To = (Get-Date).AddDays(11)
New-ChartTimeLine -DateFrom $From -DateTo $To -Name 'Test 4'
}
This could be modified https://github.com/EvotecIT/PSWriteHTML/blob/bd9848ecd7077f87e179336be7b9ccc6bb6249f5/Public/New-ChartAxisX.ps1#L13-L25
To remover empty, not provided values. I believe only $Names would need a separate check because I don't remove empty values if it's empty array. I need to expand Remove-EmptyValue for future with some kind of switch to support that.
$Object = [PSCustomObject] @{
ObjectType = 'ChartAxisX'
ChartAxisX = @{
Names = $Names
Type = $Type
TitleText = $TitleText
Min = $MinValue
Max = $MaxValue
}
# LegendPosition = $LegendPosition
# Color = $Color
}
Remove-EmptyValue -Hashtable $Object.ChartAxisX
$Object
Of course it's possible that somewhere else I remove those values already or worse throw errors if those are not set ;) So this needs sort of review.
Somewhere here would need to be added the tooltip control
https://github.com/EvotecIT/PSWriteHTML/blob/bd9848ecd7077f87e179336be7b9ccc6bb6249f5/Public/New-HTMLChart.ps1#L131-L141
And we would need to modify here, to pass ChartX/ChartY
https://github.com/EvotecIT/PSWriteHTML/blob/bd9848ecd7077f87e179336be7b9ccc6bb6249f5/Public/New-HTMLChart.ps1#L230-L235
Just like we do for:
https://github.com/EvotecIT/PSWriteHTML/blob/bd9848ecd7077f87e179336be7b9ccc6bb6249f5/Public/New-HTMLChart.ps1#L187-L202
Unfortunately in other charts, I've not done this as well so I need to fix it too in future.
Finally in New-HTMLChartTimeLine you would need to do similar thing I did for Line chart:
https://github.com/EvotecIT/PSWriteHTML/blob/bd9848ecd7077f87e179336be7b9ccc6bb6249f5/Private/ChartsAll/New-HTMLChartLine.ps1#L79-L84
You also need to modify support for different objects here... int/datetime etc
https://github.com/EvotecIT/PSWriteHTML/blob/bd9848ecd7077f87e179336be7b9ccc6bb6249f5/Private/ChartsAll/New-ChartInternalAxisX.ps1#L19-L24
I believe I managed to hack something together.
Might not be the quality that you want, but I'm trying to comprehend all the internal dependencies and how stuff is connected. I'll do a PR for you to review next, when I have it up and running. From there we can see if you feel this is the time where we refactor some stuff, to get everything into shape.
Status is: Min + Max implemented. ToolTip (Raw, hardcoded into the module for now)
Cool, we will refactor it. It's not a problem. Lets tackle - it works first ;-)
Hi @Splaxi,
Will you be continuing this?
Przemek
Yes, but it might take a few weeks, cause I don't have enough hours to spend at the moment.