From d9ed15bcacccaf8a6a0b76b1aaedd522932efcc7 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 17:48:11 +0100 Subject: [PATCH 01/19] Add original_bloom_id to the blooms table to help us with the rebloom later --- db/schema.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/db/schema.sql b/db/schema.sql index 61e7580c..11dc86dc 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -11,6 +11,7 @@ CREATE TABLE blooms ( sender_id INT NOT NULL REFERENCES users(id), content TEXT NOT NULL, send_timestamp TIMESTAMP NOT NULL + original_bloom_id BIGINT REFERENCES blooms(id) ); CREATE TABLE follows ( From 48db6f4a2f773f63c0fbc33505c407f22281e506 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 17:53:07 +0100 Subject: [PATCH 02/19] update the bloom class --- backend/data/blooms.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 7e280cf3..e373f99f 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -13,6 +13,7 @@ class Bloom: sender: User content: str sent_timestamp: datetime.datetime + original_bloom: Optional["Bloom"] = None def add_bloom(*, sender: User, content: str) -> Bloom: From 397bca1c390bf12eb35af1f9a8974ccbaf2642d2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 17:54:35 +0100 Subject: [PATCH 03/19] Create rebloom function --- backend/data/blooms.py | 49 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index e373f99f..d0a57faa 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -37,6 +37,55 @@ def add_bloom(*, sender: User, content: str) -> Bloom: dict(hashtag=hashtag, bloom_id=bloom_id), ) +def rebloom(*, sender: User, original_bloom_id: int) -> Bloom: + now = datetime.datetime.now(tz=datetime.UTC) + bloom_id = int(now.timestamp() * 1000000) + + with db_cursor() as cur: + cur.execute( + """ + INSERT INTO blooms ( + id, + sender_id, + content, + send_timestamp, + original_bloom_id + ) + SELECT + %(bloom_id)s, + %(sender_id)s, + content, + %(timestamp)s, + id + FROM blooms + WHERE id = %(original_bloom_id)s + RETURNING id, sender_id, content, send_timestamp, original_bloom_id + """, + { + "bloom_id": bloom_id, + "sender_id": sender.id, + "timestamp": now, + "original_bloom_id": original_bloom_id, + }, + ) + + row = cur.fetchone() + + if row is None: + return None + + bloom_id, sender_id, content, timestamp, original_id = row + + original_bloom = get_bloom(original_id) + + return Bloom( + id=bloom_id, + sender=sender, + content=content, + sent_timestamp=timestamp, + original_bloom=original_bloom, + ) + def get_blooms_for_user( username: str, *, before: Optional[int] = None, limit: Optional[int] = None From 320d5c6e53e891eb0abf43071a4fe035d704c983 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 17:57:45 +0100 Subject: [PATCH 04/19] update rebloom function --- backend/data/blooms.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index d0a57faa..90870986 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -37,7 +37,9 @@ def add_bloom(*, sender: User, content: str) -> Bloom: dict(hashtag=hashtag, bloom_id=bloom_id), ) -def rebloom(*, sender: User, original_bloom_id: int) -> Bloom: +def rebloom( + *, sender: User, original_bloom_id: int +) -> Optional[Bloom]: now = datetime.datetime.now(tz=datetime.UTC) bloom_id = int(now.timestamp() * 1000000) From df2ce911b88c9a8e77ee24f9284297cfe737b9e8 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 17:59:14 +0100 Subject: [PATCH 05/19] update get_bloom function --- backend/data/blooms.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 90870986..708d27bb 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -135,18 +135,39 @@ def get_blooms_for_user( def get_bloom(bloom_id: int) -> Optional[Bloom]: with db_cursor() as cur: cur.execute( - "SELECT blooms.id, users.username, content, send_timestamp FROM blooms INNER JOIN users ON users.id = blooms.sender_id WHERE blooms.id = %s", + """ + SELECT + blooms.id, + users.username, + content, + send_timestamp, + original_bloom_id + FROM blooms + INNER JOIN users ON users.id = blooms.sender_id + WHERE blooms.id = %s + """, (bloom_id,), ) + row = cur.fetchone() + if row is None: return None - bloom_id, sender_username, content, timestamp = row + + bloom_id, sender_username, content, timestamp, original_bloom_id = row + + original_bloom = ( + get_bloom(original_bloom_id) + if original_bloom_id is not None + else None + ) + return Bloom( id=bloom_id, sender=sender_username, content=content, sent_timestamp=timestamp, + original_bloom=original_bloom, ) From 532e6b3f991cf198800734488793168220690eaf Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:03:09 +0100 Subject: [PATCH 06/19] add the missing comma inside the blooms table to avoid the syntactical error --- db/schema.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/schema.sql b/db/schema.sql index 11dc86dc..1351eb28 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -10,7 +10,7 @@ CREATE TABLE blooms ( id BIGSERIAL NOT NULL PRIMARY KEY, sender_id INT NOT NULL REFERENCES users(id), content TEXT NOT NULL, - send_timestamp TIMESTAMP NOT NULL + send_timestamp TIMESTAMP NOT NULL, original_bloom_id BIGINT REFERENCES blooms(id) ); From 62f68ecad24ca785be076a96d3c0bb1e474c2871 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:10:56 +0100 Subject: [PATCH 07/19] update get_blooms_for_user function --- backend/data/blooms.py | 49 +++++++++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 708d27bb..e2c890bb 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -96,8 +96,9 @@ def get_blooms_for_user( kwargs = { "sender_username": username, } + if before is not None: - before_clause = "AND send_timestamp < %(before_limit)s" + before_clause = "AND blooms.send_timestamp < %(before_limit)s" kwargs["before_limit"] = before else: before_clause = "" @@ -105,31 +106,53 @@ def get_blooms_for_user( limit_clause = make_limit_clause(limit, kwargs) cur.execute( - f"""SELECT - blooms.id, users.username, content, send_timestamp - FROM - blooms INNER JOIN users ON users.id = blooms.sender_id - WHERE - username = %(sender_username)s - {before_clause} - ORDER BY send_timestamp DESC + f""" + SELECT + blooms.id, + users.username, + blooms.content, + blooms.send_timestamp, + blooms.original_bloom_id + FROM blooms + INNER JOIN users + ON users.id = blooms.sender_id + WHERE users.username = %(sender_username)s + {before_clause} + ORDER BY blooms.send_timestamp DESC {limit_clause} """, kwargs, ) + rows = cur.fetchall() - blooms = [] + blooms_list = [] + for row in rows: - bloom_id, sender_username, content, timestamp = row - blooms.append( + ( + bloom_id, + sender_username, + content, + timestamp, + original_bloom_id, + ) = row + + original_bloom = ( + get_bloom(original_bloom_id) + if original_bloom_id is not None + else None + ) + + blooms_list.append( Bloom( id=bloom_id, sender=sender_username, content=content, sent_timestamp=timestamp, + original_bloom=original_bloom, ) ) - return blooms + + return blooms_list def get_bloom(bloom_id: int) -> Optional[Bloom]: From 64efa8929304131cda69b7a7daa0386834d69b25 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:11:56 +0100 Subject: [PATCH 08/19] update get_bloom func --- backend/data/blooms.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index e2c890bb..af42f762 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -162,9 +162,9 @@ def get_bloom(bloom_id: int) -> Optional[Bloom]: SELECT blooms.id, users.username, - content, - send_timestamp, - original_bloom_id + blooms.content, + blooms.send_timestamp, + blooms.original_bloom_id FROM blooms INNER JOIN users ON users.id = blooms.sender_id WHERE blooms.id = %s @@ -177,7 +177,13 @@ def get_bloom(bloom_id: int) -> Optional[Bloom]: if row is None: return None - bloom_id, sender_username, content, timestamp, original_bloom_id = row + ( + bloom_id, + sender_username, + content, + timestamp, + original_bloom_id, + ) = row original_bloom = ( get_bloom(original_bloom_id) @@ -192,7 +198,7 @@ def get_bloom(bloom_id: int) -> Optional[Bloom]: sent_timestamp=timestamp, original_bloom=original_bloom, ) - + def get_blooms_with_hashtag( hashtag_without_leading_hash: str, *, limit: int = None From 05ad7279c3fac2695686aa2331aaa306bf83da99 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:13:57 +0100 Subject: [PATCH 09/19] add an endpoint for reblooming --- backend/endpoints.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/backend/endpoints.py b/backend/endpoints.py index 0e177a07..8c6241f0 100644 --- a/backend/endpoints.py +++ b/backend/endpoints.py @@ -245,3 +245,25 @@ def verify_request_fields(names_to_types: Dict[str, type]) -> Union[Response, No ) ) return None + + +@jwt_required() +def rebloom(id_str): + try: + original_bloom_id = int(id_str) + except ValueError: + return make_response(("Invalid bloom id", 400)) + + current_user = get_current_user() + + original_bloom = blooms.get_bloom(original_bloom_id) + + if original_bloom is None: + return make_response(("Bloom not found", 404)) + + rebloomed = blooms.rebloom( + sender=current_user, + original_bloom_id=original_bloom_id, + ) + + return jsonify(rebloomed) From db8601cb2df5e37e08d61b67add7929d60b08f60 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:22:27 +0100 Subject: [PATCH 10/19] import rebloom handler function endpoint and add a router for it in the main file --- backend/main.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/main.py b/backend/main.py index 7ba155fa..b45e21da 100644 --- a/backend/main.py +++ b/backend/main.py @@ -9,6 +9,7 @@ home_timeline, login, other_profile, + rebloom, register, self_profile, send_bloom, @@ -58,6 +59,7 @@ def main(): app.add_url_rule("/bloom", methods=["POST"], view_func=send_bloom) app.add_url_rule("/bloom/", methods=["GET"], view_func=get_bloom) + app.add_url_rule("/rebloom/", methods=["POST"], view_func=rebloom) app.add_url_rule("/blooms/", view_func=user_blooms) app.add_url_rule("/hashtag/", view_func=hashtag) From 02f3358896dbe3d728cbef5249c3b2e79adf5a3b Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:28:55 +0100 Subject: [PATCH 11/19] setup the api.mjs for the rebloom endpoint --- front-end/lib/api.mjs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/front-end/lib/api.mjs b/front-end/lib/api.mjs index f4b5339b..34a4a5b9 100644 --- a/front-end/lib/api.mjs +++ b/front-end/lib/api.mjs @@ -212,6 +212,24 @@ async function postBloom(content) { } } +async function rebloom(bloomId) { + try { + const data = await _apiRequest(`/rebloom/${bloomId}`, { + method: "POST", + }); + + if (data.success !== false) { + await getBlooms(); + await getProfile(state.currentUser); + } + + return data; + } catch (error) { + // Error already handled by _apiRequest + return { success: false }; + } +} + // ======= USER methods async function getProfile(username) { const endpoint = username ? `/profile/${username}` : "/profile"; @@ -291,6 +309,7 @@ const apiService = { getBloom, getBlooms, postBloom, + rebloom, getBloomsByHashtag, // User methods From e0d739bae629e48722d396deadee0ddaa86169b2 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:43:10 +0100 Subject: [PATCH 12/19] Update the html structure (template tag with "bloom-form-template" id to be exact) --- front-end/index.html | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/front-end/index.html b/front-end/index.html index 89d6b130..907fdce4 100644 --- a/front-end/index.html +++ b/front-end/index.html @@ -236,9 +236,20 @@

Share a Bloom

From fadd3e1125db114dafceba6a1421b3601a9df1b6 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:46:15 +0100 Subject: [PATCH 13/19] update create bloom --- front-end/components/bloom.mjs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/front-end/components/bloom.mjs b/front-end/components/bloom.mjs index 0b4166c3..162155d0 100644 --- a/front-end/components/bloom.mjs +++ b/front-end/components/bloom.mjs @@ -10,8 +10,11 @@ * "sent_timestamp": "datetime as ISO 8601 formatted string"} */ +import { apiService } from "../index.mjs"; + const createBloom = (template, bloom) => { if (!bloom) return; + const bloomFrag = document.getElementById(template).content.cloneNode(true); const bloomParser = new DOMParser(); @@ -20,17 +23,34 @@ const createBloom = (template, bloom) => { const bloomTime = bloomFrag.querySelector("[data-time]"); const bloomTimeLink = bloomFrag.querySelector("a:has(> [data-time])"); const bloomContent = bloomFrag.querySelector("[data-content]"); + const rebloomButton = bloomFrag.querySelector("[data-action='rebloom']"); bloomArticle.setAttribute("data-bloom-id", bloom.id); bloomUsername.setAttribute("href", `/profile/${bloom.sender}`); 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 ); + // Handle rebloom + rebloomButton.addEventListener("click", async () => { + try { + rebloomButton.disabled = true; + rebloomButton.textContent = "Reblooming..."; + + await apiService.rebloom(bloom.id); + } catch (error) { + console.error("Failed to rebloom:", error); + } finally { + rebloomButton.disabled = false; + rebloomButton.textContent = "Rebloom"; + } + }); + return bloomFrag; }; From 7280198e89186c88c4ae29df08dc5568b1e7e9e7 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 18:51:54 +0100 Subject: [PATCH 14/19] update bloom.mjs --- front-end/components/bloom.mjs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/front-end/components/bloom.mjs b/front-end/components/bloom.mjs index 162155d0..594e17b1 100644 --- a/front-end/components/bloom.mjs +++ b/front-end/components/bloom.mjs @@ -23,6 +23,7 @@ const createBloom = (template, bloom) => { const bloomTime = bloomFrag.querySelector("[data-time]"); const bloomTimeLink = bloomFrag.querySelector("a:has(> [data-time])"); const bloomContent = bloomFrag.querySelector("[data-content]"); + const rebloomInfo = bloomFrag.querySelector("[data-rebloom-info]"); const rebloomButton = bloomFrag.querySelector("[data-action='rebloom']"); bloomArticle.setAttribute("data-bloom-id", bloom.id); @@ -36,6 +37,11 @@ const createBloom = (template, bloom) => { .body.childNodes ); + if (bloom.original_bloom) { + rebloomInfo.hidden = false; + rebloomInfo.textContent = `Rebloomed from ${bloom.original_bloom.sender}`; + } + // Handle rebloom rebloomButton.addEventListener("click", async () => { try { From d0f4bb336101c9382911991cbf30b1f79347ac1d Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 19:02:48 +0100 Subject: [PATCH 15/19] update html to include span tag with the current rebloom count --- front-end/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/front-end/index.html b/front-end/index.html index 907fdce4..39b053df 100644 --- a/front-end/index.html +++ b/front-end/index.html @@ -247,7 +247,7 @@

Share a Bloom

From 2207ba9b11f241a89feb54fec359498f00d7bdd9 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 19:06:42 +0100 Subject: [PATCH 16/19] Update the rebloom btn event listner to incoude count for reblooms --- front-end/components/bloom.mjs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/front-end/components/bloom.mjs b/front-end/components/bloom.mjs index 594e17b1..16f7306e 100644 --- a/front-end/components/bloom.mjs +++ b/front-end/components/bloom.mjs @@ -25,6 +25,7 @@ const createBloom = (template, bloom) => { const bloomContent = bloomFrag.querySelector("[data-content]"); const rebloomInfo = bloomFrag.querySelector("[data-rebloom-info]"); const rebloomButton = bloomFrag.querySelector("[data-action='rebloom']"); + const rebloomCount = bloomFrag.querySelector("[data-rebloom-count]"); bloomArticle.setAttribute("data-bloom-id", bloom.id); bloomUsername.setAttribute("href", `/profile/${bloom.sender}`); @@ -49,11 +50,14 @@ const createBloom = (template, bloom) => { rebloomButton.textContent = "Reblooming..."; await apiService.rebloom(bloom.id); + + const currentCount = Number(rebloomCount.textContent); + rebloomCount.textContent = currentCount + 1; } catch (error) { console.error("Failed to rebloom:", error); } finally { rebloomButton.disabled = false; - rebloomButton.textContent = "Rebloom"; + rebloomButton.innerHTML = `Rebloom ${rebloomCount.textContent}`; } }); From 79bebde8fad750b05ce5fdd5a0c98cac23a31808 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 19:08:17 +0100 Subject: [PATCH 17/19] add rebloom_count field to my Bloom class --- backend/data/blooms.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index af42f762..99ecc02b 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -14,6 +14,7 @@ class Bloom: content: str sent_timestamp: datetime.datetime original_bloom: Optional["Bloom"] = None + rebloom_count: int = 0 def add_bloom(*, sender: User, content: str) -> Bloom: From 6282c0da20051062c2f7c33d6676d493f03fac21 Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 22:04:57 +0100 Subject: [PATCH 18/19] fix rebloom count persistence --- backend/data/blooms.py | 45 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 99ecc02b..4f47aff6 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -78,6 +78,26 @@ def rebloom( return None bloom_id, sender_id, content, timestamp, original_id = row + + cur.execute( + """ + INSERT INTO reblooms ( + rebloomer_id, + bloom_id, + rebloom_timestamp + ) + VALUES ( + %(rebloomer_id)s, + %(bloom_id)s, + %(timestamp)s + ) + """, + { + "rebloomer_id": sender.id, + "bloom_id": original_id, + "timestamp": now, + }, + ) original_bloom = get_bloom(original_id) @@ -113,7 +133,15 @@ def get_blooms_for_user( users.username, blooms.content, blooms.send_timestamp, - blooms.original_bloom_id + blooms.original_bloom_id, + ( + SELECT COUNT(*) + FROM reblooms + WHERE reblooms.bloom_id = COALESCE( + blooms.original_bloom_id, + blooms.id + ) + ) AS rebloom_count FROM blooms INNER JOIN users ON users.id = blooms.sender_id @@ -135,6 +163,7 @@ def get_blooms_for_user( content, timestamp, original_bloom_id, + rebloom_count, ) = row original_bloom = ( @@ -150,6 +179,7 @@ def get_blooms_for_user( content=content, sent_timestamp=timestamp, original_bloom=original_bloom, + rebloom_count=rebloom_count, ) ) @@ -165,7 +195,15 @@ def get_bloom(bloom_id: int) -> Optional[Bloom]: users.username, blooms.content, blooms.send_timestamp, - blooms.original_bloom_id + blooms.original_bloom_id, + ( + SELECT COUNT(*) + FROM reblooms + WHERE reblooms.bloom_id = COALESCE( + blooms.original_bloom_id, + blooms.id + ) + ) AS rebloom_count FROM blooms INNER JOIN users ON users.id = blooms.sender_id WHERE blooms.id = %s @@ -184,6 +222,7 @@ def get_bloom(bloom_id: int) -> Optional[Bloom]: content, timestamp, original_bloom_id, + rebloom_count, ) = row original_bloom = ( @@ -198,8 +237,8 @@ def get_bloom(bloom_id: int) -> Optional[Bloom]: content=content, sent_timestamp=timestamp, original_bloom=original_bloom, + rebloom_count=rebloom_count, ) - def get_blooms_with_hashtag( hashtag_without_leading_hash: str, *, limit: int = None From 8e9fdf81adfc8713183488d0b8c748a959da9cfe Mon Sep 17 00:00:00 2001 From: HassanOHOsman Date: Fri, 21 Aug 2026 22:37:07 +0100 Subject: [PATCH 19/19] 1. update add_bloom function 2. add a test content for th erebloom counter --- backend/data/blooms.py | 33 +++++++++++++++++++++------------ front-end/components/bloom.mjs | 7 ++++--- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 4f47aff6..c3e5cf7c 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -45,6 +45,22 @@ def rebloom( bloom_id = int(now.timestamp() * 1000000) with db_cursor() as cur: + cur.execute( + """ + SELECT COALESCE(original_bloom_id, id) + FROM blooms + WHERE id = %(original_bloom_id)s + """, + {"original_bloom_id": original_bloom_id}, + ) + + row = cur.fetchone() + + if row is None: + return None + + root_bloom_id = row[0] + cur.execute( """ INSERT INTO blooms ( @@ -59,7 +75,7 @@ def rebloom( %(sender_id)s, content, %(timestamp)s, - id + %(root_bloom_id)s FROM blooms WHERE id = %(original_bloom_id)s RETURNING id, sender_id, content, send_timestamp, original_bloom_id @@ -69,6 +85,7 @@ def rebloom( "sender_id": sender.id, "timestamp": now, "original_bloom_id": original_bloom_id, + "root_bloom_id": root_bloom_id, }, ) @@ -77,8 +94,6 @@ def rebloom( if row is None: return None - bloom_id, sender_id, content, timestamp, original_id = row - cur.execute( """ INSERT INTO reblooms ( @@ -94,20 +109,14 @@ def rebloom( """, { "rebloomer_id": sender.id, - "bloom_id": original_id, + "bloom_id": root_bloom_id, "timestamp": now, }, ) - original_bloom = get_bloom(original_id) + return get_bloom(bloom_id) - return Bloom( - id=bloom_id, - sender=sender, - content=content, - sent_timestamp=timestamp, - original_bloom=original_bloom, - ) + def get_blooms_for_user( diff --git a/front-end/components/bloom.mjs b/front-end/components/bloom.mjs index 16f7306e..78309680 100644 --- a/front-end/components/bloom.mjs +++ b/front-end/components/bloom.mjs @@ -26,6 +26,8 @@ const createBloom = (template, bloom) => { const rebloomInfo = bloomFrag.querySelector("[data-rebloom-info]"); const rebloomButton = bloomFrag.querySelector("[data-action='rebloom']"); const rebloomCount = bloomFrag.querySelector("[data-rebloom-count]"); + + rebloomCount.textContent = bloom.rebloom_count ?? 0; bloomArticle.setAttribute("data-bloom-id", bloom.id); bloomUsername.setAttribute("href", `/profile/${bloom.sender}`); @@ -49,10 +51,9 @@ const createBloom = (template, bloom) => { rebloomButton.disabled = true; rebloomButton.textContent = "Reblooming..."; - await apiService.rebloom(bloom.id); + const rebloomedBloom = await apiService.rebloom(bloom.id); - const currentCount = Number(rebloomCount.textContent); - rebloomCount.textContent = currentCount + 1; + rebloomCount.textContent = rebloomedBloom.rebloom_count; } catch (error) { console.error("Failed to rebloom:", error); } finally {