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

refactor(frontend): 🚧 Migrate Dashboard to Nuxt

Add API and Functinality for Admin Dashboard. Stills needs to clean-up. See // TODO's
This commit is contained in:
hay-kot 2021-08-07 15:12:25 -08:00
parent 41a6916771
commit 9386cc320b
32 changed files with 671 additions and 113 deletions

View file

@ -44,15 +44,17 @@ export const crudMixins = <T>(
return { getAll, getOne, updateOne, patchOne, deleteOne, createOne };
};
export abstract class BaseAPIClass<T, U> implements CrudAPIInterface {
export abstract class BaseAPI {
requests: ApiRequestInstance;
abstract baseRoute: string;
abstract itemRoute(itemId: string | number): string;
constructor(requests: ApiRequestInstance) {
this.requests = requests;
}
}
export abstract class BaseCRUDAPI<T, U> extends BaseAPI implements CrudAPIInterface {
abstract baseRoute: string;
abstract itemRoute(itemId: string | number): string;
async getAll(start = 0, limit = 9999) {
return await this.requests.get<T[]>(this.baseRoute, {

View file

@ -0,0 +1,69 @@
import { BaseAPI } from "./_base";
export interface BackupOptions {
recipes?: boolean;
settings?: boolean;
pages?: boolean;
themes?: boolean;
groups?: boolean;
users?: boolean;
notifications?: boolean;
}
export interface ImportBackup extends BackupOptions {
name: string;
}
export interface BackupJob {
tag?: string;
options: BackupOptions;
templates?: string[];
}
export interface BackupFile {
name: string;
date: string;
}
export interface AllBackups {
imports: BackupFile[];
templates: string[];
}
const prefix = "/api";
const routes = {
backupsAvailable: `${prefix}/backups/available`,
backupsExportDatabase: `${prefix}/backups/export/database`,
backupsUpload: `${prefix}/backups/upload`,
backupsFileNameDownload: (fileName: string) => `${prefix}/backups/${fileName}/download`,
backupsFileNameImport: (fileName: string) => `${prefix}/backups/${fileName}/import`,
backupsFileNameDelete: (fileName: string) => `${prefix}/backups/${fileName}/delete`,
};
export class BackupAPI extends BaseAPI {
/** Returns a list of avaiable .zip files for import into Mealie.
*/
async getAll() {
return await this.requests.get<AllBackups>(routes.backupsAvailable);
}
/** Generates a backup of the recipe database in json format.
*/
async createOne(payload: BackupJob) {
return await this.requests.post(routes.backupsExportDatabase, payload);
}
/** Import a database backup file generated from Mealie.
*/
async restoreDatabase(fileName: string, payload: BackupOptions) {
return await this.requests.post(routes.backupsFileNameImport(fileName), payload);
}
/** Removes a database backup from the file system
*/
async deleteOne(fileName: string) {
return await this.requests.delete(routes.backupsFileNameDelete(fileName));
}
}

View file

@ -0,0 +1,51 @@
import { BaseAPI } from "./_base";
export interface AppStatistics {
totalRecipes: number;
totalUsers: number;
totalGroups: number;
uncategorizedRecipes: number;
untaggedRecipes: number;
}
const prefix = "/api";
const routes = {
debugVersion: `${prefix}/debug/version`,
debug: `${prefix}/debug`,
debugStatistics: `${prefix}/debug/statistics`,
debugLastRecipeJson: `${prefix}/debug/last-recipe-json`,
debugLog: `${prefix}/debug/log`,
debugLogNum: (num: number) => `${prefix}/debug/log/${num}`,
};
export class DebugAPI extends BaseAPI {
/** Returns the current version of mealie
*/
async getMealieVersion() {
return await this.requests.get(routes.debugVersion);
}
/** Returns general information about the application for debugging
*/
async getDebugInfo() {
return await this.requests.get(routes.debug);
}
async getAppStatistics() {
return await this.requests.get<AppStatistics>(routes.debugStatistics);
}
/** Doc Str
*/
async getLog(num: number) {
return await this.requests.get(routes.debugLogNum(num));
}
/** Returns a token to download a file
*/
async getLogFile() {
return await this.requests.get(routes.debugLog);
}
}

View file

@ -0,0 +1,49 @@
import { BaseAPI } from "./_base";
export type EventCategory = "general" | "recipe" | "backup" | "scheduled" | "migration" | "group" | "user";
export interface Event {
id?: number;
title: string;
text: string;
timeStamp?: string;
category?: EventCategory & string;
}
export interface EventsOut {
total: number;
events: Event[];
}
const prefix = "/api";
const routes = {
aboutEvents: `${prefix}/about/events`,
aboutEventsNotifications: `${prefix}/about/events/notifications`,
aboutEventsNotificationsTest: `${prefix}/about/events/notifications/test`,
aboutEventsId: (id: number) => `${prefix}/about/events/${id}`,
aboutEventsNotificationsId: (id: number) => `${prefix}/about/events/notifications/${id}`,
};
export class EventsAPI extends BaseAPI {
/** Get event from the Database
*/
async getEvents() {
return await this.requests.get<EventsOut>(routes.aboutEvents);
}
/** Get event from the Database
*/
async deleteEvents() {
return await this.requests.delete(routes.aboutEvents);
}
/** Delete event from the Database
*/
async deleteEvent(id: number) {
return await this.requests.delete(routes.aboutEventsId(id));
}
/** Get all event_notification from the Database
*/
}

View file

@ -1,5 +1,5 @@
import { requests } from "../requests";
import { BaseAPIClass } from "./_base";
import { BaseCRUDAPI } from "./_base";
import { GroupInDB } from "~/types/api-types/user";
const prefix = "/api";
@ -15,7 +15,7 @@ export interface CreateGroup {
name: string;
}
export class GroupAPI extends BaseAPIClass<GroupInDB, CreateGroup> {
export class GroupAPI extends BaseCRUDAPI<GroupInDB, CreateGroup> {
baseRoute = routes.groups;
itemRoute = routes.groupsId;
/** Returns the Group Data for the Current User

View file

@ -1,4 +1,4 @@
import { BaseAPIClass } from "./_base";
import { BaseCRUDAPI } from "./_base";
import { Recipe } from "~/types/api-types/admin";
import { CreateRecipe } from "~/types/api-types/recipe";
@ -18,7 +18,7 @@ const routes = {
recipesRecipeSlugAssets: (recipe_slug: string) => `${prefix}/recipes/${recipe_slug}/assets`,
};
export class RecipeAPI extends BaseAPIClass<Recipe, CreateRecipe> {
export class RecipeAPI extends BaseCRUDAPI<Recipe, CreateRecipe> {
baseRoute: string = routes.recipesBase;
itemRoute = routes.recipesRecipeSlug;
@ -31,6 +31,7 @@ export class RecipeAPI extends BaseAPIClass<Recipe, CreateRecipe> {
updateImage(slug: string, fileObject: File) {
const formData = new FormData();
formData.append("image", fileObject);
// @ts-ignore
formData.append("extension", fileObject.name.split(".").pop());
return this.requests.put<any>(routes.recipesRecipeSlugImage(slug), formData);

View file

@ -0,0 +1,7 @@
import { BaseAPI } from "./_base";
export class UploadFile extends BaseAPI {
file(url: string, fileObject: any) {
return this.requests.post(url, fileObject);
}
}

View file

@ -1,4 +1,4 @@
import { BaseAPIClass } from "./_base";
import { BaseCRUDAPI } from "./_base";
import { UserIn, UserOut } from "~/types/api-types/user";
// Interfaces
@ -31,7 +31,7 @@ const routes = {
usersApiTokensTokenId: (token_id: string) => `${prefix}/users/api-tokens/${token_id}`,
};
export class UserApi extends BaseAPIClass<UserOut, UserIn> {
export class UserApi extends BaseCRUDAPI<UserOut, UserIn> {
baseRoute: string = routes.users;
itemRoute = (itemid: string) => routes.usersId(itemid);