mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-07-09 03:04:54 -04:00
Consolidate frontend types (#1245)
This commit is contained in:
parent
6a88a59981
commit
479900e912
File diff suppressed because one or more lines are too long
@ -18,33 +18,33 @@ export abstract class BaseAPI {
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class BaseCRUDAPI<T, U> extends BaseAPI implements CrudAPIInterface {
|
||||
export abstract class BaseCRUDAPI<CreateType, ReadType, UpdateType=CreateType> extends BaseAPI implements CrudAPIInterface {
|
||||
abstract baseRoute: string;
|
||||
abstract itemRoute(itemId: string | number): string;
|
||||
|
||||
async getAll(start = 0, limit = 9999, params = {} as any) {
|
||||
return await this.requests.get<T[]>(this.baseRoute, {
|
||||
return await this.requests.get<ReadType[]>(this.baseRoute, {
|
||||
params: { start, limit, ...params },
|
||||
});
|
||||
}
|
||||
|
||||
async createOne(payload: U) {
|
||||
return await this.requests.post<T>(this.baseRoute, payload);
|
||||
async createOne(payload: CreateType) {
|
||||
return await this.requests.post<ReadType>(this.baseRoute, payload);
|
||||
}
|
||||
|
||||
async getOne(itemId: string | number) {
|
||||
return await this.requests.get<T>(this.itemRoute(itemId));
|
||||
return await this.requests.get<ReadType>(this.itemRoute(itemId));
|
||||
}
|
||||
|
||||
async updateOne(itemId: string | number, payload: T) {
|
||||
return await this.requests.put<T>(this.itemRoute(itemId), payload);
|
||||
async updateOne(itemId: string | number, payload: UpdateType) {
|
||||
return await this.requests.put<ReadType, UpdateType>(this.itemRoute(itemId), payload);
|
||||
}
|
||||
|
||||
async patchOne(itemId: string, payload: Partial<T>) {
|
||||
return await this.requests.patch<T>(this.itemRoute(itemId), payload);
|
||||
async patchOne(itemId: string, payload: Partial<UpdateType>) {
|
||||
return await this.requests.patch<ReadType, Partial<UpdateType>>(this.itemRoute(itemId), payload);
|
||||
}
|
||||
|
||||
async deleteOne(itemId: string | number) {
|
||||
return await this.requests.delete<T>(this.itemRoute(itemId));
|
||||
return await this.requests.delete<ReadType>(this.itemRoute(itemId));
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,19 @@
|
||||
import { BaseCRUDAPI } from "../_base";
|
||||
import { UserOut } from "~/types/api-types/user";
|
||||
import { GroupBase, GroupInDB } from "~/types/api-types/user";
|
||||
import { GroupAdminUpdate } from "~/types/api-types/group";
|
||||
const prefix = "/api";
|
||||
|
||||
export interface Token {
|
||||
name: string;
|
||||
id: number;
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
export interface Preferences {
|
||||
privateGroup: boolean;
|
||||
firstDayOfWeek: number;
|
||||
recipePublic: boolean;
|
||||
recipeShowNutrition: boolean;
|
||||
recipeShowAssets: boolean;
|
||||
recipeLandscapeView: boolean;
|
||||
recipeDisableComments: boolean;
|
||||
recipeDisableAmount: boolean;
|
||||
groupId: number;
|
||||
id: number;
|
||||
}
|
||||
|
||||
export interface GroupCreate {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface GroupRead extends GroupCreate {
|
||||
id: number;
|
||||
categories: any[];
|
||||
webhooks: any[];
|
||||
users: UserOut[];
|
||||
preferences: Preferences;
|
||||
}
|
||||
|
||||
export interface AdminGroupUpdate {
|
||||
name: string;
|
||||
id: number;
|
||||
preferences: Preferences;
|
||||
}
|
||||
|
||||
const routes = {
|
||||
adminUsers: `${prefix}/admin/groups`,
|
||||
adminUsersId: (id: number) => `${prefix}/admin/groups/${id}`,
|
||||
adminUsersId: (id: string) => `${prefix}/admin/groups/${id}`,
|
||||
};
|
||||
|
||||
export class AdminGroupsApi extends BaseCRUDAPI<GroupRead, GroupCreate> {
|
||||
export class AdminGroupsApi extends BaseCRUDAPI<GroupBase, GroupInDB, GroupAdminUpdate> {
|
||||
baseRoute: string = routes.adminUsers;
|
||||
itemRoute = routes.adminUsersId;
|
||||
|
||||
async updateOne(id: number, payload: AdminGroupUpdate) {
|
||||
async updateOne(id: string, payload: GroupAdminUpdate) {
|
||||
// TODO: This should probably be a patch request, which isn't offered by the API currently
|
||||
return await this.requests.put<GroupRead, AdminGroupUpdate>(this.itemRoute(id), payload);
|
||||
return await this.requests.put<GroupInDB, GroupAdminUpdate>(this.itemRoute(id), payload);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
import { ServerTask } from "~/api/types/server-task";
|
||||
import { ServerTask } from "~/types/api-types/server";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
|
@ -8,7 +8,7 @@ const routes = {
|
||||
adminUsersId: (tag: string) => `${prefix}/admin/users/${tag}`,
|
||||
};
|
||||
|
||||
export class AdminUsersApi extends BaseCRUDAPI<UserOut, UserIn> {
|
||||
export class AdminUsersApi extends BaseCRUDAPI<UserIn, UserOut, UserOut> {
|
||||
baseRoute: string = routes.adminUsers;
|
||||
itemRoute = routes.adminUsersId;
|
||||
}
|
||||
|
@ -1,35 +1,5 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
|
||||
export interface BackupOptions {
|
||||
recipes?: boolean;
|
||||
settings?: boolean;
|
||||
pages?: boolean;
|
||||
themes?: boolean;
|
||||
groups?: boolean;
|
||||
users?: boolean;
|
||||
notifications?: boolean;
|
||||
}
|
||||
|
||||
export interface ImportBackup {
|
||||
name: string;
|
||||
options: BackupOptions;
|
||||
}
|
||||
|
||||
export interface BackupJob {
|
||||
tag?: string;
|
||||
options: BackupOptions;
|
||||
templates?: string[];
|
||||
}
|
||||
|
||||
export interface BackupFile {
|
||||
name: string;
|
||||
date: string;
|
||||
}
|
||||
|
||||
export interface AllBackups {
|
||||
imports: BackupFile[];
|
||||
templates: string[];
|
||||
}
|
||||
import { AllBackups, BackupOptions, CreateBackup } from "~/types/api-types/admin";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -52,7 +22,7 @@ export class BackupAPI extends BaseAPI {
|
||||
|
||||
/** Generates a backup of the recipe database in json format.
|
||||
*/
|
||||
async createOne(payload: BackupJob) {
|
||||
async createOne(payload: CreateBackup) {
|
||||
return await this.requests.post(routes.backupsExportDatabase, payload);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,7 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
import { EmailInitationResponse, EmailInvitation } from "~/types/api-types/group";
|
||||
import { ForgotPassword } from "~/types/api-types/user";
|
||||
import { EmailTest } from "~/types/api-types/admin";
|
||||
|
||||
const routes = {
|
||||
base: "/api/admin/email",
|
||||
@ -7,30 +10,16 @@ const routes = {
|
||||
invitation: "/api/groups/invitations/email",
|
||||
};
|
||||
|
||||
export interface EmailResponse {
|
||||
success: boolean;
|
||||
error: string;
|
||||
}
|
||||
|
||||
export interface EmailPayload {
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface InvitationEmail {
|
||||
email: string;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export class EmailAPI extends BaseAPI {
|
||||
test(payload: EmailPayload) {
|
||||
return this.requests.post<EmailResponse>(routes.base, payload);
|
||||
test(payload: EmailTest) {
|
||||
return this.requests.post<EmailInitationResponse>(routes.base, payload);
|
||||
}
|
||||
|
||||
sendInvitation(payload: InvitationEmail) {
|
||||
return this.requests.post<EmailResponse>(routes.invitation, payload);
|
||||
sendInvitation(payload: EmailInvitation) {
|
||||
return this.requests.post<EmailInitationResponse>(routes.invitation, payload);
|
||||
}
|
||||
|
||||
sendForgotPassword(payload: EmailPayload) {
|
||||
return this.requests.post<EmailResponse>(routes.forgotPassword, payload);
|
||||
sendForgotPassword(payload: ForgotPassword) {
|
||||
return this.requests.post<EmailInitationResponse>(routes.forgotPassword, payload);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ const routes = {
|
||||
cookbooksId: (id: number) => `${prefix}/groups/cookbooks/${id}`,
|
||||
};
|
||||
|
||||
export class CookbookAPI extends BaseCRUDAPI<RecipeCookBook, CreateCookBook> {
|
||||
export class CookbookAPI extends BaseCRUDAPI<CreateCookBook, RecipeCookBook, UpdateCookBook> {
|
||||
baseRoute: string = routes.cookbooks;
|
||||
itemRoute = routes.cookbooksId;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BaseCRUDAPI } from "../_base";
|
||||
import { GroupEventNotifierCreate, GroupEventNotifierOut } from "~/types/api-types/group";
|
||||
import { GroupEventNotifierCreate, GroupEventNotifierOut, GroupEventNotifierUpdate } from "~/types/api-types/group";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -8,7 +8,7 @@ const routes = {
|
||||
eventNotifierId: (id: string | number) => `${prefix}/groups/events/notifications/${id}`,
|
||||
};
|
||||
|
||||
export class GroupEventNotifierApi extends BaseCRUDAPI<GroupEventNotifierOut, GroupEventNotifierCreate> {
|
||||
export class GroupEventNotifierApi extends BaseCRUDAPI<GroupEventNotifierCreate, GroupEventNotifierOut, GroupEventNotifierUpdate> {
|
||||
baseRoute = routes.eventNotifier;
|
||||
itemRoute = routes.eventNotifierId;
|
||||
|
||||
|
@ -8,7 +8,7 @@ const routes = {
|
||||
ruleId: (id: string | number) => `${prefix}/groups/mealplans/rules/${id}`,
|
||||
};
|
||||
|
||||
export class MealPlanRulesApi extends BaseCRUDAPI<PlanRulesOut, PlanRulesCreate> {
|
||||
export class MealPlanRulesApi extends BaseCRUDAPI<PlanRulesCreate, PlanRulesOut> {
|
||||
baseRoute = routes.rule;
|
||||
itemRoute = routes.ruleId;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BaseCRUDAPI } from "../_base";
|
||||
import { CreatRandomEntry } from "~/types/api-types/meal-plan";
|
||||
import { CreatePlanEntry, CreateRandomEntry, ReadPlanEntry, UpdatePlanEntry } from "~/types/api-types/meal-plan";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -9,31 +9,12 @@ const routes = {
|
||||
mealplanId: (id: string | number) => `${prefix}/groups/mealplans/${id}`,
|
||||
};
|
||||
|
||||
type PlanEntryType = "breakfast" | "lunch" | "dinner" | "side";
|
||||
|
||||
export interface CreateMealPlan {
|
||||
date: string;
|
||||
entryType: PlanEntryType;
|
||||
title: string;
|
||||
text: string;
|
||||
recipeId?: string;
|
||||
}
|
||||
|
||||
export interface UpdateMealPlan extends CreateMealPlan {
|
||||
id: number;
|
||||
groupId: number;
|
||||
}
|
||||
|
||||
export interface MealPlan extends UpdateMealPlan {
|
||||
recipe: any;
|
||||
}
|
||||
|
||||
export class MealPlanAPI extends BaseCRUDAPI<MealPlan, CreateMealPlan> {
|
||||
export class MealPlanAPI extends BaseCRUDAPI<CreatePlanEntry, ReadPlanEntry, UpdatePlanEntry> {
|
||||
baseRoute = routes.mealplan;
|
||||
itemRoute = routes.mealplanId;
|
||||
|
||||
async setRandom(payload: CreatRandomEntry) {
|
||||
async setRandom(payload: CreateRandomEntry) {
|
||||
console.log(payload);
|
||||
return await this.requests.post<MealPlan>(routes.random, payload);
|
||||
return await this.requests.post<ReadPlanEntry>(routes.random, payload);
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
import { ReportSummary } from "./group-reports";
|
||||
import { ReportSummary } from "~/types/api-types/reports";
|
||||
import { SupportedMigrations } from "~/types/api-types/group";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
export type SupportedMigration = "nextcloud" | "chowdown" | "mealie_alpha" | "paprika";
|
||||
|
||||
export interface MigrationPayload {
|
||||
addMigrationTag: boolean;
|
||||
migrationType: SupportedMigration;
|
||||
migrationType: SupportedMigrations;
|
||||
archive: File;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BaseCRUDAPI } from "../_base";
|
||||
import { MultiPurposeLabelCreate, MultiPurposeLabelOut } from "~/types/api-types/labels";
|
||||
import { MultiPurposeLabelCreate, MultiPurposeLabelOut, MultiPurposeLabelUpdate } from "~/types/api-types/labels";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -8,7 +8,7 @@ const routes = {
|
||||
labelsId: (id: string | number) => `${prefix}/groups/labels/${id}`,
|
||||
};
|
||||
|
||||
export class MultiPurposeLabelsApi extends BaseCRUDAPI<MultiPurposeLabelOut, MultiPurposeLabelCreate> {
|
||||
export class MultiPurposeLabelsApi extends BaseCRUDAPI<MultiPurposeLabelCreate, MultiPurposeLabelOut, MultiPurposeLabelUpdate> {
|
||||
baseRoute = routes.labels;
|
||||
itemRoute = routes.labelsId;
|
||||
}
|
||||
|
@ -1,33 +1,8 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
import { ReportCategory, ReportOut, ReportSummary } from "~/types/api-types/reports";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
export type ReportCategory = "backup" | "restore" | "migration";
|
||||
|
||||
export type SummaryStatus = "success" | "failure" | "partial" | "in-progress";
|
||||
|
||||
export interface ReportEntry {
|
||||
id: string;
|
||||
reportId: string;
|
||||
timestamp: Date;
|
||||
success: boolean;
|
||||
message: string;
|
||||
exception: string;
|
||||
}
|
||||
|
||||
export interface ReportSummary {
|
||||
id: string;
|
||||
timestamp: Date;
|
||||
category: ReportCategory;
|
||||
groupId: number;
|
||||
name: string;
|
||||
status: SummaryStatus;
|
||||
}
|
||||
|
||||
export interface Report extends ReportSummary {
|
||||
entries: ReportEntry[];
|
||||
}
|
||||
|
||||
const routes = {
|
||||
base: `${prefix}/groups/reports`,
|
||||
getOne: (id: string) => `${prefix}/groups/reports/${id}`,
|
||||
@ -40,7 +15,7 @@ export class GroupReportsApi extends BaseAPI {
|
||||
}
|
||||
|
||||
async getOne(id: string) {
|
||||
return await this.requests.get<Report>(routes.getOne(id));
|
||||
return await this.requests.get<ReportOut>(routes.getOne(id));
|
||||
}
|
||||
|
||||
async deleteOne(id: string) {
|
||||
|
@ -4,7 +4,9 @@ import {
|
||||
ShoppingListCreate,
|
||||
ShoppingListItemCreate,
|
||||
ShoppingListItemOut,
|
||||
ShoppingListItemUpdate,
|
||||
ShoppingListOut,
|
||||
ShoppingListUpdate,
|
||||
} from "~/types/api-types/group";
|
||||
|
||||
const prefix = "/api";
|
||||
@ -18,7 +20,7 @@ const routes = {
|
||||
shoppingListItemsId: (id: string) => `${prefix}/groups/shopping/items/${id}`,
|
||||
};
|
||||
|
||||
export class ShoppingListsApi extends BaseCRUDAPI<ShoppingListOut, ShoppingListCreate> {
|
||||
export class ShoppingListsApi extends BaseCRUDAPI<ShoppingListCreate, ShoppingListOut, ShoppingListUpdate> {
|
||||
baseRoute = routes.shoppingLists;
|
||||
itemRoute = routes.shoppingListsId;
|
||||
|
||||
@ -31,7 +33,7 @@ export class ShoppingListsApi extends BaseCRUDAPI<ShoppingListOut, ShoppingListC
|
||||
}
|
||||
}
|
||||
|
||||
export class ShoppingListItemsApi extends BaseCRUDAPI<ShoppingListItemOut, ShoppingListItemCreate> {
|
||||
export class ShoppingListItemsApi extends BaseCRUDAPI<ShoppingListItemCreate, ShoppingListItemOut, ShoppingListItemUpdate> {
|
||||
baseRoute = routes.shoppingListItems;
|
||||
itemRoute = routes.shoppingListItemsId;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
import { ServerTask } from "~/api/types/server-task";
|
||||
import { ServerTask } from "~/types/api-types/server";
|
||||
const prefix = "/api";
|
||||
|
||||
const routes = {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { BaseCRUDAPI } from "../_base";
|
||||
import { CreateWebhook, ReadWebhook } from "~/types/api-types/group";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -7,19 +8,7 @@ const routes = {
|
||||
webhooksId: (id: string | number) => `${prefix}/groups/webhooks/${id}`,
|
||||
};
|
||||
|
||||
export interface CreateGroupWebhook {
|
||||
enabled: boolean;
|
||||
name: string;
|
||||
url: string;
|
||||
time: string;
|
||||
}
|
||||
|
||||
export interface GroupWebhook extends CreateGroupWebhook {
|
||||
id: string;
|
||||
groupId: string;
|
||||
}
|
||||
|
||||
export class WebhooksAPI extends BaseCRUDAPI<GroupWebhook, CreateGroupWebhook> {
|
||||
export class WebhooksAPI extends BaseCRUDAPI<CreateWebhook, ReadWebhook> {
|
||||
baseRoute = routes.webhooks;
|
||||
itemRoute = routes.webhooksId;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { BaseCRUDAPI } from "../_base";
|
||||
import { GroupInDB, UserOut } from "~/types/api-types/user";
|
||||
import { GroupStatistics, GroupStorage } from "~/types/api-types/group";
|
||||
import { CategoryBase, GroupBase, GroupInDB, UserOut } from "~/types/api-types/user";
|
||||
import { CreateInviteToken, GroupAdminUpdate, GroupStatistics, GroupStorage, ReadGroupPreferences, ReadInviteToken, SetPermissions, UpdateGroupPreferences } from "~/types/api-types/group";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -20,82 +20,34 @@ const routes = {
|
||||
groupsId: (id: string | number) => `${prefix}/admin/groups/${id}`,
|
||||
};
|
||||
|
||||
interface Category {
|
||||
id: number;
|
||||
name: string;
|
||||
slug: string;
|
||||
}
|
||||
|
||||
export interface CreateGroup {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface UpdatePreferences {
|
||||
privateGroup: boolean;
|
||||
firstDayOfWeek: number;
|
||||
recipePublic: boolean;
|
||||
recipeShowNutrition: boolean;
|
||||
recipeShowAssets: boolean;
|
||||
recipeLandscapeView: boolean;
|
||||
recipeDisableComments: boolean;
|
||||
recipeDisableAmount: boolean;
|
||||
}
|
||||
|
||||
export interface Preferences extends UpdatePreferences {
|
||||
id: number;
|
||||
group_id: number;
|
||||
}
|
||||
|
||||
export interface Group extends CreateGroup {
|
||||
id: number;
|
||||
preferences: Preferences;
|
||||
}
|
||||
|
||||
export interface CreateInvitation {
|
||||
uses: number;
|
||||
}
|
||||
|
||||
export interface Invitation {
|
||||
group_id: number;
|
||||
token: string;
|
||||
uses_left: number;
|
||||
}
|
||||
|
||||
export interface SetPermissions {
|
||||
userId: string;
|
||||
canInvite?: boolean;
|
||||
canManage?: boolean;
|
||||
canOrganize?: boolean;
|
||||
}
|
||||
|
||||
export class GroupAPI extends BaseCRUDAPI<GroupInDB, CreateGroup> {
|
||||
export class GroupAPI extends BaseCRUDAPI<GroupBase, GroupInDB, GroupAdminUpdate> {
|
||||
baseRoute = routes.groups;
|
||||
itemRoute = routes.groupsId;
|
||||
/** Returns the Group Data for the Current User
|
||||
*/
|
||||
async getCurrentUserGroup() {
|
||||
return await this.requests.get<Group>(routes.groupsSelf);
|
||||
return await this.requests.get<GroupInDB>(routes.groupsSelf);
|
||||
}
|
||||
|
||||
async getCategories() {
|
||||
return await this.requests.get<Category[]>(routes.categories);
|
||||
return await this.requests.get<CategoryBase[]>(routes.categories);
|
||||
}
|
||||
|
||||
async setCategories(payload: Category[]) {
|
||||
return await this.requests.put<Category[]>(routes.categories, payload);
|
||||
async setCategories(payload: CategoryBase[]) {
|
||||
return await this.requests.put<CategoryBase[]>(routes.categories, payload);
|
||||
}
|
||||
|
||||
async getPreferences() {
|
||||
return await this.requests.get<Preferences>(routes.preferences);
|
||||
return await this.requests.get<ReadGroupPreferences>(routes.preferences);
|
||||
}
|
||||
|
||||
async setPreferences(payload: UpdatePreferences) {
|
||||
async setPreferences(payload: UpdateGroupPreferences) {
|
||||
// TODO: This should probably be a patch request, which isn't offered by the API currently
|
||||
return await this.requests.put<Preferences, UpdatePreferences>(routes.preferences, payload);
|
||||
return await this.requests.put<ReadGroupPreferences, UpdateGroupPreferences>(routes.preferences, payload);
|
||||
}
|
||||
|
||||
async createInvitation(payload: CreateInvitation) {
|
||||
return await this.requests.post<Invitation>(routes.invitation, payload);
|
||||
async createInvitation(payload: CreateInviteToken) {
|
||||
return await this.requests.post<ReadInviteToken>(routes.invitation, payload);
|
||||
}
|
||||
|
||||
async fetchMembers() {
|
||||
@ -104,7 +56,7 @@ export class GroupAPI extends BaseCRUDAPI<GroupInDB, CreateGroup> {
|
||||
|
||||
async setMemberPermissions(payload: SetPermissions) {
|
||||
// TODO: This should probably be a patch request, which isn't offered by the API currently
|
||||
return await this.requests.put<Permissions, SetPermissions>(routes.permissions, payload);
|
||||
return await this.requests.put<UserOut, SetPermissions>(routes.permissions, payload);
|
||||
}
|
||||
|
||||
async statistics() {
|
||||
|
@ -10,7 +10,7 @@ const routes = {
|
||||
categoriesSlug: (category: string) => `${prefix}/categories/slug/${category}`,
|
||||
};
|
||||
|
||||
export class CategoriesAPI extends BaseCRUDAPI<RecipeCategoryResponse, CategoryIn> {
|
||||
export class CategoriesAPI extends BaseCRUDAPI<CategoryIn, RecipeCategoryResponse> {
|
||||
baseRoute: string = routes.categories;
|
||||
itemRoute = routes.categoriesId;
|
||||
|
||||
|
@ -10,7 +10,7 @@ const routes = {
|
||||
tagsSlug: (tag: string) => `${prefix}/tags/slug/${tag}`,
|
||||
};
|
||||
|
||||
export class TagsAPI extends BaseCRUDAPI<RecipeTagResponse, TagIn> {
|
||||
export class TagsAPI extends BaseCRUDAPI<TagIn, RecipeTagResponse> {
|
||||
baseRoute: string = routes.tags;
|
||||
itemRoute = routes.tagsId;
|
||||
|
||||
|
@ -11,7 +11,7 @@ const routes = {
|
||||
toolsSlug: (id: string) => `${prefix}/tools/slug/${id}`,
|
||||
};
|
||||
|
||||
export class ToolsApi extends BaseCRUDAPI<RecipeTool, RecipeToolCreate> {
|
||||
export class ToolsApi extends BaseCRUDAPI<RecipeToolCreate, RecipeTool> {
|
||||
baseRoute: string = routes.tools;
|
||||
itemRoute = routes.toolsId;
|
||||
|
||||
|
@ -1,45 +1,10 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
import { AssignCategories, AssignTags, DeleteRecipes, ExportRecipes } from "~/types/api-types/recipe";
|
||||
import { GroupDataExport } from "~/types/api-types/group";
|
||||
|
||||
interface BasePayload {
|
||||
recipes: string[];
|
||||
}
|
||||
|
||||
type exportType = "json";
|
||||
|
||||
// Many bulk actions return nothing
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
interface RecipeBulkDelete extends BasePayload {}
|
||||
|
||||
interface RecipeBulkExport extends BasePayload {
|
||||
exportType: exportType;
|
||||
}
|
||||
|
||||
interface RecipeBulkCategorize extends BasePayload {
|
||||
categories: string[];
|
||||
}
|
||||
|
||||
interface RecipeBulkTag extends BasePayload {
|
||||
tags: string[];
|
||||
}
|
||||
|
||||
interface BulkActionError {
|
||||
recipe: string;
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface BulkActionResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
errors: BulkActionError[];
|
||||
}
|
||||
|
||||
export interface GroupDataExport {
|
||||
id: string;
|
||||
groupId: string;
|
||||
name: string;
|
||||
filename: string;
|
||||
path: string;
|
||||
size: string;
|
||||
expires: Date;
|
||||
}
|
||||
|
||||
const prefix = "/api";
|
||||
@ -53,19 +18,19 @@ const routes = {
|
||||
};
|
||||
|
||||
export class BulkActionsAPI extends BaseAPI {
|
||||
async bulkExport(payload: RecipeBulkExport) {
|
||||
async bulkExport(payload: ExportRecipes) {
|
||||
return await this.requests.post<BulkActionResponse>(routes.bulkExport, payload);
|
||||
}
|
||||
|
||||
async bulkCategorize(payload: RecipeBulkCategorize) {
|
||||
async bulkCategorize(payload: AssignCategories) {
|
||||
return await this.requests.post<BulkActionResponse>(routes.bulkCategorize, payload);
|
||||
}
|
||||
|
||||
async bulkTag(payload: RecipeBulkTag) {
|
||||
async bulkTag(payload: AssignTags) {
|
||||
return await this.requests.post<BulkActionResponse>(routes.bulkTag, payload);
|
||||
}
|
||||
|
||||
async bulkDelete(payload: RecipeBulkDelete) {
|
||||
async bulkDelete(payload: DeleteRecipes) {
|
||||
return await this.requests.post<BulkActionResponse>(routes.bulkDelete, payload);
|
||||
}
|
||||
|
||||
@ -74,6 +39,6 @@ export class BulkActionsAPI extends BaseAPI {
|
||||
}
|
||||
|
||||
async purgeExports() {
|
||||
return await this.requests.delete(routes.purgeExports);
|
||||
return await this.requests.delete<BulkActionResponse>(routes.purgeExports);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ const routes = {
|
||||
merge: `${prefix}/foods/merge`,
|
||||
};
|
||||
|
||||
export class FoodAPI extends BaseCRUDAPI<IngredientFood, CreateIngredientFood> {
|
||||
export class FoodAPI extends BaseCRUDAPI<CreateIngredientFood, IngredientFood> {
|
||||
baseRoute: string = routes.food;
|
||||
itemRoute = routes.foodsFood;
|
||||
|
||||
|
@ -9,7 +9,7 @@ const routes = {
|
||||
merge: `${prefix}/units/merge`,
|
||||
};
|
||||
|
||||
export class UnitAPI extends BaseCRUDAPI<IngredientUnit, CreateIngredientUnit> {
|
||||
export class UnitAPI extends BaseCRUDAPI<CreateIngredientUnit, IngredientUnit> {
|
||||
baseRoute: string = routes.unit;
|
||||
itemRoute = routes.unitsUnit;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { RecipeComment, RecipeCommentCreate } from "./types";
|
||||
import { BaseCRUDAPI } from "~/api/_base";
|
||||
import { RecipeCommentCreate, RecipeCommentOut, RecipeCommentUpdate } from "~/types/api-types/recipe";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -9,11 +9,11 @@ const routes = {
|
||||
commentsId: (id: string) => `${prefix}/comments/${id}`,
|
||||
};
|
||||
|
||||
export class CommentsApi extends BaseCRUDAPI<RecipeComment, RecipeCommentCreate> {
|
||||
export class CommentsApi extends BaseCRUDAPI<RecipeCommentCreate, RecipeCommentOut, RecipeCommentUpdate> {
|
||||
baseRoute: string = routes.comment;
|
||||
itemRoute = routes.commentsId;
|
||||
|
||||
async byRecipe(slug: string) {
|
||||
return await this.requests.get<RecipeComment[]>(routes.byRecipe(slug));
|
||||
return await this.requests.get<RecipeCommentOut[]>(routes.byRecipe(slug));
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { BaseCRUDAPI } from "~/api/_base";
|
||||
import { RecipeShareToken, RecipeShareTokenCreate } from "~/types/api-types/recipe";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -7,20 +8,7 @@ const routes = {
|
||||
shareTokenId: (id: string) => `${prefix}/shared/recipes/${id}`,
|
||||
};
|
||||
|
||||
export interface RecipeShareTokenCreate {
|
||||
recipeId: string;
|
||||
expiresAt?: Date;
|
||||
}
|
||||
|
||||
export interface RecipeShareToken {
|
||||
recipeId: string;
|
||||
id: string;
|
||||
groupId: number;
|
||||
expiresAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export class RecipeShareApi extends BaseCRUDAPI<RecipeShareToken, RecipeShareTokenCreate> {
|
||||
export class RecipeShareApi extends BaseCRUDAPI<RecipeShareTokenCreate, RecipeShareToken> {
|
||||
baseRoute: string = routes.shareToken;
|
||||
itemRoute = routes.shareTokenId;
|
||||
}
|
||||
|
@ -1,11 +1,19 @@
|
||||
import { CreateAsset, ParsedIngredient, Parser, RecipeZipToken, BulkCreatePayload } from "./types";
|
||||
import { CommentsApi } from "./recipe-comments";
|
||||
import { RecipeShareApi } from "./recipe-share";
|
||||
import { BaseCRUDAPI } from "~/api/_base";
|
||||
|
||||
import { Recipe, CreateRecipe } from "~/types/api-types/recipe";
|
||||
import { Recipe, CreateRecipe, RecipeAsset, CreateRecipeByUrlBulk, ParsedIngredient, UpdateImageResponse, RecipeZipTokenResponse } from "~/types/api-types/recipe";
|
||||
import { ApiRequestInstance } from "~/types/api";
|
||||
|
||||
export type Parser = "nlp" | "brute";
|
||||
|
||||
export interface CreateAsset {
|
||||
name: string;
|
||||
icon: string;
|
||||
extension: string;
|
||||
file: File;
|
||||
}
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
const routes = {
|
||||
@ -31,7 +39,7 @@ const routes = {
|
||||
recipeShareToken: (token: string) => `${prefix}/recipes/shared/${token}`,
|
||||
};
|
||||
|
||||
export class RecipeAPI extends BaseCRUDAPI<Recipe, CreateRecipe> {
|
||||
export class RecipeAPI extends BaseCRUDAPI<CreateRecipe, Recipe, Recipe> {
|
||||
baseRoute: string = routes.recipesBase;
|
||||
itemRoute = routes.recipesRecipeSlug;
|
||||
|
||||
@ -58,7 +66,7 @@ export class RecipeAPI extends BaseCRUDAPI<Recipe, CreateRecipe> {
|
||||
formData.append("extension", payload.extension);
|
||||
formData.append("icon", payload.icon);
|
||||
|
||||
return await this.requests.post(routes.recipesRecipeSlugAssets(recipeSlug), formData);
|
||||
return await this.requests.post<RecipeAsset>(routes.recipesRecipeSlugAssets(recipeSlug), formData);
|
||||
}
|
||||
|
||||
updateImage(slug: string, fileObject: File) {
|
||||
@ -66,11 +74,11 @@ export class RecipeAPI extends BaseCRUDAPI<Recipe, CreateRecipe> {
|
||||
formData.append("image", fileObject);
|
||||
formData.append("extension", fileObject.name.split(".").pop() ?? "");
|
||||
|
||||
return this.requests.put<any>(routes.recipesRecipeSlugImage(slug), formData);
|
||||
return this.requests.put<UpdateImageResponse, FormData>(routes.recipesRecipeSlugImage(slug), formData);
|
||||
}
|
||||
|
||||
updateImagebyURL(slug: string, url: string) {
|
||||
return this.requests.post(routes.recipesRecipeSlugImage(slug), { url });
|
||||
return this.requests.post<UpdateImageResponse>(routes.recipesRecipeSlugImage(slug), { url });
|
||||
}
|
||||
|
||||
async testCreateOneUrl(url: string) {
|
||||
@ -81,8 +89,8 @@ export class RecipeAPI extends BaseCRUDAPI<Recipe, CreateRecipe> {
|
||||
return await this.requests.post<string>(routes.recipesCreateUrl, { url, includeTags });
|
||||
}
|
||||
|
||||
async createManyByUrl(payload: BulkCreatePayload) {
|
||||
return await this.requests.post(routes.recipesCreateUrlBulk, payload);
|
||||
async createManyByUrl(payload: CreateRecipeByUrlBulk) {
|
||||
return await this.requests.post<string>(routes.recipesCreateUrlBulk, payload);
|
||||
}
|
||||
|
||||
async parseIngredients(parser: Parser, ingredients: Array<string>) {
|
||||
@ -96,7 +104,7 @@ export class RecipeAPI extends BaseCRUDAPI<Recipe, CreateRecipe> {
|
||||
}
|
||||
|
||||
async getZipToken(recipeSlug: string) {
|
||||
return await this.requests.post<RecipeZipToken>(routes.recipesRecipeSlugExport(recipeSlug), {});
|
||||
return await this.requests.post<RecipeZipTokenResponse>(routes.recipesRecipeSlugExport(recipeSlug), {});
|
||||
}
|
||||
|
||||
getZipRedirectUrl(recipeSlug: string, token: string) {
|
||||
|
@ -1,72 +0,0 @@
|
||||
import { CreateIngredientFood, CreateIngredientUnit, IngredientFood, IngredientUnit } from "~/types/api-types/recipe";
|
||||
import { RecipeCategory, RecipeTag } from "~/types/api-types/user";
|
||||
|
||||
export type Parser = "nlp" | "brute";
|
||||
|
||||
export interface Confidence {
|
||||
average?: number;
|
||||
comment?: number;
|
||||
name?: number;
|
||||
unit?: number;
|
||||
quantity?: number;
|
||||
food?: number;
|
||||
}
|
||||
|
||||
export interface Ingredient {
|
||||
title?: string;
|
||||
note?: string;
|
||||
unit?: IngredientUnit | CreateIngredientUnit;
|
||||
food?: IngredientFood | CreateIngredientFood;
|
||||
disableAmount?: boolean;
|
||||
quantity?: number;
|
||||
referenceId?: string;
|
||||
}
|
||||
|
||||
export interface ParsedIngredient {
|
||||
input: string
|
||||
confidence: Confidence;
|
||||
ingredient: Ingredient;
|
||||
}
|
||||
|
||||
export interface BulkCreateRecipe {
|
||||
url: string;
|
||||
categories: RecipeCategory[];
|
||||
tags: RecipeTag[];
|
||||
}
|
||||
|
||||
export interface BulkCreatePayload {
|
||||
imports: BulkCreateRecipe[];
|
||||
}
|
||||
|
||||
export interface RecipeZipToken {
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface CreateAsset {
|
||||
name: string;
|
||||
icon: string;
|
||||
extension: string;
|
||||
file: File;
|
||||
}
|
||||
|
||||
export interface RecipeCommentCreate {
|
||||
recipeId: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface RecipeCommentUpdate extends RecipeCommentCreate {
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface RecipeCommentUser {
|
||||
id: string;
|
||||
username: string;
|
||||
admin: boolean;
|
||||
}
|
||||
|
||||
export interface RecipeComment extends RecipeCommentUpdate {
|
||||
createdAt: any;
|
||||
updatedAt: any;
|
||||
userId: number;
|
||||
user: RecipeCommentUser;
|
||||
}
|
@ -1,29 +1,5 @@
|
||||
import { BaseCRUDAPI } from "../_base";
|
||||
import { UserIn, UserOut } from "~/types/api-types/user";
|
||||
|
||||
// Interfaces
|
||||
|
||||
interface ChangePassword {
|
||||
currentPassword: string;
|
||||
newPassword: string;
|
||||
}
|
||||
|
||||
interface CreateAPIToken {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface ResponseToken {
|
||||
token: string;
|
||||
}
|
||||
|
||||
interface PasswordResetPayload {
|
||||
token: string;
|
||||
email: string;
|
||||
password: string;
|
||||
passwordConfirm: string;
|
||||
}
|
||||
|
||||
// Code
|
||||
import { ChangePassword, DeleteTokenResponse, LongLiveTokenIn, LongLiveTokenOut, ResetPassword, UserBase, UserIn, UserOut } from "~/types/api-types/user";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -43,7 +19,7 @@ const routes = {
|
||||
usersApiTokensTokenId: (token_id: string | number) => `${prefix}/users/api-tokens/${token_id}`,
|
||||
};
|
||||
|
||||
export class UserApi extends BaseCRUDAPI<UserOut, UserIn> {
|
||||
export class UserApi extends BaseCRUDAPI<UserIn, UserOut, UserBase> {
|
||||
baseRoute: string = routes.users;
|
||||
itemRoute = (itemid: string) => routes.usersId(itemid);
|
||||
|
||||
@ -63,12 +39,12 @@ export class UserApi extends BaseCRUDAPI<UserOut, UserIn> {
|
||||
return await this.requests.put(routes.usersIdPassword(id), changePassword);
|
||||
}
|
||||
|
||||
async createAPIToken(tokenName: CreateAPIToken) {
|
||||
return await this.requests.post<ResponseToken>(routes.usersApiTokens, tokenName);
|
||||
async createAPIToken(tokenName: LongLiveTokenIn) {
|
||||
return await this.requests.post<LongLiveTokenOut>(routes.usersApiTokens, tokenName);
|
||||
}
|
||||
|
||||
async deleteAPIToken(tokenId: string | number) {
|
||||
return await this.requests.delete(routes.usersApiTokensTokenId(tokenId));
|
||||
async deleteAPIToken(tokenId: number) {
|
||||
return await this.requests.delete<DeleteTokenResponse>(routes.usersApiTokensTokenId(tokenId));
|
||||
}
|
||||
|
||||
userProfileImage(id: string) {
|
||||
@ -76,7 +52,7 @@ export class UserApi extends BaseCRUDAPI<UserOut, UserIn> {
|
||||
return `/api/users/${id}/image`;
|
||||
}
|
||||
|
||||
async resetPassword(payload: PasswordResetPayload) {
|
||||
async resetPassword(payload: ResetPassword) {
|
||||
return await this.requests.post(routes.passwordReset, payload);
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,11 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
import { FileTokenResponse } from "~/types/api-types/response";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
interface DownloadData {
|
||||
fileToken: string;
|
||||
}
|
||||
|
||||
export class UtilsAPI extends BaseAPI {
|
||||
async download(url: string) {
|
||||
const { response } = await this.requests.get<DownloadData>(url);
|
||||
const { response } = await this.requests.get<FileTokenResponse>(url);
|
||||
|
||||
if (!response) {
|
||||
return;
|
||||
|
@ -1,8 +1,5 @@
|
||||
import { BaseAPI } from "../_base";
|
||||
|
||||
export type Validation = {
|
||||
valid: boolean;
|
||||
};
|
||||
import { ValidationResponse } from "~/types/api-types/response";
|
||||
|
||||
const prefix = "/api";
|
||||
|
||||
@ -15,18 +12,18 @@ const routes = {
|
||||
|
||||
export class ValidatorsApi extends BaseAPI {
|
||||
async group(name: string) {
|
||||
return await this.requests.get<Validation>(routes.group(name));
|
||||
return await this.requests.get<ValidationResponse>(routes.group(name));
|
||||
}
|
||||
|
||||
async username(name: string) {
|
||||
return await this.requests.get<Validation>(routes.user(name));
|
||||
return await this.requests.get<ValidationResponse>(routes.user(name));
|
||||
}
|
||||
|
||||
async email(email: string) {
|
||||
return await this.requests.get<Validation>(routes.email(email));
|
||||
return await this.requests.get<ValidationResponse>(routes.email(email));
|
||||
}
|
||||
|
||||
async recipe(groupId: string, name: string) {
|
||||
return await this.requests.get<Validation>(routes.recipe(groupId, name));
|
||||
return await this.requests.get<ValidationResponse>(routes.recipe(groupId, name));
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +0,0 @@
|
||||
export interface ServerTask {
|
||||
id: number;
|
||||
groupId: number;
|
||||
callback: string;
|
||||
createdAt: string;
|
||||
status: string;
|
||||
log: string;
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "@nuxtjs/composition-api";
|
||||
import { parseISO, formatDistanceToNow } from "date-fns";
|
||||
import { GroupDataExport } from "~/api/class-interfaces/recipe-bulk-actions";
|
||||
import { GroupDataExport } from "~/types/api-types/group";
|
||||
export default defineComponent({
|
||||
props: {
|
||||
exports: {
|
||||
@ -57,4 +57,3 @@ export default defineComponent({
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, toRefs, onMounted, reactive } from "@nuxtjs/composition-api";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { RecipeComment } from "~/api/class-interfaces/recipes/types";
|
||||
import { RecipeCommentOut } from "~/types/api-types/recipe";
|
||||
import UserAvatar from "~/components/Domain/User/UserAvatar.vue";
|
||||
|
||||
export default defineComponent({
|
||||
@ -76,7 +76,7 @@ export default defineComponent({
|
||||
setup(props) {
|
||||
const api = useUserApi();
|
||||
|
||||
const comments = ref<RecipeComment[]>([]);
|
||||
const comments = ref<RecipeCommentOut[]>([]);
|
||||
|
||||
const state = reactive({
|
||||
comment: "",
|
||||
|
@ -95,8 +95,9 @@ import { defineComponent, reactive, toRefs, useContext, useRouter, ref } from "@
|
||||
import RecipeDialogShare from "./RecipeDialogShare.vue";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { alert } from "~/composables/use-toast";
|
||||
import { MealType, planTypeOptions } from "~/composables/use-group-mealplan";
|
||||
import { planTypeOptions } from "~/composables/use-group-mealplan";
|
||||
import { ShoppingListSummary } from "~/types/api-types/group";
|
||||
import { PlanEntryType } from "~/types/api-types/meal-plan";
|
||||
import { useAxiosDownloader } from "~/composables/api/use-axios-download";
|
||||
|
||||
export interface ContextMenuIncludes {
|
||||
@ -183,7 +184,7 @@ export default defineComponent({
|
||||
loading: false,
|
||||
menuItems: [] as ContextMenuItem[],
|
||||
newMealdate: "",
|
||||
newMealType: "dinner" as MealType,
|
||||
newMealType: "dinner" as PlanEntryType,
|
||||
pickerMenu: false,
|
||||
});
|
||||
|
||||
|
@ -59,7 +59,7 @@
|
||||
import { defineComponent, computed, toRefs, reactive, useContext } from "@nuxtjs/composition-api";
|
||||
import { whenever } from "@vueuse/shared";
|
||||
import { useClipboard, useShare } from "@vueuse/core";
|
||||
import { RecipeShareToken } from "~/api/class-interfaces/recipes/recipe-share";
|
||||
import { RecipeShareToken } from "~/types/api-types/recipe";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { alert } from "~/composables/use-toast";
|
||||
|
||||
@ -118,7 +118,7 @@ export default defineComponent({
|
||||
|
||||
const { data } = await userApi.recipes.share.createOne({
|
||||
recipeId: props.recipeId,
|
||||
expiresAt: expirationDate,
|
||||
expiresAt: expirationDate.toISOString(),
|
||||
});
|
||||
|
||||
if (data) {
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, useRouter } from "@nuxtjs/composition-api";
|
||||
import { ReportSummary } from "~/api/class-interfaces/group-reports";
|
||||
import { ReportSummary } from "~/types/api-types/reports";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
|
@ -1,8 +1,13 @@
|
||||
import { useAsync, ref, reactive } from "@nuxtjs/composition-api";
|
||||
import { toastLoading, loader } from "./use-toast";
|
||||
import { AllBackups, ImportBackup } from "~/api/class-interfaces/backups";
|
||||
import { AllBackups, BackupOptions } from "~/types/api-types/admin";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
|
||||
interface ImportBackup {
|
||||
name: string;
|
||||
options: BackupOptions;
|
||||
}
|
||||
|
||||
const backups = ref<AllBackups>({
|
||||
imports: [],
|
||||
templates: [],
|
||||
@ -41,7 +46,6 @@ export const useBackups = function (fetch = true) {
|
||||
options: {
|
||||
recipes: true,
|
||||
settings: true,
|
||||
pages: true,
|
||||
themes: true,
|
||||
groups: true,
|
||||
users: true,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useAsync, ref, Ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { ReadCookBook, RecipeCookBook, UpdateCookBook } from "~/types/api-types/cookbook";
|
||||
import { ReadCookBook, UpdateCookBook } from "~/types/api-types/cookbook";
|
||||
|
||||
let cookbookStore: Ref<ReadCookBook[] | null> | null = null;
|
||||
|
||||
@ -66,7 +66,7 @@ export const useCookbooks = function () {
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
const { data } = await api.cookbooks.updateOne(updateData.id, updateData as RecipeCookBook);
|
||||
const { data } = await api.cookbooks.updateOne(updateData.id, updateData);
|
||||
if (data && cookbookStore?.value) {
|
||||
this.refreshAll();
|
||||
}
|
||||
|
@ -2,9 +2,7 @@ import { useAsync, ref, Ref, watch } from "@nuxtjs/composition-api";
|
||||
import { format } from "date-fns";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { CreateMealPlan, UpdateMealPlan } from "~/api/class-interfaces/group-mealplan";
|
||||
|
||||
export type MealType = "breakfast" | "lunch" | "dinner" | "side";
|
||||
import { CreatePlanEntry, PlanEntryType, UpdatePlanEntry } from "~/types/api-types/meal-plan";
|
||||
|
||||
export const planTypeOptions = [
|
||||
{ text: "Breakfast", value: "breakfast" },
|
||||
@ -55,7 +53,7 @@ export const useMealplans = function (range: Ref<DateRange>) {
|
||||
|
||||
loading.value = false;
|
||||
},
|
||||
async createOne(payload: CreateMealPlan) {
|
||||
async createOne(payload: CreatePlanEntry) {
|
||||
loading.value = true;
|
||||
|
||||
const { data } = await api.mealplans.createOne(payload);
|
||||
@ -65,13 +63,12 @@ export const useMealplans = function (range: Ref<DateRange>) {
|
||||
|
||||
loading.value = false;
|
||||
},
|
||||
async updateOne(updateData: UpdateMealPlan) {
|
||||
async updateOne(updateData: UpdatePlanEntry) {
|
||||
if (!updateData.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
// @ts-ignore TODO Modify mealpan types to be from auto-generated files
|
||||
const { data } = await api.mealplans.updateOne(updateData.id, updateData);
|
||||
if (data) {
|
||||
this.refreshAll();
|
||||
@ -87,8 +84,8 @@ export const useMealplans = function (range: Ref<DateRange>) {
|
||||
}
|
||||
},
|
||||
|
||||
async setType(payload: UpdateMealPlan, typ: MealType) {
|
||||
payload.entryType = typ;
|
||||
async setType(payload: UpdatePlanEntry, type: PlanEntryType) {
|
||||
payload.entryType = type;
|
||||
await this.updateOne(payload);
|
||||
},
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { GroupWebhook } from "~/api/class-interfaces/group-webhooks";
|
||||
import { ReadWebhook } from "~/types/api-types/group";
|
||||
|
||||
export const useGroupWebhooks = function () {
|
||||
const api = useUserApi();
|
||||
@ -47,7 +47,7 @@ export const useGroupWebhooks = function () {
|
||||
|
||||
loading.value = false;
|
||||
},
|
||||
async updateOne(updateData: GroupWebhook) {
|
||||
async updateOne(updateData: ReadWebhook) {
|
||||
if (!updateData.id) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||
import { useAsyncKey } from "./use-utils";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { CreateGroup } from "~/api/class-interfaces/groups";
|
||||
import { GroupBase } from "~/types/api-types/user";
|
||||
|
||||
export const useGroupSelf = function () {
|
||||
const api = useUserApi();
|
||||
@ -17,7 +17,7 @@ export const useGroupSelf = function () {
|
||||
return group;
|
||||
},
|
||||
async updatePreferences() {
|
||||
if (!group.value) {
|
||||
if (!group.value?.preferences) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -65,7 +65,7 @@ export const useGroups = function () {
|
||||
return data;
|
||||
}
|
||||
|
||||
async function createGroup(payload: CreateGroup) {
|
||||
async function createGroup(payload: GroupBase) {
|
||||
loading.value = true;
|
||||
const { data } = await api.groups.createOne(payload);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ref, Ref } from "@nuxtjs/composition-api";
|
||||
import { RequestResponse } from "~/types/api";
|
||||
import { Validation } from "~/api/public/validators";
|
||||
import { ValidationResponse } from "~/types/api-types/response";
|
||||
|
||||
const EMAIL_REGEX =
|
||||
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@(([[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
|
||||
@ -23,7 +23,7 @@ export const validators = {
|
||||
*/
|
||||
export const useAsyncValidator = (
|
||||
value: Ref<string>,
|
||||
validatorFunc: (v: string) => Promise<RequestResponse<Validation>>,
|
||||
validatorFunc: (v: string) => Promise<RequestResponse<ValidationResponse>>,
|
||||
validatorMessage: string,
|
||||
errorMessages: Ref<string[]>
|
||||
) => {
|
||||
|
@ -38,10 +38,10 @@
|
||||
</v-expansion-panels>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, onMounted, ref } from "@nuxtjs/composition-api";
|
||||
import { ServerTask } from "~/api/types/server-task";
|
||||
import { ServerTask } from "~/types/api-types/server";
|
||||
import { useAdminApi } from "~/composables/api";
|
||||
|
||||
export default defineComponent({
|
||||
@ -84,4 +84,4 @@ export default defineComponent({
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
|
@ -28,8 +28,8 @@ import { defineComponent, useRoute, onMounted, ref } from "@nuxtjs/composition-a
|
||||
import GroupPreferencesEditor from "~/components/Domain/Group/GroupPreferencesEditor.vue";
|
||||
import { useAdminApi } from "~/composables/api";
|
||||
import { alert } from "~/composables/use-toast";
|
||||
import { GroupInDB } from "~/types/api-types/user";
|
||||
import { VForm } from "~/types/vuetify";
|
||||
import { GroupRead } from "~/api/admin/admin-groups";
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
@ -48,7 +48,7 @@ export default defineComponent({
|
||||
|
||||
const adminApi = useAdminApi();
|
||||
|
||||
const group = ref<GroupRead | null>(null);
|
||||
const group = ref<GroupInDB | null>(null);
|
||||
|
||||
const userError = ref(false);
|
||||
|
||||
|
@ -71,9 +71,9 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, toRefs, useContext, useRouter } from "@nuxtjs/composition-api";
|
||||
import { Group } from "~/api/class-interfaces/groups";
|
||||
import { fieldTypes } from "~/composables/forms";
|
||||
import { useGroups } from "~/composables/use-groups";
|
||||
import { GroupInDB } from "~/types/api-types/user";
|
||||
|
||||
export default defineComponent({
|
||||
layout: "admin",
|
||||
@ -121,7 +121,7 @@ export default defineComponent({
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
function handleRowClick(item: Group) {
|
||||
function handleRowClick(item: GroupInDB) {
|
||||
router.push(`/admin/manage/groups/${item.id}`);
|
||||
}
|
||||
|
||||
|
@ -65,10 +65,11 @@
|
||||
</v-container>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, ref, toRefs } from "@nuxtjs/composition-api";
|
||||
import { Confidence, Parser } from "~/api/class-interfaces/recipes/types";
|
||||
import { Parser } from "~/api/class-interfaces/recipes/recipe";
|
||||
import { IngredientConfidence } from "~/types/api-types/recipe";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
|
||||
type ConfidenceAttribute = "average" | "comment" | "name" | "unit" | "quantity" | "food";
|
||||
@ -85,7 +86,7 @@ export default defineComponent({
|
||||
parser: "nlp" as Parser,
|
||||
});
|
||||
|
||||
const confidence = ref<Confidence>({});
|
||||
const confidence = ref<IngredientConfidence>({});
|
||||
|
||||
function getColor(attribute: ConfidenceAttribute) {
|
||||
const percentage = getConfidence(attribute);
|
||||
@ -141,7 +142,8 @@ export default defineComponent({
|
||||
if (data) {
|
||||
state.results = true;
|
||||
|
||||
confidence.value = data.confidence;
|
||||
if (data.confidence)
|
||||
confidence.value = data.confidence;
|
||||
|
||||
// TODO: Remove ts-ignore
|
||||
// ts-ignore because data will likely change significantly once I figure out how to return results
|
||||
@ -215,6 +217,6 @@ export default defineComponent({
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
</style>
|
||||
|
@ -259,7 +259,7 @@ export default defineComponent({
|
||||
const { data } = await adminApi.about.checkApp();
|
||||
|
||||
if (data) {
|
||||
appConfig.value = data;
|
||||
appConfig.value = { ...data, isSiteSecure: false};
|
||||
}
|
||||
|
||||
appConfig.value.isSiteSecure = isLocalHostOrHttps();
|
||||
@ -323,7 +323,7 @@ export default defineComponent({
|
||||
if (data.success) {
|
||||
state.success = true;
|
||||
} else {
|
||||
state.error = data.error;
|
||||
state.error = data.error ?? "";
|
||||
state.success = false;
|
||||
}
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ import { useUserApi } from "~/composables/api";
|
||||
import { useRecipes, allRecipes } from "~/composables/recipes";
|
||||
import { Recipe } from "~/types/api-types/recipe";
|
||||
import GroupExportData from "~/components/Domain/Group/GroupExportData.vue";
|
||||
import { GroupDataExport } from "~/api/class-interfaces/recipe-bulk-actions";
|
||||
import { GroupDataExport } from "~/types/api-types/group";
|
||||
import { MenuItem } from "~/components/global/BaseOverflowButton.vue";
|
||||
|
||||
const MODES = {
|
||||
|
@ -346,7 +346,7 @@ export default defineComponent({
|
||||
date: "",
|
||||
title: "",
|
||||
text: "",
|
||||
recipeId: undefined as number | undefined,
|
||||
recipeId: undefined as string | undefined,
|
||||
entryType: "dinner" as PlanEntryType,
|
||||
});
|
||||
|
||||
|
@ -66,10 +66,10 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, reactive, toRefs, useContext, computed, onMounted } from "@nuxtjs/composition-api";
|
||||
import { SupportedMigration } from "~/api/class-interfaces/group-migrations";
|
||||
import { ReportSummary } from "~/api/class-interfaces/group-reports";
|
||||
import { ReportSummary } from "~/types/api-types/reports";
|
||||
import { MenuItem } from "~/components/global/BaseOverflowButton.vue";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { SupportedMigrations } from "~/types/api-types/group";
|
||||
|
||||
const MIGRATIONS = {
|
||||
nextcloud: "nextcloud",
|
||||
@ -88,7 +88,7 @@ export default defineComponent({
|
||||
addMigrationTag: false,
|
||||
loading: false,
|
||||
treeState: true,
|
||||
migrationType: MIGRATIONS.nextcloud as SupportedMigration,
|
||||
migrationType: MIGRATIONS.nextcloud as SupportedMigrations,
|
||||
fileObject: {} as File,
|
||||
reports: [] as ReportSummary[],
|
||||
});
|
||||
|
@ -702,8 +702,8 @@ export default defineComponent({
|
||||
return;
|
||||
}
|
||||
const newVersion = await api.recipes.updateImage(recipe.value.slug, fileObject);
|
||||
if (newVersion?.data?.version) {
|
||||
recipe.value.image = newVersion.data.version;
|
||||
if (newVersion?.data?.image) {
|
||||
recipe.value.image = newVersion.data.image;
|
||||
}
|
||||
state.imageKey++;
|
||||
}
|
||||
|
@ -83,8 +83,8 @@
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, useRoute, useRouter } from "@nuxtjs/composition-api";
|
||||
import { invoke, until } from "@vueuse/core";
|
||||
import { ParsedIngredient, Parser } from "~/api/class-interfaces/recipes/types";
|
||||
import { CreateIngredientFood, CreateIngredientUnit, IngredientFood, IngredientUnit } from "~/types/api-types/recipe";
|
||||
import { Parser } from "~/api/class-interfaces/recipes/recipe";
|
||||
import { CreateIngredientFood, CreateIngredientUnit, IngredientFood, IngredientUnit, ParsedIngredient } from "~/types/api-types/recipe";
|
||||
import RecipeIngredientEditor from "~/components/Domain/Recipe/RecipeIngredientEditor.vue";
|
||||
import { useUserApi } from "~/composables/api";
|
||||
import { useFoods, useRecipe, useUnits } from "~/composables/recipes";
|
||||
|
@ -111,7 +111,7 @@ export default defineComponent({
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteToken(id: string | number) {
|
||||
async function deleteToken(id: number) {
|
||||
const { data } = await api.users.deleteAPIToken(id);
|
||||
nuxtContext.$auth.fetchUser();
|
||||
return data;
|
||||
@ -126,4 +126,3 @@ export default defineComponent({
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -50,10 +50,10 @@ export interface BackupOptions {
|
||||
notifications?: boolean;
|
||||
}
|
||||
export interface CheckAppConfig {
|
||||
emailReady?: boolean;
|
||||
ldapReady?: boolean;
|
||||
baseUrlSet?: boolean;
|
||||
isUpToDate?: boolean;
|
||||
emailReady: boolean;
|
||||
ldapReady: boolean;
|
||||
baseUrlSet: boolean;
|
||||
isUpToDate: boolean;
|
||||
}
|
||||
export interface ChowdownURL {
|
||||
url: string;
|
||||
@ -174,6 +174,16 @@ export interface CustomPageOut {
|
||||
export interface DockerVolumeText {
|
||||
text: string;
|
||||
}
|
||||
export interface EmailReady {
|
||||
ready: boolean;
|
||||
}
|
||||
export interface EmailSuccess {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
}
|
||||
export interface EmailTest {
|
||||
email: string;
|
||||
}
|
||||
export interface GroupImport {
|
||||
name: string;
|
||||
status: boolean;
|
||||
|
@ -41,7 +41,7 @@ export interface EmailInvitation {
|
||||
export interface GroupAdminUpdate {
|
||||
id: string;
|
||||
name: string;
|
||||
preferences: UpdateGroupPreferences;
|
||||
preferences?: UpdateGroupPreferences;
|
||||
}
|
||||
export interface UpdateGroupPreferences {
|
||||
privateGroup?: boolean;
|
||||
|
@ -14,10 +14,6 @@ export interface Category {
|
||||
name: string;
|
||||
slug: string;
|
||||
}
|
||||
export interface CreatRandomEntry {
|
||||
date: string;
|
||||
entryType?: PlanEntryType & string;
|
||||
}
|
||||
export interface CreatePlanEntry {
|
||||
date: string;
|
||||
entryType?: PlanEntryType & string;
|
||||
@ -25,6 +21,10 @@ export interface CreatePlanEntry {
|
||||
text?: string;
|
||||
recipeId?: string;
|
||||
}
|
||||
export interface CreateRandomEntry {
|
||||
date: string;
|
||||
entryType?: PlanEntryType & string;
|
||||
}
|
||||
export interface ListItem {
|
||||
title?: string;
|
||||
text?: string;
|
||||
|
@ -26,15 +26,6 @@ export interface TagBase {
|
||||
id: string;
|
||||
slug: string;
|
||||
}
|
||||
export interface BulkActionError {
|
||||
recipe: string;
|
||||
error: string;
|
||||
}
|
||||
export interface BulkActionsResponse {
|
||||
success: boolean;
|
||||
message: string;
|
||||
errors?: BulkActionError[];
|
||||
}
|
||||
export interface CategoryIn {
|
||||
name: string;
|
||||
}
|
||||
@ -335,6 +326,9 @@ export interface RecipeToolSave {
|
||||
onHand?: boolean;
|
||||
groupId: string;
|
||||
}
|
||||
export interface RecipeZipTokenResponse {
|
||||
token: string;
|
||||
}
|
||||
export interface SaveIngredientFood {
|
||||
name: string;
|
||||
description?: string;
|
||||
@ -373,3 +367,6 @@ export interface UnitFoodBase {
|
||||
name: string;
|
||||
description?: string;
|
||||
}
|
||||
export interface UpdateImageResponse {
|
||||
image: string;
|
||||
}
|
||||
|
@ -18,5 +18,5 @@ export interface SuccessResponse {
|
||||
error?: boolean;
|
||||
}
|
||||
export interface ValidationResponse {
|
||||
valid?: boolean;
|
||||
valid: boolean;
|
||||
}
|
||||
|
@ -31,6 +31,9 @@ export interface CreateUserRegistration {
|
||||
seedData?: boolean;
|
||||
locale?: string;
|
||||
}
|
||||
export interface DeleteTokenResponse {
|
||||
tokenDelete: string;
|
||||
}
|
||||
export interface ForgotPassword {
|
||||
email: string;
|
||||
}
|
||||
@ -62,9 +65,7 @@ export interface UserOut {
|
||||
cacheKey: string;
|
||||
}
|
||||
export interface LongLiveTokenOut {
|
||||
name: string;
|
||||
id: number;
|
||||
createdAt: string;
|
||||
token: string;
|
||||
}
|
||||
export interface ReadGroupPreferences {
|
||||
privateGroup?: boolean;
|
||||
@ -78,7 +79,7 @@ export interface ReadGroupPreferences {
|
||||
groupId: string;
|
||||
id: string;
|
||||
}
|
||||
export interface LoingLiveTokenIn {
|
||||
export interface LongLiveTokenIn {
|
||||
name: string;
|
||||
}
|
||||
export interface LongLiveTokenInDB {
|
||||
|
@ -1,25 +1,12 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
from mealie.routes._base import BaseAdminController, controller
|
||||
from mealie.schema._mealie import MealieModel
|
||||
from mealie.schema.admin.email import EmailReady, EmailSuccess, EmailTest
|
||||
from mealie.services.email import EmailService
|
||||
|
||||
router = APIRouter(prefix="/email")
|
||||
|
||||
|
||||
class EmailReady(MealieModel):
|
||||
ready: bool
|
||||
|
||||
|
||||
class EmailSuccess(MealieModel):
|
||||
success: bool
|
||||
error: str = None
|
||||
|
||||
|
||||
class EmailTest(MealieModel):
|
||||
email: str
|
||||
|
||||
|
||||
@controller(router)
|
||||
class AdminEmailController(BaseAdminController):
|
||||
@router.get("", response_model=EmailReady)
|
||||
|
@ -9,7 +9,7 @@ from mealie.routes._base import BaseUserController, controller
|
||||
from mealie.routes._base.mixins import HttpRepo
|
||||
from mealie.schema import mapper
|
||||
from mealie.schema.meal_plan import CreatePlanEntry, ReadPlanEntry, SavePlanEntry, UpdatePlanEntry
|
||||
from mealie.schema.meal_plan.new_meal import CreatRandomEntry
|
||||
from mealie.schema.meal_plan.new_meal import CreateRandomEntry
|
||||
from mealie.schema.meal_plan.plan_rules import PlanRulesDay
|
||||
from mealie.schema.recipe.recipe import Recipe
|
||||
from mealie.schema.response.responses import ErrorResponse
|
||||
@ -42,7 +42,7 @@ class GroupMealplanController(BaseUserController):
|
||||
return self.repo.get_today(group_id=self.group_id)
|
||||
|
||||
@router.post("/random", response_model=ReadPlanEntry)
|
||||
def create_random_meal(self, data: CreatRandomEntry):
|
||||
def create_random_meal(self, data: CreateRandomEntry):
|
||||
"""
|
||||
create_random_meal is a route that provides the randomized funcitonality for mealplaners.
|
||||
It operates by following the rules setout in the Groups mealplan settings. If not settings
|
||||
|
@ -7,13 +7,7 @@ from mealie.core.dependencies.dependencies import temporary_zip_path
|
||||
from mealie.core.security import create_file_token
|
||||
from mealie.routes._base import BaseUserController, controller
|
||||
from mealie.schema.group.group_exports import GroupDataExport
|
||||
from mealie.schema.recipe.recipe_bulk_actions import (
|
||||
AssignCategories,
|
||||
AssignTags,
|
||||
BulkActionsResponse,
|
||||
DeleteRecipes,
|
||||
ExportRecipes,
|
||||
)
|
||||
from mealie.schema.recipe.recipe_bulk_actions import AssignCategories, AssignTags, DeleteRecipes, ExportRecipes
|
||||
from mealie.schema.response.responses import SuccessResponse
|
||||
from mealie.services.recipe.recipe_bulk_service import RecipeBulkActionsService
|
||||
|
||||
@ -26,15 +20,16 @@ class RecipeBulkActionsController(BaseUserController):
|
||||
def service(self) -> RecipeBulkActionsService:
|
||||
return RecipeBulkActionsService(self.repos, self.user, self.group)
|
||||
|
||||
@router.post("/tag", response_model=BulkActionsResponse)
|
||||
# TODO Should these actions return some success response?
|
||||
@router.post("/tag")
|
||||
def bulk_tag_recipes(self, tag_data: AssignTags):
|
||||
self.service.assign_tags(tag_data.recipes, tag_data.tags)
|
||||
|
||||
@router.post("/categorize", response_model=BulkActionsResponse)
|
||||
@router.post("/categorize")
|
||||
def bulk_categorize_recipes(self, assign_cats: AssignCategories):
|
||||
self.service.assign_categories(assign_cats.recipes, assign_cats.categories)
|
||||
|
||||
@router.post("/delete", response_model=BulkActionsResponse)
|
||||
@router.post("/delete")
|
||||
def bulk_delete_recipes(self, delete_recipes: DeleteRecipes):
|
||||
self.service.delete_recipes(delete_recipes.recipes)
|
||||
|
||||
|
@ -27,6 +27,7 @@ from mealie.schema.recipe import Recipe, RecipeImageTypes, ScrapeRecipe
|
||||
from mealie.schema.recipe.recipe import CreateRecipe, CreateRecipeByUrlBulk, RecipeSummary
|
||||
from mealie.schema.recipe.recipe_asset import RecipeAsset
|
||||
from mealie.schema.recipe.recipe_scraper import ScrapeRecipeTest
|
||||
from mealie.schema.recipe.request_helpers import RecipeZipTokenResponse, UpdateImageResponse
|
||||
from mealie.schema.response.responses import ErrorResponse
|
||||
from mealie.schema.server.tasks import ServerTaskNames
|
||||
from mealie.services import urls
|
||||
@ -59,10 +60,6 @@ class RecipeGetAll(GetAll):
|
||||
load_food: bool = False
|
||||
|
||||
|
||||
class UpdateImageResponse(BaseModel):
|
||||
image: str
|
||||
|
||||
|
||||
class FormatResponse(BaseModel):
|
||||
jjson: list[str] = Field(..., alias="json")
|
||||
zip: list[str]
|
||||
@ -81,10 +78,10 @@ class RecipeExportController(BaseRecipeController):
|
||||
def get_recipe_formats_and_templates(self):
|
||||
return TemplateService().templates
|
||||
|
||||
@router_exports.post("/{slug}/exports")
|
||||
@router_exports.post("/{slug}/exports", response_model=RecipeZipTokenResponse)
|
||||
def get_recipe_zip_token(self, slug: str):
|
||||
"""Generates a recipe zip token to be used to download a recipe as a zip file"""
|
||||
return {"token": create_recipe_slug_token(slug)}
|
||||
return RecipeZipTokenResponse(token=create_recipe_slug_token(slug))
|
||||
|
||||
@router_exports.get("/{slug}/exports", response_class=FileResponse)
|
||||
def get_recipe_as_format(self, slug: str, template_name: str, temp_dir=Depends(temporary_dir)):
|
||||
|
@ -5,17 +5,17 @@ from fastapi import HTTPException, status
|
||||
from mealie.core.security import create_access_token
|
||||
from mealie.routes._base import BaseUserController, controller
|
||||
from mealie.routes._base.routers import UserAPIRouter
|
||||
from mealie.schema.user import CreateToken, LoingLiveTokenIn, LongLiveTokenInDB
|
||||
from mealie.schema.user import CreateToken, DeleteTokenResponse, LongLiveTokenIn, LongLiveTokenInDB, LongLiveTokenOut
|
||||
|
||||
router = UserAPIRouter(prefix="/users", tags=["Users: Tokens"])
|
||||
|
||||
|
||||
@controller(router)
|
||||
class UserApiTokensController(BaseUserController):
|
||||
@router.post("/api-tokens", status_code=status.HTTP_201_CREATED)
|
||||
@router.post("/api-tokens", status_code=status.HTTP_201_CREATED, response_model=LongLiveTokenOut)
|
||||
def create_api_token(
|
||||
self,
|
||||
token_name: LoingLiveTokenIn,
|
||||
token_name: LongLiveTokenIn,
|
||||
):
|
||||
"""Create api_token in the Database"""
|
||||
|
||||
@ -33,9 +33,9 @@ class UserApiTokensController(BaseUserController):
|
||||
new_token_in_db = self.repos.api_tokens.create(token_model)
|
||||
|
||||
if new_token_in_db:
|
||||
return {"token": token}
|
||||
return LongLiveTokenOut(token=token)
|
||||
|
||||
@router.delete("/api-tokens/{token_id}")
|
||||
@router.delete("/api-tokens/{token_id}", response_model=DeleteTokenResponse)
|
||||
def delete_api_token(self, token_id: int):
|
||||
"""Delete api_token from the Database"""
|
||||
token: LongLiveTokenInDB = self.repos.api_tokens.get(token_id)
|
||||
@ -45,6 +45,6 @@ class UserApiTokensController(BaseUserController):
|
||||
|
||||
if token.user.email == self.user.email:
|
||||
deleted_token = self.repos.api_tokens.delete(token_id)
|
||||
return {"token_delete": deleted_token.name}
|
||||
return DeleteTokenResponse(token_delete=deleted_token.name)
|
||||
else:
|
||||
raise HTTPException(status.HTTP_403_FORBIDDEN)
|
||||
|
@ -1,6 +1,7 @@
|
||||
# GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
from .about import *
|
||||
from .backup import *
|
||||
from .email import *
|
||||
from .maintenance import *
|
||||
from .migration import *
|
||||
from .restore import *
|
||||
|
@ -28,10 +28,10 @@ class AdminAboutInfo(AppInfo):
|
||||
|
||||
|
||||
class CheckAppConfig(MealieModel):
|
||||
email_ready: bool = False
|
||||
ldap_ready: bool = False
|
||||
base_url_set: bool = False
|
||||
is_up_to_date: bool = False
|
||||
email_ready: bool
|
||||
ldap_ready: bool
|
||||
base_url_set: bool
|
||||
is_up_to_date: bool
|
||||
|
||||
|
||||
class DockerVolumeText(MealieModel):
|
||||
|
14
mealie/schema/admin/email.py
Normal file
14
mealie/schema/admin/email.py
Normal file
@ -0,0 +1,14 @@
|
||||
from mealie.schema._mealie import MealieModel
|
||||
|
||||
|
||||
class EmailReady(MealieModel):
|
||||
ready: bool
|
||||
|
||||
|
||||
class EmailSuccess(MealieModel):
|
||||
success: bool
|
||||
error: str = None
|
||||
|
||||
|
||||
class EmailTest(MealieModel):
|
||||
email: str
|
@ -1,3 +1,5 @@
|
||||
from typing import Optional
|
||||
|
||||
from pydantic import UUID4
|
||||
|
||||
from mealie.schema._mealie import MealieModel
|
||||
@ -8,4 +10,4 @@ from .group_preferences import UpdateGroupPreferences
|
||||
class GroupAdminUpdate(MealieModel):
|
||||
id: UUID4
|
||||
name: str
|
||||
preferences: UpdateGroupPreferences
|
||||
preferences: Optional[UpdateGroupPreferences] = None
|
||||
|
@ -16,7 +16,7 @@ class PlanEntryType(str, Enum):
|
||||
side = "side"
|
||||
|
||||
|
||||
class CreatRandomEntry(MealieModel):
|
||||
class CreateRandomEntry(MealieModel):
|
||||
date: date
|
||||
entry_type: PlanEntryType = PlanEntryType.dinner
|
||||
|
||||
|
@ -26,14 +26,3 @@ class AssignTags(ExportBase):
|
||||
|
||||
class DeleteRecipes(ExportBase):
|
||||
pass
|
||||
|
||||
|
||||
class BulkActionError(MealieModel):
|
||||
recipe: str
|
||||
error: str
|
||||
|
||||
|
||||
class BulkActionsResponse(MealieModel):
|
||||
success: bool
|
||||
message: str
|
||||
errors: list[BulkActionError] = []
|
||||
|
@ -12,3 +12,11 @@ class RecipeSlug(MealieModel):
|
||||
class SlugResponse(BaseModel):
|
||||
class Config:
|
||||
schema_extra = {"example": "adult-mac-and-cheese"}
|
||||
|
||||
|
||||
class UpdateImageResponse(BaseModel):
|
||||
image: str
|
||||
|
||||
|
||||
class RecipeZipTokenResponse(BaseModel):
|
||||
token: str
|
||||
|
@ -2,4 +2,4 @@ from pydantic import BaseModel
|
||||
|
||||
|
||||
class ValidationResponse(BaseModel):
|
||||
valid: bool = False
|
||||
valid: bool
|
||||
|
@ -1,4 +1,3 @@
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional
|
||||
from uuid import UUID
|
||||
@ -18,19 +17,18 @@ from ..recipe import CategoryBase
|
||||
settings = get_app_settings()
|
||||
|
||||
|
||||
class LoingLiveTokenIn(MealieModel):
|
||||
class LongLiveTokenIn(MealieModel):
|
||||
name: str
|
||||
|
||||
|
||||
class LongLiveTokenOut(LoingLiveTokenIn):
|
||||
id: int
|
||||
created_at: datetime
|
||||
class LongLiveTokenOut(MealieModel):
|
||||
token: str
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class CreateToken(LoingLiveTokenIn):
|
||||
class CreateToken(LongLiveTokenIn):
|
||||
user_id: UUID4
|
||||
token: str
|
||||
|
||||
@ -38,6 +36,13 @@ class CreateToken(LoingLiveTokenIn):
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class DeleteTokenResponse(MealieModel):
|
||||
token_delete: str
|
||||
|
||||
class Config:
|
||||
orm_mode = True
|
||||
|
||||
|
||||
class ChangePassword(MealieModel):
|
||||
current_password: str
|
||||
new_password: str
|
||||
|
Loading…
x
Reference in New Issue
Block a user