[TIL] Toy Project Day 4 - Like & Delete Button User Control Feature & Presentation, Deployment
03/30/23
![[TIL] Toy Project Day 4 - Like & Delete Button User Control Feature & Presentation, Deployment](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1680184334867%2F391cdf75-281e-4712-9036-6cc961b4356d.png&w=3840&q=75)
Reading User Login Token Cookie
token_receive = request.cookies.get("mytoken")
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=["HS256"])
userid = payload["id"]
user_info = db.user.find_one({ "id": userid })
nickname = user_info["nick"]
return render_template("index.html", nickname=nickname )
except:
return render_template("index.html")
Like Button
Logic
Contain the store id in the "liked_store" array attribute under users DB
When the user is not logged in, the Like button is disabled
When the user is logged in,
check if the user already clicked the store
FE: increase the like count number on the page and push store id to the liked_store array
BE: send the store id to the /likeUp API
/likeUp API will increase the like attribute's number by 1 under the store's DB
/likeUp API will add the store id into "liked_store" array under the user's DB
check if the user has not clicked the store
check if the user already clicked the store
FE: increase the like count number on the page and push store id to the liked_store array
BE: send the store id to the /likeDown API
/likeDownAPI will decrease the like attribute's number by 1 under the store's DB
/likeDownAPI will delete the store id into "liked_store" array under the user's DB
Code
# Like button
@app.route("/likeUp", methods=["POST"])
def like_up():
token_receive = request.cookies.get('mytoken')
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
userid = payload["id"]
store_id_receive = request.form["id_give"]
# get current like count number
like = db.stores.find_one({"_id": ObjectId(store_id_receive)}, {"like": 1})
num_like = int(like["like"]) + 1
# update the like number of store on DB
add_like = {"$set": {"like": num_like}}
db.stores.update_one({"_id": ObjectId(store_id_receive)}, add_like)
# add the info that the user clicked the store in DB
# the way to append val to the array in MongoDB
add_liked_store = {'$addToSet': {'liked_store': store_id_receive}}
db.user.update_one({'id': userid}, add_liked_store)
return jsonify({"msg": "You added Like"})
except jwt.ExpiredSignatureError:
return redirect(url_for("go_login", msg="Login time is expired"))
except jwt.exceptions.DecodeError:
return redirect(url_for("go_login", msg="No user found"))
@app.route("/likeDown", methods=["POST"])
def like_down():
token_receive = request.cookies.get('mytoken')
try:
payload = jwt.decode(token_receive, SECRET_KEY, algorithms=['HS256'])
userid = payload["id"]
store_id_receive = request.form["id_give"]
like = db.stores.find_one({"_id": ObjectId(request.form["id_give"])}, {"like": 1})
num_like = int(like["like"]) - 1
add_like = {"$set": {"like": num_like}}
db.stores.update_one({"_id": ObjectId(request.form["id_give"])}, add_like)
# the way to delete specific value from array in DB
delete_liked_store = {'$pull': {'liked_store': store_id_receive}}
db.user.update_one({'id': userid}, delete_liked_store)
return jsonify({"msg": "You deleted Like"})
except jwt.ExpiredSignatureError:
return redirect(url_for("go_login", msg="Login time is expired"))
except jwt.exceptions.DecodeError:
return redirect(url_for("go_login", msg="No user found"))
$(".like").click(function () {
let storeid = this.value;
// Like 1 increasing part
if (!liked_store.includes(storeid)) {
// FE - number changed without refreshing page
$(this).removeClass("is-light");
$(this).html(function (i, val) {
return `👍 ${val.split(" ")[1] * 1 + 1}`;
});
// FE - add store id to liked_store array
liked_store.push(storeid);
// BE - send the changed count to DB
let formData = new FormData();
formData.append("id_give", this.value);
fetch("/likeUp", { method: "POST", body: formData })
.then((response) => response.json())
.then((data) => {});
}
// Like 1 decreasing part
else if (liked_store.includes(storeid)) {
$(this).addClass("is-light");
$(this).html(function (i, val) {
return `👍 ${val.split(" ")[1] * 1 - 1}`;
});
// FE - remove store id to liked_store array
liked_store = liked_store.filter((s) => {
return s !== storeid;
}); // THIS PART REQUIRES IMPROVEMENT FOR SUSTAINABILITY AND SPEED
let formData = new FormData();
formData.append("id_give", this.value);
fetch("/likeDown", { method: "POST", body: formData })
.then((response) => response.json())
.then((data) => {});
}
});
// style is applied when refreshing the page
// when user is not logged in
if (userid === null) {
temp_html_2 = `<div class="store-btn">
<button type="button" class="like button is-warning" title="Disabled button" disabled value=${id}>👍 ${like}</button>
</div>
</div>
</div>`;
}
// when user already clicked Like
else if (liked_store.includes(id)) {
temp_html_2 = `<div class="store-btn">
<button type="button" class="button is-danger modify" name=${writerId} value=${id}>수정</button>
<button type="button" class="like button is-warning" value=${id}>👍 ${like}</button>
</div>
</div>
</div>`;
}
// when user hasn't click Like
else {
temp_html_2 = `<div class="store-btn">
<button type="button" class="button is-danger modify" name=${writerId} value=${id}>수정</button>
<button type="button" class="like button is-warning is-light" value=${id}>👍 ${like}</button>
</div>
</div>
</div>`;
}
temp_html = temp_html_1.concat(temp_html_2);
$("#cards").append(temp_html);
Delete/Update Button
Logic
Add the writer id to store API to distinguish the writer of the post
When clicking the Delete button, check if the currently logged-in user is the writer of the post
If so, perform the delete function
If not, show an alert message
Code
$(".delete").click(function () {
console.log(this.name, userid);
if (this.name == userid) { // <button name=${writerId}>
let formData = new FormData();
formData.append("id_give", this.value);
console.log(this.value);
fetch("/store", { method: "DELETE", body: formData })
.then((response) => response.json())
.then((data) => {
window.location.reload();
});
} else {
alert("No permission to delete");
}
});
Deployment
How to keep the server running when the bash is terminated
nohup python3 app.py
How to stop the server running by nohup
Check the pid (process id) ->
sudo lsof -t -i:[port number]Kill the process ->
kill -9 [pid]
![[코테] 그리디 문제 - 무지의 먹방 라이브](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1712215455263%2F1ac1f35a-8862-4e42-8d0c-e2bea01e04c0.png&w=3840&q=75)
![[코테] Bfs 토마토](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1709032619170%2F70056896-c857-444b-9c99-45bfcb466806.png&w=3840&q=75)
![[코테] Dfs 문제 유형 - 그래프 내에서 구분하여 카운트 하기](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1709019361383%2Fb0585d72-c808-4169-83a9-2724f312e927.png&w=3840&q=75)
![[코테] DFS vs BFS](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1708971211123%2F71f9386c-6a62-43b2-a602-4d084c24d6cf.png&w=3840&q=75)
![[코테] 여행경로](/_next/image?url=https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1708971251412%2F27ce72ed-8ee7-4d13-a02f-ff4bbe50c4be.png&w=3840&q=75)