diff --git a/cigaradvisor/blocks/article-list/article-list.css b/cigaradvisor/blocks/article-list/article-list.css index 72067cdc..330a7a99 100644 --- a/cigaradvisor/blocks/article-list/article-list.css +++ b/cigaradvisor/blocks/article-list/article-list.css @@ -1,4 +1,4 @@ -.article-list.block .article-teaser-wrapper { +.article-list.block .article-teaser-wrapper .article-teaser-list{ display: flex; flex-direction: column; gap: 20px; @@ -56,7 +56,7 @@ } @media screen and (min-width: 900px) { - .article-list.block .article-teaser-wrapper { + .article-list.block .article-teaser-wrapper .article-teaser-list { display: flex; flex-flow: wrap row; gap: 20px; diff --git a/cigaradvisor/blocks/article-list/article-list.js b/cigaradvisor/blocks/article-list/article-list.js index abbfc6c0..7183bbb2 100644 --- a/cigaradvisor/blocks/article-list/article-list.js +++ b/cigaradvisor/blocks/article-list/article-list.js @@ -1,49 +1,28 @@ import { readBlockConfig, loadCSS } from '../../scripts/aem.js'; -import { fetchAuthorInfo, fetchCategoryInfo, fetchPostsInfo } from '../../scripts/scripts.js'; +import { fetchAuthorInfo, fetchCategoryInfo, fetchPostsInfo, getPostByIdx, loadPosts } from '../../scripts/scripts.js'; import { buildArticleTeaser } from '../article-teaser/article-teaser.js'; import { generatePagination } from '../../scripts/util.js'; -export default async function decorate(block) { - await loadCSS(`${window.hlx.codeBasePath}/blocks/article-teaser/article-teaser.css`); - const configs = readBlockConfig(block); - block.innerHTML = ''; - const { limit = 10 } = configs; - let { author, category, articles } = configs; - if (!category && Object.hasOwn(configs, 'category') && window.location.pathname.includes('/cigaradvisor/category/')) { - category = window.location.toString(); - } else if (!author && Object.hasOwn(configs, 'author') && window.location.pathname.includes('/cigaradvisor/author/')) { - author = window.location.toString(); - } - let currentPage = 1; - if (category) { - articles = await fetchPostsInfo(category, 'category'); - } else if (author) { - articles = await fetchPostsInfo(author, 'author'); - } else if (articles) { - const tmp = []; - const promises = []; - articles.forEach((post) => { - promises.push(fetchPostsInfo(post)); - }); - await Promise.all(promises).then((result) => { - result.forEach((detail) => { - if (detail && detail.length > 0) tmp.push(detail[0]); - }); - }); - articles = tmp; - } +let pageSize = 10; + +async function renderPage(wrapper, articles) { if (!articles || articles.length === 0) { return; } - const totalPages = Math.ceil(articles.length / limit); - const articleTeaserWrapper = document.createElement('div'); - articleTeaserWrapper.classList.add('article-teaser-wrapper'); - const urlParams = new URLSearchParams(window.location.search); - currentPage = urlParams.get('page') ? parseInt(urlParams.get('page'), 10) : 1; + const list = document.createElement('div'); + list.classList.add('article-teaser-list'); + let currentPage = 1; + const match = window.location.hash.match(/page=(\d+)/) + if (match) { + currentPage = isNaN(parseInt(match[1])) ? currentPage : parseInt(match[1]); + } + const totalPages = Math.ceil(articles.length / pageSize); + // eslint-disable-next-line max-len - const articlePromises = [...articles].slice((currentPage - 1) * limit, currentPage * limit).map(async (article) => { + // eslint-disable-next-line max-len + const articlePromises = [...articles].slice((currentPage - 1) * pageSize, currentPage * pageSize).map(async (article) => { const articleTeaser = document.createElement('div'); articleTeaser.classList.add('article-teaser'); articleTeaser.classList.add('block'); @@ -56,16 +35,102 @@ export default async function decorate(block) { buildArticleTeaser(articleTeaser, article); return articleTeaser; }); + await Promise.all(articlePromises).then((results) => { results.forEach((teaser) => { - articleTeaserWrapper.append(teaser); + list.append(teaser); }); }); - block.replaceChildren(articleTeaserWrapper); + wrapper.replaceChildren(list); + if (totalPages > 1) { const paginationContainer = document.createElement('div'); paginationContainer.classList.add('pagination-container'); paginationContainer.appendChild(generatePagination(currentPage, totalPages)); - block.append(paginationContainer); + wrapper.append(paginationContainer); + } +} + +async function renderByCategory(wrapper, category) { + const articles = await fetchPostsInfo(category, 'category'); + await renderPage(wrapper, articles); +} + + +async function renderByAuthor(wrapper, author) { + const articles = await fetchPostsInfo(author, 'author'); + await renderPage(wrapper, articles); +} + +async function renderByList(configs, wrapper, articles) { + const extra = []; + if (configs.next && !isNaN(parseInt(configs.next))) { + const total = parseInt(configs.next); + let i = 0; // Counter for how many we've found + let idx = 1; // Counter for moving through the post list. + do { + const next = await getPostByIdx(idx); + if (!next) break; + const url = new URL(next.path, window.location.href).toString(); + if (!articles.includes(url)) { + extra.push(next); + i++; + } + idx++; + } while (i < total) } + + const tmp = []; + const promises = []; + articles.forEach((post) => { + promises.push(fetchPostsInfo(post)); + }); + await Promise.all(promises).then((result) => { + result.forEach((detail) => { + if (detail && detail.length > 0) tmp.push(detail[0]); + }); + }); + articles = tmp; + articles.push(...extra); + return renderPage(wrapper, articles); +} + +export default async function decorate(block) { + await loadCSS(`${window.hlx.codeBasePath}/blocks/article-teaser/article-teaser.css`); + const configs = readBlockConfig(block); + let { author, category, articles } = configs; + + let limit = isNaN(parseInt(configs.limit)) ? 10 : parseInt(configs.limit); + if (limit) { + pageSize = Math.round(limit - (limit % 2)); + } + + if (!category && Object.hasOwn(configs, 'category') && window.location.pathname.includes('/cigaradvisor/category/')) { + category = window.location.toString(); + } else if (!author && Object.hasOwn(configs, 'author') && window.location.pathname.includes('/cigaradvisor/author/')) { + author = window.location.toString(); + } + + const articleTeaserWrapper = document.createElement('div'); + articleTeaserWrapper.classList.add('article-teaser-wrapper'); + block.replaceChildren(articleTeaserWrapper); + + + if (category) { + await renderByCategory(articleTeaserWrapper, category) + } else if (author) { + await renderByAuthor(articleTeaserWrapper, author); + } else if (articles) { + await renderByList(configs, articleTeaserWrapper, articles); + } + + addEventListener('hashchange', async (event) => { + if (category) { + await renderByCategory(articleTeaserWrapper, category) + } else if (author) { + await renderByAuthor(articleTeaserWrapper, author); + } else if (articles) { + await renderByList(configs, articleTeaserWrapper, articles); + } + }); } diff --git a/cigaradvisor/blocks/author-list/author-list.css b/cigaradvisor/blocks/author-list/author-list.css index 44d48bc0..16ccc29a 100644 --- a/cigaradvisor/blocks/author-list/author-list.css +++ b/cigaradvisor/blocks/author-list/author-list.css @@ -1,3 +1,4 @@ + .author-list.block .pagination-container { display: flex; justify-content: center; @@ -53,4 +54,4 @@ .author-list.block .author-teaser.block .author-details .author-heading h3 { display: none; -} \ No newline at end of file +} diff --git a/cigaradvisor/blocks/author-list/author-list.js b/cigaradvisor/blocks/author-list/author-list.js index b8685cb5..58c4e05d 100644 --- a/cigaradvisor/blocks/author-list/author-list.js +++ b/cigaradvisor/blocks/author-list/author-list.js @@ -3,21 +3,21 @@ import { buildAuthorTeaser } from '../author-teaser/author-teaser.js'; import { readBlockConfig, loadCSS } from '../../scripts/aem.js'; import { generatePagination } from '../../scripts/util.js'; -export default async function decorate(block) { - await loadCSS(`${window.hlx.codeBasePath}/blocks/author-teaser/author-teaser.css`); - const configs = readBlockConfig(block); - const { curatedauthors, limit = 10 } = configs; - let currentPage = 1; - block.innerHTML = ''; +let pageSize; - const urlParams = new URLSearchParams(window.location.search); - currentPage = urlParams.get('page') ? parseInt(urlParams.get('page'), 10) : 1; +async function renderList(wrapper, curatedAuthors) { - let allAuthors = await getAllAuthors(true); + let currentPage = 1; + const match = window.location.hash.match(/page=(\d+)/) + if (match) { + currentPage = isNaN(parseInt(match[1])) ? currentPage : parseInt(match[1]); + } + + let allAuthors = [...(await getAllAuthors(true))]; const curatedAuthorsInfo = []; [...allAuthors].forEach((author) => { - if (curatedauthors.some((curatedAuthor) => curatedAuthor.includes(author.path))) { + if (curatedAuthors.some((curatedAuthor) => curatedAuthor.includes(author.path))) { curatedAuthorsInfo.push(author); allAuthors.splice(allAuthors.indexOf(author), 1); } @@ -25,22 +25,42 @@ export default async function decorate(block) { allAuthors = [...curatedAuthorsInfo, ...allAuthors]; const totalAuthors = allAuthors.length; - const totalPages = Math.ceil(totalAuthors / limit); - [...allAuthors].slice((currentPage - 1) * limit, currentPage * limit).map(async (author) => { - const authorTeaserWrapper = document.createElement('div'); - authorTeaserWrapper.classList.add('author-teaser-wrapper'); + const totalPages = Math.ceil(totalAuthors / pageSize); + + const list = document.createElement('div'); + list.classList.add('author-teaser-list'); + + + [...allAuthors].slice((currentPage - 1) * pageSize, currentPage * pageSize).map(async (author) => { const authorTeaser = document.createElement('div'); authorTeaser.classList.add('author-teaser'); authorTeaser.classList.add('block'); - authorTeaserWrapper.append(authorTeaser); buildAuthorTeaser(authorTeaser, author, true); - block.append(authorTeaserWrapper); + list.append(authorTeaser); }); + wrapper.replaceChildren(list); + if (totalPages > 1) { - const pageinationContainer = document.createElement('div'); - pageinationContainer.classList.add('pagination-container'); - pageinationContainer.appendChild(generatePagination(currentPage, totalPages)); - block.append(pageinationContainer); + const paginationContainer = document.createElement('div'); + paginationContainer.classList.add('pagination-container'); + paginationContainer.appendChild(generatePagination(currentPage, totalPages)); + wrapper.append(paginationContainer); } } + +export default async function decorate(block) { + await loadCSS(`${window.hlx.codeBasePath}/blocks/author-teaser/author-teaser.css`); + const configs = readBlockConfig(block); + const { curatedauthors } = configs; + pageSize = isNaN(parseInt(configs.limit)) ? 2 : parseInt(configs.limit); + + const authorTeaserWrapper = document.createElement('div'); + authorTeaserWrapper.classList.add('author-teaser-wrapper'); + block.replaceChildren(authorTeaserWrapper); + await renderList(authorTeaserWrapper, curatedauthors); + + addEventListener('hashchange', async() => { + await renderList(authorTeaserWrapper, curatedauthors); + }) +} diff --git a/cigaradvisor/blocks/author-teaser/author-teaser.css b/cigaradvisor/blocks/author-teaser/author-teaser.css index f6335b44..82b98a22 100644 --- a/cigaradvisor/blocks/author-teaser/author-teaser.css +++ b/cigaradvisor/blocks/author-teaser/author-teaser.css @@ -1,7 +1,3 @@ -.author-teaser-wrapper { - display: flex; - padding: 20px 0; -} .author-teaser.block { display: flex; diff --git a/cigaradvisor/blocks/author-teaser/author-teaser.js b/cigaradvisor/blocks/author-teaser/author-teaser.js index 15d1bf4a..973d9e6b 100644 --- a/cigaradvisor/blocks/author-teaser/author-teaser.js +++ b/cigaradvisor/blocks/author-teaser/author-teaser.js @@ -52,7 +52,7 @@ export function buildAuthorTeaser(parentElement, author, isAuthorList = false) { } if (author.name) { const link = document.createElement('a'); - link.dataset.href = author.path; + link.href = author.path; link.textContent = `Show all ${author.name}'s Articles`; authorDetails.append(link); } diff --git a/cigaradvisor/scripts/scripts.js b/cigaradvisor/scripts/scripts.js index c52cc13e..5619086b 100644 --- a/cigaradvisor/scripts/scripts.js +++ b/cigaradvisor/scripts/scripts.js @@ -192,6 +192,12 @@ export function getRelativePath(path) { } let articleIndexData; + +/** + * Returns all the posts in the posts index. + * + * @return {Promise} + */ export async function loadPosts() { if (!articleIndexData) { const resp = await fetch(ARTICLE_INDEX_PATH); @@ -220,7 +226,7 @@ export async function fetchPostsInfo(filterValue, filterParam = 'path') { /** * Fetches a post by a given index, starting at 1. * @param idx the index - * @return {Promise} + * @return {Promise} */ export async function getPostByIdx(idx) { const articles = await loadPosts(); diff --git a/cigaradvisor/scripts/util.js b/cigaradvisor/scripts/util.js index 4291e4a6..41264a58 100644 --- a/cigaradvisor/scripts/util.js +++ b/cigaradvisor/scripts/util.js @@ -15,7 +15,7 @@ function createPageLink(pageNumber, text, className) { const listItem = document.createElement('li'); const link = document.createElement('a'); const currentPagePath = window.location.pathname; - link.href = `${currentPagePath}?page=${pageNumber}`; + link.href = `${currentPagePath}#page=${pageNumber}`; link.textContent = text; if (className) {