mirror of
				https://github.com/cse110-fa22-group29/cse110-fa22-group29.git
				synced 2025-10-31 03:46:50 +00:00 
			
		
		
		
	| @@ -13,27 +13,26 @@ function init() { | ||||
|  * Creates a form and associates a new ID with the new review card. | ||||
|  */ | ||||
| function initFormHandler() { | ||||
|  | ||||
| 	// Accesses form components | ||||
| 	let tagContainer = document.getElementById("tag-container-form"); | ||||
| 	let form = document.querySelector("form"); | ||||
| 	 | ||||
|  | ||||
| 	// Declaring variable storing image data url | ||||
| 	let imgDataURL = ""; | ||||
| 	 | ||||
|  | ||||
| 	// Accessing components related to taking photo | ||||
| 	let videoMode = true; | ||||
| 	let player = document.getElementById("player"); | ||||
| 	let canvas = document.getElementById("photoCanvas"); | ||||
| 	let photoButton = document.getElementById("photoButton"); | ||||
| 	let context = canvas.getContext('2d'); | ||||
| 	let context = canvas.getContext("2d"); | ||||
|  | ||||
| 	// Event listener for the photo taking/reset button | ||||
| 	photoButton.addEventListener('click', ()=>{ | ||||
| 	photoButton.addEventListener("click", () => { | ||||
| 		// capturing the current video frame | ||||
| 		if (videoMode) { | ||||
| 			videoMode = false; | ||||
| 			 | ||||
|  | ||||
| 			// setting up the appropriate components for displaying the photo preview | ||||
| 			photoButton.innerText = "Retake"; | ||||
| 			player.setAttribute("hidden", ""); | ||||
| @@ -57,7 +56,7 @@ function initFormHandler() { | ||||
| 	// Event listener for reading image form different data | ||||
| 	let select = document.getElementById("select"); | ||||
| 	const input = document.getElementById("mealImg"); | ||||
| 	select.addEventListener("change", function() { | ||||
| 	select.addEventListener("change", function () { | ||||
| 		// Select a photo with HTML file selector | ||||
| 		if (select.value == "file") { | ||||
| 			// enabling file upload components and hiding photo taking components | ||||
| @@ -80,27 +79,30 @@ function initFormHandler() { | ||||
| 			photoButton.removeAttribute("hidden", ""); | ||||
|  | ||||
| 			// getting video stream from user's camera then displaying it on a video element | ||||
| 			navigator.mediaDevices.getUserMedia({video: true,}).then((stream)=>{ | ||||
| 			navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => { | ||||
| 				player.srcObject = stream; | ||||
| 			}); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	// Addresses sourcing image from local file | ||||
| 	document.getElementById("mealImg").addEventListener("change", function() { | ||||
| 	document.getElementById("mealImg").addEventListener("change", function () { | ||||
| 		const reader = new FileReader(); | ||||
| 		 | ||||
|  | ||||
| 		// Store image data URL after successful image load | ||||
| 		reader.addEventListener("load", ()=>{ | ||||
| 			imgDataURL = reader.result; | ||||
| 		}, false); | ||||
| 		 | ||||
| 		reader.addEventListener( | ||||
| 			"load", | ||||
| 			() => { | ||||
| 				imgDataURL = reader.result; | ||||
| 			}, | ||||
| 			false | ||||
| 		); | ||||
|  | ||||
| 		// Convert image file into data URL for local storage | ||||
| 		reader.readAsDataURL(document.getElementById("mealImg").files[0]); | ||||
| 	}); | ||||
|  | ||||
| 	form.addEventListener("submit", function(e){ | ||||
|  | ||||
| 	form.addEventListener("submit", function (e) { | ||||
| 		// Create reviewObject and put in storage | ||||
| 		e.preventDefault(); | ||||
| 		let formData = new FormData(form); | ||||
| @@ -119,14 +121,13 @@ function initFormHandler() { | ||||
| 		} | ||||
|  | ||||
| 		// Makes sure that ratings is filled | ||||
| 		if(reviewObject["rating"] != null){ | ||||
|  | ||||
| 		if (reviewObject["rating"] != null) { | ||||
| 			//Adds rags separately as an array | ||||
| 			reviewObject["tags"] = []; | ||||
|  | ||||
| 			// Grabs tags | ||||
| 			let tags = document.querySelectorAll(".tag"); | ||||
| 			for(let i = 0; i < tags.length; i ++) { | ||||
| 			for (let i = 0; i < tags.length; i++) { | ||||
| 				reviewObject["tags"].push(tags[i].innerHTML); | ||||
| 				tagContainer.removeChild(tags[i]); | ||||
| 			} | ||||
| @@ -134,43 +135,41 @@ function initFormHandler() { | ||||
| 			// Assigns the new review with a new ID | ||||
| 			let nextReviewId = newReviewToStorage(reviewObject); | ||||
| 			sessionStorage.setItem("currID", JSON.stringify(nextReviewId)); | ||||
| 			 | ||||
|  | ||||
| 			// Redirects to a page that shows the newly created review | ||||
| 			window.location.assign("./ReviewDetails.html"); | ||||
| 		}  | ||||
| 		} | ||||
| 		// Does not let user proceed if rating is not complete | ||||
| 		else{ | ||||
| 		else { | ||||
| 			window.alert("NO! FILL IN STARS"); | ||||
| 		} | ||||
|          | ||||
| 	}); | ||||
|  | ||||
| 	// Event listener for tag functionality | ||||
| 	let tagAddBtn = document.getElementById("tag-add-btn"); | ||||
| 	//Set used to track tags and ensure no duplicates | ||||
| 	let tagSet = new Set(); | ||||
| 	tagAddBtn.addEventListener("click", ()=> { | ||||
| 	tagAddBtn.addEventListener("click", () => { | ||||
| 		let tagField = document.getElementById("tag-form"); | ||||
|  | ||||
| 		// If there is a tag, it'll display the tag | ||||
| 		if (tagField.value.length > 0) { | ||||
| 			let tagSetVal = tagField.value.toLowerCase(); | ||||
| 			if (!tagSet.has(tagSetVal)){ | ||||
| 			if (!tagSet.has(tagSetVal)) { | ||||
| 				let tagLabel = document.createElement("label"); | ||||
| 				tagLabel.innerHTML = tagField.value; | ||||
| 				tagLabel.setAttribute("class","tag"); | ||||
| 				tagLabel.setAttribute("class", "tag"); | ||||
| 				tagSet.add(tagSetVal); | ||||
| 				tagLabel.addEventListener("click",()=> { | ||||
| 				tagLabel.addEventListener("click", () => { | ||||
| 					tagContainer.removeChild(tagLabel); | ||||
| 					tagSet.delete(tagSetVal); | ||||
| 				}); | ||||
| 		 | ||||
|  | ||||
| 				tagContainer.append(tagLabel); | ||||
| 			} else { | ||||
| 				window.alert("No duplicate tags allowed"); | ||||
| 			} | ||||
| 			tagField.value = ""; | ||||
| 		} | ||||
| 	});		 | ||||
|  | ||||
| 	}); | ||||
| } | ||||
|   | ||||
| @@ -4,9 +4,9 @@ class ReviewCard extends HTMLElement { | ||||
| 	// Called once when document.createElement('review-card') is called, or | ||||
| 	// the element is written into the DOM directly as <review-card> | ||||
| 	constructor() { | ||||
| 		super();  | ||||
| 		super(); | ||||
|  | ||||
| 		let shadowEl = this.attachShadow({mode:"open"}); | ||||
| 		let shadowEl = this.attachShadow({ mode: "open" }); | ||||
|  | ||||
| 		let articleEl = document.createElement("article"); | ||||
|  | ||||
| @@ -106,7 +106,7 @@ class ReviewCard extends HTMLElement { | ||||
| 		articleEl.append(styleEl); | ||||
| 		shadowEl.append(articleEl); | ||||
| 		this.shadowEl = shadowEl; | ||||
| 		 | ||||
|  | ||||
| 		// Attach event listener to each review-card | ||||
| 		this.addEventListener("click", (event) => { | ||||
| 			console.log(event.target); | ||||
| @@ -119,40 +119,40 @@ class ReviewCard extends HTMLElement { | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	* Called when the .data property is set on this element. | ||||
| 	* | ||||
| 	* For Example: | ||||
| 	* let reviewCard = document.createElement('review-card');  | ||||
| 	* reviewCard.data = { foo: 'bar' }  | ||||
| 	* | ||||
| 	* @param {Object} data - The data to pass into the <review-card>, must be of the | ||||
| 	*                        following format: | ||||
| 	*                        { | ||||
| 	*                          "mealImg": string, | ||||
| 	*                          "mealName": string, | ||||
| 	*                          "comments": string, | ||||
| 	*                          "rating": number, | ||||
| 	*                          "restaurant": string, | ||||
| 	*                          "reviewID": number, | ||||
| 	*                          "tags": string array | ||||
| 	*                        } | ||||
| 	*/ | ||||
| 	 * Called when the .data property is set on this element. | ||||
| 	 * | ||||
| 	 * For Example: | ||||
| 	 * let reviewCard = document.createElement('review-card'); | ||||
| 	 * reviewCard.data = { foo: 'bar' } | ||||
| 	 * | ||||
| 	 * @param {Object} data - The data to pass into the <review-card>, must be of the | ||||
| 	 *                        following format: | ||||
| 	 *                        { | ||||
| 	 *                          "mealImg": string, | ||||
| 	 *                          "mealName": string, | ||||
| 	 *                          "comments": string, | ||||
| 	 *                          "rating": number, | ||||
| 	 *                          "restaurant": string, | ||||
| 	 *                          "reviewID": number, | ||||
| 	 *                          "tags": string array | ||||
| 	 *                        } | ||||
| 	 */ | ||||
| 	set data(data) { | ||||
| 		// If nothing was passed in, return | ||||
| 		if (!data) return; | ||||
|  | ||||
| 		// Select the <article> we added to the Shadow DOM in the constructor | ||||
| 		let articleEl = this.shadowEl.querySelector("article"); | ||||
|      | ||||
|  | ||||
| 		// Setting the article elements for the review card | ||||
| 		this.reviewID = data["reviewID"]; | ||||
|  | ||||
| 		// Image setup | ||||
| 		let mealImg = document.createElement("img"); | ||||
| 		mealImg.setAttribute("id", "a-meal-img"); | ||||
| 		mealImg.setAttribute("alt","Meal Photo Corrupted"); | ||||
| 		mealImg.setAttribute("src",data["mealImg"]); | ||||
| 		mealImg.addEventListener("error", function(e) { | ||||
| 		mealImg.setAttribute("alt", "Meal Photo Corrupted"); | ||||
| 		mealImg.setAttribute("src", data["mealImg"]); | ||||
| 		mealImg.addEventListener("error", function (e) { | ||||
| 			mealImg.setAttribute("src", "./assets/images/default_plate.png"); | ||||
| 			e.onerror = null; | ||||
| 		}); | ||||
| @@ -162,14 +162,14 @@ class ReviewCard extends HTMLElement { | ||||
| 		meallabelDiv.setAttribute("class", "meal-name-div"); | ||||
| 		let mealLabel = document.createElement("label"); | ||||
| 		mealLabel.setAttribute("id", "a-meal-name"); | ||||
| 		mealLabel.setAttribute("class","meal-name"); | ||||
| 		mealLabel.setAttribute("class", "meal-name"); | ||||
| 		mealLabel.innerHTML = data["mealName"]; | ||||
| 		meallabelDiv.append(mealLabel); | ||||
|  | ||||
| 		// Restaurant name setup | ||||
| 		let restaurantLabel = document.createElement("label"); | ||||
| 		restaurantLabel.setAttribute("id", "a-restaurant"); | ||||
| 		restaurantLabel.setAttribute("class","restaurant-name"); | ||||
| 		restaurantLabel.setAttribute("class", "restaurant-name"); | ||||
| 		restaurantLabel.innerHTML = data["restaurant"]; | ||||
|  | ||||
| 		// Comment section setup (display set to none) | ||||
| @@ -183,13 +183,13 @@ class ReviewCard extends HTMLElement { | ||||
| 		ratingDiv.setAttribute("class", "rating"); | ||||
| 		let starsImg = document.createElement("img"); | ||||
| 		starsImg.setAttribute("id", "a-rating"); | ||||
| 		starsImg.setAttribute("src", "./assets/images/"+data["rating"]+"-star.svg"); | ||||
| 		starsImg.setAttribute("alt", data["rating"] +" stars"); | ||||
| 		starsImg.setAttribute("src", "./assets/images/" + data["rating"] + "-star.svg"); | ||||
| 		starsImg.setAttribute("alt", data["rating"] + " stars"); | ||||
| 		starsImg.setAttribute("num", data["rating"]); | ||||
| 		ratingDiv.append(starsImg); | ||||
|  | ||||
| 		// Tags setup | ||||
| 		let tagContainerDiv = document.createElement("div");  | ||||
| 		let tagContainerDiv = document.createElement("div"); | ||||
| 		tagContainerDiv.setAttribute("class", "tag-container-div"); | ||||
| 		let tagContainer = document.createElement("div"); | ||||
| 		tagContainer.setAttribute("class", "tag-container"); | ||||
| @@ -197,10 +197,10 @@ class ReviewCard extends HTMLElement { | ||||
| 		tagContainer.setAttribute("list", data["tags"]); | ||||
|  | ||||
| 		// Checks if user gave tags, if so added to review card | ||||
| 		if(data["tags"]){ | ||||
| 		if (data["tags"]) { | ||||
| 			for (let i = 0; i < data["tags"].length; i++) { | ||||
| 				let newTag = document.createElement("label"); | ||||
| 				newTag.setAttribute("class","a-tag"); | ||||
| 				newTag.setAttribute("class", "a-tag"); | ||||
| 				newTag.innerHTML = data["tags"][i]; | ||||
| 				tagContainer.append(newTag); | ||||
| 			} | ||||
| @@ -214,33 +214,30 @@ class ReviewCard extends HTMLElement { | ||||
| 		articleEl.append(ratingDiv); | ||||
| 		articleEl.append(tagContainerDiv); | ||||
| 		articleEl.append(comments); | ||||
|  | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	* Called when getting the .data property of this element. | ||||
| 	* | ||||
| 	* For Example: | ||||
| 	* let reviewCard = document.createElement('review-card');  | ||||
| 	* reviewCard.data = { foo: 'bar' }  | ||||
| 	* | ||||
| 	* @return {Object} data - The data from the <review-card>, of the | ||||
| 	*                        following format: | ||||
| 	*                        { | ||||
| 	*                          "mealImg": string, | ||||
| 	*                          "mealName": string, | ||||
| 	*                          "comments": string, | ||||
| 	*                          "rating": number, | ||||
| 	*                          "restaurant": string, | ||||
| 	*                          "reviewID": number, | ||||
| 	*                          "tags": string array | ||||
| 	*                        } | ||||
| 	*/ | ||||
| 	 * Called when getting the .data property of this element. | ||||
| 	 * | ||||
| 	 * For Example: | ||||
| 	 * let reviewCard = document.createElement('review-card'); | ||||
| 	 * reviewCard.data = { foo: 'bar' } | ||||
| 	 * | ||||
| 	 * @return {Object} data - The data from the <review-card>, of the | ||||
| 	 *                        following format: | ||||
| 	 *                        { | ||||
| 	 *                          "mealImg": string, | ||||
| 	 *                          "mealName": string, | ||||
| 	 *                          "comments": string, | ||||
| 	 *                          "rating": number, | ||||
| 	 *                          "restaurant": string, | ||||
| 	 *                          "reviewID": number, | ||||
| 	 *                          "tags": string array | ||||
| 	 *                        } | ||||
| 	 */ | ||||
| 	get data() { | ||||
|  | ||||
| 		let dataContainer = {}; | ||||
|      | ||||
|  | ||||
| 		// Getting the article elements for the review card | ||||
| 		dataContainer["reviewID"] = this.reviewID; | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| //reviewDetails.js | ||||
| import {deleteReviewFromStorage, getReviewFromStorage, updateReviewToStorage} from "./localStorage.js"; | ||||
| import { deleteReviewFromStorage, getReviewFromStorage, updateReviewToStorage } from "./localStorage.js"; | ||||
|  | ||||
| // Run the init() function when the page has loaded | ||||
| window.addEventListener("DOMContentLoaded", init); | ||||
| @@ -7,7 +7,7 @@ window.addEventListener("DOMContentLoaded", init); | ||||
| /** | ||||
|  * Populates the relevant data to the details from local storage review. | ||||
|  */ | ||||
| function init(){ | ||||
| function init() { | ||||
| 	setupInfo(); | ||||
| 	setupDelete(); | ||||
| 	setupUpdate(); | ||||
| @@ -16,14 +16,14 @@ function init(){ | ||||
| /** | ||||
|  * Populates the relevant data to the details from local storage review | ||||
|  */ | ||||
| function setupInfo(){ | ||||
| function setupInfo() { | ||||
| 	let currID = JSON.parse(sessionStorage.getItem("currID")); | ||||
| 	let currReview = getReviewFromStorage(currID); | ||||
| 	 | ||||
|  | ||||
| 	//meal image | ||||
| 	let mealImg = document.getElementById("d-meal-img"); | ||||
| 	mealImg.setAttribute("src",currReview["mealImg"]); | ||||
| 	mealImg.addEventListener("error", function(e) { | ||||
| 	mealImg.setAttribute("src", currReview["mealImg"]); | ||||
| 	mealImg.addEventListener("error", function (e) { | ||||
| 		mealImg.setAttribute("src", "./assets/images/default_plate.png"); | ||||
| 		e.onerror = null; | ||||
| 	}); | ||||
| @@ -35,22 +35,22 @@ function setupInfo(){ | ||||
| 	//restaurant name | ||||
| 	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/"+currReview["rating"]+"-star.svg"); | ||||
| 	starsImg.setAttribute("alt", currReview["rating"] +" stars"); | ||||
| 	 | ||||
| 	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"]){ | ||||
| 	if (currReview["tags"]) { | ||||
| 		for (let i = 0; i < currReview["tags"].length; i++) { | ||||
| 			let newTag = document.createElement("label"); | ||||
| 			newTag.setAttribute("class","d-tag"); | ||||
| 			newTag.setAttribute("class", "d-tag"); | ||||
| 			newTag.innerHTML = currReview["tags"][i]; | ||||
| 			tagContainer.append(newTag); | ||||
| 		} | ||||
| @@ -60,11 +60,11 @@ function setupInfo(){ | ||||
| /** | ||||
|  * Sets up delete button to delete reveiw from storage and switch to homepage. | ||||
|  */ | ||||
| function setupDelete(){ | ||||
| function setupDelete() { | ||||
| 	let deleteBtn = document.getElementById("delete-btn"); | ||||
| 	let currID = JSON.parse(sessionStorage.getItem("currID")); | ||||
| 	deleteBtn.addEventListener("click", function(){ | ||||
| 		if(window.confirm("Are you sure you want to delete this entry?")){ | ||||
| 	deleteBtn.addEventListener("click", function () { | ||||
| 		if (window.confirm("Are you sure you want to delete this entry?")) { | ||||
| 			deleteReviewFromStorage(currID); | ||||
| 			sessionStorage.removeItem("currID"); | ||||
| 			window.location.assign("./index.html"); | ||||
| @@ -75,13 +75,13 @@ function setupDelete(){ | ||||
| /** | ||||
|  * Sets up update button to reveal form and update info in storage and the current page. | ||||
|  */ | ||||
| function setupUpdate(){ | ||||
| function setupUpdate() { | ||||
| 	let updateBtn = document.getElementById("update-btn"); | ||||
| 	let currID = JSON.parse(sessionStorage.getItem("currID")); | ||||
| 	let currReview = getReviewFromStorage(currID); | ||||
| 	let form = document.getElementById("new-food-entry"); | ||||
| 	let updateDiv = document.getElementById("update-form"); | ||||
| 	updateBtn.addEventListener("click", function(){ | ||||
| 	updateBtn.addEventListener("click", function () { | ||||
| 		//update function | ||||
|  | ||||
| 		updateDiv.classList.remove("hidden"); | ||||
| @@ -98,26 +98,26 @@ function setupUpdate(){ | ||||
| 		//Set used to track tags and ensure no duplicates | ||||
| 		let tagSet = new Set(); | ||||
|  | ||||
| 		if(currReview["tags"]){ | ||||
| 		if (currReview["tags"]) { | ||||
| 			while (tagContainer.firstChild) { | ||||
| 				tagContainer.removeChild(tagContainer.firstChild); | ||||
| 			} | ||||
|        | ||||
|  | ||||
| 			let tagSetVal; | ||||
| 			for (let i = 0; i < currReview["tags"].length; i++) { | ||||
| 				tagSetVal = currReview["tags"][i].toLowerCase(); | ||||
| 				tagSet.add(tagSetVal); | ||||
| 				let newTag = document.createElement("label"); | ||||
| 				newTag.setAttribute("class","tag"); | ||||
| 				newTag.setAttribute("class", "tag"); | ||||
| 				newTag.innerHTML = currReview["tags"][i]; | ||||
| 				newTag.addEventListener("click",()=> { | ||||
| 				newTag.addEventListener("click", () => { | ||||
| 					tagContainer.removeChild(newTag); | ||||
| 					tagSet.delete(tagSetVal); | ||||
| 				}); | ||||
| 				tagContainer.append(newTag); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		// Declaring variable storing image data url | ||||
| 		let imgDataURL = ""; | ||||
|  | ||||
| @@ -126,14 +126,14 @@ function setupUpdate(){ | ||||
| 		let player = document.getElementById("player"); | ||||
| 		let canvas = document.getElementById("photoCanvas"); | ||||
| 		let photoButton = document.getElementById("photoButton"); | ||||
| 		let context = canvas.getContext('2d'); | ||||
| 		let context = canvas.getContext("2d"); | ||||
|  | ||||
| 		// Event listener for the photo taking/reset button | ||||
| 		photoButton.addEventListener('click', ()=>{ | ||||
| 		photoButton.addEventListener("click", () => { | ||||
| 			// capturing the current video frame | ||||
| 			if (videoMode) { | ||||
| 				videoMode = false; | ||||
| 				 | ||||
|  | ||||
| 				// setting up the appropriate components for displaying the photo preview | ||||
| 				photoButton.innerText = "Retake"; | ||||
| 				player.setAttribute("hidden", ""); | ||||
| @@ -155,25 +155,25 @@ function setupUpdate(){ | ||||
| 		}); | ||||
|  | ||||
| 		/* | ||||
| 		* change the input source of the image between local file and taking photo  | ||||
| 		* depending on user's selection | ||||
| 		*/ | ||||
| 		 * change the input source of the image between local file and taking photo | ||||
| 		 * depending on user's selection | ||||
| 		 */ | ||||
| 		let select = document.getElementById("select"); | ||||
| 		const input = document.getElementById("mealImg"); | ||||
| 		select.addEventListener("change", function() { | ||||
| 		select.addEventListener("change", function () { | ||||
| 			console.log("1"); | ||||
| 			// Select a photo with HTML file selector		 | ||||
| 			// Select a photo with HTML file selector | ||||
| 			if (select.value == "file") { | ||||
| 				// enabling file upload components and hiding photo taking components | ||||
| 				input.removeAttribute("hidden", ""); | ||||
| 				player.setAttribute("hidden", ""); | ||||
| 				canvas.setAttribute("hidden", ""); | ||||
| 				photoButton.setAttribute("hidden", ""); | ||||
| 	 | ||||
|  | ||||
| 				// stopping the video stream | ||||
| 				player.srcObject.getVideoTracks()[0].stop(); | ||||
| 			} | ||||
| 	 | ||||
|  | ||||
| 			// Take a photo | ||||
| 			else { | ||||
| 				// enabling photo taking components and hiding file upload components | ||||
| @@ -182,35 +182,38 @@ function setupUpdate(){ | ||||
| 				input.setAttribute("hidden", ""); | ||||
| 				player.removeAttribute("hidden", ""); | ||||
| 				photoButton.removeAttribute("hidden", ""); | ||||
| 	 | ||||
|  | ||||
| 				// getting video stream from user's camera then displaying it on a video element | ||||
| 				navigator.mediaDevices.getUserMedia({video: true,}).then((stream)=>{ | ||||
| 				navigator.mediaDevices.getUserMedia({ video: true }).then((stream) => { | ||||
| 					player.srcObject = stream; | ||||
| 				}); | ||||
| 			} | ||||
| 		}); | ||||
|  | ||||
| 		//addressing sourcing image from local file | ||||
| 		document.getElementById("mealImg").addEventListener("change", function() { | ||||
| 		document.getElementById("mealImg").addEventListener("change", function () { | ||||
| 			console.log("reading used"); | ||||
| 			const reader = new FileReader(); | ||||
| 			 | ||||
|  | ||||
| 			//store image data URL after successful image load | ||||
| 			reader.addEventListener("load", ()=>{ | ||||
| 				imgDataURL = reader.result; | ||||
| 			}, false); | ||||
| 			 | ||||
| 			reader.addEventListener( | ||||
| 				"load", | ||||
| 				() => { | ||||
| 					imgDataURL = reader.result; | ||||
| 				}, | ||||
| 				false | ||||
| 			); | ||||
|  | ||||
| 			//convert image file into data URL for local storage | ||||
| 			reader.readAsDataURL(document.getElementById("mealImg").files[0]); | ||||
| 		}); | ||||
|  | ||||
| 		 | ||||
| 		//Take formdata values as newData when submit | ||||
| 		form.addEventListener("submit", function(){ | ||||
| 		form.addEventListener("submit", function () { | ||||
| 			/* | ||||
| 			*  User submits the form for their review. | ||||
| 			*  We create reviewCard data, replace in storage, and update tags | ||||
| 			*/ | ||||
| 			 *  User submits the form for their review. | ||||
| 			 *  We create reviewCard data, replace in storage, and update tags | ||||
| 			 */ | ||||
| 			let formData = new FormData(form); | ||||
| 			let newData = {}; | ||||
| 			//iterate through formData and add to newData | ||||
| @@ -223,43 +226,41 @@ function setupUpdate(){ | ||||
| 				// Account for the case where image is not updated | ||||
| 				if (`${key}` === "mealImg" && imgDataURL === "") { | ||||
| 					newData["mealImg"] = currReview["mealImg"]; | ||||
| 				} | ||||
| 				else if (`${key}` === "mealImg") { | ||||
| 				} else if (`${key}` === "mealImg") { | ||||
| 					newData["mealImg"] = imgDataURL; | ||||
| 				} | ||||
| 			} | ||||
| 			newData["tags"] = []; | ||||
| 		 | ||||
|  | ||||
| 			let tags = document.querySelectorAll(".tag"); | ||||
| 			for(let i = 0; i < tags.length; i ++) { | ||||
| 			for (let i = 0; i < tags.length; i++) { | ||||
| 				newData["tags"].push(tags[i].innerHTML); | ||||
| 				tagContainer.removeChild(tags[i]); | ||||
| 			} | ||||
|  | ||||
| 			newData["reviewID"] = currID; | ||||
| 			 | ||||
|  | ||||
| 			updateReviewToStorage(currID, newData); | ||||
|  | ||||
| 			updateDiv.classList.add("hidden"); | ||||
|  | ||||
| 		}); | ||||
|  | ||||
| 		// Adding tag to form functionality | ||||
| 		let tagAddBtn = document.getElementById("tag-add-btn"); | ||||
| 		tagAddBtn.addEventListener("click", ()=> { | ||||
| 		tagAddBtn.addEventListener("click", () => { | ||||
| 			let tagField = document.getElementById("tag-form"); | ||||
| 			if (tagField.value.length > 0) { | ||||
| 				let tagSetVal = tagField.value.toLowerCase(); | ||||
| 				if (!tagSet.has(tagSetVal)){ | ||||
| 				if (!tagSet.has(tagSetVal)) { | ||||
| 					let tagLabel = document.createElement("label"); | ||||
| 					tagLabel.innerHTML = tagField.value; | ||||
| 					tagLabel.setAttribute("class","tag"); | ||||
| 					tagLabel.setAttribute("class", "tag"); | ||||
| 					tagSet.add(tagSetVal); | ||||
| 					tagLabel.addEventListener("click",()=> { | ||||
| 					tagLabel.addEventListener("click", () => { | ||||
| 						tagContainer.removeChild(tagLabel); | ||||
| 						tagSet.delete(tagSetVal); | ||||
| 					}); | ||||
| 			 | ||||
|  | ||||
| 					tagContainer.append(tagLabel); | ||||
| 				} else { | ||||
| 					window.alert("No duplicate tags allowed"); | ||||
|   | ||||
| @@ -1,35 +1,34 @@ | ||||
| import {strict as assert} from "node:assert"; | ||||
| import { strict as assert } from "node:assert"; | ||||
|  | ||||
| /** | ||||
|  * Fills out a create or update review form | ||||
|  * @param {Object} page the page object which contains the create or update form | ||||
|  * @param {Object} review review data to input into the form  | ||||
|  * @param {Object} review review data to input into the form | ||||
|  */ | ||||
| export async function setReviewForm(page, review) { | ||||
| 	 | ||||
| 	// Set text fields | ||||
| 	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); | ||||
| 	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); | ||||
|  | ||||
| 	// Get all tag elements and click them to delete them | ||||
| 	let tag_items = await page.$$(".tag"); | ||||
| 	if(tag_items !== null){ | ||||
| 		for(let i = 0; i < tag_items.length; i++){ | ||||
| 	if (tag_items !== null) { | ||||
| 		for (let i = 0; i < tag_items.length; i++) { | ||||
| 			await tag_items[i].click(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	// Get the button needed to add new tags | ||||
| 	let tag_btn = await page.$("#tag-add-btn"); | ||||
| 	for(let i = 0; i < review.tags.length; i++){ | ||||
| 		await page.$eval("#tag-form", (el, value) => el.value = value, review.tags[i]); | ||||
| 	for (let i = 0; i < review.tags.length; i++) { | ||||
| 		await page.$eval("#tag-form", (el, value) => (el.value = value), review.tags[i]); | ||||
| 		await tag_btn.click(); | ||||
| 	} | ||||
|  | ||||
| 	// Select a new rating | ||||
| 	let rating_select = await page.$(`#s${review.rating}-select`); | ||||
| 	await rating_select.click({delay: 100}); | ||||
| 	await rating_select.click({ delay: 100 }); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -38,7 +37,7 @@ export async function setReviewForm(page, review) { | ||||
|  * @param {string} prefix prefix character for element IDs | ||||
|  * @param {Object} expected values for each element | ||||
|  */ | ||||
| export async function checkCorrectness(root, prefix, expected){ | ||||
| export async function checkCorrectness(root, prefix, expected) { | ||||
| 	// Get the review image and check src | ||||
| 	let img = await root.$(`#${prefix}-meal-img`); | ||||
| 	let imgSrc = await img.getProperty("src"); | ||||
| @@ -61,7 +60,7 @@ export async function checkCorrectness(root, prefix, expected){ | ||||
| 	// Check tags | ||||
| 	let tags = await root.$$(`.${prefix}-tag`); | ||||
| 	assert.strictEqual(await tags.length, expected.tags.length); | ||||
| 	for(let i = 0; i < expected.tags.length; i++){ | ||||
| 	for (let i = 0; i < expected.tags.length; i++) { | ||||
| 		let tag_text = await tags[i].getProperty("innerText"); | ||||
| 		assert.strictEqual(await tag_text.jsonValue(), expected.tags[i]); | ||||
| 	} | ||||
| @@ -70,4 +69,4 @@ export async function checkCorrectness(root, prefix, expected){ | ||||
| 	let stars = await root.$(`#${prefix}-rating`); | ||||
| 	let stars_src = await stars.getProperty("src"); | ||||
| 	assert.strictEqual(await stars_src.jsonValue(), expected.rating); | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
|  * @param {Object} review to store | ||||
|  * @return {number} ID of the newly added review | ||||
|  */ | ||||
| export function newReviewToStorage(review){ | ||||
| export function newReviewToStorage(review) { | ||||
| 	//grabbing the nextID, and putting our review object in storage associated with the ID | ||||
| 	let nextReviewId = JSON.parse(localStorage.getItem("nextID")); | ||||
| 	review["reviewID"] = nextReviewId; | ||||
| @@ -16,17 +16,17 @@ export function newReviewToStorage(review){ | ||||
|  | ||||
| 	//adding to the star storage | ||||
| 	let starArr = JSON.parse(localStorage.getItem(`star${review["rating"]}`)); | ||||
| 	if(!starArr){ | ||||
| 	if (!starArr) { | ||||
| 		starArr = []; | ||||
| 	} | ||||
| 	starArr.push(nextReviewId); | ||||
| 	localStorage.setItem(`star${review["rating"]}`, JSON.stringify(starArr)); | ||||
| 	 | ||||
|  | ||||
| 	//updating our activeIDS list | ||||
| 	let tempIdArr = JSON.parse(localStorage.getItem("activeIDS")); | ||||
| 	tempIdArr.push(nextReviewId); | ||||
| 	localStorage.setItem("activeIDS", JSON.stringify(tempIdArr)); | ||||
| 	 | ||||
|  | ||||
| 	//increment nextID for next review creation | ||||
| 	localStorage.setItem("nextID", JSON.stringify(nextReviewId + 1)); | ||||
|  | ||||
| @@ -38,7 +38,7 @@ export function newReviewToStorage(review){ | ||||
|  * @param {string} ID of the review to get | ||||
|  * @returns {Object} review object corresponding to param ID | ||||
|  */ | ||||
| export function getReviewFromStorage(ID){ | ||||
| export function getReviewFromStorage(ID) { | ||||
| 	return JSON.parse(localStorage.getItem(`review${ID}`)); | ||||
| } | ||||
|  | ||||
| @@ -47,15 +47,15 @@ export function getReviewFromStorage(ID){ | ||||
|  * @param {string} ID of review to update | ||||
|  * @param {Object} review to store | ||||
|  */ | ||||
| export function updateReviewToStorage(ID, review){ | ||||
| export function updateReviewToStorage(ID, review) { | ||||
| 	let oldReview = JSON.parse(localStorage.getItem(`review${ID}`)); | ||||
| 	let starArr = JSON.parse(localStorage.getItem(`star${review["rating"]}`)); | ||||
|  | ||||
| 	//activeID update recency | ||||
| 	let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); | ||||
| 	for (let i in activeIDS){ | ||||
| 		if(activeIDS[i] == ID){ | ||||
| 			activeIDS.splice(i,1); | ||||
| 	for (let i in activeIDS) { | ||||
| 		if (activeIDS[i] == ID) { | ||||
| 			activeIDS.splice(i, 1); | ||||
| 			activeIDS.push(ID); | ||||
| 			break; | ||||
| 		} | ||||
| @@ -63,33 +63,33 @@ export function updateReviewToStorage(ID, review){ | ||||
| 	localStorage.setItem("activeIDS", JSON.stringify(activeIDS)); | ||||
|  | ||||
| 	//star local storage update | ||||
| 	if(oldReview["rating"] !== review["rating"]){ | ||||
| 	if (oldReview["rating"] !== review["rating"]) { | ||||
| 		//first delete from previous rating array in storage | ||||
| 		let oldStarArr = JSON.parse(localStorage.getItem(`star${oldReview["rating"]}`)); | ||||
| 		for (let i in oldStarArr) { | ||||
| 			if (oldStarArr[i] == ID) { | ||||
| 				//removing from corresponding rating array and updating local Storage | ||||
| 				oldStarArr.splice(i,1); | ||||
| 				oldStarArr.splice(i, 1); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if(oldStarArr.length != 0){ | ||||
| 		if (oldStarArr.length != 0) { | ||||
| 			localStorage.setItem(`star${oldReview["rating"]}`, JSON.stringify(oldStarArr)); | ||||
| 		} else { | ||||
| 			localStorage.removeItem(`star${oldReview["rating"]}`); | ||||
| 		} | ||||
| 		//then add ID to array corresponding to new review rating | ||||
| 		let newStarArr = starArr; | ||||
| 		if(!newStarArr){ | ||||
| 		if (!newStarArr) { | ||||
| 			newStarArr = []; | ||||
| 		} | ||||
| 		newStarArr.push(ID); | ||||
| 		localStorage.setItem(`star${review["rating"]}`, JSON.stringify(newStarArr)); | ||||
| 	} else if(starArr.length !== 1) { | ||||
| 	} else if (starArr.length !== 1) { | ||||
| 		//stars update recency if unchanged | ||||
| 		for (let i in starArr){ | ||||
| 			if(starArr[i] == ID) { | ||||
| 				starArr.splice(i,1); | ||||
| 		for (let i in starArr) { | ||||
| 			if (starArr[i] == ID) { | ||||
| 				starArr.splice(i, 1); | ||||
| 				starArr.push(ID); | ||||
| 				break; | ||||
| 			} | ||||
| @@ -98,14 +98,14 @@ export function updateReviewToStorage(ID, review){ | ||||
| 	} | ||||
|  | ||||
| 	//specifically the unchanged tags update recency | ||||
| 	let repeatedTags = review["tags"].filter(x => oldReview["tags"].includes(x)); | ||||
| 	let repeatedTags = review["tags"].filter((x) => oldReview["tags"].includes(x)); | ||||
| 	let tagArr = []; | ||||
| 	for (let i in repeatedTags){ | ||||
| 	for (let i in repeatedTags) { | ||||
| 		tagArr = JSON.parse(localStorage.getItem(`!${repeatedTags[i]}`.toLocaleLowerCase())); | ||||
| 		if(tagArr.length == 1){ | ||||
| 			for (let j in tagArr){ | ||||
| 				if(tagArr[j] == ID){ | ||||
| 					tagArr.splice(j,1); | ||||
| 		if (tagArr.length == 1) { | ||||
| 			for (let j in tagArr) { | ||||
| 				if (tagArr[j] == ID) { | ||||
| 					tagArr.splice(j, 1); | ||||
| 					tagArr.push(ID); | ||||
| 					break; | ||||
| 				} | ||||
| @@ -115,8 +115,8 @@ export function updateReviewToStorage(ID, review){ | ||||
| 	} | ||||
|  | ||||
| 	//Get diff of tags and update storage | ||||
| 	let deletedTags = oldReview["tags"].filter(x => !review["tags"].includes(x)); | ||||
| 	let addedTags = review["tags"].filter(x => !oldReview["tags"].includes(x)); | ||||
| 	let deletedTags = oldReview["tags"].filter((x) => !review["tags"].includes(x)); | ||||
| 	let addedTags = review["tags"].filter((x) => !oldReview["tags"].includes(x)); | ||||
| 	deleteTagsFromStorage(ID, deletedTags); | ||||
| 	addTagsToStorage(ID, addedTags); | ||||
|  | ||||
| @@ -128,30 +128,30 @@ export function updateReviewToStorage(ID, review){ | ||||
|  * Deletes a review by ID from storage | ||||
|  * @param {string} ID of the review to delete | ||||
|  */ | ||||
| export function deleteReviewFromStorage(ID){ | ||||
| export function deleteReviewFromStorage(ID) { | ||||
| 	//removing id number from activeIDS and star{rating} | ||||
| 	let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); | ||||
| 	let reviewRating = JSON.parse(localStorage.getItem(`review${ID}`))["rating"]; | ||||
| 	let starArr = JSON.parse(localStorage.getItem(`star${reviewRating}`)); | ||||
| 	 | ||||
|  | ||||
| 	for (let i in starArr) { | ||||
| 		if (starArr[i] == ID) { | ||||
| 			//removing from corresponding rating array and updating local Storage | ||||
| 			starArr.splice(i,1); | ||||
| 			starArr.splice(i, 1); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	if(starArr.length != 0){ | ||||
| 	if (starArr.length != 0) { | ||||
| 		localStorage.setItem(`star${reviewRating}`, JSON.stringify(starArr)); | ||||
| 	} else { | ||||
| 		localStorage.removeItem(`star${reviewRating}`); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	for (let i in activeIDS) { | ||||
| 		if (activeIDS[i] == ID) { | ||||
| 			activeIDS.splice(i,1); | ||||
| 			activeIDS.splice(i, 1); | ||||
| 			localStorage.setItem("activeIDS", JSON.stringify(activeIDS)); | ||||
| 			 | ||||
|  | ||||
| 			let currReview = JSON.parse(localStorage.getItem(`review${ID}`)); | ||||
| 			deleteTagsFromStorage(ID, currReview["tags"]); | ||||
| 			localStorage.removeItem(`review${ID}`); | ||||
| @@ -168,17 +168,17 @@ export function deleteReviewFromStorage(ID){ | ||||
|  * @param {string[]} deletedTags to modify storage of | ||||
|  */ | ||||
| function deleteTagsFromStorage(ID, deletedTags) { | ||||
| 	for(let i in deletedTags){ | ||||
| 	for (let i in deletedTags) { | ||||
| 		//get local storage of each tag and remove id from tag list | ||||
| 		let tagName = "!"+ deletedTags[i].toLowerCase(); | ||||
| 		let tagName = "!" + deletedTags[i].toLowerCase(); | ||||
| 		let tagArr = JSON.parse(localStorage.getItem(tagName)); | ||||
| 		for(let j in tagArr){ | ||||
| 			if(tagArr[j] == ID){ | ||||
| 				tagArr.splice(j,1); | ||||
| 		for (let j in tagArr) { | ||||
| 			if (tagArr[j] == ID) { | ||||
| 				tagArr.splice(j, 1); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		if(tagArr.length != 0){ | ||||
| 		if (tagArr.length != 0) { | ||||
| 			localStorage.setItem(tagName, JSON.stringify(tagArr)); | ||||
| 		} else { | ||||
| 			localStorage.removeItem(tagName); | ||||
| @@ -192,10 +192,10 @@ function deleteTagsFromStorage(ID, deletedTags) { | ||||
|  * @param {string[]} addedTags to modify storage of | ||||
|  */ | ||||
| function addTagsToStorage(ID, addedTags) { | ||||
| 	for(let i in addedTags){ | ||||
| 	for (let i in addedTags) { | ||||
| 		let tagName = "!" + addedTags[i].toLowerCase(); | ||||
| 		let tagArr = JSON.parse(localStorage.getItem(tagName)); | ||||
| 		if(!tagArr){ | ||||
| 		if (!tagArr) { | ||||
| 			tagArr = []; | ||||
| 		} | ||||
| 		tagArr.push(ID); | ||||
| @@ -208,10 +208,10 @@ function addTagsToStorage(ID, addedTags) { | ||||
|  * @returns {Object} all active reviews from local storage | ||||
|  */ | ||||
| export function getAllReviewsFromStorage() { | ||||
| 	if (!(localStorage.getItem("activeIDS"))) { | ||||
| 	if (!localStorage.getItem("activeIDS")) { | ||||
| 		// we wanna init the active ID array and start the nextID count | ||||
| 		localStorage.setItem("activeIDS", JSON.stringify([])); | ||||
| 		localStorage.setItem("nextID",  JSON.stringify(0)); | ||||
| 		localStorage.setItem("nextID", JSON.stringify(0)); | ||||
| 	} | ||||
| 	//iterate thru activeIDS | ||||
| 	let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); | ||||
| @@ -228,10 +228,10 @@ export function getAllReviewsFromStorage() { | ||||
|  * @returns {number[]} list of all active IDs by recency | ||||
|  */ | ||||
| export function getIDsFromStorage() { | ||||
| 	if (!(localStorage.getItem("activeIDS"))) { | ||||
| 	if (!localStorage.getItem("activeIDS")) { | ||||
| 		// we wanna init the active ID array and start the nextID count | ||||
| 		localStorage.setItem("activeIDS", JSON.stringify([])); | ||||
| 		localStorage.setItem("nextID",  JSON.stringify(0)); | ||||
| 		localStorage.setItem("nextID", JSON.stringify(0)); | ||||
| 	} | ||||
| 	let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); | ||||
| 	return activeIDS.reverse(); | ||||
| @@ -244,7 +244,7 @@ export function getIDsFromStorage() { | ||||
|  */ | ||||
| export function getIDsByTag(tag) { | ||||
| 	let tagArr = JSON.parse(localStorage.getItem("!" + tag.toLowerCase())); | ||||
| 	if(!tagArr){ | ||||
| 	if (!tagArr) { | ||||
| 		tagArr = []; | ||||
| 	} | ||||
| 	return tagArr.reverse(); | ||||
| @@ -256,12 +256,12 @@ export function getIDsByTag(tag) { | ||||
|  */ | ||||
| export function getTopIDsFromStorage() { | ||||
| 	let resultArr = []; | ||||
| 	for(let i = 5; i > 0; i--){ | ||||
| 	for (let i = 5; i > 0; i--) { | ||||
| 		let starArr = JSON.parse(localStorage.getItem(`star${i}`)); | ||||
| 		if(!starArr){ | ||||
| 		if (!starArr) { | ||||
| 			continue; | ||||
| 		} | ||||
| 		resultArr = resultArr.concat(starArr.reverse()); | ||||
| 	} | ||||
| 	return resultArr; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,16 @@ | ||||
| import {strict as assert} from "node:assert"; | ||||
| import {describe, it, before, after} from "mocha"; | ||||
| import {newReviewToStorage, getReviewFromStorage, updateReviewToStorage, deleteReviewFromStorage, getAllReviewsFromStorage, getIDsByTag, getTopIDsFromStorage} from "./localStorage.js"; | ||||
| import { strict as assert } from "node:assert"; | ||||
| import { describe, it, before, after } from "mocha"; | ||||
| import { | ||||
| 	newReviewToStorage, | ||||
| 	getReviewFromStorage, | ||||
| 	updateReviewToStorage, | ||||
| 	deleteReviewFromStorage, | ||||
| 	getAllReviewsFromStorage, | ||||
| 	getIDsByTag, | ||||
| 	getTopIDsFromStorage, | ||||
| } from "./localStorage.js"; | ||||
|  | ||||
| describe("test CRUD localStorage interaction", () => { | ||||
| 	 | ||||
| 	before(() => { | ||||
| 		localStorage.clear(); | ||||
| 	}); | ||||
| @@ -16,11 +23,11 @@ describe("test CRUD localStorage interaction", () => { | ||||
|  | ||||
| 	it("test localStorage state after adding one review", () => { | ||||
| 		let review = { | ||||
| 			"imgSrc": "sample src", | ||||
| 			"mealName": "sample name", | ||||
| 			"restaurant": "sample restaurant", | ||||
| 			"rating": 5, | ||||
| 			"tags": ["tag 1", "tag  2", "tag 3"] | ||||
| 			imgSrc: "sample src", | ||||
| 			mealName: "sample name", | ||||
| 			restaurant: "sample restaurant", | ||||
| 			rating: 5, | ||||
| 			tags: ["tag 1", "tag  2", "tag 3"], | ||||
| 		}; | ||||
|  | ||||
| 		newReviewToStorage(review); | ||||
| @@ -37,38 +44,38 @@ describe("test CRUD localStorage interaction", () => { | ||||
| 		let reviews = getAllReviewsFromStorage(); | ||||
| 		let ids = [0]; | ||||
|  | ||||
| 		for(let i = 1; i < 1000; i++){ | ||||
| 		for (let i = 1; i < 1000; i++) { | ||||
| 			ids.push(i); | ||||
| 			let new_review = { | ||||
| 				"imgSrc": `sample src ${i}`, | ||||
| 				"mealName": `sample name ${i}`, | ||||
| 				"restaurant": `sample restaurant ${i}`, | ||||
| 				"rating": i, | ||||
| 				"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] | ||||
| 				imgSrc: `sample src ${i}`, | ||||
| 				mealName: `sample name ${i}`, | ||||
| 				restaurant: `sample restaurant ${i}`, | ||||
| 				rating: i, | ||||
| 				tags: [`tag ${3 * i}`, `tag ${3 * i + 1}`, `tag ${3 * i + 2}`], | ||||
| 			}; | ||||
|  | ||||
| 			new_review.reviewID  = newReviewToStorage(new_review); | ||||
| 			new_review.reviewID = newReviewToStorage(new_review); | ||||
| 			reviews.push(new_review); | ||||
|  | ||||
| 			assert.deepEqual(getAllReviewsFromStorage(), reviews); | ||||
| 			assert.deepEqual(getReviewFromStorage(i), new_review); | ||||
| 			assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); | ||||
| 			assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), (i+1)); | ||||
| 			assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), i + 1); | ||||
| 		} | ||||
| 	}).timeout(5000); | ||||
|  | ||||
| 	it("test localStorage state during updating 1000 reviews", () => { | ||||
| 		for(let i = 0; i < 1000; i++){ | ||||
| 		for (let i = 0; i < 1000; i++) { | ||||
| 			let old_review = getReviewFromStorage(i); | ||||
| 			let id = old_review.reviewID; | ||||
|  | ||||
| 			let new_review = { | ||||
| 				"imgSrc": `updated sample src ${id}`, | ||||
| 				"mealName": `updated sample name ${id}`, | ||||
| 				"restaurant": `updated sample restaurant ${id}`, | ||||
| 				"reviewID": id, | ||||
| 				"rating": (id % 5) + 1, | ||||
| 				"tags": [`tag ${3*id}`, `tag ${3*id + 1}`, `tag ${3*id + 2}`] | ||||
| 				imgSrc: `updated sample src ${id}`, | ||||
| 				mealName: `updated sample name ${id}`, | ||||
| 				restaurant: `updated sample restaurant ${id}`, | ||||
| 				reviewID: id, | ||||
| 				rating: (id % 5) + 1, | ||||
| 				tags: [`tag ${3 * id}`, `tag ${3 * id + 1}`, `tag ${3 * id + 2}`], | ||||
| 			}; | ||||
|  | ||||
| 			updateReviewToStorage(id, new_review); | ||||
| @@ -87,7 +94,7 @@ describe("test CRUD localStorage interaction", () => { | ||||
| 		let reviews = getAllReviewsFromStorage(); | ||||
| 		let ids = JSON.parse(localStorage.getItem("activeIDS")); | ||||
|  | ||||
| 		for(let i = 999; i >= 0; i--){ | ||||
| 		for (let i = 999; i >= 0; i--) { | ||||
| 			deleteReviewFromStorage(i); | ||||
| 			ids.pop(); | ||||
| 			reviews.pop(); | ||||
| @@ -106,30 +113,29 @@ describe("test CRUD localStorage interaction", () => { | ||||
| }); | ||||
|  | ||||
| describe("test sort/filter localStorage interaction", () => { | ||||
| 	 | ||||
| 	before(() => { | ||||
| 		localStorage.clear(); | ||||
| 		getAllReviewsFromStorage(); | ||||
| 	}); | ||||
|  | ||||
| 	it("add sample data for sort and filter", () => { | ||||
| 		for(let i = 0; i < 100; i++){ | ||||
| 		for (let i = 0; i < 100; i++) { | ||||
| 			let review = { | ||||
| 				"imgSrc": `sample src ${i}`, | ||||
| 				"mealName": `sample name ${i}`, | ||||
| 				"restaurant": `sample restaurant ${i}`, | ||||
| 				"rating": (i % 5) + 1, | ||||
| 				"tags": [`tag ${i%3}`, `tag ${i < 50}`, "tag x"] | ||||
| 				imgSrc: `sample src ${i}`, | ||||
| 				mealName: `sample name ${i}`, | ||||
| 				restaurant: `sample restaurant ${i}`, | ||||
| 				rating: (i % 5) + 1, | ||||
| 				tags: [`tag ${i % 3}`, `tag ${i < 50}`, "tag x"], | ||||
| 			}; | ||||
|  | ||||
| 			newReviewToStorage(review); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getTopIDsFromStorage end behavior after create", () =>{ | ||||
| 	it("test getTopIDsFromStorage end behavior after create", () => { | ||||
| 		let top_reviews = getTopIDsFromStorage(); | ||||
| 		let prev = Infinity; | ||||
| 		for(let i = 0; i < top_reviews.length; i++){ | ||||
| 		for (let i = 0; i < top_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(top_reviews[i]); | ||||
| 			assert.strictEqual(review.rating <= prev, true); | ||||
| 		} | ||||
| @@ -140,7 +146,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 0"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 34); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 0"), true); | ||||
| 			assert.strictEqual(review.reviewID % 3, 0); | ||||
| @@ -148,63 +154,63 @@ describe("test sort/filter localStorage interaction", () => { | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 1"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 33); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 1"), true); | ||||
| 			assert.strictEqual(review.reviewID % 3, 1); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 2");	 | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 2"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 33); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 2"), true); | ||||
| 			assert.strictEqual(review.reviewID % 3, 2); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag true");		 | ||||
| 		specific_tagged_reviews = getIDsByTag("tag true"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 50); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag true"), true); | ||||
| 			assert.strictEqual(review.reviewID < 50, true); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag false");		 | ||||
| 		specific_tagged_reviews = getIDsByTag("tag false"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 50); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag false"), true); | ||||
| 			assert.strictEqual(review.reviewID >= 50, true); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag x");		 | ||||
| 		specific_tagged_reviews = getIDsByTag("tag x"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 100); | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag y");		 | ||||
| 		specific_tagged_reviews = getIDsByTag("tag y"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
| 	}); | ||||
|  | ||||
| 	it("update sample data for sort and filter", () => { | ||||
| 		for(let i = 0; i < 100; i++){ | ||||
| 		for (let i = 0; i < 100; i++) { | ||||
| 			let old_review = getReviewFromStorage(i); | ||||
| 			let new_review = { | ||||
| 				"imgSrc": `sample src ${i}`, | ||||
| 				"mealName": `sample name ${i}`, | ||||
| 				"restaurant": `sample restaurant ${i}`, | ||||
| 				"reviewID": old_review.reviewID, | ||||
| 				"rating": (i % 5) + 1, | ||||
| 				"tags": [`tag ${i % 4}`, `tag ${i < 37}`, "tag y"] | ||||
| 				imgSrc: `sample src ${i}`, | ||||
| 				mealName: `sample name ${i}`, | ||||
| 				restaurant: `sample restaurant ${i}`, | ||||
| 				reviewID: old_review.reviewID, | ||||
| 				rating: (i % 5) + 1, | ||||
| 				tags: [`tag ${i % 4}`, `tag ${i < 37}`, "tag y"], | ||||
| 			}; | ||||
|  | ||||
| 			updateReviewToStorage(old_review.reviewID, new_review); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getTopIDsFromStorage end behavior after create", () =>{ | ||||
| 	it("test getTopIDsFromStorage end behavior after create", () => { | ||||
| 		let top_reviews = getTopIDsFromStorage(); | ||||
| 		let prev = Infinity; | ||||
| 		for(let i = 0; i < top_reviews.length; i++){ | ||||
| 		for (let i = 0; i < top_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(top_reviews[i]); | ||||
| 			assert.strictEqual(review.rating <= prev, true); | ||||
| 		} | ||||
| @@ -215,7 +221,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 0"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 25); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 0"), true); | ||||
| 			assert.strictEqual(review.reviewID % 4, 0); | ||||
| @@ -223,7 +229,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 1"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 25); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 1"), true); | ||||
| 			assert.strictEqual(review.reviewID % 4, 1); | ||||
| @@ -231,7 +237,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 2"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 25); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 2"), true); | ||||
| 			assert.strictEqual(review.reviewID % 4, 2); | ||||
| @@ -239,7 +245,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 3"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 25); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 3"), true); | ||||
| 			assert.strictEqual(review.reviewID % 4, 3); | ||||
| @@ -247,7 +253,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag true"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 37); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag true"), true); | ||||
| 			assert.strictEqual(review.reviewID < 37, true); | ||||
| @@ -255,7 +261,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
|  | ||||
| 		specific_tagged_reviews = getIDsByTag("tag false"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 63); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 		for (let i = 0; i < specific_tagged_reviews.length; i++) { | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag false"), true); | ||||
| 			assert.strictEqual(review.reviewID >= 37, true); | ||||
| @@ -269,13 +275,13 @@ describe("test sort/filter localStorage interaction", () => { | ||||
| 	}); | ||||
|  | ||||
| 	it("delete all sample data for sort and filter", () => { | ||||
| 		for(let i = 0; i < 100; i++){ | ||||
| 		for (let i = 0; i < 100; i++) { | ||||
| 			deleteReviewFromStorage(i); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getTopIDsFromStorage end behavior after delete", () =>{ | ||||
| 		for(let i = 0; i <= 100; i++){ | ||||
| 	it("test getTopIDsFromStorage end behavior after delete", () => { | ||||
| 		for (let i = 0; i <= 100; i++) { | ||||
| 			let top_reviews = getTopIDsFromStorage(i); | ||||
| 			assert.deepEqual(top_reviews, []); | ||||
| 		} | ||||
| @@ -310,4 +316,4 @@ describe("test sort/filter localStorage interaction", () => { | ||||
| 	}); | ||||
|  | ||||
| 	after(() => {}); | ||||
| }); | ||||
| }); | ||||
|   | ||||
| @@ -1,30 +1,27 @@ | ||||
| import {strict as assert} from "node:assert"; | ||||
| import {describe, it, before, after} from "mocha"; | ||||
| import { strict as assert } from "node:assert"; | ||||
| import { describe, it, before, after } from "mocha"; | ||||
| import puppeteer from "puppeteer-core"; | ||||
| import {setReviewForm, checkCorrectness} from "./appTestHelpers.js"; | ||||
| import { setReviewForm, checkCorrectness } from "./appTestHelpers.js"; | ||||
|  | ||||
| describe("test App end to end", async () => { | ||||
|  | ||||
| 	let browser; | ||||
| 	let page; | ||||
|  | ||||
| 	before(async () => { | ||||
| 		let root; | ||||
| 		try { | ||||
| 			root =  process.getuid() == 0; | ||||
| 		} | ||||
| 		catch (error) { | ||||
| 			root = process.getuid() == 0; | ||||
| 		} catch (error) { | ||||
| 			root = false; | ||||
| 		} | ||||
|  | ||||
| 		//browser = await puppeteer.launch({headless: false, slowMo: 250, args: root ? ['--no-sandbox'] : undefined}); | ||||
| 		browser = await puppeteer.launch({args: root ? ["--no-sandbox"] : undefined}); | ||||
| 		browser = await puppeteer.launch({ args: root ? ["--no-sandbox"] : undefined }); | ||||
| 		page = await browser.newPage(); | ||||
| 		try{ | ||||
| 			await page.goto("http://localhost:8080", {timeout: 2000}); | ||||
| 		try { | ||||
| 			await page.goto("http://localhost:8080", { timeout: 2000 }); | ||||
| 			await console.log(`✔ connected to localhost webserver as ${root ? "root" : "user"}`); | ||||
| 		} | ||||
| 		catch (error) { | ||||
| 		} catch (error) { | ||||
| 			await console.log("❌ failed to connect to localhost webserver on port 8080"); | ||||
| 		} | ||||
| 	}); | ||||
| @@ -36,7 +33,6 @@ describe("test App end to end", async () => { | ||||
| 	}); | ||||
|  | ||||
| 	describe("test CRUD on simple inputs and default image", () => { | ||||
|  | ||||
| 		describe("test create 1 new review", async () => { | ||||
| 			it("create 1 new review", async () => { | ||||
| 				// Click the button to create a new review | ||||
| @@ -50,7 +46,7 @@ describe("test App end to end", async () => { | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: 1 | ||||
| 					rating: 1, | ||||
| 				}; | ||||
| 				await setReviewForm(page, review); | ||||
|  | ||||
| @@ -68,11 +64,11 @@ describe("test App end to end", async () => { | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg", | ||||
| 				}; | ||||
| 				await checkCorrectness(page, "d", expected); | ||||
| 			}); | ||||
| 		 | ||||
|  | ||||
| 			it("check home page", async () => { | ||||
| 				// Click the button to return to the home page | ||||
| 				let home_btn = await page.$("#home-btn"); | ||||
| @@ -89,7 +85,7 @@ describe("test App end to end", async () => { | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg", | ||||
| 				}; | ||||
| 				await checkCorrectness(shadowRoot, "a", expected); | ||||
| 			}); | ||||
| @@ -114,7 +110,7 @@ describe("test App end to end", async () => { | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg", | ||||
| 				}; | ||||
| 				await checkCorrectness(page, "d", expected); | ||||
| 			}); | ||||
| @@ -136,16 +132,14 @@ describe("test App end to end", async () => { | ||||
| 					comments: "sample comment", | ||||
| 					restaurant: "sample restaurant", | ||||
| 					tags: ["tag 0", "tag 1", "tag 2", "tag 3", "tag 4"], | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/1-star.svg", | ||||
| 				}; | ||||
| 				await checkCorrectness(shadowRoot, "a", expected); | ||||
| 			}); | ||||
| 		}); | ||||
|  | ||||
| 		describe("test update 1 review", async () => { | ||||
|  | ||||
| 			it("update 1 review", async () => { | ||||
|  | ||||
| 				// Get the only review card and click it | ||||
| 				let review_card = await page.$("review-card"); | ||||
| 				await review_card.click(); | ||||
| @@ -161,7 +155,7 @@ describe("test App end to end", async () => { | ||||
| 					comments: "updated comment", | ||||
| 					restaurant: "updated restaurant", | ||||
| 					tags: ["tag -0", "tag -1", "tag -2", "tag -3", "tag -4", "tag -5"], | ||||
| 					rating: 5 | ||||
| 					rating: 5, | ||||
| 				}; | ||||
| 				await setReviewForm(page, review); | ||||
|  | ||||
| @@ -179,7 +173,7 @@ describe("test App end to end", async () => { | ||||
| 					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/5-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/5-star.svg", | ||||
| 				}; | ||||
| 				await checkCorrectness(page, "d", expected); | ||||
| 			}); | ||||
| @@ -201,11 +195,10 @@ describe("test App end to end", async () => { | ||||
| 					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/5-star.svg" | ||||
| 					rating: "http://localhost:8080/assets/images/5-star.svg", | ||||
| 				}; | ||||
| 				await checkCorrectness(shadowRoot, "a", expected); | ||||
| 			}); | ||||
|  | ||||
| 		}); | ||||
|  | ||||
| 		describe("test delete 1 review", async () => { | ||||
| @@ -215,7 +208,7 @@ describe("test App end to end", async () => { | ||||
| 				await review_card.click(); | ||||
| 				await page.waitForNavigation(); | ||||
|  | ||||
| 				page.on("dialog", async dialog => { | ||||
| 				page.on("dialog", async (dialog) => { | ||||
| 					console.log(dialog.message()); | ||||
| 					await dialog.accept(); | ||||
| 				}); | ||||
| @@ -227,4 +220,4 @@ describe("test App end to end", async () => { | ||||
| 		await page.close(); | ||||
| 		await browser.close(); | ||||
| 	}); | ||||
| }); | ||||
| }); | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| // main.js | ||||
| import {getIDsByTag, getIDsFromStorage, getReviewFromStorage, getTopIDsFromStorage} from "./localStorage.js"; | ||||
| import { getIDsByTag, getIDsFromStorage, getReviewFromStorage, getTopIDsFromStorage } from "./localStorage.js"; | ||||
|  | ||||
| // Run the init() function when the page has loaded | ||||
| window.addEventListener("DOMContentLoaded", init); | ||||
| @@ -11,25 +11,22 @@ function init() { | ||||
| 	initFormHandler(); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @param {Array<Object>} reviews An array of reviews | ||||
|  */ | ||||
| function addReviewsToDocument(reviews) { | ||||
| 	let reviewBox = document.getElementById("review-container"); | ||||
| 	reviews.forEach(review => { | ||||
| 	reviews.forEach((review) => { | ||||
| 		let newReview = document.createElement("review-card"); | ||||
| 		newReview.data = review; | ||||
| 		reviewBox.append(newReview); | ||||
| 	}); | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Adds the necessary event handlers to search-btn and sort | ||||
|  */ | ||||
| function initFormHandler() { | ||||
|  | ||||
| 	//grabbing search field | ||||
| 	let searchField = document.getElementById("search-bar"); | ||||
| 	let searchBtn = document.getElementById("search-btn"); | ||||
| @@ -37,14 +34,14 @@ function initFormHandler() { | ||||
| 	//adding search functionality | ||||
| 	//TODO: Add ability to enter without refresh of search bar | ||||
| 	//filter by selected tag when button clicked | ||||
| 	searchBtn.addEventListener("click", function(){ | ||||
| 	searchBtn.addEventListener("click", function () { | ||||
| 		searchTag = searchField.value; | ||||
| 		sortAndFilter(searchTag); | ||||
| 	}); | ||||
|  | ||||
| 	//for clearing tag filter | ||||
| 	let clearSearchBtn = document.getElementById("clear-search"); | ||||
| 	clearSearchBtn.addEventListener("click", function(){ | ||||
| 	clearSearchBtn.addEventListener("click", function () { | ||||
| 		searchTag = null; | ||||
| 		searchField.value = ""; | ||||
| 		sortAndFilter(searchTag); | ||||
| @@ -52,45 +49,43 @@ function initFormHandler() { | ||||
|  | ||||
| 	//sort by selected method | ||||
| 	let sortMethod = document.getElementById("sort"); | ||||
| 	sortMethod.addEventListener("input", function(){ | ||||
| 	sortMethod.addEventListener("input", function () { | ||||
| 		sortAndFilter(searchTag); | ||||
| 	}); | ||||
|  | ||||
| 	 | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Deciphers sort and filter to populate the review-container | ||||
|  * @param {string} searchTag tag name to filter by | ||||
|  */ | ||||
| function sortAndFilter(searchTag){ | ||||
| function sortAndFilter(searchTag) { | ||||
| 	let reviewBox = document.getElementById("review-container"); | ||||
| 	let sortMethod = document.getElementById("sort"); | ||||
| 	//clear review container | ||||
| 	while(reviewBox.firstChild){ | ||||
| 	while (reviewBox.firstChild) { | ||||
| 		reviewBox.removeChild(reviewBox.firstChild); | ||||
| 	} | ||||
| 	let reviewIDs = []; | ||||
| 	//sort method: most recent | ||||
| 	if(sortMethod.value == "recent"){ | ||||
| 	if (sortMethod.value == "recent") { | ||||
| 		//tag filtered most recent | ||||
| 		if(searchTag){ | ||||
| 		if (searchTag) { | ||||
| 			reviewIDs = getIDsByTag(searchTag); | ||||
| 		}  | ||||
| 		} | ||||
| 		//most recent | ||||
| 		else { | ||||
| 			reviewIDs = getIDsFromStorage(); | ||||
| 		} | ||||
| 		//reversed for recency | ||||
| 		loadReviews(0, reviewIDs); | ||||
| 	}  | ||||
| 	} | ||||
| 	//sort method: top rated | ||||
| 	else if (sortMethod.value == "top"){ | ||||
| 	else if (sortMethod.value == "top") { | ||||
| 		//tag filtered top rated | ||||
| 		if(searchTag){ | ||||
| 		if (searchTag) { | ||||
| 			//intersection of top ids list and ids by tag in top ids order | ||||
| 			reviewIDs = getTopIDsFromStorage().filter(x => getIDsByTag(searchTag).includes(x)); | ||||
| 		}  | ||||
| 			reviewIDs = getTopIDsFromStorage().filter((x) => getIDsByTag(searchTag).includes(x)); | ||||
| 		} | ||||
| 		//top rated | ||||
| 		else { | ||||
| 			reviewIDs = getTopIDsFromStorage(); | ||||
| @@ -104,36 +99,36 @@ function sortAndFilter(searchTag){ | ||||
|  * @param {number} index review index to begin with | ||||
|  * @param {number[]} reviewIDs ordered array of reviews | ||||
|  */ | ||||
| function loadReviews(index, reviewIDs){ | ||||
| function loadReviews(index, reviewIDs) { | ||||
| 	let reviewBox = document.getElementById("review-container"); | ||||
| 	// label if there are no reviews to display | ||||
| 	if(reviewIDs.length == 0){ | ||||
| 	if (reviewIDs.length == 0) { | ||||
| 		let emptyLabel = document.createElement("label"); | ||||
| 		emptyLabel.setAttribute("id", "empty"); | ||||
| 		emptyLabel.innerText = "No Reviews To Display"; | ||||
| 		reviewBox.append(emptyLabel); | ||||
| 	} else { | ||||
| 		let emptyLabel = document.getElementById("empty"); | ||||
| 		if(emptyLabel){ | ||||
| 		if (emptyLabel) { | ||||
| 			reviewBox.removeChild(emptyLabel); | ||||
| 		} | ||||
| 	} | ||||
| 	let moreBtn = document.getElementById("more-btn"); | ||||
| 	//delete load more button if exists | ||||
| 	if(moreBtn){ | ||||
| 	if (moreBtn) { | ||||
| 		reviewBox.removeChild(moreBtn); | ||||
| 	} | ||||
| 	let reviewArr = []; | ||||
| 	//check if there are more than 9 reviews left | ||||
| 	if(index + 9 > reviewIDs.length - 1){ | ||||
| 	if (index + 9 > reviewIDs.length - 1) { | ||||
| 		//add remaining reviews to review container | ||||
| 		for(let i = index; i < reviewIDs.length; i++){ | ||||
| 		for (let i = index; i < reviewIDs.length; i++) { | ||||
| 			reviewArr.push(getReviewFromStorage(reviewIDs[i])); | ||||
| 		} | ||||
| 		addReviewsToDocument(reviewArr); | ||||
| 	} else { | ||||
| 		//add 9 more reviews to container | ||||
| 		for(let i = index; i < index + 9; i++){ | ||||
| 		for (let i = index; i < index + 9; i++) { | ||||
| 			reviewArr.push(getReviewFromStorage(reviewIDs[i])); | ||||
| 		} | ||||
| 		addReviewsToDocument(reviewArr); | ||||
| @@ -142,19 +137,20 @@ function loadReviews(index, reviewIDs){ | ||||
| 		moreBtn.setAttribute("id", "more-btn"); | ||||
| 		moreBtn.innerText = "Load More"; | ||||
| 		//if load more clicked, load 9 more | ||||
| 		moreBtn.addEventListener("click", function(){loadReviews(index + 9, reviewIDs);}); | ||||
| 		moreBtn.addEventListener("click", function () { | ||||
| 			loadReviews(index + 9, reviewIDs); | ||||
| 		}); | ||||
| 		reviewBox.append(moreBtn); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| const registerServiceWorker = async () => { | ||||
| 	if ("serviceWorker" in navigator) { | ||||
| 		try { | ||||
| 			await navigator.serviceWorker.register("./sw.js", {scope: "./"}); | ||||
| 			await navigator.serviceWorker.register("./sw.js", { scope: "./" }); | ||||
| 		} catch (error) { | ||||
| 			console.error(`Registration failed with ${error}`); | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
| registerServiceWorker(); | ||||
| registerServiceWorker(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user