- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-13-2023 03:24 AM
Here is the scenario, I have a widget that contains a button. When I click the button, it will change the application scope from global to Human Resource Core. I don't know how to do it through scripting. I tried to do it through user preference table where I set the sys id of HR Core Application in apps.current_app record, the scope only changes when I restart the session.
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-13-2023 04:20 PM - edited ‎02-14-2023 02:14 AM
Here's how one could do it - obviously adapting code SN already wrote:
create new Angular Provider record:
- Type: Factory
- Name: applicationScope
- Client script:
function applicationScope ($rootScope, $http) {
var fetchedInitialData = false;
var initialized = false;
var applicationData = {
current: {},
currentId: '',
list: [],
showInHeader: false,
};
$rootScope.$on('concourse.application.changed', concourseApplicationChanged);
return {
'applicationData': applicationData,
'getApplicationList': getApplicationList,
'hasFetchedData': hasFetchedData,
'initialize': initialize,
'updateCurrent': updateCurrent,
};
function concourseApplicationChanged (evt, current) {
applicationData.current = current;
applicationData.currentId = current.sysId;
}
function getApplicationList () {
fetchedInitialData = true;
return $http
.get('/api/now/ui/concoursepicker/application?cache=' + new Date().getTime())
.then(getApplicationListResponse);
}
function getApplicationListResponse (response) {
if (response && response.data && response.data.result) {
applicationData.list = response.data.result.list;
if (response.data.result.current && response.data.result.current != applicationData.currentId) {
var apps = response.data.result.list;
var curr = response.data.result.current;
for (var i = 0; i < apps.length; i++) {
if (curr == apps[i].sysId) {
applicationData.current = apps[i];
applicationData.currentId = apps[i].sysId;
break;
}
}
triggerChangeEvent();
}
}
}
function hasFetchedData () {
return fetchedInitialData;
}
function initialize (current) {
if (initialized)
return;
initialized = true;
applicationData.list = [current];
applicationData.current = current;
applicationData.currentId = current.sysId;
}
function triggerChangeEvent () {
$rootScope.$broadcast('concourse.application.changed', applicationData.current);
}
function triggerRefreshFrameEvent () {
$rootScope.$broadcast('concourse.application.refresh', {});
}
function updateCurrent () {
var apps = applicationData.list;
var curr = applicationData.currentId;
for (var i = 0; i < apps.length; i++) {
if (curr == apps[i].sysId) {
applicationData.current = apps[i];
break;
}
}
$http
.put('/api/now/ui/concoursepicker/application', { 'app_id': applicationData.currentId })
.then(updateCurrentResponse);
}
function updateCurrentResponse (response) {
if (response && response.data && response.data.result && response.data.result.app_id) {
triggerRefreshFrameEvent();
triggerChangeEvent();
}
}
}
create new Angular Provider record:
- Type: Directive
- Name: applicationScopePicker
- Client script:
function applicationScopePicker (applicationScope, snCustomEvent) {
"use strict";
return {
'controller': function ($scope) {
$scope.app = applicationScope.applicationData;
$scope.refreshApplicationPicker = refreshApplicationPicker;
$scope.updateCurrent = updateCurrent;
snCustomEvent.observe('glide:ui_notification.application_change', applicationChanged);
snCustomEvent.observe('sn:change_application', changeApplication);
snCustomEvent.observe('sn:refresh_application_picker', refreshApplicationPicker);
if ($scope.current) {
applicationScope.initialize($scope.current);
}
function applicationChanged () {
applicationScope.getApplicationList();
}
function changeApplication (appId) {
applicationScope.getApplicationList().then(getApplicationListResponder);
}
function getApplicationListResponder (appId) {
return function getApplicationListResponse () {
applicationScope.applicationData.currentId = appId;
$scope.updateCurrent();
};
}
function refreshApplicationPicker () {
applicationScope.getApplicationList();
}
function updateCurrent () {
applicationScope.updateCurrent();
}
},
'link': function (scope, element) {
element.on('mouseover', mouseOver);
function mouseOver () {
if (!applicationScope.hasFetchedData())
applicationScope.getApplicationList();
}
},
'replace': false,
'restrict': 'E',
'scope': {
'current': '=',
'hintText': '=',
'titleText': '=',
},
'template': getTemplate(),
};
function getTemplate () {
return '\n' +
'<div class="applicationScopePicker">\n' +
' <div class="input-group">\n' +
' <span class="input-group-addon">\n' +
' <a class="icon-application-generic" data-name="current-application-picker" data-title-text="{{ titleText }}" data-toggle="tooltip" href="/sys_scope.do?sys_id={{ app.current.sysId }}" target="gsft_main">\n' +
' <span class="sr-only">{{ hintText }}</span>\n' +
' </a>\n' +
' </span>\n' +
' <select class="form-control" ng-change="updateCurrent()" ng-model="app.currentId" ng-options="a.sysId as a.name for a in app.list" title="{{ titleText }}"></select>\n' +
' </div>\n' +
'</div>\n' +
'';
}
}
- Related list [Required Providers]: add the previously created Factory - applicationScope
create a new Widget record:
- Body HTML template:
<div style="padding-top: 2.5em;">
<application-scope-picker
current="data.currentScope"
hint-text="data.messages.hint"
title-text="data.messages.title" />
</div>
- Server script:
(function (data) {
data.currentScope = getCurrentScope(gs.getCurrentApplicationId());
data.messages = getMessages();
function getCurrentApplicationDisplayValue (uniqueValue) {
var gr = new GlideRecord('sys_scope');
return gr.get(uniqueValue) ? gr.getDisplayValue() : uniqueValue;
}
function getCurrentScope (currentApplicationId) {
return {
'name': getCurrentApplicationDisplayValue(currentApplicationId),
'sysId': currentApplicationId,
};
}
function getMessages () {
return {
'hint': gs.getMessage('View current application under development'),
'title': gs.getMessage('Show selected application'),
};
}
})(data);
- Related list [Angular Providers]: add the previously created directive: applicationScopePicker
The result:
This literally does the exact same thing as the application picker in the main UI, so as soon as the select box is updated with a new option, the scope is changed for the current user.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-13-2023 03:33 AM - edited ‎02-13-2023 03:35 AM
Hello @Fazeel Ahmed ,
Maybe restarting the user session through script might help you out. Please find below mentioned thread regarding the same:
How can I refresh a user session via script
If my answer has helped with your question, please mark it as correct and give it a thumbs up!
Regards,
Shubham
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-13-2023 05:23 AM
He suggest GlideSecurityManager but it's not working. do you have any idea why?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-13-2023 03:34 AM
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎02-13-2023 04:20 PM - edited ‎02-14-2023 02:14 AM
Here's how one could do it - obviously adapting code SN already wrote:
create new Angular Provider record:
- Type: Factory
- Name: applicationScope
- Client script:
function applicationScope ($rootScope, $http) {
var fetchedInitialData = false;
var initialized = false;
var applicationData = {
current: {},
currentId: '',
list: [],
showInHeader: false,
};
$rootScope.$on('concourse.application.changed', concourseApplicationChanged);
return {
'applicationData': applicationData,
'getApplicationList': getApplicationList,
'hasFetchedData': hasFetchedData,
'initialize': initialize,
'updateCurrent': updateCurrent,
};
function concourseApplicationChanged (evt, current) {
applicationData.current = current;
applicationData.currentId = current.sysId;
}
function getApplicationList () {
fetchedInitialData = true;
return $http
.get('/api/now/ui/concoursepicker/application?cache=' + new Date().getTime())
.then(getApplicationListResponse);
}
function getApplicationListResponse (response) {
if (response && response.data && response.data.result) {
applicationData.list = response.data.result.list;
if (response.data.result.current && response.data.result.current != applicationData.currentId) {
var apps = response.data.result.list;
var curr = response.data.result.current;
for (var i = 0; i < apps.length; i++) {
if (curr == apps[i].sysId) {
applicationData.current = apps[i];
applicationData.currentId = apps[i].sysId;
break;
}
}
triggerChangeEvent();
}
}
}
function hasFetchedData () {
return fetchedInitialData;
}
function initialize (current) {
if (initialized)
return;
initialized = true;
applicationData.list = [current];
applicationData.current = current;
applicationData.currentId = current.sysId;
}
function triggerChangeEvent () {
$rootScope.$broadcast('concourse.application.changed', applicationData.current);
}
function triggerRefreshFrameEvent () {
$rootScope.$broadcast('concourse.application.refresh', {});
}
function updateCurrent () {
var apps = applicationData.list;
var curr = applicationData.currentId;
for (var i = 0; i < apps.length; i++) {
if (curr == apps[i].sysId) {
applicationData.current = apps[i];
break;
}
}
$http
.put('/api/now/ui/concoursepicker/application', { 'app_id': applicationData.currentId })
.then(updateCurrentResponse);
}
function updateCurrentResponse (response) {
if (response && response.data && response.data.result && response.data.result.app_id) {
triggerRefreshFrameEvent();
triggerChangeEvent();
}
}
}
create new Angular Provider record:
- Type: Directive
- Name: applicationScopePicker
- Client script:
function applicationScopePicker (applicationScope, snCustomEvent) {
"use strict";
return {
'controller': function ($scope) {
$scope.app = applicationScope.applicationData;
$scope.refreshApplicationPicker = refreshApplicationPicker;
$scope.updateCurrent = updateCurrent;
snCustomEvent.observe('glide:ui_notification.application_change', applicationChanged);
snCustomEvent.observe('sn:change_application', changeApplication);
snCustomEvent.observe('sn:refresh_application_picker', refreshApplicationPicker);
if ($scope.current) {
applicationScope.initialize($scope.current);
}
function applicationChanged () {
applicationScope.getApplicationList();
}
function changeApplication (appId) {
applicationScope.getApplicationList().then(getApplicationListResponder);
}
function getApplicationListResponder (appId) {
return function getApplicationListResponse () {
applicationScope.applicationData.currentId = appId;
$scope.updateCurrent();
};
}
function refreshApplicationPicker () {
applicationScope.getApplicationList();
}
function updateCurrent () {
applicationScope.updateCurrent();
}
},
'link': function (scope, element) {
element.on('mouseover', mouseOver);
function mouseOver () {
if (!applicationScope.hasFetchedData())
applicationScope.getApplicationList();
}
},
'replace': false,
'restrict': 'E',
'scope': {
'current': '=',
'hintText': '=',
'titleText': '=',
},
'template': getTemplate(),
};
function getTemplate () {
return '\n' +
'<div class="applicationScopePicker">\n' +
' <div class="input-group">\n' +
' <span class="input-group-addon">\n' +
' <a class="icon-application-generic" data-name="current-application-picker" data-title-text="{{ titleText }}" data-toggle="tooltip" href="/sys_scope.do?sys_id={{ app.current.sysId }}" target="gsft_main">\n' +
' <span class="sr-only">{{ hintText }}</span>\n' +
' </a>\n' +
' </span>\n' +
' <select class="form-control" ng-change="updateCurrent()" ng-model="app.currentId" ng-options="a.sysId as a.name for a in app.list" title="{{ titleText }}"></select>\n' +
' </div>\n' +
'</div>\n' +
'';
}
}
- Related list [Required Providers]: add the previously created Factory - applicationScope
create a new Widget record:
- Body HTML template:
<div style="padding-top: 2.5em;">
<application-scope-picker
current="data.currentScope"
hint-text="data.messages.hint"
title-text="data.messages.title" />
</div>
- Server script:
(function (data) {
data.currentScope = getCurrentScope(gs.getCurrentApplicationId());
data.messages = getMessages();
function getCurrentApplicationDisplayValue (uniqueValue) {
var gr = new GlideRecord('sys_scope');
return gr.get(uniqueValue) ? gr.getDisplayValue() : uniqueValue;
}
function getCurrentScope (currentApplicationId) {
return {
'name': getCurrentApplicationDisplayValue(currentApplicationId),
'sysId': currentApplicationId,
};
}
function getMessages () {
return {
'hint': gs.getMessage('View current application under development'),
'title': gs.getMessage('Show selected application'),
};
}
})(data);
- Related list [Angular Providers]: add the previously created directive: applicationScopePicker
The result:
This literally does the exact same thing as the application picker in the main UI, so as soon as the select box is updated with a new option, the scope is changed for the current user.