Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 13 additions & 27 deletions front-end/components/bloom.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -26,18 +23,20 @@ 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;
};

function _formatHashtags(text) {
if (!text) return text;

return text.replace(
/\B#[^#]+/g,
/#[A-Za-z0-9_]+/g,
(match) => `<a href="/hashtag/${match.slice(1)}">${match}</a>`
);
}
Expand All @@ -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",
Expand All @@ -84,4 +70,4 @@ function _formatTimestamp(timestamp) {
}
}

export {createBloom};
export { createBloom };
22 changes: 15 additions & 7 deletions front-end/views/hashtag.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -28,28 +34,30 @@ function hashtagView(hashtag) {
document
.querySelector("[data-action='logout']")
?.addEventListener("click", handleLogout);

renderOne(
state.isLoggedIn,
getLoginContainer(),
"login-template",
createLogin
);
document
.querySelector("[data-action='login']")
?.addEventListener("click", handleLogin);
.querySelector("[data-form='login']")
?.addEventListener("submit", handleLogin);

renderOne(
state.currentHashtag,
getHeadingContainer(),
"heading-template",
createHeading
);

renderEach(
state.hashtagBlooms || [],
blooms,
getTimelineContainer(),
"bloom-template",
createBloom
);
}

export {hashtagView};
export {hashtagView };