
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-09-2018 02:37 PM
Hi Community,
I've run into an issue with adding attachments to catalog items by non-itil users where they select a document to attach but it seems like the system is not 'processing' it and showing it in the catalog item like it does for ITIL users. Please see the screen shots below. The widget is cloned but the attachment part has not changed at all. Would this be related to ACLs? I see the document added to the sys_attachment table when the user tries to attach it but it's just not visible to them to show that they actually attached something.
This is the widget code:
<div id="sc_cat_item" >
<div class="row" ng-if="::data.sc_cat_item" >
<div ng-if="::data.sc_cat_item.picture" class="col-sm-3">
<div class="panel panel-{{::options.color}} b wrapper-lg text-center">
<img class="img-responsive catalog-item-image" style="display: inline; font-size:500px;" ng-src="{{::data.sc_cat_item.picture}}" />
</div>
</div>
<div ng-class="{true:'col-sm-9',false:'col-sm-12'}[data.sc_cat_item.picture.length > 0]">
<div class="panel panel-default">
<div class="wrapper-md">
<widget id="sp-favorite"></widget>
<h1 class="h2 m-t-none m-b-sm font-thin">{{::data.sc_cat_item.name}}</h1>
<div class="text-muted">{{::data.sc_cat_item.short_description}}</div>
</div>
<div ng-if="::data.sc_cat_item.description" class="wrapper-md b-t">
<div ng-bind-html="::data.sc_cat_item.description"></div>
</div>
<div ng-if="::data.sc_cat_item.content_type == 'external'" class="wrapper-md"><a ng-href="{{::data.sc_cat_item.url}}" target={{::data.sc_cat_item.target}}>{{::data.sc_cat_item.url}} ➚</a></div>
<div ng-if="::data.sc_cat_item.content_type == 'kb'" class="wrapper-md"><a ng-href="?id=kb_article&sys_id={{::data.sc_cat_item.kb_article}}">${Go to KB Article:} {{::data.sc_cat_item.kb_article_description}}</a></div>
<div ng-if="::data.sc_cat_item._fields">
<sp-cat-item item="::data.sc_cat_item" />
<form>
<div ng-class="{'b-t wrapper-md': data.sc_cat_item._view.length}">
<!-- display view and model -->
<sp-model form-model="::data.sc_cat_item" mandatory="mandatory"></sp-model>
</div>
<div ng-if="data.sc_cat_item.sys_class_name != 'sc_cat_item_content'" class="b-t wrapper-md">
<div class="m-b" ng-if="data.showPrices && (data.sc_cat_item.price || data.sc_cat_item.recurring_price)" >
<h4 ng-if="data.sc_cat_item.price" class="cat_item_price">${Price}: {{data.sc_cat_item.price}}</h4>
<em ng-if="data.sc_cat_item.recurring_price" class="cat_item_price">${Recurring Price}: {{data.sc_cat_item.recurring_price}}</em>
</div>
<now-attachments-list template="sp_attachment_single_line" ></now-attachments-list>
<!--<select ng-if="c.showQuantitySelector()"
ng-disabled="submitted"
class="form-control quantity-selector"
ng-model="c.quantity"
ng-options="num for num in [1,2,3,4,5,6,7,8,9,10]">
</select>-->
<!--New quantity field to allow type in numbers-->
<input type="number"
ng-if="c.showQuantitySelector()"
class="form-control input-number"
ng-model="c.quantity"
min="1"
max="100">
<span ng-if="c.showQuantitySelector()">-</span>
<button tabindex="0" name="submit" ng-disabled="submitted" ng-click="triggerOnSubmit()" class="btn btn-primary">{{submitButtonMsg}}</button>
<!--<button tabindex="0" ng-if="c.showAddCartBtn()" name="submit" ng-disabled="submitted" ng-click="triggerAddToCart()" class="btn btn-default">${Add to Cart}</button>-->
<button tabindex="0" ng-if="c.showAddCartBtn()" name="submit" ng-click="triggerAddToCart()" class="btn btn-default">${Add to Cart}</button>
<span ng-if="submitting" style="padding-left:4px">${Submitting...}</span>
<label tabindex="0" ng-if="!submitted" style="float:right;font-weight:normal;cursor:pointer;"><sp-attachment-button></sp-attachment-button><span style="padding-left:4px;">${Add attachments}</span></label>
<div ng-if="hasMandatory(mandatory)" class="alert alert-info" style="margin-top: .5em">
<span ng-if="hasMandatory(mandatory)">${Required information} </span>
<span ng-repeat="f in mandatory" class="label label-danger" style="margin-right: .5em; display: inline-block;">{{::f.label}}</span>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
<sp-message-dialog name="delete_attachment"
title="{{m.dialogTitle}}"
message="{{m.dialogMessage}}"
ok="{{m.dialogOK}}"
cancel="{{m.dialogCancel}}"
dialog-class="delete-dialog"/>
<div ng-if="::!data.sc_cat_item" >
<div class="panel panel-default" ng-if="::data.sys_id">
<div class="panel-heading"><h4 class="panel-title">${Item not found: {{::data.sys_id}}}</h4></div>
<div class="panel-body wrapper">
<p>${This item is not found or currently not available}</p>
<p>${Suggestions}:</p>
<ul>
<li>${Try searching for the item}</li>
<li>${Go to the Service Catalog homepage}</li>
<li>${Contact your portal administrator}</li>
</ul>
</div>
</div>
</div>
</div>
Server:
// populate the 'data' variable with catalog item, variables, and variable view
(function() {
options.show_add_cart_button = (options.show_add_cart_button == "true");
if (options.page) {
var pageGR = new GlideRecord("sp_page");
options.page = (pageGR.get(options.page)) ? pageGR.getValue("id") : null;
}
if (options.table) {
var tableGR = new GlideRecord("sys_db_object");
options.table = (tableGR.get(options.table)) ? tableGR.getValue("name") : null;
}
//options.url = options.url || "?id={page}&table={table}&sys_id={sys_id}";
options.url = options.url || "?id=thankyou";
data.showPrices = $sp.showCatalogPrices();
var m = data.msgs = {};
//m.submitMsg = gs.getMessage("Submit");
m.submitMsg = gs.getMessage("Order Now");
m.submittedMsg = gs.getMessage("Submitted");
m.createdMsg = gs.getMessage("Created");
m.trackMsg = gs.getMessage("track using 'Requests' in the header or");
m.clickMsg = gs.getMessage("click here to view");
m.dialogTitle = gs.getMessage("Delete Attachment");
m.dialogMessage = gs.getMessage("Are you sure?");
m.dialogOK = gs.getMessage("OK");
m.dialogCancel = gs.getMessage("Cancel");
m.largeAttachmentMsg = gs.getMessage("Attached files must be smaller than {0} - please try again", "24MB");
if (input)
data.sys_id = input.sys_id;
else if(options.sys_id)
data.sys_id = options.sys_id;
else
data.sys_id = $sp.getParameter("sys_id") || $sp.getParameter('sl_sys_id');
data._attachmentGUID = gs.generateGUID();
// portal can specify a catalog home page
data.sc_catalog_page = $sp.getDisplayValue("sc_catalog_page") || "sc_home";
var validatedItem = new GlideappCatalogItem.get(data.sys_id);
if (!validatedItem.canView())
return;
data.sc_cat_item = $sp.getCatalogItem(data.sys_id, true);
if (data.sc_cat_item.category) {
var categoryGR = new GlideRecord('sc_category');
categoryGR.get(data.sc_cat_item.category);
data.category = {
name: categoryGR.getDisplayValue('title'),
url: '?id=sc_category&sys_id=' + categoryGR.sys_id
}
}
$sp.logStat('Catalog View', data.sc_cat_item.sys_class_name, data.sys_id, data.sc_cat_item.name);
})()
Client Script:
function ($scope, $http, spUtil, nowAttachmentHandler, $rootScope, $sanitize, $window, $sce, i18n) {
var c = this;
c.quantity = 1;
$scope.data.sc_cat_item.description = $sce.trustAsHtml($scope.data.sc_cat_item.description);
c.widget._debugContextMenu = [
[ i18n.getMessage("Open") + " sc_cat_item", function(){
var item = c.data.sc_cat_item;
$window.open("/$sp.do?id=form&table=" + item.table + "&sys_id=" + item.sys_id); }]
];
c.showAddCartBtn = function() {
return c.options.show_add_cart_button &&
c.data.sc_cat_item.sys_class_name !== "sc_cat_item_producer" &&
!c.data.sc_cat_item.no_cart;
}
c.showQuantitySelector = function() {
return c.data.sc_cat_item.sys_class_name !== "sc_cat_item_producer" &&
!c.data.sc_cat_item.no_quantity;
}
$scope.$on('dialog.upload_too_large.show', function(e){
console.log($scope.m.largeAttachmentMsg);
spUtil.addErrorMessage($scope.m.largeAttachmentMsg);
});
$scope.m = $scope.data.msgs;
$scope.submitButtonMsg = $scope.m.submitMsg;
var ah = $scope.attachmentHandler = new nowAttachmentHandler(setAttachments, function() {});
ah.setParams('sp_portal', $scope.data._attachmentGUID, 1024 * 1024 * 24);
function setAttachments(attachments, action) {
$scope.attachments = attachments;
}
$scope.attachmentHandler.getAttachmentList();
$scope.confirmDeleteAttachment = function(attachment, $event) {
$rootScope.$broadcast("dialog.delete_attachment.show", {
parms: {
ok: function() {
$scope.attachmentHandler.deleteAttachment(attachment);
$rootScope.$broadcast("dialog.delete_attachment.close");
},
cancel: function() {
$rootScope.$broadcast("dialog.delete_attachment.close");
},
details: attachment.name
}
})
}
// Breadcrumbs
if ($scope.data.sc_cat_item) {
var bc = [{label: $scope.page.title, url: '?id=' + $scope.data.sc_catalog_page}];
if ($scope.data.category)
bc[bc.length] = {label: $scope.data.category.name, url: $scope.data.category.url};
bc[bc.length] = {label: $scope.data.sc_cat_item.name, url: '#'};
$rootScope.$broadcast('sp.update.breadcrumbs', bc);
spUtil.setSearchPage('sc');
}
var g_form;
$scope.$on('spModel.gForm.initialized', function(e, gFormInstance){
g_form = gFormInstance;
// This runs after all onSubmit scripts have executed
g_form.$private.events.on('submitted', function(){
if ($scope.data.sc_cat_item.item_action === "order")
getOne();
else if ($scope.data.sc_cat_item.item_action === "add_to_cart")
addToCart();
});
});
$scope.triggerAddToCart = function() {
$scope.data.sc_cat_item.item_action = "add_to_cart";
$scope.data.sc_cat_item.quantity = c.quantity;
if (g_form)
g_form.submit();
}
$scope.triggerOnSubmit = function(){
$scope.data.sc_cat_item.item_action = "order";
$scope.data.sc_cat_item.quantity = c.quantity;
if (g_form)
g_form.submit();
}
// order / create request
function getOne() {
postCatalogFormRequest().success(function(response) {
var a = response.answer;
var n = a.number;
$scope.$emit("$$uiNotification", response.$$uiNotification);
$scope.$emit("$sp.sc_cat_item.submitted", a);
if (n)
issueMessage(n, a.table, a.sys_id);
$scope.submitting = false;
$scope.submitButtonMsg = $scope.m.submittedMsg;
});
}
function addToCart() {
/*var cartURL = '?id=sc_cart';
var cartMsg = 'Added item to shopping cart. You can check out by going to your cart';
var cartMsg2 = ' or continue shopping';*/
postCatalogFormRequest().success(function(response) {
$rootScope.$broadcast("$sp.service_catalog.cart.add_item");
$rootScope.$broadcast("$sp.service_catalog.cart.update");
//spUtil.addInfoMessage("<a href=" + cartURL + ">" + cartMsg + cartMsg2 + "</a>");
spUtil.addInfoMessage("Added item to shopping cart. You can continue shopping or check out your items by going to your cart in the header menu");
$scope.submitting = false;
});
}
function postCatalogFormRequest() {
//setFieldsReadonly();
$scope.submitted = true;
$scope.submitting = true;
var t = $scope.data.sc_cat_item;
t._attachmentGUID = $scope.data._attachmentGUID;
// calls into SPCatalogForm.getItem()
return $http.post(spUtil.getURL('sc_cat_item'), t);
}
// spModel populates mandatory - hasMandatory is called by the submit button
$scope.hasMandatory = function(mandatory) {
return mandatory && mandatory.length > 0;
};
// switch catalog items
var unregister = $scope.$on('$sp.list.click', onListClick);
$scope.$on("$destroy", function() {
unregister();
});
function onListClick(evt, arg) {
$scope.data.sys_id = arg.sys_id;
spUtil.update($scope);
}
/* Original code
function setFieldsReadonly(){
var allFields = g_form.getFieldNames();
for(var fieldName in allFields){
g_form.setReadOnly(allFields[fieldName], true);
}
}*/
//Updated code to make fields editable after adding to cart
function setFieldsReadonly(){
var allFields = g_form.getFieldNames();
for(var fieldName in allFields){
g_form.setReadOnly(allFields[fieldName], false);
}
}
/*function issueMessage(n, table, sys_id) {
var page = table == 'sc_request' ? 'sc_request' : 'ticket';
if (c.options.page) {page = c.options.page;}
if (c.options.table) {table = c.options.table;}
var url = spUtil.format(c.options.url, {page: page, table: table, sys_id: sys_id});
//var url = "?id=nonemployee-thankyou";
if (c.options.auto_redirect == "true") {
$window.location.href = url;
return;
}
var t = $scope.m.createdMsg + " " + n + " - ";
t += $scope.m.trackMsg;
t += ' <a href="' + url + '">' + $scope.m.clickMsg + '</a>';
spUtil.addInfoMessage(t);
}*/
function issueMessage(n, table, sys_id, redirectTo, redirectUrl) {
var page = table == 'sc_request' ? 'sc_request' : 'ticket';
if (c.options.page) {page = c.options.page;}
if (c.options.table) {table = c.options.table;}
if (redirectTo == 'catalog_home') page = 'sc_home';
//var url = spUtil.format(c.options.url, {page: page, table: table, sys_id: sys_id});
var url = "?id=thankyou";
if (c.options.auto_redirect == "true") {
if (redirectUrl)
$window.location.href = redirectUrl;
else
$window.location.href = url;
return;
}
var t = $scope.m.createdMsg + " " + n + " - ";
t += $scope.m.trackMsg;
t += ' <a href="' + url + '">' + $scope.m.clickMsg + '</a>';
spUtil.addInfoMessage(t);
}
}
what ITIL users see:
What non-itil users see - even after attaching a document:
Any help or suggestions is appreciated!
Thank you,
Yeny
Solved! Go to Solution.
- Labels:
-
Service Portal Development

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-13-2018 12:22 PM
Hi Joel,
Thank you for your response! It ended up being an encryption issue with attachments and we were able to fix it with a script include and workflow.
Thank you!!
Yeny

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-09-2018 03:36 PM
Hi Yeny,
I just created a widget in my personal developers instance and copied across your Body HTML template, client controller code and server code. After replacing the SC Catalog Item widget for your customised version I tried attaching a document both as the System Administrator and also as a user without roles. In both cases I was not able to replicate your issue. As you suspect, the issue is most likely to do with the ACL's preventing non-itil users from being able to see attachments.

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-13-2018 12:22 PM
Hi Joel,
Thank you for your response! It ended up being an encryption issue with attachments and we were able to fix it with a script include and workflow.
Thank you!!
Yeny

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-13-2018 12:39 PM
Thanks for the update and the feedback Yeny, glad that you could resolve this issue!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
02-19-2019 02:35 PM
Hi, I am facing a similar issue with attachments. Will you be able to share how exactly you were able to resolve this issue?
Thanks in advance!