Added read more articles section
This commit is contained in:
parent
6f0b44dc69
commit
5e7981efdb
39
css/main.css
39
css/main.css
@ -22,7 +22,7 @@ body,
|
||||
body * {
|
||||
--accent-color: #256eff;
|
||||
--text-color: 20, 20, 20;
|
||||
--background-color: 255, 250, 246;
|
||||
--background-color: 252, 245, 239;
|
||||
--foreground-color: rgb(255, 255, 255);
|
||||
--danger-color: rgb(255, 75, 75);
|
||||
--green: #1cad59;
|
||||
@ -60,12 +60,9 @@ strong:not(:last-of-type) {
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:not([class]) {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
a:not([class]):focus-visible {
|
||||
a:focus-visible {
|
||||
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
|
||||
}
|
||||
|
||||
@ -118,7 +115,6 @@ button,
|
||||
|
||||
.cta {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
@ -676,9 +672,22 @@ theme-toggle {
|
||||
}
|
||||
|
||||
.article-card {
|
||||
gap: 0.3rem;
|
||||
position: relative;
|
||||
gap: 0.3rem 1rem;
|
||||
grid-template-columns: 5rem 1fr;
|
||||
grid-template-rows: auto 1fr;
|
||||
align-items: flex-start;
|
||||
grid-template-areas: "img title" "img content";
|
||||
}
|
||||
.article-card img {
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
}
|
||||
.article-card a {
|
||||
grid-area: title;
|
||||
color: inherit;
|
||||
}
|
||||
.article-card .article-link {
|
||||
@ -688,6 +697,7 @@ theme-toggle {
|
||||
line-height: 1.4;
|
||||
}
|
||||
.article-card .flex {
|
||||
grid-area: content;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
@ -719,6 +729,7 @@ theme-toggle {
|
||||
overflow: hidden;
|
||||
}
|
||||
.trending-article p {
|
||||
font-family: "Noto serif", serif;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
@ -762,7 +773,6 @@ theme-toggle {
|
||||
|
||||
#article {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow-y: auto;
|
||||
}
|
||||
#article main > section:last-of-type {
|
||||
@ -813,11 +823,6 @@ theme-toggle {
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#article_category {
|
||||
color: var(--accent-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
#article_image {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
@ -840,6 +845,12 @@ theme-toggle {
|
||||
padding: 0.3rem 0.5rem;
|
||||
}
|
||||
|
||||
#related_articles {
|
||||
margin-top: 1rem;
|
||||
grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
#action_panel {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
@ -949,6 +960,7 @@ theme-toggle {
|
||||
|
||||
#preview_popup h1,
|
||||
#article h1 {
|
||||
font-weight: 800;
|
||||
font-size: 1.7rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
@ -1194,7 +1206,6 @@ theme-toggle {
|
||||
#preview_popup h1,
|
||||
#article h1 {
|
||||
font-size: 2.2rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
#preview_popup h3,
|
||||
#article h3 {
|
||||
|
||||
2
css/main.min.css
vendored
2
css/main.min.css
vendored
File diff suppressed because one or more lines are too long
@ -19,7 +19,7 @@ body {
|
||||
* {
|
||||
--accent-color: #256eff;
|
||||
--text-color: 20, 20, 20;
|
||||
--background-color: 255, 250, 246;
|
||||
--background-color: 252, 245, 239;
|
||||
--foreground-color: rgb(255, 255, 255);
|
||||
--danger-color: rgb(255, 75, 75);
|
||||
--green: #1cad59;
|
||||
@ -63,10 +63,7 @@ strong {
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
a:not([class]) {
|
||||
color: var(--accent-color);
|
||||
|
||||
&:focus-visible {
|
||||
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
|
||||
}
|
||||
@ -116,7 +113,6 @@ button,
|
||||
}
|
||||
.cta {
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
@ -638,8 +634,21 @@ theme-toggle {
|
||||
}
|
||||
|
||||
.article-card {
|
||||
gap: 0.3rem;
|
||||
position: relative;
|
||||
gap: 0.3rem 1rem;
|
||||
grid-template-columns: 5rem 1fr;
|
||||
grid-template-rows: auto 1fr;
|
||||
align-items: flex-start;
|
||||
grid-template-areas: "img title" "img content";
|
||||
img {
|
||||
left: 0;
|
||||
top: 0;
|
||||
position: absolute;
|
||||
height: 5rem;
|
||||
width: 5rem;
|
||||
}
|
||||
a {
|
||||
grid-area: title;
|
||||
color: inherit;
|
||||
}
|
||||
.article-link {
|
||||
@ -649,6 +658,7 @@ theme-toggle {
|
||||
line-height: 1.4;
|
||||
}
|
||||
.flex {
|
||||
grid-area: content;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
@ -678,6 +688,7 @@ theme-toggle {
|
||||
overflow: hidden;
|
||||
}
|
||||
p {
|
||||
font-family: "Noto serif", serif;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
@ -721,7 +732,6 @@ theme-toggle {
|
||||
|
||||
#article {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow-y: auto;
|
||||
main {
|
||||
& > section:last-of-type {
|
||||
@ -770,10 +780,6 @@ theme-toggle {
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
#article_category {
|
||||
color: var(--accent-color);
|
||||
font-weight: 500;
|
||||
}
|
||||
#article_image {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
@ -792,6 +798,11 @@ theme-toggle {
|
||||
border-radius: 0.3rem;
|
||||
padding: 0.3rem 0.5rem;
|
||||
}
|
||||
#related_articles {
|
||||
margin-top: 1rem;
|
||||
grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
|
||||
gap: 1.5rem;
|
||||
}
|
||||
#action_panel {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
@ -904,10 +915,10 @@ theme-toggle {
|
||||
#preview_popup,
|
||||
#article {
|
||||
h1 {
|
||||
font-weight: 800;
|
||||
font-size: 1.7rem;
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
h3:not(:first-of-type) {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
@ -1127,7 +1138,6 @@ theme-toggle {
|
||||
#article {
|
||||
h1 {
|
||||
font-size: 2.2rem;
|
||||
font-weight: 800;
|
||||
}
|
||||
h3 {
|
||||
font-size: 1.4rem;
|
||||
|
||||
52
index.html
52
index.html
@ -13,7 +13,7 @@
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400..700&family=Noto+Serif:ital,wght@0,400;0,700;1,400;1,700&display=swap"
|
||||
rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@400..800&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Archivo:wght@400..900&display=swap" rel="stylesheet">
|
||||
<script src="purify.min.js" defer></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/fuse.js@6.4.6" defer></script>
|
||||
<script id="floGlobals">
|
||||
@ -236,7 +236,7 @@
|
||||
</aside>
|
||||
<main class="grid gap-2">
|
||||
<header class="hero-section">
|
||||
<div class="flex align-center" style="margin-bottom: 0.5rem; font-size: 0.9rem;">
|
||||
<div class="flex align-center" style="margin-bottom: 0.5rem; font-size: 0.9rem; font-weight: 500;">
|
||||
<a href="#/home">Home</a>
|
||||
<svg class="icon" xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24"
|
||||
width="24px" fill="#000000">
|
||||
@ -268,6 +268,10 @@
|
||||
<h4>Article by -</h4>
|
||||
<div id="article_contributors" class="flex"></div>
|
||||
</section>
|
||||
<section>
|
||||
<h5>Pick something to read </h5>
|
||||
<div id="related_articles" class="grid"></div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<button id="go_to_top" class="floating-button hide" onclick="goToTop()">
|
||||
@ -563,8 +567,9 @@
|
||||
</div>
|
||||
</template>
|
||||
<template id="article_card_template">
|
||||
<li class="article-card grid" draggable="true">
|
||||
<li class="article-card grid">
|
||||
<a href="" class="grid article-link">
|
||||
<img class="article-card__image" src="" alt="" loading="lazy">
|
||||
<h4 class="article-card__title"></h4>
|
||||
</a>
|
||||
<div class="flex align-center" style="margin-top: 0.3rem;">
|
||||
@ -1106,11 +1111,12 @@
|
||||
const relativeTime = new RelativeTime({ style: 'narrow' });
|
||||
const render = {
|
||||
articleCard(details) {
|
||||
const { uid: articleID, category, title, readTime, published } = details
|
||||
const { uid: articleID, category, title, readTime, published, heroImage } = details
|
||||
const clone = getRef('article_card_template').content.cloneNode(true).firstElementChild
|
||||
clone.querySelector('.article-card__category').textContent = category
|
||||
clone.querySelector('.article-card__category').href = `#/explore?type=category&query=${category}`
|
||||
clone.querySelector('.article-link').href = `#/article?articleID=${articleID}`
|
||||
clone.querySelector('.article-card__image').src = heroImage
|
||||
clone.querySelector('.article-card__title').textContent = title
|
||||
clone.querySelector('.article-card__read-time').textContent = `${readTime} Min read`
|
||||
clone.querySelector('.article-card__published').textContent = relativeTime.from(published)
|
||||
@ -1227,8 +1233,32 @@
|
||||
})
|
||||
getRef('article_contributors').innerHTML = ''
|
||||
getRef('article_contributors').append(frag)
|
||||
getRef('like_count').textContent = floGlobals.appObjects.rmTimes.articles[articleID].votes
|
||||
|
||||
const fuse = new Fuse(getArrayOfObj(floGlobals.appObjects.rmTimes.articles), { keys: ['category'], threshold: 0 })
|
||||
const searchResult = fuse.search(category).map(v => v.item).filter(v => v.uid !== articleID)
|
||||
compactIDB.readData('appObjects', 'heroImages').then(heroImages => {
|
||||
let randomNumbers = []
|
||||
if (searchResult.length > 3) {
|
||||
// generate non-repeating random numbers
|
||||
while (randomNumbers.length < 3) {
|
||||
const randomNumber = Math.floor(Math.random() * searchResult.length)
|
||||
if (!randomNumbers.includes(randomNumber)) {
|
||||
randomNumbers.push(randomNumber)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
randomNumbers = searchResult.map((v, i) => i)
|
||||
}
|
||||
randomNumbers.forEach((index) => {
|
||||
const { uid } = searchResult[index]
|
||||
frag.append(render.articleCard({ ...searchResult[index], heroImage: heroImages[uid].thumbnail }))
|
||||
})
|
||||
getRef('related_articles').innerHTML = ''
|
||||
getRef('related_articles').append(frag)
|
||||
})
|
||||
|
||||
// implement live voting
|
||||
getRef('like_count').textContent = floGlobals.appObjects.rmTimes.articles[articleID].votes
|
||||
if (!openedArticles.hasOwnProperty(articleID)) {
|
||||
floCloudAPI.requestGeneralData(`article_${articleID}_votes`, {
|
||||
lowerVectorClock: floGlobals.appObjects.rmTimes.articles[articleID].lastCountedVC + 1,
|
||||
@ -1251,23 +1281,25 @@
|
||||
getRef('like_count').textContent = floGlobals.appObjects.rmTimes.articles[articleID].votes
|
||||
}
|
||||
},
|
||||
explorePage(params) {
|
||||
async explorePage(params) {
|
||||
const heroImages = await compactIDB.readData('appObjects', 'heroImages')
|
||||
const { type, query } = params
|
||||
const frag = document.createDocumentFragment()
|
||||
const sortedByTime = getArrayOfObj(floGlobals.appObjects.rmTimes.articles).sort((a, b) => b.published - a.published)
|
||||
if (type === 'recent') {
|
||||
sortedByTime.forEach(articleDetail => frag.append(render.trendingArticleCard(articleDetail)))
|
||||
sortedByTime.forEach(articleDetail => frag.append(render.trendingArticleCard({ ...articleDetail, heroImage: heroImages[articleDetail.uid].thumbnail })))
|
||||
} else {
|
||||
const options = (type === 'category') ? { keys: ['category'], threshold: 0 } : { keys: ['title', 'category', 'tags'], threshold: 0.3 }
|
||||
const fuse = new Fuse(sortedByTime, options)
|
||||
const searchResult = fuse.search(query).map(v => v.item)
|
||||
searchResult.forEach(articleDetail => frag.append(render.trendingArticleCard(articleDetail)))
|
||||
searchResult.forEach(articleDetail => frag.append(render.trendingArticleCard({ ...articleDetail, heroImage: heroImages[articleDetail.uid].thumbnail })))
|
||||
getRef('explore_heading').textContent = `${type === 'category' ? 'Explore' : 'Related to'} ${query}`
|
||||
}
|
||||
getRef('query_results_list').innerHTML = ''
|
||||
getRef('query_results_list').append(frag)
|
||||
},
|
||||
writerPage(params) {
|
||||
async writerPage(params) {
|
||||
const heroImages = await compactIDB.readData('appObjects', 'heroImages')
|
||||
if (floGlobals.appObjects.rmTimes.articleWriters.hasOwnProperty(params.id)) {
|
||||
const { name, bio } = floGlobals.appObjects.rmTimes.articleWriters[params.id]
|
||||
getRef('writer_initials').textContent = name[0]
|
||||
@ -1284,7 +1316,7 @@
|
||||
const options = { keys: ['contributors'], threshold: 0 }
|
||||
const fuse = new Fuse(sortedByTime, options)
|
||||
const searchResult = fuse.search(params.id).map(v => v.item)
|
||||
searchResult.forEach(articleDetail => frag.append(render.trendingArticleCard(articleDetail)))
|
||||
searchResult.forEach(articleDetail => frag.append(render.trendingArticleCard({ ...articleDetail, heroImage: heroImages[articleDetail.uid].thumbnail })))
|
||||
getRef('written_article_list').innerHTML = ''
|
||||
getRef('written_article_list').append(frag)
|
||||
},
|
||||
|
||||
Loading…
Reference in New Issue
Block a user