1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-07-24 07:39:41 +02:00

feat: User-specific Recipe Ratings (#3345)
Some checks failed
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docker Nightly Production / Backend Server Tests (push) Has been cancelled
Docker Nightly Production / Frontend and End-to-End Tests (push) Has been cancelled
Docker Nightly Production / Build Tagged Release (push) Has been cancelled
Docker Nightly Production / Notify Discord (push) Has been cancelled

This commit is contained in:
Michael Genson 2024-04-11 21:28:43 -05:00 committed by GitHub
parent 8ab09cf03b
commit 2a541f081a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
50 changed files with 1497 additions and 443 deletions

View file

@ -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;

View file

@ -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) {