mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-08-02 20:15:24 +02:00
More localization (#358)
* Translate missing items on About page * Localize import summary dialog * Make site menu translation reactive * Localize import options * Include semi colon in string * Move API texts to frontend + better status codes * Provide feedback to user when no meal is planned * Fix API tests after latest rework * Add warning for API changes in changelog * Refactor API texts handling * Refactor API texts handling #2 * Better API feedback * Rearrange strings hierarchy * Add messages upon recipe updated * Fix 'recipe effected' typo * Remove snackbar usage in backend * Translate toolbox * Provide feedback for tags CRUD * Fix messed up merge * Translate sign-up form * Better feedback for sign-up CRUD * Refactor log-in API texts handling * No error message when user is not authenticated * Remove unimportant console log
This commit is contained in:
parent
861020ffe0
commit
1e5edc7434
72 changed files with 890 additions and 606 deletions
|
@ -1,75 +1,57 @@
|
|||
const baseURL = "/api/";
|
||||
import axios from "axios";
|
||||
import utils from "@/utils";
|
||||
import { store } from "../store";
|
||||
import utils from "@/utils";
|
||||
|
||||
axios.defaults.headers.common[
|
||||
"Authorization"
|
||||
] = `Bearer ${store.getters.getToken}`;
|
||||
|
||||
function processResponse(response) {
|
||||
try {
|
||||
utils.notify.show(response.data.snackbar.text, response.data.snackbar.type);
|
||||
} catch (err) {
|
||||
return;
|
||||
function handleError(error, getText) {
|
||||
if(getText) {
|
||||
utils.notify.error(getText(error.response));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function handleResponse(response, getText) {
|
||||
if(response && getText) {
|
||||
const successText = getText(response);
|
||||
utils.notify.success(successText);
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
return;
|
||||
function defaultErrorText(response) {
|
||||
return response.statusText;
|
||||
}
|
||||
|
||||
function defaultSuccessText(response) {
|
||||
return response.statusText;
|
||||
}
|
||||
|
||||
const apiReq = {
|
||||
post: async function(url, data) {
|
||||
let response = await axios.post(url, data).catch(function(error) {
|
||||
if (error.response) {
|
||||
processResponse(error.response);
|
||||
return error.response;
|
||||
}
|
||||
});
|
||||
processResponse(response);
|
||||
return response;
|
||||
post: async function(url, data, getErrorText = defaultErrorText, getSuccessText) {
|
||||
const response = await axios.post(url, data).catch(function(error) { handleError(error, getErrorText) });
|
||||
return handleResponse(response, getSuccessText);
|
||||
},
|
||||
|
||||
put: async function(url, data, getErrorText = defaultErrorText, getSuccessText) {
|
||||
const response = await axios.put(url, data).catch(function(error) { handleError(error, getErrorText) });
|
||||
return handleResponse(response, getSuccessText);
|
||||
},
|
||||
|
||||
patch: async function(url, data, getErrorText = defaultErrorText, getSuccessText) {
|
||||
const response = await axios.patch(url, data).catch(function(error) { handleError(error, getErrorText) });
|
||||
return handleResponse(response, getSuccessText);
|
||||
},
|
||||
|
||||
put: async function(url, data) {
|
||||
let response = await axios.put(url, data).catch(function(error) {
|
||||
if (error.response) {
|
||||
processResponse(error.response);
|
||||
return response;
|
||||
} else return;
|
||||
});
|
||||
processResponse(response);
|
||||
return response;
|
||||
},
|
||||
patch: async function(url, data) {
|
||||
let response = await axios.patch(url, data).catch(function(error) {
|
||||
if (error.response) {
|
||||
processResponse(error.response);
|
||||
return response;
|
||||
} else return;
|
||||
});
|
||||
processResponse(response);
|
||||
return response;
|
||||
get: function(url, data, getErrorText = defaultErrorText) {
|
||||
return axios.get(url, data).catch(function(error) { handleError(error, getErrorText) });
|
||||
},
|
||||
|
||||
get: async function(url, data) {
|
||||
let response = await axios.get(url, data).catch(function(error) {
|
||||
if (error.response) {
|
||||
processResponse(error.response);
|
||||
return response;
|
||||
} else return;
|
||||
});
|
||||
processResponse(response);
|
||||
return response;
|
||||
},
|
||||
|
||||
delete: async function(url, data) {
|
||||
let response = await axios.delete(url, data).catch(function(error) {
|
||||
if (error.response) {
|
||||
processResponse(error.response);
|
||||
return response;
|
||||
}
|
||||
});
|
||||
processResponse(response);
|
||||
return response;
|
||||
delete: async function(url, data, getErrorText = defaultErrorText, getSuccessText = defaultSuccessText ) {
|
||||
const response = await axios.delete(url, data).catch( function(error) { handleError(error, getErrorText) } );
|
||||
return handleResponse(response, getSuccessText);
|
||||
},
|
||||
|
||||
async download(url) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "@/store";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
const backupBase = baseURL + "backups/";
|
||||
|
||||
|
@ -40,7 +41,12 @@ export const backupAPI = {
|
|||
* @param {string} fileName
|
||||
*/
|
||||
async delete(fileName) {
|
||||
await apiReq.delete(backupURLs.deleteBackup(fileName));
|
||||
return apiReq.delete(
|
||||
backupURLs.deleteBackup(fileName),
|
||||
null,
|
||||
function() { return i18n.t('settings.backup.unable-to-delete-backup'); },
|
||||
function() { return i18n.t('settings.backup.backup-deleted'); }
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Creates a backup on the serve given a set of options
|
||||
|
@ -48,8 +54,12 @@ export const backupAPI = {
|
|||
* @returns
|
||||
*/
|
||||
async create(options) {
|
||||
let response = apiReq.post(backupURLs.createBackup, options);
|
||||
return response;
|
||||
return apiReq.post(
|
||||
backupURLs.createBackup,
|
||||
options,
|
||||
function() { return i18n.t('settings.backup.error-creating-backup-see-log-file'); },
|
||||
function(response) { return i18n.t('settings.backup.backup-created-at-response-export_path', {path: response.data.export_path}); }
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Downloads a file from the server. I don't actually think this is used?
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "@/store";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
const prefix = baseURL + "categories";
|
||||
|
||||
|
@ -22,29 +23,44 @@ export const categoryAPI = {
|
|||
return response.data;
|
||||
},
|
||||
async create(name) {
|
||||
let response = await apiReq.post(categoryURLs.getAll, { name: name });
|
||||
store.dispatch("requestCategories");
|
||||
return response.data;
|
||||
const response = await apiReq.post(
|
||||
categoryURLs.getAll,
|
||||
{ name: name },
|
||||
function() { return i18n.t('category.category-creation-failed'); },
|
||||
function() { return i18n.t('category.category-created'); }
|
||||
);
|
||||
if(response) {
|
||||
store.dispatch("requestCategories");
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
async getRecipesInCategory(category) {
|
||||
let response = await apiReq.get(categoryURLs.getCategory(category));
|
||||
return response.data;
|
||||
},
|
||||
async update(name, newName, overrideRequest = false) {
|
||||
let response = await apiReq.put(categoryURLs.updateCategory(name), {
|
||||
name: newName,
|
||||
});
|
||||
if (!overrideRequest) {
|
||||
const response = await apiReq.put(
|
||||
categoryURLs.updateCategory(name),
|
||||
{ name: newName },
|
||||
function() { return i18n.t('category.category-update-failed'); },
|
||||
function() { return i18n.t('category.category-updated'); }
|
||||
);
|
||||
if (response && !overrideRequest) {
|
||||
store.dispatch("requestCategories");
|
||||
return response.data;
|
||||
}
|
||||
return response.data;
|
||||
},
|
||||
async delete(category, overrideRequest = false) {
|
||||
let response = await apiReq.delete(categoryURLs.deleteCategory(category));
|
||||
if (!overrideRequest) {
|
||||
const response = await apiReq.delete(
|
||||
categoryURLs.deleteCategory(category),
|
||||
null,
|
||||
function() { return i18n.t('category.category-deletion-failed'); },
|
||||
function() { return i18n.t('category.category-deleted'); }
|
||||
);
|
||||
if (response && !overrideRequest) {
|
||||
store.dispatch("requestCategories");
|
||||
}
|
||||
return response.data;
|
||||
return response;
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -68,28 +84,48 @@ export const tagAPI = {
|
|||
return response.data;
|
||||
},
|
||||
async create(name) {
|
||||
let response = await apiReq.post(tagURLs.getAll, { name: name });
|
||||
store.dispatch("requestTags");
|
||||
return response.data;
|
||||
const response = await apiReq.post(
|
||||
tagURLs.getAll,
|
||||
{ name: name },
|
||||
function() { return i18n.t('tag.tag-creation-failed'); },
|
||||
function() { return i18n.t('tag.tag-created'); }
|
||||
);
|
||||
if(response) {
|
||||
store.dispatch("requestTags");
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
async getRecipesInTag(tag) {
|
||||
let response = await apiReq.get(tagURLs.getTag(tag));
|
||||
return response.data;
|
||||
},
|
||||
async update(name, newName, overrideRequest = false) {
|
||||
let response = await apiReq.put(tagURLs.updateTag(name), { name: newName });
|
||||
const response = await apiReq.put(
|
||||
tagURLs.updateTag(name),
|
||||
{ name: newName },
|
||||
function() { return i18n.t('tag.tag-update-failed'); },
|
||||
function() { return i18n.t('tag.tag-updated'); }
|
||||
);
|
||||
|
||||
if (!overrideRequest) {
|
||||
store.dispatch("requestTags");
|
||||
if(response) {
|
||||
if (!overrideRequest) {
|
||||
store.dispatch("requestTags");
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
|
||||
return response.data;
|
||||
},
|
||||
async delete(tag, overrideRequest = false) {
|
||||
let response = await apiReq.delete(tagURLs.deleteTag(tag));
|
||||
if (!overrideRequest) {
|
||||
store.dispatch("requestTags");
|
||||
const response = await apiReq.delete(
|
||||
tagURLs.deleteTag(tag),
|
||||
null,
|
||||
function() { return i18n.t('tag.tag-deletion-failed'); },
|
||||
function() { return i18n.t('tag.tag-deleted'); }
|
||||
);
|
||||
if(response) {
|
||||
if (!overrideRequest) {
|
||||
store.dispatch("requestTags");
|
||||
}
|
||||
return response.data;
|
||||
}
|
||||
return response.data;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from '@/i18n.js';
|
||||
const groupPrefix = baseURL + "groups";
|
||||
|
||||
const groupsURLs = {
|
||||
|
@ -10,25 +11,58 @@ const groupsURLs = {
|
|||
update: id => `${groupPrefix}/${id}`,
|
||||
};
|
||||
|
||||
function deleteErrorText(response) {
|
||||
switch(response.data.detail) {
|
||||
case 'GROUP_WITH_USERS':
|
||||
return i18n.t('group.cannot-delete-group-with-users');
|
||||
|
||||
case 'GROUP_NOT_FOUND':
|
||||
return i18n.t('group.group-not-found');
|
||||
|
||||
case 'DEFAULT_GROUP':
|
||||
return i18n.t('group.cannot-delete-default-group');
|
||||
|
||||
default:
|
||||
return i18n.t('group.group-deletion-failed');
|
||||
}
|
||||
}
|
||||
|
||||
export const groupAPI = {
|
||||
async allGroups() {
|
||||
let response = await apiReq.get(groupsURLs.groups);
|
||||
return response.data;
|
||||
},
|
||||
async create(name) {
|
||||
let response = await apiReq.post(groupsURLs.create, { name: name });
|
||||
return response.data;
|
||||
create(name) {
|
||||
return apiReq.post(
|
||||
groupsURLs.create,
|
||||
{ name: name },
|
||||
function() { return i18n.t('group.user-group-creation-failed'); },
|
||||
function() { return i18n.t('group.user-group-created'); }
|
||||
);
|
||||
},
|
||||
async delete(id) {
|
||||
let response = await apiReq.delete(groupsURLs.delete(id));
|
||||
return response.data;
|
||||
delete(id) {
|
||||
return apiReq.delete(
|
||||
groupsURLs.delete(id),
|
||||
null,
|
||||
deleteErrorText,
|
||||
function() { return i18n.t('group.group-deleted'); }
|
||||
);
|
||||
},
|
||||
async current() {
|
||||
let response = await apiReq.get(groupsURLs.current);
|
||||
return response.data;
|
||||
const response = await apiReq.get(
|
||||
groupsURLs.current,
|
||||
null,
|
||||
null);
|
||||
if(response) {
|
||||
return response.data;
|
||||
}
|
||||
},
|
||||
async update(data) {
|
||||
let response = await apiReq.put(groupsURLs.update(data.id), data);
|
||||
return response.data;
|
||||
update(data) {
|
||||
return apiReq.put(
|
||||
groupsURLs.update(data.id),
|
||||
data,
|
||||
function() { return i18n.t('group.error-updating-group'); },
|
||||
function() { return i18n.t('settings.group-settings-updated'); }
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
const prefix = baseURL + "meal-plans/";
|
||||
|
||||
|
@ -15,9 +16,13 @@ const mealPlanURLs = {
|
|||
};
|
||||
|
||||
export const mealplanAPI = {
|
||||
async create(postBody) {
|
||||
let response = await apiReq.post(mealPlanURLs.create, postBody);
|
||||
return response;
|
||||
create(postBody) {
|
||||
return apiReq.post(
|
||||
mealPlanURLs.create,
|
||||
postBody,
|
||||
function() { return i18n.t('meal-plan.mealplan-creation-failed')},
|
||||
function() { return i18n.t('meal-plan.mealplan-created'); }
|
||||
);
|
||||
},
|
||||
|
||||
async all() {
|
||||
|
@ -35,14 +40,21 @@ export const mealplanAPI = {
|
|||
return response;
|
||||
},
|
||||
|
||||
async delete(id) {
|
||||
let response = await apiReq.delete(mealPlanURLs.delete(id));
|
||||
return response;
|
||||
delete(id) {
|
||||
return apiReq.delete(mealPlanURLs.delete(id),
|
||||
null,
|
||||
function() { return i18n.t('meal-plan.mealplan-deletion-failed'); },
|
||||
function() { return i18n.t('meal-plan.mealplan-deleted'); }
|
||||
);
|
||||
},
|
||||
|
||||
async update(id, body) {
|
||||
let response = await apiReq.put(mealPlanURLs.update(id), body);
|
||||
return response;
|
||||
update(id, body) {
|
||||
return apiReq.put(
|
||||
mealPlanURLs.update(id),
|
||||
body,
|
||||
function() { return i18n.t('meal-plan.mealplan-update-failed'); },
|
||||
function() { return i18n.t('meal-plan.mealplan-updated'); }
|
||||
);
|
||||
},
|
||||
|
||||
async shoppingList(id) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "../store";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
const migrationBase = baseURL + "migrations";
|
||||
|
||||
|
@ -17,8 +18,13 @@ export const migrationAPI = {
|
|||
return response.data;
|
||||
},
|
||||
async delete(folder, file) {
|
||||
let response = await apiReq.delete(migrationURLs.delete(folder, file));
|
||||
return response.data;
|
||||
const response = await apiReq.delete(
|
||||
migrationURLs.delete(folder, file),
|
||||
null,
|
||||
function() { return i18n.t('general.file-folder-not-found'); },
|
||||
function() { return i18n.t('migration.migration-data-removed'); }
|
||||
);
|
||||
return response;
|
||||
},
|
||||
async import(folder, file) {
|
||||
let response = await apiReq.post(migrationURLs.import(folder, file));
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "../store";
|
||||
import { router } from "../main";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
const prefix = baseURL + "recipes/";
|
||||
|
||||
|
@ -26,9 +26,12 @@ export const recipeAPI = {
|
|||
* @returns {string} Recipe Slug
|
||||
*/
|
||||
async createByURL(recipeURL) {
|
||||
let response = await apiReq.post(recipeURLs.createByURL, {
|
||||
url: recipeURL,
|
||||
});
|
||||
const response = await apiReq.post(
|
||||
recipeURLs.createByURL,
|
||||
{ url: recipeURL },
|
||||
function() { return i18n.t('recipe.recipe-creation-failed'); },
|
||||
function() { return i18n.t('recipe.recipe-created'); }
|
||||
);
|
||||
|
||||
store.dispatch("requestRecentRecipes");
|
||||
return response;
|
||||
|
@ -43,7 +46,12 @@ export const recipeAPI = {
|
|||
},
|
||||
|
||||
async create(recipeData) {
|
||||
let response = await apiReq.post(recipeURLs.create, recipeData);
|
||||
const response = await apiReq.post(
|
||||
recipeURLs.create,
|
||||
recipeData,
|
||||
function() { return i18n.t('recipe.recipe-creation-failed'); },
|
||||
function() { return i18n.t('recipe.recipe-created'); }
|
||||
);
|
||||
store.dispatch("requestRecentRecipes");
|
||||
return response.data;
|
||||
},
|
||||
|
@ -53,14 +61,24 @@ export const recipeAPI = {
|
|||
return response.data;
|
||||
},
|
||||
|
||||
async updateImage(recipeSlug, fileObject) {
|
||||
const fd = new FormData();
|
||||
fd.append("image", fileObject);
|
||||
fd.append("extension", fileObject.name.split(".").pop());
|
||||
let response = apiReq.put(recipeURLs.updateImage(recipeSlug), fd);
|
||||
return response;
|
||||
},
|
||||
updateImage(recipeSlug, fileObject, overrideSuccessMsg = false) {
|
||||
const formData = new FormData();
|
||||
formData.append("image", fileObject);
|
||||
formData.append("extension", fileObject.name.split(".").pop());
|
||||
|
||||
let successMessage = null;
|
||||
if(!overrideSuccessMsg) {
|
||||
successMessage = function() { return overrideSuccessMsg ? null : i18n.t('recipe.recipe-image-updated'); };
|
||||
}
|
||||
|
||||
return apiReq.put(
|
||||
recipeURLs.updateImage(recipeSlug),
|
||||
formData,
|
||||
function() { return i18n.t('general.image-upload-failed'); },
|
||||
successMessage
|
||||
);
|
||||
},
|
||||
|
||||
async createAsset(recipeSlug, fileObject, name, icon) {
|
||||
const fd = new FormData();
|
||||
fd.append("file", fileObject);
|
||||
|
@ -70,17 +88,27 @@ export const recipeAPI = {
|
|||
let response = apiReq.post(recipeURLs.createAsset(recipeSlug), fd);
|
||||
return response;
|
||||
},
|
||||
|
||||
async updateImagebyURL(slug, url) {
|
||||
const response = apiReq.post(recipeURLs.updateImage(slug), { url: url });
|
||||
return response;
|
||||
|
||||
updateImagebyURL(slug, url) {
|
||||
return apiReq.post(
|
||||
recipeURLs.updateImage(slug),
|
||||
{ url: url },
|
||||
function() { return i18n.t('general.image-upload-failed'); },
|
||||
function() { return i18n.t('recipe.recipe-image-updated'); }
|
||||
);
|
||||
},
|
||||
|
||||
async update(data) {
|
||||
console.log(data)
|
||||
let response = await apiReq.put(recipeURLs.update(data.slug), data);
|
||||
store.dispatch("patchRecipe", response.data);
|
||||
return response.data.slug; // ! Temporary until I rewrite to refresh page without additional request
|
||||
let response = await apiReq.put(
|
||||
recipeURLs.update(data.slug),
|
||||
data,
|
||||
function() { return i18n.t('recipe.recipe-update-failed'); },
|
||||
function() { return i18n.t('recipe.recipe-updated'); }
|
||||
);
|
||||
if(response) {
|
||||
store.dispatch("patchRecipe", response.data);
|
||||
return response.data.slug; // ! Temporary until I rewrite to refresh page without additional request
|
||||
}
|
||||
},
|
||||
|
||||
async patch(data) {
|
||||
|
@ -89,10 +117,13 @@ export const recipeAPI = {
|
|||
return response.data;
|
||||
},
|
||||
|
||||
async delete(recipeSlug) {
|
||||
await apiReq.delete(recipeURLs.delete(recipeSlug));
|
||||
store.dispatch("requestRecentRecipes");
|
||||
router.push(`/`);
|
||||
delete(recipeSlug) {
|
||||
return apiReq.delete(
|
||||
recipeURLs.delete(recipeSlug),
|
||||
null,
|
||||
function() { return i18n.t('recipe.unable-to-delete-recipe'); },
|
||||
function() { return i18n.t('recipe.recipe-deleted'); }
|
||||
);
|
||||
},
|
||||
|
||||
async allSummary(start = 0, limit = 9999) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
const signUpPrefix = baseURL + "users/sign-ups";
|
||||
|
||||
|
@ -16,15 +17,25 @@ export const signupAPI = {
|
|||
return response.data;
|
||||
},
|
||||
async createToken(data) {
|
||||
let response = await apiReq.post(signUpURLs.createToken, data);
|
||||
let response = await apiReq.post(
|
||||
signUpURLs.createToken,
|
||||
data,
|
||||
function() { return i18n.t('signup.sign-up-link-creation-failed'); },
|
||||
function() { return i18n.t('signup.sign-up-link-created'); }
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
async deleteToken(token) {
|
||||
let response = await apiReq.delete(signUpURLs.deleteToken(token));
|
||||
return response.data;
|
||||
return await apiReq.delete(signUpURLs.deleteToken(token),
|
||||
null,
|
||||
function() { return i18n.t('signup.sign-up-token-deletion-failed'); },
|
||||
function() { return i18n.t('signup.sign-up-token-deleted'); }
|
||||
);
|
||||
},
|
||||
async createUser(token, data) {
|
||||
let response = await apiReq.post(signUpURLs.createUser(token), data);
|
||||
return response.data;
|
||||
return apiReq.post(signUpURLs.createUser(token), data,
|
||||
function() { return i18n.t('user.you-are-not-allowed-to-create-a-user'); },
|
||||
function() { return i18n.t('user.user-created'); }
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import { store } from "@/store";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
const settingsBase = baseURL + "site-settings";
|
||||
|
||||
|
@ -19,9 +20,16 @@ export const siteSettingsAPI = {
|
|||
},
|
||||
|
||||
async update(body) {
|
||||
let response = await apiReq.put(settingsURLs.updateSiteSettings, body);
|
||||
store.dispatch("requestSiteSettings");
|
||||
return response.data;
|
||||
const response = await apiReq.put(
|
||||
settingsURLs.updateSiteSettings,
|
||||
body,
|
||||
function() { return i18n.t('settings.settings-update-failed'); },
|
||||
function() { return i18n.t('settings.settings-updated'); }
|
||||
);
|
||||
if(response) {
|
||||
store.dispatch("requestSiteSettings");
|
||||
}
|
||||
return response;
|
||||
},
|
||||
|
||||
async getPages() {
|
||||
|
@ -34,23 +42,39 @@ export const siteSettingsAPI = {
|
|||
return response.data;
|
||||
},
|
||||
|
||||
async createPage(body) {
|
||||
let response = await apiReq.post(settingsURLs.customPages, body);
|
||||
return response.data;
|
||||
createPage(body) {
|
||||
return apiReq.post(
|
||||
settingsURLs.customPages,
|
||||
body,
|
||||
function() { return i18n.t('page.page-creation-failed'); },
|
||||
function() { return i18n.t('page.new-page-created'); }
|
||||
);
|
||||
},
|
||||
|
||||
async deletePage(id) {
|
||||
let response = await apiReq.delete(settingsURLs.customPage(id));
|
||||
return response.data;
|
||||
return await apiReq.delete(
|
||||
settingsURLs.customPage(id),
|
||||
null,
|
||||
function() { return i18n.t('page.page-deletion-failed'); },
|
||||
function() { return i18n.t('page.page-deleted'); });
|
||||
},
|
||||
|
||||
async updatePage(body) {
|
||||
let response = await apiReq.put(settingsURLs.customPage(body.id), body);
|
||||
return response.data;
|
||||
updatePage(body) {
|
||||
return apiReq.put(
|
||||
settingsURLs.customPage(body.id),
|
||||
body,
|
||||
function() { return i18n.t('page.page-update-failed'); },
|
||||
function() { return i18n.t('page.page-updated'); }
|
||||
);
|
||||
},
|
||||
|
||||
async updateAllPages(allPages) {
|
||||
let response = await apiReq.put(settingsURLs.customPages, allPages);
|
||||
let response = await apiReq.put(
|
||||
settingsURLs.customPages,
|
||||
allPages,
|
||||
function() { return i18n.t('page.pages-update-failed'); },
|
||||
function() { return i18n.t('page.pages-updated'); }
|
||||
);
|
||||
return response;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
const prefix = baseURL + "themes";
|
||||
|
||||
|
@ -23,21 +24,31 @@ export const themeAPI = {
|
|||
},
|
||||
|
||||
async create(postBody) {
|
||||
let response = await apiReq.post(settingsURLs.createTheme, postBody);
|
||||
return response.data;
|
||||
return await apiReq.post(
|
||||
settingsURLs.createTheme,
|
||||
postBody,
|
||||
function() { return i18n.t('settings.theme.error-creating-theme-see-log-file'); },
|
||||
function() { return i18n.t('settings.theme.theme-saved'); });
|
||||
},
|
||||
|
||||
async update(themeName, colors) {
|
||||
update(themeName, colors) {
|
||||
const body = {
|
||||
name: themeName,
|
||||
colors: colors,
|
||||
};
|
||||
let response = await apiReq.put(settingsURLs.updateTheme(themeName), body);
|
||||
return response.data;
|
||||
return apiReq.put(
|
||||
settingsURLs.updateTheme(themeName),
|
||||
body,
|
||||
function() { return i18n.t('settings.theme.error-updating-theme'); },
|
||||
function() { return i18n.t('settings.theme.theme-updated'); });
|
||||
},
|
||||
|
||||
async delete(themeName) {
|
||||
let response = await apiReq.delete(settingsURLs.deleteTheme(themeName));
|
||||
return response.data;
|
||||
delete(themeName) {
|
||||
return apiReq.delete(
|
||||
settingsURLs.deleteTheme(themeName),
|
||||
null,
|
||||
function() { return i18n.t('settings.theme.error-deleting-theme'); },
|
||||
function() { return i18n.t('settings.theme.theme-deleted'); }
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import { apiReq } from "./api-utils";
|
||||
import i18n from '@/i18n.js';
|
||||
|
||||
export const utilsAPI = {
|
||||
// import { api } from "@/api";
|
||||
async uploadFile(url, fileObject) {
|
||||
uploadFile(url, fileObject) {
|
||||
console.log("API Called");
|
||||
|
||||
let response = await apiReq.post(url, fileObject, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
},
|
||||
});
|
||||
return response.data;
|
||||
return apiReq.post(
|
||||
url,
|
||||
fileObject,
|
||||
function() { return i18n.t('general.failure-uploading-file'); },
|
||||
function() { return i18n.t('general.file-uploaded'); }
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { baseURL } from "./api-utils";
|
||||
import { apiReq } from "./api-utils";
|
||||
import axios from "axios";
|
||||
import i18n from '@/i18n.js';
|
||||
const authPrefix = baseURL + "auth";
|
||||
const userPrefix = baseURL + "users";
|
||||
|
||||
|
@ -17,13 +18,23 @@ const usersURLs = {
|
|||
resetPassword: id => `${userPrefix}/${id}/reset-password`,
|
||||
};
|
||||
|
||||
function deleteErrorText(response) {
|
||||
switch(response.data.detail) {
|
||||
case 'SUPER_USER':
|
||||
return i18n.t('user.error-cannot-delete-super-user');
|
||||
|
||||
default:
|
||||
return i18n.t('user.you-are-not-allowed-to-delete-this-user');
|
||||
}
|
||||
}
|
||||
export const userAPI = {
|
||||
async login(formData) {
|
||||
let response = await apiReq.post(authURLs.token, formData, {
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
});
|
||||
let response = await apiReq.post(
|
||||
authURLs.token,
|
||||
formData,
|
||||
function() { return i18n.t('user.incorrect-username-or-password'); },
|
||||
function() { return i18n.t('user.user-successfully-logged-in'); }
|
||||
);
|
||||
return response;
|
||||
},
|
||||
async refresh() {
|
||||
|
@ -36,9 +47,13 @@ export const userAPI = {
|
|||
let response = await apiReq.get(usersURLs.users);
|
||||
return response.data;
|
||||
},
|
||||
async create(user) {
|
||||
let response = await apiReq.post(usersURLs.users, user);
|
||||
return response.data;
|
||||
create(user) {
|
||||
return apiReq.post(
|
||||
usersURLs.users,
|
||||
user,
|
||||
function() { return i18n.t('user.user-creation-failed'); },
|
||||
function() { return i18n.t('user.user-created'); }
|
||||
);
|
||||
},
|
||||
async self() {
|
||||
let response = await apiReq.get(usersURLs.self);
|
||||
|
@ -48,20 +63,37 @@ export const userAPI = {
|
|||
let response = await apiReq.get(usersURLs.userID(id));
|
||||
return response.data;
|
||||
},
|
||||
async update(user) {
|
||||
let response = await apiReq.put(usersURLs.userID(user.id), user);
|
||||
return response.data;
|
||||
update(user) {
|
||||
return apiReq.put(
|
||||
usersURLs.userID(user.id),
|
||||
user,
|
||||
function() { return i18n.t('user.user-update-failed'); },
|
||||
function() { return i18n.t('user.user-updated'); }
|
||||
);
|
||||
},
|
||||
async changePassword(id, password) {
|
||||
let response = await apiReq.put(usersURLs.password(id), password);
|
||||
return response.data;
|
||||
changePassword(id, password) {
|
||||
return apiReq.put(
|
||||
usersURLs.password(id),
|
||||
password,
|
||||
function() { return i18n.t('user.existing-password-does-not-match'); },
|
||||
function() { return i18n.t('user.password-updated'); }
|
||||
);
|
||||
},
|
||||
async delete(id) {
|
||||
let response = await apiReq.delete(usersURLs.userID(id));
|
||||
return response.data;
|
||||
|
||||
delete(id) {
|
||||
return apiReq.delete(
|
||||
usersURLs.userID(id),
|
||||
null,
|
||||
deleteErrorText,
|
||||
function() { return i18n.t('user.user-deleted'); }
|
||||
);
|
||||
},
|
||||
async resetPassword(id) {
|
||||
let response = await apiReq.put(usersURLs.resetPassword(id));
|
||||
return response.data;
|
||||
resetPassword(id) {
|
||||
return apiReq.put(
|
||||
usersURLs.resetPassword(id),
|
||||
null,
|
||||
function() { return i18n.t('user.password-reset-failed'); },
|
||||
function() { return i18n.t('user.password-has-been-reset-to-the-default-password'); }
|
||||
);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -90,7 +90,7 @@ export default {
|
|||
computed: {
|
||||
inputLabel() {
|
||||
if (!this.showLabel) return null;
|
||||
return this.tagSelector ? this.$t('recipe.tags') : this.$t('recipe.categories');
|
||||
return this.tagSelector ? this.$t('tag.tags') : this.$t('recipe.categories');
|
||||
},
|
||||
activeItems() {
|
||||
let ItemObjects = [];
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
mdi-import
|
||||
</v-icon>
|
||||
<v-toolbar-title class="headline">
|
||||
Import Summary
|
||||
{{ $t("settings.backup.import-summary") }}
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
</v-app-bar>
|
||||
|
@ -18,8 +18,8 @@
|
|||
<div>
|
||||
<h3>{{ values.title }}</h3>
|
||||
</div>
|
||||
<div class="success--text">Success: {{ values.success }}</div>
|
||||
<div class="error--text">Failed: {{ values.failure }}</div>
|
||||
<div class="success--text">{{ $t("general.success-count", { count: values.success }) }}</div>
|
||||
<div class="error--text">{{ $t("general.failed-count", { count: values.failure }) }}</div>
|
||||
</v-card-text>
|
||||
</div>
|
||||
</v-row>
|
||||
|
@ -28,7 +28,7 @@
|
|||
<v-tab>{{ $t("general.recipes") }}</v-tab>
|
||||
<v-tab>{{ $t("general.themes") }}</v-tab>
|
||||
<v-tab>{{ $t("general.settings") }}</v-tab>
|
||||
<v-tab> Pages </v-tab>
|
||||
<v-tab> {{ $t("settings.pages") }} </v-tab>
|
||||
<v-tab>{{ $t("general.users") }}</v-tab>
|
||||
<v-tab>{{ $t("general.groups") }}</v-tab>
|
||||
</v-tabs>
|
||||
|
@ -59,24 +59,30 @@ export default {
|
|||
userData: [],
|
||||
groupData: [],
|
||||
pageData: [],
|
||||
importHeaders: [
|
||||
{
|
||||
text: "Status",
|
||||
value: "status",
|
||||
},
|
||||
{
|
||||
text: "Name",
|
||||
align: "start",
|
||||
sortable: true,
|
||||
value: "name",
|
||||
},
|
||||
|
||||
{ text: "Exception", value: "data-table-expand", align: "center" },
|
||||
],
|
||||
allDataTables: [],
|
||||
}),
|
||||
|
||||
computed: {
|
||||
|
||||
importHeaders() {
|
||||
return [
|
||||
{
|
||||
text: this.$t('general.status'),
|
||||
value: "status",
|
||||
},
|
||||
{
|
||||
text: this.$t('general.name'),
|
||||
align: "start",
|
||||
sortable: true,
|
||||
value: "name",
|
||||
},
|
||||
{
|
||||
text: this.$t('general.exception'),
|
||||
value: "data-table-expand",
|
||||
align: "center"
|
||||
},
|
||||
]
|
||||
},
|
||||
recipeNumbers() {
|
||||
return this.calculateNumbers(this.$t("general.recipes"), this.recipeData);
|
||||
},
|
||||
|
@ -96,7 +102,7 @@ export default {
|
|||
return this.calculateNumbers(this.$t("general.groups"), this.groupData);
|
||||
},
|
||||
pageNumbers() {
|
||||
return this.calculateNumbers("Pages", this.pageData);
|
||||
return this.calculateNumbers(this.$t("settings.pages"), this.pageData);
|
||||
},
|
||||
allNumbers() {
|
||||
return [
|
||||
|
|
|
@ -91,18 +91,12 @@ export default {
|
|||
let formData = new FormData();
|
||||
formData.append("username", this.user.email);
|
||||
formData.append("password", this.user.password);
|
||||
let key;
|
||||
try {
|
||||
key = await api.users.login(formData);
|
||||
} catch {
|
||||
const response = await api.users.login(formData);
|
||||
if (!response) {
|
||||
this.error = true;
|
||||
}
|
||||
if (key.status != 200) {
|
||||
this.error = true;
|
||||
this.loading = false;
|
||||
} else {
|
||||
this.clear();
|
||||
this.$store.commit("setToken", key.data.access_token);
|
||||
this.$store.commit("setToken", response.data.access_token);
|
||||
this.$emit("logged-in");
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@
|
|||
class="mr-2"
|
||||
>
|
||||
</v-progress-circular>
|
||||
<v-toolbar-title class="headline"> Sign Up </v-toolbar-title>
|
||||
<v-toolbar-title class="headline">
|
||||
{{$t('signup.sign-up')}}
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
</v-app-bar>
|
||||
<v-card-text>
|
||||
Welcome to Mealie! To become a user of this instance you are required to
|
||||
have a valid invitation link. If you haven't recieved an invitation you
|
||||
are unable to sign-up. To recieve a link, contact the sites administrator.
|
||||
{{$t('signup.welcome-to-mealie')}}
|
||||
<v-divider class="mt-3"></v-divider>
|
||||
<v-form ref="signUpForm" @submit.prevent="signUp">
|
||||
<v-text-field
|
||||
|
@ -28,7 +28,7 @@
|
|||
prepend-icon="mdi-account"
|
||||
validate-on-blur
|
||||
:rules="[existsRule]"
|
||||
label="Display Name"
|
||||
:label="$t('signup.display-name')"
|
||||
type="email"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
|
@ -59,7 +59,7 @@
|
|||
:type="showPassword ? 'text' : 'password'"
|
||||
:append-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
|
||||
:rules="[
|
||||
user.password === user.passwordConfirm || 'Password must match',
|
||||
user.password === user.passwordConfirm || $t('user.password-must-match'),
|
||||
]"
|
||||
@click:append="showPassword = !showPassword"
|
||||
></v-text-field>
|
||||
|
@ -71,11 +71,11 @@
|
|||
block="block"
|
||||
type="submit"
|
||||
>
|
||||
Sign Up
|
||||
{{$t('signup.sign-up')}}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
<v-alert dense v-if="error" outlined class="mt-3 mb-0" type="error">
|
||||
Error Signing Up
|
||||
{{$t('signup.error-signing-up')}}
|
||||
</v-alert>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
|
@ -132,18 +132,16 @@ export default {
|
|||
admin: false,
|
||||
};
|
||||
|
||||
let successUser = false;
|
||||
if (this.$refs.signUpForm.validate()) {
|
||||
let response = await api.signUps.createUser(this.token, userData);
|
||||
successUser = response.snackbar.text.includes("Created");
|
||||
if (await api.signUps.createUser(this.token, userData)) {
|
||||
this.$emit("user-created");
|
||||
this.$router.push("/");
|
||||
}
|
||||
}
|
||||
|
||||
this.$emit("user-created");
|
||||
|
||||
|
||||
this.loading = false;
|
||||
if (successUser) {
|
||||
this.$router.push("/");
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -36,8 +36,9 @@ export default {
|
|||
return utils.getDateAsPythonDate(dateObject);
|
||||
},
|
||||
async update() {
|
||||
await api.mealPlans.update(this.mealPlan.uid, this.mealPlan);
|
||||
this.$emit("updated");
|
||||
if (await api.mealPlans.update(this.mealPlan.uid, this.mealPlan)) {
|
||||
this.$emit("updated");
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -197,11 +197,12 @@ export default {
|
|||
endDate: this.endDate,
|
||||
meals: this.meals,
|
||||
};
|
||||
await api.mealPlans.create(mealBody);
|
||||
this.$emit(CREATE_EVENT);
|
||||
this.meals = [];
|
||||
this.startDate = null;
|
||||
this.endDate = null;
|
||||
if (await api.mealPlans.create(mealBody)) {
|
||||
this.$emit(CREATE_EVENT);
|
||||
this.meals = [];
|
||||
this.startDate = null;
|
||||
this.endDate = null;
|
||||
}
|
||||
},
|
||||
|
||||
getImage(image) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<v-icon left>
|
||||
mdi-image
|
||||
</v-icon>
|
||||
{{ $t("recipe.image") }}
|
||||
{{ $t("general.image") }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card width="400">
|
||||
|
@ -71,8 +71,9 @@ export default {
|
|||
},
|
||||
async getImageFromURL() {
|
||||
this.loading = true;
|
||||
const response = await api.recipes.updateImagebyURL(this.slug, this.url);
|
||||
if (response) this.$emit(REFRESH_EVENT);
|
||||
if (await api.recipes.updateImagebyURL(this.slug, this.url)) {
|
||||
this.$emit(REFRESH_EVENT);
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
},
|
||||
|
|
|
@ -74,7 +74,7 @@
|
|||
:show-label="false"
|
||||
/>
|
||||
|
||||
<h2 class="mt-4">{{ $t("recipe.tags") }}</h2>
|
||||
<h2 class="mt-4">{{ $t("tag.tags") }}</h2>
|
||||
<CategoryTagSelector
|
||||
:return-object="false"
|
||||
v-model="value.tags"
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
</v-card>
|
||||
<v-card class="mt-2" v-if="tags.length > 0">
|
||||
<v-card-title class="py-2">
|
||||
{{ $t("recipe.tags") }}
|
||||
{{ $t("tag.tags") }}
|
||||
</v-card-title>
|
||||
<v-divider class="mx-2"></v-divider>
|
||||
<v-card-text>
|
||||
|
@ -69,7 +69,7 @@
|
|||
</v-row>
|
||||
<div v-if="!medium">
|
||||
<RecipeChips :title="$t('recipe.categories')" :items="categories" />
|
||||
<RecipeChips :title="$t('recipe.tags')" :items="tags" />
|
||||
<RecipeChips :title="$t('tag.tags')" :items="tags" />
|
||||
<Nutrition :value="nutrition" :edit="false" />
|
||||
<Assets :value="assets" :edit="false" :slug="slug" />
|
||||
</div>
|
||||
|
|
|
@ -55,10 +55,10 @@ export default {
|
|||
let formData = new FormData();
|
||||
formData.append(this.fileName, this.file);
|
||||
|
||||
await api.utils.uploadFile(this.url, formData);
|
||||
|
||||
if(await api.utils.uploadFile(this.url, formData)) {
|
||||
this.$emit(UPLOAD_EVENT);
|
||||
}
|
||||
this.isSelecting = false;
|
||||
this.$emit(UPLOAD_EVENT);
|
||||
}
|
||||
},
|
||||
onButtonClick() {
|
||||
|
|
|
@ -105,17 +105,15 @@ export default {
|
|||
async createRecipe() {
|
||||
if (this.$refs.urlForm.validate()) {
|
||||
this.processing = true;
|
||||
let response = await api.recipes.createByURL(this.recipeURL);
|
||||
if (response.status !== 201) {
|
||||
this.error = true;
|
||||
this.processing = false;
|
||||
return;
|
||||
}
|
||||
|
||||
this.addRecipe = false;
|
||||
const response = await api.recipes.createByURL(this.recipeURL);
|
||||
this.processing = false;
|
||||
this.recipeURL = "";
|
||||
this.$router.push(`/recipe/${response.data}`);
|
||||
if (response) {
|
||||
this.addRecipe = false;
|
||||
this.recipeURL = "";
|
||||
this.$router.push(`/recipe/${response.data}`);
|
||||
} else {
|
||||
this.error = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -44,9 +44,9 @@ export default {
|
|||
components: {
|
||||
LoginDialog,
|
||||
},
|
||||
data: function() {
|
||||
return {
|
||||
items: [
|
||||
computed: {
|
||||
items() {
|
||||
return [
|
||||
{
|
||||
icon: "mdi-account",
|
||||
title: "Login",
|
||||
|
@ -83,10 +83,8 @@ export default {
|
|||
nav: "/admin",
|
||||
restricted: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
]
|
||||
},
|
||||
filteredItems() {
|
||||
if (this.loggedIn) {
|
||||
return this.items.filter(x => x.restricted == true);
|
||||
|
|
|
@ -13,11 +13,22 @@
|
|||
"demo": "Demo",
|
||||
"demo-status": "Demo Status",
|
||||
"development": "Development",
|
||||
"download-log": "Download Log",
|
||||
"download-recipe-json": "Download Recipe JSON",
|
||||
"not-demo": "Not Demo",
|
||||
"production": "Production",
|
||||
"sqlite-file": "SQLite File",
|
||||
"version": "Version"
|
||||
},
|
||||
"category": {
|
||||
"category-created": "Category created",
|
||||
"category-creation-failed": "Category creation failed",
|
||||
"category-deleted": "Category Deleted",
|
||||
"category-deletion-failed": "Category deletion failed",
|
||||
"category-filter": "Category Filter",
|
||||
"category-update-failed": "Category update failed",
|
||||
"category-updated": "Category updated"
|
||||
},
|
||||
"general": {
|
||||
"apply": "Apply",
|
||||
"cancel": "Cancel",
|
||||
|
@ -30,29 +41,40 @@
|
|||
"download": "Download",
|
||||
"edit": "Edit",
|
||||
"enabled": "Enabled",
|
||||
"exception": "Exception",
|
||||
"failed-count": "Failed: {count}",
|
||||
"failure-uploading-file": "Failure uploading file",
|
||||
"field-required": "Field Required",
|
||||
"file-folder-not-found": "File/folder not found",
|
||||
"file-uploaded": "File uploaded",
|
||||
"filter": "Filter",
|
||||
"friday": "Friday",
|
||||
"get": "Get",
|
||||
"groups": "Groups",
|
||||
"image": "Image",
|
||||
"image-upload-failed": "Image upload failed",
|
||||
"import": "Import",
|
||||
"keyword": "Keyword",
|
||||
"monday": "Monday",
|
||||
"name": "Name",
|
||||
"no": "No",
|
||||
"ok": "OK",
|
||||
"options": "Options",
|
||||
"options": "Options:",
|
||||
"random": "Random",
|
||||
"recent": "Recent",
|
||||
"recipes": "Recipes",
|
||||
"rename-object": "Rename {0}",
|
||||
"reset": "Reset",
|
||||
"saturday": "Saturday",
|
||||
"save": "Save",
|
||||
"settings": "Settings",
|
||||
"sort": "Sort",
|
||||
"sort-alphabetically": "A-Z",
|
||||
"status": "Status",
|
||||
"submit": "Submit",
|
||||
"success-count": "Success: {count}",
|
||||
"sunday": "Sunday",
|
||||
"templates": "Templates",
|
||||
"templates": "Templates:",
|
||||
"themes": "Themes",
|
||||
"thursday": "Thursday",
|
||||
"token": "Token",
|
||||
|
@ -64,6 +86,25 @@
|
|||
"wednesday": "Wednesday",
|
||||
"yes": "Yes"
|
||||
},
|
||||
"group": {
|
||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
||||
"cannot-delete-default-group": "Cannot delete default group",
|
||||
"cannot-delete-group-with-users": "Cannot delete group with users",
|
||||
"confirm-group-deletion": "Confirm Group Deletion",
|
||||
"create-group": "Create Group",
|
||||
"error-updating-group": "Error updating group",
|
||||
"group": "Group",
|
||||
"group-deleted": "Group deleted",
|
||||
"group-deletion-failed": "Group deletion failed",
|
||||
"group-id-with-value": "Group ID: {groupID}",
|
||||
"group-name": "Group Name",
|
||||
"group-not-found": "Group not found",
|
||||
"groups": "Groups",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"user-group": "User Group",
|
||||
"user-group-created": "User Group Created",
|
||||
"user-group-creation-failed": "User Group Creation Failed"
|
||||
},
|
||||
"meal-plan": {
|
||||
"create-a-new-meal-plan": "Create a New Meal Plan",
|
||||
"dinner-this-week": "Dinner This Week",
|
||||
|
@ -73,6 +114,14 @@
|
|||
"group": "Group (Beta)",
|
||||
"meal-planner": "Meal Planner",
|
||||
"meal-plans": "Meal Plans",
|
||||
"mealplan-created": "Mealplan created",
|
||||
"mealplan-creation-failed": "Mealplan creation failed",
|
||||
"mealplan-deleted": "Mealplan Deleted",
|
||||
"mealplan-deletion-failed": "Mealplan deletion failed",
|
||||
"mealplan-update-failed": "Mealplan update failed",
|
||||
"mealplan-updated": "Mealplan Updated",
|
||||
"no-meal-plan-defined-yet": "No meal plan defined yet",
|
||||
"no-meal-planned-for-today": "No meal planned for today",
|
||||
"only-recipes-with-these-categories-will-be-used-in-meal-plans": "Only recipes with these categories will be used in Meal Plans",
|
||||
"planner": "Planner",
|
||||
"quick-week": "Quick Week",
|
||||
|
@ -84,6 +133,7 @@
|
|||
"description": "Migrate data from Chowdown",
|
||||
"title": "Chowdown"
|
||||
},
|
||||
"migration-data-removed": "Migration data removed",
|
||||
"nextcloud": {
|
||||
"description": "Migrate data from a Nextcloud Cookbook intance",
|
||||
"title": "Nextcloud Cookbook"
|
||||
|
@ -102,23 +152,30 @@
|
|||
"page": {
|
||||
"all-recipes": "All Recipes",
|
||||
"home-page": "Home Page",
|
||||
"new-page-created": "New page created",
|
||||
"page-creation-failed": "Page creation failed",
|
||||
"page-deleted": "Page deleted",
|
||||
"page-deletion-failed": "Page deletion failed",
|
||||
"page-update-failed": "Page update failed",
|
||||
"page-updated": "Page updated",
|
||||
"pages-update-failed": "Pages update failed",
|
||||
"pages-updated": "Pages updated",
|
||||
"recent": "Recent"
|
||||
},
|
||||
"recipe": {
|
||||
"assets": "Assets",
|
||||
"add-key": "Add Key",
|
||||
"api-extras": "API Extras",
|
||||
"assets": "Assets",
|
||||
"calories": "Calories",
|
||||
"calories-suffix": "calories",
|
||||
"carbohydrate-content": "Carbohydrate",
|
||||
"categories": "Categories",
|
||||
"delete-confirmation": "Are you sure you want to delete this recipe?",
|
||||
"delete-recipe": "Delete Recipe",
|
||||
"description": "Description",
|
||||
"fat-content": "Fat",
|
||||
"fiber-content": "Fiber",
|
||||
"carbohydrate-content": "Carbohydrate",
|
||||
"grams": "grams",
|
||||
"image": "Image",
|
||||
"ingredient": "Ingredient",
|
||||
"ingredients": "Ingredients",
|
||||
"instructions": "Instructions",
|
||||
|
@ -135,27 +192,32 @@
|
|||
"perform-time": "Cook Time",
|
||||
"prep-time": "Prep Time",
|
||||
"protein-content": "Protein",
|
||||
"recipe-created": "Recipe created",
|
||||
"recipe-creation-failed": "Recipe creation failed",
|
||||
"recipe-deleted": "Recipe deleted",
|
||||
"recipe-image": "Recipe Image",
|
||||
"recipe-image-updated": "Recipe image updated",
|
||||
"recipe-name": "Recipe Name",
|
||||
"recipe-update-failed": "Recipe update failed",
|
||||
"recipe-updated": "Recipe updated",
|
||||
"servings": "Servings",
|
||||
"sodium-content": "Sodium",
|
||||
"step-index": "Step: {step}",
|
||||
"sugar-content": "Sugar",
|
||||
"tags": "Tags",
|
||||
"title": "Title",
|
||||
"total-time": "Total Time",
|
||||
"unable-to-delete-recipe": "Unable to Delete Recipe",
|
||||
"view-recipe": "View Recipe"
|
||||
},
|
||||
"search": {
|
||||
"search-mealie": "Search Mealie (press /)",
|
||||
"search-placeholder": "Search...",
|
||||
"max-results": "Max Results",
|
||||
"category-filter": "Category Filter",
|
||||
"and": "and",
|
||||
"exclude": "Exclude",
|
||||
"include": "Include",
|
||||
"max-results": "Max Results",
|
||||
"or": "Or",
|
||||
"and": "and",
|
||||
"search": "Search",
|
||||
"search-mealie": "Search Mealie (press /)",
|
||||
"search-placeholder": "Search...",
|
||||
"tag-filter": "Tag Filter"
|
||||
},
|
||||
"settings": {
|
||||
|
@ -163,10 +225,15 @@
|
|||
"admin-settings": "Admin Settings",
|
||||
"available-backups": "Available Backups",
|
||||
"backup": {
|
||||
"backup-created-at-response-export_path": "Backup Created at {path}",
|
||||
"backup-deleted": "Backup deleted",
|
||||
"backup-tag": "Backup Tag",
|
||||
"create-heading": "Create a Backup",
|
||||
"error-creating-backup-see-log-file": "Error Creating Backup. See Log File",
|
||||
"full-backup": "Full Backup",
|
||||
"partial-backup": "Partial Backup"
|
||||
"import-summary": "Import Summary",
|
||||
"partial-backup": "Partial Backup",
|
||||
"unable-to-delete-backup": "Unable to Delete Backup."
|
||||
},
|
||||
"backup-and-exports": "Backups",
|
||||
"backup-info": "Backups are exported in standard JSON format along with all the images stored on the file system. In your backup folder you'll find a .zip file that contains all of the recipe JSON and images from the database. Additionally, if you selected a markdown file, those will also be stored in the .zip file. To import a backup, it must be located in your backups folder. Automated backups are done each day at 3:00 AM.",
|
||||
|
@ -175,6 +242,7 @@
|
|||
"custom-pages": "Custom Pages",
|
||||
"edit-page": "Edit Page",
|
||||
"first-day-of-week": "First day of the week",
|
||||
"group-settings-updated": "Group Settings Updated",
|
||||
"homepage": {
|
||||
"all-categories": "All Categories",
|
||||
"card-per-section": "Card Per Section",
|
||||
|
@ -190,9 +258,12 @@
|
|||
"migrations": "Migrations",
|
||||
"new-page": "New Page",
|
||||
"page-name": "Page Name",
|
||||
"pages": "Pages",
|
||||
"profile": "Profile",
|
||||
"remove-existing-entries-matching-imported-entries": "Remove existing entries matching imported entries",
|
||||
"set-new-time": "Set New Time",
|
||||
"settings-update-failed": "Settings update failed",
|
||||
"settings-updated": "Settings updated",
|
||||
"site-settings": "Site Settings",
|
||||
"theme": {
|
||||
"accent": "Accent",
|
||||
|
@ -203,6 +274,9 @@
|
|||
"default-to-system": "Default to system",
|
||||
"delete-theme": "Delete Theme",
|
||||
"error": "Error",
|
||||
"error-creating-theme-see-log-file": "Error creating theme. See log file.",
|
||||
"error-deleting-theme": "Error deleting theme",
|
||||
"error-updating-theme": "Error updating theme",
|
||||
"info": "Info",
|
||||
"light": "Light",
|
||||
"primary": "Primary",
|
||||
|
@ -210,51 +284,69 @@
|
|||
"select-a-theme-from-the-dropdown-or-create-a-new-theme-note-that-the-default-theme-will-be-served-to-all-users-who-have-not-set-a-theme-preference": "Select a theme from the dropdown or create a new theme. Note that the default theme will be served to all users who have not set a theme preference.",
|
||||
"success": "Success",
|
||||
"theme": "Theme",
|
||||
"theme-deleted": "Theme deleted",
|
||||
"theme-name": "Theme Name",
|
||||
"theme-name-is-required": "Theme Name is required.",
|
||||
"theme-saved": "Theme Saved",
|
||||
"theme-settings": "Theme Settings",
|
||||
"theme-updated": "Theme updated",
|
||||
"warning": "Warning"
|
||||
},
|
||||
"toolbox": {
|
||||
"assign-all": "Assign All",
|
||||
"bulk-assign": "Bulk Assign",
|
||||
"new-name": "New Name",
|
||||
"no-unused-items": "No Unused Items",
|
||||
"recipes-affected": "No Recipes Affected|One Recipe Affected|{count} Recipes Affected",
|
||||
"remove-unused": "Remove Unused",
|
||||
"title-case-all": "Title Case All",
|
||||
"toolbox": "Toolbox"
|
||||
},
|
||||
"webhooks": {
|
||||
"meal-planner-webhooks": "Meal Planner Webhooks",
|
||||
"test-webhooks": "Test Webhooks",
|
||||
"the-urls-listed-below-will-recieve-webhooks-containing-the-recipe-data-for-the-meal-plan-on-its-scheduled-day-currently-webhooks-will-execute-at": "The URLs listed below will receive webhooks containing the recipe data for the meal plan on it's scheduled day. Currently Webhooks will execute at",
|
||||
"webhook-url": "Webhook URL"
|
||||
},
|
||||
"toolbox": {
|
||||
"toolbox": "Toolbox",
|
||||
"new-name": "New Name",
|
||||
"recipes-effected": "Recipes Effected",
|
||||
"title-case-all": "Title Case All",
|
||||
"no-unused-items": "No Unused Items",
|
||||
"remove-unused": "Remove Unused",
|
||||
"assign-all": "Assign All",
|
||||
"bulk-assign": "Bulk Assign"
|
||||
}
|
||||
},
|
||||
"signup": {
|
||||
"display-name": "Display Name",
|
||||
"error-signing-up": "Error Signing Up",
|
||||
"sign-up": "Sign Up",
|
||||
"sign-up-link-created": "Sign up link created",
|
||||
"sign-up-link-creation-failed": "Sign up link creation failed",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"sign-up-token-deleted": "Sign Up Token Deleted",
|
||||
"sign-up-token-deletion-failed": "Sign up token deletion failed",
|
||||
"welcome-to-mealie": "Welcome to Mealie! To become a user of this instance you are required to have a valid invitation link. If you haven't recieved an invitation you are unable to sign-up. To recieve a link, contact the sites administrator."
|
||||
},
|
||||
"tag": {
|
||||
"tag-created": "Tag created",
|
||||
"tag-creation-failed": "Tag creation failed",
|
||||
"tag-deleted": "Tag deleted",
|
||||
"tag-deletion-failed": "Tag deletion failed",
|
||||
"tag-update-failed": "Tag update failed",
|
||||
"tag-updated": "Tag updated",
|
||||
"tags": "Tags"
|
||||
},
|
||||
"user": {
|
||||
"admin": "Admin",
|
||||
"are-you-sure-you-want-to-delete-the-group": "Are you sure you want to delete <b>{groupName}<b/>?",
|
||||
"are-you-sure-you-want-to-delete-the-link": "Are you sure you want to delete the link <b>{link}<b/>?",
|
||||
"are-you-sure-you-want-to-delete-the-user": "Are you sure you want to delete the user <b>{activeName} ID: {activeId}<b/>?",
|
||||
"confirm-group-deletion": "Confirm Group Deletion",
|
||||
"confirm-link-deletion": "Confirm Link Deletion",
|
||||
"confirm-password": "Confirm Password",
|
||||
"confirm-user-deletion": "Confirm User Deletion",
|
||||
"could-not-validate-credentials": "Could Not Validate Credentials",
|
||||
"create-group": "Create Group",
|
||||
"create-link": "Create Link",
|
||||
"create-user": "Create User",
|
||||
"current-password": "Current Password",
|
||||
"e-mail-must-be-valid": "E-mail must be valid",
|
||||
"edit-user": "Edit User",
|
||||
"email": "Email",
|
||||
"error-cannot-delete-super-user": "Error! Cannot Delete Super User",
|
||||
"existing-password-does-not-match": "Existing password does not match",
|
||||
"full-name": "Full Name",
|
||||
"group": "Group",
|
||||
"group-id-with-value": "Group ID: {groupID}",
|
||||
"group-name": "Group Name",
|
||||
"groups": "Groups",
|
||||
"groups-can-only-be-set-by-administrators": "Groups can only be set by administrators",
|
||||
"incorrect-username-or-password": "Incorrect username or password",
|
||||
"link-id": "Link ID",
|
||||
"link-name": "Link Name",
|
||||
"login": "Login",
|
||||
|
@ -262,20 +354,29 @@
|
|||
"new-password": "New Password",
|
||||
"new-user": "New User",
|
||||
"password": "Password",
|
||||
"password-has-been-reset-to-the-default-password": "Password has been reset to the default password",
|
||||
"password-must-match": "Password must match",
|
||||
"password-reset-failed": "Password reset failed",
|
||||
"password-updated": "Password updated",
|
||||
"reset-password": "Reset Password",
|
||||
"sign-in": "Sign in",
|
||||
"sign-up-links": "Sign Up Links",
|
||||
"total-mealplans": "Total MealPlans",
|
||||
"total-users": "Total Users",
|
||||
"upload-photo": "Upload Photo",
|
||||
"use-8-characters-or-more-for-your-password": "Use 8 characters or more for your password",
|
||||
"user-group": "User Group",
|
||||
"user-created": "User created",
|
||||
"user-creation-failed": "User creation failed",
|
||||
"user-deleted": "User deleted",
|
||||
"user-id": "User ID",
|
||||
"user-id-with-value": "User ID: {id}",
|
||||
"user-password": "User Password",
|
||||
"user-successfully-logged-in": "User Successfully Logged In",
|
||||
"user-update-failed": "User update failed",
|
||||
"user-updated": "User updated",
|
||||
"users": "Users",
|
||||
"webhook-time": "Webhook Time",
|
||||
"webhooks-enabled": "Webhooks Enabled"
|
||||
"webhooks-enabled": "Webhooks Enabled",
|
||||
"you-are-not-allowed-to-create-a-user": "You are not allowed to create a user",
|
||||
"you-are-not-allowed-to-delete-this-user": "You are not allowed to delete this user"
|
||||
}
|
||||
}
|
|
@ -23,11 +23,11 @@
|
|||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<TheDownloadBtn
|
||||
button-text="Download Recipe JSON"
|
||||
:button-text="$t('about.download-recipe-json')"
|
||||
download-url="/api/debug/last-recipe-json"
|
||||
/>
|
||||
<TheDownloadBtn
|
||||
button-text="Download Log"
|
||||
:button-text="$t('about.download-log')"
|
||||
download-url="/api/debug/log"
|
||||
/>
|
||||
</v-card-actions>
|
||||
|
|
|
@ -62,17 +62,21 @@ export default {
|
|||
},
|
||||
async importBackup(data) {
|
||||
this.$emit("loading");
|
||||
let response = await api.backups.import(data.name, data);
|
||||
const response = await api.backups.import(data.name, data);
|
||||
if(response) {
|
||||
let importData = response.data;
|
||||
this.$emit("finished", importData);
|
||||
} else {
|
||||
this.$emit("finished");
|
||||
}
|
||||
|
||||
let importData = response.data;
|
||||
|
||||
this.$emit("finished", importData);
|
||||
},
|
||||
deleteBackup(data) {
|
||||
async deleteBackup(data) {
|
||||
this.$emit("loading");
|
||||
|
||||
api.backups.delete(data.name);
|
||||
this.selectedBackup = null;
|
||||
if (await api.backups.delete(data.name)) {
|
||||
this.selectedBackup = null;
|
||||
}
|
||||
this.backupLoading = false;
|
||||
|
||||
this.$emit("finished");
|
||||
|
|
|
@ -28,7 +28,7 @@ export default {
|
|||
},
|
||||
pages: {
|
||||
value: true,
|
||||
text: "Pages",
|
||||
text: this.$t("settings.pages"),
|
||||
},
|
||||
themes: {
|
||||
value: true,
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
<v-card-text class="mt-n4">
|
||||
<v-row>
|
||||
<v-col sm="4">
|
||||
<p>{{ $t("general.options") }}:</p>
|
||||
<p>{{ $t("general.options") }}</p>
|
||||
<ImportOptions @update-options="updateOptions" class="mt-5" />
|
||||
</v-col>
|
||||
<v-col>
|
||||
<p>{{ $t("general.templates") }}:</p>
|
||||
<p>{{ $t("general.templates") }}</p>
|
||||
<v-checkbox
|
||||
v-for="template in availableTemplates"
|
||||
:key="template"
|
||||
|
@ -97,10 +97,11 @@ export default {
|
|||
templates: this.selectedTemplates,
|
||||
};
|
||||
|
||||
await api.backups.create(data);
|
||||
if (await api.backups.create(data)) {
|
||||
this.$emit("created");
|
||||
}
|
||||
this.loading = false;
|
||||
|
||||
this.$emit("created");
|
||||
},
|
||||
appendTemplate(templateName) {
|
||||
if (this.selectedTemplates.includes(templateName)) {
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
<div>
|
||||
<ConfirmationDialog
|
||||
ref="deleteGroupConfirm"
|
||||
:title="$t('user.confirm-group-deletion')"
|
||||
:title="$t('group.confirm-group-deletion')"
|
||||
:message="
|
||||
$t('user.are-you-sure-you-want-to-delete-the-group', {
|
||||
$t('group.are-you-sure-you-want-to-delete-the-group', {
|
||||
groupName: group.name,
|
||||
})
|
||||
"
|
||||
|
@ -18,7 +18,7 @@
|
|||
<v-card-title class="py-1">{{ group.name }}</v-card-title>
|
||||
<v-divider></v-divider>
|
||||
<v-subheader>{{
|
||||
$t("user.group-id-with-value", { groupID: group.id })
|
||||
$t("group.group-id-with-value", { groupID: group.id })
|
||||
}}</v-subheader>
|
||||
<v-list-item-group color="primary">
|
||||
<v-list-item v-for="property in groupProps" :key="property.text">
|
||||
|
@ -91,8 +91,9 @@ export default {
|
|||
this.$refs.deleteGroupConfirm.open();
|
||||
},
|
||||
async deleteGroup() {
|
||||
await api.groups.delete(this.group.id);
|
||||
this.$emit(RENDER_EVENT);
|
||||
if (await api.groups.delete(this.group.id)) {
|
||||
this.$emit(RENDER_EVENT);
|
||||
}
|
||||
},
|
||||
closeGroupDelete() {
|
||||
console.log("Close Delete");
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
v-bind="attrs"
|
||||
v-on="on"
|
||||
>
|
||||
{{ $t("user.create-group") }}
|
||||
{{ $t("group.create-group") }}
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-card>
|
||||
|
@ -34,7 +34,7 @@
|
|||
</v-icon>
|
||||
|
||||
<v-toolbar-title class="headline">
|
||||
{{ $t("user.create-group") }}
|
||||
{{ $t("group.create-group") }}
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer></v-spacer>
|
||||
|
@ -43,7 +43,7 @@
|
|||
<v-card-text>
|
||||
<v-text-field
|
||||
v-model="newGroupName"
|
||||
:label="$t('user.group-name')"
|
||||
:label="$t('group.group-name')"
|
||||
:rules="[existsRule]"
|
||||
></v-text-field>
|
||||
</v-card-text>
|
||||
|
@ -104,12 +104,11 @@ export default {
|
|||
methods: {
|
||||
async createGroup() {
|
||||
this.groupLoading = true;
|
||||
let response = await api.groups.create(this.newGroupName);
|
||||
if (response.created) {
|
||||
this.groupLoading = false;
|
||||
if (await api.groups.create(this.newGroupName)) {
|
||||
this.groupDialog = false;
|
||||
this.$store.dispatch("requestAllGroups");
|
||||
}
|
||||
this.groupLoading = false;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<v-card outlined class="mt-n1">
|
||||
<ConfirmationDialog
|
||||
ref="deleteUserDialog"
|
||||
ref="deleteTokenDialog"
|
||||
:title="$t('user.confirm-link-deletion')"
|
||||
:message="
|
||||
$t('user.are-you-sure-you-want-to-delete-the-link', {
|
||||
|
@ -9,7 +9,7 @@
|
|||
})
|
||||
"
|
||||
icon="mdi-alert"
|
||||
@confirm="deleteUser"
|
||||
@confirm="deleteToken"
|
||||
:width="450"
|
||||
@close="closeDelete"
|
||||
/>
|
||||
|
@ -18,7 +18,7 @@
|
|||
mdi-link-variant
|
||||
</v-icon>
|
||||
<v-toolbar-title class="headine">
|
||||
{{ $t("user.sign-up-links") }}
|
||||
{{ $t("signup.sign-up-links") }}
|
||||
</v-toolbar-title>
|
||||
|
||||
<v-spacer> </v-spacer>
|
||||
|
@ -181,9 +181,10 @@ export default {
|
|||
this.links = await api.signUps.getAll();
|
||||
},
|
||||
|
||||
async deleteUser() {
|
||||
await api.signUps.deleteToken(this.activeId);
|
||||
this.initialize();
|
||||
async deleteToken() {
|
||||
if (await api.signUps.deleteToken(this.activeId)) {
|
||||
this.initialize();
|
||||
}
|
||||
},
|
||||
|
||||
editItem(item) {
|
||||
|
@ -197,7 +198,7 @@ export default {
|
|||
this.activeName = item.name;
|
||||
this.editedIndex = this.links.indexOf(item);
|
||||
this.editedItem = Object.assign({}, item);
|
||||
this.$refs.deleteUserDialog.open();
|
||||
this.$refs.deleteTokenDialog.open();
|
||||
},
|
||||
|
||||
deleteItemConfirm() {
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
dense
|
||||
v-model="editedItem.group"
|
||||
:items="existingGroups"
|
||||
:label="$t('user.user-group')"
|
||||
:label="$t('group.user-group')"
|
||||
></v-select>
|
||||
</v-col>
|
||||
<v-col cols="12" sm="12" md="6" v-if="showPassword">
|
||||
|
@ -94,7 +94,7 @@
|
|||
|
||||
<v-card-actions>
|
||||
<v-btn color="info" text @click="resetPassword">
|
||||
Reset Password
|
||||
{{$t('user.reset-password')}}
|
||||
</v-btn>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn color="grey" text @click="close">
|
||||
|
@ -165,7 +165,7 @@ export default {
|
|||
},
|
||||
{ text: this.$t("user.full-name"), value: "fullName" },
|
||||
{ text: this.$t("user.email"), value: "email" },
|
||||
{ text: this.$t("user.group"), value: "group" },
|
||||
{ text: this.$t("group.group"), value: "group" },
|
||||
{ text: this.$t("user.admin"), value: "admin" },
|
||||
{ text: "", value: "actions", sortable: false, align: "center" },
|
||||
],
|
||||
|
@ -223,8 +223,9 @@ export default {
|
|||
},
|
||||
|
||||
async deleteUser() {
|
||||
await api.users.delete(this.activeId);
|
||||
this.initialize();
|
||||
if (await api.users.delete(this.activeId)) {
|
||||
this.initialize();
|
||||
}
|
||||
},
|
||||
|
||||
editItem(item) {
|
||||
|
@ -264,17 +265,27 @@ export default {
|
|||
|
||||
async save() {
|
||||
if (this.editedIndex > -1) {
|
||||
await api.users.update(this.editedItem);
|
||||
this.close();
|
||||
this.updateUser();
|
||||
} else if (this.$refs.newUser.validate()) {
|
||||
await api.users.create(this.editedItem);
|
||||
this.close();
|
||||
this.createUser();
|
||||
}
|
||||
await this.initialize();
|
||||
},
|
||||
resetPassword() {
|
||||
api.users.resetPassword(this.editedItem.id);
|
||||
},
|
||||
|
||||
async createUser() {
|
||||
if(await api.users.create(this.editedItem)) {
|
||||
this.close();
|
||||
}
|
||||
},
|
||||
|
||||
async updateUser() {
|
||||
if(await api.users.update(this.editedItem)) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -16,12 +16,12 @@
|
|||
</v-tab>
|
||||
|
||||
<v-tab>
|
||||
{{ $t("user.sign-up-links") }}
|
||||
{{ $t("signup.sign-up-links") }}
|
||||
<v-icon>mdi-account-plus-outline</v-icon>
|
||||
</v-tab>
|
||||
|
||||
<v-tab>
|
||||
{{ $t("user.groups") }}
|
||||
{{ $t("group.groups") }}
|
||||
<v-icon>mdi-account-group</v-icon>
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
|
|
|
@ -135,9 +135,10 @@ export default {
|
|||
this.groupSettings.webhookUrls.splice(index, 1);
|
||||
},
|
||||
async saveGroupSettings() {
|
||||
await api.groups.update(this.groupSettings);
|
||||
await this.$store.dispatch("requestCurrentGroup");
|
||||
this.getSiteSettings();
|
||||
if (await api.groups.update(this.groupSettings)) {
|
||||
await this.$store.dispatch("requestCurrentGroup");
|
||||
this.getSiteSettings();
|
||||
}
|
||||
},
|
||||
testWebhooks() {
|
||||
api.settings.testWebhooks();
|
||||
|
|
|
@ -86,9 +86,10 @@ export default {
|
|||
};
|
||||
},
|
||||
methods: {
|
||||
deleteMigration(file_name) {
|
||||
api.migrations.delete(this.folder, file_name);
|
||||
this.$emit("refresh");
|
||||
async deleteMigration(file_name) {
|
||||
if (await api.migrations.delete(this.folder, file_name)) {
|
||||
this.$emit("refresh");
|
||||
}
|
||||
},
|
||||
async importMigration(file_name) {
|
||||
this.loading = true;
|
||||
|
|
|
@ -55,11 +55,11 @@
|
|||
>
|
||||
</v-text-field>
|
||||
<v-text-field
|
||||
:label="$t('user.group')"
|
||||
:label="$t('group.group')"
|
||||
readonly
|
||||
v-model="user.group"
|
||||
persistent-hint
|
||||
:hint="$t('user.groups-can-only-be-set-by-administrators')"
|
||||
:hint="$t('group.groups-can-only-be-set-by-administrators')"
|
||||
>
|
||||
</v-text-field>
|
||||
</v-form>
|
||||
|
@ -201,11 +201,13 @@ export default {
|
|||
},
|
||||
async updateUser() {
|
||||
this.loading = true;
|
||||
let newKey = await api.users.update(this.user);
|
||||
this.$store.commit("setToken", newKey.access_token);
|
||||
this.refreshProfile();
|
||||
this.loading = false;
|
||||
this.$store.dispatch("requestUserData");
|
||||
const response = await api.users.update(this.user);
|
||||
if(response) {
|
||||
this.$store.commit("setToken", response.data.access_token);
|
||||
this.refreshProfile();
|
||||
this.loading = false;
|
||||
this.$store.dispatch("requestUserData");
|
||||
}
|
||||
},
|
||||
async changePassword() {
|
||||
this.paswordLoading = true;
|
||||
|
@ -215,7 +217,9 @@ export default {
|
|||
};
|
||||
|
||||
if (this.$refs.passChange.validate()) {
|
||||
await api.users.changePassword(this.user.id, data);
|
||||
if (await api.users.changePassword(this.user.id, data)) {
|
||||
this.$emit("refresh");
|
||||
}
|
||||
}
|
||||
this.paswordLoading = false;
|
||||
},
|
||||
|
|
|
@ -82,14 +82,18 @@ export default {
|
|||
this.$refs.categoryFormSelector.setInit(this.page.categories);
|
||||
},
|
||||
async submitForm() {
|
||||
let response;
|
||||
if (this.create) {
|
||||
await api.siteSettings.createPage(this.page);
|
||||
response = await api.siteSettings.createPage(this.page);
|
||||
} else {
|
||||
await api.siteSettings.updatePage(this.page);
|
||||
response = await api.siteSettings.updatePage(this.page);
|
||||
}
|
||||
|
||||
if (response) {
|
||||
this.pageDialog = false;
|
||||
this.page.categories = [];
|
||||
this.$emit(NEW_PAGE_EVENT);
|
||||
}
|
||||
this.pageDialog = false;
|
||||
this.page.categories = [];
|
||||
this.$emit(NEW_PAGE_EVENT);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -109,9 +109,10 @@ export default {
|
|||
element.position = index;
|
||||
});
|
||||
|
||||
await api.siteSettings.updateAllPages(this.customPages);
|
||||
if (await api.siteSettings.updateAllPages(this.customPages)) {
|
||||
this.getPages();
|
||||
}
|
||||
|
||||
this.getPages();
|
||||
},
|
||||
editPage(index) {
|
||||
this.editPageData.data = this.customPages[index];
|
||||
|
|
|
@ -214,7 +214,7 @@ export default {
|
|||
this.settings.language = val;
|
||||
},
|
||||
deleteCategoryfromDatabase(category) {
|
||||
api.categories.delete(category);
|
||||
api.categories.delete(category);
|
||||
},
|
||||
async getOptions() {
|
||||
this.settings = await api.siteSettings.get();
|
||||
|
@ -223,8 +223,9 @@ export default {
|
|||
this.settings.categories.splice(index, 1);
|
||||
},
|
||||
async saveSettings() {
|
||||
await api.siteSettings.update(this.settings);
|
||||
this.getOptions();
|
||||
if (await api.siteSettings.update(this.settings)) {
|
||||
this.getOptions();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -70,11 +70,11 @@ export default {
|
|||
},
|
||||
async deleteSelectedTheme() {
|
||||
//Delete Theme from DB
|
||||
await api.themes.delete(this.theme.name);
|
||||
|
||||
//Get the new list of available from DB
|
||||
this.availableThemes = await api.themes.requestAll();
|
||||
this.$emit(DELETE_EVENT);
|
||||
if (await api.themes.delete(this.theme.name)) {
|
||||
//Get the new list of available from DB
|
||||
this.availableThemes = await api.themes.requestAll();
|
||||
this.$emit(DELETE_EVENT);
|
||||
}
|
||||
},
|
||||
async saveThemes() {
|
||||
this.$store.commit("setTheme", this.theme);
|
||||
|
|
|
@ -171,9 +171,11 @@ export default {
|
|||
* Create the new Theme and select it.
|
||||
*/
|
||||
async appendTheme(NewThemeDialog) {
|
||||
await api.themes.create(NewThemeDialog);
|
||||
this.availableThemes.push(NewThemeDialog);
|
||||
this.$store.commit("setTheme", NewThemeDialog);
|
||||
const response = await api.themes.create(NewThemeDialog);
|
||||
if (response) {
|
||||
this.availableThemes.push(NewThemeDialog);
|
||||
this.$store.commit("setTheme", NewThemeDialog);
|
||||
}
|
||||
},
|
||||
setStoresDarkMode() {
|
||||
this.$store.commit("setDarkMode", this.selectedDarkMode);
|
||||
|
@ -181,8 +183,8 @@ export default {
|
|||
/**
|
||||
* This will save the current colors and make the selected theme live.
|
||||
*/
|
||||
async saveThemes() {
|
||||
await api.themes.update(
|
||||
saveThemes() {
|
||||
api.themes.update(
|
||||
this.selectedTheme.name,
|
||||
this.selectedTheme.colors
|
||||
);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
ref="assignDialog"
|
||||
title-icon="mdi-tag"
|
||||
color="primary"
|
||||
title="Bulk Assign"
|
||||
:title="$t('settings.toolbox.bulk-assign')"
|
||||
:loading="loading"
|
||||
modal-width="700"
|
||||
:top="true"
|
||||
|
@ -13,7 +13,7 @@
|
|||
<v-text-field
|
||||
v-model="search"
|
||||
autocomplete="off"
|
||||
label="Keyword"
|
||||
:label="$t('general.keyword')"
|
||||
></v-text-field>
|
||||
<CategoryTagSelector
|
||||
:tag-selector="false"
|
||||
|
@ -44,7 +44,7 @@
|
|||
<v-card-title class="headline"> </v-card-title>
|
||||
<CardSection
|
||||
class="px-2 pb-2"
|
||||
:title="`${results.length || 0} Recipes Effected`"
|
||||
:title="$tc('settings.toolbox.recipes-affected', results.length || 0)"
|
||||
:mobile-cards="true"
|
||||
:recipes="results"
|
||||
:single-column="true"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
:title="
|
||||
$t('general.delete') +
|
||||
' ' +
|
||||
(isTags ? $t('recipe.tags') : $t('recipe.categories'))
|
||||
(isTags ? $t('tag.tags') : $t('recipe.categories'))
|
||||
"
|
||||
:loading="loading"
|
||||
modal-width="400"
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
</v-form>
|
||||
<template slot="below-actions">
|
||||
<v-card-title class="headline">
|
||||
{{ renameTarget.recipes.length || 0 }}
|
||||
{{ $t("settings.toolbox.recipes-effected") }}
|
||||
{{ $tc("settings.toolbox.recipes-affected", renameTarget.recipes.length || 0) }}
|
||||
</v-card-title>
|
||||
<MobileRecipeCard
|
||||
class="ml-2 mr-2 mt-2 mb-2"
|
||||
|
@ -94,10 +93,10 @@
|
|||
<v-card-title class="py-1">{{ item.name }}</v-card-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn small text color="info" @click="openEditDialog(item)">
|
||||
Edit
|
||||
{{$t('general.edit')}}
|
||||
</v-btn>
|
||||
<v-btn small text color="error" @click="deleteItem(item.slug)"
|
||||
>Delete
|
||||
<v-btn small text color="error" @click="deleteItem(item.slug)">
|
||||
{{$t('general.delete')}}
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
@ -177,7 +176,7 @@ export default {
|
|||
}
|
||||
|
||||
this.renameTarget = {
|
||||
title: `Rename ${item.name}`,
|
||||
title:this.$t('general.rename-object', [item.name]),
|
||||
name: item.name,
|
||||
slug: item.slug,
|
||||
newName: "",
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</v-tab>
|
||||
|
||||
<v-tab>
|
||||
{{ $t("recipe.tags") }}
|
||||
{{ $t("tag.tags") }}
|
||||
<v-icon>mdi-tag-multiple-outline</v-icon>
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
|
|
|
@ -128,8 +128,9 @@ export default {
|
|||
this.requestMeals();
|
||||
},
|
||||
async deletePlan(id) {
|
||||
await api.mealPlans.delete(id);
|
||||
this.requestMeals();
|
||||
if (await api.mealPlans.delete(id)) {
|
||||
this.requestMeals();
|
||||
}
|
||||
},
|
||||
openShoppingList(id) {
|
||||
this.$refs.shoppingList.openDialog(id);
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
<script>
|
||||
import { api } from "@/api";
|
||||
import utils from "@/utils";
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
@ -60,6 +61,9 @@ export default {
|
|||
},
|
||||
async mounted() {
|
||||
this.mealPlan = await api.mealPlans.thisWeek();
|
||||
if(!this.mealPlan) {
|
||||
utils.notify.warning(this.$t('meal-plan.no-meal-plan-defined-yet'))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getOrder(index) {
|
||||
|
|
|
@ -101,7 +101,7 @@ export default {
|
|||
let slug = await api.recipes.create(this.recipeDetails);
|
||||
|
||||
if (this.fileObject) {
|
||||
await api.recipes.updateImage(slug, this.fileObject);
|
||||
api.recipes.updateImage(slug, this.fileObject, true);
|
||||
}
|
||||
|
||||
this.isLoading = false;
|
||||
|
|
|
@ -80,6 +80,8 @@ import RecipeEditor from "@/components/Recipe/RecipeEditor";
|
|||
import RecipeTimeCard from "@/components/Recipe/RecipeTimeCard.vue";
|
||||
import EditorButtonRow from "@/components/Recipe/EditorButtonRow";
|
||||
import { user } from "@/mixins/user";
|
||||
import store from "@/store";
|
||||
import { router } from "@/routes";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -166,8 +168,12 @@ export default {
|
|||
return api.recipes.recipeImage(image) + "&rnd=" + this.imageKey;
|
||||
}
|
||||
},
|
||||
deleteRecipe() {
|
||||
api.recipes.delete(this.recipeDetails.slug);
|
||||
async deleteRecipe() {
|
||||
let response = await api.recipes.delete(this.recipeDetails.slug);
|
||||
if (response) {
|
||||
store.dispatch("requestRecentRecipes");
|
||||
router.push(`/`);
|
||||
}
|
||||
},
|
||||
validateRecipe() {
|
||||
if (this.jsonEditor) {
|
||||
|
@ -176,18 +182,19 @@ export default {
|
|||
return this.$refs.recipeEditor.validateRecipe();
|
||||
}
|
||||
},
|
||||
async saveImage() {
|
||||
async saveImage(overrideSuccessMsg = false) {
|
||||
if (this.fileObject) {
|
||||
await api.recipes.updateImage(this.recipeDetails.slug, this.fileObject);
|
||||
if (api.recipes.updateImage(this.recipeDetails.slug, this.fileObject, overrideSuccessMsg)) {
|
||||
this.imageKey += 1;
|
||||
}
|
||||
}
|
||||
this.imageKey += 1;
|
||||
},
|
||||
async saveRecipe() {
|
||||
if (this.validateRecipe()) {
|
||||
let slug = await api.recipes.update(this.recipeDetails);
|
||||
|
||||
if (this.fileObject) {
|
||||
this.saveImage();
|
||||
this.saveImage(true);
|
||||
}
|
||||
|
||||
this.form = false;
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<v-row dense class="mt-0 flex-row align-center justify-space-around">
|
||||
<v-col>
|
||||
<h3 class="pl-2 text-center headline">
|
||||
{{ $t("search.category-filter") }}
|
||||
{{ $t("category.category-filter") }}
|
||||
</h3>
|
||||
<FilterSelector class="mb-1" @update="updateCatParams" />
|
||||
<CategoryTagSelector
|
||||
|
|
|
@ -2,6 +2,9 @@ import Planner from "@/pages/MealPlan/Planner";
|
|||
import ThisWeek from "@/pages/MealPlan/ThisWeek";
|
||||
import { api } from "@/api";
|
||||
|
||||
import i18n from '@/i18n.js';
|
||||
import utils from "@/utils";
|
||||
|
||||
export const mealRoutes = [
|
||||
{
|
||||
path: "/meal-plan/planner",
|
||||
|
@ -21,7 +24,12 @@ export const mealRoutes = [
|
|||
path: "/meal-plan/today",
|
||||
beforeEnter: async (_to, _from, next) => {
|
||||
await todaysMealRoute().then(redirect => {
|
||||
next(redirect);
|
||||
if(redirect) {
|
||||
next(redirect);
|
||||
} else {
|
||||
utils.notify.error(i18n.t('meal-plan.no-meal-planned-for-today'));
|
||||
next(_from);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
|
@ -29,5 +37,9 @@ export const mealRoutes = [
|
|||
|
||||
async function todaysMealRoute() {
|
||||
const response = await api.mealPlans.today();
|
||||
return "/recipe/" + response.data;
|
||||
if (response.status == 200 && response.data) {
|
||||
return "/recipe/" + response.data;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue