I had an idea and I am pretty sure that I know the answer but i'm hoping someone knows for sure. I know that the custom dashboard can't directly manipulate the file system to create a flag file or edit registry key or something to cause BigFix to trigger an action but from a custom Client Dashboard in the Self-Service Application is there any way to initiate an offer from the custom client dashboard rather than the offers panel, or initiate any kind of change that could be used to initiate an action on the device?
@JasonWalker I know you have done some work with Client dashboards in the past but are you aware of any way to do this?
We have an offer that will do what we call a Network health check. I was curious if there was any way to kick off the offer for the Network Health check from within a dashboard instead of them opening the Dashboard and then having to go to the offers tab and accept it then come back to the Dashboard to get the results.
I'm also genuinely curious what others are doing with Client Dashboards. We have used a Device Dashboard for a number of years but somewhat recently with one of the 3.4 builds it seems to have broken the javascript running in our dashboard, so the collapsing menus broke. Since it felt out of date, I re-wrote it and modernized it quite a bit and it got me thinking of what else might be possible within Client Dashboards. If anyone would be willing to share what you have done with Client Dashboards i'd be very interested in what they are being used for in other places.
Why, yes, yes you can.
The thing you want to execute (i.e. the Network Health Check) does need to exist as an open action, and it needs to be an Offer...but you aren't limited to using the 'Offers' tab to accept the offer, there are specially-crafted URLs you can use in custom dashboards to accept the offer action.
Let me check docs on this, be back shortly.
Accept a single offer for action 104888
<a href="takeoffer:10488"> Accept Offer 10488</a></p>
Create a table of Offers that can be accepted:
<table border="all">
<?relevance
concatenation of trs of (td of html ("<a href=%22takeoffer:" & item 0 of it as string & "%22>" & item 1 of it & "</a>")) of (id of it, value of header "Subject" of it) of actions (ids of fixlets whose (value of header "X-Action-Component-Type" of it = "Action") of sites whose (type of it = "Master Action Site" or type of it = "Operator Site" or type of it = "Mailbox Site")) whose (offer of it and pending of it)
?>
</table>
Hiding an Offer from the 'Offers' tab:
When you submit the Action, if you specify a 'Category' value that begins with "dashboard", that action is hidden from the default Offers tab of the BESClientUI / SSA. This allows for specific client-side dashboards to handle the offer exclusively - so we could have Software Distribution offers that don't clutter up the 'Offers' tab, and only appear in a SWD client dashboard page, for example.
We can leverage this to create an action that is hidden from the 'Offers' tab by default:
...then we could have a custom client dashboard that builds the table of links, that only includes our hidden-dashboard actions:
<table border="all">
<?relevance
concatenation of trs of (td of html ("<a href=%22takeoffer:" & item 0 of it as string & "%22>" & item 1 of it & "</a>")) of (id of it, value of header "Subject" of it) of actions (ids of fixlets whose (value of header "X-Action-Component-Type" of it = "Action") of sites whose (type of it = "Master Action Site" or type of it = "Operator Site" or type of it = "Mailbox Site")) whose (offer of it and pending of it and value of header "offer-ui-category" of it = "dashboard:MyHiddenDashboard")
?>
</table>
In that last piece, my original notebook actually had the offer-ui-category value as "dashboard%253aMyHiddenDashboard" - I'm not exactly sure which syntax is needed, my notebook has been translated through a few different tools over the users and that might be a botched character encoding. So the value there might be one of
dashboard:MyHiddenDashboard
dashboard%3aMyHiddenDashboard
dashboard%253aMyHiddenDashboard
If you dig into that, please post back which one is correct and I'll update it here.
This is exactly what I was looking for ! Thank you very much ! I knew there was something that I had found regarding accepting offers and also remember seeing the hidden dashboard but couldn't find it when I went searching for it.
Thanks a lot !
I'm also looking for official documentation how to create client dashboard for the Self Service Application.
I've found the following documentation - Creating custom client dashboards and I was able to create a new tab named "Dashboard" and some general information
I want to change the:
- name of the Tabe to a different name
- change the Icon
- Want to list all of the relevant offers that I will choose with some additional information
Hi @orbiton ,
This might help
Brad Sexton also created a blog post on Linked in regarding how to begin with Self-Service Application.
(6) BigFix - Customize the Self Service Application | LinkedIn
Thanks all , I'm trying to understand if all of those are officially supported by the vendor and if there is any official guidelines - Ive opened support case to verify this.
I'd be curious what response you get on that. It's certainly a difficult area to support custom content of any kind... in the context of a fixlet or custom dashboard, I think we'd have to treat it as something like "we won't troubleshoot your dashboard, but if you can demonstrate a specific function or statement that does not behave as documented, we can produce fixes for that"
this is great: so many things I have been trying tro do have been spelled out here ![]()
I have also been stymied by the evaluation of âexists active actionsâ.
I want to let my users know that âsomething else is currently running, and this may affect their offer speedâ. However, that relevance doesnât seem to get re-evaluated in the UI.
There is a way to add a "Refresh" button to the dashboard, as well as a way to automatically refresh on a timer, but I'm having an issue making mine refresh specifically while there's an action running. It may be that the client won't respond to refresh requests while there's an action running? I'm not certain though, I'm upgrading my SSA to the latest version and will try early next week
Remind me if I forget ![]()
EDIT: Ignore my last post. I just read the part in your post about a timer.
So... This is pretty cool. For the record my dashboard is still a work in progress and trying to work on it in my free time and it still has a bit of work to do on it. I have it counting down until the next refresh but I also have a manual refresh button as well which gets disabled if someone presses the manual refresh to prevent someone from clicking it repeatedly.
jgstew has a method for refreshing the content on his dashboard example but I did something slightly different with mine bigfix-content/clientui/offers/_dashboard.html at main · jgstew/bigfix-content · GitHub
I set mine to 3 minutes, so I didn't have to wait so long. (I get impatient)
Here is the
<div class="last-updated">
<span>Page last updated: <?relevance now ?></span>
<span id="refreshCountdown" style="margin-left: 12px; opacity: 0.9;">Next refresh in 5:00</span>
<a class="refresh-btn" id="refreshBtn" href="javascript:void(0);" onclick="manualRefresh()">â» Refresh</a>
</div>
Then I have a dashboard.js that I have some other javascript functions running from that I added this function to.
// ===== Auto-refresh every 3 minutes =====
(function() {
const REFRESH_INTERVAL = 180; // seconds (3 minutes)
let timeLeft = REFRESH_INTERVAL;
function updateCountdown() {
const el = document.getElementById("refreshCountdown");
if (el) {
const minutes = Math.floor(timeLeft / 60);
const seconds = timeLeft % 60;
el.textContent = "Next refresh in " + minutes + ":" + (seconds < 10 ? "0" : "") + seconds;
}
if (timeLeft <= 0) {
window.location.href = "cid:load?page=_dashboard.html";
} else {
timeLeft--;
setTimeout(updateCountdown, 1000);
}
}
// Start after page is ready
window.addEventListener("load", function() {
setTimeout(updateCountdown, 500);
});
})();
// ===== Manual Refresh Button function + Disable Button ib click =====
function manualRefresh() {
const btn = document.getElementById("refreshBtn");
if (btn) {
btn.style.opacity = "0.45";
btn.style.pointerEvents = "none"; // disables clicking
btn.textContent = "â» Refreshing...";
}
// Small delay then actually refresh
setTimeout(function() {
window.location.href = "cid:load?page=_dashboard.html";
}, 150);
}
// Disable the button while the countdown is running so users canât spam it right after a refresh
window.addEventListener("load", function() {
const btn = document.getElementById("refreshBtn");
if (btn) {
// Keep it enabled on load, but you can force a short cooldown if desired
btn.style.opacity = "1";
btn.style.pointerEvents = "auto";
}
});
That looks great! Thanks for sharing, I'll be adding that timer to my dashboards ![]()
(exists active action) does seem to work to identify if an action is running (at least in debugger) but there isn't a way to show what the name or ID of that action is, is there?
@JasonWalker I finally got time to work on the actual offers last night and unfortunately it doesn't seem like adding dashboard: to the category hides it from the offers tab any longer.
I was able to confirm that the correct format for the relevance statement is
concatenation of trs of (td of html ("<a href=%22takeoffer:" & item 0 of it as string & "%22>" & item 1 of it & "</a>")) of (id of it, value of header "Subject" of it) of actions (ids of fixlets whose (value of header "X-Action-Component-Type" of it = "Action") of sites whose (type of it = "Master Action Site" or type of it = "Operator Site" or type of it = "Mailbox Site")) whose (offer of it and pending of it and value of header "offer-ui-category" of it = "dashboard%253aMyHiddenDashboard")
I did find a reference to a forum post where this was discussed in 2022 and apparently it wasn't working then either.
Self Service Technician Tab HTML - BigFix Forum
I'm posting this here Please Upvote this Idea if this is something you would like to see added back.


