Merge pull request #102 from cse110-fa22-group29/filter-sort

Filter and Sort Functionality
This commit is contained in:
rheabhutada02 2022-12-01 16:39:02 -08:00 committed by GitHub
commit f0f706e575
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 446 additions and 171 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -97,10 +97,10 @@ function initFormHandler() {
let tagLabel = document.createElement("label"); let tagLabel = document.createElement("label");
tagLabel.innerHTML = tagField.value; tagLabel.innerHTML = tagField.value;
tagLabel.setAttribute("class","tag"); tagLabel.setAttribute("class","tag");
tagSet.add(tagField.value.toLowerCase()); tagSet.add(tagSetVal);
tagLabel.addEventListener("click",()=> { tagLabel.addEventListener("click",()=> {
tagContainer.removeChild(tagLabel); tagContainer.removeChild(tagLabel);
tagSet.delete(tagField.value.toLowerCase()); tagSet.delete(tagSetVal);
}); });
tagContainer.append(tagLabel); tagContainer.append(tagLabel);

View File

@ -17,6 +17,7 @@ class ReviewCard extends HTMLElement {
margin: 0; margin: 0;
padding: 0; padding: 0;
overflow-wrap: anywhere; overflow-wrap: anywhere;
cursor: pointer;
} }
a { a {
@ -157,7 +158,7 @@ class ReviewCard extends HTMLElement {
//image setup //image setup
let mealImg = document.createElement("img"); let mealImg = document.createElement("img");
mealImg.setAttribute("id", "a-mealImg"); mealImg.setAttribute("id", "a-meal-img");
mealImg.setAttribute("alt","Meal Photo Corrupted"); mealImg.setAttribute("alt","Meal Photo Corrupted");
mealImg.setAttribute("src",data["mealImg"]); mealImg.setAttribute("src",data["mealImg"]);
mealImg.addEventListener("error", function(e) { mealImg.addEventListener("error", function(e) {
@ -169,7 +170,7 @@ class ReviewCard extends HTMLElement {
let meallabelDiv = document.createElement("div"); let meallabelDiv = document.createElement("div");
meallabelDiv.setAttribute("class", "meal-name-div"); meallabelDiv.setAttribute("class", "meal-name-div");
let mealLabel = document.createElement("label"); let mealLabel = document.createElement("label");
mealLabel.setAttribute("id", "a-mealName"); mealLabel.setAttribute("id", "a-meal-name");
mealLabel.setAttribute("class","meal-name"); mealLabel.setAttribute("class","meal-name");
mealLabel.innerHTML = data["mealName"]; mealLabel.innerHTML = data["mealName"];
meallabelDiv.append(mealLabel); meallabelDiv.append(mealLabel);
@ -251,11 +252,11 @@ class ReviewCard extends HTMLElement {
dataContainer["reviewID"] = this.reviewID; dataContainer["reviewID"] = this.reviewID;
//get image //get image
let mealImg = this.shadowEl.getElementById("a-mealImg"); let mealImg = this.shadowEl.getElementById("a-meal-img");
dataContainer["mealImg"] = mealImg.getAttribute("src"); dataContainer["mealImg"] = mealImg.getAttribute("src");
//get meal name //get meal name
let mealLabel = this.shadowEl.getElementById("a-mealName"); let mealLabel = this.shadowEl.getElementById("a-meal-name");
dataContainer["mealName"] = mealLabel.innerHTML; dataContainer["mealName"] = mealLabel.innerHTML;
//get comment section //get comment section

View File

@ -99,8 +99,10 @@ function setupUpdate(){
while (tagContainer.firstChild) { while (tagContainer.firstChild) {
tagContainer.removeChild(tagContainer.firstChild); tagContainer.removeChild(tagContainer.firstChild);
} }
let tagSetVal = currReview["tags"][i].toLowerCase();
let tagSetVal;
for (let i = 0; i < currReview["tags"].length; i++) { for (let i = 0; i < currReview["tags"].length; i++) {
tagSetVal = currReview["tags"][i].toLowerCase()
tagSet.add(tagSetVal); tagSet.add(tagSetVal);
let newTag = document.createElement("label"); let newTag = document.createElement("label");
newTag.setAttribute("class","tag"); newTag.setAttribute("class","tag");

View File

@ -40,13 +40,13 @@ export async function setReviewForm(page, review) {
*/ */
export async function checkCorrectness(root, prefix, expected){ export async function checkCorrectness(root, prefix, expected){
// Get the review image and check src // 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"); let imgSrc = await img.getProperty("src");
// Check src // Check src
assert.strictEqual(await imgSrc.jsonValue(), expected.imgSrc); assert.strictEqual(await imgSrc.jsonValue(), expected.imgSrc);
// Get the title, comment, and restaurant // 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 title_text = await title.getProperty("innerText");
let comment = await root.$(`#${prefix}-comments`); let comment = await root.$(`#${prefix}-comments`);
let comment_text = await comment.getProperty("innerText"); let comment_text = await comment.getProperty("innerText");

View File

@ -13,6 +13,14 @@ export function newReviewToStorage(review){
// adding to the tag keys // adding to the tag keys
addTagsToStorage(nextReviewId, review["tags"]); 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 //updating our activeIDS list
let tempIdArr = JSON.parse(localStorage.getItem("activeIDS")); let tempIdArr = JSON.parse(localStorage.getItem("activeIDS"));
@ -41,6 +49,70 @@ export function getReviewFromStorage(ID){
*/ */
export function updateReviewToStorage(ID, review){ export function updateReviewToStorage(ID, review){
let oldReview = JSON.parse(localStorage.getItem(`review${ID}`)); 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 //Get diff of tags and update storage
let deletedTags = oldReview["tags"].filter(x => !review["tags"].includes(x)); 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 * @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 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) { for (let i in activeIDS) {
if (activeIDS[i] == ID) { if (activeIDS[i] == ID) {
activeIDS.splice(i,1); activeIDS.splice(i,1);
localStorage.setItem("activeIDS", JSON.stringify(activeIDS)); localStorage.setItem("activeIDS", JSON.stringify(activeIDS));
let currReview = JSON.parse(localStorage.getItem(`review${ID}`)); let currReview = JSON.parse(localStorage.getItem(`review${ID}`));
deleteTagsFromStorage(ID, currReview["tags"]); deleteTagsFromStorage(ID, currReview["tags"]);
localStorage.removeItem(`review${ID}`); 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. * Test Helper Function to get all reviews from local storage
* @param {number} n number of reviews to return * @returns {Object} all active reviews from local storage
* @returns {Object} list of n reviews that are the top rated
*/ */
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() { export function getAllReviewsFromStorage() {
if (!(localStorage.getItem("activeIDS"))) { if (!(localStorage.getItem("activeIDS"))) {
// we wanna init the active ID array and start the nextID count // we wanna init the active ID array and start the nextID count
@ -147,4 +221,47 @@ export function getAllReviewsFromStorage() {
reviews.push(currReview); reviews.push(currReview);
} }
return reviews; 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;
} }

View File

@ -1,6 +1,6 @@
import {strict as assert} from "node:assert"; import {strict as assert} from "node:assert";
import {describe, it, before, after} from "mocha"; 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", () => { describe("test CRUD localStorage interaction", () => {
@ -58,26 +58,27 @@ describe("test CRUD localStorage interaction", () => {
}).timeout(5000); }).timeout(5000);
it("test localStorage state during updating 1000 reviews", () => { 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++){ for(let i = 0; i < 1000; i++){
let old_review = getReviewFromStorage(i);
let id = old_review.reviewID;
let new_review = { let new_review = {
"imgSrc": `updated sample src ${i}`, "imgSrc": `updated sample src ${id}`,
"mealName": `updated sample name ${i}`, "mealName": `updated sample name ${id}`,
"restaurant": `updated sample restaurant ${i}`, "restaurant": `updated sample restaurant ${id}`,
"rating": i*2+i, "reviewID": id,
"tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] "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(getReviewFromStorage(i), new_review);
assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids);
assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000); assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000);
} }
}).timeout(5000); }).timeout(5000);
@ -108,6 +109,7 @@ describe("test sort/filter localStorage interaction", () => {
before(() => { before(() => {
localStorage.clear(); localStorage.clear();
getAllReviewsFromStorage();
}); });
it("add sample data for sort and filter", () => { it("add sample data for sort and filter", () => {
@ -116,7 +118,7 @@ describe("test sort/filter localStorage interaction", () => {
"imgSrc": `sample src ${i}`, "imgSrc": `sample src ${i}`,
"mealName": `sample name ${i}`, "mealName": `sample name ${i}`,
"restaurant": `sample restaurant ${i}`, "restaurant": `sample restaurant ${i}`,
"rating": i, "rating": (i % 5) + 1,
"tags": [`tag ${i%3}`, `tag ${i < 50}`, "tag x"] "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", () =>{ it("test getTopIDsFromStorage end behavior after create", () =>{
for(let i = 0; i <= 100; i++){ let top_reviews = getTopIDsFromStorage();
let top_reviews = getTopReviewsFromStorage(i); let prev = Infinity;
for(let j = 0; j < i; j++){ for(let i = 0; i < top_reviews.length; i++){
assert.strictEqual(top_reviews[j].rating, 99 - j); let review = getReviewFromStorage(top_reviews[i]);
assert.strictEqual(top_reviews[j].reviewID, 99 - j); assert.strictEqual(review.rating <= prev, true);
}
} }
}); });
it("test getReviewsByTag end behavior after create", () => { it("test getIDsByTag end behavior after create", () => {
let specific_tagged_reviews = []; let specific_tagged_reviews = [];
specific_tagged_reviews = getReviewsByTag("tag 0"); specific_tagged_reviews = getIDsByTag("tag 0");
assert.strictEqual(specific_tagged_reviews.length, 34); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 0"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID % 3, 0); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 1"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID % 3, 1); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 2"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID % 3, 2); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag true"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID < 50, true); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag false"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID >= 50, true); 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); assert.strictEqual(specific_tagged_reviews.length, 100);
specific_tagged_reviews = getReviewsByTag("tag y"); specific_tagged_reviews = getIDsByTag("tag y");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
}); });
it("update sample data for sort and filter", () => { 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 = { let new_review = {
"imgSrc": `sample src ${i}`, "imgSrc": `sample src ${i}`,
"mealName": `sample name ${i}`, "mealName": `sample name ${i}`,
"restaurant": `sample restaurant ${i}`, "restaurant": `sample restaurant ${i}`,
"rating": 99-i, "reviewID": old_review.reviewID,
"tags": [`tag ${i%4}`, `tag ${i < 37}`, "tag y"] "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", () =>{ it("test getTopIDsFromStorage end behavior after create", () =>{
for(let i = 0; i <= 100; i++){ let top_reviews = getTopIDsFromStorage();
let top_reviews = getTopReviewsFromStorage(i); let prev = Infinity;
for(let j = 0; j < i; j++){ for(let i = 0; i < top_reviews.length; i++){
assert.strictEqual(top_reviews[j].rating, 99 - j); let review = getReviewFromStorage(top_reviews[i]);
assert.strictEqual(top_reviews[j].reviewID, j); assert.strictEqual(review.rating <= prev, true);
}
} }
}); });
it("test getReviewsByTag end behavior after update", () => { it("test getIDsByTag end behavior after update", () => {
let specific_tagged_reviews = []; let specific_tagged_reviews = [];
specific_tagged_reviews = getReviewsByTag("tag 0"); specific_tagged_reviews = getIDsByTag("tag 0");
assert.strictEqual(specific_tagged_reviews.length, 25); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 0"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID % 4, 0); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 1"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID % 4, 1); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 2"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID % 4, 2); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag 3"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID % 4, 3); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag true"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID < 37, true); 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); 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++){
assert.strictEqual(specific_tagged_reviews[i].tags.includes("tag false"), true); let review = getReviewFromStorage(specific_tagged_reviews[i]);
assert.strictEqual(specific_tagged_reviews[i].reviewID >= 37, true); 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, []); assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getReviewsByTag("tag y"); specific_tagged_reviews = getIDsByTag("tag y");
assert.strictEqual(specific_tagged_reviews.length, 100); 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++){ for(let i = 0; i <= 100; i++){
let top_reviews = getTopReviewsFromStorage(i); let top_reviews = getTopIDsFromStorage(i);
assert.deepEqual(top_reviews, []); assert.deepEqual(top_reviews, []);
} }
}); });
it("test getReviewsByTag end behavior after delete", () => { it("test getIDsByTag end behavior after delete", () => {
let specific_tagged_reviews = []; let specific_tagged_reviews = [];
specific_tagged_reviews = getReviewsByTag("tag 0"); specific_tagged_reviews = getIDsByTag("tag 0");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getReviewsByTag("tag 1"); specific_tagged_reviews = getIDsByTag("tag 1");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getReviewsByTag("tag 2"); specific_tagged_reviews = getIDsByTag("tag 2");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getReviewsByTag("tag 3"); specific_tagged_reviews = getIDsByTag("tag 3");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getReviewsByTag("tag true"); specific_tagged_reviews = getIDsByTag("tag true");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getReviewsByTag("tag false"); specific_tagged_reviews = getIDsByTag("tag false");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getReviewsByTag("tag x"); specific_tagged_reviews = getIDsByTag("tag x");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
specific_tagged_reviews = getReviewsByTag("tag y"); specific_tagged_reviews = getIDsByTag("tag y");
assert.deepEqual(specific_tagged_reviews, []); assert.deepEqual(specific_tagged_reviews, []);
}); });

View File

@ -1,15 +1,13 @@
// main.js // main.js
import {getAllReviewsFromStorage} from "./localStorage.js"; import {getIDsByTag, getIDsFromStorage, getReviewFromStorage, getTopIDsFromStorage} from "./localStorage.js";
// Run the init() function when the page has loaded // Run the init() function when the page has loaded
window.addEventListener("DOMContentLoaded", init); window.addEventListener("DOMContentLoaded", init);
function init() { function init() {
// Get the reviews from localStorage //initial population of review container
let reviews = getAllReviewsFromStorage(); sortAndFilter(false, null);
// Add each reviews to the <main> element //Add the event listeners to dropdown and search bar
addReviewsToDocument(reviews);
// Add the event listeners to the form elements
initFormHandler(); initFormHandler();
} }
@ -22,23 +20,132 @@ function addReviewsToDocument(reviews) {
reviews.forEach(review => { reviews.forEach(review => {
let newReview = document.createElement("review-card"); let newReview = document.createElement("review-card");
newReview.data = review; newReview.data = review;
//TODO: want to append it to whatever the box is in layout
reviewBox.append(newReview); reviewBox.append(newReview);
}); });
} }
/** /**
* Adds the necessary event handlers to <form> and the clear storage * Adds the necessary event handlers to search-btn and sort
* <button>.
*/ */
function initFormHandler() { function initFormHandler() {
//btn to create form (could be its own function?) //grabbing search field
let createBtn = document.getElementById("create-btn"); let searchField = document.getElementById("search-bar");
createBtn.addEventListener("click", function(){ let searchBtn = document.getElementById("search-btn");
window.location.assign("./CreatePage.html"); 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 () => { const registerServiceWorker = async () => {

View File

@ -1,56 +1,65 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Food Journal</title>
<!--Add Favicon--> <head>
<link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico"> <meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Food Journal</title>
<!-- Recipe Card Custom Element --> <!--Add Favicon-->
<script src="assets/scripts/ReviewCard.js" type="module"></script> <link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico">
<!-- Main Stylesheets & Scripts --> <!-- Recipe Card Custom Element -->
<!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config--> <script src="assets/scripts/ReviewCard.js" type="module"></script>
<!-- <link rel="stylesheet" href="/static/reset.css" /> -->
<link rel="stylesheet" href="./static/homepage.css" />
<script src="assets/scripts/main.js" type="module"></script>
</head>
<body>
<header>
<div class="top-bar">
<img src ="./assets/images/Logo.png" alt="logo" />
<h1> Food Journal </h1>
<img src ="./assets/images/Logo.png" alt="logo" />
</div>
</header>
<main>
<div class="body-container">
<div style="width: 20%;"></div>
<div style="width: 60%;">
<div class="search-bar">
<form id="form">
<input type="search" id="searching" name="searchBar" placeholder="Search journal...">
<button class="click" type="search"> Search </button>
<div class="Filter-box">
</div>
</form>
</div>
<div class="center-display">
<img src ="./assets/images/Grouppink.png" alt="CREATE" style="opacity: 100%;" id="create-btn" title="Add an entry!" onclick="window.location.assign('./CreatePage.html')"/>
<h2 id="recent-reviews-text"> Recent Reviews </h2>
<img src ="./assets/images/Grouppink.png" style="opacity:0;"/>
</div>
<div class="review-container" id="review-container"></div> <!-- Main Stylesheets & Scripts -->
<!-- Temporarily commented out reset.css due to furthur discussion needed on the values of the default config-->
<!-- <link rel="stylesheet" href="/static/reset.css" /> -->
<link rel="stylesheet" href="./static/homepage.css" />
<script src="assets/scripts/main.js" type="module"></script>
</head>
<body>
<header>
<div class="top-bar">
<img src="./assets/images/Logo.png" alt="logo" />
<h1> Food Journal </h1>
<img src="./assets/images/Logo.png" alt="logo" />
</div>
</header>
<main>
<div class="body-container">
<div style="width: 20%;"></div>
<div style="width: 60%;">
<div class="search-bar">
<form id="form">
<label for="sort">Sorting Method:</label>
<select id="sort">
<option value="recent">Most Recent</option>
<option value="top">Top Rated</option>
</select>
<input type="search" id="search-bar" name="searchBar" placeholder="Search tags...">
<button id="clear-search">Clear Search</button>
</form>
<img src="./assets/images/search_button.png" alt="SEARCH BTN" id="search-btn" />
</div> </div>
<div style="width: 20%;">
<div class="center-display">
<img src="./assets/images/create_button.png" alt="CREATE" id="create-btn" title="Add an entry!"
onclick="window.location.assign('./CreatePage.html')" />
<h2 id="recent-reviews-text"> Recent Reviews </h2>
<img src="./assets/images/create_button.png" id="create-btn-invis" draggable="false" />
</div> </div>
<div class="review-container" id="review-container"></div>
</div> </div>
</main> <div style="width: 20%;">
</body> </div>
</html> </div>
</main>
</body>
</html>

View File

@ -52,18 +52,33 @@ body {
.search-bar { .search-bar {
display: flex; display: flex;
justify-content: center; justify-content: center;
font-family: 'Century Gothic';
font-weight: bold;
color: #516754;
}
#sort{
margin-right: 1em;
} }
.search-bar > form { .search-bar > form {
float: right; float: right;
padding: 6px 10px; padding: 6px 10px;
margin-top: 8px; /*
margin-top: 8px;
margin-right: 16px; margin-right: 16px;
*/
background: rgb(239 183 183); background: rgb(239 183 183);
font-size: 17px; font-size: 17px;
border: none; border: none;
border-radius: 12px; border-radius: 12px;
cursor: pointer; }
#search-btn {
position: relative;
align-self: center;
width: 30px;
height: 30px;
} }
#recent-reviews-text { #recent-reviews-text {
@ -78,6 +93,17 @@ img#create-btn {
align-self: center; align-self: center;
padding-left: 2.5%; padding-left: 2.5%;
padding-right: 2.5%; padding-right: 2.5%;
cursor: pointer;
width: 10%;
height: 10%;
}
img#create-btn-invis {
opacity: 0%;
padding-left: 2.5%;
padding-right: 2.5%;
width: 10%;
height: 10%;
} }
.review-container { .review-container {