Skip to content

Commit b5c8b4b

Browse files
committed
## Tweet Application: First Phase: Bug Fix
* 1 -> All text content saved in tweet, comment, nested comment goes in single line. new line character is not being preserved in UI. However data saved in DB is ok. -- Done * 2.1 -> Post create new comment, text not get cleared. --Done * 2.2 -> Post create new Nested comment, text not get cleared. -- Done * 3 -> increase size of text-area in EditableLabel.jsx to all width of screen or component. Also height to show all text --Done * 4 -> updated text of EditableLabel component is not being saved on first click of "Update" button -- Unresolved. Moved to TechDebt * 5 -> Comments and Nested comments get updated, even if textarea containing empty string. Add checks for empty strings same as in case of save comment and nested-comment -- Done * 6 -> Text of EditableLabel should be wrapped in view mode -- Done * 7 -> Add one changelog.md file to track what all things done in different iterations -- Done * 8 -> Make font of tweet, comment and nested text different. eg, tweet bold and some bigger, comment normal, nested comment smaller and italic -- Done * 9 -> set Times New Roman (serif) font family globally in Tweet application -- Done
1 parent cee685e commit b5c8b4b

File tree

8 files changed

+259
-18
lines changed

8 files changed

+259
-18
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
## Tweet Application: First Phase: Requirements
2+
3+
Below points done and pushed to repo
4+
5+
- Create basic application to
6+
- Add update tweet
7+
- Add update comment
8+
- Add update nested comment
9+
- List all Tweets
10+
- Add one sort button to sort tweets on createdAt
11+
12+
## Tweet Application: First Phase: Bug Fix
13+
14+
- 1 -> All text content saved in tweet, comment, nested comment goes in single line. new line character is not being preserved in UI. However data saved in DB is ok. -- Done
15+
- 2.1 -> Post create new comment, text not get cleared. --Done
16+
- 2.2 -> Post create new Nested comment, text not get cleared. -- Done
17+
- 3 -> increase size of text-area in EditableLabel.jsx to all width of screen or component. Also height to show all text --Done
18+
- 4 -> updated text of EditableLabel component is not being saved on first click of "Update" button -- Unresolved. Moved to TechDebt
19+
- 5 -> Comments and Nested comments get updated, even if textarea containing empty string. Add checks for empty strings same as in case of save comment and nested-comment -- Done
20+
- 6 -> Text of EditableLabel should be wrapped in view mode -- Done
21+
- 7 -> Add one changelog.md file to track what all things done in different iterations -- Done
22+
- 8 -> Make font of tweet, comment and nested text different. eg, tweet bold and some bigger, comment normal, nested comment smaller and italic -- Done
23+
- 9 -> set Times New Roman (serif) font family globally in Tweet application
24+
25+
## Tweet Application: Second Phase: Requirements
26+
27+
- 1 -> Bug Fixes of First Phase. New Development freeze till all major Bug Fix Done for First Phase.
28+
- 2 -> Add buttons to save new Comment, remove onBlur event on text-area for comment
29+
- 3 -> Add one property saveOnBlur(true or false) in EditableLabel.jsx component. If true, then on blur, data will be saved.
30+
- 4 -> Make default sorting order for tweets to descending order, i.e., latest tweet should be displayed first.
31+
32+
### TechDebt
33+
- 1 -> updated text of EditableLabel component is not being saved on first click of "Update" button
34+

learn-react/TweetApp/frontend/src/components/common/EditableLabel.jsx

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useState } from "react";
22

3-
function EditableLabel({ text, postUpdateClick=()=>{} }) {
3+
function EditableLabel({ text, postUpdateClick = () => {}, style = {} }) {
44
const [editing, setEditing] = useState(false);
55
const [editedText, setEditedText] = useState(text);
66

@@ -9,10 +9,11 @@ function EditableLabel({ text, postUpdateClick=()=>{} }) {
99
};
1010

1111
const handleTextareaChange = (e) => {
12-
setEditedText(e.target.value);
12+
setEditedText((prevEditedText) => e.target.value);
13+
console.log(editedText);
1314
};
1415

15-
const handleTextareaBlur = () => {
16+
const cancelEdit = () => {
1617
setEditing(false);
1718
};
1819

@@ -23,24 +24,38 @@ function EditableLabel({ text, postUpdateClick=()=>{} }) {
2324
<textarea
2425
value={editedText}
2526
onChange={handleTextareaChange}
27+
onBlur={cancelEdit}
28+
style={{
29+
width: "100%", // Expand the textarea width
30+
height: `${editedText.split("\n").length + 3}em`, // Set height based on number of lines
31+
}}
2632
/>
2733
<button
2834
onClick={() => {
29-
console.log(editedText);
30-
setEditing(false);
31-
postUpdateClick(editedText)
35+
console.log(editedText);
36+
setEditing(false);
37+
postUpdateClick(editedText);
3238
}}
3339
>
3440
Update
3541
</button>
36-
<button
37-
onClick={() => setEditing(false)}
38-
>
39-
cancel
40-
</button>
42+
<button onClick={cancelEdit}>cancel</button>
4143
</>
4244
) : (
43-
<label onClick={handleLabelClick}>{text}</label>
45+
<>
46+
<label
47+
onClick={handleLabelClick}
48+
style={{
49+
...style, // Apply custom style passed via prop
50+
whiteSpace: "pre-wrap", // Allows wrapping within <pre>
51+
cursor: "pointer", // Change cursor to pointer on hover
52+
padding: "10px", // Add padding for visual comfort
53+
border: "1px solid #ccc", // Add a border for clarity
54+
}}
55+
>
56+
{text}
57+
</label>
58+
</>
4459
)}
4560
</div>
4661
);

learn-react/TweetApp/frontend/src/components/tweets/ListTweetsUpdate4.jsx

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useState } from "react";
22
import "./list-tweets3.css";
33
import CreateTweet from "./CreateTweet";
4-
import Tweet from "./ViewTweet";
4+
import Tweet from "./ViewTweet2";
55
import GlobalConstants from "../../common/globalConstants";
66

77
function formatTimestamp(timestamp) {
@@ -16,7 +16,7 @@ function ListTweetsUpdate({
1616
}) {
1717
const BASE_URL=GlobalConstants.tweetsApplicationBaseURL;
1818

19-
const [sortAscending, setSortAscending] = useState(true); // Toggle to sort ascending or descending
19+
const [sortAscending, setSortAscending] = useState(false); // Toggle to sort ascending or descending
2020

2121
const sortedTweets = [...tweets].sort((a, b) =>
2222
sortAscending
@@ -29,6 +29,9 @@ function ListTweetsUpdate({
2929
};
3030

3131
const handleUpdateTweet = async (tweetId, updatedContent) => {
32+
if (updatedContent.trim() === "") {
33+
return;
34+
}
3235
try {
3336
const response = await fetch(`${BASE_URL}/tweets/${tweetId}`, {
3437
method: "PUT",
@@ -49,6 +52,9 @@ function ListTweetsUpdate({
4952
};
5053

5154
const handleUpdateComment = async (tweetId, commentId, updatedText) => {
55+
if (updatedText.trim() === "") {
56+
return;
57+
}
5258
try {
5359
const response = await fetch(
5460
`${BASE_URL}/tweets/${tweetId}/comments/${commentId}`,
@@ -77,6 +83,9 @@ function ListTweetsUpdate({
7783
nestedCommentId,
7884
updatedText
7985
) => {
86+
if (updatedText.trim() === "") {
87+
return;
88+
}
8089
try {
8190
const response = await fetch(
8291
`${BASE_URL}/tweets/${tweetId}/comments/${commentId}/nested/${nestedCommentId}`,
@@ -99,7 +108,9 @@ function ListTweetsUpdate({
99108
}
100109
};
101110

102-
const handleAddComment = async (tweetId, newCommentText) => {
111+
const [newCommentText, setNewCommentText] = useState(""); // State to hold the new comment text
112+
113+
const handleAddComment = async (tweetId) => {
103114
if (newCommentText.trim() === "") {
104115
return;
105116
}
@@ -119,7 +130,8 @@ function ListTweetsUpdate({
119130
if (response.ok) {
120131
const updatedTweet = await response.json();
121132
onUpdate(updatedTweet);
122-
refreshFunction();
133+
refreshFunction();
134+
setNewCommentText(""); // Reset the new comment text
123135
}
124136
} catch (error) {
125137
console.error("Error adding comment:", error);
@@ -176,6 +188,8 @@ function ListTweetsUpdate({
176188
handleAddComment={handleAddComment}
177189
handleAddNestedComment={handleAddNestedComment}
178190
formatTimestamp={formatTimestamp}
191+
newCommentText={newCommentText} // Pass the new comment text as a prop
192+
setNewCommentText={setNewCommentText} // Pass the setter function as a prop
179193
/>
180194
))}
181195
</div>
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from "react";
2+
import EditableLabel from "../common/EditableLabel";
3+
import NestedComment from "./ViewNestedComment";
4+
import { useState } from "react";
5+
6+
function Comment({
7+
tweetId,
8+
comment,
9+
handleUpdateComment,
10+
handleAddNestedComment,
11+
handleUpdateNestedComment,
12+
formatTimestamp,
13+
// newNestedCommentText,
14+
// setNewNestedCommentText
15+
}) {
16+
const [newNestedCommentText, setNewNestedCommentText] = useState(""); // State to hold the new comment text
17+
return (
18+
<div key={comment._id} className="comment">
19+
<p className="timestamp">{formatTimestamp(comment.createdAt)}</p>
20+
<EditableLabel
21+
text={comment.text}
22+
postUpdateClick={(updatedText) =>
23+
handleUpdateComment(tweetId, comment._id, updatedText)
24+
}
25+
style={{
26+
fontWeight: "normal", // Apply normal style for comment
27+
fontSize: "16px", // Set font size for comment
28+
}}
29+
/>
30+
<div className="nested-comments">
31+
<div>
32+
<textarea
33+
placeholder="Enter a nested comment"
34+
onBlur={(e) =>{
35+
handleAddNestedComment(tweetId, comment._id, e.target.value)
36+
setNewNestedCommentText(""); // Reset the new comment text after adding
37+
}}
38+
value={newNestedCommentText} // Use the state value for the textarea value
39+
onChange={(e) => setNewNestedCommentText(e.target.value)} // Update the state as you type
40+
/>
41+
</div>
42+
{comment.nestedComments.map((nestedComment) => (
43+
<NestedComment
44+
key={nestedComment._id}
45+
tweetId={tweetId}
46+
commentId={comment._id}
47+
nestedComment={nestedComment}
48+
handleUpdateNestedComment={handleUpdateNestedComment}
49+
formatTimestamp={formatTimestamp}
50+
/>
51+
))}
52+
</div>
53+
</div>
54+
);
55+
}
56+
57+
export default Comment;
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import React from "react";
2+
import EditableLabel from "../common/EditableLabel";
3+
4+
function NestedComment({
5+
tweetId,
6+
commentId,
7+
nestedComment,
8+
handleUpdateNestedComment,
9+
formatTimestamp,
10+
}) {
11+
return (
12+
<div key={nestedComment._id} className="nested-comment">
13+
<p className="timestamp">{formatTimestamp(nestedComment.createdAt)}</p>
14+
<EditableLabel
15+
text={nestedComment.text}
16+
style={{
17+
fontStyle: "italic", // Apply italic style for nested comment
18+
fontSize: "14px", // Set font size for nested comment
19+
}}
20+
postUpdateClick={(updatedText) =>
21+
handleUpdateNestedComment(
22+
tweetId,
23+
commentId,
24+
nestedComment._id,
25+
updatedText
26+
)
27+
}
28+
/>
29+
</div>
30+
);
31+
}
32+
33+
export default NestedComment;

learn-react/TweetApp/frontend/src/components/tweets/ViewTweet.jsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ function Tweet({
88
handleUpdateNestedComment,
99
handleAddComment,
1010
handleAddNestedComment,
11-
formatTimestamp
11+
formatTimestamp,
12+
newCommentText,
13+
setNewCommentText,
1214
}) {
1315
return (
1416
<div key={tweet._id} className="tweet-card">
@@ -18,13 +20,22 @@ function Tweet({
1820
postUpdateClick={(updatedContent) =>
1921
handleUpdateTweet(tweet._id, updatedContent)
2022
}
23+
style={{
24+
fontWeight: "bold", // Apply bold style for tweet
25+
fontSize: "18px", // Set font size for tweet
26+
}}
2127
/>
2228

2329
<div className="comments-section">
2430
<div>
2531
<textarea
2632
placeholder="Enter a new comment"
27-
onBlur={(e) => handleAddComment(tweet._id, e.target.value)}
33+
onBlur={(e) => {
34+
handleAddComment(tweet._id, e.target.value);
35+
setNewCommentText(""); // Reset the new comment text after adding
36+
}}
37+
value={newCommentText} // Use the state value for the textarea value
38+
onChange={(e) => setNewCommentText(e.target.value)} // Update the state as you type
2839
/>
2940
</div>
3041
{tweet.comments.map((comment) => (
@@ -35,6 +46,10 @@ function Tweet({
3546
postUpdateClick={(updatedText) =>
3647
handleUpdateComment(tweet._id, comment._id, updatedText)
3748
}
49+
style={{
50+
fontWeight: "normal", // Apply normal style for comment
51+
fontSize: "16px", // Set font size for comment
52+
}}
3853
/>
3954
<div className="nested-comments">
4055
<div>
@@ -56,6 +71,10 @@ function Tweet({
5671
</p>
5772
<EditableLabel
5873
text={nestedComment.text}
74+
style={{
75+
fontStyle: "italic", // Apply italic style for nested comment
76+
fontSize: "14px", // Set font size for nested comment
77+
}}
5978
postUpdateClick={(updatedText) =>
6079
handleUpdateNestedComment(
6180
tweet._id,
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import React from "react";
2+
import EditableLabel from "../common/EditableLabel";
3+
import Comment from "./ViewComment"; // Import the Comment component
4+
import { useState } from "react";
5+
6+
function Tweet({
7+
tweet,
8+
handleUpdateTweet,
9+
handleAddComment,
10+
handleAddNestedComment,
11+
handleUpdateComment, // Make sure this function is imported and available
12+
handleUpdateNestedComment, // Make sure this function is imported and available
13+
formatTimestamp,
14+
newCommentText,
15+
setNewCommentText,
16+
}) {
17+
const [newNestedCommentText, setNewNestedCommentText] = useState(""); // State to hold the new comment text
18+
return (
19+
<div key={tweet._id} className="tweet-card">
20+
<p className="timestamp">{formatTimestamp(tweet.createdAt)}</p>
21+
<EditableLabel
22+
text={tweet.content}
23+
postUpdateClick={(updatedContent) =>
24+
handleUpdateTweet(tweet._id, updatedContent)
25+
}
26+
style={{
27+
fontWeight: "bold", // Apply bold style for tweet
28+
fontSize: "18px", // Set font size for tweet
29+
}}
30+
/>
31+
32+
<div className="comments-section">
33+
<div>
34+
<textarea
35+
placeholder="Enter a new comment"
36+
onBlur={(e) => {
37+
handleAddComment(tweet._id, e.target.value);
38+
setNewCommentText(""); // Reset the new comment text after adding
39+
}}
40+
value={newCommentText} // Use the state value for the textarea value
41+
onChange={(e) => setNewCommentText(e.target.value)} // Update the state as you type
42+
/>
43+
</div>
44+
{tweet.comments.map((comment) => (
45+
<Comment
46+
key={comment._id}
47+
tweetId={tweet._id}
48+
comment={comment}
49+
handleUpdateComment={handleUpdateComment}
50+
handleAddNestedComment={handleAddNestedComment}
51+
handleUpdateNestedComment={handleUpdateNestedComment}
52+
formatTimestamp={formatTimestamp}
53+
newNestedCommentText={newNestedCommentText} // Pass the new comment text as a prop
54+
setNewNestedCommentText={setNewNestedCommentText} // Pass the setter function as a prop
55+
/>
56+
))}
57+
</div>
58+
</div>
59+
);
60+
}
61+
62+
export default Tweet;

0 commit comments

Comments
 (0)