customise portal catalogue home page
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-01-2024 06:18 AM - edited 11-02-2024 06:50 AM
Please find the changes i made to the widget to customize the portal. something seems to be broken in my code
I am writing a select function to filter catalogues on basis on alphabetical order and popularity and favourites.
server side:
(function() {
var catalog_id = $sp.getParameter("catalog_id") ? $sp.getParameter("catalog_id") + "" : "-1";
var catalogSelectorArr = [{
value: "-1",
displayValue: gs.getMessage("All")
}];
data.selectedCatalogIndex = catalog_id == -1 ? 0 : -1;
data.visibleCategories = 0;
var catalogIDs = $sp.getCatalogs().value + "";
var catalogs = catalogIDs.split(",");
var isCatalogAccessibleViaPortal = catalog_id == -1 ? true : false;
catalogs.forEach(function(catalogSysId) {
if (catalog_id == catalogSysId) {
isCatalogAccessibleViaPortal = true;
}
});
var counter = 1;
catalogs.forEach(function(catalogSysId) {
var catalog = new sn_sc.Catalog(catalogSysId);
var catalogObj = {
value: catalogSysId,
displayValue: catalog.getTitle()
};
if (catalog.canView()) {
if (catalog_id === catalogSysId) {
data.selectedCatalogIndex = counter;
}
catalogSelectorArr.push(catalogObj);
counter++;
}
});
data.catalogSelectorArr = catalogSelectorArr;
data.catalog_id = catalog_id ? catalog_id : "-1";
data.showMoreMsg = gs.getMessage("Show More {0}", options.title);
data.pleaseWait = gs.getMessage("Please wait... fetching {0}", options.title);
var categoryId = JSUtil.nil($sp.getParameter('sys_id')) ? "" : $sp.getParameter('sys_id') + "";
data.categoryId = categoryId;
var catalogIDs = (data.catalog_id && data.catalog_id !== "-1") ? data.catalog_id : $sp.getCatalogs().value + "";
var catalogIDArr = catalogIDs.split(",");
var viewType = '';
var checkCanView = false;
var showBadge = false;
var nestedLayout = (options.category_layout !== "Flat");
var dynamicCategory = false;
var favoriteApi = new sn_ex_sp.FavoriteAPI();var portalId = $sp.getPortalRecord().getUniqueValue();
data.sortBy = $sp.getParameter('sortBy');
var favoritePage = new sn_ex_sp.FavoritesPage(portalId);
data.contentList = favoritePage.getAllFavoritesWithContent(0, data.favoriteCountPerPage, true, '', data.sortBy);
// gs.addInfoMessage(JSON.stringify(data.contentList));
data.favCategories=[];
data.contentList.forEach(function(content){
var fGr = new GlideRecord('sc_cat_item');
fGr.get(content.sysId);
data.favCategories.push(fGr.getValue('category'));
});
data.popularItems=getPopularItems();
function getPopularItems() {
return new SCPopularItems().useOptimisedQuery(gs.getProperty('glide.sc.portal.popular_items.optimize', true) + '' == 'true')
.baseQuery(options.popular_items_created + '')
.allowedItems(getAllowedCatalogItems())
.visibleStandalone(true)
.visibleServicePortal(true)
.itemsLimit(6)
.restrictedItemTypes('sc_cat_item_guide,sc_cat_item_wizard,sc_cat_item_content,sc_cat_item_producer'.split(','))
.itemValidator(function(item, itemDetails) {
if (!item.canView() || !item.isVisibleServicePortal())
return false;
return true;
})
.responseObjectFormatter(function(item, itemType, itemCount) {
return {
order: 0 - itemCount,
name: item.name,
category:item.category,
short_description: item.short_description,
picture: item.picture,
price: item.price,
sys_id: item.sys_id,
hasPrice: item.price != 0,
page: itemType == 'sc_cat_item_guide' ? 'sc_cat_item_guide' : 'sc_cat_item'
};
})
.generate();
}
data.popularCategories=[];
data.popularItems.forEach(function(content){
data.popularCategories.push(content.category.sys_id);
});
// gs.addInfoMessage(JSON.stringify(data.popularCategories));
function getAllowedCatalogItems () {
var allowedItems = [];
catalogIDArr.forEach(function(catalogID) {
var catalogObj = new sn_sc.Catalog(catalogID);
var catItemIds = catalogObj.getCatalogItemIds();
for(var i=0; i<catItemIds.length; i++) {
if (allowedItems.indexOf(catItemIds[i]) === -1)
allowedItems.push(catItemIds[i]);
}
});
return allowedItems;
}
var catalogArr = catalogIDs.split(",");
var catalogs = [];
catalogArr.forEach(function(catalogSysId) {
var catalog = new sn_sc.Catalog(catalogSysId);
if (catalog.canView()) {
catalogs.push(catalogSysId);
}
});
data.categoryId = categoryId;
var msg = data.messages = {};
msg.catalogTitle = options.catalog_title ? gs.getMessage(options.catalog_title) : gs.getMessage('All Catalogs');
msg.category = gs.getMessage("category");
msg.selected = gs.getMessage("selected");
msg.containing = gs.getMessage("containing");
msg.item = gs.getMessage("item");
msg.items = gs.getMessage("items");
msg.expand = gs.getMessage("Expand");
msg.collapse = gs.getMessage("Collapse");
data.largeDataSet = gs.getProperty("glide.sc.largeSet.optimization.enable", "false");
if (data.largeDataSet == 'true')
nestedLayout = false;
if (options.page) {
var page = new GlideRecord('sp_page');
if (page.get(options.page))
data.page = page.id + '';
}
checkCanView = String(options.check_can_view) == 'true';
showBadge = String(options.omit_badges) == 'false';
if (!isCatalogAccessibleViaPortal) {
return;
}
data.categoriesList = [];
var categoriesInPage = options.number_of_categories_to_load || 15;
data.limit = categoriesInPage;
if (input && input.new_limit) {
data.limit = input.new_limit;
}
if (input && input.categoriesList)
data.categoriesList = input.categoriesList.slice(); //Copy the input array
if (input && input.startWindow) {
data.endWindow = input.endWindow;
} else {
data.startWindow = 0;
data.endWindow = 0;
}
while (data.categoriesList.length < data.limit + 1) {
data.startWindow = data.endWindow;
data.endWindow = data.endWindow + categoriesInPage;
var catGr = queryCategory(catalogs, nestedLayout, dynamicCategory, data.startWindow, data.endWindow);
if (!catGr.hasNext())
break;
fetchCategories(catGr, data.categoriesList);
}
for (var i = 0; i < data.limit; i++) {
if (data.categoriesList[i].totalCount > 0) {
data.visibleCategories++;
data.categoriesList[i].position = data.visibleCategories;
}
}
data.visibleCategoriesList = data.categoriesList.filter(function(category) {
return category.totalCount > 0;
});
if (data.visibleCategoriesList.length > 0) {
data.visibleCategoriesList[0].isFirstCategory = true;
}
if (data.visibleCategoriesList.length > data.limit)
data.showMore = true;
else
data.showMore = false;
data.more_msg = gs.getMessage("Showing {0} categories", data.visibleCategories + "" || categoriesInPage);
function fetchCategories(categoriesGr, categories) {
while (categoriesGr.next()) {
var categoryJS = new sn_sc.CatCategory(categoriesGr.getUniqueValue() + '');
if (!categoryJS.canView())
continue;
var categoryDetails = getCategoryDetails(categoryJS, 0);
categoryDetails.sys_id = categoriesGr.getUniqueValue();
categories.push(categoryDetails);
}
}
function queryCategory(catalogs, nestedLayout, dynamicCategory, startWindow, endWindow) {
var categoriesGr = new GlideRecord('sc_category');
categoriesGr.addQuery("sc_catalog", catalogs);
if (!dynamicCategory)
categoriesGr.addQuery("sys_class_name", "sc_category");
categoriesGr.addActiveQuery();
categoriesGr.orderBy('order');
categoriesGr.orderBy('title');
if (nestedLayout)
categoriesGr.addNullQuery("parent");
categoriesGr.chooseWindow(startWindow, endWindow);
categoriesGr.query();
return categoriesGr;
}
function getItemCount(categoryJS) {
if (showBadge)
return checkCanView ? categoryJS.getViewableItemsCount(true) : categoryJS.getItemsCount(true);
else
return categoryJS.hasVisibleItem(true, checkCanView) ? 1 : 0;
}
function getCategoryDetails(categoryJS, level) {
var categoryDetails = {};
var showChildren = false;
if (!categoryJS) {
return categoryDetails;
}
categoryDetails.title = categoryJS.getTitle();
categoryDetails.level = level;
categoryDetails.description = categoryJS.getDescription();
categoryDetails.full_description = categoryJS.getFullDescription();
categoryDetails.icon = categoryJS.getIconSRC();
categoryDetails.header_icon = categoryJS.getHeaderIconSRC();
categoryDetails.homepage_image = categoryJS.getHomepageImageSRC();
categoryDetails.sys_id = categoryJS.getID();
categoryDetails.showChildren = (categoryDetails.sys_id === categoryId);
categoryDetails.catalog = {
"sys_id": categoryJS.getCatalog(),
"title": new sn_sc.Catalog(categoryJS.getCatalog()).getTitle()
}
categoryDetails.count = categoryDetails.totalCount = ((data.largeDataSet != 'true') ? getItemCount(categoryJS) : 1);
if (catalog_id == -1 && catalogSelectorArr.length > 2)
categoryDetails.catalog_tooltip = gs.getMessage("[{0}]", categoryDetails.catalog.title);
else
categoryDetails.catalog_tooltip = '';
var subCategoryCounts = 0;
var positionCount = 0;
if (nestedLayout) {
var subcategories = categoryJS.getViewableSubCategories();
if (subcategories.length == 0) {
categoryDetails.subcategories = [];
} else {
categoryDetails.subcategories = [];
subcategories.forEach(function(subCategory) {
var subCategoryJS = new sn_sc.CatCategory(subCategory.sys_id + '');
var category = getCategoryDetails(subCategoryJS, level + 1);
categoryDetails.totalCount = categoryDetails.totalCount + category.totalCount;
if (category.totalCount > 0) {
category.position = ++positionCount;
categoryDetails.subcategories.push(category);
}
categoryDetails.showChildren = categoryDetails.showChildren || category.showChildren;
});
}
} else {
categoryDetails.totalCount = categoryDetails.count;
}
return categoryDetails;
}
})();
client side:
function($scope, $location, $timeout, $window, $document, $rootScope, spUtil, spAriaUtil, i18n, urlTools) {
var c = this;
loadPage();
$scope.getFilterCategories = function(search,catname){
if(!search ||catname.toLowerCase().indexOf(search.toLowerCase())!=-1 ||search==""){
return true;
}
return false;
}
$scope.sortSelected='title';
$scope.fullList = c.data.visibleCategoriesList;
$scope.sortArray=function(){
//console.log("sort triggered"+JSON.stringify(c.data.visibleCategoriesList));
if($scope.sortSelected=='-title'){
c.data.visibleCategoriesList = $scope.fullList;
c.data.visibleCategoriesList.sort(function(a, b) {return (a.title < b.title ? 1 : -1)});
}
else if($scope.sortSelected=='title'){
c.data.visibleCategoriesList = $scope.fullList;
c.data.visibleCategoriesList.sort(function(a, b) {return (a.title > b.title ? 1 : -1)});
}
else if($scope.sortSelected=='favourite'){
//console.log("triggered"+JSON.stringify(c.data.favCategories));
c.data.visibleCategoriesList = $scope.fullList;
//console.log("selected" +JSON.stringify( $scope.fullList));
c.data.visibleCategoriesList = c.data.visibleCategoriesList.filter(function(visibleCategory){
if(c.data.favCategories.includes(visibleCategory.sys_id)){
//console.log("favourite selected");
c.data.favCategories.includes(visibleCategory.sys_id)
return true;
}
else if(visibleCategory.subcategories.length>0){
for(var i=0;i<visibleCategory.subcategories.length;i++){
console.log("sub category "+visibleCategory.subcategories[i].sys_id + " : "+JSON.stringify(c.data.favCategories));
if(c.data.favCategories.includes(visibleCategory.subcategories[i].sys_id)){
return true;
}
}
}
else{
return false;
}
});
}
else if($scope.sortSelected=='popular'){
c.data.visibleCategoriesList = $scope.fullList;
c.data.visibleCategoriesList = c.data.visibleCategoriesList.filter(function(visibleCategory){
if(c.data.popularCategories.includes(visibleCategory.sys_id)){
return true;
}
else if(visibleCategory.subcategories.length>0){
for(var i=0;i<visibleCategory.subcategories.length;i++){
if(c.data.popularCategories.includes(visibleCategory.subcategories[i].sys_id)){
return true;
}
}
}
else{
return false;
}
});
}
}
function loadPage() {
$scope.selectedCatalog = c.data.catalogSelectorArr[c.data.selectedCatalogIndex];
$scope.hideCategoryWidgetInXS = (c.options.hide_xs == 'true');
if (c.data.categoryId) {
if (!$scope.hideCategoryWidgetInXS)
$scope.hideCategoryWidgetInXS = true;
} else {
if ($scope.hideCategoryWidgetInXS)
$scope.hideCategoryWidgetInXS = false;
}
handleToolTip();
$(document).on('keydown', '.select2-focusser', function(e) {
if (e.which === 40 || e.which === 38) {
$(this).closest(".select2-container").siblings('select:enabled').select2('open');
}
});
}
function handleToolTip() {
$timeout(function() {
$(".group-item").each(function(index) {
var span = $(this).find(".category");
if (span && span[0] && span.width() >= span[0].scrollWidth) {
$(this).removeAttr("title");
$(this).removeAttr("data-original-title");
}
});
}, 100);
}
$scope.changeCatalog = function(selectedCatalog) {
window.GlideWebAnalytics.trackEvent("Service Catalog", "Catalog Browse", "Catalog Filter Changed");
$timeout(function() {
if (selectedCatalog && selectedCatalog.hasOwnProperty("value")) {
$location.search('catalog_id', selectedCatalog.value ? selectedCatalog.value : -1);
$location.search('sys_id', null);
$location.search('spa', null);
}
});
}
$scope.getCategoryAriaLabel = function(category) {
var label = c.data.messages.category + ' ' + category.title + ' ';
if (c.options.omit_badges != 'true' && c.data.largeDataSet != 'true') {
label += c.data.messages.containing + ' ' + category.totalCount + ' ';
if (category.totalCount == 1)
label += c.data.messages.item;
else
label += c.data.messages.items;
}
return label;
}
$scope.handleKeyPressOnCategory = function($event, category) {
var currentElement = $($event.currentTarget);
var allCategories = currentElement.closest('ul.category-list').find('.group-item');
var index = -1;
if (allCategories.length > 0) {
index = allCategories.index(currentElement);
}
//Add stopPropagation and preventDefault only for up/down/right/left arrow keys
switch ($event.which) {
case 40: // bottom key
$event.stopPropagation();
$event.preventDefault();
if (index + 1 < allCategories.length) {
allCategories.get(index).setAttribute('tabindex', '-1');
allCategories.get(index + 1).setAttribute('tabindex', '0');
allCategories.get(index + 1).focus();
}
break;
case 38: // top key
$event.stopPropagation();
$event.preventDefault();
if (index > 0) {
allCategories.get(index).setAttribute('tabindex', '-1');
allCategories.get(index - 1).setAttribute('tabindex', '0');
allCategories.get(index - 1).focus();
}
break;
case 37: // Left key
$event.stopPropagation();
$event.preventDefault();
if (category.showChildren) {
$scope.displayChildren($event, category);
} else {
var parentSubcategory = currentElement.closest('ul.sub-category-list');
if (parentSubcategory) {
var closestParent = parentSubcategory.parent('li').find('.group-item');
if (closestParent && closestParent.length > 0) {
currentElement.attr('tabindex', -1);
closestParent.get(0).setAttribute('tabindex', 0);
closestParent.get(0).focus();
}
}
}
break;
case 39: //right key
$event.stopPropagation();
$event.preventDefault();
if (!category.showChildren) {
$scope.displayChildren($event, category);
} else if (category.subcategories && category.subcategories.length > 0) {
var closestChild = currentElement.next().find('.group-item');
if (closestChild && closestChild.length > 0)
currentElement.attr('tabindex', -1);
closestChild.get(0).setAttribute('tabindex', 0);
closestChild.get(0).focus();
}
break;
}
}
spUtil.getPreference('glide.ui.accessibility', function(value) {
if (value == "true")
$scope.tabindex = 0;
else
$scope.tabindex = -1;
});
$scope.displayChildren = function($event, category) {
$event.stopPropagation();
if (!category || !category.subcategories || category.subcategories.length === 0) {
return;
}
category.showChildren = !category.showChildren;
var currentElement = $($event.currentTarget);
currentElement.closest('.list-group-item').attr('aria-expanded', category.showChildren);
handleToolTip();
};
$scope.toggleSubCategories = function(val) {
toggleSubCategories(c.data.categoriesList, val);
};
function toggleSubCategories(categories, val) {
categories.forEach(function(category) {
category.showChildren = val;
if (category.subcategories && category.subcategories.length > 0) {
toggleSubCategories(category.subcategories, val);
}
});
}
$scope.loadMore = function() {
c.data.new_limit = c.data.limit + (c.options.number_of_categories_to_load || 15);
c.data.more_msg = c.data.pleaseWait;
var categoryDiffCounter = c.data.visibleCategories;
c.server.update().then(function() {
handleToolTip();
if (!c.data.showMore)
$('.sc_category_treeitem_0').focus();
else {
//post-digest handling to ensure that 'show more' button is visible in the window
$scope.$$postDigest(function() {
var showMoreBtn = angular.element('#show-more-btn');
if (showMoreBtn && showMoreBtn.offset()) {
var scrollPosn = showMoreBtn.offset().top;
$("html, body").animate({
scrollTop: scrollPosn
});
}
});
}
categoryDiffCounter = c.data.visibleCategories - categoryDiffCounter;
i18n.getMessages(["Fetched", "additional {0}"], function(msgs) {
var categoryMsg = i18n.format(msgs["additional {0}"], c.options.title);
var concatMsg = msgs["Fetched"] + " " + categoryDiffCounter + " " + categoryMsg;
spAriaUtil.sendLiveMessage(concatMsg);
});
});
};
$scope.categorySelected = function($event, category) {
var s = {
'id': c.data.page || 'category_home',
'sys_id': category.sys_id,
'catalog_id': c.data.catalog_id,
'spa': 1
};
c.data.categoryId = category.sys_id;
$rootScope.$broadcast('$sp.service_catalog.category.selected', s);
$location.search(s);
loadPage();
$scope.displayChildren($event, category);
};
var listenerForBrowseCategories = $scope.$on("$sp.service_catelog.show.categories_widget", function() {
$scope.hideCategoryWidgetInXS = false;
});
$scope.hideBrowseCategory = function() {
$scope.hideCategoryWidgetInXS = true;
$rootScope.$broadcast("$sp.service_catelog.show.items_widget", {
setFocusOnAllCategsLink: true
});
}
$scope.$on("$destroy", function() {
listenerForBrowseCategories();
locationChangeSuccessListener();
locationURLChangeWatcher();
destroyTooltips();
});
//Destroy the sticky tooltips of category
function destroyTooltips() {
var tooltips = $("body > .tooltip");
if (tooltips.length != 0)
tooltips.remove();
}
$scope.isTouchDevice = function() {
return ('ontouchstart' in $window);
}
$scope.getCategoryPadding = function(categoryLevel) {
if (categoryLevel >= 4)
categoryLevel = 4;
return 15 * categoryLevel + "px";
}
// Location change handler for back/forward buttons
var locationChangeSuccessListener = $rootScope.$on('$locationChangeSuccess', function() {
$rootScope.actualLocation = $location.absUrl();
});
var locationURLChangeWatcher = $rootScope.$watch(function() {
return $location.absUrl()
}, function(newLocation, oldLocation) {
if ($rootScope.actualLocation === newLocation) {
var urlParts = urlTools.parseQueryString(newLocation);
if ((urlParts.id === 'sc_category' || urlParts.id === c.data.page) && urlParts.spa == '1' && urlParts.sys_id != c.data.categoryId) {
var categoryInfo = {
'sys_id': urlParts.sys_id,
'catalog_id': urlParts.catalog_id
};
c.data.categoryId = urlParts.sys_id;
$rootScope.$broadcast('$sp.service_catalog.category.selected', categoryInfo);
loadPage();
}
}
});
}
html:
<section aria-label="${Service Catalog categories}">
<div ng-if="c.data.catalogSelectorArr.length > 2" ng-class="{'hidden-xs' : hideCategoryWidgetInXS}" class="panel panel-{{::options.color}} category-widget no-border">
<div class="panel-primary panel-heading">
<h2 class="h4 panel-title">
{{::data.messages.catalogTitle}}
</h2>
</div>
<ul class="list-group category-list" id="catalog_title" data-label="Catalogs" aria-label="{{::data.messages.catalogTitle}}">
<li class="list-group-item text-overflow-ellipsis" ng-include="'catalog-template.html'"></li>
</ul>
</div>
<script type="text/ng-template" id="catalog-template.html">
<select class="sc-basic-select" aria-label="{{::data.messages.catalogTitle}}" ng-change="changeCatalog(selectedCatalog)" sn-focus="true" ng-model="selectedCatalog" ng-options="catalog.displayValue for catalog in c.data.catalogSelectorArr track by catalog.value"></select>
</script>
<div ng-class="{'hidden-xs' : hideCategoryWidgetInXS}" class="panel panel-{{::options.color}} category-widget no-border">
<div class="panel-heading">
<span class="pull-right visible-xs" >
<i class="fa fa-times-circle close-button" ng-click="hideBrowseCategory()" tabindex="0" data-original-title="${Close category explorer}" data-toggle="tooltip" data-placement="bottom"></i>
</span>
<div class="titl"> <h2 class="h4 panel-title">
<span ng-if="::options.glyph">
<fa name="{{::options.glyph}}"></fa>
</span>${All categories}</h2>
<!--changes from 30 &31 line-->
<select name="singleSelect" ng-model="sortSelected" ng-change="sortArray()">
<option value="title">A-Z</option>
<option value="-title" >Z-A</option>
<option value="popular" >Popular Items</option>
<option value="favourite" >Favourite Items</option>
</select>
</div><br>
<input type="text" ng-model="searchCat">
</div>
<ul class="list-group category-list" role="tree" data-label="Catalog filters" aria-label="{{::options.title}}">
<li role="none"
class="list-group-item text-overflow-ellipsis"
ng-if="category.totalCount > 0" ng-include="'category-template.html'"
ng-repeat="category in c.data.visibleCategoriesList as list track by category.title| orderBy:'-title'">
</li>
</ul>
<div class="panel-footer text-center" ng-if="data.showMore">
<button class="text-center btn-link" ng-click="loadMore()" id="show-more-btn">{{::data.showMoreMsg}}</button>
<div class="text-muted text-center">
{{data.more_msg}}
</div>
</div>
</div>
<script type="text/ng-template" id="category-template.html">
<div ng-click="categorySelected($event, category)"
ng-keydown="handleKeyPressOnCategory($event, category)"
sn-focus="category.sys_id == data.categoryId"
ng-enabled="category.totalCount > 0"
role="treeitem"
aria-current ="{{category.sys_id == data.categoryId}}"
ng-class="{true: 'text-active', false: ''}[category.sys_id == data.categoryId]"
tabindex="{{category.isFirstCategory ? '0' : '-1'}}"
class="group-item group-item-primary pointer sc_category_treeitem_{{::data.visibleCategoriesList.indexOf(category)}}" data-ng-attr-style="padding-left:{{getCategoryPadding(category.level + 1)}}"
title="{{::category.title}} {{::category.catalog_tooltip}}"
data-toggle="{{!isTouchDevice() ? 'tooltip' : undefined}}"
data-placement="top"
data-container="body"
data-ng-attr-aria-label="{{getCategoryAriaLabel(category)}}"
ng-attr-aria-expanded="{{category.subcategories.length > 0 && category.totalCount > category.count ? category.showChildren : undefined}}"
aria-posinset = "{{category.position}}"
aria-setsize = "{{list.length}}"
ng-if="getFilterCategories(searchCat, category.title)">
<div role="none">
<i ng-if="::category.subcategories.length > 0 && category.totalCount > category.count"
class="l-h-1_6x pull-left fa collapse-icon"
data-toggle="tooltip"
data-placement="right"
data-original-title="{{category.showChildren ? data.messages.collapse : data.messages.expand}}"
ng-class="{true: 'fa-minus-square-o', false: 'fa-plus-square-o'}[category.showChildren]"
ng-click="displayChildren($event, category)">
</i>
<span class="badge pull-right pointer">{{::category.totalCount}}</span>
<span class="block text-overflow-ellipsis category" id="{{::category.sys_id}}">{{::category.title}}</span>
</div>
</div>
<ul class="list-group sub-category-list list-bg-primary" role="group" aria-label="{{category.title}} ${subcategories}" ng-if="category.showChildren && category.subcategories.length > 0" ng-class="{true: 'no-indent', false: ''}[category.level > 2]">
<li role="none"
class="list-group-item text-overflow-ellipsis"
ng-include="'category-template.html'"
ng-repeat="category in category.subcategories as list track by category.sys_id"
ng-if="category.totalCount > 0">
</li>
</ul>
</script>
</section>