diff --git a/backend/data/blooms.py b/backend/data/blooms.py index 7e280cf..62b4238 100644 --- a/backend/data/blooms.py +++ b/backend/data/blooms.py @@ -14,8 +14,13 @@ class Bloom: content: str sent_timestamp: datetime.datetime +MAX_BLOOM_LENGTH = 280 # this is to ensure the extra safety def add_bloom(*, sender: User, content: str) -> Bloom: + + if len(content) > MAX_BLOOM_LENGTH: + raise ValueError(f"blooms content is too long(max {MAX_BLOOM_LENGTH})") + hashtags = [word[1:] for word in content.split(" ") if word.startswith("#")] now = datetime.datetime.now(tz=datetime.UTC) diff --git a/backend/endpoints.py b/backend/endpoints.py index 0e177a0..c237739 100644 --- a/backend/endpoints.py +++ b/backend/endpoints.py @@ -149,13 +149,22 @@ def do_follow(): } ) - +MAX_BLOOM_LENGTH = 280 @jwt_required() def send_bloom(): type_check_error = verify_request_fields({"content": str}) if type_check_error is not None: return type_check_error + content = request.json ["content"] + + if len(content) > MAX_BLOOM_LENGTH: + return make_response( + ({"success": False, + "message": f"blloms can't be longe than {MAX_BLOOM_LENGTH} symbols", + }, 400,) + ) + user = get_current_user() blooms.add_bloom(sender=user, content=request.json["content"]) diff --git a/front-end/components/bloom.mjs b/front-end/components/bloom.mjs index 0b4166c..4d1a537 100644 --- a/front-end/components/bloom.mjs +++ b/front-end/components/bloom.mjs @@ -37,8 +37,8 @@ const createBloom = (template, bloom) => { function _formatHashtags(text) { if (!text) return text; return text.replace( - /\B#[^#]+/g, - (match) => `${match}` + /\B#([a-zA-Z0-9_]+)/g,// gets SwizBiz, without # or trailing love!!. + (match, tag) => `[${match}](/hashtag/${tag})` ); } diff --git a/front-end/views/hashtag.mjs b/front-end/views/hashtag.mjs index 7b7e996..83ebf5f 100644 --- a/front-end/views/hashtag.mjs +++ b/front-end/views/hashtag.mjs @@ -16,9 +16,7 @@ import {createHeading} from "../components/heading.mjs"; function hashtagView(hashtag) { destroy(); - - apiService.getBloomsByHashtag(hashtag); - +// it will show the basic structure or loading msg renderOne( state.isLoggedIn, getLogoutContainer(), @@ -28,6 +26,7 @@ function hashtagView(hashtag) { document .querySelector("[data-action='logout']") ?.addEventListener("click", handleLogout); + renderOne( state.isLoggedIn, getLoginContainer(), @@ -39,17 +38,25 @@ function hashtagView(hashtag) { ?.addEventListener("click", handleLogin); renderOne( - state.currentHashtag, + `#${hashtag}`, getHeadingContainer(), "heading-template", createHeading ); + apiService.getBloomsByHashtag(hashtag).then(() => { + renderOne( + state.currentHashtag, + getHeadingContainer(), + "heading-template", + createHeading + ); renderEach( state.hashtagBlooms || [], getTimelineContainer(), "bloom-template", createBloom ); +}); } export {hashtagView}; diff --git a/front-end/views/profile.mjs b/front-end/views/profile.mjs index dd2b92a..31139a9 100644 --- a/front-end/views/profile.mjs +++ b/front-end/views/profile.mjs @@ -39,8 +39,8 @@ function profileView(username) { createLogin ); document - .querySelector("[data-action='login']") - ?.addEventListener("click", handleLogin); + .querySelector("[data-form='login']") + ?.addEventListener("submit", handleLogin); const profileData = state.profiles.find((p) => p.username === username); if (profileData) {