Skip to content
This repository was archived by the owner on Sep 10, 2025. It is now read-only.

Commit bb63924

Browse files
updated
1 parent 197ccb8 commit bb63924

File tree

4 files changed

+183
-106
lines changed

4 files changed

+183
-106
lines changed

body.txt

Lines changed: 82 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,96 @@
11

2-
This challenge focuses on styling a multi-level nested list using CSS. We'll create a visually appealing and easily navigable list with distinct styling for each level. We will use standard CSS for this example.
3-
4-
5-
## Description of the Styling
6-
7-
The goal is to create a nested list where:
8-
9-
* The top-level list items (`<li>`) have a larger font size and are bolded.
10-
* Each subsequent level is indented further and has a smaller font size.
11-
* List markers are replaced with custom icons (using background images for simplicity).
12-
* A subtle background color alternates between list levels to enhance readability.
13-
14-
## Full Code
15-
16-
```html
17-
<!DOCTYPE html>
18-
<html>
19-
<head>
20-
<title>Nested List Styling</title>
21-
<style>
22-
ul {
23-
list-style: none; /* Remove default bullet points */
24-
padding: 0;
25-
margin-left: 20px; /* Initial indent */
26-
}
27-
28-
li {
29-
margin-bottom: 10px;
30-
}
31-
32-
li::before {
33-
content: ""; /* Add content for custom icons */
34-
display: inline-block;
35-
width: 20px;
36-
height: 20px;
37-
margin-right: 10px;
38-
background-repeat: no-repeat;
39-
background-size: contain;
40-
}
41-
42-
ul.level-1 > li {
43-
font-size: 18px;
44-
font-weight: bold;
45-
background-color: #f9f9f9;
46-
padding: 10px;
47-
margin-left: 0; /* Remove the default indentation from first level */
48-
49-
}
50-
ul.level-1 > li::before {
51-
background-image: url('folder-icon.png'); /* Replace with your icon */
52-
}
53-
54-
ul.level-2 > li {
55-
font-size: 16px;
56-
background-color: #f2f2f2;
57-
padding: 5px;
58-
}
59-
ul.level-2 > li::before {
60-
background-image: url('file-icon.png'); /* Replace with your icon */
61-
}
62-
63-
ul.level-3 > li {
64-
font-size: 14px;
65-
background-color: #f9f9f9;
66-
padding: 5px;
67-
}
68-
ul.level-3 > li::before {
69-
background-image: url('document-icon.png'); /* Replace with your icon */
70-
}
71-
72-
/* Add more styles for deeper levels as needed */
73-
</style>
74-
</head>
75-
<body>
76-
77-
<h1>My Documents</h1>
78-
79-
<ul class="level-1">
80-
<li>Project Alpha
81-
<ul class="level-2">
82-
<li>Report.pdf</li>
83-
<li>Presentation.pptx</li>
84-
</ul>
85-
</li>
86-
<li>Project Beta
87-
<ul class="level-2">
88-
<li>Design Mockups
89-
<ul class="level-3">
90-
<li>Homepage.jpg</li>
91-
<li>AboutUs.png</li>
92-
</ul>
93-
</li>
94-
<li>Code.zip</li>
95-
</ul>
96-
</li>
97-
</ul>
98-
99-
</body>
100-
</html>
2+
## Description of the Error
1013

4+
A common issue when working with Firestore and posts (or any time-sensitive data) is incorrect handling of timestamps. Developers often try to directly set the timestamp on the client using `FieldValue.serverTimestamp()`, expecting Firestore to automatically populate the field with the server's time. While this function *is* designed to get the server time, attempting to set it directly in a client-side write can lead to unexpected behavior, including the timestamp being set to null or an older client-side time. This can result in posts appearing out of order or with incorrect timestamps displayed to users. The problem stems from the fact that the `serverTimestamp()` function needs to be handled *within* the Firestore server, not just requested from the client.
5+
6+
## Fixing the Issue Step-by-Step
7+
8+
This example demonstrates creating and updating posts with accurate timestamps using a Cloud Function. This approach ensures the server handles timestamp generation, preventing client-side discrepancies.
9+
10+
11+
**1. Set up a Cloud Function (Node.js):**
12+
13+
First, you need a Cloud Function triggered by Firestore writes. This function will intercept the write operation and correctly set the timestamp.
14+
15+
```javascript
16+
// index.js (Cloud Function)
17+
18+
const functions = require("firebase-functions");
19+
const admin = require("firebase-admin");
20+
admin.initializeApp();
21+
const db = admin.firestore();
22+
23+
exports.updatePostTimestamp = functions.firestore
24+
.document("posts/{postId}")
25+
.onWrite(async (change, context) => {
26+
const before = change.before.data();
27+
const after = change.after.data();
28+
29+
// Only update if the timestamp is missing (new post or not specifically updated)
30+
if (!after.timestamp && after.title && after.content) {
31+
const updatedPost = {
32+
...after,
33+
timestamp: admin.firestore.FieldValue.serverTimestamp(),
34+
};
35+
await change.after.ref.set(updatedPost, {merge: true});
36+
}
37+
38+
// Optionally, handle updates to the timestamp - for example, prevent users from modifying the timestamp after it has been set.
39+
if(before.timestamp && after.timestamp && before.timestamp.toMillis() != after.timestamp.toMillis()){
40+
//Log an error or revert the change in a production environment.
41+
console.log("Timestamp modification attempt detected.");
42+
}
43+
44+
});
10245
```
10346

104-
Remember to replace `folder-icon.png`, `file-icon.png`, and `document-icon.png` with actual paths to your icon images.
47+
**2. Client-side Code (Example using JavaScript):**
48+
49+
Your client-side code should *not* attempt to set the `timestamp` field directly. Instead, omit it from the data sent to Firestore. The Cloud Function will handle adding it.
50+
51+
52+
```javascript
53+
// client-side code (example using JavaScript and Firebase SDK)
54+
55+
// ... other code ...
56+
57+
const addPost = async (title, content) => {
58+
try {
59+
await db.collection("posts").add({
60+
title: title,
61+
content: content,
62+
// DO NOT INCLUDE timestamp HERE
63+
});
64+
console.log("Post added successfully!");
65+
} catch (error) {
66+
console.error("Error adding post:", error);
67+
}
68+
};
69+
70+
// ... rest of your client-side code ...
71+
```
72+
73+
**3. Deploy the Cloud Function:**
74+
75+
Deploy the Cloud Function to your Firebase project using the Firebase CLI:
76+
77+
```bash
78+
firebase deploy --only functions
79+
```
10580

10681

10782
## Explanation
10883

109-
The CSS code uses a combination of list-style removal, pseudo-elements (`::before`), and class-based styling to achieve the desired visual hierarchy. Each level of the nested list gets its own class (`.level-1`, `.level-2`, `.level-3`) allowing for specific font sizes, background colors, and icon assignments. The `::before` pseudo-element adds the custom icon before each list item. The `background-image` property sets the icon. You can adjust the font sizes, colors, indentation, and icon sizes to your preference.
84+
This solution leverages a Cloud Function to handle the timestamp generation on the server-side. The client sends the post data without the timestamp. The Cloud Function, triggered by the `onWrite` event, checks if a `timestamp` field exists. If not (meaning a new post), it adds the server timestamp using `admin.firestore.FieldValue.serverTimestamp()`. This guarantees accuracy and consistency across all clients. The merge option is used to ensure that existing fields in the document are not overwritten.
85+
86+
The second part of the conditional statement in the cloud function provides a mechanism to prevent timestamp modification after it has been set.
11087

11188

112-
## Resources to Learn More
89+
## External References
11390

114-
* **MDN Web Docs CSS Reference:** [https://developer.mozilla.org/en-US/docs/Web/CSS](https://developer.mozilla.org/en-US/docs/Web/CSS) (Excellent resource for all things CSS)
115-
* **CSS Tricks:** [https://css-tricks.com/](https://css-tricks.com/) (A website with tutorials and articles on CSS techniques)
91+
* **Firebase Cloud Functions Documentation:** [https://firebase.google.com/docs/functions](https://firebase.google.com/docs/functions)
92+
* **Firebase Firestore Documentation:** [https://firebase.google.com/docs/firestore](https://firebase.google.com/docs/firestore)
93+
* **FieldValue.serverTimestamp() Documentation:** [https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents#FieldValue](https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents#FieldValue)
11694

11795

11896
Copyrights (c) OpenRockets Open-source Network. Free to use, copy, share, edit or publish.
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# 🐞 Handling Firestore's `FieldValue.serverTimestamp()` in Client-Side Code for Post Timestamps
2+
3+
4+
## Description of the Error
5+
6+
A common issue when working with Firestore and posts (or any time-sensitive data) is incorrect handling of timestamps. Developers often try to directly set the timestamp on the client using `FieldValue.serverTimestamp()`, expecting Firestore to automatically populate the field with the server's time. While this function *is* designed to get the server time, attempting to set it directly in a client-side write can lead to unexpected behavior, including the timestamp being set to null or an older client-side time. This can result in posts appearing out of order or with incorrect timestamps displayed to users. The problem stems from the fact that the `serverTimestamp()` function needs to be handled *within* the Firestore server, not just requested from the client.
7+
8+
## Fixing the Issue Step-by-Step
9+
10+
This example demonstrates creating and updating posts with accurate timestamps using a Cloud Function. This approach ensures the server handles timestamp generation, preventing client-side discrepancies.
11+
12+
13+
**1. Set up a Cloud Function (Node.js):**
14+
15+
First, you need a Cloud Function triggered by Firestore writes. This function will intercept the write operation and correctly set the timestamp.
16+
17+
```javascript
18+
// index.js (Cloud Function)
19+
20+
const functions = require("firebase-functions");
21+
const admin = require("firebase-admin");
22+
admin.initializeApp();
23+
const db = admin.firestore();
24+
25+
exports.updatePostTimestamp = functions.firestore
26+
.document("posts/{postId}")
27+
.onWrite(async (change, context) => {
28+
const before = change.before.data();
29+
const after = change.after.data();
30+
31+
// Only update if the timestamp is missing (new post or not specifically updated)
32+
if (!after.timestamp && after.title && after.content) {
33+
const updatedPost = {
34+
...after,
35+
timestamp: admin.firestore.FieldValue.serverTimestamp(),
36+
};
37+
await change.after.ref.set(updatedPost, {merge: true});
38+
}
39+
40+
// Optionally, handle updates to the timestamp - for example, prevent users from modifying the timestamp after it has been set.
41+
if(before.timestamp && after.timestamp && before.timestamp.toMillis() != after.timestamp.toMillis()){
42+
//Log an error or revert the change in a production environment.
43+
console.log("Timestamp modification attempt detected.");
44+
}
45+
46+
});
47+
```
48+
49+
**2. Client-side Code (Example using JavaScript):**
50+
51+
Your client-side code should *not* attempt to set the `timestamp` field directly. Instead, omit it from the data sent to Firestore. The Cloud Function will handle adding it.
52+
53+
54+
```javascript
55+
// client-side code (example using JavaScript and Firebase SDK)
56+
57+
// ... other code ...
58+
59+
const addPost = async (title, content) => {
60+
try {
61+
await db.collection("posts").add({
62+
title: title,
63+
content: content,
64+
// DO NOT INCLUDE timestamp HERE
65+
});
66+
console.log("Post added successfully!");
67+
} catch (error) {
68+
console.error("Error adding post:", error);
69+
}
70+
};
71+
72+
// ... rest of your client-side code ...
73+
```
74+
75+
**3. Deploy the Cloud Function:**
76+
77+
Deploy the Cloud Function to your Firebase project using the Firebase CLI:
78+
79+
```bash
80+
firebase deploy --only functions
81+
```
82+
83+
84+
## Explanation
85+
86+
This solution leverages a Cloud Function to handle the timestamp generation on the server-side. The client sends the post data without the timestamp. The Cloud Function, triggered by the `onWrite` event, checks if a `timestamp` field exists. If not (meaning a new post), it adds the server timestamp using `admin.firestore.FieldValue.serverTimestamp()`. This guarantees accuracy and consistency across all clients. The merge option is used to ensure that existing fields in the document are not overwritten.
87+
88+
The second part of the conditional statement in the cloud function provides a mechanism to prevent timestamp modification after it has been set.
89+
90+
91+
## External References
92+
93+
* **Firebase Cloud Functions Documentation:** [https://firebase.google.com/docs/functions](https://firebase.google.com/docs/functions)
94+
* **Firebase Firestore Documentation:** [https://firebase.google.com/docs/firestore](https://firebase.google.com/docs/firestore)
95+
* **FieldValue.serverTimestamp() Documentation:** [https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents#FieldValue](https://firebase.google.com/docs/firestore/reference/rest/v1/projects.databases.documents#FieldValue)
96+
97+
98+
Copyrights (c) OpenRockets Open-source Network. Free to use, copy, share, edit or publish.
99+

0 commit comments

Comments
 (0)