mirror of
				https://github.com/cse110-fa22-group29/cse110-fa22-group29.git
				synced 2025-10-31 03:46:50 +00:00 
			
		
		
		
	Merge branch 'sprint-3' into 49-image-feature
This commit is contained in:
		| @@ -159,10 +159,10 @@ function initFormHandler() { | ||||
| 				let tagLabel = document.createElement("label"); | ||||
| 				tagLabel.innerHTML = tagField.value; | ||||
| 				tagLabel.setAttribute("class","tag"); | ||||
| 				tagSet.add(tagField.value.toLowerCase()); | ||||
| 				tagSet.add(tagSetVal); | ||||
| 				tagLabel.addEventListener("click",()=> { | ||||
| 					tagContainer.removeChild(tagLabel); | ||||
| 					tagSet.delete(tagField.value.toLowerCase()); | ||||
| 					tagSet.delete(tagSetVal); | ||||
| 				}); | ||||
| 		 | ||||
| 				tagContainer.append(tagLabel); | ||||
|   | ||||
| @@ -17,6 +17,7 @@ class ReviewCard extends HTMLElement { | ||||
| 			margin: 0; | ||||
| 			padding: 0; | ||||
| 			overflow-wrap: anywhere; | ||||
| 			cursor: pointer; | ||||
| 		} | ||||
| 		 | ||||
| 		a { | ||||
| @@ -149,7 +150,7 @@ class ReviewCard extends HTMLElement { | ||||
|  | ||||
| 		// Image setup | ||||
| 		let mealImg = document.createElement("img"); | ||||
| 		mealImg.setAttribute("id", "a-mealImg"); | ||||
| 		mealImg.setAttribute("id", "a-meal-img"); | ||||
| 		mealImg.setAttribute("alt","Meal Photo Corrupted"); | ||||
| 		mealImg.setAttribute("src",data["mealImg"]); | ||||
| 		mealImg.addEventListener("error", function(e) { | ||||
| @@ -157,11 +158,11 @@ class ReviewCard extends HTMLElement { | ||||
| 			e.onerror = null; | ||||
| 		}); | ||||
|  | ||||
| 		//meal name setup | ||||
| 		// Meal name setup | ||||
| 		let meallabelDiv = document.createElement("div"); | ||||
| 		meallabelDiv.setAttribute("class", "meal-name-div"); | ||||
| 		let mealLabel = document.createElement("label"); | ||||
| 		mealLabel.setAttribute("id", "a-mealName"); | ||||
| 		mealLabel.setAttribute("id", "a-meal-name"); | ||||
| 		mealLabel.setAttribute("class","meal-name"); | ||||
| 		mealLabel.innerHTML = data["mealName"]; | ||||
| 		meallabelDiv.append(mealLabel); | ||||
| @@ -188,7 +189,7 @@ class ReviewCard extends HTMLElement { | ||||
| 		starsImg.setAttribute("num", data["rating"]); | ||||
| 		ratingDiv.append(starsImg); | ||||
|  | ||||
| 		//added tags | ||||
| 		// Tags setup | ||||
| 		let tagContainerDiv = document.createElement("div");  | ||||
| 		tagContainerDiv.setAttribute("class", "tag-container-div"); | ||||
| 		let tagContainer = document.createElement("div"); | ||||
| @@ -244,12 +245,12 @@ class ReviewCard extends HTMLElement { | ||||
| 		// Getting the article elements for the review card | ||||
| 		dataContainer["reviewID"] = this.reviewID; | ||||
|  | ||||
| 		// Get image | ||||
| 		let mealImg = this.shadowEl.getElementById("a-mealImg"); | ||||
| 		//get image | ||||
| 		let mealImg = this.shadowEl.getElementById("a-meal-img"); | ||||
| 		dataContainer["mealImg"] = mealImg.getAttribute("src"); | ||||
|  | ||||
| 		// Get meal name | ||||
| 		let mealLabel = this.shadowEl.getElementById("a-mealName"); | ||||
| 		//get meal name | ||||
| 		let mealLabel = this.shadowEl.getElementById("a-meal-name"); | ||||
| 		dataContainer["mealName"] = mealLabel.innerHTML; | ||||
|  | ||||
| 		// Get comment section | ||||
|   | ||||
| @@ -58,7 +58,7 @@ function setupInfo(){ | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Sets up delete button to delete review from storage and switch to homepage | ||||
|  * Sets up delete button to delete reveiw from storage and switch to homepage. | ||||
|  */ | ||||
| function setupDelete(){ | ||||
| 	let deleteBtn = document.getElementById("delete-btn"); | ||||
| @@ -73,7 +73,7 @@ function setupDelete(){ | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Sets up update button to reveal form and update info in storage and the current page  | ||||
|  * Sets up update button to reveal form and update info in storage and the current page. | ||||
|  */ | ||||
| function setupUpdate(){ | ||||
| 	let updateBtn = document.getElementById("update-btn"); | ||||
| @@ -102,8 +102,10 @@ function setupUpdate(){ | ||||
| 			while (tagContainer.firstChild) { | ||||
| 				tagContainer.removeChild(tagContainer.firstChild); | ||||
| 			} | ||||
|        | ||||
| 			let tagSetVal; | ||||
| 			for (let i = 0; i < currReview["tags"].length; i++) { | ||||
| 				let tagSetVal = currReview["tags"][i].toLowerCase() | ||||
| 				tagSetVal = currReview["tags"][i].toLowerCase(); | ||||
| 				tagSet.add(tagSetVal); | ||||
| 				let newTag = document.createElement("label"); | ||||
| 				newTag.setAttribute("class","tag"); | ||||
| @@ -242,7 +244,7 @@ function setupUpdate(){ | ||||
|  | ||||
| 		}); | ||||
|  | ||||
| 		//adding tag to form functionality | ||||
| 		// Adding tag to form functionality | ||||
| 		let tagAddBtn = document.getElementById("tag-add-btn"); | ||||
| 		tagAddBtn.addEventListener("click", ()=> { | ||||
| 			let tagField = document.getElementById("tag-form"); | ||||
|   | ||||
| @@ -40,13 +40,13 @@ export async function setReviewForm(page, review) { | ||||
|  */ | ||||
| export async function checkCorrectness(root, prefix, expected){ | ||||
| 	// Get the review image and check src | ||||
| 	let img = await root.$(`#${prefix}-mealImg`); | ||||
| 	let img = await root.$(`#${prefix}-meal-img`); | ||||
| 	let imgSrc = await img.getProperty("src"); | ||||
| 	// Check src | ||||
| 	assert.strictEqual(await imgSrc.jsonValue(), expected.imgSrc); | ||||
|  | ||||
| 	// Get the title, comment, and restaurant | ||||
| 	let title = await root.$(`#${prefix}-mealName`); | ||||
| 	let title = await root.$(`#${prefix}-meal-name`); | ||||
| 	let title_text = await title.getProperty("innerText"); | ||||
| 	let comment = await root.$(`#${prefix}-comments`); | ||||
| 	let comment_text = await comment.getProperty("innerText"); | ||||
|   | ||||
| @@ -13,6 +13,14 @@ export function newReviewToStorage(review){ | ||||
|  | ||||
| 	// adding to the tag keys | ||||
| 	addTagsToStorage(nextReviewId, review["tags"]); | ||||
|  | ||||
| 	//adding to the star storage | ||||
| 	let starArr = JSON.parse(localStorage.getItem(`star${review["rating"]}`)); | ||||
| 	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")); | ||||
| @@ -41,6 +49,70 @@ export function getReviewFromStorage(ID){ | ||||
|  */ | ||||
| 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); | ||||
| 			activeIDS.push(ID); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	localStorage.setItem("activeIDS", JSON.stringify(activeIDS)); | ||||
|  | ||||
| 	//star local storage update | ||||
| 	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); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		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){ | ||||
| 			newStarArr = []; | ||||
| 		} | ||||
| 		newStarArr.push(ID); | ||||
| 		localStorage.setItem(`star${review["rating"]}`, JSON.stringify(newStarArr)); | ||||
| 	} else if(starArr.length !== 1) { | ||||
| 		//stars update recency if unchanged | ||||
| 		for (let i in starArr){ | ||||
| 			if(starArr[i] == ID) { | ||||
| 				starArr.splice(i,1); | ||||
| 				starArr.push(ID); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 		localStorage.setItem(`star${review["rating"]}`, JSON.stringify(starArr)); | ||||
| 	} | ||||
|  | ||||
| 	//specifically the unchanged tags update recency | ||||
| 	let repeatedTags = review["tags"].filter(x => oldReview["tags"].includes(x)); | ||||
| 	let tagArr = []; | ||||
| 	for (let i in repeatedTags){ | ||||
| 		tagArr = JSON.parse(localStorage.getItem(`!${repeatedTags[i]}`)); | ||||
| 		if(tagArr.length == 1){ | ||||
| 			for (let j in tagArr){ | ||||
| 				if(tagArr[j] == ID){ | ||||
| 					tagArr.splice(j,1); | ||||
| 					tagArr.push(ID); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			localStorage.setItem(`!${repeatedTags[i]}`, JSON.stringify(tagArr)); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	//Get diff of tags and update storage | ||||
| 	let deletedTags = oldReview["tags"].filter(x => !review["tags"].includes(x)); | ||||
| @@ -57,12 +129,29 @@ export function updateReviewToStorage(ID, review){ | ||||
|  * @param {string} ID of the review to delete | ||||
|  */ | ||||
| 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); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	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); | ||||
| 			localStorage.setItem("activeIDS", JSON.stringify(activeIDS)); | ||||
| 			 | ||||
| 			let currReview = JSON.parse(localStorage.getItem(`review${ID}`)); | ||||
| 			deleteTagsFromStorage(ID, currReview["tags"]); | ||||
| 			localStorage.removeItem(`review${ID}`); | ||||
| @@ -115,24 +204,9 @@ function addTagsToStorage(ID, addedTags) { | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns the top n reviews by ID. If there are less than n reviews, returns the most possible.  | ||||
|  * @param {number} n number of reviews to return | ||||
|  * @returns {Object} list of n reviews that are the top rated | ||||
|  * Test Helper Function to get all reviews from local storage | ||||
|  * @returns {Object} all active reviews from local storage | ||||
|  */ | ||||
| export function getTopReviewsFromStorage(n) { | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns all reviews which contain the same tag specified.  | ||||
|  * @param {string} tag to filter by | ||||
|  * @returns {Object} list of reviews that all contain the specified tag | ||||
|  */ | ||||
| export function getReviewsByTag(tag) { | ||||
|  | ||||
| } | ||||
|  | ||||
| // legacy function | ||||
| export function getAllReviewsFromStorage() { | ||||
| 	if (!(localStorage.getItem("activeIDS"))) { | ||||
| 		// we wanna init the active ID array and start the nextID count | ||||
| @@ -147,4 +221,47 @@ export function getAllReviewsFromStorage() { | ||||
| 		reviews.push(currReview); | ||||
| 	} | ||||
| 	return reviews; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get all IDs of active reviews (order: most recent) | ||||
|  * @returns {number[]} list of all active IDs by recency | ||||
|  */ | ||||
| export function getIDsFromStorage() { | ||||
| 	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)); | ||||
| 	} | ||||
| 	let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); | ||||
| 	return activeIDS.reverse(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns all review IDs which contain the same tag specified (order: most recent) | ||||
|  * @param {string} tag to filter by | ||||
|  * @returns {number[]} list of IDs of reviews that all contain the specified tag by recency | ||||
|  */ | ||||
| export function getIDsByTag(tag) { | ||||
| 	let tagArr = JSON.parse(localStorage.getItem("!" + tag.toLowerCase())); | ||||
| 	if(!tagArr){ | ||||
| 		tagArr = []; | ||||
| 	} | ||||
| 	return tagArr.reverse(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns the top rated review IDs in order. | ||||
|  * @returns {number[]} list of IDs of reviews in order of top rating (most recent if equal rating) | ||||
|  */ | ||||
| export function getTopIDsFromStorage() { | ||||
| 	let resultArr = []; | ||||
| 	for(let i = 5; i > 0; i--){ | ||||
| 		let starArr = JSON.parse(localStorage.getItem(`star${i}`)); | ||||
| 		if(!starArr){ | ||||
| 			continue; | ||||
| 		} | ||||
| 		resultArr = resultArr.concat(starArr.reverse()); | ||||
| 	} | ||||
| 	return resultArr; | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| import {strict as assert} from "node:assert"; | ||||
| import {describe, it, before, after} from "mocha"; | ||||
| import {newReviewToStorage, getReviewFromStorage, updateReviewToStorage, deleteReviewFromStorage, getAllReviewsFromStorage, getTopReviewsFromStorage, getReviewsByTag} from "./localStorage.js"; | ||||
| import {newReviewToStorage, getReviewFromStorage, updateReviewToStorage, deleteReviewFromStorage, getAllReviewsFromStorage, getIDsByTag, getTopIDsFromStorage} from "./localStorage.js"; | ||||
|  | ||||
| describe("test CRUD localStorage interaction", () => { | ||||
| 	 | ||||
| @@ -58,26 +58,27 @@ describe("test CRUD localStorage interaction", () => { | ||||
| 	}).timeout(5000); | ||||
|  | ||||
| 	it("test localStorage state during updating 1000 reviews", () => { | ||||
| 		let reviews = getAllReviewsFromStorage(); | ||||
| 		let ids = JSON.parse(localStorage.getItem("activeIDS")); | ||||
|  | ||||
| 		for(let i = 0; i < 1000; i++){ | ||||
| 			let old_review = getReviewFromStorage(i); | ||||
| 			let id = old_review.reviewID; | ||||
|  | ||||
| 			let new_review = { | ||||
| 				"imgSrc": `updated sample src ${i}`, | ||||
| 				"mealName": `updated sample name ${i}`, | ||||
| 				"restaurant": `updated sample restaurant ${i}`, | ||||
| 				"rating": i*2+i, | ||||
| 				"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 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}`] | ||||
| 			}; | ||||
| 			new_review.reviewID = i; | ||||
|  | ||||
| 			reviews[i] = new_review; | ||||
| 			updateReviewToStorage(id, new_review); | ||||
|  | ||||
| 			updateReviewToStorage(i, new_review); | ||||
| 			let all_reviews = getAllReviewsFromStorage(); | ||||
| 			let active_ids = JSON.parse(localStorage.getItem("activeIDS")); | ||||
|  | ||||
| 			assert.deepEqual(getAllReviewsFromStorage(), reviews); | ||||
| 			assert.deepEqual(all_reviews[999], new_review); | ||||
| 			assert.strictEqual(active_ids[999], id); | ||||
| 			assert.deepEqual(getReviewFromStorage(i), new_review); | ||||
| 			assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); | ||||
| 			assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000); | ||||
| 		} | ||||
| 	}).timeout(5000); | ||||
| @@ -108,6 +109,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
| 	 | ||||
| 	before(() => { | ||||
| 		localStorage.clear(); | ||||
| 		getAllReviewsFromStorage(); | ||||
| 	}); | ||||
|  | ||||
| 	it("add sample data for sort and filter", () => { | ||||
| @@ -116,7 +118,7 @@ describe("test sort/filter localStorage interaction", () => { | ||||
| 				"imgSrc": `sample src ${i}`, | ||||
| 				"mealName": `sample name ${i}`, | ||||
| 				"restaurant": `sample restaurant ${i}`, | ||||
| 				"rating": i, | ||||
| 				"rating": (i % 5) + 1, | ||||
| 				"tags": [`tag ${i%3}`, `tag ${i < 50}`, "tag x"] | ||||
| 			}; | ||||
|  | ||||
| @@ -124,134 +126,145 @@ describe("test sort/filter localStorage interaction", () => { | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getTopReviewsFromStorage end behavior after create", () =>{ | ||||
| 		for(let i = 0; i <= 100; i++){ | ||||
| 			let top_reviews = getTopReviewsFromStorage(i); | ||||
| 			for(let j = 0; j < i; j++){ | ||||
| 				assert.strictEqual(top_reviews[j].rating, 99 - j); | ||||
| 				assert.strictEqual(top_reviews[j].reviewID, 99 - j); | ||||
| 			} | ||||
| 	it("test getTopIDsFromStorage end behavior after create", () =>{ | ||||
| 		let top_reviews = getTopIDsFromStorage(); | ||||
| 		let prev = Infinity; | ||||
| 		for(let i = 0; i < top_reviews.length; i++){ | ||||
| 			let review = getReviewFromStorage(top_reviews[i]); | ||||
| 			assert.strictEqual(review.rating <= prev, true); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getReviewsByTag end behavior after create", () => { | ||||
| 	it("test getIDsByTag end behavior after create", () => { | ||||
| 		let specific_tagged_reviews = []; | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 0"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 0"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 34); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 0"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID % 3, 0); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 0"), true); | ||||
| 			assert.strictEqual(review.reviewID % 3, 0); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 1"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 1"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 33); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 1"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID % 3, 1); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 1"), true); | ||||
| 			assert.strictEqual(review.reviewID % 3, 1); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("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++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 2"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID % 3, 2); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 2"), true); | ||||
| 			assert.strictEqual(review.reviewID % 3, 2); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("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++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag true"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID < 50, true); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag true"), true); | ||||
| 			assert.strictEqual(review.reviewID < 50, true); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("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++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag false"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID >= 50, true); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag false"), true); | ||||
| 			assert.strictEqual(review.reviewID >= 50, true); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag x"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag x");		 | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 100); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("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++){ | ||||
| 			let old_review = getReviewFromStorage(i); | ||||
| 			let new_review = { | ||||
| 				"imgSrc": `sample src ${i}`, | ||||
| 				"mealName": `sample name ${i}`, | ||||
| 				"restaurant": `sample restaurant ${i}`, | ||||
| 				"rating": 99-i, | ||||
| 				"tags": [`tag ${i%4}`, `tag ${i < 37}`, "tag y"] | ||||
| 				"reviewID": old_review.reviewID, | ||||
| 				"rating": (i % 5) + 1, | ||||
| 				"tags": [`tag ${i % 4}`, `tag ${i < 37}`, "tag y"] | ||||
| 			}; | ||||
|  | ||||
| 			updateReviewToStorage(i, new_review); | ||||
| 			updateReviewToStorage(old_review.reviewID, new_review); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getTopReviewsFromStorage end behavior after create", () =>{ | ||||
| 		for(let i = 0; i <= 100; i++){ | ||||
| 			let top_reviews = getTopReviewsFromStorage(i); | ||||
| 			for(let j = 0; j < i; j++){ | ||||
| 				assert.strictEqual(top_reviews[j].rating, 99 - j); | ||||
| 				assert.strictEqual(top_reviews[j].reviewID, j); | ||||
| 			} | ||||
| 	it("test getTopIDsFromStorage end behavior after create", () =>{ | ||||
| 		let top_reviews = getTopIDsFromStorage(); | ||||
| 		let prev = Infinity; | ||||
| 		for(let i = 0; i < top_reviews.length; i++){ | ||||
| 			let review = getReviewFromStorage(top_reviews[i]); | ||||
| 			assert.strictEqual(review.rating <= prev, true); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getReviewsByTag end behavior after update", () => { | ||||
| 	it("test getIDsByTag end behavior after update", () => { | ||||
| 		let specific_tagged_reviews = []; | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 0"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 0"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 25); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 0"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID % 4, 0); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 0"), true); | ||||
| 			assert.strictEqual(review.reviewID % 4, 0); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 1"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 1"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 25); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 1"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID % 4, 1); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 1"), true); | ||||
| 			assert.strictEqual(review.reviewID % 4, 1); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 2"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 2"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 25); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 2"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID % 4, 2); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 2"), true); | ||||
| 			assert.strictEqual(review.reviewID % 4, 2); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 3"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 3"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 25); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 3"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID % 4, 3); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag 3"), true); | ||||
| 			assert.strictEqual(review.reviewID % 4, 3); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag true"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag true"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 37); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag true"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID < 37, true); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag true"), true); | ||||
| 			assert.strictEqual(review.reviewID < 37, true); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag false"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag false"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 63); | ||||
| 		for(let i = 0; i < specific_tagged_reviews.length; i++){ | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag false"), true); | ||||
| 			assert.strictEqual(specific_tagged_reviews[i].reviewID >= 37, true); | ||||
| 			let review = getReviewFromStorage(specific_tagged_reviews[i]); | ||||
| 			assert.strictEqual(review.tags.includes("tag false"), true); | ||||
| 			assert.strictEqual(review.reviewID >= 37, true); | ||||
| 		} | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag x"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag x"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag y"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag y"); | ||||
| 		assert.strictEqual(specific_tagged_reviews.length, 100); | ||||
| 	}); | ||||
|  | ||||
| @@ -261,38 +274,38 @@ describe("test sort/filter localStorage interaction", () => { | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getTopReviewsFromStorage end behavior after delete", () =>{ | ||||
| 	it("test getTopIDsFromStorage end behavior after delete", () =>{ | ||||
| 		for(let i = 0; i <= 100; i++){ | ||||
| 			let top_reviews = getTopReviewsFromStorage(i); | ||||
| 			let top_reviews = getTopIDsFromStorage(i); | ||||
| 			assert.deepEqual(top_reviews, []); | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	it("test getReviewsByTag end behavior after delete", () => { | ||||
| 	it("test getIDsByTag end behavior after delete", () => { | ||||
| 		let specific_tagged_reviews = []; | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 0"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 0"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 1"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 1"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 2"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 2"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag 3"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag 3"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag true"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag true"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag false"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag false"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag x"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag x"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
|  | ||||
| 		specific_tagged_reviews = getReviewsByTag("tag y"); | ||||
| 		specific_tagged_reviews = getIDsByTag("tag y"); | ||||
| 		assert.deepEqual(specific_tagged_reviews, []); | ||||
| 	}); | ||||
|  | ||||
|   | ||||
| @@ -1,15 +1,13 @@ | ||||
| // main.js | ||||
| import {getAllReviewsFromStorage} from "./localStorage.js"; | ||||
| import {getIDsByTag, getIDsFromStorage, getReviewFromStorage, getTopIDsFromStorage} from "./localStorage.js"; | ||||
|  | ||||
| // Run the init() function when the page has loaded | ||||
| window.addEventListener("DOMContentLoaded", init); | ||||
|  | ||||
| function init() { | ||||
| 	// Get the reviews from localStorage | ||||
| 	let reviews = getAllReviewsFromStorage(); | ||||
| 	// Add each reviews to the <main> element | ||||
| 	addReviewsToDocument(reviews); | ||||
| 	// Add the event listeners to the form elements | ||||
| 	//initial population of review container | ||||
| 	sortAndFilter(false, null); | ||||
| 	//Add the event listeners to dropdown and search bar | ||||
| 	initFormHandler(); | ||||
| } | ||||
|  | ||||
| @@ -22,21 +20,141 @@ function addReviewsToDocument(reviews) { | ||||
| 	reviews.forEach(review => { | ||||
| 		let newReview = document.createElement("review-card"); | ||||
| 		newReview.data = review; | ||||
| 		//TODO: want to append it to whatever the box is in layout  | ||||
| 		reviewBox.append(newReview); | ||||
| 	}); | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Adds the necessary event handlers to <form> and the clear storage | ||||
|  * <button>. | ||||
|  * Adds the necessary event handlers to search-btn and sort | ||||
|  */ | ||||
| function initFormHandler() { | ||||
|  | ||||
| 	//btn to create form (could be its own function?) | ||||
| 	let createBtn = document.getElementById("create-btn"); | ||||
| 	createBtn.addEventListener("click", function(){ | ||||
| 		window.location.assign("./CreatePage.html"); | ||||
| 	//grabbing search field | ||||
| 	let searchField = document.getElementById("search-bar"); | ||||
| 	let searchBtn = document.getElementById("search-btn"); | ||||
| 	let searchTag = null; | ||||
| 	//adding search functionality | ||||
| 	//TODO: Add ability to enter without refresh of search bar | ||||
| 	//filter by selected tag when button clicked | ||||
| 	searchBtn.addEventListener("click", function(){ | ||||
| 		searchTag = searchField.value; | ||||
| 		sortAndFilter(searchTag); | ||||
| 	}); | ||||
|  | ||||
| 	//for clearing tag filter | ||||
| 	let clearSearchBtn = document.getElementById("clear-search"); | ||||
| 	clearSearchBtn.addEventListener("click", function(){ | ||||
| 		searchTag = null; | ||||
| 		searchField.value = ""; | ||||
| 		sortAndFilter(searchTag); | ||||
| 	}); | ||||
|  | ||||
| 	//sort by selected method | ||||
| 	let sortMethod = document.getElementById("sort"); | ||||
| 	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){ | ||||
| 	let reviewBox = document.getElementById("review-container"); | ||||
| 	let sortMethod = document.getElementById("sort"); | ||||
| 	//clear review container | ||||
| 	while(reviewBox.firstChild){ | ||||
| 		reviewBox.removeChild(reviewBox.firstChild); | ||||
| 	} | ||||
| 	let reviewIDs = []; | ||||
| 	//sort method: most recent | ||||
| 	if(sortMethod.value == "recent"){ | ||||
| 		//tag filtered most recent | ||||
| 		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"){ | ||||
| 		//tag filtered top rated | ||||
| 		if(searchTag){ | ||||
| 			//intersection of top ids list and ids by tag in top ids order | ||||
| 			reviewIDs = getTopIDsFromStorage().filter(x => getIDsByTag(searchTag).includes(x)); | ||||
| 		}  | ||||
| 		//top rated | ||||
| 		else { | ||||
| 			reviewIDs = getTopIDsFromStorage(); | ||||
| 		} | ||||
| 		loadReviews(0, reviewIDs); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Populate review-container with 9 more reviews | ||||
|  * @param {number} index review index to begin with | ||||
|  * @param {number[]} reviewIDs ordered array of reviews | ||||
|  */ | ||||
| function loadReviews(index, reviewIDs){ | ||||
| 	let reviewBox = document.getElementById("review-container"); | ||||
| 	// label if there are no reviews to display | ||||
| 	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){ | ||||
| 			reviewBox.removeChild(emptyLabel); | ||||
| 		} | ||||
| 	} | ||||
| 	let moreBtn = document.getElementById("more-btn"); | ||||
| 	//delete load more button if exists | ||||
| 	if(moreBtn){ | ||||
| 		reviewBox.removeChild(moreBtn); | ||||
| 	} | ||||
| 	let reviewArr = []; | ||||
| 	//check if there are more than 9 reviews left | ||||
| 	if(index + 9 > reviewIDs.length - 1){ | ||||
| 		//add remaining reviews to review container | ||||
| 		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++){ | ||||
| 			reviewArr.push(getReviewFromStorage(reviewIDs[i])); | ||||
| 		} | ||||
| 		addReviewsToDocument(reviewArr); | ||||
| 		//create and add load more button | ||||
| 		moreBtn = document.createElement("button"); | ||||
| 		moreBtn.setAttribute("id", "more-btn"); | ||||
| 		moreBtn.innerText = "Load More"; | ||||
| 		//if load more clicked, load 9 more | ||||
| 		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: "./"}); | ||||
| 		} catch (error) { | ||||
| 			console.error(`Registration failed with ${error}`); | ||||
| 		} | ||||
| 	} | ||||
| }; | ||||
| registerServiceWorker(); | ||||
		Reference in New Issue
	
	Block a user