mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 02:03:35 -04:00 
			
		
		
		
	feat: User-specific Recipe Ratings (#3345)
This commit is contained in:
		| @@ -5,10 +5,11 @@ | ||||
| /* Do not modify it by hand - just update the pydantic models and then re-run the script | ||||
| */ | ||||
|  | ||||
| export type WebhookType = "mealplan"; | ||||
| export type AuthMethod = "Mealie" | "LDAP" | "OIDC"; | ||||
|  | ||||
| export interface ChangePassword { | ||||
|   currentPassword: string; | ||||
|   currentPassword?: string; | ||||
|   newPassword: string; | ||||
| } | ||||
| export interface CreateToken { | ||||
| @@ -30,6 +31,11 @@ export interface CreateUserRegistration { | ||||
|   seedData?: boolean; | ||||
|   locale?: string; | ||||
| } | ||||
| export interface CredentialsRequest { | ||||
|   username: string; | ||||
|   password: string; | ||||
|   remember_me?: boolean; | ||||
| } | ||||
| export interface DeleteTokenResponse { | ||||
|   tokenDelete: string; | ||||
| } | ||||
| @@ -44,7 +50,7 @@ export interface GroupInDB { | ||||
|   id: string; | ||||
|   slug: string; | ||||
|   categories?: CategoryBase[]; | ||||
|   webhooks?: unknown[]; | ||||
|   webhooks?: ReadWebhook[]; | ||||
|   users?: UserOut[]; | ||||
|   preferences?: ReadGroupPreferences; | ||||
| } | ||||
| @@ -60,7 +66,17 @@ export interface CategoryBase { | ||||
|   id: string; | ||||
|   slug: string; | ||||
| } | ||||
| export interface ReadWebhook { | ||||
|   enabled?: boolean; | ||||
|   name?: string; | ||||
|   url?: string; | ||||
|   webhookType?: WebhookType & string; | ||||
|   scheduledTime: string; | ||||
|   groupId: string; | ||||
|   id: string; | ||||
| } | ||||
| export interface UserOut { | ||||
|   id: string; | ||||
|   username?: string; | ||||
|   fullName?: string; | ||||
|   email: string; | ||||
| @@ -68,11 +84,9 @@ export interface UserOut { | ||||
|   admin?: boolean; | ||||
|   group: string; | ||||
|   advanced?: boolean; | ||||
|   favoriteRecipes?: string[]; | ||||
|   canInvite?: boolean; | ||||
|   canManage?: boolean; | ||||
|   canOrganize?: boolean; | ||||
|   id: string; | ||||
|   groupId: string; | ||||
|   groupSlug: string; | ||||
|   tokens?: LongLiveTokenOut[]; | ||||
| @@ -109,6 +123,7 @@ export interface LongLiveTokenInDB { | ||||
|   user: PrivateUser; | ||||
| } | ||||
| export interface PrivateUser { | ||||
|   id: string; | ||||
|   username?: string; | ||||
|   fullName?: string; | ||||
|   email: string; | ||||
| @@ -116,11 +131,9 @@ export interface PrivateUser { | ||||
|   admin?: boolean; | ||||
|   group: string; | ||||
|   advanced?: boolean; | ||||
|   favoriteRecipes?: string[]; | ||||
|   canInvite?: boolean; | ||||
|   canManage?: boolean; | ||||
|   canOrganize?: boolean; | ||||
|   id: string; | ||||
|   groupId: string; | ||||
|   groupSlug: string; | ||||
|   tokens?: LongLiveTokenOut[]; | ||||
| @@ -129,6 +142,9 @@ export interface PrivateUser { | ||||
|   loginAttemps?: number; | ||||
|   lockedAt?: string; | ||||
| } | ||||
| export interface OIDCRequest { | ||||
|   id_token: string; | ||||
| } | ||||
| export interface PasswordResetToken { | ||||
|   token: string; | ||||
| } | ||||
| @@ -163,9 +179,17 @@ export interface UpdateGroup { | ||||
|   id: string; | ||||
|   slug: string; | ||||
|   categories?: CategoryBase[]; | ||||
|   webhooks?: unknown[]; | ||||
|   webhooks?: CreateWebhook[]; | ||||
| } | ||||
| export interface CreateWebhook { | ||||
|   enabled?: boolean; | ||||
|   name?: string; | ||||
|   url?: string; | ||||
|   webhookType?: WebhookType & string; | ||||
|   scheduledTime: string; | ||||
| } | ||||
| export interface UserBase { | ||||
|   id?: string; | ||||
|   username?: string; | ||||
|   fullName?: string; | ||||
|   email: string; | ||||
| @@ -173,65 +197,12 @@ export interface UserBase { | ||||
|   admin?: boolean; | ||||
|   group?: string; | ||||
|   advanced?: boolean; | ||||
|   favoriteRecipes?: string[]; | ||||
|   canInvite?: boolean; | ||||
|   canManage?: boolean; | ||||
|   canOrganize?: boolean; | ||||
| } | ||||
| export interface UserFavorites { | ||||
|   username?: string; | ||||
|   fullName?: string; | ||||
|   email: string; | ||||
|   authMethod?: AuthMethod & string; | ||||
|   admin?: boolean; | ||||
|   group?: string; | ||||
|   advanced?: boolean; | ||||
|   favoriteRecipes?: RecipeSummary[]; | ||||
|   canInvite?: boolean; | ||||
|   canManage?: boolean; | ||||
|   canOrganize?: boolean; | ||||
| } | ||||
| export interface RecipeSummary { | ||||
|   id?: string; | ||||
|   userId?: string; | ||||
|   groupId?: string; | ||||
|   name?: string; | ||||
|   slug?: string; | ||||
|   image?: unknown; | ||||
|   recipeYield?: string; | ||||
|   totalTime?: string; | ||||
|   prepTime?: string; | ||||
|   cookTime?: string; | ||||
|   performTime?: string; | ||||
|   description?: string; | ||||
|   recipeCategory?: RecipeCategory[]; | ||||
|   tags?: RecipeTag[]; | ||||
|   tools?: RecipeTool[]; | ||||
|   rating?: number; | ||||
|   orgURL?: string; | ||||
|   dateAdded?: string; | ||||
|   dateUpdated?: string; | ||||
|   createdAt?: string; | ||||
|   updateAt?: string; | ||||
|   lastMade?: string; | ||||
| } | ||||
| export interface RecipeCategory { | ||||
|   id?: string; | ||||
|   name: string; | ||||
|   slug: string; | ||||
| } | ||||
| export interface RecipeTag { | ||||
|   id?: string; | ||||
|   name: string; | ||||
|   slug: string; | ||||
| } | ||||
| export interface RecipeTool { | ||||
|   id: string; | ||||
|   name: string; | ||||
|   slug: string; | ||||
|   onHand?: boolean; | ||||
| } | ||||
| export interface UserIn { | ||||
|   id?: string; | ||||
|   username?: string; | ||||
|   fullName?: string; | ||||
|   email: string; | ||||
| @@ -239,15 +210,32 @@ export interface UserIn { | ||||
|   admin?: boolean; | ||||
|   group?: string; | ||||
|   advanced?: boolean; | ||||
|   favoriteRecipes?: string[]; | ||||
|   canInvite?: boolean; | ||||
|   canManage?: boolean; | ||||
|   canOrganize?: boolean; | ||||
|   password: string; | ||||
| } | ||||
| export interface UserRatingCreate { | ||||
|   recipeId: string; | ||||
|   rating?: number; | ||||
|   isFavorite?: boolean; | ||||
|   userId: string; | ||||
| } | ||||
| export interface UserRatingOut { | ||||
|   recipeId: string; | ||||
|   rating?: number; | ||||
|   isFavorite?: boolean; | ||||
|   userId: string; | ||||
|   id: string; | ||||
| } | ||||
| export interface UserRatingSummary { | ||||
|   recipeId: string; | ||||
|   rating?: number; | ||||
|   isFavorite?: boolean; | ||||
| } | ||||
| export interface UserSummary { | ||||
|   id: string; | ||||
|   fullName?: string; | ||||
|   fullName: string; | ||||
| } | ||||
| export interface ValidateResetToken { | ||||
|   token: string; | ||||
|   | ||||
| @@ -9,17 +9,27 @@ import { | ||||
|   LongLiveTokenOut, | ||||
|   ResetPassword, | ||||
|   UserBase, | ||||
|   UserFavorites, | ||||
|   UserIn, | ||||
|   UserOut, | ||||
|   UserRatingOut, | ||||
|   UserRatingSummary, | ||||
|   UserSummary, | ||||
| } from "~/lib/api/types/user"; | ||||
|  | ||||
| export interface UserRatingsSummaries { | ||||
|   ratings: UserRatingSummary[]; | ||||
| } | ||||
|  | ||||
| export interface UserRatingsOut { | ||||
|   ratings: UserRatingOut[]; | ||||
| } | ||||
|  | ||||
| const prefix = "/api"; | ||||
|  | ||||
| const routes = { | ||||
|   groupUsers: `${prefix}/users/group-users`, | ||||
|   usersSelf: `${prefix}/users/self`, | ||||
|   ratingsSelf: `${prefix}/users/self/ratings`, | ||||
|   groupsSelf: `${prefix}/users/self/group`, | ||||
|   passwordReset: `${prefix}/users/reset-password`, | ||||
|   passwordChange: `${prefix}/users/password`, | ||||
| @@ -30,6 +40,10 @@ const routes = { | ||||
|   usersId: (id: string) => `${prefix}/users/${id}`, | ||||
|   usersIdFavorites: (id: string) => `${prefix}/users/${id}/favorites`, | ||||
|   usersIdFavoritesSlug: (id: string, slug: string) => `${prefix}/users/${id}/favorites/${slug}`, | ||||
|   usersIdRatings: (id: string) => `${prefix}/users/${id}/ratings`, | ||||
|   usersIdRatingsSlug: (id: string, slug: string) => `${prefix}/users/${id}/ratings/${slug}`, | ||||
|   usersSelfFavoritesId: (id: string) => `${prefix}/users/self/favorites/${id}`, | ||||
|   usersSelfRatingsId: (id: string) => `${prefix}/users/self/ratings/${id}`, | ||||
|  | ||||
|   usersApiTokens: `${prefix}/users/api-tokens`, | ||||
|   usersApiTokensTokenId: (token_id: string | number) => `${prefix}/users/api-tokens/${token_id}`, | ||||
| @@ -56,7 +70,23 @@ export class UserApi extends BaseCRUDAPI<UserIn, UserOut, UserBase> { | ||||
|   } | ||||
|  | ||||
|   async getFavorites(id: string) { | ||||
|     return await this.requests.get<UserFavorites>(routes.usersIdFavorites(id)); | ||||
|     return await this.requests.get<UserRatingsOut>(routes.usersIdFavorites(id)); | ||||
|   } | ||||
|  | ||||
|   async getSelfFavorites() { | ||||
|     return await this.requests.get<UserRatingsSummaries>(routes.ratingsSelf); | ||||
|   } | ||||
|  | ||||
|   async getRatings(id: string) { | ||||
|     return await this.requests.get<UserRatingsOut>(routes.usersIdRatings(id)); | ||||
|   } | ||||
|  | ||||
|   async setRating(id: string, slug: string, rating: number | null, isFavorite: boolean | null) { | ||||
|     return await this.requests.post(routes.usersIdRatingsSlug(id, slug), { rating, isFavorite }); | ||||
|   } | ||||
|  | ||||
|   async getSelfRatings() { | ||||
|     return await this.requests.get<UserRatingsSummaries>(routes.ratingsSelf); | ||||
|   } | ||||
|  | ||||
|   async changePassword(changePassword: ChangePassword) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user