mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-02-11 14:52:01 +08:00
chore: move notifications to lib
This commit is contained in:
parent
c6b91b1f96
commit
b229a34787
@ -1,58 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { ref } from "vue";
|
||||
|
||||
const notificationStore = useNotificationStore();
|
||||
const notifications = ref(notificationStore.notifications);
|
||||
|
||||
//TODO make more responsive: stop removal timer and progress bar on hover
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="fixed h-screen flex bottom-15 right-10 items-end pointer-events-none z-60 text-right">
|
||||
<div>
|
||||
<div v-for="notification in notificationStore.notifications" :key="notification.addedAt" class="mb-3">
|
||||
<div
|
||||
class="rounded-t p-4 pb-2 px-3 pointer-events-auto text-right border-left-5px bg-gray-300 dark:bg-slate-700"
|
||||
:style="{ 'border-color': notification.color }"
|
||||
>
|
||||
<div class="inline-flex items-center">
|
||||
<span class="text-lg mr-2">
|
||||
<IconMdiAlertOutline v-if="notification.color === 'red'" class="text-red-600" />
|
||||
<IconMdiCheck v-else-if="notification.color === 'green'" class="text-lime-600" />
|
||||
<IconMdiInformation v-else-if="notification.color === 'orange'" class="text-red-400" />
|
||||
</span>
|
||||
{{ notification.message }}
|
||||
<IconMdiClose v-if="notification.clearable" class="ml-2 cursor-pointer" @click="notificationStore.remove(notification)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="bar">
|
||||
<div class="progress" :style="'animation-duration: ' + notification.timeout + 'ms'"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.bar {
|
||||
width: 100%;
|
||||
background-color: gray;
|
||||
}
|
||||
|
||||
.progress {
|
||||
height: 5px;
|
||||
background-color: lightblue;
|
||||
animation-name: progress;
|
||||
animation-duration: 7s;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
@keyframes progress {
|
||||
0% {
|
||||
width: 100%;
|
||||
}
|
||||
100% {
|
||||
width: 0;
|
||||
}
|
||||
} ;
|
||||
</style>
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { onMounted } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import { useAuthStore } from "~/store/auth";
|
||||
import Button from "~/lib/components/design/Button.vue";
|
||||
import { useConfig } from "~/lib/composables/useConfig";
|
||||
|
@ -14,7 +14,7 @@ import { useInternalApi } from "~/composables/useApi";
|
||||
import { HangarProject } from "hangar-internal";
|
||||
import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
import { AxiosError } from "axios";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
|
||||
const props = defineProps<{
|
||||
project: HangarProject;
|
||||
|
@ -11,7 +11,7 @@ import { User } from "hangar-api";
|
||||
import { ref } from "vue";
|
||||
import { useRouter } from "vue-router";
|
||||
import InputTextarea from "~/lib/components/ui/InputTextarea.vue";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
|
||||
const props = defineProps<{
|
||||
user: User;
|
||||
|
@ -9,7 +9,7 @@ import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
import InputAutocomplete from "~/lib/components/ui/InputAutocomplete.vue";
|
||||
import { ref } from "vue";
|
||||
import { PaginatedResult, User } from "hangar-api";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
|
||||
const props = defineProps<{
|
||||
organization: string;
|
||||
|
@ -10,7 +10,7 @@ import InputTextarea from "~/lib/components/ui/InputTextarea.vue";
|
||||
import { useInternalApi } from "~/composables/useApi";
|
||||
import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
import { useContext } from "vite-ssr/vue";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import { useRouter } from "vue-router";
|
||||
import { Flag } from "hangar-internal";
|
||||
import { Project } from "hangar-api";
|
||||
|
@ -3,7 +3,7 @@ import { useI18n } from "vue-i18n";
|
||||
import Button from "~/lib/components/design/Button.vue";
|
||||
import Modal from "~/lib/components/modals/Modal.vue";
|
||||
import { ref } from "vue";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import InputText from "~/lib/components/ui/InputText.vue";
|
||||
import { useInternalApi } from "~/composables/useApi";
|
||||
import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
|
@ -10,7 +10,7 @@ import InputTextarea from "~/lib/components/ui/InputTextarea.vue";
|
||||
import { useInternalApi } from "~/composables/useApi";
|
||||
import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
import { useContext } from "vite-ssr/vue";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import { useRouter } from "vue-router";
|
||||
|
||||
const props = defineProps<{
|
||||
|
@ -11,7 +11,7 @@ import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
import { useContext } from "vite-ssr/vue";
|
||||
import Tooltip from "~/lib/components/design/Tooltip.vue";
|
||||
import { useAuthStore } from "~/store/auth";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import FlagModal from "~/components/modals/FlagModal.vue";
|
||||
import Alert from "~/lib/components/design/Alert.vue";
|
||||
import { hasPerms } from "~/composables/usePerm";
|
||||
|
@ -2,7 +2,7 @@ import { AxiosError } from "axios";
|
||||
import { HangarApiException, HangarValidationException, MultiHangarApiException } from "hangar-api";
|
||||
import { Composer, VueMessageType } from "vue-i18n";
|
||||
import { Context } from "vite-ssr/vue";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
|
||||
export function handleRequestError(
|
||||
err: AxiosError,
|
||||
|
@ -2,7 +2,7 @@
|
||||
import Header from "~/components/layout/Header.vue";
|
||||
import Footer from "~/components/layout/Footer.vue";
|
||||
import Container from "~/lib/components/design/Container.vue";
|
||||
import Notifications from "~/components/Notifications.vue";
|
||||
import Notifications from "~/lib/components/design/Notifications.vue";
|
||||
import { computed } from "vue";
|
||||
import { useRoute } from "vue-router";
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import Header from "~/components/layout/Header.vue";
|
||||
import Footer from "~/components/layout/Footer.vue";
|
||||
import Notifications from "~/components/Notifications.vue";
|
||||
import Notifications from "~/lib/components/design/Notifications.vue";
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit de3ffee1c3f34c1f806bf41d0d5e5cedfbff52fe
|
||||
Subproject commit ec51c259360015f4d905bbcb2b97c9a1ed55e7a4
|
@ -19,7 +19,7 @@ import { useSeo } from "~/composables/useSeo";
|
||||
import { projectIconUrl } from "~/composables/useUrlHelper";
|
||||
import { useRoute } from "vue-router";
|
||||
import Tooltip from "~/lib/components/design/Tooltip.vue";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import InputRadio from "~/lib/components/ui/InputRadio.vue";
|
||||
import { ref } from "vue";
|
||||
|
||||
|
@ -21,7 +21,7 @@ import InputFile from "~/lib/components/ui/InputFile.vue";
|
||||
import { useApi, useInternalApi } from "~/composables/useApi";
|
||||
import { handleRequestError } from "~/composables/useErrorHandling";
|
||||
import { useContext } from "vite-ssr/vue";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import InputTag from "~/lib/components/ui/InputTag.vue";
|
||||
import TextAreaModal from "~/lib/components/modals/TextAreaModal.vue";
|
||||
import ProjectSettingsSection from "~/components/projects/ProjectSettingsSection.vue";
|
||||
|
@ -21,7 +21,7 @@ import Link from "~/lib/components/design/Link.vue";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { useSeo } from "~/composables/useSeo";
|
||||
import { projectIconUrl } from "~/composables/useUrlHelper";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import DropdownButton from "~/lib/components/design/DropdownButton.vue";
|
||||
import DropdownItem from "~/lib/components/design/DropdownItem.vue";
|
||||
import PlatformVersionEditModal from "~/components/modals/PlatformVersionEditModal.vue";
|
||||
|
@ -16,7 +16,7 @@ import Card from "~/lib/components/design/Card.vue";
|
||||
import { useSeo } from "~/composables/useSeo";
|
||||
import { avatarUrl } from "~/composables/useUrlHelper";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import { maxLength, minLength, required } from "~/lib/composables/useValidationHelpers";
|
||||
import { validApiKeyName } from "~/composables/useHangarValidations";
|
||||
import { useVuelidate } from "@vuelidate/core";
|
||||
|
@ -14,7 +14,7 @@ import Card from "~/lib/components/design/Card.vue";
|
||||
import Table from "~/lib/components/design/Table.vue";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { useSeo } from "~/composables/useSeo";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
|
||||
const ctx = useContext();
|
||||
const i18n = useI18n();
|
||||
|
@ -9,7 +9,7 @@ import { computed, ref, Ref } from "vue";
|
||||
import { useInternalApi } from "~/composables/useApi";
|
||||
import { useSeo } from "~/composables/useSeo";
|
||||
import { useHead } from "@vueuse/head";
|
||||
import { useNotificationStore } from "~/store/notification";
|
||||
import { useNotificationStore } from "~/lib/store/notification";
|
||||
import Card from "~/lib/components/design/Card.vue";
|
||||
import Button from "~/lib/components/design/Button.vue";
|
||||
import { lastUpdated } from "~/lib/composables/useTime";
|
||||
|
@ -1,46 +0,0 @@
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
|
||||
export interface Notification {
|
||||
color?: string;
|
||||
timeout?: number;
|
||||
message: string;
|
||||
clearable: boolean;
|
||||
addedAt: number;
|
||||
}
|
||||
|
||||
function waitTimeout(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
const defaultTimeout = 7_000;
|
||||
export const useNotificationStore = defineStore("notification", () => {
|
||||
const notifications = ref<Set<Notification>>(new Set<Notification>());
|
||||
|
||||
async function show(notification: Notification) {
|
||||
notifications.value.add(notification);
|
||||
if (notification.timeout === -1) {
|
||||
return;
|
||||
}
|
||||
await waitTimeout(notification.timeout || defaultTimeout);
|
||||
remove(notification);
|
||||
}
|
||||
|
||||
async function success(message: string, clearable = true, timeout = defaultTimeout) {
|
||||
await show({ message, color: "green", clearable, timeout, addedAt: Date.now() });
|
||||
}
|
||||
|
||||
async function error(message: string, clearable = true, timeout = defaultTimeout) {
|
||||
await show({ message, color: "red", clearable, timeout, addedAt: Date.now() });
|
||||
}
|
||||
|
||||
async function warn(message: string, clearable = true, timeout = defaultTimeout) {
|
||||
await show({ message, color: "orange", clearable, timeout, addedAt: Date.now() });
|
||||
}
|
||||
|
||||
function remove(notification: Notification) {
|
||||
notifications.value.delete(notification);
|
||||
}
|
||||
|
||||
return { notifications, show, remove, success, error, warn };
|
||||
});
|
Loading…
Reference in New Issue
Block a user