mirror of
https://github.com/cse110-fa22-group29/cse110-fa22-group29.git
synced 2024-12-26 17:09:09 +00:00
Merge pull request #102 from cse110-fa22-group29/filter-sort
Filter and Sort Functionality
This commit is contained in:
commit
f0f706e575
Binary file not shown.
Before Width: | Height: | Size: 2.0 KiB |
BIN
source/assets/images/create_button.png
Normal file
BIN
source/assets/images/create_button.png
Normal file
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 |
BIN
source/assets/images/search_button.png
Normal file
BIN
source/assets/images/search_button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
@ -97,10 +97,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 {
|
||||
@ -157,7 +158,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) {
|
||||
@ -169,7 +170,7 @@ class ReviewCard extends HTMLElement {
|
||||
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);
|
||||
@ -251,11 +252,11 @@ class ReviewCard extends HTMLElement {
|
||||
dataContainer["reviewID"] = this.reviewID;
|
||||
|
||||
//get image
|
||||
let mealImg = this.shadowEl.getElementById("a-mealImg");
|
||||
let mealImg = this.shadowEl.getElementById("a-meal-img");
|
||||
dataContainer["mealImg"] = mealImg.getAttribute("src");
|
||||
|
||||
//get meal name
|
||||
let mealLabel = this.shadowEl.getElementById("a-mealName");
|
||||
let mealLabel = this.shadowEl.getElementById("a-meal-name");
|
||||
dataContainer["mealName"] = mealLabel.innerHTML;
|
||||
|
||||
//get comment section
|
||||
|
@ -99,8 +99,10 @@ function setupUpdate(){
|
||||
while (tagContainer.firstChild) {
|
||||
tagContainer.removeChild(tagContainer.firstChild);
|
||||
}
|
||||
let tagSetVal = currReview["tags"][i].toLowerCase();
|
||||
|
||||
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");
|
||||
|
@ -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");
|
||||
|
@ -14,6 +14,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"));
|
||||
tempIdArr.push(nextReviewId);
|
||||
@ -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
|
||||
@ -148,3 +222,46 @@ export function getAllReviewsFromStorage() {
|
||||
}
|
||||
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,23 +20,132 @@ 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 () => {
|
||||
|
@ -1,56 +1,65 @@
|
||||
<!DOCTYPE html>
|
||||
<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-->
|
||||
<link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico">
|
||||
<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>
|
||||
|
||||
<!-- Recipe Card Custom Element -->
|
||||
<script src="assets/scripts/ReviewCard.js" type="module"></script>
|
||||
<!--Add Favicon-->
|
||||
<link rel="icon" type="image/x-icon" href="./assets/images/favicon.ico">
|
||||
|
||||
<!-- 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">
|
||||
<input type="search" id="searching" name="searchBar" placeholder="Search journal...">
|
||||
<button class="click" type="search"> Search </button>
|
||||
<div class="Filter-box">
|
||||
<!-- Recipe Card Custom Element -->
|
||||
<script src="assets/scripts/ReviewCard.js" type="module"></script>
|
||||
|
||||
</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;"/>
|
||||
<!-- 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>
|
||||
|
||||
</div>
|
||||
<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="review-container" id="review-container"></div>
|
||||
<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 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 class="review-container" id="review-container"></div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
<div style="width: 20%;">
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
|
||||
</html>
|
@ -52,18 +52,33 @@ body {
|
||||
.search-bar {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
font-family: 'Century Gothic';
|
||||
font-weight: bold;
|
||||
color: #516754;
|
||||
}
|
||||
|
||||
#sort{
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.search-bar > form {
|
||||
float: right;
|
||||
padding: 6px 10px;
|
||||
/*
|
||||
margin-top: 8px;
|
||||
margin-right: 16px;
|
||||
*/
|
||||
background: rgb(239 183 183);
|
||||
font-size: 17px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#search-btn {
|
||||
position: relative;
|
||||
align-self: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
#recent-reviews-text {
|
||||
@ -78,6 +93,17 @@ img#create-btn {
|
||||
align-self: center;
|
||||
padding-left: 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 {
|
||||
|
Loading…
Reference in New Issue
Block a user