Don't miss your chance to take exam DP-600 or DP-700 on us!
Request nowLearn from the best! Meet the four finalists headed to the FINALS of the Power BI Dataviz World Championships! Register now
Hi everyone,
I am building a real-time schedule visual in Vega. I have a working visual that shows all data, but it breaks when I try to filter for the current day.
Data from provided from Power Bi to deneb:
- DST_ClockDiffBtwLocationAndLocalOffset:This is a measure. TimeZone Difference. provides the offset of this difference.
- From my Power BI table:
- ScheduleType
- day_num
- type
-startTime
-endTime
I have a query named AllSegments that creates a clean, flat table
Each day, for each scheduleType, we can have multiple rows. For example:
| Scheduletype | day_num | type | start_time | end_time | startTime | endTime |
| Production | 0 | No Production | 00:00:00 | 22:00:00 | 0 | 22 |
| Production | 0 | Normal | 22:00:00 | 23:59:00 | 22 | 23.9833333 |
| Production | 1 | Normal | 00:00:00 | 23:59:00 | 0 | 23:9833333 |
| ... | ||||||
| SiteOpening | 0 | No Production | 00:00:00 | 23:59:00 | 0 | 23.9833333 |
| SiteOpening | 1 | Normal | 08:30:00 | 12:30:00 | 8.5 | 12.5 |
| SiteOpening | 1 | Normal | 13:30 | 17:00:00 | 13.5 | 17 |
| ... | ||||||
| Support | 0 | No Production | 00:00:00 | 23:59:00 | 0 | 23.9833333 |
| Support | 1 | Normal | 08:30:00 | 12:30:00 | 8.5 | 12.5 |
| Support | 1 | Flexible | 13:30:00 | 17:00:00 | 13.5 | 17
|
The goal is one graph with a 24 hours
My working code:
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A static visual for Monday with a dynamic real-time clock.",
"background": "transparent",
"width": 360,
"height": 80,
"autosize": {"type": "fit", "contains": "padding"},
"signals": [
{
"name": "timer",
"update": "now()",
"on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}]
},
{
"name": "adjustedTime",
"update": "length(data('source')) > 0 ? utcOffset('seconds', timer, data('source')[0].DST_ClockDiffBtwLocationAndLocalOffset) : now()"
},
{
"name": "currentTime",
"update": "hours(adjustedTime) + minutes(adjustedTime) / 60"
},
{
"name": "adjustedDate",
"update": "timeFormat(adjustedTime, '%Y-%m-%d')"
}
],
"data": [
{
"name": "source"
},
{
"name": "dataset",
"source": "source",
"transform": [
{
"type": "filter",
"expr": "datum.ScheduleType == 'SiteOpening' && datum.type != 'No Production' && +datum.day_num == 1"
}
]
}
],
"scales": [
{
"name": "xscale",
"type": "linear",
"domain": [0, 24],
"range": "width"
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"title": {"signal": "adjustedDate"},
"tickCount": 24,
"labelFontSize": 8,
"offset": 5
}
],
"marks": [
{
"type": "rect",
"from": {"data": "dataset"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"x2": {"scale": "xscale", "field": "endTime"},
"y": {"value": 20},
"height": {"value": 30},
"fill": {"value": "lightgray"}
}
}
},
{
"type": "rule",
"from": {"data": "dataset"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"y": {"value": 15},
"y2": {"value": 55},
"stroke": {"value": "black"},
"strokeWidth": {"value": 1}
}
}
},
{
"type": "symbol",
"from": {"data": "dataset"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"y": {"value": 15},
"shape": {"value": "triangle-down"},
"size": {"value": 40},
"fill": {"value": "black"}
}
}
},
{
"type": "symbol",
"from": {"data": "dataset"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "endTime"},
"y": {"value": 55},
"shape": {"value": "triangle-up"},
"size": {"value": 40},
"fill": {"value": "black"}
}
}
},
{
"type": "rule",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "currentTime"},
"y": {"value": 10},
"y2": {"value": 60},
"stroke": {"value": "red"},
"strokeWidth": {"value": 2}
}
}
},
{
"type": "text",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "currentTime"},
"y": {"value": 5},
"text": {"signal": "timeFormat(adjustedTime, '%H:%M')"},
"align": {"value": "center"},
"fill": {"value": "red"},
"fontSize": {"value": 10}
}
}
}
]
}Now, I want to filter these bars to show only the ones for the current day. I added a signals block for the current time and a filter to my data transform ...
Code doesn't work:
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "A dynamic, real-time visual for Site Opening Hours.",
"background": "transparent",
"width": 360,
"height": 80,
"autosize": {"type": "fit", "contains": "padding"},
"signals": [
{
"name": "timer",
"update": "now()",
"on": [{"events": {"type": "timer", "throttle": 1000}, "update": "now()"}]
},
{
"name": "adjustedTime",
"update": "length(data('source')) > 0 ? utcOffset('seconds', timer, data('source')[0].DST_ClockDiffBtwLocationAndLocalOffset) : now()"
},
{
"name": "currentTime",
"update": "hours(adjustedTime) + minutes(adjustedTime) / 60"
},
{
"name": "adjustedDate",
"update": "timeFormat(adjustedTime, '%Y-%m-%d')"
},
{
"name": "currentDayNum",
"update": "day(adjustedTime)"
}
],
"data": [
{
"name": "source"
},
{
"name": "opening_hours_today",
"source": "source",
"transform": [
{
"type": "filter",
"expr": "datum.ScheduleType == 'SiteOpening' && datum.type != 'No Production' && +datum.day_num == currentDayNum"
}
]
}
],
"scales": [
{
"name": "xscale",
"type": "linear",
"domain": [0, 24],
"range": "width"
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"title": {"signal": "adjustedDate"},
"tickCount": 24,
"labelFontSize": 8,
"offset": 5
}
],
"marks": [
{
"type": "rect",
"from": {"data": "opening_hours_today"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"x2": {"scale": "xscale", "field": "endTime"},
"y": {"value": 20},
"height": {"value": 30},
"fill": {"value": "lightgray"}
}
}
},
{
"type": "rule",
"from": {"data": "opening_hours_today"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"y": {"value": 15},
"y2": {"value": 55},
"stroke": {"value": "black"},
"strokeWidth": {"value": 1}
}
}
},
{
"type": "symbol",
"from": {"data": "opening_hours_today"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"y": {"value": 15},
"shape": {"value": "triangle-down"},
"size": {"value": 40},
"fill": {"value": "black"}
}
}
},
{
"type": "symbol",
"from": {"data": "opening_hours_today"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "endTime"},
"y": {"value": 55},
"shape": {"value": "triangle-up"},
"size": {"value": 40},
"fill": {"value": "black"}
}
}
},
{
"type": "rule",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "currentTime"},
"y": {"value": 10},
"y2": {"value": 60},
"stroke": {"value": "red"},
"strokeWidth": {"value": 2}
}
}
},
{
"type": "text",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "currentTime"},
"y": {"value": 5},
"text": {"signal": "timeFormat(adjustedTime, '%H:%M')"},
"align": {"value": "center"},
"fill": {"value": "red"},
"fontSize": {"value": 10}
}
}
}
]
}the final goal is:
- real time current clock (red bar + current hour text)
- real time current day. if it is a production day, a blue rect align on the 24 hours, if it is Flexible period, a dark blue rect. if No prod, a gray rect
- A second bar to provide info about when the location can have a support
- a legend with the different info
Thanks a lot for the support you will accept to provide
Solved! Go to Solution.
OK, I solved all my problems so I post my code here if it can help someone else
I obtained my final visual like I show in my first post.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "Final version with corrected 'ITSupport' string in the filter expression.",
"width": 372,
"height": 50,
"signals": [
{
"name": "pbi_time_offset_seconds",
"init": "isValid(data('pbi_summarize')[0]) ? data('pbi_summarize')[0].DST_ClockDiffBtwLocationAndLocalOffset : 0"
},
{
"name": "utc_now",
"init": "now()",
"on": [
{
"events": {"type": "timer", "throttle": 1000},
"update": "now()"
}
]
},
{
"name": "remote_now",
"update": "utc_now + (pbi_time_offset_seconds * 1000)"
},
{
"name": "remote_day",
"update": "day(remote_now)"
},
{
"name": "remote_hour_decimal",
"update": "hours(remote_now) + (minutes(remote_now) / 60) + (seconds(remote_now) / 3600)"
},
{
"name": "remote_time_label",
"update": "timeFormat(remote_now, '%H:%M')"
}
],
"data": [
{
"name": "dataset"
},
{
"name": "pbi_summarize"
},
{
"name": "schedule_bands",
"source": "dataset",
"transform": [
{
"type": "filter",
"expr": "datum.day_num != null && (datum.ScheduleType == 'Production' || datum.ScheduleType == 'ITSupport') && datum.day_num == remote_day"
},
{
"type": "formula",
"as": "display_type",
"expr": "datum.type == 'Normal' ? (datum.ScheduleType == 'Production' ? 'Working hours' : 'Support hours') : datum.type == 'Flexible' ? 'Flexible hours' : 'No Working hours'"
}
]
},
{
"name": "site_opening_start",
"source": "dataset",
"transform": [
{"type": "filter", "expr": "datum.day_num != null && datum.ScheduleType == 'SiteOpening' && datum.day_num == remote_day"},
{"type": "project", "fields": ["startTime"], "as": ["time_value"]}
]
},
{
"name": "site_opening_end",
"source": "dataset",
"transform": [
{"type": "filter", "expr": "datum.day_num != null && datum.ScheduleType == 'SiteOpening' && datum.day_num == remote_day"},
{"type": "project", "fields": ["endTime"], "as": ["time_value"]}
]
}
],
"scales": [
{
"name": "xscale",
"type": "linear",
"range": "width",
"domain": [0, 24]
},
{
"name": "yscale",
"type": "band",
"range": [1, 50],
"domain": ["ITSupport", "Production"],
"padding": 0.1
},
{
"name": "color",
"type": "ordinal",
"domain": ["Working hours", "Support hours", "Flexible hours", "No Working hours"],
"range": ["#a6cee3", "#b2df8a", "#1f78b4", "#d3d3d3"]
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"tickCount": 25,
"title": {
"signal": "timeFormat(remote_now, 'Time & Day (%Y-%m-%d)')"
},
"labelFontSize": 9,
"titleFontSize": 9
}
],
"marks": [
{
"type": "group",
"name": "custom_legend",
"encode": {"enter": {"x": {"value": 0}, "y": {"value": -40}}},
"marks": [
{"type": "rect", "encode": {"enter": {"x": {"value": 0}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#a6cee3"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 15}, "y": {"value": 9}, "text": {"value": "Working hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}},
{"type": "rect", "encode": {"enter": {"x": {"value": 120}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#1f78b4"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 135}, "y": {"value": 9}, "text": {"value": "Flexible hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}},
{"type": "rect", "encode": {"enter": {"x": {"value": 240}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#d3d3d3"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 255}, "y": {"value": 9}, "text": {"value": "No Working hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}},
{"type": "rect", "encode": {"enter": {"x": {"value": 0}, "y": {"value": 15}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#b2df8a"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 15}, "y": {"value": 24}, "text": {"value": "Support hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}},
{"type": "rule", "encode": {"enter": {"x": {"value": 122}, "y": {"value": 13}, "x2": {"value": 122}, "y2": {"value": 23}, "stroke": {"value": "black"}}}},
{"type": "symbol", "encode": {"enter": {"x": {"value": 122}, "y": {"value": 22}, "shape": {"value": "triangle-up"}, "size": {"value": 25}, "fill": {"value": "black"}}}},
{"type": "rule", "encode": {"enter": {"x": {"value": 128}, "y": {"value": 15}, "x2": {"value": 128}, "y2": {"value": 24}, "stroke": {"value": "black"}}}},
{"type": "symbol", "encode": {"enter": {"x": {"value": 128}, "y": {"value": 15}, "shape": {"value": "triangle-down"}, "size": {"value": 25}, "fill": {"value": "black"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 135}, "y": {"value": 24}, "text": {"value": "Site Opening"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}}
]
},
{
"type": "rect",
"from": {"data": "schedule_bands"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"x2": {"scale": "xscale", "field": "endTime"},
"y": {"scale": "yscale", "field": "ScheduleType"},
"height": {"scale": "yscale", "band": 1},
"fill": {"scale": "color", "field": "display_type"}
}
}
},
{
"type": "rule",
"from": {"data": "site_opening_start"},
"encode": {"enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 0}, "y2": {"value": 50}, "stroke": {"value": "black"}, "strokeWidth": {"value": 2}}}
},
{
"type": "symbol",
"from": {"data": "site_opening_start"},
"encode": {"enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 50}, "shape": {"value": "triangle-up"}, "size": {"value": 50}, "fill": {"value": "black"}}}
},
{
"type": "rule",
"from": {"data": "site_opening_end"},
"encode": {"enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 0}, "y2": {"value": 50}, "stroke": {"value": "black"}, "strokeWidth": {"value": 2}}}
},
{
"type": "symbol",
"from": {"data": "site_opening_end"},
"encode": {"enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 3}, "shape": {"value": "triangle-down"}, "size": {"value": 50}, "fill": {"value": "black"}}}
},
{
"type": "rule",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "remote_hour_decimal"},
"y": {"value": 2}, "y2": {"value": 50},
"stroke": {"value": "red"},
"strokeWidth": {"value": 2}
}
}
},
{
"type": "text",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "remote_hour_decimal"},
"y": {"value": 3},
"text": {"signal": "remote_time_label"},
"baseline": {"value": "bottom"},
"align": {"value": "center"},
"fill": {"value": "red"}
}
}
}
]
}
@DGPBi Hi! Try with this adjusted code:
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "Real-time schedule visual (Site Opening) with correct day filtering.",
"background": "transparent",
"width": 360,
"height": 80,
"autosize": {"type": "fit", "contains": "padding"},
"signals": [
{
"name": "timer",
"update": "now()",
"on": [
{
"events": {"type": "timer", "throttle": 1000},
"update": "now()"
}
]
},
{
"name": "adjustedTime",
"update": "length(data('source')) > 0 ? utcOffset('seconds', timer, data('source')[0].DST_ClockDiffBtwLocationAndLocalOffset) : now()"
},
{
"name": "currentTime",
"update": "hours(adjustedTime) + minutes(adjustedTime) / 60"
},
{
"name": "adjustedDate",
"update": "timeFormat(adjustedTime, '%Y-%m-%d')"
},
{
"name": "currentDayNum",
"update": "(day(adjustedTime) + 6) % 7"
}
],
"data": [
{ "name": "source" },
{
"name": "opening_hours_today",
"source": "source",
"transform": [
{
"type": "filter",
"expr":
"datum.ScheduleType == 'SiteOpening' && datum.type != 'No Production' && +datum.day_num == currentDayNum"
}
]
}
],
"scales": [
{
"name": "xscale",
"type": "linear",
"domain": [0, 24],
"range": "width"
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"title": {"signal": "adjustedDate"},
"tickCount": 24,
"labelFontSize": 8,
"offset": 5
}
],
"marks": [
{
"type": "rect",
"from": {"data": "opening_hours_today"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"x2": {"scale": "xscale", "field": "endTime"},
"y": {"value": 20},
"height": {"value": 30},
"fill": {"value": "lightgray"}
}
}
},
{
"type": "rule",
"from": {"data": "opening_hours_today"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"y": {"value": 15},
"y2": {"value": 55},
"stroke": {"value": "black"},
"strokeWidth": {"value": 1}
}
}
},
{
"type": "symbol",
"from": {"data": "opening_hours_today"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"y": {"value": 15},
"shape": {"value": "triangle-down"},
"size": {"value": 40},
"fill": {"value": "black"}
}
}
},
{
"type": "symbol",
"from": {"data": "opening_hours_today"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "endTime"},
"y": {"value": 55},
"shape": {"value": "triangle-up"},
"size": {"value": 40},
"fill": {"value": "black"}
}
}
},
{
"type": "rule",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "currentTime"},
"y": {"value": 10},
"y2": {"value": 60},
"stroke": {"value": "red"},
"strokeWidth": {"value": 2}
}
}
},
{
"type": "text",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "currentTime"},
"y": {"value": 5},
"text": {"signal": "timeFormat(adjustedTime, '%H:%M')"},
"align": {"value": "center"},
"fill": {"value": "red"},
"fontSize": {"value": 10}
}
}
}
]
}
BBF
Hi BeaBF,
Thank you so much for your answer.
I tested your code but I only have the 24 hours scale and the current time bar + text. No rect on the graph
And the filter on the day seems not working.
In my example, The difference between Local and destination is the same time zone it is why you 0 for his offset
Please find an example of data. I will ertainely help you to play with them.
"data": [
{
"name": "dataset",
"values": [
{"ScheduleType": "Production", "day_num": 0, "type": "No Production", "startTime": 0, "endTime": 22},
{"ScheduleType": "Production", "day_num": 0, "type": "Normal", "startTime": 22, "endTime": 23.9833333333333},
{"ScheduleType": "Production", "day_num": 1, "type": "Normal", "startTime": 0, "endTime": 23.9833333333333},
{"ScheduleType": "Production", "day_num": 2, "type": "Normal", "startTime": 0, "endTime": 23.9833333333333},
{"ScheduleType": "Production", "day_num": 3, "type": "Normal", "startTime": 0, "endTime": 23.9833333333333},
{"ScheduleType": "Production", "day_num": 4, "type": "Normal", "startTime": 0, "endTime": 23.9833333333333},
{"ScheduleType": "Production", "day_num": 5, "type": "Normal", "startTime": 0, "endTime": 22},
{"ScheduleType": "Production", "day_num": 5, "type": "Flexible", "startTime": 22, "endTime": 23.9833333333333},
{"ScheduleType": "Production", "day_num": 6, "type": "Flexible", "startTime": 0, "endTime": 6},
{"ScheduleType": "Production", "day_num": 6, "type": "No Production", "startTime": 6, "endTime": 23.9833333333333},
{"ScheduleType": "SiteOpening", "day_num": 0, "type": "No Production", "startTime": 0, "endTime": 23.9833333333333},
{"ScheduleType": "SiteOpening", "day_num": 1, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "SiteOpening", "day_num": 1, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "SiteOpening", "day_num": 2, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "SiteOpening", "day_num": 2, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "SiteOpening", "day_num": 3, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "SiteOpening", "day_num": 3, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "SiteOpening", "day_num": 4, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "SiteOpening", "day_num": 4, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "SiteOpening", "day_num": 5, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "SiteOpening", "day_num": 5, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "SiteOpening", "day_num": 6, "type": "No Production", "startTime": 0, "endTime": 23.9833333333333},
{"ScheduleType": "ITSupport", "day_num": 0, "type": "No Production", "startTime": 0, "endTime": 23.9833333333333},
{"ScheduleType": "ITSupport", "day_num": 1, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "ITSupport", "day_num": 1, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "ITSupport", "day_num": 2, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "ITSupport", "day_num": 2, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "ITSupport", "day_num": 3, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "ITSupport", "day_num": 3, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "ITSupport", "day_num": 4, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "ITSupport", "day_num": 4, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "ITSupport", "day_num": 5, "type": "Normal", "startTime": 8.5, "endTime": 12.5},
{"ScheduleType": "ITSupport", "day_num": 5, "type": "Normal", "startTime": 13.5, "endTime": 16.5},
{"ScheduleType": "ITSupport", "day_num": 6, "type": "No Production", "startTime": 0, "endTime": 23.9833333333333}
]
},
OK, I solved all my problems so I post my code here if it can help someone else
I obtained my final visual like I show in my first post.
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "Final version with corrected 'ITSupport' string in the filter expression.",
"width": 372,
"height": 50,
"signals": [
{
"name": "pbi_time_offset_seconds",
"init": "isValid(data('pbi_summarize')[0]) ? data('pbi_summarize')[0].DST_ClockDiffBtwLocationAndLocalOffset : 0"
},
{
"name": "utc_now",
"init": "now()",
"on": [
{
"events": {"type": "timer", "throttle": 1000},
"update": "now()"
}
]
},
{
"name": "remote_now",
"update": "utc_now + (pbi_time_offset_seconds * 1000)"
},
{
"name": "remote_day",
"update": "day(remote_now)"
},
{
"name": "remote_hour_decimal",
"update": "hours(remote_now) + (minutes(remote_now) / 60) + (seconds(remote_now) / 3600)"
},
{
"name": "remote_time_label",
"update": "timeFormat(remote_now, '%H:%M')"
}
],
"data": [
{
"name": "dataset"
},
{
"name": "pbi_summarize"
},
{
"name": "schedule_bands",
"source": "dataset",
"transform": [
{
"type": "filter",
"expr": "datum.day_num != null && (datum.ScheduleType == 'Production' || datum.ScheduleType == 'ITSupport') && datum.day_num == remote_day"
},
{
"type": "formula",
"as": "display_type",
"expr": "datum.type == 'Normal' ? (datum.ScheduleType == 'Production' ? 'Working hours' : 'Support hours') : datum.type == 'Flexible' ? 'Flexible hours' : 'No Working hours'"
}
]
},
{
"name": "site_opening_start",
"source": "dataset",
"transform": [
{"type": "filter", "expr": "datum.day_num != null && datum.ScheduleType == 'SiteOpening' && datum.day_num == remote_day"},
{"type": "project", "fields": ["startTime"], "as": ["time_value"]}
]
},
{
"name": "site_opening_end",
"source": "dataset",
"transform": [
{"type": "filter", "expr": "datum.day_num != null && datum.ScheduleType == 'SiteOpening' && datum.day_num == remote_day"},
{"type": "project", "fields": ["endTime"], "as": ["time_value"]}
]
}
],
"scales": [
{
"name": "xscale",
"type": "linear",
"range": "width",
"domain": [0, 24]
},
{
"name": "yscale",
"type": "band",
"range": [1, 50],
"domain": ["ITSupport", "Production"],
"padding": 0.1
},
{
"name": "color",
"type": "ordinal",
"domain": ["Working hours", "Support hours", "Flexible hours", "No Working hours"],
"range": ["#a6cee3", "#b2df8a", "#1f78b4", "#d3d3d3"]
}
],
"axes": [
{
"orient": "bottom",
"scale": "xscale",
"tickCount": 25,
"title": {
"signal": "timeFormat(remote_now, 'Time & Day (%Y-%m-%d)')"
},
"labelFontSize": 9,
"titleFontSize": 9
}
],
"marks": [
{
"type": "group",
"name": "custom_legend",
"encode": {"enter": {"x": {"value": 0}, "y": {"value": -40}}},
"marks": [
{"type": "rect", "encode": {"enter": {"x": {"value": 0}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#a6cee3"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 15}, "y": {"value": 9}, "text": {"value": "Working hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}},
{"type": "rect", "encode": {"enter": {"x": {"value": 120}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#1f78b4"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 135}, "y": {"value": 9}, "text": {"value": "Flexible hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}},
{"type": "rect", "encode": {"enter": {"x": {"value": 240}, "y": {"value": 0}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#d3d3d3"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 255}, "y": {"value": 9}, "text": {"value": "No Working hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}},
{"type": "rect", "encode": {"enter": {"x": {"value": 0}, "y": {"value": 15}, "width": {"value": 10}, "height": {"value": 10}, "fill": {"value": "#b2df8a"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 15}, "y": {"value": 24}, "text": {"value": "Support hours"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}},
{"type": "rule", "encode": {"enter": {"x": {"value": 122}, "y": {"value": 13}, "x2": {"value": 122}, "y2": {"value": 23}, "stroke": {"value": "black"}}}},
{"type": "symbol", "encode": {"enter": {"x": {"value": 122}, "y": {"value": 22}, "shape": {"value": "triangle-up"}, "size": {"value": 25}, "fill": {"value": "black"}}}},
{"type": "rule", "encode": {"enter": {"x": {"value": 128}, "y": {"value": 15}, "x2": {"value": 128}, "y2": {"value": 24}, "stroke": {"value": "black"}}}},
{"type": "symbol", "encode": {"enter": {"x": {"value": 128}, "y": {"value": 15}, "shape": {"value": "triangle-down"}, "size": {"value": 25}, "fill": {"value": "black"}}}},
{"type": "text", "encode": {"enter": {"x": {"value": 135}, "y": {"value": 24}, "text": {"value": "Site Opening"}, "fontSize": {"value": 10}, "align": {"value": "left"}}}}
]
},
{
"type": "rect",
"from": {"data": "schedule_bands"},
"encode": {
"enter": {
"x": {"scale": "xscale", "field": "startTime"},
"x2": {"scale": "xscale", "field": "endTime"},
"y": {"scale": "yscale", "field": "ScheduleType"},
"height": {"scale": "yscale", "band": 1},
"fill": {"scale": "color", "field": "display_type"}
}
}
},
{
"type": "rule",
"from": {"data": "site_opening_start"},
"encode": {"enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 0}, "y2": {"value": 50}, "stroke": {"value": "black"}, "strokeWidth": {"value": 2}}}
},
{
"type": "symbol",
"from": {"data": "site_opening_start"},
"encode": {"enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 50}, "shape": {"value": "triangle-up"}, "size": {"value": 50}, "fill": {"value": "black"}}}
},
{
"type": "rule",
"from": {"data": "site_opening_end"},
"encode": {"enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 0}, "y2": {"value": 50}, "stroke": {"value": "black"}, "strokeWidth": {"value": 2}}}
},
{
"type": "symbol",
"from": {"data": "site_opening_end"},
"encode": {"enter": {"x": {"scale": "xscale", "field": "time_value"}, "y": {"value": 3}, "shape": {"value": "triangle-down"}, "size": {"value": 50}, "fill": {"value": "black"}}}
},
{
"type": "rule",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "remote_hour_decimal"},
"y": {"value": 2}, "y2": {"value": 50},
"stroke": {"value": "red"},
"strokeWidth": {"value": 2}
}
}
},
{
"type": "text",
"encode": {
"update": {
"x": {"scale": "xscale", "signal": "remote_hour_decimal"},
"y": {"value": 3},
"text": {"signal": "remote_time_label"},
"baseline": {"value": "bottom"},
"align": {"value": "center"},
"fill": {"value": "red"}
}
}
}
]
}
Share feedback directly with Fabric product managers, participate in targeted research studies and influence the Fabric roadmap.
Check out the February 2026 Power BI update to learn about new features.