diff options
author | ache <ache@ache.one> | 2022-12-10 08:15:44 +0100 |
---|---|---|
committer | ache <ache@ache.one> | 2022-12-10 08:15:44 +0100 |
commit | 045b3f3c21bf9c0f9b728fe14ce75e4d2a90944a (patch) | |
tree | f1ffd05522f351eba8561410548b404e10cfa23a /src | |
parent | Show date on each article (diff) |
First implementation of Likes
Diffstat (limited to 'src')
-rw-r--r-- | src/build/index.mjs | 4 | ||||
-rwxr-xr-x | src/css/_contenu.scss | 111 | ||||
-rw-r--r-- | src/js/love.js | 113 | ||||
-rw-r--r-- | src/templates/article.tmpl | 2 | ||||
-rw-r--r-- | src/templates/likes.tmpl | 17 |
5 files changed, 245 insertions, 2 deletions
diff --git a/src/build/index.mjs b/src/build/index.mjs index a8fac14..54a0b02 100644 --- a/src/build/index.mjs +++ b/src/build/index.mjs @@ -103,6 +103,7 @@ const loadMD = (listFile, suffix) => { }; const leftPanelTmpl = fs.readFileSync('src/templates/left.tmpl', 'utf8'); +const likesTmpl = fs.readFileSync('src/templates/likes.tmpl', 'utf8'); const headerTmpl = fs.readFileSync('src/templates/header.tmpl', 'utf8'); const articleTmpl = fs.readFileSync('src/templates/article.tmpl', 'utf8'); const indexTmpl = fs.readFileSync('src/templates/index.tmpl', 'utf8'); @@ -113,13 +114,12 @@ const baseUrl = 'https://ache.one/'; const partials = { header: headerTmpl, leftPanel: leftPanelTmpl, + likesButton: likesTmpl, hid: hidTmpl, }; const svg = loadSVG(); - const articles = loadMD(listArticles, 'articles'); - const tagsArticle = new Map(); for (const article of articles) { diff --git a/src/css/_contenu.scss b/src/css/_contenu.scss index 4dab365..c261aff 100755 --- a/src/css/_contenu.scss +++ b/src/css/_contenu.scss @@ -281,6 +281,116 @@ code { } } +section.likes { + display: flex; + justify-content: center; + + .likesBox { + padding: 20px; + border-radius: 8px; + background-color: #CDE3EC; + display: flex; + + .likesTitle { + font: monospace; + font-family: Source Sans Pro,Segoe UI,Trebuchet MS,Helvetica,Helvetica Neue,Arial,sans-serif; + font-weight: 800; + } + .likesText { + font-size: 0.8em; + } + .likesNotes { + font-size: 0.8em; + color: #777; + &.err { + color: red; + } + } + + + .icon { + fill: transparent; + stroke: pink; + stroke-width: 20; + cursor: pointer; + position: relative; + svg { + overflow: visible; + width: 10rem; + } + + path { + stroke-dashoffset: 0; + stroke-dasharray: 1550; + transform-origin: center; + } + + .hear-main { + z-index: 2; + } + .heart-background { + position: absolute; + left: 0; + right: 0; + z-index: 1; + stroke: none; + } + .heart-main path.anim { + animation: stroke-animation 2s ease-in-out forwards; + } + + .heart-main ~ .heart-background path.anim-click { + animation: fade-animation 0.35s ease-in-out forwards; + } + .nbLikes { + font-family: Source Sans Pro,Segoe UI,Trebuchet MS,Helvetica,Helvetica Neue,Arial,sans-serif; + color: #00324D; + text-align: center; + position: relative; + top: -10px; + height: 0; + } + } + + @keyframes stroke-animation { + 0% { + fill: transparent; + transform: scale(1); + } + 50% { + fill: pink; + transform: scale(1.1); + } + 70% { + transform: scale(1); + } + 100% { + stroke-dashoffset: 0; + fill: pink; + } + } + + @keyframes fade-animation { + 0% { + fill: transparent; + transform: scale(1); + } + 13% { + fill: lightpink; + transform: scale(1.2); + opacity: 1; + } + 66% { + opacity: 0.8; + } + 100% { + transform: scale(2); + opacity: 0; + } + } + } +} + .tags { display: flex; gap: 10px; @@ -293,6 +403,7 @@ code { padding: 0px 8px; border-radius: 3px; } + } .inline-tag { position: relative; diff --git a/src/js/love.js b/src/js/love.js new file mode 100644 index 0000000..5706c95 --- /dev/null +++ b/src/js/love.js @@ -0,0 +1,113 @@ +window.addEventListener('DOMContentLoaded', () => { + // This script insert a love button at the end of an article page + + const articles = document.querySelectorAll('article'); + + const config = { + likesEndPointBase: 'localhost:3000', + }; + + function getLikeEndPoint() { + let currentArticleName = window.location.pathname.split('/')[2]; + if (currentArticleName.indexOf('.') > 0) { + currentArticleName = currentArticleName.slice(0, currentArticleName.lastIndexOf('.')) + } + return `${window.location.protocol}//${config.likesEndPointBase}/like/${currentArticleName}`; + } + + // The front page have multiple articles + if (articles.length === 1) { + const article = articles[0]; + const likes = article.querySelector('.likes'); + const nbLikes = article.querySelector('.nbLikes'); + const footnotes = article.querySelector('.footnotes'); + + likes.style="display: 'block';"; + const updateNbLikes = () => { + fetch(getLikeEndPoint(), { + method: 'GET', + headers: { + 'i-love-what-you-do': '<3', + }, + }).then((res) => { + if (res.ok) { + res.text().then((text) => nbLikes.textContent = text); + } else { + nbLikes.textContent = ""; + } + }); + }; + + updateNbLikes(); + + if (footnotes) { + // We want: article.insertBefore(likes, footnotes); + footnotes.before(likes); + } + + const icon = likes.querySelector('.icon'); + const messagesLike = likes.querySelector('.likesNotes'); + + icon.addEventListener('mouseover', () => { + for (const c of icon.children) { + const path = c.querySelector('path'); + path?.classList.add('anim'); + } + }); + + icon.addEventListener('mouseout', () => { + for (const c of icon.children) { + const path = c.querySelector('path'); + path?.classList.remove('anim'); + } + }); + + let timeOut; + let messageText; + icon.addEventListener('click', () => { + const c = icon.children[1]; + { + const path = c.querySelector('path'); + console.log(path) + path.classList.add('anim-click'); + path.getAnimations().forEach(anim => { + anim.cancel(); + anim.play(); + }); + + fetch(getLikeEndPoint(), { + method: 'POST', + headers: { + 'i-love-what-you-do': '<3', + }, + }).then(response => { + const currentText = messagesLike.textContent; + const t = response.text().then(text => { + messagesLike.textContent = text; + return text; + }); + + if (response.ok) { + messagesLike.classList.remove('err'); + t.then((t) => messageText = t); + updateNbLikes(); + } else { + if (!messageText) { + messageText = currentText; + } + + messagesLike.classList.add('err'); + setTimeout(() => { + messagesLike.classList.remove('err'); + messagesLike.textContent = messageText; + }, 3000); + } + }).catch(() => { + messagesLike.classList.add('err'); + messagesLike.textContent = 'Désolé, le service est indisponible'; + messageText = ''; + }); + } + }); + } +}); diff --git a/src/templates/article.tmpl b/src/templates/article.tmpl index e5267ff..6b1b628 100644 --- a/src/templates/article.tmpl +++ b/src/templates/article.tmpl @@ -6,7 +6,9 @@ <div class="marge"></div> <article class="post" id="{{domTitle}}_article"> <div class="tags">{{# metaData.tags }}<a href="/tag/{{{ . }}}" class="tag">{{{ . }}}</a>{{/ metaData.tags }}</div> + <div class="pubdate">{{ metaData.pubDateISO }}</div> {{{ content }}} + {{> likesButton }} </article> <div class="sidenotes"></div> </div> diff --git a/src/templates/likes.tmpl b/src/templates/likes.tmpl new file mode 100644 index 0000000..a0018d9 --- /dev/null +++ b/src/templates/likes.tmpl @@ -0,0 +1,17 @@ +<section class="likes" style="display: none"> + <span class="likesBox"> + <div class="icon"> + <svg class="heart-main" viewBox="0 0 512 512" title="heart" z-index="1" height="100"> + <path d="M462.3 62.6C407.5 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z" class=""></path> + </svg> + <svg class="heart-background" viewBox="0 0 512 512" title="heart" z-index="1" height="100"> + <path d="M462.3 62.6C407.5 15.9 326 24.3 275.7 76.2L256 96.5l-19.7-20.3C186.1 24.3 104.5 15.9 49.7 62.6c-62.8 53.6-66.1 149.8-9.9 207.9l193.5 199.8c12.5 12.9 32.8 12.9 45.3 0l193.5-199.8c56.3-58.1 53-154.3-9.8-207.9z" class=""></path> + </svg> + <div class="nbLikes"><div></div></div> + </div> + <div> + <span class="likesTitle">Si vous avez aimez cet article cliquez sur le cœur !</span> + <p class="likesText">Vous pouvez même envoyez plusieurs cœurs ! <br><span class="likesNotes">Le délais d'attente entre deux cœurs double à chaque fois.</span></p> + </div></span> + + </section> |