PSWriteHTML icon indicating copy to clipboard operation
PSWriteHTML copied to clipboard

Timeline Chart, support for min, max and multiple entries.

Open Splaxi opened this issue 5 years ago • 6 comments

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>

image

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.

Splaxi avatar Nov 13 '20 08:11 Splaxi

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

PrzemyslawKlys avatar Nov 13 '20 08:11 PrzemyslawKlys

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

PrzemyslawKlys avatar Nov 13 '20 09:11 PrzemyslawKlys

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)

Splaxi avatar Nov 13 '20 22:11 Splaxi

Cool, we will refactor it. It's not a problem. Lets tackle - it works first ;-)

PrzemyslawKlys avatar Nov 13 '20 22:11 PrzemyslawKlys

Hi @Splaxi,

Will you be continuing this?

Przemek

PrzemyslawKlys avatar Nov 24 '20 16:11 PrzemyslawKlys

Yes, but it might take a few weeks, cause I don't have enough hours to spend at the moment.

Splaxi avatar Nov 24 '20 17:11 Splaxi