- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎09-09-2022 09:29 PM
Hi,
I have been task with creating a Role Base Access (RBAC) table. This custom table is used for our Identity Access Management.
I had an idea that would allow our business users to do attestation of the job codes and job profiles that they own in that RBAC table from within the Service portal.
I am a bit stuck with what I am trying to accomplish. Below is a screenshot that I hope would make sense.
Part 1 of my question:
I created a left navigation that contains a list of records from that custom RBAC table where the Portal Identifier is not empty. As you can see in the above image, the side navigation has duplicate values. The reason there are duplicate values is that each record may have the same job code, but different applications. That is what makes up the RBAC table. How can I get that list to display only unique values?
Part 2 of my question:
If I can get the left navigation working, I want it so that if they click on one of the options in the left navigation then in the table list on the right would display only the records that match the Portal Identifier of the option selected.
Any ideas on how to achieve this?
Solved! Go to Solution.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎09-12-2022 12:08 AM
In the server script you should not do this:
var data = {
'rbac': []
};
you are hiding the "real" object data
and so your data will not arrive to client side.
You can load the data directly, there is no need to pump it through function simulateRow
- I did so only to make the code "demonstrable" in Scripts - Background:
var rbacGR = new GlideRecord('u_role_base_access');
rbacGR.addQuery('u_active', true);
rbacGR.query();
while (rbacGR.next()) {
data.rbac.push({
'portalIdentifier': rbacGR.u_portal_identifier.toString(),
'jobCode': rbacGR.u_job_code.toString(),
'jobProfileName': rbacGR.u_job_profile_name.toString(),
'costCenterID': rbacGR.getUniqueValue(),
'costCenterName': rbacGR.getDisplayValue(),
});
}
In my opinion
rbacGR.getUniqueValue()
is better looking than
rbacGR.sys_id.toString()
and the end result is the same - possibly a little faster.
As for the HTML template, since you are declaring "variable" rbac when writing
<... ng-repeat="rbac in data.jobs">
you have to use the same variable "down the road":
<h4 class="list-group-item-heading">
{{rbac.code}}
and
<p class="list-group-item-text">
Portal Identifier: {{rbac.portalID}}
But I must also say that
<... ng-repeat="rbac in data.jobs">
is misleading
<... ng-repeat="job in data.jobs">
better conveys "the message" of what is going on; of course the new "variable" job must be used in all places where it has been used:
<h4 class="list-group-item-heading">
{{job.code}}
<p class="list-group-item-text">
Portal Identifier: {{job.portalID}}
After those adjustments it should work.
Here's my test widget:
HTML template:
<div class="panel panel-default">
<div class="panel-heading clearfix">
<h3 class="panel-title pull-left">
${RBAC Items}
</h3>
</div>
<div class="list-group">
<a class="list-group-item" ng-click="c.selectItem($index)" ng-repeat="job in c.data.jobs">
<h class="list-group-item-heading">{{job.code}}</h>
<p class="list-group-item-text">Portal Identifier: {{job.portalID}}</p>
</a>
</div>
</div>
Server script:
(function ($sp, options, data, input) {
data.rbac = [];
var rbacGR = new GlideRecord('u_role_base_access');
rbacGR.addQuery('u_active', true);
rbacGR.query();
while (rbacGR.next()) {
data.rbac.push(simulateRow(rbacGR.u_portal_identifier.toString() + ',' + rbacGR.u_job_code.toString() + ',' + rbacGR.u_job_profile_name.toString() + ',' + rbacGR.sys_id.toString()));
}
//data.rbac.push(simulateRow('1236599,ITSM Developer,,,1236599ITSM Developer'));
//data.rbac.push(simulateRow('1236599,ITSM Developer,,,1236599ITSM Developer'));
//data.rbac.push(simulateRow('dsaDASDAS8, FDASFSDA, , , dsaDASDAS8FDASFSDA'));
//data.rbac.push(simulateRow('1236599,ITSM Developer,,,1236599ITSM Developer'));
//data.rbac.push(simulateRow('TestCode, 236589 - 1, 56989, fadsfdsafds, TestCode236589 - 1'));
data.jobs = data.rbac.reduce(groupJobs({}), []);
console.log(JSON.stringify(data, null, '\t'));
console.log(data.jobs);
function groupJobs (jobsAdded) {
return function (jobs, row) {
if (typeof jobsAdded[row.portalIdentifier] == 'undefined') {
jobsAdded[row.portalIdentifier] = true;
jobs.push({
'portalID': row.portalIdentifier,
'code': row.jobCode,
'profileName': row.jobProfileName
});
}
return jobs;
};
}
function addFieldToRow (fields) {
return function (row, fieldName, index) {
row[fieldName] = fields[index];
return row;
};
}
function simulateRow (data) {
var fields = data.split(/\s*,\s*/g),
row = {};
return ['portalIdentifier', 'jobCode', 'jobProfileName', 'costCenterID', 'costCenterName'].reduce(addFieldToRow(fields), row)
}
})($sp, options, data, input);
Note that using
console.log()
in the server script does not mean that the data logged actually is present client side. To test the data on client side one should use console.log()
in the Client controller script. For sure while both look the same, there is absolutely no connection/relation between the server side console.log()
and the client side control.log();
On the other hand, on client side - at least, there is an even easier way to inspect the data: right (inverse) click on the widget while holding down Ctrl than activating either the "Log to console: $scope.data" or the "Log to console: $scope" menu items:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎09-11-2022 04:07 PM
Thank you so much for your help in this.
HTML script:
<div class="panel panel-default">
<div class="panel-heading clearfix">
<h3 class="panel-title pull-left">
${RBAC Items}
</h3>
</div>
<div class="list-group">
<a class="list-group-item" ng-click="c.selectItem($index)" ng-repeat="rbac in data.jobs">
<h4 class="list-group-item-heading">
{{rbac.jobs.code}}
</h4>
<p class="list-group-item-text">
Portal Identifier: {{rbac.jobs.portalID}}
</p>
</a>
</div>
</div>
Client script:
function($rootScope,$scope) {
/* widget controller */
var c = this;
c.selectItem = function(idx) {
var id = c.data.jobs[idx].portalID;
console.log('Portal ID: ' + id);
$rootScope.rbacID = id;
$rootScope.$emit('selectRBAC', id);
}
}
Server Script:
(function() {
//create an array to populate with notes
var data = {
'rbac': []
};
var rbacGR = new GlideRecord('u_role_base_access');
rbacGR.addQuery('u_active', true);
rbacGR.query();
while (rbacGR.next()) {
data.rbac.push(simulateRow(rbacGR.u_portal_identifier.toString()+','+rbacGR.u_job_code.toString()+','+rbacGR.u_job_profile_name.toString()+','+rbacGR.sys_id.toString()));
}
data.jobs = data.rbac.reduce(groupJobs({}), []);
console.log(JSON.stringify(data, null, '\t'));
console.log(data.jobs);
function groupJobs (jobsAdded) {
return function (jobs, row) {
if (typeof jobsAdded[row.portalIdentifier] == 'undefined') {
jobsAdded[row.portalIdentifier] = true;
jobs.push({
'portalID': row.portalIdentifier,
'code': row.jobCode,
'profileName': row.jobProfileName
});
}
return jobs;
};
}
function addFieldToRow (fields) {
return function (row, fieldName, index) {
row[fieldName] = fields[index];
return row;
};
}
function simulateRow(data) {
var fields = data.split(/\s*,\s*/g),
row = {};
return ['portalIdentifier',
'jobCode',
'jobProfileName',
'costCenterID',
'costCenterName'].reduce(addFieldToRow(fields), row)
}
})();
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎09-12-2022 12:08 AM
In the server script you should not do this:
var data = {
'rbac': []
};
you are hiding the "real" object data
and so your data will not arrive to client side.
You can load the data directly, there is no need to pump it through function simulateRow
- I did so only to make the code "demonstrable" in Scripts - Background:
var rbacGR = new GlideRecord('u_role_base_access');
rbacGR.addQuery('u_active', true);
rbacGR.query();
while (rbacGR.next()) {
data.rbac.push({
'portalIdentifier': rbacGR.u_portal_identifier.toString(),
'jobCode': rbacGR.u_job_code.toString(),
'jobProfileName': rbacGR.u_job_profile_name.toString(),
'costCenterID': rbacGR.getUniqueValue(),
'costCenterName': rbacGR.getDisplayValue(),
});
}
In my opinion
rbacGR.getUniqueValue()
is better looking than
rbacGR.sys_id.toString()
and the end result is the same - possibly a little faster.
As for the HTML template, since you are declaring "variable" rbac when writing
<... ng-repeat="rbac in data.jobs">
you have to use the same variable "down the road":
<h4 class="list-group-item-heading">
{{rbac.code}}
and
<p class="list-group-item-text">
Portal Identifier: {{rbac.portalID}}
But I must also say that
<... ng-repeat="rbac in data.jobs">
is misleading
<... ng-repeat="job in data.jobs">
better conveys "the message" of what is going on; of course the new "variable" job must be used in all places where it has been used:
<h4 class="list-group-item-heading">
{{job.code}}
<p class="list-group-item-text">
Portal Identifier: {{job.portalID}}
After those adjustments it should work.
Here's my test widget:
HTML template:
<div class="panel panel-default">
<div class="panel-heading clearfix">
<h3 class="panel-title pull-left">
${RBAC Items}
</h3>
</div>
<div class="list-group">
<a class="list-group-item" ng-click="c.selectItem($index)" ng-repeat="job in c.data.jobs">
<h class="list-group-item-heading">{{job.code}}</h>
<p class="list-group-item-text">Portal Identifier: {{job.portalID}}</p>
</a>
</div>
</div>
Server script:
(function ($sp, options, data, input) {
data.rbac = [];
var rbacGR = new GlideRecord('u_role_base_access');
rbacGR.addQuery('u_active', true);
rbacGR.query();
while (rbacGR.next()) {
data.rbac.push(simulateRow(rbacGR.u_portal_identifier.toString() + ',' + rbacGR.u_job_code.toString() + ',' + rbacGR.u_job_profile_name.toString() + ',' + rbacGR.sys_id.toString()));
}
//data.rbac.push(simulateRow('1236599,ITSM Developer,,,1236599ITSM Developer'));
//data.rbac.push(simulateRow('1236599,ITSM Developer,,,1236599ITSM Developer'));
//data.rbac.push(simulateRow('dsaDASDAS8, FDASFSDA, , , dsaDASDAS8FDASFSDA'));
//data.rbac.push(simulateRow('1236599,ITSM Developer,,,1236599ITSM Developer'));
//data.rbac.push(simulateRow('TestCode, 236589 - 1, 56989, fadsfdsafds, TestCode236589 - 1'));
data.jobs = data.rbac.reduce(groupJobs({}), []);
console.log(JSON.stringify(data, null, '\t'));
console.log(data.jobs);
function groupJobs (jobsAdded) {
return function (jobs, row) {
if (typeof jobsAdded[row.portalIdentifier] == 'undefined') {
jobsAdded[row.portalIdentifier] = true;
jobs.push({
'portalID': row.portalIdentifier,
'code': row.jobCode,
'profileName': row.jobProfileName
});
}
return jobs;
};
}
function addFieldToRow (fields) {
return function (row, fieldName, index) {
row[fieldName] = fields[index];
return row;
};
}
function simulateRow (data) {
var fields = data.split(/\s*,\s*/g),
row = {};
return ['portalIdentifier', 'jobCode', 'jobProfileName', 'costCenterID', 'costCenterName'].reduce(addFieldToRow(fields), row)
}
})($sp, options, data, input);
Note that using
console.log()
in the server script does not mean that the data logged actually is present client side. To test the data on client side one should use console.log()
in the Client controller script. For sure while both look the same, there is absolutely no connection/relation between the server side console.log()
and the client side control.log();
On the other hand, on client side - at least, there is an even easier way to inspect the data: right (inverse) click on the widget while holding down Ctrl than activating either the "Log to console: $scope.data" or the "Log to console: $scope" menu items:
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎09-12-2022 02:37 PM
This worked. I really appreciate all that help that you have given me. I learned so much from your examples.
Thank you again.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
‎09-13-2022 12:13 PM
You're most welcome! 🙂