Skip to content

Commit 07adccc

Browse files
authored
Catalog Item Explorer - Widget Upgrade (#2003)
* Catalog Item Explorer - Widget Update Functionality update: - Support for the external URL content items. - The default target window changed to "_self" (same window). - Option to open an item in a new window added at the end of the row. * Update css.scss * Update script.js * Update client_script.js * Update options_schema.json * Update README.md * Update README.md
1 parent b367407 commit 07adccc

File tree

5 files changed

+224
-188
lines changed

5 files changed

+224
-188
lines changed

Modern Development/Service Portal Widgets/Catalog Item Explorer/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@ The primary goal of the Catalog Item Explorer widget is to serve as a valuable l
2424
7. **Quick Search Placeholder:** Define the placeholder message for the Quick Search field to align with your portal's user interface.
2525
8. **Widget Title:** Customize the title of the widget to match its purpose within your Service Portal.
2626
9. **Copyright Display:** Choose whether to display copyright information in the bottom right corner of the widget.
27+
28+
## Latest Update (v1.21):
29+
- **Support for the external URL content items.
30+
- **The default target window changed to "_self" (same window).
31+
- **Option to open an item in the new window added at the end of the row.
Lines changed: 139 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,151 +1,152 @@
1-
api.controller = function ($scope, $window) {
2-
/* widget controller */
3-
var c = this;
1+
api.controller = function($scope, $window) {
2+
/* widget controller */
3+
var c = this;
44

5-
/* Variable and Service Initizalization */
6-
setWidgetState("initial", c.data.catalogCategories);
7-
8-
/* Function to be called when "Show All Items" has been clicked */
9-
c.showAllItems = function () {
5+
/* Variable and Service Initizalization */
106
setWidgetState("initial", c.data.catalogCategories);
11-
c.filteredCatalogItems = c.displayItems = c.data.catalogItems;
12-
c.isShowAllSelected = true;
13-
c.data.currentPage = resetCurrentPage();
14-
c.isMultiplePage = checkMultiPage(c.filteredCatalogItems.length, c.data.itemsPerPage);
15-
};
16-
17-
/* Function to be called when "Quick Search" is active */
18-
c.quickSearch = function () {
19-
if ($scope.searchText.length == 0) {
20-
setWidgetState("initial", c.data.catalogCategories);
21-
return;
7+
8+
/* Function to be called when "Show All Items" has been clicked */
9+
c.showAllItems = function() {
10+
setWidgetState("initial", c.data.catalogCategories);
11+
c.filteredCatalogItems = c.displayItems = c.data.catalogItems;
12+
c.isShowAllSelected = true;
13+
c.data.currentPage = resetCurrentPage();
14+
c.isMultiplePage = checkMultiPage(c.filteredCatalogItems.length, c.data.itemsPerPage);
15+
};
16+
17+
/* Function to be called when "Quick Search" is active */
18+
c.quickSearch = function() {
19+
if ($scope.searchText.length == 0) {
20+
setWidgetState("initial", c.data.catalogCategories);
21+
return;
22+
}
23+
24+
setWidgetState("default-selected", c.data.catalogCategories);
25+
c.data.currentPage = resetCurrentPage();
26+
c.filteredCatalogItems = c.displayItems = $scope.searchText.length > 0 ? quickSearch(c.data.catalogItems, $scope.searchText) : [];
27+
c.isMultiplePage = checkMultiPage(c.filteredCatalogItems.length, c.data.itemsPerPage);
28+
};
29+
30+
/* Function to be called when category letter has been clicked */
31+
c.selectCategory = function(category) {
32+
setWidgetState("default", c.data.catalogCategories);
33+
category.selected = true;
34+
c.data.currentPage = resetCurrentPage();
35+
c.filteredCatalogItems = selectCategory(c.data.catalogItems, category);
36+
c.isMultiplePage = checkMultiPage(c.filteredCatalogItems.length, c.data.itemsPerPage);
37+
c.displayItems = calculateDisplayCatalogItems(c.filteredCatalogItems, c.data.currentPage, c.data.itemsPerPage);
38+
};
39+
40+
/* Function to be called when reset button has been pressed*/
41+
c.resetState = function() {
42+
setWidgetState("initial", c.data.catalogCategories);
43+
};
44+
45+
/* Function to generate URL and define the target window */
46+
c.openUrl = function (itemId, externalUrl, openInNewWindow) {
47+
var fullLink = "";
48+
fullLink = c.data.defaultCatalogLink + itemId;
49+
50+
/* If external URL provided then replace the output with it */
51+
if (externalUrl) { fullLink = externalUrl; }
52+
53+
/* Define the target window */
54+
var target = openInNewWindow ? '_blank' : '_self';
55+
$window.open(fullLink, target);
56+
};
57+
58+
/* Pagination */
59+
60+
/* Function to be called by the form element when another page has been selected */
61+
c.pageChanged = function() {
62+
c.displayItems = calculateDisplayCatalogItems(c.filteredCatalogItems, c.data.currentPage, c.data.itemsPerPage);
63+
};
64+
65+
/* Functions */
66+
67+
/* If it is a quick seach then we are giving filtered array based on the condition */
68+
function quickSearch(items, searchText) {
69+
return items.filter(function(item) {
70+
try {
71+
/* First we need to check that values are not null, otherwise assign them with empty space to avoid app crash */
72+
var itemName = item.name != null ? item.name.toLowerCase() : "";
73+
var itemDescription = item.description != null ? item.description.toLowerCase() : "";
74+
75+
/* Return item if quick search text we placed in our input field is contained in the item name or description */
76+
return (itemName).indexOf(searchText.toLowerCase()) != -1 || (itemDescription).indexOf(searchText.toLowerCase()) != -1;
77+
} catch (error) {
78+
console.log("Something went wrong while filtering searching by item name or description");
79+
}
80+
});
2281
}
2382

24-
setWidgetState("default-selected", c.data.catalogCategories);
25-
c.data.currentPage = resetCurrentPage();
26-
c.filteredCatalogItems = c.displayItems = $scope.searchText.length > 0 ? quickSearch(c.data.catalogItems, $scope.searchText) : [];
27-
c.isMultiplePage = checkMultiPage(c.filteredCatalogItems.length, c.data.itemsPerPage);
28-
};
29-
30-
/* Function to be called when category letter has been clicked */
31-
c.selectCategory = function (category) {
32-
setWidgetState("default", c.data.catalogCategories);
33-
category.selected = true;
34-
c.data.currentPage = resetCurrentPage();
35-
c.filteredCatalogItems = selectCategory(c.data.catalogItems, category);
36-
c.isMultiplePage = checkMultiPage(c.filteredCatalogItems.length, c.data.itemsPerPage);
37-
c.displayItems = calculateDisplayCatalogItems(c.filteredCatalogItems, c.data.currentPage, c.data.itemsPerPage);
38-
};
39-
40-
/* Function to be called when reset button has been pressed*/
41-
c.resetState = function () {
42-
setWidgetState("initial", c.data.catalogCategories);
43-
};
44-
45-
/* Function to make the whole row clickable */
46-
c.openUrl = function (itemId, externalUrl) {
47-
48-
var fullLink = "";
49-
fullLink = c.data.defaultCatalogLink + itemId;
50-
51-
/* If external URL provided then replace the output with it */
52-
if (externalUrl) { fullLink = externalUrl };
53-
54-
$window.open(fullLink, "_blank");
55-
};
56-
57-
/* Pagination */
58-
59-
/* Function to be called by the form element when another page has been selected */
60-
c.pageChanged = function () {
61-
c.displayItems = calculateDisplayCatalogItems(c.filteredCatalogItems, c.data.currentPage, c.data.itemsPerPage);
62-
};
63-
64-
/* Functions */
65-
66-
/* If it is a quick seach then we are giving filtered array based on the condition */
67-
function quickSearch(items, searchText) {
68-
return items.filter(function (item) {
69-
try {
70-
/* First we need to check that values are not null, otherwise assign them with empty space to avoid app crash */
71-
var itemName = item.name != null ? item.name.toLowerCase() : "";
72-
var itemDescription = item.description != null ? item.description.toLowerCase() : "";
73-
74-
/* Return item if quick search text we placed in our input field is contained in the item name or description */
75-
return (itemName).indexOf(searchText.toLowerCase()) != -1 || (itemDescription).indexOf(searchText.toLowerCase()) != -1;
76-
} catch (error) {
77-
console.log("Something went wrong while filtering searching by item name or description");
78-
}
79-
});
80-
}
81-
82-
/* If it is a quick seach then we are giving filtered array based on the condition */
83-
function selectCategory(items, category) {
84-
return items.filter(function (item) {
85-
return (item.name.toLowerCase()).substring(0, 1) == category.letter.toLowerCase();
86-
});
87-
}
88-
89-
/* Function to reset the category selection to default state (all are non-selected) */
90-
function resetSelected(items) {
91-
for (var i = 0; i < items.length; i++) {
92-
items[i].selected = false;
83+
/* If it is a quick seach then we are giving filtered array based on the condition */
84+
function selectCategory(items, category) {
85+
return items.filter(function(item) {
86+
return (item.name.toLowerCase()).substring(0, 1) == category.letter.toLowerCase();
87+
});
88+
}
89+
90+
/* Function to reset the category selection to default state (all are non-selected) */
91+
function resetSelected(items) {
92+
for (var i = 0; i < items.length; i++) {
93+
items[i].selected = false;
94+
}
95+
c.isShowAllSelected = false;
9396
}
94-
c.isShowAllSelected = false;
95-
}
96-
97-
/* Function to reset quick search text in the input field */
98-
function resetQuickSearchText() {
99-
$scope.searchText = "";
100-
}
101-
102-
/* Function that accumulates reset of selected category and quick search text */
103-
function setWidgetState(state, items) {
104-
/* Default state is intended to clear quick search text and reset category selection only */
105-
if (state == "default") {
106-
resetSelected(items);
107-
resetQuickSearchText();
108-
109-
return c.data.msgDefaultState;
97+
98+
/* Function to reset quick search text in the input field */
99+
function resetQuickSearchText() {
100+
$scope.searchText = "";
110101
}
111102

112-
/* Default-Selected is intended to reset the category selection state only e.g. for All items category selection */
113-
if (state == "default-selected") {
114-
resetSelected(items);
103+
/* Function that accumulates reset of selected category and quick search text */
104+
function setWidgetState(state, items) {
105+
/* Default state is intended to clear quick search text and reset category selection only */
106+
if (state == "default") {
107+
resetSelected(items);
108+
resetQuickSearchText();
109+
110+
return c.data.msgDefaultState;
111+
}
112+
113+
/* Default-Selected is intended to reset the category selection state only e.g. for All items category selection */
114+
if (state == "default-selected") {
115+
resetSelected(items);
116+
117+
return c.data.msgCategoryReset;
118+
}
119+
120+
/* Initial is intended to bring the widget to the initial state same as after pager reload */
121+
if (state == "initial") {
122+
resetQuickSearchText();
123+
resetSelected(items);
124+
c.filteredCatalogItems = c.data.catalogItems;
125+
c.displayItems = [];
126+
c.isShowAllSelected = false;
127+
c.isMultiplePage = false;
128+
129+
return "Initialization has completed";
130+
}
131+
}
115132

116-
return c.data.msgCategoryReset;
133+
/* Function to flag multipaging which is used by pagination to display page selector */
134+
function checkMultiPage(itemsToDisplay, numOfPages) {
135+
return Math.ceil(itemsToDisplay / numOfPages) > 1 ? true : false;
117136
}
118137

119-
/* Initial is intended to bring the widget to the initial state same as after pager reload */
120-
if (state == "initial") {
121-
resetQuickSearchText();
122-
resetSelected(items);
123-
c.filteredCatalogItems = c.data.catalogItems;
124-
c.displayItems = [];
125-
c.isShowAllSelected = false;
126-
c.isMultiplePage = false;
138+
/* Function to reset the current page to 1 everytime the category changes */
139+
function resetCurrentPage() {
140+
return 1;
141+
}
142+
143+
/* Function to prepare the list of items to display based on the selected page */
144+
function calculateDisplayCatalogItems(filteredItemsArray, currentPage, itemsPerPage) {
145+
return filteredItemsArray.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
146+
}
127147

128-
return "Initialization has completed";
148+
/* Debug - Logs */
149+
if (c.data.isDebugEnabled) {
150+
console.log(c);
129151
}
130-
}
131-
132-
/* Function to flag multipaging which is used by pagination to display page selector */
133-
function checkMultiPage(itemsToDisplay, numOfPages) {
134-
return Math.ceil(itemsToDisplay / numOfPages) > 1 ? true : false;
135-
}
136-
137-
/* Function to reset the current page to 1 everytime the category changes */
138-
function resetCurrentPage() {
139-
return 1;
140-
}
141-
142-
/* Function to prepare the list of items to display based on the selected page */
143-
function calculateDisplayCatalogItems(filteredItemsArray, currentPage, itemsPerPage) {
144-
return filteredItemsArray.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage);
145-
}
146-
147-
/* Debug - Logs */
148-
if (c.data.isDebugEnabled) {
149-
console.log(c);
150-
}
151152
};

Modern Development/Service Portal Widgets/Catalog Item Explorer/css.scss

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,18 @@
33
justify-content: center;
44
flex-wrap: wrap;
55
width: 100%;
6-
padding: 10px 0;
6+
padding: 1rem 0;
77
margin: 0;
88
}
99

1010
.catalog-category {
11-
font-size: 25px;
11+
font-size: 2.4rem;
1212
font-weight: 600;
1313
}
1414

1515
.category-letter:hover {
1616
transform: scale(1.4);
17-
border-radius: 10px;
17+
border-radius: 1rem;
1818
cursor: pointer;
1919
}
2020

@@ -36,12 +36,35 @@
3636
color: #428BCA;
3737
}
3838

39+
.list-group-item {
40+
margin:0;
41+
display: flex;
42+
align-items: center;
43+
}
44+
3945
.main-column {
46+
flex: 55%;
4047
cursor: pointer;
4148
}
4249

50+
.item-type-column {
51+
flex: 25%;
52+
text-align: center;
53+
font-size: 1.2rem;
54+
}
55+
56+
.external-redirect-cell {
57+
flex: 10%;
58+
text-align: center;
59+
}
60+
61+
.panels-container {
62+
display: flex;
63+
justify-content: center;
64+
}
65+
4366
.panel-footer, .panel-heading {
44-
height: 40px;
67+
height: 4rem;
4568
display: flex;
4669
justify-content: space-between;
4770
align-items: center;

0 commit comments

Comments
 (0)