From 9749e012e0f3a90fee27d3d06e8e112e32041445 Mon Sep 17 00:00:00 2001 From: Kate Lovett Date: Sat, 3 Nov 2018 09:02:58 -0500 Subject: [PATCH] Moved idb implementation out of service worker. Fixed a few bugs in the review form. --- app/js/dbhelper.js | 69 ++++++++++++++++++++++++++++++--- app/js/restaurant_info.js | 51 +++++++++++++++++++++--- app/js/swregister.js | 2 +- app/sw.js | 79 +++++++++----------------------------- dist/js/dbhelper.js | 2 +- dist/js/restaurant_info.js | 2 +- dist/sw.js | 2 +- 7 files changed, 131 insertions(+), 76 deletions(-) diff --git a/app/js/dbhelper.js b/app/js/dbhelper.js index 93052a1..d368e01 100644 --- a/app/js/dbhelper.js +++ b/app/js/dbhelper.js @@ -3,7 +3,7 @@ */ // Change this to your server port const port = 1337; -const dbPromise = idb.open('restaurantReviews', 3, upgradeDb => { +const dbPromise = idb.open("restaurantReviews", 3, upgradeDb => { switch(upgradeDb.oldVersion) { case 0: upgradeDb.createObjectStore("restaurantData", {keyPath: "id"}); case 1: upgradeDb.createObjectStore("reviewData", {keypath: "id"}).createIndex("restaurant_id", "restaurant_id"); @@ -61,7 +61,7 @@ class DBHelper { * Fetch a restaurant by its ID. */ static fetchRestaurantById(id, callback) { - console.log(`In fetchRestaurantsById - id: ${id}, callback: ${callback}`); + console.log(`In fetchRestaurantsById - id: ${id}`); // fetch all restaurants with proper error handling. DBHelper.fetchRestaurants((error, restaurants) => { if (error) { @@ -201,15 +201,16 @@ class DBHelper { static fetchReviewsById(id) { let requestURL = DBHelper.DATABASE_URL_REVIEWS + "/?restaurant_id=" + id; console.log(`In DBHelper.fetchReviewsById - request: ${requestURL}, id: ${id}`); - fetch(requestURL, {method: "GET"}) + return fetch(requestURL, {method: "GET"}) .then(function(response) { + console.log("response: ", response); if (response.ok) return response.json(); //throw new Error("Fetch response Error in fetchReviewsBy...ID") }) .then(function(reviewData) { // If fetch successful - console.log(reviewData); + console.log("reviewData: ", reviewData); //dbPromise.putReviews(reviewData); return reviewData; }) @@ -242,7 +243,8 @@ class DBHelper { let updaterestaurant = restaurants[0]; if (!updaterestaurant) return; // Update restaurant with new data - Object.keys(update).forEach(key => { updaterestaurant[key] = update[key]; }); + let keys = Object.keys(update) + keys.forEach(key => { updaterestaurant[key] = update[key]; }); // Store updated information back in idb dbPromise.then(function(db) { @@ -263,7 +265,8 @@ class DBHelper { let updaterestaurant = value.data; if (!updaterestaurant) return; // Update restaurant wiht new data - Object.keys(update).forEach(key => { updaterestaurant[key] = update[key] }); + let keys = Object.keys(update) + keys.forEach(key => { updaterestaurant[key] = update[key] }); // Store updated information back in idb dbPromise.then(function(db) { @@ -365,4 +368,58 @@ class DBHelper { //callback(null, null); } + // IDB Functionality ------ + + /* + * Function to check idb for restaurant information + */ + static idbRestaurantRequest() { + return dbPromise.then(function(db) { + return db.transaction('restaurantData').objectStore('restaurantData').get(id); + }) + .then(function(data) { + return (data && data.data) || fetch(event.request) + .then(function(response) { + return dbPromise + .then(function(db) { + db.transaction('restaurantData', 'readwrite').objectStore('restaurantData').put({ id: id, data: response.json() }); + return response.json(); + }); + }); + }) + .then(function(endResponse) { return new Response(JSON.stringify(endResponse)); }) + .catch(function(error) { console.log(`In DBHelper.idbRestaurantRequest, error: ${error.message}`); }) + } + + /* + * Function to check idb for review information + */ + static idbReviewRequest() { + return dbPromise.then(function(db) { + return db.transaction('reviewData').objectStore('reviewData').index('restaurant_id').getAll(id); + }) + .then(function(data) { + return (data && data.data) || fetch(event.request) + .then(function(response) { + return dbPromise + .then(function(db) { + let store = db.transaction('reviewData', 'readwrite').objectStore('reviewData'); + let r = response.json(); + r.forEach(function(review) { + store.put({id: review.id, 'restaurant_id': review.restaurant_id, data: review}); + }) + return r; + }); + }); + }) + .then(function(endResponse) { + if(endResponse[0].data) { + let formatted = endResponse.map(review => review.data); + return new Response(JSON.stringify(formatted)); + } + return new Response(JSON.stringify(endResponse)); + }) + .catch(function(error) { console.log(`In apiFetch catch-reviewData, error: ${error.message}`); }) + } + } diff --git a/app/js/restaurant_info.js b/app/js/restaurant_info.js index 10429b0..27efd2a 100644 --- a/app/js/restaurant_info.js +++ b/app/js/restaurant_info.js @@ -35,6 +35,7 @@ fetchRestaurantFromURL = (callback) => { callback(error, null); } else { DBHelper.fetchRestaurantById(id, (error, restaurant) => { + //console.log(restaurant); self.restaurant = restaurant; if (!restaurant) { console.error(error); @@ -74,7 +75,7 @@ fillRestaurantHTML = (restaurant = self.restaurant) => { image.srcset = `/img/${restaurant.id}@1x.webp 300w, /img/${restaurant.id}@2x.webp 600w, /img/${restaurant.id}@3x.webp 900w`; - image.alt = restaurant.alt_text; + image.alt = `Image of ${restaurant.name} restaurant`; const cuisine = document.getElementById('restaurant-cuisine'); cuisine.innerHTML = restaurant.cuisine_type; @@ -86,7 +87,7 @@ fillRestaurantHTML = (restaurant = self.restaurant) => { // fill reviews //fillReviewsHTML(); console.log(`In fillRestaurantHTML, about to call fetch then fill with id: ${restaurant.id}`); - DBHelper.fetchReviewsById(restaurant.id).then(fillReviewsHTML(reviews)); + DBHelper.fetchReviewsById(restaurant.id).then(fillReviewsHTML); } /* @@ -141,7 +142,7 @@ fillRestaurantHoursHTML = (operatingHours = self.restaurant.operating_hours) => /* * Create all reviews HTML and add them to the webpage. */ -fillReviewsHTML = (reviews) => { +fillReviewsHTML = (reviews = self.restaurant.reviews) => { console.log("In fillReviewsHTML ", reviews); const container = document.getElementById('reviews-container'); const title = document.createElement('h3'); @@ -156,7 +157,7 @@ fillReviewsHTML = (reviews) => { if (!reviews) { const noReviews = document.createElement('h3'); - noReviews.innerHTML = 'No reviews yet!'; + noReviews.innerHTML = '
No reviews yet!
'; container.appendChild(noReviews); return; } @@ -178,7 +179,7 @@ createReviewHTML = (review) => { li.appendChild(name); const date = document.createElement('p'); - date.innerHTML = review.date; + date.innerHTML = new Date(review.createdAt).toLocaleDateString(); li.appendChild(date); const rating = document.createElement('p'); @@ -323,8 +324,46 @@ handleSubmit = (e) => { //console.log("in handleSubmit"); let id = self.restaurant.id; let name = document.getElementById("name").value; - let rating = document.getElementById("rating").value + 0; + let rating = document.getElementById("rating").value - 0; let comments = document.getElementById("comments").value; + // Add the new review to the reviews list + const ul = document.getElementById('reviews-list'); + + // Put new review in reviews list on site --- + const li = document.createElement('li'); + const newName = document.createElement('p'); + newName.id = "reviewer-name"; + newName.innerHTML = name; + li.appendChild(newName); + + const date = document.createElement('p'); + //let now = Date.now(); + date.innerHTML = "Date";// TODO, sort this mess out : now.toLocaleDateString(); + li.appendChild(date); + + const newRating = document.createElement('p'); + newRating.innerHTML = `Rating: ${rating}`; + li.appendChild(newRating); + + const stars = document.createElement('p'); + var starString = ""; + for (i = 0; i < rating; i++){ + starString += "★ "; + } + //console.log("starString ", starString); + stars.innerHTML = starString; + li.appendChild(stars); + + const line = document.createElement('hr'); + li.appendChild(line); + + const newComments = document.createElement('p'); + newComments.id = "reviewer-comments"; + newComments.innerHTML = comments; + li.appendChild(newComments); + //--- + + ul.appendChild(li); DBHelper.saveReview(id, name, rating, comments, Date.now()); // Get rid of the form diff --git a/app/js/swregister.js b/app/js/swregister.js index 564a5cb..bd62401 100644 --- a/app/js/swregister.js +++ b/app/js/swregister.js @@ -1,5 +1,5 @@ // Registering the Service Worker -if ("serviceWorker" in navigator) { +if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') .then(function(registration) { console.log('Registration successful, scope is: ', registration.scope); diff --git a/app/sw.js b/app/sw.js index ae19f19..5ba260f 100644 --- a/app/sw.js +++ b/app/sw.js @@ -3,7 +3,7 @@ */ // Include DBHelper functions for fetching restaurants and putting in indexedDB -self.importScripts('./js/dbhelper.js', './js/idb.js'); +self.importScripts('js/dbhelper.js', 'js/idb.js'); // Cache Information var myCache = 'restaurantReview_301'; @@ -20,24 +20,24 @@ var cacheFiles = [ ]; // IDB Information -const dbPromise = idb.open('restaurantReviews', 3, upgradeDb => { - switch(upgradeDb.oldVersion) { - case 0: upgradeDb.createObjectStore('restaurantData', {keyPath: 'id'}); - case 1: upgradeDb.createObjectStore('reviewData', {keypath: 'id'}).createIndex('restaurant_id', 'restaurant_id'); - case 2: upgradeDb.createObjectStore('updateData', {keyPath: 'id', autoIncrement: true}); - } -}); +//const dbPromise = idb.open('restaurantReviews', 3, upgradeDb => { +// switch(upgradeDb.oldVersion) { +// case 0: upgradeDb.createObjectStore('restaurantData', {keyPath: 'id'}); +// case 1: upgradeDb.createObjectStore('reviewData', {keypath: 'id'}).createIndex('restaurant_id', 'restaurant_id'); +// case 2: upgradeDb.createObjectStore('updateData', {keyPath: 'id', autoIncrement: true}); +// } +//}); /* * Event Listener for install - caching the files */ self.addEventListener('install', function(event) { - console.log('In eventListener for install, event: ', event) + console.log('In eventListener for install') event.waitUntil(caches.open(myCache) .then(function(cache) { return cache.addAll(cacheFiles) - .then(function() { console.log('Cache worked!'); } ) - .catch(function(error) { console.log('Caching failed, error: ', error); } ); + .then(function() { console.log('Cache worked!'); }) + .catch(function(error) { console.log('Caching failed, error: ', error); }); })); }); @@ -46,7 +46,7 @@ self.addEventListener('install', function(event) { * Event Listener for fetch - pull files from cache and update with fetch is possible */ self.addEventListener('fetch', function(event) { - console.log('In eventListener for fetch, event: ', event); + console.log('In eventListener for fetch, event'); // Separating fetch requests let requestURL = new URL(event.request.url); if (requestURL.port === '1337') { @@ -67,8 +67,8 @@ self.addEventListener('fetch', function(event) { }); function apiFetch(event, id) { - console.log(`In apiFetch - event: ${event} id: ${id}`); - if (event.request.method == 'POST' || event.request.method == 'PUT') { + console.log('In apiFetch'); + if (event.request.method != 'GET') { // Post & Put methods are not cached. Process request without further action. return fetch(event.request) .then(function(response) { return response.json(); }); @@ -76,58 +76,17 @@ function apiFetch(event, id) { // Restaurant and Review information are now being kept in separate stores: restaurantData & reviewData - // Restaurant Request ------------------------------------------------------------------------------- + // Restaurant Request if(event.request.url.indexOf('restaurants') > -1) { - event.respondWith(dbPromise.then(function(db) { - return db.transaction('restaurantData').objectStore('restaurantData').get(id); - }) - .then(function(data) { - return (data && data.data) || fetch(event.request) - - .then(function(response) { - return dbPromise - - .then(function(db) { - db.transaction('restaurantData', 'readwrite').objectStore('restaurantData').put({ id: id, data: response.json() }); - return response.json(); - }); - }); - }) - .then(function(endResponse) { return new Response(JSON.stringify(endResponse)); }) - .catch(function(error) { console.log(`In apiFetch catch-restaurantData, error: ${error.message}`); })); + event.respondWith(DBHelper.idbRestaurantRequest()); } - // Review Request ----------------------------------------------------------------------------------- - event.respondWith(dbPromise.then(function(db) { - return db.transaction('reviewData').objectStore('reviewData').index('restaurant_id').getAll(id); - }) - .then(function(data) { - return (data && data.data) || fetch(event.request) - - .then(function(response) { - return dbPromise - - .then(function(db) { - let store = db.transaction('reviewData', 'readwrite').objectStore('reviewData'); - response.json().forEach(function(review) { - store.put({id: review.id, 'restaurant_id': review.restaurant_id, data: review}); - }) - return response.json(); - }); - }); - }) - .then(function(endResponse) { - if(endResponse[0].data) { - let formatted = endResponse.map(review => review.data); - return new Response(JSON.stringify(formatted)); - } - return new Response(JSON.stringify(endResponse)); - }) - .catch(function(error) { console.log(`In apiFetch catch-reviewData, error: ${error.message}`); })); + // Review Request + event.respondWith(DBHelper.idbReviewRequest()); } function cacheFetch(event, request) { - console.log(`In cacheFetch - event: ${event} request: ${request}`); + console.log('In cacheFetch'); // Check the cache before fetching. // If fetched, store in the cache. event.respondWith(caches.match(request)) diff --git a/dist/js/dbhelper.js b/dist/js/dbhelper.js index 6381b7e..5d6c127 100644 --- a/dist/js/dbhelper.js +++ b/dist/js/dbhelper.js @@ -1 +1 @@ -const port=1337,dbPromise=idb.open("restaurantReviews",3,e=>{switch(e.oldVersion){case 0:e.createObjectStore("restaurantData",{keyPath:"id"});case 1:e.createObjectStore("reviewData",{keypath:"id"}).createIndex("restaurant_id","restaurant_id");case 2:e.createObjectStore("updateData",{keyPath:"id",autoIncrement:!0})}});class DBHelper{static get DATABASE_URL(){return`http://localhost:${port}/restaurants`}static get DATABASE_URL_REVIEWS(){return`http://localhost:${port}/reviews`}static fetchRestaurants(e){console.log(`In fetchRestaurants - callback: ${e}`);let t=DBHelper.DATABASE_URL;fetch(t,{method:"GET"}).then(function(e){if(e.ok)return e.json()}).then(function(t){e(null,t)}).catch(function(e){console.log("In fetchRestaurants catch, error: ",e.message)})}static fetchRestaurantById(e,t){console.log(`In fetchRestaurantsById - id: ${e}, callback: ${t}`),DBHelper.fetchRestaurants((a,n)=>{if(a)t(a,null);else{const a=n.find(t=>t.id==e);a?t(null,a):t("Restaurant does not exist",null)}})}static fetchRestaurantByCuisine(e,t){DBHelper.fetchRestaurants((a,n)=>{if(a)t(a,null);else{const a=n.filter(t=>t.cuisine_type==e);t(null,a)}})}static fetchRestaurantByNeighborhood(e,t){DBHelper.fetchRestaurants((a,n)=>{if(a)t(a,null);else{const a=n.filter(t=>t.neighborhood==e);t(null,a)}})}static fetchRestaurantByCuisineAndNeighborhood(e,t,a){DBHelper.fetchRestaurants((n,r)=>{if(n)a(n,null);else{let n=r;"all"!=e&&(n=n.filter(t=>t.cuisine_type==e)),"all"!=t&&(n=n.filter(e=>e.neighborhood==t)),a(null,n)}})}static fetchNeighborhoods(e){DBHelper.fetchRestaurants((t,a)=>{if(t)e(t,null);else{const t=a.map((e,t)=>a[t].neighborhood),n=t.filter((e,a)=>t.indexOf(e)==a);e(null,n)}})}static fetchCuisines(e){DBHelper.fetchRestaurants((t,a)=>{if(t)e(t,null);else{const t=a.map((e,t)=>a[t].cuisine_type),n=t.filter((e,a)=>t.indexOf(e)==a);e(null,n)}})}static urlForRestaurant(e){return`./restaurant.html?id=${e.id}`}static imageUrlForRestaurant(e){return`/img/${e.photograph}`}static mapMarkerForRestaurant(e,t){return new google.maps.Marker({position:e.latlng,title:e.name,url:DBHelper.urlForRestaurant(e),map:t,animation:google.maps.Animation.DROP})}static fetchReviewsById(e){let t=DBHelper.DATABASE_URL_REVIEWS+"/?restaurant_id="+e;console.log(`In DBHelper.fetchReviewsById - request: ${t}, id: ${e}`),fetch(t,{method:"GET"}).then(function(e){if(e.ok)return e.json()}).then(function(e){return console.log(e),e}).catch(function(e){console.log("In fetchReviewsBy...ID catch, error:",e.message)})}static updateRestaurantCache(e,t){console.log(`In updateRestaurantCache - id: ${e}, update: ${t}`);let a=idb.open("restaurantReviews");a.then(function(n){n.transaction("restaurantData","readwrite").objectStore("restaurantData").get("-1").then(function(n){if(!n)return void console.log("No value, update all, in updateRestaurantCache");let r=n.data.filter(t=>t.id===e)[0];r&&(Object.keys(t).forEach(e=>{r[e]=t[e]}),a.then(function(e){return e.transaction("restaurantData","readwrite").objectStore("restaurantData").put({id:"-1",data:n.data}).complete}))})}),a.then(function(n){n.transaction("restaurantData","readwrite").objectStore("restaurantData").get(e+"").then(function(n){if(!n)return void console.log("No value, update individual, in updateRestaurantCache");let r=n.data;r&&(Object.keys(t).forEach(e=>{r[e]=t[e]}),a.then(function(t){return t.transaction("restaurantData","readwrite").objectStore("restaurantData").put({id:e+"",data:n.data}).complete}))})})}static updateReviewCache(e,t){console.log(`In updateReviewCache - id: ${e}, update: ${t}`),idb.open("restaurantReviews").then(function(a){return a.transaction("reviewData","readwrite").objectStore("reviewData").put({id:Date.now(),restaurant_id:e,data:t}).complete})}static addToUpdateQueue(e,t,a){console.log(`In addToUpdateQueue - url: ${e}, method: ${t}, update: ${a}`),idb.open("restaurantReviews").then(function(n){n.transaction("updateData","readwrite").objectStore("updateData").put({data:{url:e,method:t,update:a}})}).catch(function(e){console.log("In addToUpdateQueue catch, error: ",e.message)}).then(DBHelper.pushUpdates())}static pushUpdates(){console.log("In pushUpdates"),idb.open("restaurantReviews").then(function(e){e.transaction("updateData","readwrite").objectStore("updateData").openCursor().then(function(t){if(!t)return;let a=t.value.data,n={body:JSON.stringify(a.body),method:a.method};fetch(a.url,n).then(function(e){e.ok}).then(function(){e.transaction("updateData","readwrite").objectStore("updateData").openCursor().then(function(e){e.delete().then(function(){console.log("Record deleted, calling next..."),DBHelper.pushUpdates()})})})}).catch(function(e){console.log("In pushUpdates catch, error: ",e.message)})})}static saveReview(e,t,a,n,r){let o=`${DBHelper.DATABASE_URL_REVIEWS}`,s={restaurant_id:e,name:t,rating:a,comments:n,createdAt:r};console.log(`In saveReview - url: ${o}, method: POST, body: ${s}`),DBHelper.updateReviewCache(e,s),DBHelper.addToUpdateQueue(o,"POST",s)}} \ No newline at end of file +const port=1337,dbPromise=idb.open("restaurantReviews",3,t=>{switch(t.oldVersion){case 0:t.createObjectStore("restaurantData",{keyPath:"id"});case 1:t.createObjectStore("reviewData",{keypath:"id"}).createIndex("restaurant_id","restaurant_id");case 2:t.createObjectStore("updateData",{keyPath:"id",autoIncrement:!0})}});class DBHelper{static get DATABASE_URL(){return`http://localhost:${port}/restaurants`}static get DATABASE_URL_REVIEWS(){return`http://localhost:${port}/reviews`}static fetchRestaurants(t){console.log(`In fetchRestaurants - callback: ${t}`);let e=DBHelper.DATABASE_URL;fetch(e,{method:"GET"}).then(function(t){if(t.ok)return t.json()}).then(function(e){t(null,e)}).catch(function(t){console.log("In fetchRestaurants catch, error: ",t.message)})}static fetchRestaurantById(t,e){console.log(`In fetchRestaurantsById - id: ${t}`),DBHelper.fetchRestaurants((a,n)=>{if(a)e(a,null);else{const a=n.find(e=>e.id==t);a?e(null,a):e("Restaurant does not exist",null)}})}static fetchRestaurantByCuisine(t,e){DBHelper.fetchRestaurants((a,n)=>{if(a)e(a,null);else{const a=n.filter(e=>e.cuisine_type==t);e(null,a)}})}static fetchRestaurantByNeighborhood(t,e){DBHelper.fetchRestaurants((a,n)=>{if(a)e(a,null);else{const a=n.filter(e=>e.neighborhood==t);e(null,a)}})}static fetchRestaurantByCuisineAndNeighborhood(t,e,a){DBHelper.fetchRestaurants((n,r)=>{if(n)a(n,null);else{let n=r;"all"!=t&&(n=n.filter(e=>e.cuisine_type==t)),"all"!=e&&(n=n.filter(t=>t.neighborhood==e)),a(null,n)}})}static fetchNeighborhoods(t){DBHelper.fetchRestaurants((e,a)=>{if(e)t(e,null);else{const e=a.map((t,e)=>a[e].neighborhood),n=e.filter((t,a)=>e.indexOf(t)==a);t(null,n)}})}static fetchCuisines(t){DBHelper.fetchRestaurants((e,a)=>{if(e)t(e,null);else{const e=a.map((t,e)=>a[e].cuisine_type),n=e.filter((t,a)=>e.indexOf(t)==a);t(null,n)}})}static urlForRestaurant(t){return`./restaurant.html?id=${t.id}`}static imageUrlForRestaurant(t){return`/img/${t.photograph}`}static mapMarkerForRestaurant(t,e){return new google.maps.Marker({position:t.latlng,title:t.name,url:DBHelper.urlForRestaurant(t),map:e,animation:google.maps.Animation.DROP})}static fetchReviewsById(t){let e=DBHelper.DATABASE_URL_REVIEWS+"/?restaurant_id="+t;return console.log(`In DBHelper.fetchReviewsById - request: ${e}, id: ${t}`),fetch(e,{method:"GET"}).then(function(t){if(console.log("response: ",t),t.ok)return t.json()}).then(function(t){return console.log("reviewData: ",t),t}).catch(function(t){console.log("In fetchReviewsBy...ID catch, error:",t.message)})}static updateRestaurantCache(t,e){console.log(`In updateRestaurantCache - id: ${t}, update: ${e}`);let a=idb.open("restaurantReviews");a.then(function(n){n.transaction("restaurantData","readwrite").objectStore("restaurantData").get("-1").then(function(n){if(!n)return void console.log("No value, update all, in updateRestaurantCache");let r=n.data.filter(e=>e.id===t)[0];r&&(Object.keys(e).forEach(t=>{r[t]=e[t]}),a.then(function(t){return t.transaction("restaurantData","readwrite").objectStore("restaurantData").put({id:"-1",data:n.data}).complete}))})}),a.then(function(n){n.transaction("restaurantData","readwrite").objectStore("restaurantData").get(t+"").then(function(n){if(!n)return void console.log("No value, update individual, in updateRestaurantCache");let r=n.data;r&&(Object.keys(e).forEach(t=>{r[t]=e[t]}),a.then(function(e){return e.transaction("restaurantData","readwrite").objectStore("restaurantData").put({id:t+"",data:n.data}).complete}))})})}static updateReviewCache(t,e){console.log(`In updateReviewCache - id: ${t}, update: ${e}`),idb.open("restaurantReviews").then(function(a){return a.transaction("reviewData","readwrite").objectStore("reviewData").put({id:Date.now(),restaurant_id:t,data:e}).complete})}static addToUpdateQueue(t,e,a){console.log(`In addToUpdateQueue - url: ${t}, method: ${e}, update: ${a}`),idb.open("restaurantReviews").then(function(n){n.transaction("updateData","readwrite").objectStore("updateData").put({data:{url:t,method:e,update:a}})}).catch(function(t){console.log("In addToUpdateQueue catch, error: ",t.message)}).then(DBHelper.pushUpdates())}static pushUpdates(){console.log("In pushUpdates"),idb.open("restaurantReviews").then(function(t){t.transaction("updateData","readwrite").objectStore("updateData").openCursor().then(function(e){if(!e)return;let a=e.value.data,n={body:JSON.stringify(a.body),method:a.method};fetch(a.url,n).then(function(t){t.ok}).then(function(){t.transaction("updateData","readwrite").objectStore("updateData").openCursor().then(function(t){t.delete().then(function(){console.log("Record deleted, calling next..."),DBHelper.pushUpdates()})})})}).catch(function(t){console.log("In pushUpdates catch, error: ",t.message)})})}static saveReview(t,e,a,n,r){let o=`${DBHelper.DATABASE_URL_REVIEWS}`,s={restaurant_id:t,name:e,rating:a,comments:n,createdAt:r};console.log(`In saveReview - url: ${o}, method: POST, body: ${s}`),DBHelper.updateReviewCache(t,s),DBHelper.addToUpdateQueue(o,"POST",s)}static idbRestaurantRequest(){return dbPromise.then(function(t){return t.transaction("restaurantData").objectStore("restaurantData").get(id)}).then(function(t){return t&&t.data||fetch(event.request).then(function(t){return dbPromise.then(function(e){return e.transaction("restaurantData","readwrite").objectStore("restaurantData").put({id:id,data:t.json()}),t.json()})})}).then(function(t){return new Response(JSON.stringify(t))}).catch(function(t){console.log(`In DBHelper.idbRestaurantRequest, error: ${t.message}`)})}static idbReviewRequest(){return dbPromise.then(function(t){return t.transaction("reviewData").objectStore("reviewData").index("restaurant_id").getAll(id)}).then(function(t){return t&&t.data||fetch(event.request).then(function(t){return dbPromise.then(function(e){let a=e.transaction("reviewData","readwrite").objectStore("reviewData"),n=t.json();return n.forEach(function(t){a.put({id:t.id,restaurant_id:t.restaurant_id,data:t})}),n})})}).then(function(t){if(t[0].data){let e=t.map(t=>t.data);return new Response(JSON.stringify(e))}return new Response(JSON.stringify(t))}).catch(function(t){console.log(`In apiFetch catch-reviewData, error: ${t.message}`)})}} \ No newline at end of file diff --git a/dist/js/restaurant_info.js b/dist/js/restaurant_info.js index bbc33ce..d4b8551 100644 --- a/dist/js/restaurant_info.js +++ b/dist/js/restaurant_info.js @@ -1 +1 @@ -let restaurant;var map;window.initMap=(()=>{fetchRestaurantFromURL((e,t)=>{e?console.error(e):(self.map=new google.maps.Map(document.getElementById("map"),{zoom:16,center:t.latlng,scrollwheel:!1}),fillBreadcrumb(),DBHelper.mapMarkerForRestaurant(self.restaurant,self.map))}),DBHelper.pushUpdates()}),fetchRestaurantFromURL=(e=>{if(self.restaurant)return void e(null,self.restaurant);const t=getParameterByName("id");if(t)DBHelper.fetchRestaurantById(t,(t,n)=>{self.restaurant=n,n?(fillRestaurantHTML(),e(null,n)):console.error(t)});else{e("No restaurant id in URL",null)}}),fillRestaurantHTML=((e=self.restaurant)=>{const t=document.getElementById("restaurant-name");t.innerHTML=e.name;const n=document.createElement("button");n.className="favButton";let r=!(!e.is_favorite||"true"!==e.is_favorite.toString());n.setAttribute("aria-pressed",r),n.setAttribute("aria-label",`Make ${e.name} a favorite!`),n.innerHTML=r?"♥":"♡",n.onclick=(t=>favoriteClicked(e,n)),t.appendChild(n),document.getElementById("restaurant-address").innerHTML=e.address;const a=document.getElementById("restaurant-img");a.className="restaurant-img",a.src=`/img/${e.id}@1x.webp`,a.srcset=`/img/${e.id}@1x.webp 300w,\n /img/${e.id}@2x.webp 600w,\n /img/${e.id}@3x.webp 900w`,a.alt=e.alt_text,document.getElementById("restaurant-cuisine").innerHTML=e.cuisine_type,e.operating_hours&&fillRestaurantHoursHTML(),console.log(`In fillRestaurantHTML, about to call fetch then fill with id: ${e.id}`),DBHelper.fetchReviewsById(e.id).then(fillReviewsHTML(reviews))}),favoriteClicked=((e,t)=>{let n=!(!t.getAttribute("aria-pressed")||"true"!==t.getAttribute("aria-pressed")),r=`${DBHelper.DATABASE_URL}/${e.id}/?is_favorite=${!n}`;DBHelper.updateRestaurantCache(e.id,{is_favorite:!n}),DBHelper.addToUpdateQueue(r,"PUT"),t.setAttribute("aria-pressed",!n),t.innerHTML=n?"♡":"♥",t.onclick=(n=>favoriteClicked(e,t))}),fillRestaurantHoursHTML=((e=self.restaurant.operating_hours)=>{const t=document.getElementById("restaurant-hours");for(let n in e){const r=document.createElement("tr"),a=document.createElement("th");a.innerHTML=n,r.appendChild(a);const i=document.createElement("td");i.innerHTML=e[n],r.appendChild(i),t.appendChild(r)}}),fillReviewsHTML=(e=>{console.log("In fillReviewsHTML ",e);const t=document.getElementById("reviews-container"),n=document.createElement("h3");n.innerHTML="Reviews",t.appendChild(n);const r=document.createElement("button");if(r.innerHTML="Add a Review",r.id="reviewButton",r.onclick=addReviewForm,t.appendChild(r),!e){const e=document.createElement("h3");return e.innerHTML="No reviews yet!",void t.appendChild(e)}const a=document.getElementById("reviews-list");e.forEach(e=>{a.appendChild(createReviewHTML(e))}),t.appendChild(a)}),createReviewHTML=(e=>{const t=document.createElement("li"),n=document.createElement("p");n.id="reviewer-name",n.innerHTML=e.name,t.appendChild(n);const r=document.createElement("p");r.innerHTML=e.date,t.appendChild(r);const a=document.createElement("p");a.innerHTML=`Rating: ${e.rating}`,t.appendChild(a);const l=document.createElement("p");var d="";for(i=0;i{const t=document.getElementById("breadcrumb"),n=document.createElement("li");n.setAttribute("aria-current","page"),n.innerHTML=e.name,t.appendChild(n)}),getParameterByName=((e,t)=>{t||(t=window.location.href),e=e.replace(/[\[\]]/g,"\\$&");const n=new RegExp(`[?&]${e}(=([^&#]*)|&|#|$)`).exec(t);return n?n[2]?decodeURIComponent(n[2].replace(/\+/g," ")):"":null}),addReviewForm=(()=>{document.getElementById("reviewButton").style.display="none",document.getElementById("reviews-list").appendChild(reviewForm()),document.getElementById("name").focus()}),reviewForm=(()=>{let e=document.createElement("li"),t=document.createElement("form");t.id="reviewForm";let n=document.createElement("p");n.innerHTML="New Review",n.id="reviewer-name",t.appendChild(n);let r=document.createElement("p"),a=document.createElement("input"),i=document.createElement("label");i.setAttribute("for","name"),i.innerHTML="First Name: ",a.id="name",a.setAttribute("type","text"),r.appendChild(i),r.appendChild(a),t.appendChild(r),r=document.createElement("p");let l=document.createElement("label");l.setAttribute("for","rating"),l.innerText="Your rating: ",r.appendChild(l);let d=document.createElement("select");d.id="rating",d.name="rating",d.classList.add("rating"),["--",1,2,3,4,5].forEach(e=>{const t=document.createElement("option");t.value=e,t.innerHTML=e,"--"===e&&(t.selected=!0),d.appendChild(t)}),r.appendChild(d),t.appendChild(r),r=document.createElement("p");let m=document.createElement("textarea"),o=document.createElement("label");o.setAttribute("for","comments"),o.innerHTML="Comments: ",m.id="comments",m.setAttribute("rows","10"),r.appendChild(o),r.appendChild(m),r.style.display="flex",r.style.alignItems="center",t.appendChild(r),r=document.createElement("p");let c=document.createElement("button");return c.id="submitReview",c.setAttribute("type","submit"),c.innerHTML="Submit Review",r.appendChild(c),t.appendChild(r),t.onsubmit=handleSubmit,e.appendChild(t),e}),handleSubmit=(e=>{e.preventDefault();let t=self.restaurant.id,n=document.getElementById("name").value,r=document.getElementById("rating").value+0,a=document.getElementById("comments").value;DBHelper.saveReview(t,n,r,a,Date.now());let i=document.getElementById("reviewForm");i.parentNode.removeChild(i),document.getElementById("reviewButton").style.display="block"}); \ No newline at end of file +let restaurant;var map;window.initMap=(()=>{fetchRestaurantFromURL((e,t)=>{e?console.error(e):(self.map=new google.maps.Map(document.getElementById("map"),{zoom:16,center:t.latlng,scrollwheel:!1}),fillBreadcrumb(),DBHelper.mapMarkerForRestaurant(self.restaurant,self.map))}),DBHelper.pushUpdates()}),fetchRestaurantFromURL=(e=>{if(self.restaurant)return void e(null,self.restaurant);const t=getParameterByName("id");if(t)DBHelper.fetchRestaurantById(t,(t,n)=>{self.restaurant=n,n?(fillRestaurantHTML(),e(null,n)):console.error(t)});else{e("No restaurant id in URL",null)}}),fillRestaurantHTML=((e=self.restaurant)=>{const t=document.getElementById("restaurant-name");t.innerHTML=e.name;const n=document.createElement("button");n.className="favButton";let r=!(!e.is_favorite||"true"!==e.is_favorite.toString());n.setAttribute("aria-pressed",r),n.setAttribute("aria-label",`Make ${e.name} a favorite!`),n.innerHTML=r?"♥":"♡",n.onclick=(t=>favoriteClicked(e,n)),t.appendChild(n),document.getElementById("restaurant-address").innerHTML=e.address;const a=document.getElementById("restaurant-img");a.className="restaurant-img",a.src=`/img/${e.id}@1x.webp`,a.srcset=`/img/${e.id}@1x.webp 300w,\n /img/${e.id}@2x.webp 600w,\n /img/${e.id}@3x.webp 900w`,a.alt=`Image of ${e.name} restaurant`,document.getElementById("restaurant-cuisine").innerHTML=e.cuisine_type,e.operating_hours&&fillRestaurantHoursHTML(),console.log(`In fillRestaurantHTML, about to call fetch then fill with id: ${e.id}`),DBHelper.fetchReviewsById(e.id).then(fillReviewsHTML)}),favoriteClicked=((e,t)=>{let n=!(!t.getAttribute("aria-pressed")||"true"!==t.getAttribute("aria-pressed")),r=`${DBHelper.DATABASE_URL}/${e.id}/?is_favorite=${!n}`;DBHelper.updateRestaurantCache(e.id,{is_favorite:!n}),DBHelper.addToUpdateQueue(r,"PUT"),t.setAttribute("aria-pressed",!n),t.innerHTML=n?"♡":"♥",t.onclick=(n=>favoriteClicked(e,t))}),fillRestaurantHoursHTML=((e=self.restaurant.operating_hours)=>{const t=document.getElementById("restaurant-hours");for(let n in e){const r=document.createElement("tr"),a=document.createElement("th");a.innerHTML=n,r.appendChild(a);const i=document.createElement("td");i.innerHTML=e[n],r.appendChild(i),t.appendChild(r)}}),fillReviewsHTML=((e=self.restaurant.reviews)=>{console.log("In fillReviewsHTML ",e);const t=document.getElementById("reviews-container"),n=document.createElement("h3");n.innerHTML="Reviews",t.appendChild(n);const r=document.createElement("button");if(r.innerHTML="Add a Review",r.id="reviewButton",r.onclick=addReviewForm,t.appendChild(r),!e){const e=document.createElement("h3");return e.innerHTML="
No reviews yet!
",void t.appendChild(e)}const a=document.getElementById("reviews-list");e.forEach(e=>{a.appendChild(createReviewHTML(e))}),t.appendChild(a)}),createReviewHTML=(e=>{const t=document.createElement("li"),n=document.createElement("p");n.id="reviewer-name",n.innerHTML=e.name,t.appendChild(n);const r=document.createElement("p");r.innerHTML=new Date(e.createdAt).toLocaleDateString(),t.appendChild(r);const a=document.createElement("p");a.innerHTML=`Rating: ${e.rating}`,t.appendChild(a);const l=document.createElement("p");var d="";for(i=0;i{const t=document.getElementById("breadcrumb"),n=document.createElement("li");n.setAttribute("aria-current","page"),n.innerHTML=e.name,t.appendChild(n)}),getParameterByName=((e,t)=>{t||(t=window.location.href),e=e.replace(/[\[\]]/g,"\\$&");const n=new RegExp(`[?&]${e}(=([^&#]*)|&|#|$)`).exec(t);return n?n[2]?decodeURIComponent(n[2].replace(/\+/g," ")):"":null}),addReviewForm=(()=>{document.getElementById("reviewButton").style.display="none",document.getElementById("reviews-list").appendChild(reviewForm()),document.getElementById("name").focus()}),reviewForm=(()=>{let e=document.createElement("li"),t=document.createElement("form");t.id="reviewForm";let n=document.createElement("p");n.innerHTML="New Review",n.id="reviewer-name",t.appendChild(n);let r=document.createElement("p"),a=document.createElement("input"),i=document.createElement("label");i.setAttribute("for","name"),i.innerHTML="First Name: ",a.id="name",a.setAttribute("type","text"),r.appendChild(i),r.appendChild(a),t.appendChild(r),r=document.createElement("p");let l=document.createElement("label");l.setAttribute("for","rating"),l.innerText="Your rating: ",r.appendChild(l);let d=document.createElement("select");d.id="rating",d.name="rating",d.classList.add("rating"),["--",1,2,3,4,5].forEach(e=>{const t=document.createElement("option");t.value=e,t.innerHTML=e,"--"===e&&(t.selected=!0),d.appendChild(t)}),r.appendChild(d),t.appendChild(r),r=document.createElement("p");let m=document.createElement("textarea"),o=document.createElement("label");o.setAttribute("for","comments"),o.innerHTML="Comments: ",m.id="comments",m.setAttribute("rows","10"),r.appendChild(o),r.appendChild(m),r.style.display="flex",r.style.alignItems="center",t.appendChild(r),r=document.createElement("p");let c=document.createElement("button");return c.id="submitReview",c.setAttribute("type","submit"),c.innerHTML="Submit Review",r.appendChild(c),t.appendChild(r),t.onsubmit=handleSubmit,e.appendChild(t),e}),handleSubmit=(e=>{e.preventDefault();let t=self.restaurant.id,n=document.getElementById("name").value,r=document.getElementById("rating").value-0,a=document.getElementById("comments").value;const l=document.getElementById("reviews-list"),d=document.createElement("li"),m=document.createElement("p");m.id="reviewer-name",m.innerHTML=n,d.appendChild(m);const o=document.createElement("p");o.innerHTML="Date",d.appendChild(o);const c=document.createElement("p");c.innerHTML=`Rating: ${r}`,d.appendChild(c);const s=document.createElement("p");var u="";for(i=0;i{switch(e.oldVersion){case 0:e.createObjectStore("restaurantData",{keyPath:"id"});case 1:e.createObjectStore("reviewData",{keypath:"id"}).createIndex("restaurant_id","restaurant_id");case 2:e.createObjectStore("updateData",{keyPath:"id",autoIncrement:!0})}});function apiFetch(e,t){if(console.log(`In apiFetch - event: ${e} id: ${t}`),"POST"==e.request.method||"PUT"==e.request.method)return fetch(e.request).then(function(e){return e.json()});e.request.url.indexOf("restaurants")>-1&&e.respondWith(dbPromise.then(function(e){return e.transaction("restaurantData").objectStore("restaurantData").get(t)}).then(function(n){return n&&n.data||fetch(e.request).then(function(e){return dbPromise.then(function(n){return n.transaction("restaurantData","readwrite").objectStore("restaurantData").put({id:t,data:e.json()}),e.json()})})}).then(function(e){return new Response(JSON.stringify(e))}).catch(function(e){console.log(`In apiFetch catch-restaurantData, error: ${e.message}`)})),e.respondWith(dbPromise.then(function(e){return e.transaction("reviewData").objectStore("reviewData").index("restaurant_id").getAll(t)}).then(function(t){return t&&t.data||fetch(e.request).then(function(e){return dbPromise.then(function(t){let n=t.transaction("reviewData","readwrite").objectStore("reviewData");return e.json().forEach(function(e){n.put({id:e.id,restaurant_id:e.restaurant_id,data:e})}),e.json()})})}).then(function(e){if(e[0].data){let t=e.map(e=>e.data);return new Response(JSON.stringify(t))}return new Response(JSON.stringify(e))}).catch(function(e){console.log(`In apiFetch catch-reviewData, error: ${e.message}`)}))}function cacheFetch(e,t){console.log(`In cacheFetch - event: ${e} request: ${t}`),e.respondWith(caches.match(t)).then(function(t){return t||fetch(e.request).then(function(t){return caches.open(myCache).then(function(n){return-1===t.url.indexOf("browsersync")&&n.put(e.request,t.clone()),t})}).catch(function(e){console.log(`In cacheFetch catch, error: ${e.message}`)})})}self.addEventListener("install",function(e){console.log("In eventListener for install, event: ",e),e.waitUntil(caches.open(myCache).then(function(e){return e.addAll(cacheFiles).then(function(){console.log("Cache worked!")}).catch(function(e){console.log("Caching failed, error: ",e)})}))}),self.addEventListener("fetch",function(e){console.log("In eventListener for fetch, event: ",e);let t=new URL(e.request.url);if("1337"===t.port){let n=t.searchParams.get("restaurant_id")-0;if(n){let t=e.request;t.url.indexOf("restaurant.html")>-1&&(t=new Request("restaurant.html")),cacheFetch(e,t)}else{if(t.pathname.indexOf("restaurants")){let e=t.pathname.split("/");n="restaurants"===e[e.length-1]?"-1":e[e.length-1]}else n=t.searchParams.get("restaurant_id");apiFetch(e,n)}}}); \ No newline at end of file +self.importScripts("js/dbhelper.js","js/idb.js");var myCache="restaurantReview_301",cacheFiles=["/index.html","/restaurant.html","/css/styles.css","/img/","/js/dbhelper.js","/js/main.js","/js/restaurant_info.js","/js/swregister.js","/js/idb.js"];function apiFetch(e,t){if(console.log("In apiFetch"),"GET"!=e.request.method)return fetch(e.request).then(function(e){return e.json()});e.request.url.indexOf("restaurants")>-1&&e.respondWith(DBHelper.idbRestaurantRequest()),e.respondWith(DBHelper.idbReviewRequest())}function cacheFetch(e,t){console.log("In cacheFetch"),e.respondWith(caches.match(t)).then(function(t){return t||fetch(e.request).then(function(t){return caches.open(myCache).then(function(n){return-1===t.url.indexOf("browsersync")&&n.put(e.request,t.clone()),t})}).catch(function(e){console.log(`In cacheFetch catch, error: ${e.message}`)})})}self.addEventListener("install",function(e){console.log("In eventListener for install"),e.waitUntil(caches.open(myCache).then(function(e){return e.addAll(cacheFiles).then(function(){console.log("Cache worked!")}).catch(function(e){console.log("Caching failed, error: ",e)})}))}),self.addEventListener("fetch",function(e){console.log("In eventListener for fetch, event");let t=new URL(e.request.url);if("1337"===t.port){let n=t.searchParams.get("restaurant_id")-0;if(n){let t=e.request;t.url.indexOf("restaurant.html")>-1&&(t=new Request("restaurant.html")),cacheFetch(e,t)}else{if(t.pathname.indexOf("restaurants")){let e=t.pathname.split("/");n="restaurants"===e[e.length-1]?"-1":e[e.length-1]}else n=t.searchParams.get("restaurant_id");apiFetch(e,n)}}}); \ No newline at end of file