1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-02 20:15:24 +02:00

feat(frontend): 👷 Add image operations to recipe page

Added/Fixed image upload/get process on the recipe pages as well as some additional styling
This commit is contained in:
hay-kot 2021-08-03 21:38:45 -08:00
parent afcad2f701
commit 5ee0a57163
15 changed files with 238 additions and 114 deletions

View file

@ -10,6 +10,36 @@ export interface CrudAPIInterface {
// Methods
}
export const crudMixins = <T>(
requests: ApiRequestInstance,
baseRoute: string,
itemRoute: (itemId: string) => string
) => {
async function getAll(start = 0, limit = 9999) {
return await requests.get<T[]>(baseRoute, {
params: { start, limit },
});
}
async function getOne(itemId: string) {
return await requests.get<T>(itemRoute(itemId));
}
async function updateOne(itemId: string, payload: T) {
return await requests.put<T>(itemRoute(itemId), payload);
}
async function patchOne(itemId: string, payload: T) {
return await requests.patch(itemRoute(itemId), payload);
}
async function deleteOne(itemId: string) {
return await requests.delete<T>(itemRoute(itemId));
}
return { getAll, getOne, updateOne, patchOne, deleteOne };
};
export abstract class BaseAPIClass<T> implements CrudAPIInterface {
requests: ApiRequestInstance;
@ -30,11 +60,7 @@ export abstract class BaseAPIClass<T> implements CrudAPIInterface {
return await this.requests.get<T>(this.itemRoute(itemId));
}
async createOne(payload: T) {
return await this.requests.post(this.baseRoute, payload);
}
async updateOne(itemId: string, payload: T){
async updateOne(itemId: string, payload: T) {
return await this.requests.put<T>(this.itemRoute(itemId), payload);
}
@ -45,5 +71,4 @@ export abstract class BaseAPIClass<T> implements CrudAPIInterface {
async deleteOne(itemId: string) {
return await this.requests.delete<T>(this.itemRoute(itemId));
}
}

View file

@ -1,5 +1,6 @@
import { BaseAPIClass } from "./_base";
import { BaseAPIClass, crudMixins } from "./_base";
import { Recipe } from "~/types/api-types/admin";
import { ApiRequestInstance } from "~/types/api";
const prefix = "/api";
@ -10,7 +11,6 @@ const routes = {
recipesTestScrapeUrl: `${prefix}/recipes/test-scrape-url`,
recipesCreateUrl: `${prefix}/recipes/create-url`,
recipesCreateFromZip: `${prefix}/recipes/create-from-zip`,
recipesCategory: `${prefix}/recipes/category`,
recipesRecipeSlug: (recipe_slug: string) => `${prefix}/recipes/${recipe_slug}`,
@ -19,20 +19,45 @@ const routes = {
recipesRecipeSlugAssets: (recipe_slug: string) => `${prefix}/recipes/${recipe_slug}/assets`,
};
class RecipeAPI extends BaseAPIClass<Recipe> {
export class RecipeAPI extends BaseAPIClass<Recipe> {
baseRoute: string = routes.recipesSummary;
itemRoute = (itemid: string) => routes.recipesRecipeSlug(itemid);
itemRoute = routes.recipesRecipeSlug;
constructor(requests: ApiRequestInstance) {
super(requests);
const { getAll, getOne, updateOne, patchOne, deleteOne } = crudMixins<Recipe>(
requests,
routes.recipesSummary,
routes.recipesRecipeSlug
);
this.getAll = getAll;
this.getOne = getOne;
this.updateOne = updateOne;
this.patchOne = patchOne;
this.deleteOne = deleteOne;
}
async getAllByCategory(categories: string[]) {
return await this.requests.get<Recipe[]>(routes.recipesCategory, {
categories
categories,
});
}
// @ts-ignore - Override method doesn't take same arguments are parent class
updateImage(slug: string, fileObject: File) {
const formData = new FormData();
formData.append("image", fileObject);
formData.append("extension", fileObject.name.split(".").pop());
return this.requests.put<any>(routes.recipesRecipeSlugImage(slug), formData);
}
updateImagebyURL(slug: string, url: string) {
return this.requests.post(routes.recipesRecipeSlugImage(slug), { url });
}
async createOne(name: string) {
return await this.requests.post(routes.recipesBase, { name });
return await this.requests.post<Recipe>(routes.recipesBase, { name });
}
async createOneByUrl(url: string) {
@ -56,5 +81,3 @@ class RecipeAPI extends BaseAPIClass<Recipe> {
return `/api/media/recipes/${recipeSlug}/assets/${assetName}`;
}
}
export { RecipeAPI };

View file

@ -0,0 +1,31 @@
import { BaseAPIClass } from "./_base";
import { UserOut } from "~/types/api-types/user";
const prefix = "/api";
const routes = {
usersSelf: `${prefix}/users/self`,
users: `${prefix}/users`,
usersIdImage: (id: string) => `${prefix}/users/${id}/image`,
usersIdResetPassword: (id: string) => `${prefix}/users/${id}/reset-password`,
usersId: (id: string) => `${prefix}/users/${id}`,
usersIdPassword: (id: string) => `${prefix}/users/${id}/password`,
usersIdFavorites: (id: string) => `${prefix}/users/${id}/favorites`,
usersIdFavoritesSlug: (id: string, slug: string) => `${prefix}/users/${id}/favorites/${slug}`,
};
export class UserApi extends BaseAPIClass<UserOut> {
baseRoute: string = routes.users;
itemRoute = (itemid: string) => routes.usersId(itemid);
async addFavorite(id: string, slug: string) {
const response = await this.requests.post(routes.usersIdFavoritesSlug(id, slug), {});
return response.data;
}
async removeFavorite(id: string, slug: string) {
const response = await this.requests.delete(routes.usersIdFavoritesSlug(id, slug));
return response.data;
}
}

View file

@ -1,9 +1,11 @@
import { RecipeAPI } from "./class-interfaces/recipes";
import { UserApi } from "./class-interfaces/users";
import { ApiRequestInstance } from "~/types/api";
class Api {
private static instance: Api;
public recipes: RecipeAPI;
public users: UserApi;
constructor(requests: ApiRequestInstance) {
if (Api.instance instanceof Api) {
@ -11,6 +13,7 @@ class Api {
}
this.recipes = new RecipeAPI(requests);
this.users = new UserApi(requests);
Object.freeze(this);
Api.instance = this;