still sharpening up my angular/bootstrap skills but this does the trick functionally!
at the moment the sort by state is not working too great as it's held in different fields in the target tables (document_id > KB, CHG, RITM )
Contents
HTML
<!--
https://xd.adobe.com/view/0305f2c4-d644-4abb-8558-269aab4c658c-5656/screen/16db5429-79fc-4240-acbb-693a42cdf99d/specs/
https://xd.adobe.com/view/0305f2c4-d644-4abb-8558-269aab4c658c-5656/screen/1c1d968d-a267-4eca-868a-0a346f327916/specs/
https://xd.adobe.com/view/0305f2c4-d644-4abb-8558-269aab4c658c-5656/screen/21c0ca7f-8363-4625-bc93-7ba9f87a20c6/specs/
-->
<div class="ma-container">
<div>
<!-- your widget template -->
<h1 class="mi1">My Approvals</h1>
<!-- current user: {{data.sysUserID}}-->
</div>
<div class="ma-openclosed">
<div class="ma-padded">
<div class="ma-center">
<button id="ma-button-open" autofocus class="btn btn-default" ng-click="ma_showOpen()">Open Approvals</button>
<button id="ma-button-closed" class="btn btn-default" ng-click="ma_showClosed()">Closed Approvals</button>
</div>
<div class="typea">
<widget id="typeahead-search"
options=data.search_options></widget>
</div>
</div>
</div>
<div class="panel-heading break-word">
<h2 id="ma-total-panel-title" class="h4 panel-title">{{c.resultsList}}
<span class="issues-total">{{c.totalTickets}}</span>
{{c.cellPadder}}<span class="sortby-small">Sorted by: {{c.sortedBy}}</span>
<span class="issues-sort" >Sort by:
<button id="ma-button-sort-1" class="btn btn-default" ng-click="ma_sort_last_updated()">Last updated</button>
<button id="ma-button-sort-2" class="btn btn-default" ng-click="ma_sort_created_date()">Created date</button>
<button id="ma-button-sort-3" class="btn btn-default" ng-click="ma_sort_status()">Status</button>
</span>
</h2>
</div>
<div id="ma-open-tickets" ng-model = "c.openList" ng-hide="{{c.data.showOpen}}">
<div ng-repeat="openTicket in
c.openTickets" >
<div class="panel-body b-b result-item" style="background-color:#F2FBFE">
<!--buttons-->
<div style="float: right;">
<div class="divider"></div>
<!--APPROVE:--><button class="btn btn-default" style="background-color:#145896;color:#F2FBFE;font-size:14px" ng-click="c.ma_approveRecord(${openTicket.approval_ticket},
${openTicket.sys_id})">Approve</button>
<!--REJECT:--><button class="btn btn-default" style="background-color:white;color:#145896;font-size:14px" ng-click="c.ma_rejectRecord(${openTicket.approval_ticket},${openTicket.sys_id})">Reject</button>
</div>
<a href="?id=ticket&sys_id={{openTicket.sys_id}}&table=sysapproval_approver"><span style="font-size:16px">Approval for:
{{openTicket.approval_ticket}}, {{openTicket.short_description}}</span>
</a><br/>
<span id="ma-fi-updated-o-{{openTicket.number}}" style="font-weight:normal" class="ma-fi">Requestor: {{openTicket.requestor}}</span>
<!--{{c.cellPadder}}<span
id="ma-fi-updated-o-{{openTicket.number}}"
style="font-weight:normal" class="ma-fi">Approver:
{{openTicket.approver}}</span>-->
{{c.cellPadder}}<span id="ma-priority-o-{{openTicket.number}}" style="font-weight:{{c.highlightColor5}}" class="ma-fi">Ticket state: {{openTicket.state}}</span>
{{c.cellPadder}}<span id="ma-fi-created-o-{{openTicket.number}}" style="font-weight:{{c.highlightColor1}}" class="ma-fi">Created: {{openTicket.sys_created_on}}</span>
{{c.cellPadder}}<span id="ma-fi-updated-o-{{openTicket.number}}" style="font-weight:{{c.highlightColor2}}" class="ma-fi">Updated: {{openTicket.sys_updated_on}}</span>
</div>
<div class="ma-spacer"></div>
</div>
</div>
<div id="ma-closed-tickets" style="display:none" ng-model = "c.closedList">,
<div ng-repeat="closedTicket in
c.closedTickets" >
<div class="panel-body b-b result-item" style="background-color:#F2FBFE">
<!--buttons-->
<div style="float: right;">
<button class="btn btn-default" style="float:
right;background-color:#145896;color:#F2FBFE;font-size:14px" ng-click="ma_viewRecord(${closedTicket.sys_id})">View Approval</button>
</div>
<a href="?id=ticket&sys_id={{closedTicket.sys_id}}&table=sysapproval_approver"><span class="ma-sd">Approval for:
{{closedTicket.approval_ticket}}, {{closedTicket.short_description}}</span>
</a><br/>
<span id="ma-fi-updated-c-{{openTicket.number}}" style="font-weight:normal" class="ma-fi">Requestor: {{closedTicket.requestor}}</span>
<!--{{c.cellPadder}}<span
id="ma-fi-updated-o-{{openTicket.number}}"
style="font-weight:normal" class="ma-fi">Approver:
{{closedTicket.approver}}</span>-->
{{c.cellPadder}}<span id="ma-priority-c-{{closedTicket.number}}" style="font-weight:{{c.highlightColor5}}" class="ma-fi">Ticket state: {{closedTicket.state}}</span>
{{c.cellPadder}}<span id="ma-fi-created-c-{{closedTicket.number}}" style="font-weight:{{c.highlightColor3}}" class="ma-fi">Created:
{{closedTicket.sys_created_on}}</span>
{{c.cellPadder}}<span id="ma-fi-updated-c={{closedTicket.number}}" style="font-weight:{{c.highlightColor4}}" class="ma-fi">Updated:
{{closedTicket.sys_updated_on}}</span>
</div>
</div>
<div class="ma-spacer"></div>
</div>
</div>
CSS
/*the typeahead input within the embedded widget*/
input[name="q"] {
border-radius: 50px;
height:100%;
}
button[name="search"] {
border-radius: 50px;
height:100%;
}
button[class="input-group-btn"]{
border-radius: 50px;
}
div.typea{
width: 380px;
float: right;
padding: 15px;
}
/*end typeahead*/
h1.ma1{
color:#003057;
background-color:#F5F6F8;
font-size:25px;
}
div.ma-openclosed{
background-color:#145896;
color:white;
height: 70px;
}
div.ma-center{
margin: 0;
position: absolute;
margin-top: 12px;
}
div.ma-padded{
padding-left: 20px
!important;
}
div.ma-spacer{
height:10px;
background-color:#F5F6F8;
}
div.ma-container{
/* min-height: 703px; */
}
div.divider{
width:2px;
height:auto;
display:inline-block;
}
span.ma-fi{
font-size:14px;
color:#003057;
}
span.ma-sd{
font-size:16px;
}
span.issues-total{
color:#145896;
font-size:16px;
}
span.issues-sort{
color:#145896;
font-size:16px;
float: right;
}
span.sortby-small{
color:#2A363B;
font-size:14px;
}
span[id^='ma-fi-updated-o'] {
font-weight:bold;
}
span[id^='ma-fi-updated-c'] {
font-weight:bold;
}
/*span[id^='ma-priority']{
font-weight:normal;
}*/
#ma-total-panel-title{
color:#2A363B;
font-size:16px;
}
#ma-button-open
{background-color:#F2FBFE;
color:#145896;
font-size:18px;
}
#ma-button-open:focus {
background-color:#145896;
color:#F2FBFE;
opacity: 1;
font-size:18px;
}
#ma-button-closed {
/*background-color: white;*/
background-color:#F2FBFE;
color:#145896;
/*opacity: 1;*/
font-size:20px;
}
#ma-button-closed:focus {
background-color:#145896;
/*color:white;*/
color:#F2FBFE;
opacity: 1;
font-size:20px;
}
button[id^='ma-button-sort'] {
background-color:#F2FBFE;
color:#145896;
}
button[id^='ma-button-sort']:focus {
background-color:#145896;
color:#F2FBFE;
opacity: 1;
}
Client Script
function($scope, spModal) {
/* widget controller */
var c = this;
c.data.showOpen = false;
c.data.showClosed = true;
c.sortbystate=false;
c.resultsList = 'Total open approvals: ';
c.totalTickets = c.data.totalOpenIssues;
c.openTickets = c.data.openIssuesList;
c.closedTickets = c.data.closedIssuesList;
c.sortedBy = c.data.sortedBy;
document.getElementById("ma-button-sort-1").style.backgroundColor = "#145896";
document.getElementById("ma-button-sort-1").style.color = "#F2FBFE";
var sPad = '';
for (ic = 0; ic < 3; ic++) {
sPad += String.fromCharCode(160);
}
c.cellPadder = sPad;
//--show open button clicked-------------------
$scope.ma_showOpen = function() {
document.getElementById("ma-button-sort-1").style.backgroundColor = "#145896";
document.getElementById("ma-button-sort-1").style.color = "#F2FBFE";
c.server.get({
action: "sort_updated",
msg: "Sorting issues by updated date..."
}).then(function(r) {
c.openTickets = r.data.openIssuesList;
c.closedTickets = r.data.closedIssuesList;
c.sortedBy = r.data.sortedBy;
});
c.data.showOpen = false;
c.resultsList = 'Total open approvals: ';
c.totalTickets = c.data.totalOpenIssues;
document.getElementById("ma-closed-tickets").style.display = "none";
document.getElementById("ma-open-tickets").style.display = "block";
c.highlightColor1 = 'normal';
c.highlightColor3 = 'normal';
c.highlightColor2 = 'bold';
c.highlightColor4 = 'bold';
c.highlightColor5 = 'normal';
}
//--show open closed clicked-------------------
$scope.ma_showClosed = function() {
document.getElementById("ma-button-sort-1").style.backgroundColor = "#145896";
document.getElementById("ma-button-sort-1").style.color = "#F2FBFE";
c.server.get({
action: "sort_updated",
msg: "Sorting issues by updated date..."
}).then(function(r) {
c.openTickets = r.data.openIssuesList;
c.closedTickets = r.data.closedIssuesList;
c.sortedBy = r.data.sortedBy;
});
c.resultsList = 'Total closed approvals: ';
c.totalTickets = c.data.totalClosedIssues;
document.getElementById("ma-closed-tickets").style.display = "block";
document.getElementById("ma-open-tickets").style.display = "none";
c.highlightColor1 = 'normal';
c.highlightColor3 = 'normal';
c.highlightColor2 = 'bold';
c.highlightColor4 = 'bold';
c.highlightColor5 = 'normal';
}
//--approve approval button clicked-------------------
c.ma_approveRecord = function(apprTicketNumber, apprTicketNumberSYSID) {
spModal.confirm("Are you sure you wish to mark " + apprTicketNumber + " as approved?", c.name).then(function(confirmed) {
c.confirmed = confirmed;
if (c.confirmed) {
c.server.get({
action: "approve_ticket",
msg: "Approving ticket...",
ticket_number: apprTicketNumber,
approval_sysid: apprTicketNumberSYSID
}).then(function(r) {
location.reload(true);
window.location.href = window.location.href;
});
}
});
}
//--reject approval button clicked-------------------
c.ma_rejectRecord = function(apprTicketNumber, apprTicketNumberSYSID) {
spModal.prompt("Why are you rejecting " + apprTicketNumber + "?", c.name).then(function(name) {
c.name = name;
c.server.get({
action: "reject_ticket",
msg: "Rejecting ticket...",
ticket_number: apprTicketNumber,
comments: c.name.toString(),
approval_sysid: apprTicketNumberSYSID
}).then(function(r) {
location.reload(true);
window.location.href = window.location.href;
});
});
}
//--view record button clicked-------------------
$scope.ma_viewRecord = function(issueSYSID) {
var sLink = "?id=ticket&sys_id=" + issueSYSID + "&table=sysapproval_approver";
//alert(sLink);
window.open(sLink, '_self');
}
//----------------sort by UPDATED button clicked----------------------
$scope.ma_sort_last_updated = function() {
document.getElementById("ma-button-sort-1").style.backgroundColor = "#145896";
document.getElementById("ma-button-sort-1").style.color = "#F2FBFE";
c.sortbystate=false;
c.server.get({
action: "sort_updated",
msg: "Sorting issues by updated date..."
}).then(function(up) {
c.openTickets = up.data.openIssuesList;
c.closedTickets = up.data.closedIssuesList;
c.sortedBy = up.data.sortedBy;
});
c.highlightColor2 = 'bold';
c.highlightColor4 = 'bold';
c.highlightColor1 = 'normal';
c.highlightColor3 = 'normal';
c.highlightColor5 = 'normal';
}
//----------------sort by CREATED button clicked----------------------
$scope.ma_sort_created_date = function() {
document.getElementById("ma-button-sort-1").style.backgroundColor = "#F2FBFE";
document.getElementById("ma-button-sort-1").style.color = "#145896";
c.sortbystate=false;
c.server.get({
action: "sort_created",
msg: "Sorting issues by created date..."
}).then(function(cr) {
c.openTickets = cr.data.openIssuesList;
c.closedTickets = cr.data.closedIssuesList;
c.sortedBy = cr.data.sortedBy;
});
c.highlightColor1 = 'bold';
c.highlightColor3 = 'bold';
c.highlightColor2 = 'normal';
c.highlightColor4 = 'normal';
c.highlightColor5 = 'normal';
}
//----------------sort by STATUS button clicked----------------------
$scope.ma_sort_status = function() {
document.getElementById("ma-button-sort-1").style.backgroundColor = "#F2FBFE";
document.getElementById("ma-button-sort-1").style.color = "#145896";
c.sortbystate=true;
c.server.get({
action: "sort_status",
msg: "Sorting issues by status..."
}).then(function(pr) {
c.openTickets = pr.data.openIssuesList;
c.closedTickets = pr.data.closedIssuesList;
c.sortedBy = pr.data.sortedBy;
});
c.highlightColor1 = 'normal';
c.highlightColor3 = 'normal';
c.highlightColor2 = 'normal';
c.highlightColor4 = 'normal';
c.highlightColor5 = 'bold';
}
}
Server Script
(function() {
/* populate the 'data' object */
/* e.g., data.table = $sp.getValue('table'); */
var sMsgPadder = "*********************************** MSG: ";
data.sysUserID = $sp.getParameter("sys_id");
if (!data.sysUserID) {
data.sysUserID = gs.getUser().getID();
}
data.search_options = '{"contextual_search_sources": { "value":
"51cb15cadb8d6c10f04aad05059619bc", "displayValue":
"My Approvals" }}';
if (input && input.action === "reject_ticket") { //--REJECT BUTTON CLICKED
gs.addInfoMessage(sMsgPadder + 'rejecting: ' + input.ticket_number);
var rejSYSID = input.approval_sysid;
var rejectionComments = input.comments;
processApproval('rejected', rejSYSID, rejectionComments);
return;
}
if (input && input.action === "approve_ticket") { //--APPROVE BUTTON CLICKED
gs.addInfoMessage(sMsgPadder + 'approving: ' + input.ticket_number);
var apprSYSID = input.approval_sysid;
processApproval('approved', apprSYSID, '');
return;
}
//gs.addInfoMessage(sMsgPadder+'test');
var sOrderByField = 'sys_updated_on';
data.sortedBy = 'approval updated';
var sOB_descAsc = 'desc';
//--order by status
if (input && input.action === "sort_status") {
sOrderByField = 'document_id.state';
data.sortedBy = 'ticket state';
sOB_descAsc = 'asc';
}
//--order by created
if (input && input.action === "sort_created") {
sOrderByField = 'sys_created_on';
data.sortedBy = 'approval created';
sOB_descAsc = 'desc';
}
//default--order by updated
var sQuery = 'state=requested^approver=' + data.sysUserID;
var iLimit = 5;
var bSortByState = (data.sortedBy == 'ticket state');
data.openIssuesList = [];
var grApprOpen = buildApprovalsGR(sOB_descAsc, sOrderByField, true, sQuery, 0);
iLimit = grApprOpen.getRowCount(); //--uncomment if want to limit to initial iLimit value
data.totalOpenIssues = iLimit;
while (grApprOpen.next()) {
var object_o = buildUpApprArr(grApprOpen, bSortByState);
data.openIssuesList.push(object_o);
}
sQuery = 'approver=' + data.sysUserID;
data.closedIssuesList = [];
var grApprClosed = buildApprovalsGR(sOB_descAsc, sOrderByField, false, sQuery, 0);
iLimit = grApprClosed.getRowCount(); //--uncomment if want to limit to initial iLimit value
data.totalClosedIssues = iLimit;
while (grApprClosed.next()) {
var object_c = buildUpApprArr(grApprClosed, bSortByState);
data.closedIssuesList.push(object_c);
}
})();
function buildUpApprArr(grAppr, bSortByState) {
var objArr = {};
objArr.sys_id = grAppr.getValue("sys_id");
var sTicketNumber = grAppr.getDisplayValue('document_id') + "";
objArr.approval_ticket = sTicketNumber;
objArr.short_description = grAppr.document_id.short_description + "";
//--created on:
var sCrOn = grAppr.getDisplayValue('sys_created_on');
var sCrOn_Arr = sCrOn.split(' ');
objArr.sys_created_on = sCrOn_Arr[0] + "";
//--updated on:
var sUpdOn = grAppr.getDisplayValue('sys_updated_on');
var sUpdOn_Arr = sUpdOn.split(' ');
objArr.sys_updated_on = sUpdOn_Arr[0] + "";
objArr.approver = grAppr.getDisplayValue('approver') + "";
var sCreatedByName = "";
var sCrBy = grAppr.getValue("sys_created_by");
var grUser = new GlideRecord('sys_user');
if (grUser.get('user_name', sCrBy)) {
sCreatedByName = grUser.getValue("name");
}
//--state
objArr.requestor = sCreatedByName;
if (sTicketNumber.indexOf('KB') > -1) {
objArr.state = grAppr.getDisplayValue('document_id.workflow_state') + ""; //--KA
} else {
objArr.state = grAppr.getDisplayValue('document_id.state') + ""; //--RITM / CHG
}
return objArr;
}
function buildApprovalsGR(orderByAscOrDesc, orderByField, activeQuery, query, iLimit) {
var grAppr = new GlideRecord('sysapproval_approver');
if (activeQuery) {
grAppr.addActiveQuery();
}
if (!activeQuery) {
grAppr.addInactiveQuery();
}
if (iLimit > 0) {
grAppr.setLimit(iLimit);
}
if (orderByField != '') {
if (orderByAscOrDesc == "desc") {
grAppr.orderByDesc(orderByField);
} else {
grAppr.orderBy(orderByField);
}
if (orderByField == 'document_id.state') {
//--add an additional order by for KB
grAppr.orderBy('document_id.workflow_state');
}
}
grAppr.addQuery(query);
grAppr.query();
return grAppr;
}
function processApproval(approveReject, aqpproval_SYSID, comments) {
var grApproval = new GlideRecord('sysapproval_approver');
if (grApproval.get('sys_id', aqpproval_SYSID)) {
grApproval.state = approveReject;
if (!gs.nil(comments)) {
grApproval.comments = comments;
}
grApproval.update();
}
}
Comments
Post a Comment