Created
May 14, 2024 12:59
-
-
Save prince-neres/df20c8bd5be017f246850522c1775df5 to your computer and use it in GitHub Desktop.
Search contents fragment with headless API Liferay
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"fieldSets": [ | |
{ | |
"fields": [ | |
{ | |
"name": "contentStructureId", | |
"label": "ID da estrutura do conteúdo", | |
"type": "text", | |
"dataType": "int", | |
"defaultValue": "" | |
}, | |
{ | |
"name": "vocabularyId", | |
"label": "ID do vocabulário de categorias há filtrar", | |
"type": "text", | |
"dataType": "int", | |
"defaultValue": "" | |
}, | |
{ | |
"name": "itemsPerPage", | |
"label": "Número de items por página", | |
"type": "select", | |
"dataType": "int", | |
"typeOptions": { | |
"validValues": [ | |
{ "value": "1" }, | |
{ "value": "2" }, | |
{ "value": "3" }, | |
{ "value": "4" }, | |
{ "value": "5" }, | |
{ "value": "6" }, | |
{ "value": "7" }, | |
{ "value": "8" }, | |
{ "value": "9" }, | |
{ "value": "10" } | |
] | |
}, | |
"defaultValue": "3" | |
} | |
] | |
} | |
] | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.contents-search-container { | |
background: #f1f2f5; | |
border: 1px solid #ccc; | |
} | |
.contents-search-container .contents-search { | |
gap: 1rem; | |
} | |
.contents-search-container .contents-categories-select, | |
.contents-search-container .contents-search-input { | |
width: 100% !important; | |
padding: 0.625rem !important; | |
background-color: #fff !important; | |
border-color: #ced4da !important; | |
border-style: solid !important; | |
border-width: 0.0625rem !important; | |
border-radius: 0.25rem !important; | |
box-sizing: border-box !important; | |
appearance: none !important; | |
-moz-appearance: none !important; | |
-webkit-appearance: none !important; | |
position: relative !important; | |
height: auto !important; | |
} | |
.contents-search-container .contents-categories-select { | |
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><path d='M6 8l4 4 4-4z'/></svg>") no-repeat right center; | |
} | |
.contents-search-container .search-icon { | |
position: absolute; | |
top: 50%; | |
right: 0.625rem; | |
transform: translateY(-50%); | |
width: 1.5rem; | |
height: 1.5rem; | |
background-image: url(/o/gestao-aluno/css/search-icon.svg); | |
background-repeat: no-repeat; | |
background-size: contain; | |
cursor: pointer; | |
} | |
.contents-search-container .contents-navigation { | |
gap: 1rem; | |
} | |
.contents-search-container .content-entry:not(:last-child) { | |
border-bottom: 1px solid #dddddd; | |
} | |
.contents-search-container a, .contents-search-container a:focus, | |
.contents-search-container a:hover { | |
color: #4a5058; | |
user-select: none; | |
} | |
.contents-search-container a:hover { | |
opacity: .8; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[#assign | |
vocabularyLocalService = serviceLocator.findService("com.liferay.asset.kernel.service.AssetVocabularyLocalService") | |
vocabularyId = configuration.vocabularyId | |
categories = [] | |
/] | |
[#if vocabularyId?has_content && vocabularyId != 0 ] | |
[#assign | |
vocabulary = vocabularyLocalService.getAssetVocabulary(vocabularyId) | |
categories = vocabulary.getCategories() | |
/] | |
[/#if] | |
<div class="contents-search-container p-3"> | |
<div class="contents-search d-flex"> | |
<select | |
class="contents-categories-select" | |
> | |
<option>Todas Categorias</option> | |
[#list categories as category] | |
<option | |
id="${category.getCategoryId()}" | |
> | |
${category.getName()} | |
</option> | |
[/#list] | |
</select> | |
<div class="contents-search-input-wrapper position-relative inline-block w-100"> | |
<input | |
class="contents-search-input" | |
placeholder="Buscar Serviços" | |
/> | |
<span class="search-icon"></span> | |
</div> | |
</div> | |
<div class="contents-results my-3"> | |
</div> | |
<div class="contents-navigation d-flex align-items-center justify-content-center"> | |
</div> | |
</div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const CONTENT_STRUCTURE_ID = configuration.contentStructureId; | |
const API_URL_STRUCTURED_CONTENTS = `/o/headless-delivery/v1.0/content-structures/${CONTENT_STRUCTURE_ID}/structured-contents`; | |
const ITEMS_PER_PAGE = configuration.itemsPerPage; | |
const selectCategory = fragmentElement.querySelector( | |
".contents-categories-select" | |
); | |
const searchInput = fragmentElement.querySelector(".contents-search-input"); | |
const contentsResultsElement = | |
fragmentElement.querySelector(".contents-results"); | |
const contentsNavigation = fragmentElement.querySelector( | |
".contents-navigation" | |
); | |
const locale = themeDisplay.getBCP47LanguageId(); | |
let contents = []; | |
let currPage = 0; | |
let totalPages = 0; | |
const fetchContents = async (page) => { | |
const categorySelected = Number(selectCategory.selectedOptions[0].id); | |
const categoryQuery = categorySelected | |
? `&filter=taxonomyCategoryIds%2Fany%28t%3At+eq+${categorySelected}%29` | |
: ""; | |
const searchValue = searchInput.value; | |
const searchQuery = searchValue ? `&search=${searchValue}` : ""; | |
const sortParam = "sort=title%3Aasc"; | |
const pageSizeParam = `pageSize=${ITEMS_PER_PAGE}`; | |
const pageParam = `page=${page}`; | |
const url = `${API_URL_STRUCTURED_CONTENTS}?${sortParam}&${pageSizeParam}&${pageParam}&${categoryQuery}&${searchQuery}`; | |
try { | |
const response = await Liferay.Util.fetch(url, { | |
headers: { "Accept-Language": locale }, | |
}); | |
if (!response.ok) { | |
throw new Error("Failed to fetch contents"); | |
} | |
const data = await response.json(); | |
const { items } = data; | |
currPage = data.page; | |
totalPages = data.lastPage; | |
return items.map((content) => ({ | |
title: content.title, | |
url: "w/" + content.friendlyUrlPath, | |
category: content.taxonomyCategoryBriefs[0]?.taxonomyCategoryName || "", | |
})); | |
} catch (error) { | |
console.error("Error fetching contents:", error); | |
return []; | |
} | |
}; | |
const putContentsResults = () => { | |
contentsResultsElement.innerHTML = ""; | |
contents.forEach((content) => { | |
const contentDiv = document.createElement("div"); | |
contentDiv.classList.add("content-entry", "py-3"); | |
const contentAnchor = document.createElement("a"); | |
contentAnchor.classList.add("text-decoration-none", "font-weight-bold"); | |
contentAnchor.innerText = content.title; | |
contentAnchor.setAttribute("href", content.url); | |
contentDiv.appendChild(contentAnchor); | |
contentsResultsElement.appendChild(contentDiv); | |
}); | |
}; | |
const createNavigation = () => { | |
contentsNavigation.innerHTML = ""; | |
if (currPage != 1) createNavigationLink("«", currPage - 1, true); | |
if (currPage >= 3 || currPage === 2) { | |
createNavigationLink(1, 1, true); | |
if (currPage >= 3) { | |
createNavigationLink("...", 0, false); | |
} | |
} | |
createNavigationLink(currPage, currPage, false); | |
if (totalPages - currPage >= 2 || currPage === totalPages - 1) { | |
if (totalPages - currPage >= 2) createNavigationLink("...", 0, false); | |
createNavigationLink(totalPages, totalPages, true); | |
} | |
if (currPage != totalPages) | |
createNavigationLink("»", currPage + 1, true); | |
const navItems = fragmentElement.querySelectorAll("[data-page]"); | |
navItems.forEach((navItem) => { | |
navItem.addEventListener("click", handleChange); | |
}); | |
}; | |
const createNavigationLink = (content, page, navigable) => { | |
const navLink = document.createElement("a"); | |
navLink.innerHTML = content; | |
navLink.setAttribute("href", "javascript:void(0);"); | |
navLink.classList.add("text-decoration-none"); | |
if (navigable) navLink.setAttribute("data-page", page); | |
else navLink.classList.add("font-weight-bold"); | |
contentsNavigation.appendChild(navLink); | |
}; | |
const handleChange = async (event) => { | |
const page = event.target.dataset?.page || 1; | |
contents = await fetchContents(page); | |
putContentsResults(); | |
createNavigation(); | |
}; | |
(async () => { | |
contents = await fetchContents(1); | |
putContentsResults(); | |
createNavigation(); | |
})(); | |
searchInput.addEventListener("blur", handleChange); | |
searchInput.addEventListener("keyup", function (event) { | |
if (event.key === "Enter" || event.keyCode === 13) { | |
handleChange(event); | |
} | |
}); | |
selectCategory.addEventListener("change", handleChange); | |
contentsResultsElement.style.height = ITEMS_PER_PAGE * 75 + "px"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment