This commit is contained in:
Dan Elbert 2018-04-18 17:04:25 -05:00
parent 91e9e78650
commit c3dbefbb4f
8 changed files with 74 additions and 26 deletions

View File

@ -56,8 +56,7 @@
created() { created() {
this.loadResource( this.loadResource(
api.getRecipe(this.recipeId) api.getRecipe(this.recipeId, data => this.log.recipe = data)
.then(data => { this.log.recipe = data; return data; })
); );
}, },

View File

@ -59,8 +59,7 @@
methods: { methods: {
refreshData() { refreshData() {
this.loadResource( this.loadResource(
api.getRecipe(this.recipeId, this.scale, this.system, this.unit) api.getRecipe(this.recipeId, this.scale, this.system, this.unit, data => this.recipe = data)
.then(data => { this.recipe = data; return data; })
); );
} }
}, },

View File

@ -48,8 +48,7 @@
created() { created() {
this.loadResource( this.loadResource(
api.getRecipe(this.recipeId) api.getRecipe(this.recipeId, data => { this.recipe = data; return data; })
.then(data => { this.recipe = data; return data; })
); );
}, },

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<h1 class="title">Recipes 2</h1> <h1 class="title">Recipes</h1>
<router-link v-if="isLoggedIn" :to="{name: 'new_recipe'}" class="button is-primary">Create Recipe</router-link> <router-link v-if="isLoggedIn" :to="{name: 'new_recipe'}" class="button is-primary">Create Recipe</router-link>
@ -142,8 +142,7 @@
getList: debounce(function() { getList: debounce(function() {
this.loadResource( this.loadResource(
api.getRecipeList(this.search.page, this.search.per, this.search.sortColumn, this.search.sortDirection, this.search.name, this.search.tags) api.getRecipeList(this.search.page, this.search.per, this.search.sortColumn, this.search.sortDirection, this.search.name, this.search.tags, data => this.recipeData = data)
.then(data => this.recipeData = data)
); );
}, 500, {leading: true, trailing: true}), }, 500, {leading: true, trailing: true}),

View File

@ -25,19 +25,19 @@ class Api {
} }
} }
parseJSON(response) { performRequest(url, method, params = {}, headers = {}) {
return response.json();
}
performRequest(url, method, params = {}) {
const hasBody = Object.keys(params || {}).length !== 0; const hasBody = Object.keys(params || {}).length !== 0;
const headers = new Headers(); const reqHeaders = new Headers();
headers.append('Accept', 'application/json'); reqHeaders.append('Accept', 'application/json');
headers.append('Content-Type', 'application/json'); reqHeaders.append('Content-Type', 'application/json');
for (let key in headers) {
reqHeaders.append(key, headers[key]);
}
const opts = { const opts = {
headers, headers: reqHeaders,
method: method, method: method,
credentials: "same-origin" credentials: "same-origin"
}; };
@ -67,17 +67,47 @@ class Api {
return queryParams; return queryParams;
} }
get(url, params = {}) { buildGetUrl(url, params = {}) {
const queryParams = this.objectToUrlParams(params); const queryParams = this.objectToUrlParams(params);
if (queryParams.length) { if (queryParams.length) {
url = url + "?" + queryParams.join("&"); url = url + "?" + queryParams.join("&");
} }
return url;
}
get(url, params = {}) {
url = this.buildGetUrl(url, params);
return this.performRequest(url, "GET"); return this.performRequest(url, "GET");
} }
cacheFirstGet(url, params = {}, dataHandler) {
url = this.buildGetUrl(url, params);
let networkDataReceived = false;
const networkUpdate = this.performRequest(url, "GET", {}, {"Cache-Then-Network": "true"})
.then(data => {
networkDataReceived = true;
return dataHandler(data);
});
return caches.match(url)
.then(response => {
if (!response) throw Error("No data");
return response.json();
})
.then(data => {
// don't overwrite newer network data
if (!networkDataReceived) {
dataHandler(data);
}
})
.catch(function() {
// we didn't get cached data, the network is our last hope:
return networkUpdate;
});
}
post(url, params = {}) { post(url, params = {}) {
return this.performRequest(url, "POST", params); return this.performRequest(url, "POST", params);
} }
@ -90,7 +120,7 @@ class Api {
return this.performRequest(url, "DELETE", params); return this.performRequest(url, "DELETE", params);
} }
getRecipeList(page, per, sortColumn, sortDirection, name, tags) { getRecipeList(page, per, sortColumn, sortDirection, name, tags, dataHandler) {
const params = { const params = {
criteria: { criteria: {
page: page || null, page: page || null,
@ -102,17 +132,17 @@ class Api {
} }
}; };
return this.get("/recipes", params); return this.cacheFirstGet("/recipes", params, dataHandler);
} }
getRecipe(id, scale = null, system = null, unit = null) { getRecipe(id, scale = null, system = null, unit = null, dataHandler) {
const params = { const params = {
scale, scale,
system, system,
unit unit
}; };
return this.get("/recipes/" + id, params); return this.cacheFirstGet("/recipes/" + id, params, dataHandler);
} }
buildRecipeParams(recipe) { buildRecipeParams(recipe) {

View File

@ -9,6 +9,7 @@ export default new Vuex.Store({
strict: process.env.NODE_ENV !== 'production', strict: process.env.NODE_ENV !== 'production',
state: { state: {
updateAvailable: false, updateAvailable: false,
loadingCount: 0,
loading: false, loading: false,
error: null, error: null,
authChecked: false, authChecked: false,
@ -44,7 +45,12 @@ export default new Vuex.Store({
}, },
setLoading(state, value) { setLoading(state, value) {
state.loading = value; if (value) {
state.loadingCount = state.loadingCount + 1;
} else {
state.loadingCount = state.loadingCount - 1;
}
state.loading = state.loadingCount !== 0;
}, },
setError(state, value) { setError(state, value) {

View File

@ -7,6 +7,7 @@ $coolors-green: rgba(121, 167, 54, 1);
$coolors-red: #ab4c34; $coolors-red: #ab4c34;
$coolors-yellow: rgba(240, 162, 2, 1); $coolors-yellow: rgba(240, 162, 2, 1);
//$family-sans-serif: "Verdana", "Helvetica Neue", "Helvetica", "Arial", sans-serif !default
$family-serif: Georgia, "Times New Roman", Times, serif; $family-serif: Georgia, "Times New Roman", Times, serif;
// Bluma default overrides // Bluma default overrides

View File

@ -36,8 +36,10 @@ self.addEventListener('activate', function(event) {
self.addEventListener('fetch', function(event) { self.addEventListener('fetch', function(event) {
var reqUrl = new URL(event.request.url); var reqUrl = new URL(event.request.url);
var isCacheThenNetwork = event.request.headers.get("Cache-Then-Network") === "true";
var x, asset; var x, asset;
// Cache-first response for static assets
for (x = 0; x < staticAssets.length; x++) { for (x = 0; x < staticAssets.length; x++) {
asset = staticAssets[x]; asset = staticAssets[x];
if (asset === reqUrl.pathname) { if (asset === reqUrl.pathname) {
@ -50,7 +52,20 @@ self.addEventListener('fetch', function(event) {
} }
} }
// If the 'CacheThenNetwork' header is set, hit the network, cache the page, and return the response
if (isCacheThenNetwork) {
event.respondWith(caches.open(cacheName).then(function (cache) {
return fetch(event.request)
.then(function (response) {
cache.put(event.request, response.clone());
return response;
});
}));
return;
}
// Network, falling back to cache by default to support offline browsing of any cached resources
event.respondWith(caches.open(cacheName).then(function(cache) { event.respondWith(caches.open(cacheName).then(function(cache) {
return fetch(event.request) return fetch(event.request)
.then(function(response) { .then(function(response) {