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