From 467828d388d2d19b99c3efbb60ed8056f5900a39 Mon Sep 17 00:00:00 2001 From: rheabhutada02 <83424582+rheabhutada02@users.noreply.github.com> Date: Wed, 16 Nov 2022 15:48:10 -0800 Subject: [PATCH 01/15] Rename 11822-sprint1day2.md to 110822-sprint1day2.md --- admin/meetings/{11822-sprint1day2.md => 110822-sprint1day2.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename admin/meetings/{11822-sprint1day2.md => 110822-sprint1day2.md} (100%) diff --git a/admin/meetings/11822-sprint1day2.md b/admin/meetings/110822-sprint1day2.md similarity index 100% rename from admin/meetings/11822-sprint1day2.md rename to admin/meetings/110822-sprint1day2.md From 41905a219b40fdd73ef88c7336c067ad9b6ec4f2 Mon Sep 17 00:00:00 2001 From: rheabhutada02 <83424582+rheabhutada02@users.noreply.github.com> Date: Wed, 16 Nov 2022 15:54:50 -0800 Subject: [PATCH 02/15] updated checkin6.md --- admin/meetings/checkin6.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 admin/meetings/checkin6.md diff --git a/admin/meetings/checkin6.md b/admin/meetings/checkin6.md new file mode 100644 index 0000000..0c37037 --- /dev/null +++ b/admin/meetings/checkin6.md @@ -0,0 +1,33 @@ +# Meeting Minutes (11/16/2022) +## Team 29: Hackers1995 +## Meeting Topic: Weekly TA Catchup with Gagan +We are meeting with Gagan to discuss Checkpoint 1 and Sprint 2 resolutions. + +## Attendance +1. Rhea Bhutada +2. George Dubinin +3. Gagan Gopalaiah +4. Kara Hoagland + +## Meeting Details +- When: 11/16/2022 at 3:30PM +- Where: Zoom + +## Agenda: + +## Discussion Points by Gagan +- Updated Gagan on Sprint 1 + - looked at Girhub actions + - looked at the published page so far + - discussed retrospective +- Upcoming Assignments + - we have to come up with a video on the status of our app + - ramp up the styling part, so u can brag about the design of the app + - this video is supposed to encourage healthy competition +- Other Concerns + - JSDocs - not primary concern right now + - GitHub Pages vs. Netlify + - Gagan sees Netlify as more professional and not to difficult to implement + +## End Time +- 11/09/2022 at 3:45PM From 56dceb5edb200cfa82bd1df2a05574b67d71abf5 Mon Sep 17 00:00:00 2001 From: rheabhutada02 <83424582+rheabhutada02@users.noreply.github.com> Date: Wed, 16 Nov 2022 15:55:18 -0800 Subject: [PATCH 03/15] Rename checkin6.md to 111622-checkin6.md --- admin/meetings/{checkin6.md => 111622-checkin6.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename admin/meetings/{checkin6.md => 111622-checkin6.md} (100%) diff --git a/admin/meetings/checkin6.md b/admin/meetings/111622-checkin6.md similarity index 100% rename from admin/meetings/checkin6.md rename to admin/meetings/111622-checkin6.md From 85dc0544c707333af9ccd789036dab985cb11f23 Mon Sep 17 00:00:00 2001 From: Sanjit Joseph <78522615+sm-joseph@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:19:26 -0800 Subject: [PATCH 04/15] Add star rating system to main page --- source/static/ReviewCard.css | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/source/static/ReviewCard.css b/source/static/ReviewCard.css index 2c69f0b..20feb3a 100644 --- a/source/static/ReviewCard.css +++ b/source/static/ReviewCard.css @@ -81,3 +81,49 @@ main { background-color: rgb(254 171 171); border-color: red; } + +.hidden, +.rating:not(:checked) > input { /* Hide radio circles while star rating */ +display: none; +} + +/* Unchecked stars */ +.rating:not(:checked) > label { + /* Make stars line up sideways and not vertically */ + float:right; + + /* Hide label text */ + width:1em; + overflow:hidden; + white-space:nowrap; + + font-size:200%; + line-height:1.2; + color:#b3b3cc; +} + +.rating:not(:checked) > label:before { + content:'★'; +} + +/* Checked star color */ +.rating > input:checked ~ label { + color: #FFBF00; +} + +.rating:not(:checked) > label:hover, +.rating:not(:checked) > label:hover ~ label { + color: orangered; +} + +.rating > input:checked + label:hover, +.rating > input:checked + label:hover ~ label, +.rating > input:checked ~ label:hover, +.rating > input:checked ~ label:hover ~ label, +.rating > label:hover ~ input:checked ~ label { + color: orangered; +} + +.rating > label:active { + position:relative; +} From f9074a2bc6d62237b65591e68ea61fa2b1f6bd29 Mon Sep 17 00:00:00 2001 From: Sanjit Joseph <78522615+sm-joseph@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:31:51 -0800 Subject: [PATCH 05/15] Attempt CSS linting fix --- source/static/ReviewCard.css | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/source/static/ReviewCard.css b/source/static/ReviewCard.css index 20feb3a..33b8dc1 100644 --- a/source/static/ReviewCard.css +++ b/source/static/ReviewCard.css @@ -82,33 +82,33 @@ main { border-color: red; } -.hidden, +.hidden, .rating:not(:checked) > input { /* Hide radio circles while star rating */ -display: none; + display: none; } /* Unchecked stars */ .rating:not(:checked) > label { /* Make stars line up sideways and not vertically */ - float:right; + float: right; /* Hide label text */ - width:1em; - overflow:hidden; - white-space:nowrap; + width: 1em; + overflow: hidden; + white-space: nowrap; - font-size:200%; - line-height:1.2; - color:#b3b3cc; + font-size: 200%; + line-height: 1.2; + color: #b3b3cc; } .rating:not(:checked) > label:before { - content:'★'; + content: "★"; } /* Checked star color */ .rating > input:checked ~ label { - color: #FFBF00; + color: #ffbf00; } .rating:not(:checked) > label:hover, @@ -116,6 +116,10 @@ display: none; color: orangered; } +.rating > label:active { + position: relative; +} + .rating > input:checked + label:hover, .rating > input:checked + label:hover ~ label, .rating > input:checked ~ label:hover, @@ -123,7 +127,3 @@ display: none; .rating > label:hover ~ input:checked ~ label { color: orangered; } - -.rating > label:active { - position:relative; -} From 004e5cc2a23ecffadd4a0014ce999b9ddac14c02 Mon Sep 17 00:00:00 2001 From: Sanjit Joseph <78522615+sm-joseph@users.noreply.github.com> Date: Thu, 17 Nov 2022 12:44:19 -0800 Subject: [PATCH 06/15] Attempt CSS linting fix - v2 --- source/static/ReviewCard.css | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/source/static/ReviewCard.css b/source/static/ReviewCard.css index 33b8dc1..87b5958 100644 --- a/source/static/ReviewCard.css +++ b/source/static/ReviewCard.css @@ -90,19 +90,24 @@ main { /* Unchecked stars */ .rating:not(:checked) > label { /* Make stars line up sideways and not vertically */ - float: right; + float: right; /* Hide label text */ width: 1em; overflow: hidden; white-space: nowrap; + /* Star default color and size */ font-size: 200%; line-height: 1.2; color: #b3b3cc; } -.rating:not(:checked) > label:before { +.rating > label:active { + position: relative; +} + +.rating:not(:checked) > label::before { content: "★"; } @@ -116,13 +121,9 @@ main { color: orangered; } -.rating > label:active { - position: relative; -} - .rating > input:checked + label:hover, -.rating > input:checked + label:hover ~ label, .rating > input:checked ~ label:hover, +.rating > input:checked + label:hover ~ label, .rating > input:checked ~ label:hover ~ label, .rating > label:hover ~ input:checked ~ label { color: orangered; From 35f44049a263d598ce5a89376c3d1922fc1d62a7 Mon Sep 17 00:00:00 2001 From: rheabhutada02 <83424582+rheabhutada02@users.noreply.github.com> Date: Thu, 17 Nov 2022 18:45:53 -0800 Subject: [PATCH 07/15] updated crud features to work better Co-authored-by: look-its-ashton Co-authored-by: Kara Hoagland Co-authored-by: Gavyn Ezell --- source/CreatePage.html | 8 +-- source/ReviewDetails.html | 1 + source/assets/scripts/CreatePage.js | 78 ++++++++++++++++++++++++++ source/assets/scripts/ReviewCard.js | 39 +++++-------- source/assets/scripts/ReviewDetails.js | 68 ++++++++++------------ source/assets/scripts/localStorage.js | 18 ++++-- source/assets/scripts/main.js | 14 +++-- source/index.html | 6 +- 8 files changed, 150 insertions(+), 82 deletions(-) create mode 100644 source/assets/scripts/CreatePage.js diff --git a/source/CreatePage.html b/source/CreatePage.html index 64dfe78..bc37e7a 100644 --- a/source/CreatePage.html +++ b/source/CreatePage.html @@ -14,12 +14,13 @@ - - + + +
Pic: @@ -69,8 +70,7 @@
- - +
diff --git a/source/ReviewDetails.html b/source/ReviewDetails.html index 74b6365..c790b4e 100644 --- a/source/ReviewDetails.html +++ b/source/ReviewDetails.html @@ -19,6 +19,7 @@
+
diff --git a/source/assets/scripts/CreatePage.js b/source/assets/scripts/CreatePage.js new file mode 100644 index 0000000..f334be6 --- /dev/null +++ b/source/assets/scripts/CreatePage.js @@ -0,0 +1,78 @@ +window.addEventListener("DOMContentLoaded", init); + +function init() { + // get next id + + // creates the key + initFormHandler(); + +} + +function initFormHandler() { + + //accessing form components + let tagContainer = document.getElementById("tag-container-form"); + let form = document.querySelector("form"); + + form.addEventListener("submit", function(e){ + /* + * User submits the form for their review. + * We create reviewCard and put in storage + */ + e.preventDefault(); + let formData = new FormData(form); + let reviewObject = {}; + for (let [key, value] of formData) { + console.log(`${key}`); + console.log(`${value}`); + if (`${key}` !== "tag-form") { + reviewObject[`${key}`] = `${value}`; + } + } + reviewObject["tags"] = []; + + let tags = document.querySelectorAll(".tag"); + for(let i = 0; i < tags.length; i ++) { + reviewObject["tags"].push(tags[i].innerHTML); + tagContainer.removeChild(tags[i]); + } + + //grabbing the nextID, and putting our review object in storage associated with the ID + let nextReviewId = JSON.parse(localStorage.getItem("nextID")); + reviewObject["reviewID"] = nextReviewId; + + localStorage.setItem("review"+nextReviewId, JSON.stringify(reviewObject)); + sessionStorage.setItem("currID", JSON.stringify(nextReviewId)); + + //updating our activeIDS list + let tempIdArr = JSON.parse(localStorage.getItem("activeIDS")); + tempIdArr.push(nextReviewId); + localStorage.setItem("activeIDS", JSON.stringify(tempIdArr)); + + + //increment nextID for next review creation + nextReviewId++; + localStorage.setItem("nextID", JSON.stringify(nextReviewId)); + + window.location.assign('./ReviewDetails.html'); + + }); + + let tagAddBtn = document.getElementById("tagAdd"); + tagAddBtn.addEventListener("click", ()=> { + let tagField = document.getElementById("tag-form"); + if (tagField.value.length > 0) { + let tagLabel = document.createElement("label"); + tagLabel.innerHTML = tagField.value; + tagLabel.setAttribute("class","tag"); + tagLabel.addEventListener("click",()=> { + tagContainer.removeChild(tagLabel); + }); + + tagContainer.append(tagLabel); + tagField.value = ""; + + } + }); + +} diff --git a/source/assets/scripts/ReviewCard.js b/source/assets/scripts/ReviewCard.js index 07df6a6..d7bd1ce 100644 --- a/source/assets/scripts/ReviewCard.js +++ b/source/assets/scripts/ReviewCard.js @@ -6,7 +6,6 @@ class ReviewCard extends HTMLElement { constructor() { super(); - let shadowEl = this.attachShadow({mode:"open"}); let articleEl = document.createElement("article"); @@ -88,9 +87,9 @@ class ReviewCard extends HTMLElement { //attach event listener to each recipe-card this.addEventListener("click", (event) => { console.log(event.target); - console.log(event.target.data); + console.log(event.target.reviewId); //Option 1: sending current data to second html page using localStorage (could also just store index) - sessionStorage.setItem("current", JSON.stringify(event.target.data)); + sessionStorage.setItem("currID", JSON.stringify(event.target.data.reviewID)); window.location.assign("./ReviewDetails.html"); /* //Option 2: sending current data to second html page using string query w/ url (currently not storing value) @@ -133,12 +132,18 @@ class ReviewCard extends HTMLElement { let articleEl = this.shadowEl.querySelector("article"); // setting the article elements for the review card + this.reviewID = data["reviewID"]; //image setup let mealImg = document.createElement("img"); mealImg.setAttribute("id", "a-mealImg"); - mealImg.setAttribute("src",data["mealImg"]); mealImg.setAttribute("alt",data["imgAlt"]); + if(data["mealImg"] != ""){ + mealImg.setAttribute("src",data["mealImg"]); + } + else{ + mealImg.setAttribute("src", "./assets/images/icons/plate_with_cutlery.png"); + } //meal name setup let mealLabel = document.createElement("label"); @@ -147,26 +152,6 @@ class ReviewCard extends HTMLElement { mealLabel.innerHTML = data["mealName"]; //restaurant name setup - /* - //review page link - //giving it functionality to save the review card's info to session storage for loading the review page - let reviewLink = document.createElement('a'); - reviewLink.setAttribute('href','./review.html') - reviewLink.innerHTML = 'review page' - reviewLink.addEventListener('click', () => { - sessionStorage.clear(); - let currReview = { - "imgSrc": data['imgSrc'], - "imgAlt": data['imgAlt'], - "mealName": data['mealName'], - "restaurant": data['restaurant'], - "comments": data['comments'], - "rating": data['rating'], - "tags": data['tags'] - } - sessionStorage.setItem('currReview', JSON.stringify(currReview)); - }); -*/ let restaurantLabel = document.createElement("label"); restaurantLabel.setAttribute("id", "a-restaurant"); restaurantLabel.setAttribute("class","restaurant-name"); @@ -197,14 +182,15 @@ class ReviewCard extends HTMLElement { for (let i = 0; i < data["tags"].length; i++) { let newTag = document.createElement("label"); newTag.setAttribute("class","tag"); - newTag.innerHTML = data["tags"][i] + " "; + newTag.innerHTML = data["tags"][i]; tagContainer.append(newTag); } } + //adding final ID to data! + articleEl.append(mealImg); articleEl.append(mealLabel); - //articleEl.append(reviewLink) articleEl.append(restaurantLabel); articleEl.append(ratingDiv); articleEl.append(tagContainer); @@ -237,6 +223,7 @@ class ReviewCard extends HTMLElement { let dataContainer = {}; // getting the article elements for the review card + dataContainer["reviewID"] = this.reviewID; //get image let mealImg = this.shadowEl.getElementById("a-mealImg"); diff --git a/source/assets/scripts/ReviewDetails.js b/source/assets/scripts/ReviewDetails.js index 8447ebe..70a0b2d 100644 --- a/source/assets/scripts/ReviewDetails.js +++ b/source/assets/scripts/ReviewDetails.js @@ -11,23 +11,18 @@ function init(){ function setupDelete(){ let deleteBtn = document.getElementById("delete-btn"); - let reviews = getReviewsFromStorage(); - let current = JSON.parse(sessionStorage.getItem("current")); + let currID = JSON.parse(sessionStorage.getItem("currID")); + let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); deleteBtn.addEventListener("click", function(){ if(window.confirm("Are you sure you want to delete this entry?")){ - //delete function - if(current){ - console.log(current); - for(let i = 0; i < reviews.length; i++){ - console.log(reviews[i]); - if(reviews[i]["mealName"] == current["mealName"] && reviews[i]["restaurant"] == current["restaurant"]){ - console.log("match found"); - reviews.splice(i,1); - saveReviewsToStorage(reviews); - sessionStorage.removeItem("current"); - window.location.assign("./index.html"); - break; - } + for (let i in activeIDS) { + if (activeIDS[i] == currID) { + activeIDS.splice(i,1); + localStorage.setItem('activeIDS', JSON.stringify(activeIDS)); + sessionStorage.removeItem('currID'); + localStorage.removeItem(`review${currID}`); + window.location.assign("./index.html"); + break; } } } @@ -36,30 +31,31 @@ function setupDelete(){ function setupUpdate(){ let updateBtn = document.getElementById("update-btn"); - let reviews = getReviewsFromStorage(); - let current = JSON.parse(sessionStorage.getItem("current")); + let currID = JSON.parse(sessionStorage.getItem("currID")); + let currReview = JSON.parse(localStorage.getItem(`review${currID}`)); let form = document.getElementById("update-food-entry"); updateBtn.addEventListener("click", function(){ //update function - if(current){ - console.log(current); + if(currReview){ form.style.display = "block"; let tagContainer = document.getElementById("tag-container-form"); - console.log(document.querySelectorAll("#update-food-entry input")); //Set value of each input element to current's values - document.getElementById("mealImg").defaultValue = current["mealImg"]; - document.getElementById("imgAlt").defaultValue = current["imgAlt"]; - document.getElementById("mealName").defaultValue = current["mealName"]; - document.getElementById("comments").textContent = current["comments"]; - document.getElementById("rating-" + `${current["rating"]}`).checked = true; - document.getElementById("restaurant").defaultValue = current["restaurant"]; + document.getElementById("mealImg").defaultValue = currReview["mealImg"]; + document.getElementById("imgAlt").defaultValue = currReview["imgAlt"]; + document.getElementById("mealName").defaultValue = currReview["mealName"]; + document.getElementById("comments").textContent = currReview["comments"]; + document.getElementById("s" + `${currReview["rating"]}`).checked = true; + document.getElementById("restaurant").defaultValue = currReview["restaurant"]; - if(current["tags"]){ - for (let i = 0; i < current["tags"].length; i++) { + if(currReview["tags"]){ + while (tagContainer.firstChild) { + tagContainer.removeChild(tagContainer.firstChild); + } + for (let i = 0; i < currReview["tags"].length; i++) { let newTag = document.createElement("label"); newTag.setAttribute("class","tag"); - newTag.innerHTML = current["tags"][i] + " "; + newTag.innerHTML = currReview["tags"][i]; newTag.addEventListener("click",()=> { tagContainer.removeChild(newTag); }); @@ -89,16 +85,10 @@ function setupUpdate(){ tagContainer.removeChild(tags[i]); } - for(let i = 0; i < reviews.length; i++){ - console.log(reviews[i]); - if(reviews[i]["mealName"] == current["mealName"] && reviews[i]["restaurant"] == current["restaurant"]){ - console.log("match found"); - reviews.splice(i,1,newData); - saveReviewsToStorage(reviews); - sessionStorage.setItem("current", JSON.stringify(newData)); - break; - } - } + newData["reviewID"] = currID; + + + localStorage.setItem("review"+currID, JSON.stringify(newData)); form.style.display = "none"; diff --git a/source/assets/scripts/localStorage.js b/source/assets/scripts/localStorage.js index 48fc891..f160d1d 100644 --- a/source/assets/scripts/localStorage.js +++ b/source/assets/scripts/localStorage.js @@ -2,11 +2,19 @@ * @returns {Array} An array of reviews found in localStorage */ export function getReviewsFromStorage() { - let result = JSON.parse(localStorage.getItem("reviews")); - if (result) { - return result; + 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)); } - return new Array(0); + //iterate thru activeIDS + let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); + let reviews = [] + for (let i = 0; i < activeIDS.length; i++) { + let currReview = JSON.parse(localStorage.getItem('review'+activeIDS[i])); + reviews.push(currReview); + } + return reviews; } /** @@ -15,5 +23,5 @@ export function getReviewsFromStorage() { * @param {Array} reviews An array of reviews */ export function saveReviewsToStorage(reviews) { - localStorage.setItem("reviews", JSON.stringify(reviews)); + localStorage.setItem(`review${reviewId}`, JSON.stringify(reviews)); } diff --git a/source/assets/scripts/main.js b/source/assets/scripts/main.js index 9d37c44..0c76db4 100644 --- a/source/assets/scripts/main.js +++ b/source/assets/scripts/main.js @@ -13,6 +13,7 @@ function init() { initFormHandler(); } + /** * @param {Array} reviews An array of reviews */ @@ -33,14 +34,14 @@ function addReviewsToDocument(reviews) { */ function initFormHandler() { - /* //btn to create form (could be its own function?) - let createBtn = document.getElementById("create"); + let createBtn = document.getElementById("create-btn"); createBtn.addEventListener("click", function(){ window.location.assign("./CreatePage.html"); - });*/ - + }); + //accessing form components + /* let tagContainer = document.getElementById("tag-container-form"); let form = document.querySelector("form"); @@ -48,7 +49,6 @@ function initFormHandler() { /* * User submits the form for their review. * We create reviewCard and put in storage - */ let formData = new FormData(form); let reviewObject = {}; for (let [key, value] of formData) { @@ -74,6 +74,9 @@ function initFormHandler() { let mainEl = document.querySelector("main"); mainEl.append(newReview); + // TODO: assign an ID to be used for referencing this object form the activeIDs array and the tag arrays + let ID = localStorage.nextID; + let storedReviews = getReviewsFromStorage(); storedReviews.push(reviewObject); saveReviewsToStorage(storedReviews); @@ -115,5 +118,6 @@ function initFormHandler() { } }); + */ } diff --git a/source/index.html b/source/index.html index 4418ea0..c83fe94 100644 --- a/source/index.html +++ b/source/index.html @@ -22,8 +22,8 @@
- -
+ + +
--> From 6493fbd17197aff98519726fa5b2422681880465 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 18 Nov 2022 07:13:53 +0000 Subject: [PATCH 08/15] modularize localStorage calls into localStorage.js in preparation for unit testing --- source/assets/scripts/CreatePage.js | 18 +-- source/assets/scripts/ReviewDetails.js | 147 ++++++++++++------------- source/assets/scripts/localStorage.js | 78 ++++++++++--- source/assets/scripts/main.js | 4 +- 4 files changed, 139 insertions(+), 108 deletions(-) diff --git a/source/assets/scripts/CreatePage.js b/source/assets/scripts/CreatePage.js index f334be6..fca6dc5 100644 --- a/source/assets/scripts/CreatePage.js +++ b/source/assets/scripts/CreatePage.js @@ -1,3 +1,5 @@ +import { newReviewToStorage } from "./localStorage.js"; + window.addEventListener("DOMContentLoaded", init); function init() { @@ -37,23 +39,9 @@ function initFormHandler() { tagContainer.removeChild(tags[i]); } - //grabbing the nextID, and putting our review object in storage associated with the ID - let nextReviewId = JSON.parse(localStorage.getItem("nextID")); - reviewObject["reviewID"] = nextReviewId; - - localStorage.setItem("review"+nextReviewId, JSON.stringify(reviewObject)); + let nextReviewId = newReviewToStorage(reviewObject); sessionStorage.setItem("currID", JSON.stringify(nextReviewId)); - //updating our activeIDS list - let tempIdArr = JSON.parse(localStorage.getItem("activeIDS")); - tempIdArr.push(nextReviewId); - localStorage.setItem("activeIDS", JSON.stringify(tempIdArr)); - - - //increment nextID for next review creation - nextReviewId++; - localStorage.setItem("nextID", JSON.stringify(nextReviewId)); - window.location.assign('./ReviewDetails.html'); }); diff --git a/source/assets/scripts/ReviewDetails.js b/source/assets/scripts/ReviewDetails.js index 70a0b2d..f2545fa 100644 --- a/source/assets/scripts/ReviewDetails.js +++ b/source/assets/scripts/ReviewDetails.js @@ -1,5 +1,5 @@ //reviewDetails.js -import {getReviewsFromStorage, saveReviewsToStorage} from "./localStorage.js"; +import {deleteReviewFromStorage, getReviewFromStorage, updateReviewToStorage} from "./localStorage.js"; // Run the init() function when the page has loaded window.addEventListener("DOMContentLoaded", init); @@ -12,19 +12,11 @@ function init(){ function setupDelete(){ let deleteBtn = document.getElementById("delete-btn"); let currID = JSON.parse(sessionStorage.getItem("currID")); - let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); deleteBtn.addEventListener("click", function(){ if(window.confirm("Are you sure you want to delete this entry?")){ - for (let i in activeIDS) { - if (activeIDS[i] == currID) { - activeIDS.splice(i,1); - localStorage.setItem('activeIDS', JSON.stringify(activeIDS)); - sessionStorage.removeItem('currID'); - localStorage.removeItem(`review${currID}`); - window.location.assign("./index.html"); - break; - } - } + deleteReviewFromStorage(currID); + sessionStorage.removeItem('currID'); + window.location.assign("./index.html"); } }); } @@ -32,83 +24,82 @@ function setupDelete(){ function setupUpdate(){ let updateBtn = document.getElementById("update-btn"); let currID = JSON.parse(sessionStorage.getItem("currID")); - let currReview = JSON.parse(localStorage.getItem(`review${currID}`)); + let currReview = getReviewFromStorage(currID); let form = document.getElementById("update-food-entry"); updateBtn.addEventListener("click", function(){ //update function - if(currReview){ - form.style.display = "block"; - let tagContainer = document.getElementById("tag-container-form"); - //Set value of each input element to current's values - document.getElementById("mealImg").defaultValue = currReview["mealImg"]; - document.getElementById("imgAlt").defaultValue = currReview["imgAlt"]; - document.getElementById("mealName").defaultValue = currReview["mealName"]; - document.getElementById("comments").textContent = currReview["comments"]; - document.getElementById("s" + `${currReview["rating"]}`).checked = true; - document.getElementById("restaurant").defaultValue = currReview["restaurant"]; + form.style.display = "block"; + form.classList.remove("hidden"); + let tagContainer = document.getElementById("tag-container-form"); - if(currReview["tags"]){ - while (tagContainer.firstChild) { - tagContainer.removeChild(tagContainer.firstChild); - } - for (let i = 0; i < currReview["tags"].length; i++) { - let newTag = document.createElement("label"); - newTag.setAttribute("class","tag"); - newTag.innerHTML = currReview["tags"][i]; - newTag.addEventListener("click",()=> { - tagContainer.removeChild(newTag); - }); - tagContainer.append(newTag); + //Set value of each input element to current's values + document.getElementById("mealImg").defaultValue = currReview["mealImg"]; + document.getElementById("imgAlt").defaultValue = currReview["imgAlt"]; + document.getElementById("mealName").defaultValue = currReview["mealName"]; + document.getElementById("comments").textContent = currReview["comments"]; + document.getElementById("s" + `${currReview["rating"]}`).checked = true; + document.getElementById("restaurant").defaultValue = currReview["restaurant"]; + + if(currReview["tags"]){ + while (tagContainer.firstChild) { + tagContainer.removeChild(tagContainer.firstChild); + } + for (let i = 0; i < currReview["tags"].length; i++) { + let newTag = document.createElement("label"); + newTag.setAttribute("class","tag"); + newTag.innerHTML = currReview["tags"][i]; + newTag.addEventListener("click",()=> { + tagContainer.removeChild(newTag); + }); + tagContainer.append(newTag); + } + } + //Take formdata values as newData when submit + form.addEventListener("submit", function(){ + /* + * User submits the form for their review. + * We create reviewCard and put in storage + */ + let formData = new FormData(form); + let newData = {}; + for (let [key, value] of formData) { + console.log(`${key}`); + console.log(`${value}`); + if (`${key}` !== "tag-form") { + newData[`${key}`] = `${value}`; } } - //Take formdata values as newData when submit - form.addEventListener("submit", function(){ - /* - * User submits the form for their review. - * We create reviewCard and put in storage - */ - let formData = new FormData(form); - let newData = {}; - for (let [key, value] of formData) { - console.log(`${key}`); - console.log(`${value}`); - if (`${key}` !== "tag-form") { - newData[`${key}`] = `${value}`; - } - } - newData["tags"] = []; - - let tags = document.querySelectorAll(".tag"); - for(let i = 0; i < tags.length; i ++) { - newData["tags"].push(tags[i].innerHTML); - tagContainer.removeChild(tags[i]); - } + newData["tags"] = []; + + let tags = document.querySelectorAll(".tag"); + for(let i = 0; i < tags.length; i ++) { + newData["tags"].push(tags[i].innerHTML); + tagContainer.removeChild(tags[i]); + } - newData["reviewID"] = currID; + newData["reviewID"] = currID; + updateReviewToStorage(currID, newData); - localStorage.setItem("review"+currID, JSON.stringify(newData)); + form.style.display = "none"; - form.style.display = "none"; + }); - }); - - let tagAddBtn = document.getElementById("tag-add-btn"); - tagAddBtn.addEventListener("click", ()=> { - let tagField = document.getElementById("tag-form"); - if (tagField.value.length > 0) { - let tagLabel = document.createElement("label"); - tagLabel.innerHTML = tagField.value; - tagLabel.setAttribute("class","tag"); - tagLabel.addEventListener("click",()=> { - tagContainer.removeChild(tagLabel); - }); - - tagContainer.append(tagLabel); - tagField.value = ""; - } - }); - } + let tagAddBtn = document.getElementById("tag-add-btn"); + tagAddBtn.addEventListener("click", ()=> { + let tagField = document.getElementById("tag-form"); + if (tagField.value.length > 0) { + let tagLabel = document.createElement("label"); + tagLabel.innerHTML = tagField.value; + tagLabel.setAttribute("class","tag"); + tagLabel.addEventListener("click",()=> { + tagContainer.removeChild(tagLabel); + }); + + tagContainer.append(tagLabel); + tagField.value = ""; + } + }); }); } diff --git a/source/assets/scripts/localStorage.js b/source/assets/scripts/localStorage.js index f160d1d..62b834d 100644 --- a/source/assets/scripts/localStorage.js +++ b/source/assets/scripts/localStorage.js @@ -1,7 +1,68 @@ /** - * @returns {Array} An array of reviews found in localStorage + * Creates a new review to storage and performs related meta tasks + * @param {Object} review to store + * @return {number} ID of the newly added review */ -export function getReviewsFromStorage() { +export function newReviewToStorage(review){ + //grabbing the nextID, and putting our review object in storage associated with the ID + let nextReviewId = JSON.parse(localStorage.getItem("nextID")); + review["reviewID"] = nextReviewId; + + // set the review entry to the review object + localStorage.setItem(`review${nextReviewId}`, JSON.stringify(review)); + + //updating our activeIDS list + let tempIdArr = JSON.parse(localStorage.getItem("activeIDS")); + tempIdArr.push(nextReviewId); + localStorage.setItem("activeIDS", JSON.stringify(tempIdArr)); + + //increment nextID for next review creation + nextReviewId++; + localStorage.setItem("nextID", JSON.stringify(nextReviewId)); + + return nextReviewId; +} + +/** + * Gets a single review by ID from storage + * @param {string} ID of the review to get + * @returns {Object} review object corresponding to param ID + */ +export function getReviewFromStorage(ID){ + return JSON.parse(localStorage.getItem(`review${ID}`)); +} + +/** + * Updates a single review by ID to storage + * @param {string} ID of review to update + * @param {Object} review to store + */ +export function updateReviewToStorage(ID, review){ + // set the review entry with ID to the review object + localStorage.setItem(`review${ID}`, JSON.stringify(review)); +} + +/** + * Deletes a review by ID from storage + * @param {string} ID of the review to delete + */ +export function deleteReviewFromStorage(ID){ + let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); + + for (let i in activeIDS) { + if (activeIDS[i] == ID) { + activeIDS.splice(i,1); + localStorage.setItem('activeIDS', JSON.stringify(activeIDS)); + localStorage.removeItem(`review${ID}`) + return; + } + } + + console.error(`could not find review${ID} in localStorage`); +} + +// legacy function +export function getAllReviewsFromStorage() { if (!(localStorage.getItem("activeIDS"))) { // we wanna init the active ID array and start the nextID count localStorage.setItem("activeIDS", JSON.stringify([])); @@ -11,17 +72,8 @@ export function getReviewsFromStorage() { let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); let reviews = [] for (let i = 0; i < activeIDS.length; i++) { - let currReview = JSON.parse(localStorage.getItem('review'+activeIDS[i])); + let currReview = JSON.parse(localStorage.getItem(`review${activeIDS[i]}`)); reviews.push(currReview); } return reviews; -} - -/** - * Takes in an array of reviews, converts it to a string, and then - * saves that string to 'reviews' in localStorage - * @param {Array} reviews An array of reviews - */ -export function saveReviewsToStorage(reviews) { - localStorage.setItem(`review${reviewId}`, JSON.stringify(reviews)); -} +} \ No newline at end of file diff --git a/source/assets/scripts/main.js b/source/assets/scripts/main.js index 0c76db4..331492e 100644 --- a/source/assets/scripts/main.js +++ b/source/assets/scripts/main.js @@ -1,12 +1,12 @@ // main.js -import {getReviewsFromStorage, saveReviewsToStorage} from "./localStorage.js"; +import {getAllReviewsFromStorage} 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 = getReviewsFromStorage(); + let reviews = getAllReviewsFromStorage(); // Add each reviews to the
element addReviewsToDocument(reviews); // Add the event listeners to the form elements From 5e833386687d511ce074c7bf248ebaa2fe0c4b64 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 18 Nov 2022 07:51:08 +0000 Subject: [PATCH 09/15] update unit tests to match new localStorage implementations --- source/assets/scripts/localStorage.test.js | 113 ++++++++++++++++----- 1 file changed, 86 insertions(+), 27 deletions(-) diff --git a/source/assets/scripts/localStorage.test.js b/source/assets/scripts/localStorage.test.js index 90ed2b7..94730d1 100644 --- a/source/assets/scripts/localStorage.test.js +++ b/source/assets/scripts/localStorage.test.js @@ -1,49 +1,108 @@ import {strict as assert} from "node:assert"; import {describe, it, beforeEach} from "mocha"; -import {saveReviewsToStorage, getReviewsFromStorage} from "./localStorage.js"; +import {newReviewToStorage, getReviewFromStorage, updateReviewToStorage, deleteReviewFromStorage, getAllReviewsFromStorage} from "./localStorage.js"; describe("test app localStorage interaction", () => { - beforeEach(() => { + before(() => { localStorage.clear(); + localStorage.setItem("activeIDS", JSON.stringify([])); + localStorage.setItem("nextID", JSON.stringify(0)); }); - it("get after init", () => { - assert.deepEqual(getReviewsFromStorage(), []); + it("test localStorage state after init", () => { + assert.deepEqual(getAllReviewsFromStorage(), []); + assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), []); + assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 0); }); - it("store one then get", () => { - let reviews = [{ + + it("test localStorage state after adding one review", () => { + let review = { "imgSrc": "sample src", "imgAlt": "sample alt", "mealName": "sample name", "restaurant": "sample restaurant", "rating": 5, "tags": ["tag 1", "tag 2", "tag 3"] - }]; + }; - saveReviewsToStorage(reviews); - assert.deepEqual(getReviewsFromStorage(), reviews); + newReviewToStorage(review); + + review.reviewID = 0; + + assert.deepEqual(getAllReviewsFromStorage(), [review]); + assert.deepEqual(getReviewFromStorage(0), review); + assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), [0]); + assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1); }); - it("repeated store one more and get", () => { - let reviews = []; - assert.deepEqual(getReviewsFromStorage(), reviews); + it("test localStorage state during adding 999 reviews", () => { + let reviews = getAllReviewsFromStorage(); + let ids = [0]; + + for(let i = 1; i < 1000; i++){ + ids.push(i); + let new_review = { + "imgSrc": `sample src ${i}`, + "imgAlt": `sample alt ${i}`, + "mealName": `sample name ${i}`, + "restaurant": `sample restaurant ${i}`, + "rating": i, + "tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] + } + + newReviewToStorage(new_review); + + new_review.reviewID = i; + reviews.push(new_review); + + assert.deepEqual(getAllReviewsFromStorage(), reviews); + assert.deepEqual(getReviewFromStorage(i), new_review); + assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); + assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), (i+1)); + } + }).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++){ - reviews = getReviewsFromStorage(); - - reviews.push( - { - "imgSrc": `sample src ${i}`, - "imgAlt": `sample alt ${i}`, - "mealName": `sample name ${i}`, - "restaurant": `sample restaurant ${i}`, - "rating": i, - "tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] - } - ); - saveReviewsToStorage(reviews); - assert.deepEqual(getReviewsFromStorage(), reviews); + let new_review = { + "imgSrc": `updated sample src ${i}`, + "imgAlt": `updated sample alt ${i}`, + "mealName": `updated sample name ${i}`, + "restaurant": `updated sample restaurant ${i}`, + "rating": i*2+i, + "tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] + } + new_review.reviewID = i; + + reviews[i] = new_review; + + updateReviewToStorage(i, new_review); + + assert.deepEqual(getAllReviewsFromStorage(), reviews); + assert.deepEqual(getReviewFromStorage(i), new_review); + assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); + assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000); } - }).timeout(10000); + }).timeout(5000); + + it("test localStorage state during deleting 1000 reviews", () => { + let reviews = getAllReviewsFromStorage(); + let ids = JSON.parse(localStorage.getItem("activeIDS")); + + for(let i = 999; i >= 0; i--){ + deleteReviewFromStorage(i); + ids.pop(); + reviews.pop(); + + assert.deepEqual(getAllReviewsFromStorage(), reviews); + assert.deepEqual(JSON.parse(localStorage.getItem("activeIDS")), ids); + assert.strictEqual(JSON.parse(localStorage.getItem("nextID")), 1000); + } + }).timeout(5000); + + after(() => {}); }); From 89b7319dd86166a594123ac94d936070b666bee3 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 18 Nov 2022 07:52:43 +0000 Subject: [PATCH 10/15] cleanup unused html and js code --- source/assets/scripts/ReviewPage.js | 13 ----- source/assets/scripts/main.js | 81 ----------------------------- source/review.html | 16 ------ 3 files changed, 110 deletions(-) delete mode 100644 source/assets/scripts/ReviewPage.js delete mode 100644 source/review.html diff --git a/source/assets/scripts/ReviewPage.js b/source/assets/scripts/ReviewPage.js deleted file mode 100644 index 89cd440..0000000 --- a/source/assets/scripts/ReviewPage.js +++ /dev/null @@ -1,13 +0,0 @@ -// Run the init() function when the page has loaded -window.addEventListener("DOMContentLoaded", init); - -function init() { - let result = sessionStorage.getItem("currReview"); - - let main = document.querySelector("main"); - - main.innerHTML = result; - let p = document.createElement("p"); - p.innerHTML = JSON.parse(result)["comments"]; - main.append(p); -} diff --git a/source/assets/scripts/main.js b/source/assets/scripts/main.js index 331492e..c402faf 100644 --- a/source/assets/scripts/main.js +++ b/source/assets/scripts/main.js @@ -39,85 +39,4 @@ function initFormHandler() { createBtn.addEventListener("click", function(){ window.location.assign("./CreatePage.html"); }); - - //accessing form components - /* - let tagContainer = document.getElementById("tag-container-form"); - let form = document.querySelector("form"); - - form.addEventListener("submit", function(){ - /* - * User submits the form for their review. - * We create reviewCard and put in storage - let formData = new FormData(form); - let reviewObject = {}; - for (let [key, value] of formData) { - console.log(`${key}`); - console.log(`${value}`); - if (`${key}` !== "tag-form") { - reviewObject[`${key}`] = `${value}`; - } - } - reviewObject["tags"] = []; - - let tags = document.querySelectorAll(".tag"); - for(let i = 0; i < tags.length; i ++) { - reviewObject["tags"].push(tags[i].innerHTML); - tagContainer.removeChild(tags[i]); - } - - - let newReview = document.createElement("review-card"); - newReview.data = reviewObject; - - //TODO: want to append it to whatever the box is in layout - let mainEl = document.querySelector("main"); - mainEl.append(newReview); - - // TODO: assign an ID to be used for referencing this object form the activeIDs array and the tag arrays - let ID = localStorage.nextID; - - let storedReviews = getReviewsFromStorage(); - storedReviews.push(reviewObject); - saveReviewsToStorage(storedReviews); - document.getElementById("new-food-entry").reset(); - }); - - // DEV-MODE: for testing purposes - let clearBtn = document.querySelector(".danger"); - clearBtn.addEventListener("click", function() { - localStorage.clear(); - let mainEl = document.querySelector("main"); - while (mainEl.firstChild) { - mainEl.removeChild(mainEl.firstChild); - } - let deleteTags = document.querySelectorAll(".tag"); - for(let i = 0; i < deleteTags.length; i ++) { - tagContainer.removeChild(deleteTags[i]); - } - - //clears reviews AS WELL as resets form - document.getElementById("new-food-entry").reset(); - - - }); - - let tagAddBtn = document.getElementById("tagAdd"); - tagAddBtn.addEventListener("click", ()=> { - let tagField = document.getElementById("tag-form"); - if (tagField.value.length > 0) { - let tagLabel = document.createElement("label"); - tagLabel.innerHTML = tagField.value; - tagLabel.setAttribute("class","tag"); - tagLabel.addEventListener("click",()=> { - tagContainer.removeChild(tagLabel); - }); - - tagContainer.append(tagLabel); - tagField.value = ""; - - } - }); - */ - } diff --git a/source/review.html b/source/review.html deleted file mode 100644 index b9894ad..0000000 --- a/source/review.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Food Journal - - - - -

Current Review:

-
-
- - \ No newline at end of file From 3422f584f98dc9f6f74786a261a7ef0c1a0f537d Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 18 Nov 2022 07:56:07 +0000 Subject: [PATCH 11/15] fix linting in js --- source/assets/scripts/CreatePage.js | 8 ++++---- source/assets/scripts/ReviewCard.js | 18 +++++++++--------- source/assets/scripts/ReviewDetails.js | 2 +- source/assets/scripts/localStorage.js | 6 +++--- source/assets/scripts/localStorage.test.js | 6 +++--- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/source/assets/scripts/CreatePage.js b/source/assets/scripts/CreatePage.js index fca6dc5..c5c641f 100644 --- a/source/assets/scripts/CreatePage.js +++ b/source/assets/scripts/CreatePage.js @@ -3,10 +3,10 @@ import { newReviewToStorage } from "./localStorage.js"; window.addEventListener("DOMContentLoaded", init); function init() { - // get next id + // get next id - // creates the key - initFormHandler(); + // creates the key + initFormHandler(); } @@ -42,7 +42,7 @@ function initFormHandler() { let nextReviewId = newReviewToStorage(reviewObject); sessionStorage.setItem("currID", JSON.stringify(nextReviewId)); - window.location.assign('./ReviewDetails.html'); + window.location.assign("./ReviewDetails.html"); }); diff --git a/source/assets/scripts/ReviewCard.js b/source/assets/scripts/ReviewCard.js index d7bd1ce..70a0660 100644 --- a/source/assets/scripts/ReviewCard.js +++ b/source/assets/scripts/ReviewCard.js @@ -132,18 +132,18 @@ class ReviewCard extends HTMLElement { let articleEl = this.shadowEl.querySelector("article"); // setting the article elements for the review card - this.reviewID = data["reviewID"]; + this.reviewID = data["reviewID"]; //image setup let mealImg = document.createElement("img"); mealImg.setAttribute("id", "a-mealImg"); mealImg.setAttribute("alt",data["imgAlt"]); - if(data["mealImg"] != ""){ - mealImg.setAttribute("src",data["mealImg"]); - } - else{ - mealImg.setAttribute("src", "./assets/images/icons/plate_with_cutlery.png"); - } + if(data["mealImg"] != ""){ + mealImg.setAttribute("src",data["mealImg"]); + } + else{ + mealImg.setAttribute("src", "./assets/images/icons/plate_with_cutlery.png"); + } //meal name setup let mealLabel = document.createElement("label"); @@ -187,7 +187,7 @@ class ReviewCard extends HTMLElement { } } - //adding final ID to data! + //adding final ID to data! articleEl.append(mealImg); articleEl.append(mealLabel); @@ -223,7 +223,7 @@ class ReviewCard extends HTMLElement { let dataContainer = {}; // getting the article elements for the review card - dataContainer["reviewID"] = this.reviewID; + dataContainer["reviewID"] = this.reviewID; //get image let mealImg = this.shadowEl.getElementById("a-mealImg"); diff --git a/source/assets/scripts/ReviewDetails.js b/source/assets/scripts/ReviewDetails.js index f2545fa..b07282b 100644 --- a/source/assets/scripts/ReviewDetails.js +++ b/source/assets/scripts/ReviewDetails.js @@ -15,7 +15,7 @@ function setupDelete(){ deleteBtn.addEventListener("click", function(){ if(window.confirm("Are you sure you want to delete this entry?")){ deleteReviewFromStorage(currID); - sessionStorage.removeItem('currID'); + sessionStorage.removeItem("currID"); window.location.assign("./index.html"); } }); diff --git a/source/assets/scripts/localStorage.js b/source/assets/scripts/localStorage.js index 62b834d..20be650 100644 --- a/source/assets/scripts/localStorage.js +++ b/source/assets/scripts/localStorage.js @@ -52,8 +52,8 @@ export function deleteReviewFromStorage(ID){ for (let i in activeIDS) { if (activeIDS[i] == ID) { activeIDS.splice(i,1); - localStorage.setItem('activeIDS', JSON.stringify(activeIDS)); - localStorage.removeItem(`review${ID}`) + localStorage.setItem("activeIDS", JSON.stringify(activeIDS)); + localStorage.removeItem(`review${ID}`); return; } } @@ -70,7 +70,7 @@ export function getAllReviewsFromStorage() { } //iterate thru activeIDS let activeIDS = JSON.parse(localStorage.getItem("activeIDS")); - let reviews = [] + let reviews = []; for (let i = 0; i < activeIDS.length; i++) { let currReview = JSON.parse(localStorage.getItem(`review${activeIDS[i]}`)); reviews.push(currReview); diff --git a/source/assets/scripts/localStorage.test.js b/source/assets/scripts/localStorage.test.js index 94730d1..0ed85c4 100644 --- a/source/assets/scripts/localStorage.test.js +++ b/source/assets/scripts/localStorage.test.js @@ -1,5 +1,5 @@ import {strict as assert} from "node:assert"; -import {describe, it, beforeEach} from "mocha"; +import {describe, it, before, after} from "mocha"; import {newReviewToStorage, getReviewFromStorage, updateReviewToStorage, deleteReviewFromStorage, getAllReviewsFromStorage} from "./localStorage.js"; describe("test app localStorage interaction", () => { @@ -49,7 +49,7 @@ describe("test app localStorage interaction", () => { "restaurant": `sample restaurant ${i}`, "rating": i, "tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] - } + }; newReviewToStorage(new_review); @@ -75,7 +75,7 @@ describe("test app localStorage interaction", () => { "restaurant": `updated sample restaurant ${i}`, "rating": i*2+i, "tags": [`tag ${3*i}`, `tag ${3*i + 1}`, `tag ${3*i + 2}`] - } + }; new_review.reviewID = i; reviews[i] = new_review; From 425bc45453fa26e5f3458795dbdd7c864a368e7d Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 18 Nov 2022 09:23:54 +0000 Subject: [PATCH 12/15] fix unit test action stall issue --- .github/workflows/js-unittest.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/js-unittest.yml b/.github/workflows/js-unittest.yml index 5c07e35..918ce70 100644 --- a/.github/workflows/js-unittest.yml +++ b/.github/workflows/js-unittest.yml @@ -24,6 +24,6 @@ jobs: - name: Install dependencies run: sudo npm install - name: Start local http server - run: sudo npm run http-server + run: sudo npm run http-server & - name: Run tests run: sudo npm test \ No newline at end of file From f6a9fb7fc52b1b521b15084e5369fc6282fc1b27 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 18 Nov 2022 14:08:19 -0800 Subject: [PATCH 13/15] remove implied init from localStorage unit tests Signed-off-by: Arthur Lu --- source/assets/scripts/localStorage.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/source/assets/scripts/localStorage.test.js b/source/assets/scripts/localStorage.test.js index 0ed85c4..8f87ce0 100644 --- a/source/assets/scripts/localStorage.test.js +++ b/source/assets/scripts/localStorage.test.js @@ -6,8 +6,6 @@ describe("test app localStorage interaction", () => { before(() => { localStorage.clear(); - localStorage.setItem("activeIDS", JSON.stringify([])); - localStorage.setItem("nextID", JSON.stringify(0)); }); it("test localStorage state after init", () => { From 9cf7baf3e526eace3d9dc1db8fefae8f039f280f Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 18 Nov 2022 14:43:59 -0800 Subject: [PATCH 14/15] remove commented form from index Signed-off-by: Arthur Lu --- source/index.html | 52 ----------------------------------------------- 1 file changed, 52 deletions(-) diff --git a/source/index.html b/source/index.html index c83fe94..b8d4438 100644 --- a/source/index.html +++ b/source/index.html @@ -23,57 +23,5 @@
- From baa722b55e407c84ad6f0df45d946ff3d64adf34 Mon Sep 17 00:00:00 2001 From: Arthur Lu Date: Fri, 18 Nov 2022 15:15:20 -0800 Subject: [PATCH 15/15] remove unused files Signed-off-by: Arthur Lu --- .../assets/images/1_spooky-ghost-cookies.jpeg | Bin 6801 -> 0 bytes .../2_frightfully-easy-ghost-cookies.jpeg | Bin 4986 -> 0 bytes .../3_ingredient-ghost-halloween-cookies.jpeg | Bin 8829 -> 0 bytes source/reviews.json | 19 ------------------ 4 files changed, 19 deletions(-) delete mode 100644 source/assets/images/1_spooky-ghost-cookies.jpeg delete mode 100644 source/assets/images/2_frightfully-easy-ghost-cookies.jpeg delete mode 100644 source/assets/images/3_ingredient-ghost-halloween-cookies.jpeg delete mode 100644 source/reviews.json diff --git a/source/assets/images/1_spooky-ghost-cookies.jpeg b/source/assets/images/1_spooky-ghost-cookies.jpeg deleted file mode 100644 index aa5a1ede5c6ff00ba604f42424c48858efc72c80..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6801 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 diff --git a/source/assets/images/2_frightfully-easy-ghost-cookies.jpeg b/source/assets/images/2_frightfully-easy-ghost-cookies.jpeg deleted file mode 100644 index 38b34e8a1c8a138d990e2eeb75b5b7d2fe86829c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4986 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 diff --git a/source/assets/images/3_ingredient-ghost-halloween-cookies.jpeg b/source/assets/images/3_ingredient-ghost-halloween-cookies.jpeg deleted file mode 100644 index 2bca5e0ddb2dc15edfbb14be9e5cd695a6898ca2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8829 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 MGN#FM^nU(-0GIBt#Q*>R diff --git a/source/reviews.json b/source/reviews.json deleted file mode 100644 index 0f36b32..0000000 --- a/source/reviews.json +++ /dev/null @@ -1,19 +0,0 @@ -[ - { - "imgSrc": "https://cdn.vox-cdn.com/thumbor/Cj5J-5WqSCjlC2tWCOXEB536CJY=/0x0:1810x1182/1200x800/filters:focal(761x447:1049x735)/cdn.vox-cdn.com/uploads/chorus_image/image/69422966/Tacos_Lined_Up.0.png", - "imgAlt": "tacos pic", - "mealName": "Birria Tacos", - "restaurant": "Mike's Red Tacos", - "rating": 5, - "tags": ["delicious", "#worthit","omg"] - }, - { - "imgSrc": "https://www.redwormcomposting.com/images/worm-burrito.JPG", - "imgAlt": "wolftown pic", - "mealName": "Carnitas Burrito", - "restaurant": "Wolftown UCSD", - "rating": 0, - "tags": ["gross", "why","no"] - - } -]