Skip to content
Open
11 changes: 11 additions & 0 deletions edge-apps/powerbi/screenly.yml
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you reformat the code? Let's not touch it until the global config

Copy link
Collaborator Author

@salmanfarisvp salmanfarisvp Dec 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rusko124 to fix the lint errors. D

Would you like me to revert it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,14 @@ settings:
help_text: The URL of the Power BI dashboard or report to display.
type: oauth:power_bi:embed_url
schema_version: 1
app_refresh_interval:
type: string
title: App Refresh Interval (minutes)
optional: true
default_value: '30'
help_text:
properties:
advanced: true
help_text: How often to refresh the Power BI report/dashboard (in minutes). Default is 30 minutes. Minimum is 1 minute.
type: number
schema_version: 1
11 changes: 11 additions & 0 deletions edge-apps/powerbi/screenly_qc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,14 @@ settings:
help_text: The URL of the Power BI dashboard or report to display.
type: oauth:power_bi:embed_url
schema_version: 1
app_refresh_interval:
type: string
title: App Refresh Interval (minutes)
optional: true
default_value: '30'
help_text:
properties:
advanced: true
help_text: How often to refresh the Power BI report/dashboard (in minutes). Default is 30 minutes. Minimum is 1 minute.
type: number
schema_version: 1
88 changes: 56 additions & 32 deletions edge-apps/powerbi/static/js/main.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
/* global screenly, panic */

(function () {
const DEFAULT_TOKEN_REFRESH_SEC = 30 * 60; // refresh token every 30 minutes
const MIN_TOKEN_REFRESH_MIN = 1;
const DEFAULT_TOKEN_REFRESH_MIN = 30;

function getTokenRefreshInterval() {
var intervalMinutes = parseInt(screenly.settings.app_refresh_interval, 10);
if (isNaN(intervalMinutes) || intervalMinutes < MIN_TOKEN_REFRESH_MIN) {
return DEFAULT_TOKEN_REFRESH_MIN * 60;
}
return intervalMinutes * 60;
}

function getEmbedTypeFromUrl(url) {
switch (true) {
case url.indexOf('/dashboard') !== -1:
return 'dashboard';
case url.indexOf("/dashboard") !== -1:
return "dashboard";
default:
return 'report';
return "report";
}
}

Expand All @@ -17,13 +26,16 @@
return screenly.settings.embed_token;
}

var response = await fetch(screenly.settings.screenly_oauth_tokens_url + 'embed_token/', {
method: 'GET',
headers: {
Accept: 'application/json',
Authorization: `Bearer ${screenly.settings.screenly_app_auth_token}`,
var response = await fetch(
screenly.settings.screenly_oauth_tokens_url + "embed_token/",
{
method: "GET",
headers: {
Accept: "application/json",
Authorization: `Bearer ${screenly.settings.screenly_app_auth_token}`,
},
},
});
);

const { token } = await response.json();
return token;
Expand All @@ -33,15 +45,19 @@
var currentErrorStep = 0;
var initErrorDelaySec = 15;
var maxErrorStep = 7;
var tokenRefreshInterval = getTokenRefreshInterval();

async function run() {
var nextTimeout = DEFAULT_TOKEN_REFRESH_SEC;
var nextTimeout = tokenRefreshInterval;
try {
var newToken = await getEmbedToken();
await report.setAccessToken(newToken);
currentErrorStep = 0;
} catch {
nextTimeout = Math.min(initErrorDelaySec * Math.pow(2, currentErrorStep), nextTimeout);
nextTimeout = Math.min(
initErrorDelaySec * Math.pow(2, currentErrorStep),
nextTimeout,
);
if (currentErrorStep >= maxErrorStep) {
return;
}
Expand All @@ -50,45 +66,53 @@
setTimeout(run, nextTimeout * 1000);
}

setTimeout(run, DEFAULT_TOKEN_REFRESH_SEC * 1000);
setTimeout(run, tokenRefreshInterval * 1000);
}

async function initializePowerBI() {
const models = window['powerbi-client'].models;
const models = window["powerbi-client"].models;
const embedUrl = screenly.settings.embed_url;
const resourceType = getEmbedTypeFromUrl(embedUrl);

const report = window.powerbi.embed(document.getElementById('embed-container'), {
embedUrl: embedUrl,
accessToken: await getEmbedToken(),
type: resourceType,
tokenType: models.TokenType.Embed,
permissions: models.Permissions.All,
settings: {
filterPaneEnabled: false,
navContentPaneEnabled: false,
const report = window.powerbi.embed(
document.getElementById("embed-container"),
{
embedUrl: embedUrl,
accessToken: await getEmbedToken(),
type: resourceType,
tokenType: models.TokenType.Embed,
permissions: models.Permissions.All,
settings: {
filterPaneEnabled: false,
navContentPaneEnabled: false,
},
},
});
);

if (resourceType === 'report') {
report.on('rendered', screenly.signalReadyForRendering);
} else if (resourceType === 'dashboard') {
report.on('loaded', () => {
if (resourceType === "report") {
report.on("rendered", screenly.signalReadyForRendering);
} else if (resourceType === "dashboard") {
report.on("loaded", () => {
setTimeout(screenly.signalReadyForRendering, 1000);
});
}

if (!screenly.settings.embed_token) {
initTokenRefreshLoop(report);
}

return report;
}

panic.configure({
handleErrors: screenly.settings.display_errors == 'true' || false,
handleErrors: screenly.settings.display_errors == "true" || false,
});
if (screenly.settings.display_errors == 'true') {
window.addEventListener('error', screenly.signalReadyForRendering);
window.addEventListener('unhandledrejection', screenly.signalReadyForRendering);
if (screenly.settings.display_errors == "true") {
window.addEventListener("error", screenly.signalReadyForRendering);
window.addEventListener(
"unhandledrejection",
screenly.signalReadyForRendering,
);
}

initializePowerBI();
Expand Down