mirror of
				https://github.com/cse110-fa22-group29/cse110-fa22-group29.git
				synced 2025-10-31 03:46:50 +00:00 
			
		
		
		
	Merge pull request #84 from cse110-fa22-group29/sprint-2-css-review-details
Sprint 2 css review details
This commit is contained in:
		| @@ -12,76 +12,93 @@ class ReviewCard extends HTMLElement { | ||||
|  | ||||
| 		let styleEl = document.createElement("style"); | ||||
| 		styleEl.textContent = ` | ||||
|       * { | ||||
|         font-family: sans-serif; | ||||
|         margin: 0; | ||||
|         padding: 0; | ||||
|       } | ||||
|      | ||||
|       a { | ||||
|         text-decoration: none; | ||||
|       } | ||||
|      | ||||
|       a:hover { | ||||
|         text-decoration: underline; | ||||
|       } | ||||
|      | ||||
|       article { | ||||
|         align-items: center; | ||||
|         border: 1px solid rgb(223, 225, 229); | ||||
|         border-radius: 8px; | ||||
|         display: grid; | ||||
|         grid-template-rows: 118px 56px 14px 18px 15px 36px; | ||||
|         height: auto; | ||||
|         row-gap: 5px; | ||||
|         padding: 0 16px 16px 16px; | ||||
|         width: 178px; | ||||
| 		margin: 8px 8px 8px 8px; | ||||
|       } | ||||
|      | ||||
|       div.rating { | ||||
|         align-items: center; | ||||
|         column-gap: 5px; | ||||
|         display: flex; | ||||
|       } | ||||
|      | ||||
|       div.rating>img { | ||||
|         height: auto; | ||||
|         display: inline-block; | ||||
|         object-fit: scale-down; | ||||
|         width: 78px; | ||||
|       } | ||||
|      | ||||
|       article>img { | ||||
|         border-top-left-radius: 8px; | ||||
|         border-top-right-radius: 8px; | ||||
|         height: 118px; | ||||
|         object-fit: cover; | ||||
|         margin-left: -16px; | ||||
|         width: calc(100% + 32px); | ||||
|       } | ||||
|      | ||||
|       label.restaurant-name { | ||||
|         color: black !important; | ||||
|       } | ||||
|      | ||||
|       label.meal-name { | ||||
|         display: -webkit-box; | ||||
|         font-size: 16px; | ||||
|         height: 36px; | ||||
|         line-height: 18px; | ||||
|         overflow: hidden; | ||||
|         -webkit-line-clamp: 2; | ||||
|         -webkit-box-orient: vertical; | ||||
|       } | ||||
|      | ||||
|       label:not(.meal-name), | ||||
|       span, | ||||
|       time { | ||||
|         color: #70757A; | ||||
|         font-size: 12px; | ||||
|       } | ||||
|     `; | ||||
| 		* { | ||||
| 			font-family: Century Gothic; | ||||
| 			margin: 0; | ||||
| 			padding: 0; | ||||
| 			overflow-wrap: anywhere; | ||||
| 		} | ||||
| 		 | ||||
| 		a { | ||||
| 			text-decoration: none; | ||||
| 		} | ||||
| 		 | ||||
| 		a:hover { | ||||
| 			text-decoration: underline; | ||||
| 		} | ||||
| 		 | ||||
| 		article { | ||||
| 			align-items: center; | ||||
| 			border: 2px solid rgb(31, 41, 32); | ||||
| 			border-radius: 8px; | ||||
| 			display: grid; | ||||
| 			grid-template-rows: 118px 56px 14px 18px 15px 36px; | ||||
| 			height: auto; | ||||
| 			row-gap: 5px; | ||||
| 			padding: 0 16px 16px 16px; | ||||
| 			width: 178px; | ||||
| 			margin: 8px 8px 8px 8px; | ||||
| 		} | ||||
| 		 | ||||
| 		div.rating { | ||||
| 			align-items: center; | ||||
| 			column-gap: 5px; | ||||
| 			display: flex; | ||||
| 		} | ||||
| 		 | ||||
| 		div.rating>img { | ||||
| 			height: auto; | ||||
| 			display: inline-block; | ||||
| 			object-fit: scale-down; | ||||
| 			width: 78px; | ||||
| 		} | ||||
| 		 | ||||
| 		article>img { | ||||
| 			border-top-left-radius: 6px; | ||||
| 			border-top-right-radius: 6px; | ||||
| 			height: 119px; | ||||
| 			object-fit: cover; | ||||
| 			margin-left: -16px; | ||||
| 			width: calc(100% + 32px); | ||||
| 		} | ||||
| 		 | ||||
| 		label.restaurant-name { | ||||
| 			color: black !important; | ||||
| 		} | ||||
| 		 | ||||
| 		label.meal-name { | ||||
| 			display: -webkit-box; | ||||
| 			font-size: 16px; | ||||
| 			height: 36px; | ||||
| 			line-height: 18px; | ||||
| 			overflow: hidden; | ||||
| 			-webkit-line-clamp: 2; | ||||
| 			-webkit-box-orient: vertical; | ||||
| 		} | ||||
| 		 | ||||
| 		label:not(.meal-name), | ||||
| 		span, | ||||
| 		time { | ||||
| 			color: #70757A; | ||||
| 			font-size: 12px; | ||||
| 		} | ||||
|  | ||||
| 		.tag-container { | ||||
| 			margin-top: 20px; | ||||
| 			display: flex; | ||||
| 			flex-flow: row wrap; | ||||
| 		} | ||||
| 		 | ||||
| 		.a-tag { | ||||
| 			background-color:#94da97; | ||||
| 			border-radius: 7px; | ||||
| 			color: #94da97; | ||||
| 			padding-right: 7px; | ||||
| 			padding-left: 7px; | ||||
| 			margin: 3px; | ||||
| 			font-weight: bold; | ||||
| 		} | ||||
|     	`; | ||||
| 		articleEl.append(styleEl); | ||||
| 		shadowEl.append(articleEl); | ||||
| 		this.shadowEl = shadowEl; | ||||
| @@ -117,7 +134,6 @@ class ReviewCard extends HTMLElement { | ||||
|    *                        following format: | ||||
|    *                        { | ||||
|    *                          "mealImg": "string", | ||||
|    *                          "imgAlt": "string", | ||||
|    *                          "mealName": "string", | ||||
|    *                          "comments": "string", | ||||
|    *                          "rating": number, | ||||
| @@ -138,13 +154,12 @@ class ReviewCard extends HTMLElement { | ||||
| 		//image setup | ||||
| 		let mealImg = document.createElement("img"); | ||||
| 		mealImg.setAttribute("id", "a-mealImg"); | ||||
| 		mealImg.setAttribute("alt",data["imgAlt"]); | ||||
| 		if(data["mealImg"] != ""){ | ||||
| 			mealImg.setAttribute("src",data["mealImg"]); | ||||
| 		} | ||||
| 		else{ | ||||
| 			mealImg.setAttribute("src", "./assets/images/icons/plate_with_cutlery.png"); | ||||
| 		} | ||||
| 		mealImg.setAttribute("alt","Meal Photo Corrupted"); | ||||
| 		mealImg.setAttribute("src",data["mealImg"]); | ||||
| 		mealImg.addEventListener("error", function(e) { | ||||
| 			mealImg.setAttribute("src", "./assets/images/plate_with_cutlery.png"); | ||||
| 			e.onerror = null; | ||||
| 		}); | ||||
|  | ||||
| 		//meal name setup | ||||
| 		let mealLabel = document.createElement("label"); | ||||
| @@ -169,7 +184,7 @@ class ReviewCard extends HTMLElement { | ||||
| 		ratingDiv.setAttribute("class", "rating"); | ||||
| 		let starsImg = document.createElement("img"); | ||||
| 		starsImg.setAttribute("id", "a-rating"); | ||||
| 		starsImg.setAttribute("src", "./assets/images/icons/"+data["rating"]+"-star.svg"); | ||||
| 		starsImg.setAttribute("src", "./assets/images/"+data["rating"]+"-star.svg"); | ||||
| 		starsImg.setAttribute("alt", data["rating"] +" stars"); | ||||
| 		starsImg.setAttribute("num", data["rating"]); | ||||
| 		ratingDiv.append(starsImg); | ||||
| @@ -182,7 +197,7 @@ class ReviewCard extends HTMLElement { | ||||
| 		if(data["tags"]){ | ||||
| 			for (let i = 0; i < data["tags"].length; i++) { | ||||
| 				let newTag = document.createElement("label"); | ||||
| 				newTag.setAttribute("class","tag"); | ||||
| 				newTag.setAttribute("class","a-tag"); | ||||
| 				newTag.innerHTML = data["tags"][i]; | ||||
| 				tagContainer.append(newTag); | ||||
| 			} | ||||
| @@ -211,7 +226,6 @@ class ReviewCard extends HTMLElement { | ||||
|    *                        following format: | ||||
|    *                        { | ||||
|    *                          "mealImg": "string", | ||||
|    *                          "imgAlt": "string", | ||||
|    *                          "mealName": "string", | ||||
|    *                          "comments": "string", | ||||
|    *                          "rating": number, | ||||
| @@ -229,7 +243,6 @@ class ReviewCard extends HTMLElement { | ||||
| 		//get image | ||||
| 		let mealImg = this.shadowEl.getElementById("a-mealImg"); | ||||
| 		dataContainer["mealImg"] = mealImg.getAttribute("src"); | ||||
| 		dataContainer["imgAlt"] = mealImg.getAttribute("alt"); | ||||
|  | ||||
| 		//get meal name | ||||
| 		let mealLabel = this.shadowEl.getElementById("a-mealName"); | ||||
|   | ||||
| @@ -16,41 +16,39 @@ function setupInfo(){ | ||||
| 	 | ||||
| 	//meal image | ||||
| 	let mealImg = document.getElementById("d-mealImg"); | ||||
| 	mealImg.setAttribute("alt", currReview["imgAlt"]); | ||||
| 	if(currReview["mealImg"] != ""){ | ||||
| 		mealImg.setAttribute("src",currReview["mealImg"]); | ||||
| 	} | ||||
| 	else{ | ||||
| 		mealImg.setAttribute("src", "./assets/images/icons/plate_with_cutlery.png"); | ||||
| 	} | ||||
| 	mealImg.setAttribute("src",currReview["mealImg"]); | ||||
| 	mealImg.addEventListener("error", function(e) { | ||||
| 		mealImg.setAttribute("src", "./assets/images/plate_with_cutlery.png"); | ||||
| 		e.onerror = null; | ||||
| 	}); | ||||
|  | ||||
| 	//meal name | ||||
| 	let mealLabel = document.getElementById("d-mealName"); | ||||
| 	mealLabel.innerHTML = currReview["mealName"]; | ||||
|  | ||||
| 	//restaurant name | ||||
| 	/*let restaurantLabel = document.getElementById("d-restaurant"); | ||||
| 	let restaurantLabel = document.getElementById("d-restaurant"); | ||||
| 	restaurantLabel.innerHTML = currReview["restaurant"]; | ||||
|  | ||||
| 	 | ||||
| 	//comments | ||||
| 	let comments = document.getElementById("d-comments"); | ||||
| 	comments.innerText = currReview["comments"]; | ||||
| 	*/ | ||||
|  | ||||
| 	//rating | ||||
| 	let starsImg = document.getElementById("d-rating"); | ||||
| 	starsImg.setAttribute("src", "./assets/images/icons/"+currReview["rating"]+"-star.svg"); | ||||
| 	starsImg.setAttribute("src", "./assets/images/"+currReview["rating"]+"-star.svg"); | ||||
| 	starsImg.setAttribute("alt", currReview["rating"] +" stars"); | ||||
| 	/* | ||||
| 	 | ||||
| 	//tags | ||||
| 	let tagContainer = document.getElementById("d-tags"); | ||||
| 	if(currReview["tags"]){ | ||||
| 		for (let i = 0; i < currReview["tags"].length; i++) { | ||||
| 			let newTag = document.createElement("label"); | ||||
| 			newTag.setAttribute("class","tag"); | ||||
| 			newTag.setAttribute("class","d-tag"); | ||||
| 			newTag.innerHTML = currReview["tags"][i]; | ||||
| 			tagContainer.append(newTag); | ||||
| 		} | ||||
| 	}*/ | ||||
| 	} | ||||
| } | ||||
|  | ||||
| function setupDelete(){ | ||||
| @@ -69,17 +67,17 @@ function setupUpdate(){ | ||||
| 	let updateBtn = document.getElementById("update-btn"); | ||||
| 	let currID = JSON.parse(sessionStorage.getItem("currID")); | ||||
| 	let currReview = getReviewFromStorage(currID); | ||||
| 	let form = document.getElementById("update-food-entry"); | ||||
| 	let updateDiv = document.getElementById("update-form-div"); | ||||
| 	let form = document.getElementById("new-food-entry"); | ||||
| 	let updateDiv = document.getElementById("update-form"); | ||||
| 	updateBtn.addEventListener("click", function(){ | ||||
| 		//update function | ||||
|  | ||||
| 		updateDiv.style.display = "block"; | ||||
| 		updateDiv.classList.remove("hidden"); | ||||
|  | ||||
| 		let tagContainer = document.getElementById("tag-container-form"); | ||||
|  | ||||
| 		//Set value of each input element to current's values | ||||
| 		document.getElementById("mealImg").defaultValue = currReview["mealImg"]; | ||||
| 		document.getElementById("imgAlt").defaultValue = currReview["imgAlt"]; | ||||
| 		document.getElementById("mealName").defaultValue = currReview["mealName"]; | ||||
| 		document.getElementById("comments").textContent = currReview["comments"]; | ||||
| 		document.getElementById("s" + `${currReview["rating"]}`).checked = true; | ||||
| @@ -173,7 +171,7 @@ function setupUpdate(){ | ||||
|  | ||||
| 			updateReviewToStorage(currID, newData); | ||||
|  | ||||
| 			form.style.display = "none"; | ||||
| 			updateDiv.classList.add("hidden"); | ||||
|  | ||||
| 		}); | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,6 @@ import {strict as assert} from "node:assert"; | ||||
| export async function setReviewForm(page, review) { | ||||
| 	 | ||||
| 	// Set text fields | ||||
| 	await page.$eval("#imgAlt", (el, value) => el.value = value, review.imgAlt); | ||||
| 	await page.$eval("#mealName", (el, value) => el.value = value, review.mealName); | ||||
| 	await page.$eval("#comments", (el, value) => el.value = value, review.comments); | ||||
| 	await page.$eval("#restaurant", (el, value) => el.value = value, review.restaurant); | ||||
| @@ -34,19 +33,17 @@ export async function setReviewForm(page, review) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Tests a page or shadowDOM for correct element text, src, or alt values | ||||
|  * Tests a page or shadowDOM for correct element text or src values | ||||
|  * @param {Object} root page or shodowDOM to test | ||||
|  * @param {string} prefix prefix character for element IDs | ||||
|  * @param {Object} expected values for eahc element | ||||
|  * @param {Object} expected values for each element | ||||
|  */ | ||||
| export async function checkCorrectness(root, prefix, expected){ | ||||
| 	// Get the review image and check src and alt | ||||
| 	// Get the review image and check src | ||||
| 	let img = await root.$(`#${prefix}-mealImg`); | ||||
| 	let imgSrc = await img.getProperty("src"); | ||||
| 	let imgAlt = await img.getProperty("alt"); | ||||
| 	// Check src and alt | ||||
| 	// Check src | ||||
| 	assert.strictEqual(await imgSrc.jsonValue(), expected.imgSrc); | ||||
| 	assert.strictEqual(await imgAlt.jsonValue(), expected.imgAlt); | ||||
|  | ||||
| 	// Get the title, comment, and restaurant | ||||
| 	let title = await root.$(`#${prefix}-mealName`); | ||||
| @@ -62,7 +59,7 @@ export async function checkCorrectness(root, prefix, expected){ | ||||
| 	assert.strictEqual(await restaurant_text.jsonValue(), expected.restaurant); | ||||
|  | ||||
| 	// Check tags | ||||
| 	let tags = await root.$$(".tag"); | ||||
| 	let tags = await root.$$(`.${prefix}-tag`); | ||||
| 	assert.strictEqual(await tags.length, expected.tags.length); | ||||
| 	for(let i = 0; i < expected.tags.length; i++){ | ||||
| 		let tag_text = await tags[i].getProperty("innerText"); | ||||
|   | ||||
| @@ -17,7 +17,6 @@ describe("test app localStorage interaction", () => { | ||||
| 	it("test localStorage state after adding one review", () => { | ||||
| 		let review = { | ||||
| 			"imgSrc": "sample src", | ||||
| 			"imgAlt": "sample alt", | ||||
| 			"mealName": "sample name", | ||||
| 			"restaurant": "sample restaurant", | ||||
| 			"rating": 5, | ||||
| @@ -42,7 +41,6 @@ describe("test app localStorage interaction", () => { | ||||
| 			ids.push(i); | ||||
| 			let new_review = { | ||||
| 				"imgSrc": `sample src ${i}`, | ||||
| 				"imgAlt": `sample alt ${i}`, | ||||
| 				"mealName": `sample name ${i}`, | ||||
| 				"restaurant": `sample restaurant ${i}`, | ||||
| 				"rating": i, | ||||
| @@ -68,7 +66,6 @@ describe("test app localStorage interaction", () => { | ||||
| 		for(let i = 0; i < 1000; i++){ | ||||
| 			let new_review = { | ||||
| 				"imgSrc": `updated sample src ${i}`, | ||||
| 				"imgAlt": `updated sample alt ${i}`, | ||||
| 				"mealName": `updated sample name ${i}`, | ||||
| 				"restaurant": `updated sample restaurant ${i}`, | ||||
| 				"rating": i*2+i, | ||||
|   | ||||
| @@ -48,7 +48,6 @@ describe("test App end to end", async () => { | ||||
|  | ||||
| 				// create a new review | ||||
| 				let review = { | ||||
| 					imgAlt: "sample alt", | ||||
| 					mealName: "sample name", | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| @@ -66,13 +65,12 @@ describe("test App end to end", async () => { | ||||
| 			it("check details page", async () => { | ||||
| 				// check the details page for correctness | ||||
| 				let expected = { | ||||
| 					imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", | ||||
| 					imgAlt: "sample alt", | ||||
| 					imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", | ||||
| 					mealName: "sample name", | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: "http://localhost:8080/assets/images/icons/1-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg" | ||||
| 				}; | ||||
| 				await checkCorrectness(page, "d", expected); | ||||
| 			}); | ||||
| @@ -88,13 +86,12 @@ describe("test App end to end", async () => { | ||||
| 				let shadowRoot = await review_card.getProperty("shadowRoot"); | ||||
|  | ||||
| 				let expected = { | ||||
| 					imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", | ||||
| 					imgAlt: "sample alt", | ||||
| 					imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", | ||||
| 					mealName: "sample name", | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: "http://localhost:8080/assets/images/icons/1-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg" | ||||
| 				}; | ||||
| 				await checkCorrectness(shadowRoot, "a", expected); | ||||
| 			}); | ||||
| @@ -114,13 +111,12 @@ describe("test App end to end", async () => { | ||||
|  | ||||
| 				// check the details page for correctness | ||||
| 				let expected = { | ||||
| 					imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", | ||||
| 					imgAlt: "sample alt", | ||||
| 					imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", | ||||
| 					mealName: "sample name", | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: "http://localhost:8080/assets/images/icons/1-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg" | ||||
| 				}; | ||||
| 				await checkCorrectness(page, "d", expected); | ||||
| 			}); | ||||
| @@ -137,13 +133,12 @@ describe("test App end to end", async () => { | ||||
|  | ||||
| 				// check the details page for correctness | ||||
| 				let expected = { | ||||
| 					imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", | ||||
| 					imgAlt: "sample alt", | ||||
| 					imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", | ||||
| 					mealName: "sample name", | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: "http://localhost:8080/assets/images/icons/1-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg" | ||||
| 				}; | ||||
| 				await checkCorrectness(shadowRoot, "a", expected); | ||||
| 			}); | ||||
| @@ -164,7 +159,6 @@ describe("test App end to end", async () => { | ||||
|  | ||||
| 				// create a new review | ||||
| 				let review = { | ||||
| 					imgAlt: "updated alt", | ||||
| 					mealName: "updated name", | ||||
| 					comments: "updated comment", | ||||
| 					restaurant: "updated restaurant", | ||||
| @@ -182,13 +176,12 @@ describe("test App end to end", async () => { | ||||
| 			it("check details page", async () => { | ||||
| 				// check the details page for correctness | ||||
| 				let expected = { | ||||
| 					imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", | ||||
| 					imgAlt: "updated alt", | ||||
| 					imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", | ||||
| 					mealName: "updated name", | ||||
| 					comments: "updated comment", | ||||
| 					restaurant: "updated restaurant", | ||||
| 					tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], | ||||
| 					rating: "http://localhost:8080/assets/images/icons/5-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/5-star.svg" | ||||
| 				}; | ||||
| 				await checkCorrectness(page, "d", expected); | ||||
| 			}); | ||||
| @@ -205,13 +198,12 @@ describe("test App end to end", async () => { | ||||
|  | ||||
| 				// check the details page for correctness | ||||
| 				let expected = { | ||||
| 					imgSrc: "http://localhost:8080/assets/images/icons/plate_with_cutlery.png", | ||||
| 					imgAlt: "updated alt", | ||||
| 					imgSrc: "http://localhost:8080/assets/images/plate_with_cutlery.png", | ||||
| 					mealName: "updated name", | ||||
| 					comments: "updated comment", | ||||
| 					restaurant: "updated restaurant", | ||||
| 					tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], | ||||
| 					rating: "http://localhost:8080/assets/images/icons/5-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/5-star.svg" | ||||
| 				}; | ||||
| 				await checkCorrectness(shadowRoot, "a", expected); | ||||
| 			}); | ||||
|   | ||||
| @@ -18,12 +18,12 @@ function init() { | ||||
|  * @param {Array<Object>} reviews An array of reviews | ||||
|  */ | ||||
| function addReviewsToDocument(reviews) { | ||||
| 	let box = document.getElementById("review-container"); | ||||
| 	let reviewBox = document.getElementById("review-container"); | ||||
| 	reviews.forEach(review => { | ||||
| 		let newReview = document.createElement("review-card"); | ||||
| 		newReview.data = review; | ||||
| 		//TODO: want to append it to whatever the box is in layout  | ||||
| 		box.append(newReview); | ||||
| 		reviewBox.append(newReview); | ||||
| 	}); | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user