diff --git a/front-end/components/bloom.mjs b/front-end/components/bloom.mjs index 0b4166c..bd999cc 100644 --- a/front-end/components/bloom.mjs +++ b/front-end/components/bloom.mjs @@ -2,16 +2,13 @@ * Create a bloom component * @param {string} template - The ID of the template to clone * @param {Object} bloom - The bloom data - * @returns {DocumentFragment} - The bloom fragment of UI, for items in the Timeline - * btw a bloom object is composed thus - * {"id": Number, - * "sender": username, - * "content": "string from textarea", - * "sent_timestamp": "datetime as ISO 8601 formatted string"} - + * @returns {DocumentFragment} */ +import { apiService } from "../index.mjs"; + const createBloom = (template, bloom) => { if (!bloom) return; + const bloomFrag = document.getElementById(template).content.cloneNode(true); const bloomParser = new DOMParser(); @@ -26,9 +23,10 @@ const createBloom = (template, bloom) => { bloomUsername.textContent = bloom.sender; bloomTime.textContent = _formatTimestamp(bloom.sent_timestamp); bloomTimeLink.setAttribute("href", `/bloom/${bloom.id}`); + bloomContent.replaceChildren( ...bloomParser.parseFromString(_formatHashtags(bloom.content), "text/html") - .body.childNodes + .body.childNodes, ); return bloomFrag; @@ -36,8 +34,9 @@ const createBloom = (template, bloom) => { function _formatHashtags(text) { if (!text) return text; + return text.replace( - /\B#[^#]+/g, + /#[A-Za-z0-9_]+/g, (match) => `${match}` ); } @@ -50,30 +49,17 @@ function _formatTimestamp(timestamp) { const now = new Date(); const diffSeconds = Math.floor((now - date) / 1000); - // Less than a minute - if (diffSeconds < 60) { - return `${diffSeconds}s`; - } + if (diffSeconds < 60) return `${diffSeconds}s`; - // Less than an hour const diffMinutes = Math.floor(diffSeconds / 60); - if (diffMinutes < 60) { - return `${diffMinutes}m`; - } + if (diffMinutes < 60) return `${diffMinutes}m`; - // Less than a day const diffHours = Math.floor(diffMinutes / 60); - if (diffHours < 24) { - return `${diffHours}h`; - } + if (diffHours < 24) return `${diffHours}h`; - // Less than a week const diffDays = Math.floor(diffHours / 24); - if (diffDays < 7) { - return `${diffDays}d`; - } + if (diffDays < 7) return `${diffDays}d`; - // Format as month and day for older dates return new Intl.DateTimeFormat("en-US", { month: "short", day: "numeric", @@ -84,4 +70,4 @@ function _formatTimestamp(timestamp) { } } -export {createBloom}; +export { createBloom }; \ No newline at end of file diff --git a/front-end/views/hashtag.mjs b/front-end/views/hashtag.mjs index 7b7e996..773731a 100644 --- a/front-end/views/hashtag.mjs +++ b/front-end/views/hashtag.mjs @@ -12,12 +12,18 @@ import {createLogout, handleLogout} from "../components/logout.mjs"; import {createBloom} from "../components/bloom.mjs"; import {createHeading} from "../components/heading.mjs"; -// Hashtag view: show all tweets containing this tag - +// Hashtag view: show all blooms containing this tag function hashtagView(hashtag) { destroy(); - apiService.getBloomsByHashtag(hashtag); + const blooms = []; + + // Only fetch if this hashtag isn't already loaded + if (state.currentHashtag !== `#${hashtag}`) { + apiService.getBloomsByHashtag(hashtag); + } else { + blooms.push(...(state.hashtagBlooms || [])); + } renderOne( state.isLoggedIn, @@ -28,6 +34,7 @@ function hashtagView(hashtag) { document .querySelector("[data-action='logout']") ?.addEventListener("click", handleLogout); + renderOne( state.isLoggedIn, getLoginContainer(), @@ -35,8 +42,8 @@ function hashtagView(hashtag) { createLogin ); document - .querySelector("[data-action='login']") - ?.addEventListener("click", handleLogin); + .querySelector("[data-form='login']") + ?.addEventListener("submit", handleLogin); renderOne( state.currentHashtag, @@ -44,12 +51,13 @@ function hashtagView(hashtag) { "heading-template", createHeading ); + renderEach( - state.hashtagBlooms || [], + blooms, getTimelineContainer(), "bloom-template", createBloom ); } -export {hashtagView}; +export {hashtagView }; \ No newline at end of file