From f08a4d38a5ee2188aafc8c6504556650ed470a3a Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Fri, 25 Apr 2025 22:31:51 +0530 Subject: [PATCH 01/10] Pagination for home page and category page --- app.py | 6 + modules.py | 3 + routes/category.py | 25 ++-- routes/index.py | 35 ++---- routes/returnHomeFeedData.py | 53 +++++++++ routes/returnPostAnalyticsData.py | 2 +- static/tailwindUI/js/homeFeed.js | 112 ++++++++++++++++++ .../pureHtmlMacro/postCardMacro.html | 39 ++++++ templates/tailwindUI/category.html.jinja | 30 +++-- .../tailwindUI/components/sortMenu.html.jinja | 5 +- templates/tailwindUI/index.html.jinja | 28 +++-- templates/tailwindUI/user.html.jinja | 4 +- utils/getHomeFeedData.py | 43 +++++++ 13 files changed, 322 insertions(+), 63 deletions(-) create mode 100644 routes/returnHomeFeedData.py create mode 100644 static/tailwindUI/js/homeFeed.js create mode 100644 static/tailwindUI/pureHtmlMacro/postCardMacro.html create mode 100644 utils/getHomeFeedData.py diff --git a/app.py b/app.py index 0d5d02db..e6e97c5e 100755 --- a/app.py +++ b/app.py @@ -168,6 +168,9 @@ from routes.verifyUser import ( verifyUserBlueprint, ) # Importing the blueprint for user verification route +from routes.returnHomeFeedData import ( + returnHomeFeedDataBlueprint, +) # Importing the blueprint for home page feed data endpoint route from utils.afterRequest import ( afterRequestLogger, ) # This function handles loggins of every request @@ -463,6 +466,9 @@ def afterRequest(response): app.register_blueprint( returnPostAnalyticsDataBlueprint ) # Registering the blueprint for the postAnalyticsData endpoint route +app.register_blueprint( + returnHomeFeedDataBlueprint +) # Registering the blueprint for the homeFeddData endpoint route # Check if the name of the module is the main module match __name__: diff --git a/modules.py b/modules.py index 3df5d6cb..4fc9c8af 100644 --- a/modules.py +++ b/modules.py @@ -137,3 +137,6 @@ getAnalyticsPageOSGraphData, getAnalyticsPageTrafficGraphData, ) + +# Importing the getHomeFeedData for home pag +from utils.getHomeFeedData import getHomeFeedData diff --git a/routes/category.py b/routes/category.py index be3ffb4e..d9789d0a 100755 --- a/routes/category.py +++ b/routes/category.py @@ -34,6 +34,10 @@ def category(category, by="timeStamp", sort="desc"): :param sort: The sorting order of the posts :return: A rendered template with the posts and the category as context """ + + # Original copy of by + _by = by + # List of available categories categories = [ "games", @@ -76,23 +80,6 @@ def category(category, by="timeStamp", sort="desc"): case False: abort(404) - Log.database( - f"Connecting to '{DB_POSTS_ROOT}' database" - ) # Log the database connection is started - - # Establishing a connection to the SQLite database - connection = sqlite3.connect(DB_POSTS_ROOT) - connection.set_trace_callback( - Log.database - ) # Set the trace callback for the connection - cursor = connection.cursor() - - # Executing SQL query to retrieve posts of the requested category and sorting them accordingly - cursor.execute( - f"""select * from posts where lower(category) = ? order by {by} {sort}""", - [(category.lower())], - ) - posts = cursor.fetchall() # Modify the sorting name for better readability match by: @@ -120,8 +107,10 @@ def category(category, by="timeStamp", sort="desc"): # Rendering the HTML template with posts and category context return render_template( "category.html.jinja", - posts=posts, category=translations["categories"][category.lower()], sortName=sortName, source=f"/category/{category}", + sortBy=_by, + orderBy=sort, + categoryBy = category ) diff --git a/routes/index.py b/routes/index.py index eae77211..5ac23e83 100755 --- a/routes/index.py +++ b/routes/index.py @@ -48,6 +48,9 @@ def index(by="hot", sort="desc"): The rendered template of the home page with sorted posts according to the provided sorting options. """ + # Original copy of by + _by = by + # Define valid options for sorting and filtering byOptions = ["timeStamp", "title", "views", "category", "lastEditTimeStamp", "hot"] sortOptions = ["asc", "desc"] @@ -60,31 +63,6 @@ def index(by="hot", sort="desc"): ) return redirect("/") - Log.database( - f"Connecting to '{DB_POSTS_ROOT}' database" - ) # Log the database connection is started - # Connect to the posts database - connection = sqlite3.connect(DB_POSTS_ROOT) - connection.set_trace_callback( - Log.database - ) # Set the trace callback for the connection - # Create a cursor object for executing queries - cursor = connection.cursor() - # Select all the columns from the posts table and order them by the specified field and sorting order - match by: - case "hot": # If the sorting field is "hot" - cursor.execute( - f"SELECT *, (views * 1 / log(1 + (strftime('%s', 'now') - timeStamp) / 3600 + 2)) AS hotScore FROM posts ORDER BY hotScore {sort}" - ) # Execute the query to sort by hotness - pass - case _: # For all other sorting fields - cursor.execute( - f"select * from posts order by {by} {sort}" - ) # Execute the query to sort by the specified field - - # Fetch all the results as a list of tuples - posts = cursor.fetchall() - # Modify the sorting name for better readability match by: case "timeStamp": @@ -110,5 +88,10 @@ def index(by="hot", sort="desc"): # Return the rendered template of the home page and pass the posts list and sorting name as keyword arguments return render_template( - "index.html.jinja", posts=posts, sortName=sortName, source="" + "index.html.jinja", + sortName=sortName, + source="", + sortBy=_by, + orderBy=sort, + categoryBy="all", ) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py new file mode 100644 index 00000000..eeb3188c --- /dev/null +++ b/routes/returnHomeFeedData.py @@ -0,0 +1,53 @@ +from modules import ( + getHomeFeedData, + Blueprint, + make_response, + getSlugFromPostTitle, + url_for, + getProfilePicture, + request, +) + +returnHomeFeedDataBlueprint = Blueprint("returnHomeFeedData", __name__) + + +@returnHomeFeedDataBlueprint.route("/api/v1/homeFeedData") +def homeFeedData(): + """ + Takes param parameters + """ + print(request.args) + category = request.args.get("category", type=str, default="all") + by = request.args.get("by", type=str, default="hot") + sort = request.args.get("sort", type=str, default="desc") + limit = request.args.get("limit", type=int, default="4") + offset = request.args.get("offset", type=int, default="0") + + print(category, by, sort, limit, offset, "rohit") + + try: + rawHomeFeedData = getHomeFeedData( + category=category, by=by, sort=sort, limit=limit, offset=offset + ) + listOfHomeFeedData = [] + for data in rawHomeFeedData: + homeFeedObj = {} + homeFeedObj["id"] = data[0] + homeFeedObj["title"] = data[1] + homeFeedObj["content"] = data[2] + homeFeedObj["author"] = data[3] + homeFeedObj["timeStamp"] = data[4] + homeFeedObj["category"] = data[5] + homeFeedObj["urlID"] = data[6] + homeFeedObj["bannerImgSrc"] = url_for( + "returnPostBanner.returnPostBanner", postID=data[0] + ) + homeFeedObj["authorProfile"] = getProfilePicture(data[3]) + homeFeedObj["postLink"] = url_for( + "post.post", slug=getSlugFromPostTitle(data[1]), urlID=data[6] + ) + listOfHomeFeedData.append(homeFeedObj) + + return make_response({"payload": listOfHomeFeedData}, 200) + except Exception as e: + return make_response({"error": f"{e}"}, 500) diff --git a/routes/returnPostAnalyticsData.py b/routes/returnPostAnalyticsData.py index 65a56402..bda47385 100644 --- a/routes/returnPostAnalyticsData.py +++ b/routes/returnPostAnalyticsData.py @@ -212,4 +212,4 @@ def storeTimeSpendsDuraton() -> dict: case False: # Return error if analytics is disabled - return ({"message": "analytics is disabled by admin"}, 410) + return make_response({"message": "analytics is disabled by admin"}, 410) diff --git a/static/tailwindUI/js/homeFeed.js b/static/tailwindUI/js/homeFeed.js new file mode 100644 index 00000000..de7e5fe4 --- /dev/null +++ b/static/tailwindUI/js/homeFeed.js @@ -0,0 +1,112 @@ +// Initialize variable for postCardMacro and postContainer +let postCardMacro +let postContainer + +// Limit +let limit = 4 +// Offset +let offset = 0 + +// Id +let homeSpinner = document.getElementById("homeSpinner") +let loadMoreSpinner = document.getElementById("lodeMoreSpinner") +let currentCategory = document.getElementById("currentCategoryText") +let loadMoreButtonDiv = document.getElementById("loadMoreButton") +const sortBy = document.getElementById("currentSortText") +const orderby = document.getElementById("currentOrderText") + +const categoryList = { + 'Games': '', + 'History': '', + 'Science': '', + 'Code': '', + 'Technology': '', + 'Education': '', + 'Sports': '', + 'Foods': '', + 'Health': '', + 'Apps': '', + 'Movies': '', + 'Series': '', + 'Travel': '', + 'Books': '', + 'Music': '', + 'Nature': '', + 'Art': '', + 'Finance': '', + 'Business': '', + 'Web': '', + 'Other': '', + 'Default': '' +}; + + +async function intializePostCard() { + fetch(postCardMacroPath) + .then(res => res.text()) + .then(postCardHtml => { + // Insert the fetched template into a hidden container + const tempContainer = document.createElement('div'); + tempContainer.innerHTML = postCardHtml; + + // Register macro in dome + document.body.appendChild(tempContainer); // or keep it detached + + /// Assign html id of content to variable + postCardMacro = document.getElementById("postCardMacro"); + postContainer = document.getElementById("postCardContainer"); + }); +} + +intializePostCard() + +async function fetchHomeFeedData() { + try { + let connection = await fetch(`/api/v1/homeFeedData?category=${currentCategory.value}&by=${sortBy.value}&sort=${orderby.value}&limit=${limit}&offset=${offset}`) + let res = await connection.json() + + if (connection.ok) { + posts = res.payload; + + // Check if posts length is not less than limit + + posts.forEach(post => { + const clone = postCardMacro.content.cloneNode(true) + clone.querySelector(".postTitle").innerText = post.title + clone.querySelector(".postTitle").href = post.postLink + clone.querySelector(".postContent").innerHTML = post.content + clone.querySelector(".postBanner").src = post.bannerImgSrc + clone.querySelector(".postAuthorPicture").src = post.authorProfile + clone.querySelector(".postAuthor").innerText = post.author + clone.querySelector(".postAuthor").href = `/user/${post.author}` + clone.querySelector(".postCategory").innerHTML = categoryList[post.category] || categoryList["Default"] + clone.querySelector(".postTimeStamp").innerText = post.timeStamp + postContainer.appendChild(clone) + }); + offset += 4 + if (posts.length < limit) { + // Hide button + loadMoreButtonDiv.classList.add("hidden") + } + } else { + console.error(connection.status) + } + } catch (error) { + console.error(error) + } +} + +async function loadMoreButton() { + // Show spinner + loadMoreSpinner.classList.remove("hidden") + await fetchHomeFeedData() + // Hide spinner + loadMoreSpinner.classList.add("hidden") +} + +// Call the function to load data +window.onload = async function () { + homeSpinner.classList.remove("hidden") + await fetchHomeFeedData() + homeSpinner.classList.add("hidden") +} \ No newline at end of file diff --git a/static/tailwindUI/pureHtmlMacro/postCardMacro.html b/static/tailwindUI/pureHtmlMacro/postCardMacro.html new file mode 100644 index 00000000..d4457ace --- /dev/null +++ b/static/tailwindUI/pureHtmlMacro/postCardMacro.html @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/templates/tailwindUI/category.html.jinja b/templates/tailwindUI/category.html.jinja index bf35a781..73b6df25 100755 --- a/templates/tailwindUI/category.html.jinja +++ b/templates/tailwindUI/category.html.jinja @@ -17,18 +17,25 @@ {% from "components/sortMenu.html.jinja" import sortMenu %} -{{ sortMenu(sortName,source,translations) }} +{{ sortMenu(sortName,source,translations, sortBy, orderBy) }} -
- {% for post in posts %} - - {% from "components/postCardMacro.html.jinja" import postCard with context %} - {{ postCard(post=post, authorProfilePicture=getProfilePicture(post[5])) }} - {% endfor %} +
+ +
+ + +
+ + + +
+
@@ -41,4 +48,11 @@ {{ translations.about.credits | safe }}
+ + + + {% endblock body %} \ No newline at end of file diff --git a/templates/tailwindUI/components/sortMenu.html.jinja b/templates/tailwindUI/components/sortMenu.html.jinja index ce05aa03..2b0c4866 100644 --- a/templates/tailwindUI/components/sortMenu.html.jinja +++ b/templates/tailwindUI/components/sortMenu.html.jinja @@ -1,6 +1,9 @@ -{% macro sortMenu(sortName,source,translations) %} +{% macro sortMenu(sortName,source,translations, sortBy, orderBy) %}
+ + +
diff --git a/templates/tailwindUI/index.html.jinja b/templates/tailwindUI/index.html.jinja index d98eb9f1..638e6f00 100755 --- a/templates/tailwindUI/index.html.jinja +++ b/templates/tailwindUI/index.html.jinja @@ -23,16 +23,22 @@ {% from "components/sortMenu.html.jinja" import sortMenu %} -{{ sortMenu(sortName,source,translations) }} +{{ sortMenu(sortName,source,translations, sortBy, orderBy) }} -
- {% for post in posts %} - - {% from "components/postCardMacro.html.jinja" import postCard with context %} - {{ postCard(post=post, authorProfilePicture=getProfilePicture(post[5])) }} - {% endfor %} + +
+ + +
+ + + +
@@ -47,4 +53,12 @@ {{ translations.about.credits | safe }}
+ + + + + {% endblock body %} \ No newline at end of file diff --git a/templates/tailwindUI/user.html.jinja b/templates/tailwindUI/user.html.jinja index 44661b12..0fbdcbe2 100755 --- a/templates/tailwindUI/user.html.jinja +++ b/templates/tailwindUI/user.html.jinja @@ -96,8 +96,8 @@ class="flex item-center justify-center flex-wrap gap-x-2 gap-y-6 mx-auto w-11/12 md:w-10/12 lg:w-9/12 2xl:w-8/12 my-6"> {% for post in posts %} {% from "components/postCardMacro.html.jinja" - import postCard%} {{ - postCard(post=post,authorProfilePicture=getProfilePicture(post[5])) }} {% + import postCard with context %} {{ + postCard(post=post,authorProfilePicture=getProfilePicture(post[5]))}} {% endfor %}
{% endif %} {% if showComments %} diff --git a/utils/getHomeFeedData.py b/utils/getHomeFeedData.py new file mode 100644 index 00000000..ddb11475 --- /dev/null +++ b/utils/getHomeFeedData.py @@ -0,0 +1,43 @@ +from modules import ( + sqlite3, + Log, + DB_POSTS_ROOT, +) + + +def getHomeFeedData( + by="hot", sort="desc", category: str = "all", offset: int = 0, limit: int = 3 +) -> list: + Log.database( + f"Connecting to '{DB_POSTS_ROOT}' database" + ) # Log the database connection is started + # Connect to the posts database + connection = sqlite3.connect(DB_POSTS_ROOT) + connection.set_trace_callback( + Log.database + ) # Set the trace callback for the connection + # Create a cursor object for executing queries + cursor = connection.cursor() + # Select all the columns from the posts table and order them by the specified field and sorting order + match category: + case "all": + match by: + case "hot": # If the sorting field is "hot" + cursor.execute( + f"SELECT id, title, content, author, timeStamp, category, urlID, (views * 1 / log(1 + (strftime('%s', 'now') - timeStamp) / 3600 + 2)) AS hotScore FROM posts ORDER BY hotScore {sort} LIMIT {limit} OFFSET {offset}" + ) # Execute the query to sort by hotness + pass + case _: # For all other sorting fields + cursor.execute( + f"select id, title, content, author, timeStamp, category, urlID from posts order by {by} {sort} LIMIT {limit} OFFSET {offset}" + ) # Execute the query to sort by the specified field + case _: + # Executing SQL query to retrieve posts of the requested category and sorting them accordingly + cursor.execute( + f"""select id, title, content, author, timeStamp, category, urlID from posts where lower(category) = ? order by {by} {sort} LIMIT {limit} OFFSET {offset}""", + [(category.lower())], + ) + posts = cursor.fetchall() + # Close database connection + connection.close() + return posts From d1f329105fbbf31294a04578468b8207696b1b8e Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Sat, 26 Apr 2025 22:35:29 +0530 Subject: [PATCH 02/10] Added Comments and removed unnecessary code --- modules.py | 2 +- routes/category.py | 5 +- routes/returnHomeFeedData.py | 38 +++++++--- static/tailwindUI/js/homeFeed.js | 92 +++++++++++++----------- templates/tailwindUI/category.html.jinja | 3 +- templates/tailwindUI/index.html.jinja | 3 +- 6 files changed, 85 insertions(+), 58 deletions(-) diff --git a/modules.py b/modules.py index 4fc9c8af..b2c0dbdf 100644 --- a/modules.py +++ b/modules.py @@ -138,5 +138,5 @@ getAnalyticsPageTrafficGraphData, ) -# Importing the getHomeFeedData for home pag +# Importing the getHomeFeedData for home page feed from utils.getHomeFeedData import getHomeFeedData diff --git a/routes/category.py b/routes/category.py index d9789d0a..5e30cf22 100755 --- a/routes/category.py +++ b/routes/category.py @@ -80,7 +80,6 @@ def category(category, by="timeStamp", sort="desc"): case False: abort(404) - # Modify the sorting name for better readability match by: case "timeStamp": @@ -110,7 +109,7 @@ def category(category, by="timeStamp", sort="desc"): category=translations["categories"][category.lower()], sortName=sortName, source=f"/category/{category}", - sortBy=_by, + sortBy=_by, orderBy=sort, - categoryBy = category + categoryBy=category, ) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py index eeb3188c..3dfb8ef1 100644 --- a/routes/returnHomeFeedData.py +++ b/routes/returnHomeFeedData.py @@ -1,3 +1,4 @@ +# Import required modules and functions from modules import ( getHomeFeedData, Blueprint, @@ -14,40 +15,55 @@ @returnHomeFeedDataBlueprint.route("/api/v1/homeFeedData") def homeFeedData(): """ - Takes param parameters + API endpoint to fetch home feed data. + Accepts query parameters: category, by, sort, limit, offset """ - print(request.args) + + # Get query parameters with default values if not provided category = request.args.get("category", type=str, default="all") by = request.args.get("by", type=str, default="hot") sort = request.args.get("sort", type=str, default="desc") limit = request.args.get("limit", type=int, default="4") offset = request.args.get("offset", type=int, default="0") - print(category, by, sort, limit, offset, "rohit") - try: + # Fetch raw home feed data based on parameters rawHomeFeedData = getHomeFeedData( category=category, by=by, sort=sort, limit=limit, offset=offset ) + listOfHomeFeedData = [] + + # Process each post's raw data for data in rawHomeFeedData: homeFeedObj = {} - homeFeedObj["id"] = data[0] - homeFeedObj["title"] = data[1] - homeFeedObj["content"] = data[2] - homeFeedObj["author"] = data[3] - homeFeedObj["timeStamp"] = data[4] - homeFeedObj["category"] = data[5] - homeFeedObj["urlID"] = data[6] + homeFeedObj["id"] = data[0] # Post ID + homeFeedObj["title"] = data[1] # Post Title + homeFeedObj["content"] = data[2] # Post Content + homeFeedObj["author"] = data[3] # Author Name + homeFeedObj["timeStamp"] = data[4] # Timestamp + homeFeedObj["category"] = data[5] # Post Category + homeFeedObj["urlID"] = data[6] # URL ID + + # Generate URL for the post's banner image homeFeedObj["bannerImgSrc"] = url_for( "returnPostBanner.returnPostBanner", postID=data[0] ) + + # Get the author's profile picture homeFeedObj["authorProfile"] = getProfilePicture(data[3]) + + # Generate URL for viewing the full post homeFeedObj["postLink"] = url_for( "post.post", slug=getSlugFromPostTitle(data[1]), urlID=data[6] ) + + # Add the processed post data to the list listOfHomeFeedData.append(homeFeedObj) + # Return the list as a JSON payload with status 200 OK return make_response({"payload": listOfHomeFeedData}, 200) + except Exception as e: + # In case of any error, return a JSON error response with status 500 Internal Server Error return make_response({"error": f"{e}"}, 500) diff --git a/static/tailwindUI/js/homeFeed.js b/static/tailwindUI/js/homeFeed.js index de7e5fe4..045f50e2 100644 --- a/static/tailwindUI/js/homeFeed.js +++ b/static/tailwindUI/js/homeFeed.js @@ -1,20 +1,21 @@ // Initialize variable for postCardMacro and postContainer -let postCardMacro -let postContainer +let postCardMacro; +let postContainer; // Limit -let limit = 4 +let limit = 6; // Offset -let offset = 0 +let offset = 0; -// Id -let homeSpinner = document.getElementById("homeSpinner") -let loadMoreSpinner = document.getElementById("lodeMoreSpinner") -let currentCategory = document.getElementById("currentCategoryText") -let loadMoreButtonDiv = document.getElementById("loadMoreButton") -const sortBy = document.getElementById("currentSortText") -const orderby = document.getElementById("currentOrderText") +// Id of div elements and hidden input values +let homeSpinner = document.getElementById("homeSpinner"); +let loadMoreSpinner = document.getElementById("loadMoreSpinner"); +let currentCategory = document.getElementById("currentCategoryText"); +let loadMoreButtonDiv = document.getElementById("loadMoreButton"); +const sortBy = document.getElementById("currentSortText"); +const orderby = document.getElementById("currentOrderText"); +// Categories and associated icons const categoryList = { 'Games': '', 'History': '', @@ -40,7 +41,7 @@ const categoryList = { 'Default': '' }; - +// Function to inject html post macro in document body async function intializePostCard() { fetch(postCardMacroPath) .then(res => res.text()) @@ -52,61 +53,70 @@ async function intializePostCard() { // Register macro in dome document.body.appendChild(tempContainer); // or keep it detached - /// Assign html id of content to variable + /// Assign html element's id of content to variable postCardMacro = document.getElementById("postCardMacro"); postContainer = document.getElementById("postCardContainer"); }); } +// Call initialize post card function to inject post macro +intializePostCard(); -intializePostCard() - +// Function to fetch homeFeedData from backend async function fetchHomeFeedData() { try { - let connection = await fetch(`/api/v1/homeFeedData?category=${currentCategory.value}&by=${sortBy.value}&sort=${orderby.value}&limit=${limit}&offset=${offset}`) - let res = await connection.json() + let connection = await fetch(`/api/v1/homeFeedData?category=${currentCategory.value}&by=${sortBy.value}&sort=${orderby.value}&limit=${limit}&offset=${offset}`); + let res = await connection.json(); if (connection.ok) { - posts = res.payload; - - // Check if posts length is not less than limit + let posts = res.payload; posts.forEach(post => { - const clone = postCardMacro.content.cloneNode(true) - clone.querySelector(".postTitle").innerText = post.title - clone.querySelector(".postTitle").href = post.postLink - clone.querySelector(".postContent").innerHTML = post.content - clone.querySelector(".postBanner").src = post.bannerImgSrc - clone.querySelector(".postAuthorPicture").src = post.authorProfile - clone.querySelector(".postAuthor").innerText = post.author - clone.querySelector(".postAuthor").href = `/user/${post.author}` - clone.querySelector(".postCategory").innerHTML = categoryList[post.category] || categoryList["Default"] - clone.querySelector(".postTimeStamp").innerText = post.timeStamp - postContainer.appendChild(clone) + const clone = postCardMacro.content.cloneNode(true); + clone.querySelector(".postTitle").innerText = post.title; + clone.querySelector(".postTitle").href = post.postLink; + clone.querySelector(".postContent").innerHTML = post.content; + clone.querySelector(".postBanner").src = post.bannerImgSrc; + clone.querySelector(".postAuthorPicture").src = post.authorProfile; + clone.querySelector(".postAuthor").innerText = post.author; + clone.querySelector(".postAuthor").href = `/user/${post.author}`; + clone.querySelector(".postCategory").innerHTML = categoryList[post.category] || categoryList["Default"]; + clone.querySelector(".postTimeStamp").innerText = post.timeStamp; + postContainer.appendChild(clone); }); - offset += 4 + + // Increase the offset with the value of limit + offset += limit; + + // Check if posts length is not less than limit if (posts.length < limit) { // Hide button - loadMoreButtonDiv.classList.add("hidden") + loadMoreButtonDiv.classList.add("hidden"); } } else { - console.error(connection.status) + // Print error on console + console.error(connection.status); } } catch (error) { - console.error(error) + // Print error on console + console.error(error); } } async function loadMoreButton() { // Show spinner - loadMoreSpinner.classList.remove("hidden") - await fetchHomeFeedData() + loadMoreSpinner.classList.remove("hidden"); + // Fetch homeFeed + await fetchHomeFeedData(); // Hide spinner - loadMoreSpinner.classList.add("hidden") + loadMoreSpinner.classList.add("hidden"); } // Call the function to load data window.onload = async function () { - homeSpinner.classList.remove("hidden") - await fetchHomeFeedData() - homeSpinner.classList.add("hidden") + // Show spinner + homeSpinner.classList.remove("hidden"); + // Fetch initial homeFeed + await fetchHomeFeedData(); + // Hide spinner + homeSpinner.classList.add("hidden"); } \ No newline at end of file diff --git a/templates/tailwindUI/category.html.jinja b/templates/tailwindUI/category.html.jinja index 73b6df25..80fbbbd8 100755 --- a/templates/tailwindUI/category.html.jinja +++ b/templates/tailwindUI/category.html.jinja @@ -28,11 +28,12 @@
+ + id="loadMoreSpinner">
diff --git a/templates/tailwindUI/index.html.jinja b/templates/tailwindUI/index.html.jinja index 638e6f00..bd767d0a 100755 --- a/templates/tailwindUI/index.html.jinja +++ b/templates/tailwindUI/index.html.jinja @@ -34,11 +34,12 @@
+ + id="loadMoreSpinner">
From a1ff755fd21f29fa5a750167b4d3d3d43eea5000 Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Sun, 27 Apr 2025 08:16:26 +0530 Subject: [PATCH 03/10] Fixed typo and bug --- routes/returnHomeFeedData.py | 4 ++-- static/tailwindUI/js/homeFeed.js | 2 +- utils/getHomeFeedData.py | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py index 3dfb8ef1..862afde2 100644 --- a/routes/returnHomeFeedData.py +++ b/routes/returnHomeFeedData.py @@ -23,8 +23,8 @@ def homeFeedData(): category = request.args.get("category", type=str, default="all") by = request.args.get("by", type=str, default="hot") sort = request.args.get("sort", type=str, default="desc") - limit = request.args.get("limit", type=int, default="4") - offset = request.args.get("offset", type=int, default="0") + limit = request.args.get("limit", type=int, default=6) + offset = request.args.get("offset", type=int, default=0) try: # Fetch raw home feed data based on parameters diff --git a/static/tailwindUI/js/homeFeed.js b/static/tailwindUI/js/homeFeed.js index 045f50e2..1fdacc01 100644 --- a/static/tailwindUI/js/homeFeed.js +++ b/static/tailwindUI/js/homeFeed.js @@ -50,7 +50,7 @@ async function intializePostCard() { const tempContainer = document.createElement('div'); tempContainer.innerHTML = postCardHtml; - // Register macro in dome + // Register macro in DOM document.body.appendChild(tempContainer); // or keep it detached /// Assign html element's id of content to variable diff --git a/utils/getHomeFeedData.py b/utils/getHomeFeedData.py index ddb11475..4d6b8a6f 100644 --- a/utils/getHomeFeedData.py +++ b/utils/getHomeFeedData.py @@ -6,7 +6,11 @@ def getHomeFeedData( - by="hot", sort="desc", category: str = "all", offset: int = 0, limit: int = 3 + by: str = "hot", + sort: str = "desc", + category: str = "all", + offset: int = 0, + limit: int = 6, ) -> list: Log.database( f"Connecting to '{DB_POSTS_ROOT}' database" From 299a82bbbe5c2dbf2f04c0834a26fe37f624bd89 Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Tue, 29 Apr 2025 11:32:58 +0530 Subject: [PATCH 04/10] fixed typo and optimization --- app.py | 2 +- static/tailwindUI/js/homeFeed.js | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app.py b/app.py index e6e97c5e..01b92936 100755 --- a/app.py +++ b/app.py @@ -468,7 +468,7 @@ def afterRequest(response): ) # Registering the blueprint for the postAnalyticsData endpoint route app.register_blueprint( returnHomeFeedDataBlueprint -) # Registering the blueprint for the homeFeddData endpoint route +) # Registering the blueprint for the homeFeedData endpoint route # Check if the name of the module is the main module match __name__: diff --git a/static/tailwindUI/js/homeFeed.js b/static/tailwindUI/js/homeFeed.js index 1fdacc01..1cc79e1f 100644 --- a/static/tailwindUI/js/homeFeed.js +++ b/static/tailwindUI/js/homeFeed.js @@ -42,7 +42,7 @@ const categoryList = { }; // Function to inject html post macro in document body -async function intializePostCard() { +function initializePostCard() { fetch(postCardMacroPath) .then(res => res.text()) .then(postCardHtml => { @@ -58,8 +58,7 @@ async function intializePostCard() { postContainer = document.getElementById("postCardContainer"); }); } -// Call initialize post card function to inject post macro -intializePostCard(); + // Function to fetch homeFeedData from backend async function fetchHomeFeedData() { @@ -115,7 +114,10 @@ async function loadMoreButton() { window.onload = async function () { // Show spinner homeSpinner.classList.remove("hidden"); - // Fetch initial homeFeed + // Call initialize post card function to inject post macro in DOM + initializePostCard(); + + // Fetch initial homeFeed posts await fetchHomeFeedData(); // Hide spinner homeSpinner.classList.add("hidden"); From b01266518d510b11192d9a1a674aa81e35455406 Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Thu, 1 May 2025 15:44:45 +0530 Subject: [PATCH 05/10] Fix timeStamp breaks from python side --- routes/returnHomeFeedData.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py index 862afde2..ecc5e967 100644 --- a/routes/returnHomeFeedData.py +++ b/routes/returnHomeFeedData.py @@ -7,6 +7,7 @@ url_for, getProfilePicture, request, + datetime ) returnHomeFeedDataBlueprint = Blueprint("returnHomeFeedData", __name__) @@ -41,7 +42,7 @@ def homeFeedData(): homeFeedObj["title"] = data[1] # Post Title homeFeedObj["content"] = data[2] # Post Content homeFeedObj["author"] = data[3] # Author Name - homeFeedObj["timeStamp"] = data[4] # Timestamp + homeFeedObj["timeStamp"] = datetime.fromtimestamp(data[4]).strftime("%d.%m.%Y") # Timestamp homeFeedObj["category"] = data[5] # Post Category homeFeedObj["urlID"] = data[6] # URL ID From 040b1ebb7edb6c60134be0dad125a965adf84271 Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Thu, 1 May 2025 15:55:10 +0530 Subject: [PATCH 06/10] ruff format fix --- routes/returnHomeFeedData.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py index ecc5e967..1a7a7557 100644 --- a/routes/returnHomeFeedData.py +++ b/routes/returnHomeFeedData.py @@ -7,7 +7,7 @@ url_for, getProfilePicture, request, - datetime + datetime, ) returnHomeFeedDataBlueprint = Blueprint("returnHomeFeedData", __name__) @@ -42,7 +42,9 @@ def homeFeedData(): homeFeedObj["title"] = data[1] # Post Title homeFeedObj["content"] = data[2] # Post Content homeFeedObj["author"] = data[3] # Author Name - homeFeedObj["timeStamp"] = datetime.fromtimestamp(data[4]).strftime("%d.%m.%Y") # Timestamp + homeFeedObj["timeStamp"] = datetime.fromtimestamp(data[4]).strftime( + "%d.%m.%Y" + ) # Timestamp homeFeedObj["category"] = data[5] # Post Category homeFeedObj["urlID"] = data[6] # URL ID From 0868283889a766cc796eb12bb448491d3a79572c Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Thu, 1 May 2025 18:46:38 +0530 Subject: [PATCH 07/10] round year --- routes/returnHomeFeedData.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py index 1a7a7557..f470df8f 100644 --- a/routes/returnHomeFeedData.py +++ b/routes/returnHomeFeedData.py @@ -43,7 +43,7 @@ def homeFeedData(): homeFeedObj["content"] = data[2] # Post Content homeFeedObj["author"] = data[3] # Author Name homeFeedObj["timeStamp"] = datetime.fromtimestamp(data[4]).strftime( - "%d.%m.%Y" + "%d.%m.%y" ) # Timestamp homeFeedObj["category"] = data[5] # Post Category homeFeedObj["urlID"] = data[6] # URL ID From a7834e90dacf2b9f9ee8386cd09d50a90dad83c4 Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Sun, 11 May 2025 13:29:26 +0530 Subject: [PATCH 08/10] Revert "round year" This reverts commit 0868283889a766cc796eb12bb448491d3a79572c. --- routes/returnHomeFeedData.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py index f470df8f..1a7a7557 100644 --- a/routes/returnHomeFeedData.py +++ b/routes/returnHomeFeedData.py @@ -43,7 +43,7 @@ def homeFeedData(): homeFeedObj["content"] = data[2] # Post Content homeFeedObj["author"] = data[3] # Author Name homeFeedObj["timeStamp"] = datetime.fromtimestamp(data[4]).strftime( - "%d.%m.%y" + "%d.%m.%Y" ) # Timestamp homeFeedObj["category"] = data[5] # Post Category homeFeedObj["urlID"] = data[6] # URL ID From 8b24335b59d02d25ca0d0e03c274377a04090bb9 Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Sun, 11 May 2025 13:32:17 +0530 Subject: [PATCH 09/10] Revert "ruff format fix" This reverts commit 040b1ebb7edb6c60134be0dad125a965adf84271. --- routes/returnHomeFeedData.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py index 1a7a7557..ecc5e967 100644 --- a/routes/returnHomeFeedData.py +++ b/routes/returnHomeFeedData.py @@ -7,7 +7,7 @@ url_for, getProfilePicture, request, - datetime, + datetime ) returnHomeFeedDataBlueprint = Blueprint("returnHomeFeedData", __name__) @@ -42,9 +42,7 @@ def homeFeedData(): homeFeedObj["title"] = data[1] # Post Title homeFeedObj["content"] = data[2] # Post Content homeFeedObj["author"] = data[3] # Author Name - homeFeedObj["timeStamp"] = datetime.fromtimestamp(data[4]).strftime( - "%d.%m.%Y" - ) # Timestamp + homeFeedObj["timeStamp"] = datetime.fromtimestamp(data[4]).strftime("%d.%m.%Y") # Timestamp homeFeedObj["category"] = data[5] # Post Category homeFeedObj["urlID"] = data[6] # URL ID From f6a47e3dbd8d7f04ba04b07dc36c5d6ee8c03bcc Mon Sep 17 00:00:00 2001 From: Rohit Vishwakarma Date: Sun, 11 May 2025 13:32:47 +0530 Subject: [PATCH 10/10] Revert "Fix timeStamp breaks from python side" This reverts commit b01266518d510b11192d9a1a674aa81e35455406. --- routes/returnHomeFeedData.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/routes/returnHomeFeedData.py b/routes/returnHomeFeedData.py index ecc5e967..862afde2 100644 --- a/routes/returnHomeFeedData.py +++ b/routes/returnHomeFeedData.py @@ -7,7 +7,6 @@ url_for, getProfilePicture, request, - datetime ) returnHomeFeedDataBlueprint = Blueprint("returnHomeFeedData", __name__) @@ -42,7 +41,7 @@ def homeFeedData(): homeFeedObj["title"] = data[1] # Post Title homeFeedObj["content"] = data[2] # Post Content homeFeedObj["author"] = data[3] # Author Name - homeFeedObj["timeStamp"] = datetime.fromtimestamp(data[4]).strftime("%d.%m.%Y") # Timestamp + homeFeedObj["timeStamp"] = data[4] # Timestamp homeFeedObj["category"] = data[5] # Post Category homeFeedObj["urlID"] = data[6] # URL ID