Search code examples
jsonpowerbivegadeneb

Power bi deneb vega timer issue


I have a deneb vega issue. The script works fine excepted the currentTime is not updated. A timer is created in signals. Can you have a look?

For info: Measures provided by power BI DST_ClockDiffBtwLocationAndLocalOffset : is offset of TimeZone in seconds (ex: 3600) SiteSupportStartFrom : HH:MM for the green rectangle (ex: 08:00) SiteSupportDayTo : HH:MM for the end of the green rectangle. (ex: 17:00)

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "width": 360,
  "height": 50,
  "data": [
    {
      "name": "dataset",
      "transform": [
        {
          "type": "formula",
          "expr": "utcOffset('seconds', now(), datum.DST_ClockDiffBtwLocationAndLocalOffset)",
          "as": "adjustedTime"
        },
        {
          "type": "formula",
          "expr": "hours(datum.adjustedTime) + minutes(datum.adjustedTime) / 60",
          "as": "currentTime"
        },
        {
          "type": "formula",
          "expr": "hours(datetime(datum.SiteSupportStartFrom)) + minutes(datetime(datum.SiteSupportStartFrom)) / 60",
          "as": "startSupportTime"
        },
        {
          "type": "formula",
          "expr": "hours(datetime(datum.SiteSupportDayTo)) + minutes(datetime(datum.SiteSupportDayTo)) / 60",
          "as": "endSupportTime"
        }
      ]
    }
  ],
  "signals": [
    {
      "name": "timer",
      "value": null,
      "on": [
        {
          "events": {"type": "timer", "throttle": 1000},  // Trigger every second
          "update": "now()"  // Timer updates to the current time
        }
      ]
    }
  ],
  "scales": [
    {
      "name": "xscale",
      "type": "linear",
      "domain": [0, 24],
      "range": [0, 350]
    }
  ],
  "marks": [
    {
      "type": "rect",
      "from": {"data": "dataset"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "startSupportTime"},
          "x2": {"scale": "xscale", "field": "endSupportTime"},
          "y": {"value": 5},
          "y2": {"value": 20},
          "fill": {"value": "lightgreen"}
        }
      }
    },
    {
      "type": "rule",
      "from": {"data": "dataset"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "currentTime"},
          "y": {"value": 0},
          "y2": {"value": 27},
          "stroke": {"value": "red"},
          "strokeWidth": {"value": 2}
        }
      }
    },
    {
      "type": "text",
      "from": {"data": "dataset"},
      "encode": {
        "enter": {
          "x": {"scale": "xscale", "field": "currentTime"},
          "y": {"value": 8},
          "text": {
            "signal": "timeFormat(datum.adjustedTime, '%H:%M')"
          },
          "fill": {"value": "black"},
          "align": {"value": "center"},
          "dy": {"value": -10}
        }
      }
    }
  ],
  "axes": [
    {
      "orient": "bottom",
      "scale": "xscale",
      //"title": "Hour of Day",
      "tickCount": 24
    }
  ]
}

Solution

  • After hours on this code, I finally obtained the correct visual with everything implemented.

    In power BI, please provide to deneb :

    • DST_ClockDiffBtwLocationAndLocalOffset: time zone offset in seconds. Because only now() is available in Vega, you have to calculate the difference between your time zone and the destination time zone.
    • SiteSupportStartFrom: in format 1899-12-30T08:00:00.000Z
    • SiteSupportDayTo: in format 1899-12-30T17:00:00.000Z The 2 last are use to dynamically move the green rectangle. Final result here

    Find the code here in Vega.

    {
      "$schema": "https://vega.github.io/schema/vega/v5.json",
      "background": "transparent",  // Transparent background
      "width": 360,
      "height": 71,
      "data": [
        {
          "name": "dataset",
          "transform": [
            {
              "type": "formula",
              "expr": "utcOffset('seconds', timer, datum.DST_ClockDiffBtwLocationAndLocalOffset)",
              "as": "adjustedTime"
            },
            {
              "type": "formula",
              "expr": "(hours(datum.adjustedTime) + minutes(datum.adjustedTime) / 60)",
              "as": "currentTime"
            },
            {
              "type": "formula",
              "expr": "hours(datetime(datum.SiteSupportStartFrom)) + minutes(datetime(datum.SiteSupportStartFrom)) / 60",
              "as": "startSupportTime"
            },
            {
              "type": "formula",
              "expr": "hours(datetime(datum.SiteSupportDayTo)) + minutes(datetime(datum.SiteSupportDayTo)) / 60",
              "as": "endSupportTime"
            },
            {
              "type": "formula",
              "expr": "(datum.startSupportTime + datum.endSupportTime) / 2",
              "as": "midSupportTime"
            }
          ]
        }
      ],
      "signals": [
        {
          "name": "timer",
          "update": "now()",
          "on": [
            {
              "events": {"type": "timer", "throttle": 1000},
              "update": "now()"
            }
          ]
        },
        {
          "name": "adjustedDate",
          "update": "timeFormat(utcOffset('seconds', timer, data('dataset')[0].DST_ClockDiffBtwLocationAndLocalOffset), '%Y-%m-%d')"  // Adjusted date using offset
        }
      ],
      "scales": [
        {
          "name": "xscale",
          "type": "linear",
          "domain": [0, 24],
          "range": [0, 350]
        }
      ],
      "marks": [
        {
          "type": "rect",  // Grey background spanning 24 hours
          "encode": {
            "enter": {
              "x": {"scale": "xscale", "value": 0},
              "x2": {"scale": "xscale", "value": 24},
              "y": {"value": 18},
              "y2": {"value": 32},
              "fill": {"value": "lightgrey"}
            }
          }
        },
        {
          "type": "rect",
          "from": {"data": "dataset"},
          "encode": {
            "enter": {
              "x": {"scale": "xscale", "field": "startSupportTime"},
              "x2": {"scale": "xscale", "field": "endSupportTime"},
              "y": {"value": 15},
              "y2": {"value": 35},
              "fill": {"value": "lightgreen"}
            }
          }
        },
        {
          "type": "text",  // Text in the middle of the green rectangle
          "from": {"data": "dataset"},
          "encode": {
            "enter": {
              "x": {"scale": "xscale", "field": "midSupportTime"},
              "y": {"value": 25},
              "text": {"value": "IT Site Support hours"},
              "fill": {"value": "black"},
              "align": {"value": "center"},
              "baseline": {"value": "middle"},
              "fontSize": {"value": 10},
              "fontWeight": {"value": "bold"}
            }
          }
        },
        {
          "type": "rule",
          "from": {"data": "dataset"},
          "encode": {
            "enter": {
              "x": {"scale": "xscale", "field": "currentTime"},
              "y": {"value": 10},
              "y2": {"value": 45},
              "stroke": {"value": "red"},
              "strokeWidth": {"value": 2}
            },
            "update": {
              "x": {"scale": "xscale", "field": "currentTime"}
            }
          }
        },
        {
          "type": "text",
          "from": {"data": "dataset"},
          "encode": {
            "enter": {
              "x": {"scale": "xscale", "field": "currentTime"},
              "y": {"value": 8},  // Positioned near the red bar
              "align": {"value": "center"},
              "dy": {"value": 1},
              "fontSize": {"value": 10}
            },
            "update": {
              "text": {
                "signal": "timeFormat(utcOffset('seconds', timer, datum.DST_ClockDiffBtwLocationAndLocalOffset), '%H:%M')"
              },
              "fill": {
                "signal": "datum.currentTime >= datum.startSupportTime && datum.currentTime <= datum.endSupportTime ? 'darkgreen' : 'darkred'"
              }
            }
          }
        }
      ],
      "axes": [
        {
          "orient": "bottom",
          "scale": "xscale",
          "title": {"signal": "adjustedDate"},  // Dynamic title for the adjusted date
          "tickCount": 24
        }
      ]
    }