Attachments in Catalog Item widget (Service Portal) not working for non-itil users?

YenGar
Mega Sage

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:

find_real_file.png

 

What non-itil users see - even after attaching a document:

find_real_file.png

 

Any help or suggestions is appreciated!

Thank you, 

Yeny

1 ACCEPTED SOLUTION

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

View solution in original post

7 REPLIES 7

Hi, I facing similar issue with external users while adding the attachments. could you please tell me if you have found the solution.

Hi, Could you please tell me how you fixed it.. we are trying to do the same but it's not working for external users.

SanSri1122
Tera Expert

Hi yeny,

I am facing same issue. Can you help me out resolve this. which steps exactly i need to proceed?

 

Regards,

Srilatha.Tangudu