mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-06-22 06:51:35 -04:00
events api
This commit is contained in:
parent
6d3a06e1b9
commit
7d40f8d74d
@ -0,0 +1,42 @@
|
|||||||
|
import { requests } from "../requests";
|
||||||
|
import { BaseCRUDAPI } from "./_base";
|
||||||
|
|
||||||
|
export type EventCategory = "general" | "recipe" | "backup" | "scheduled" | "migration" | "group" | "user";
|
||||||
|
export type DeclaredTypes = "General" | "Discord" | "Gotify" | "Pushover" | "Home Assistant";
|
||||||
|
export type GotifyPriority = "low" | "moderate" | "normal" | "high";
|
||||||
|
|
||||||
|
export interface EventNotification {
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
type?: DeclaredTypes & string;
|
||||||
|
general?: boolean;
|
||||||
|
recipe?: boolean;
|
||||||
|
backup?: boolean;
|
||||||
|
scheduled?: boolean;
|
||||||
|
migration?: boolean;
|
||||||
|
group?: boolean;
|
||||||
|
user?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateEventNotification extends EventNotification {
|
||||||
|
notificationUrl?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const prefix = "/api";
|
||||||
|
|
||||||
|
const routes = {
|
||||||
|
aboutEventsNotifications: `${prefix}/about/events/notifications`,
|
||||||
|
aboutEventsNotificationsTest: `${prefix}/about/events/notifications/test`,
|
||||||
|
|
||||||
|
aboutEventsNotificationsId: (id: number) => `${prefix}/about/events/notifications/${id}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export class NotificationsAPI extends BaseCRUDAPI<EventNotification, CreateEventNotification> {
|
||||||
|
baseRoute = routes.aboutEventsNotifications;
|
||||||
|
itemRoute = routes.aboutEventsNotificationsId;
|
||||||
|
/** Returns the Group Data for the Current User
|
||||||
|
*/
|
||||||
|
async testNotification(id: number) {
|
||||||
|
return await requests.post(routes.aboutEventsNotificationsTest, { id });
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ import { UploadFile } from "./class-interfaces/upload";
|
|||||||
import { CategoriesAPI } from "./class-interfaces/categories";
|
import { CategoriesAPI } from "./class-interfaces/categories";
|
||||||
import { TagsAPI } from "./class-interfaces/tags";
|
import { TagsAPI } from "./class-interfaces/tags";
|
||||||
import { UtilsAPI } from "./class-interfaces/utils";
|
import { UtilsAPI } from "./class-interfaces/utils";
|
||||||
|
import { NotificationsAPI } from "./class-interfaces/event-notifications";
|
||||||
import { ApiRequestInstance } from "~/types/api";
|
import { ApiRequestInstance } from "~/types/api";
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
@ -21,6 +22,7 @@ class Api {
|
|||||||
public categories: CategoriesAPI;
|
public categories: CategoriesAPI;
|
||||||
public tags: TagsAPI;
|
public tags: TagsAPI;
|
||||||
public utils: UtilsAPI;
|
public utils: UtilsAPI;
|
||||||
|
public notifications: NotificationsAPI;
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
public upload: UploadFile;
|
public upload: UploadFile;
|
||||||
@ -43,6 +45,7 @@ class Api {
|
|||||||
this.debug = new DebugAPI(requests);
|
this.debug = new DebugAPI(requests);
|
||||||
this.events = new EventsAPI(requests);
|
this.events = new EventsAPI(requests);
|
||||||
this.backups = new BackupAPI(requests);
|
this.backups = new BackupAPI(requests);
|
||||||
|
this.notifications = new NotificationsAPI(requests);
|
||||||
|
|
||||||
// Utils
|
// Utils
|
||||||
this.upload = new UploadFile(requests);
|
this.upload = new UploadFile(requests);
|
||||||
|
88
frontend/composables/use-notifications.ts
Normal file
88
frontend/composables/use-notifications.ts
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import { useAsync, ref } from "@nuxtjs/composition-api";
|
||||||
|
import { CreateEventNotification } from "@/api/class-interfaces/event-notifications";
|
||||||
|
import { useAsyncKey } from "./use-utils";
|
||||||
|
import { useApiSingleton } from "~/composables/use-api";
|
||||||
|
|
||||||
|
const notificationTypes = ["General", "Discord", "Gotify", "Pushover", "Home Assistant"];
|
||||||
|
|
||||||
|
|
||||||
|
export const useNotifications = function () {
|
||||||
|
const api = useApiSingleton();
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
const createNotificationData = ref<CreateEventNotification>({
|
||||||
|
name: "",
|
||||||
|
type: "General",
|
||||||
|
general: true,
|
||||||
|
recipe: true,
|
||||||
|
backup: true,
|
||||||
|
scheduled: true,
|
||||||
|
migration: true,
|
||||||
|
group: true,
|
||||||
|
user: true,
|
||||||
|
notificationUrl: "",
|
||||||
|
});
|
||||||
|
|
||||||
|
const deleteTarget = ref(0)
|
||||||
|
|
||||||
|
function getNotifications() {
|
||||||
|
loading.value = true;
|
||||||
|
const notifications = useAsync(async () => {
|
||||||
|
const { data } = await api.notifications.getAll();
|
||||||
|
return data;
|
||||||
|
}, useAsyncKey());
|
||||||
|
loading.value = false;
|
||||||
|
return notifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refreshNotifications() {
|
||||||
|
loading.value = true;
|
||||||
|
const { data } = await api.notifications.getAll();
|
||||||
|
if (data) {
|
||||||
|
notifications.value = data;
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function createNotification() {
|
||||||
|
if (createNotificationData.value.name === "" || createNotificationData.value.notificationUrl === "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { response } = await api.notifications.createOne(createNotificationData.value);
|
||||||
|
|
||||||
|
if (response?.status === 200) {
|
||||||
|
refreshNotifications();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteNotification() {
|
||||||
|
const { response } = await api.notifications.deleteOne(deleteTarget.value);
|
||||||
|
if (response?.status === 200) {
|
||||||
|
refreshNotifications();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testById() {
|
||||||
|
// TODO: Test by ID
|
||||||
|
}
|
||||||
|
|
||||||
|
async function testByUrl() {
|
||||||
|
// TODO: Test by URL
|
||||||
|
}
|
||||||
|
|
||||||
|
const notifications = getNotifications();
|
||||||
|
|
||||||
|
return {
|
||||||
|
createNotification,
|
||||||
|
deleteNotification,
|
||||||
|
refreshNotifications,
|
||||||
|
getNotifications,
|
||||||
|
testById,
|
||||||
|
testByUrl,
|
||||||
|
notifications,
|
||||||
|
loading,
|
||||||
|
createNotificationData,
|
||||||
|
notificationTypes,
|
||||||
|
deleteTarget,
|
||||||
|
};
|
||||||
|
};
|
@ -2,17 +2,213 @@
|
|||||||
<v-container fluid>
|
<v-container fluid>
|
||||||
<BaseCardSectionTitle title="Event Notifications">
|
<BaseCardSectionTitle title="Event Notifications">
|
||||||
{{ $t("events.new-notification-form-description") }}
|
{{ $t("events.new-notification-form-description") }}
|
||||||
|
|
||||||
|
<div class="d-flex justify-space-around">
|
||||||
|
<a href="https://github.com/caronc/apprise/wiki" target="_blanks"> Apprise </a>
|
||||||
|
<a href="https://github.com/caronc/apprise/wiki/Notify_gotify" target="_blanks"> Gotify </a>
|
||||||
|
<a href="https://github.com/caronc/apprise/wiki/Notify_discord" target="_blanks"> Discord </a>
|
||||||
|
<a href="https://github.com/caronc/apprise/wiki/Notify_homeassistant" target="_blanks"> Home Assistant </a>
|
||||||
|
<a href="https://github.com/caronc/apprise/wiki/Notify_matrix" target="_blanks"> Matrix </a>
|
||||||
|
<a href="https://github.com/caronc/apprise/wiki/Notify_pushover" target="_blanks"> Pushover </a>
|
||||||
|
</div>
|
||||||
</BaseCardSectionTitle>
|
</BaseCardSectionTitle>
|
||||||
|
|
||||||
|
<BaseDialog
|
||||||
|
ref="domDeleteConfirmation"
|
||||||
|
:title="$t('settings.backup.delete-backup')"
|
||||||
|
color="error"
|
||||||
|
:icon="$globals.icons.alertCircle"
|
||||||
|
@confirm="deleteNotification()"
|
||||||
|
>
|
||||||
|
<v-card-text>
|
||||||
|
{{ $t("general.confirm-delete-generic") }}
|
||||||
|
</v-card-text>
|
||||||
|
</BaseDialog>
|
||||||
|
|
||||||
|
<v-toolbar flat class="justify-between">
|
||||||
|
<BaseDialog
|
||||||
|
:icon="$globals.icons.bellAlert"
|
||||||
|
:title="$t('general.new') + ' ' + $t('events.notification')"
|
||||||
|
@submit="createNotification"
|
||||||
|
>
|
||||||
|
<template #activator="{ open }">
|
||||||
|
<BaseButton @click="open"> {{ $t("events.notification") }}</BaseButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<v-card-text>
|
||||||
|
<v-select
|
||||||
|
v-model="createNotificationData.type"
|
||||||
|
:items="notificationTypes"
|
||||||
|
:label="$t('general.type')"
|
||||||
|
></v-select>
|
||||||
|
<v-text-field v-model="createNotificationData.name" :label="$t('general.name')"></v-text-field>
|
||||||
|
<v-text-field
|
||||||
|
v-model="createNotificationData.notificationUrl"
|
||||||
|
:label="$t('events.apprise-url')"
|
||||||
|
></v-text-field>
|
||||||
|
|
||||||
|
<BaseButton class="d-flex ml-auto" small color="info" @click="testByUrl(newNotification.notificationUrl)">
|
||||||
|
<template #icon> {{ $globals.icons.testTube }}</template>
|
||||||
|
{{ $t("general.test") }}
|
||||||
|
</BaseButton>
|
||||||
|
|
||||||
|
<p class="text-uppercase">{{ $t("events.subscribed-events") }}</p>
|
||||||
|
<div class="d-flex flex-wrap justify-center">
|
||||||
|
<v-checkbox
|
||||||
|
v-model="createNotificationData.general"
|
||||||
|
class="mb-n2 mt-n2 mx-2"
|
||||||
|
:label="$t('general.general')"
|
||||||
|
></v-checkbox>
|
||||||
|
<v-checkbox
|
||||||
|
v-model="createNotificationData.recipe"
|
||||||
|
class="mb-n2 mt-n2 mx-2"
|
||||||
|
:label="$t('general.recipe')"
|
||||||
|
></v-checkbox>
|
||||||
|
<v-checkbox
|
||||||
|
v-model="createNotificationData.backup"
|
||||||
|
class="mb-n2 mt-n2 mx-2"
|
||||||
|
:label="$t('settings.backup-and-exports')"
|
||||||
|
></v-checkbox>
|
||||||
|
<v-checkbox
|
||||||
|
v-model="createNotificationData.scheduled"
|
||||||
|
class="mb-n2 mt-n2 mx-2"
|
||||||
|
:label="$t('events.scheduled')"
|
||||||
|
></v-checkbox>
|
||||||
|
<v-checkbox
|
||||||
|
v-model="createNotificationData.migration"
|
||||||
|
class="mb-n2 mt-n2 mx-2"
|
||||||
|
:label="$t('settings.migrations')"
|
||||||
|
></v-checkbox>
|
||||||
|
<v-checkbox
|
||||||
|
v-model="createNotificationData.group"
|
||||||
|
class="mb-n2 mt-n2 mx-2"
|
||||||
|
:label="$t('group.group')"
|
||||||
|
></v-checkbox>
|
||||||
|
<v-checkbox
|
||||||
|
v-model="createNotificationData.user"
|
||||||
|
class="mb-n2 mt-n2 mx-2"
|
||||||
|
:label="$t('user.user')"
|
||||||
|
></v-checkbox>
|
||||||
|
</div>
|
||||||
|
</v-card-text>
|
||||||
|
</BaseDialog>
|
||||||
|
</v-toolbar>
|
||||||
|
|
||||||
|
<!-- Data Table -->
|
||||||
|
<v-data-table
|
||||||
|
:headers="headers"
|
||||||
|
:items="notifications || []"
|
||||||
|
class="elevation-0"
|
||||||
|
hide-default-footer
|
||||||
|
disable-pagination
|
||||||
|
>
|
||||||
|
<template v-for="boolHeader in headers" #[`item.${boolHeader.value}`]="{ item }">
|
||||||
|
<div :key="boolHeader.value">
|
||||||
|
<div v-if="boolHeader.value === 'type'">
|
||||||
|
{{ item[boolHeader.value] }}
|
||||||
|
</div>
|
||||||
|
<v-icon
|
||||||
|
v-else-if="item[boolHeader.value] === true || item[boolHeader.value] === false"
|
||||||
|
:color="item[boolHeader.value] ? 'success' : 'gray'"
|
||||||
|
>
|
||||||
|
{{ item[boolHeader.value] ? $globals.icons.check : $globals.icons.close }}
|
||||||
|
</v-icon>
|
||||||
|
<div v-else-if="boolHeader.value === 'actions'" class="d-flex">
|
||||||
|
<BaseButton
|
||||||
|
class="mr-1"
|
||||||
|
delete
|
||||||
|
x-small
|
||||||
|
minor
|
||||||
|
@click="
|
||||||
|
deleteTarget = item.id;
|
||||||
|
domDeleteConfirmation.open();
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
<BaseButton edit x-small @click="testById(item.id)">
|
||||||
|
<template #icon>
|
||||||
|
{{ $globals.icons.testTube }}
|
||||||
|
</template>
|
||||||
|
{{ $t("general.test") }}
|
||||||
|
</BaseButton>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
|
{{ item[boolHeader.value] }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v-data-table>
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "@nuxtjs/composition-api";
|
import { defineComponent, reactive, useContext, toRefs, ref } from "@nuxtjs/composition-api";
|
||||||
|
import { useNotifications } from "@/composables/use-notifications";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
layout: "admin",
|
layout: "admin",
|
||||||
setup() {
|
setup() {
|
||||||
return {};
|
// @ts-ignore -> Ignore missing $globals
|
||||||
|
const { i18n } = useContext();
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
headers: [
|
||||||
|
{ text: i18n.t("general.type"), value: "type" },
|
||||||
|
{ text: i18n.t("general.name"), value: "name" },
|
||||||
|
{ text: i18n.t("general.general"), value: "general", align: "center" },
|
||||||
|
{ text: i18n.t("general.recipe"), value: "recipe", align: "center" },
|
||||||
|
{ text: i18n.t("events.database"), value: "backup", align: "center" },
|
||||||
|
{ text: i18n.t("events.scheduled"), value: "scheduled", align: "center" },
|
||||||
|
{ text: i18n.t("settings.migrations"), value: "migration", align: "center" },
|
||||||
|
{ text: i18n.t("group.group"), value: "group", align: "center" },
|
||||||
|
{ text: i18n.t("user.user"), value: "user", align: "center" },
|
||||||
|
{ text: "", value: "actions" },
|
||||||
|
],
|
||||||
|
keepDialogOpen: false,
|
||||||
|
notifications: [],
|
||||||
|
newNotification: {
|
||||||
|
type: "General",
|
||||||
|
name: "",
|
||||||
|
notificationUrl: "",
|
||||||
|
},
|
||||||
|
newNotificationOptions: {
|
||||||
|
general: true,
|
||||||
|
recipe: true,
|
||||||
|
backup: true,
|
||||||
|
scheduled: true,
|
||||||
|
migration: true,
|
||||||
|
group: true,
|
||||||
|
user: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const {
|
||||||
|
deleteNotification,
|
||||||
|
createNotification,
|
||||||
|
refreshNotifications,
|
||||||
|
notifications,
|
||||||
|
loading,
|
||||||
|
testById,
|
||||||
|
testByUrl,
|
||||||
|
createNotificationData,
|
||||||
|
notificationTypes,
|
||||||
|
deleteTarget,
|
||||||
|
} = useNotifications();
|
||||||
|
|
||||||
|
// API
|
||||||
|
const domDeleteConfirmation = ref(null);
|
||||||
|
return {
|
||||||
|
...toRefs(state),
|
||||||
|
domDeleteConfirmation,
|
||||||
|
notifications,
|
||||||
|
loading,
|
||||||
|
createNotificationData,
|
||||||
|
deleteNotification,
|
||||||
|
deleteTarget,
|
||||||
|
createNotification,
|
||||||
|
refreshNotifications,
|
||||||
|
testById,
|
||||||
|
testByUrl,
|
||||||
|
notificationTypes,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user