parsley/app/javascript/lib/Api.js

463 lines
11 KiB
JavaScript
Raw Normal View History

2018-03-29 22:08:13 -05:00
import config from '../config';
import * as Errors from './Errors';
class Api {
constructor() {
}
baseUrl() { return config.baseApiUrl; }
url(path) {
return this.baseUrl() + path;
}
checkStatus(response) {
2018-04-07 10:54:56 -05:00
if (response.status == 204) {
return null;
} else if (response.ok) {
return response.json();
2018-03-29 22:08:13 -05:00
} else if (response.status === 404) {
throw new Errors.ApiNotFoundError(response.statusText, response);
2018-04-01 21:43:23 -05:00
} else if (response.status === 422) {
return response.json().then(json => { throw new Errors.ApiValidationError(null, response, json) }, jsonErr => { throw new Errors.ApiValidationError(null, response, null) });
2018-03-29 22:08:13 -05:00
} else {
throw new Errors.ApiServerError(response.statusText || "Unknown Server Error", response);
}
}
2018-04-18 17:04:25 -05:00
performRequest(url, method, params = {}, headers = {}) {
2018-03-29 22:08:13 -05:00
const hasBody = Object.keys(params || {}).length !== 0;
2018-04-18 17:04:25 -05:00
const reqHeaders = new Headers();
reqHeaders.append('Accept', 'application/json');
reqHeaders.append('Content-Type', 'application/json');
for (let key in headers) {
reqHeaders.append(key, headers[key]);
}
2018-03-29 22:08:13 -05:00
const opts = {
2018-04-18 17:04:25 -05:00
headers: reqHeaders,
2018-03-30 17:08:09 -05:00
method: method,
credentials: "same-origin"
2018-03-29 22:08:13 -05:00
};
if (hasBody) {
opts.body = JSON.stringify(params);
}
2018-04-07 10:54:56 -05:00
return fetch(url, opts).then(this.checkStatus);
2018-03-29 22:08:13 -05:00
}
2018-04-01 21:43:23 -05:00
objectToUrlParams(obj, queryParams = [], prefixes = []) {
for (let key in obj) {
const val = obj[key];
const paramName = prefixes.join("[") + "[".repeat(Math.min(prefixes.length, 1)) + encodeURIComponent(key) + "]".repeat(prefixes.length);
2018-03-29 22:08:13 -05:00
if (Array.isArray(val)) {
for (let x of val) {
2018-04-01 21:43:23 -05:00
queryParams.push(paramName + "[]=" + (x === null ? '' : encodeURIComponent(x)));
2018-03-29 22:08:13 -05:00
}
2018-04-01 21:43:23 -05:00
} else if (typeof(val) === "object") {
this.objectToUrlParams(val, queryParams, prefixes.concat([key]));
2018-03-29 22:08:13 -05:00
} else {
2018-04-01 21:43:23 -05:00
queryParams.push(paramName + "=" + (val === null ? '' : encodeURIComponent(val)));
2018-03-29 22:08:13 -05:00
}
}
2018-04-01 21:43:23 -05:00
return queryParams;
}
2018-04-18 17:04:25 -05:00
buildGetUrl(url, params = {}) {
2018-04-01 21:43:23 -05:00
const queryParams = this.objectToUrlParams(params);
2018-03-29 22:08:13 -05:00
if (queryParams.length) {
url = url + "?" + queryParams.join("&");
}
2018-04-18 17:04:25 -05:00
return url;
}
get(url, params = {}) {
url = this.buildGetUrl(url, params);
2018-03-29 22:08:13 -05:00
return this.performRequest(url, "GET");
}
2018-04-18 17:04:25 -05:00
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;
});
}
2018-03-30 17:08:09 -05:00
post(url, params = {}) {
return this.performRequest(url, "POST", params);
}
2018-04-01 21:43:23 -05:00
patch(url, params = {}) {
return this.performRequest(url, "PATCH", params);
}
2018-04-07 10:54:56 -05:00
del(url, params = {}) {
return this.performRequest(url, "DELETE", params);
}
2018-04-18 17:04:25 -05:00
getRecipeList(page, per, sortColumn, sortDirection, name, tags, dataHandler) {
2018-03-30 14:31:09 -05:00
const params = {
2018-04-01 21:43:23 -05:00
criteria: {
page: page || null,
per: per || null,
sort_column: sortColumn || null,
sort_direction: sortDirection || null,
name: name || null,
tags: tags || null
}
2018-03-30 14:31:09 -05:00
};
2018-04-18 17:04:25 -05:00
return this.cacheFirstGet("/recipes", params, dataHandler);
2018-03-30 14:31:09 -05:00
}
2018-03-30 17:08:09 -05:00
2018-04-18 17:04:25 -05:00
getRecipe(id, scale = null, system = null, unit = null, dataHandler) {
2018-04-16 11:28:58 -05:00
const params = {
scale,
system,
unit
};
2018-04-18 17:04:25 -05:00
return this.cacheFirstGet("/recipes/" + id, params, dataHandler);
2018-04-01 21:43:23 -05:00
}
2018-04-01 22:32:13 -05:00
buildRecipeParams(recipe) {
2018-04-01 21:43:23 -05:00
const params = {
recipe: {
name: recipe.name,
description: recipe.description,
source: recipe.source,
yields: recipe.yields,
total_time: recipe.total_time,
active_time: recipe.active_time,
step_text: recipe.step_text,
2018-07-13 16:01:56 -05:00
tag_names: recipe.tags,
2018-04-01 21:43:23 -05:00
recipe_ingredients_attributes: recipe.ingredients.map(i => {
if (i._destroy) {
return {
id: i.id,
_destroy: true
};
} else {
return {
id: i.id,
name: i.name,
2018-04-01 22:32:13 -05:00
ingredient_id: i.ingredient_id,
2018-04-01 21:43:23 -05:00
quantity: i.quantity,
units: i.units,
preparation: i.preparation,
sort_order: i.sort_order
};
}
})
}
};
2018-04-01 22:32:13 -05:00
return params;
}
patchRecipe(recipe) {
return this.patch("/recipes/" + recipe.id, this.buildRecipeParams(recipe));
}
2018-04-01 21:43:23 -05:00
2018-04-01 22:32:13 -05:00
postRecipe(recipe) {
return this.post("/recipes/", this.buildRecipeParams(recipe));
2018-04-01 21:43:23 -05:00
}
2018-05-01 10:55:57 -05:00
deleteRecipe(id) {
return this.del("/recipes/" + id);
}
2018-04-01 21:43:23 -05:00
postPreviewSteps(step_text) {
const params = {
step_text: step_text
};
return this.post("/recipes/preview_steps", params);
}
getSearchIngredients(query) {
const params = { query: query };
return this.get("/ingredients/search", params);
}
2018-04-02 00:10:06 -05:00
getCalculate(input, output_unit, density) {
const params = {
input,
output_unit,
density
};
return this.get("/calculator/calculate", params);
}
getIngredientList(page, per, name) {
const params = {
page,
per,
name
};
return this.get("/ingredients/", params);
}
getIngredient(id) {
return this.get("/ingredients/" + id);
}
2018-04-03 18:31:20 -05:00
buildIngredientParams(ingredient) {
return {
ingredient: {
name: ingredient.name,
notes: ingredient.notes,
ndbn: ingredient.ndbn,
density: ingredient.density,
water: ingredient.water,
ash: ingredient.ash,
protein: ingredient.protein,
kcal: ingredient.kcal,
fiber: ingredient.fiber,
sugar: ingredient.sugar,
carbohydrates: ingredient.carbohydrates,
calcium: ingredient.calcium,
iron: ingredient.iron,
magnesium: ingredient.magnesium,
phosphorus: ingredient.phosphorus,
potassium: ingredient.potassium,
sodium: ingredient.sodium,
zinc: ingredient.zinc,
copper: ingredient.copper,
manganese: ingredient.manganese,
vit_c: ingredient.vit_c,
vit_b6: ingredient.vit_b6,
vit_b12: ingredient.vit_b12,
vit_a: ingredient.vit_a,
vit_e: ingredient.vit_e,
vit_d: ingredient.vit_d,
vit_k: ingredient.vit_k,
cholesterol: ingredient.cholesterol,
lipids: ingredient.lipids,
ingredient_units_attributes: ingredient.ingredient_units.map(iu => {
if (iu._destroy) {
return {
id: iu.id,
_destroy: true
};
} else {
return {
id: iu.id,
name: iu.name,
gram_weight: iu.gram_weight
};
}
})
}
}
}
postIngredient(ingredient) {
return this.post("/ingredients/", this.buildIngredientParams(ingredient));
}
patchIngredient(ingredient) {
return this.patch("/ingredients/" + ingredient.id, this.buildIngredientParams(ingredient));
}
2018-05-01 10:55:57 -05:00
deleteIngredient(id) {
return this.del("/ingredients/" + id);
}
2018-04-03 18:31:20 -05:00
postIngredientSelectNdbn(ingredient) {
const url = ingredient.id ? "/ingredients/" + ingredient.id + "/select_ndbn" : "/ingredients/select_ndbn";
return this.post(url, this.buildIngredientParams(ingredient));
}
getUsdaFoodSearch(query) {
return this.get("/ingredients/usda_food_search", {query: query});
}
2018-04-07 10:54:56 -05:00
getNoteList() {
return this.get("/notes/");
}
postNote(note) {
const params = {
content: note.content
};
return this.post("/notes/", params);
}
deleteNote(note) {
return this.del("/notes/" + note.id);
}
2018-04-13 10:25:18 -05:00
getLogList(page, per) {
const params = {
page,
per
};
return this.get("/logs", params);
}
2018-04-14 15:04:08 -05:00
getLog(id) {
return this.get("/logs/" + id);
}
2018-04-13 10:25:18 -05:00
buildLogParams(log) {
2018-04-13 23:32:34 -05:00
const recParams = this.buildRecipeParams(log.recipe);
2018-04-13 10:25:18 -05:00
return {
log: {
date: log.date,
rating: log.rating,
notes: log.notes,
source_recipe_id: log.source_recipe_id,
2018-04-13 23:32:34 -05:00
recipe_attributes: recParams.recipe
2018-04-13 10:25:18 -05:00
}
};
}
postLog(log) {
2018-04-15 14:15:42 -05:00
const params = this.buildLogParams(log);
const rec = params.log.recipe_attributes;
if (rec && rec.recipe_ingredients_attributes) {
rec.recipe_ingredients_attributes.forEach(ri => ri.id = null);
}
return this.post("/recipes/" + log.original_recipe_id + "/logs/", params);
2018-04-13 10:25:18 -05:00
}
patchLog(log) {
return this.patch("/logs/" + log.id, this.buildLogParams(log));
2018-08-28 16:52:56 -05:00
}
getTaskLists(dataHandler) {
return this.cacheFirstGet("/task_lists/", {}, dataHandler);
}
buildTaskListParams(taskList) {
return {
task_list: {
name: taskList.name
}
};
}
postTaskList(taskList) {
const params = this.buildTaskListParams(taskList);
return this.post("/task_lists/", params);
}
patchTaskList(taskList) {
const params = this.buildTaskListParams(taskList);
return this.patch(`/task_lists/${taskList.id}`, params);
}
deleteTaskList(taskList) {
return this.del(`/task_lists/${taskList.id}`);
}
buildTaskItemParams(taskItem) {
return {
task_item: {
name: taskItem.name,
2018-09-06 18:16:13 -05:00
quantity: taskItem.quantity,
completed: taskItem.completed
2018-08-28 16:52:56 -05:00
}
}
}
postTaskItem(listId, taskItem) {
2018-09-06 18:16:13 -05:00
const params = this.buildTaskItemParams(taskItem);
return this.post(`/task_lists/${listId}/task_items`, params);
2018-08-28 16:52:56 -05:00
}
patchTaskItem(listId, taskItem) {
const params = this.buildTaskItemParams(taskItem);
return this.patch(`/task_lists/${listId}/task_items/${taskItem.id}`, params);
}
deleteTaskItem(listId, taskItem) {
return this.del(`/task_lists/${listId}/task_items/${taskItem.id}`);
2018-04-13 10:25:18 -05:00
}
2018-06-09 12:36:46 -05:00
getAdminUserList() {
return this.get("/admin/users");
}
postUser(userObj) {
const params = {
user: {
username: userObj.username,
full_name: userObj.full_name,
email: userObj.email,
password: userObj.password,
password_confirmation: userObj.password_confirmation
}
};
return this.post("/user/", params);
}
patchUser(userObj) {
const params = {
user: {
username: userObj.username,
full_name: userObj.full_name,
email: userObj.email,
password: userObj.password,
password_confirmation: userObj.password_confirmation
}
};
return this.patch("/user/", params);
}
2018-03-30 17:08:09 -05:00
postLogin(username, password) {
const params = {
username: username,
password: password
};
return this.post("/login", params);
}
2018-04-01 12:17:54 -05:00
getLogout() {
return this.get("/logout");
}
2018-03-30 17:08:09 -05:00
getCurrentUser() {
return this.get("/user")
}
2018-03-29 22:08:13 -05:00
}
const api = new Api();
export default api;