The Zurich release has arrived! Interested in new features and functionalities? Click here for more

Is there a way to share a dashboard and all the widgets it contains in a single step?

Swankeeper
Tera Contributor

I'm frequently asked to build dashboards for a single group, that can contain multiple tabs and a dozen or more reports (especially the "single-shot body count" reports).  Often that dashboard will prove useful to other teams, but I must share the dashboard itself first, and then share each contained report individually.  I find it hard to believe that SN hasn't come up with some facility to say "share this and everything in it" in one activity.

(as I tend to operate on the periphery of the core functionality, especially as it iterates from release to release, I wouldn't be shocked to learn there is such a feature, and I'm just unaware of it).

1 ACCEPTED SOLUTION

Mark Manders
Mega Patron

Platform Analytics will resolve this. Washington has a migration tool and before that it's a separate workspace. The new dashboards are just shared once and will include all of the reports. So either wait (you will be 'forced' to Platform Analytics on Yokohama), or create some custom functionality (catalog item with a request to join a dashboard, which shares the dashboards and it's content after approval). That will take a lot of scripting though.


Please mark any helpful or correct solutions as such. That helps others find their solutions.
Mark

View solution in original post

8 REPLIES 8

AndersBGS
Tera Patron
Tera Patron

Hi @Swankeeper ,

 

There is no OOTB solution from ServiceNow in relation to Dashboards. You could create a group, and share all widgets and dashboards with that group. When users are requesting access, then they should "just" be part of that group.

 

If you want an OOTB solution from ServiceNow, then you should look towards analytics workspace instead. Here you only need to share once as you're requesting.

 

If my answer has helped with your question, please mark my answer as accepted solution and give a thumb up.

 

best regards

Anders 

If my answer has helped with your question, please mark my answer as the accepted solution and give a thumbs up.

Best regards
Anders

Rising star 2024
MVP 2025
linkedIn: https://www.linkedin.com/in/andersskovbjerg/

Thank you, Anders.  We've been down the path of "make a group, share everything with the group, and then use the group for future access".  It carries (for us) an overhead cost almost akin to the efforts to share and re-share reports one by one.

Looking forward to the forced shift from dashboards to PA to solve this.

Mark Manders
Mega Patron

Platform Analytics will resolve this. Washington has a migration tool and before that it's a separate workspace. The new dashboards are just shared once and will include all of the reports. So either wait (you will be 'forced' to Platform Analytics on Yokohama), or create some custom functionality (catalog item with a request to join a dashboard, which shares the dashboards and it's content after approval). That will take a lot of scripting though.


Please mark any helpful or correct solutions as such. That helps others find their solutions.
Mark

pbusch
Tera Expert

I was inspired by a similar script , and created the below UI Action running on pa_dashboards ; it is a form link that is executed from the form which loads when 'Dashboard Properties' is navigated to from a given db additional actions hamburger menu.

Bear in mind that this will share all reports on every tab, but if you are in an environment with properly configured ACLs, that will be a non-issue.

 

This shares all reports on the given dashboard with every 'user' , 'group' , and 'role' that the dashboard is shared with. Other UI Field configurations can be derived from the snip I am attaching as well.

pbusch_0-1728573576992.png

 

var dashboardTabM2M = new GlideRecord('pa_m2m_dashboard_tabs');
dashboardTabM2M.addQuery("dashboard", current.sys_id);
dashboardTabM2M.query();
var canvas_pages = [];
while (dashboardTabM2M.next()) {
    canvas_pages.push(dashboardTabM2M.tab.canvas_page.sys_id + "");
}

var portal_widgets = [];

canvas_pages.forEach(function(canvas_pageID) {
    var grid_canvas_pane = new GlideRecord("sys_grid_canvas_pane");
    grid_canvas_pane.addQuery("grid_canvas", canvas_pageID);
    grid_canvas_pane.query();
    while (grid_canvas_pane.next()) {
        portal_widgets.push(grid_canvas_pane.portal_widget + '');
    }
});

var reportIds = [];
portal_widgets.forEach(function(portal_widgetIDs) {
    var portals = new GlideRecord("sys_portal");
    portals.addQuery("sys_id", portal_widgetIDs);
    portals.query();
    while (portals.next()) {
        var pageProp = new GlideRecord("sys_portal_preferences");
        pageProp.addQuery("portal_section", portals.getUniqueValue());
        pageProp.addQuery("name", "sys_id");
        pageProp.query();
        if (pageProp.next()) {
            reportIds.push(pageProp.getValue("value"));
        }
    }
});

var shareUsers = [];
var shareRoles = [];
var shareGroups = [];
var dashboardPerms = new GlideRecord("pa_dashboards_permissions");
dashboardPerms.addQuery("dashboard", current.getUniqueValue());
dashboardPerms.query();
while (dashboardPerms.next()) {
    if (dashboardPerms.type == "2")
        shareGroups.push(dashboardPerms.getValue("group"));
    if (dashboardPerms.type == "1")
        shareRoles.push(dashboardPerms.getValue("role"));
    if (dashboardPerms.type == "3")
        shareUsers.push(dashboardPerms.getValue("user"));
}

var reportGR = new GlideRecord("sys_report");
reportGR.addQuery("sys_id", "IN", reportIds.join(","));
reportGR.query();
while (reportGR.next()) {
    reportGR.setValue("user", "group");
    reportGR.update();
}

reportIds.forEach(function(reportId) {
    var validCheck = new GlideRecord('sys_report');
    if (!validCheck.get(reportId))
        return; // not a real report id

    shareGroups.forEach(function(groupId) {
        var reportPerm = new GlideRecord("sys_report_users_groups");
        reportPerm.addQuery("report_id", reportId);
        reportPerm.addQuery("group_id", groupId);
        reportPerm.query();
        if (reportPerm.next()) {
            gs.addInfoMessage(gs.getMessage("Report {0} is already shared with group {1}", [reportPerm.getDisplayValue("report_id"), reportPerm.getDisplayValue("group_id")]));
        } else {
            reportPerm.newRecord();
            reportPerm.setValue("report_id", reportId);
            reportPerm.setValue("group_id", groupId);
            reportPerm.insert();
            gs.addInfoMessage(gs.getMessage("Report {0} shared with group {1}", [reportPerm.getDisplayValue("report_id"), reportPerm.getDisplayValue("group_id")]));
        }
    });

    shareUsers.forEach(function(userId) {
        var reportPerm = new GlideRecord("sys_report_users_groups");
        reportPerm.addQuery("report_id", reportId);
        reportPerm.addQuery("user_id", userId);
        reportPerm.query();
        if (reportPerm.next()) {
            gs.addInfoMessage(gs.getMessage("Report {0} is already shared with user {1}", [reportPerm.getDisplayValue("report_id"), reportPerm.getDisplayValue("user_id")]));
        } else {
            reportPerm.newRecord();
            reportPerm.setValue("report_id", reportId);
            reportPerm.setValue("user_id", userId);
            reportPerm.insert();
            gs.addInfoMessage(gs.getMessage("Report {0} shared with user {1}", [reportPerm.getDisplayValue("report_id"), reportPerm.getDisplayValue("user_id")]));
        }
    });

    shareRoles.forEach(function(roleId) {
        var userIds = [];
        var userRoleGR = new GlideRecord("sys_user_has_role");
        userRoleGR.addQuery("user.active", true);
        userRoleGR.addQuery("role", roleId);
        userRoleGR.query();
        var roleName;
        while (userRoleGR.next()) {
            if (!roleName) {
                roleName = userRoleGR.getDisplayValue("role"); // for info msg
            }
            userIds.push(userRoleGR.getValue("user"));
        }
        var au = new global.ArrayUtil();
        userIds = au.unique(userIds);

        var reportName;
        userIds.forEach(function(userId) {
            var reportPerm = new GlideRecord("sys_report_users_groups");
            reportPerm.addQuery("report_id", reportId);
            reportPerm.addQuery("user_id", userId);
            reportPerm.query();
            if (reportPerm.next()) {
                // gs.addInfoMessage(gs.getMessage("Report {0} is already shared with user {1}", [reportPerm.getDisplayValue("report_id"), reportPerm.getDisplayValue("user_id")]));
            } else {
                reportPerm.newRecord();
                reportPerm.setValue("report_id", reportId);
                reportPerm.setValue("user_id", userId);
                reportPerm.insert();
                gs.addInfoMessage(gs.getMessage("Report {0} shared with user {1}", [reportPerm.getDisplayValue("report_id"), reportPerm.getDisplayValue("user_id")]));
                gs.addAlert(gs.getMessage("Report {0} shared with user {1}", [reportPerm.getDisplayValue("report_id"), reportPerm.getDisplayValue("user_id")]));
                gs.addLog(gs.getMessage("Report {0} shared with user {1}", [reportPerm.getDisplayValue("report_id"), reportPerm.getDisplayValue("user_id")]));
            }
            if (!reportName) {
                reportName = reportPerm.getDisplayValue("report_id");
            }
        });
        gs.addInfoMessage(gs.getMessage("Report {0} shared with {1} users who have the {2} role", [reportName, userIds.length + "", roleName]));
    });
});

action.setRedirectURL(current);



~ "Breynia Disticha"