chore: move notifications to lib

This commit is contained in:
MiniDigger | Martin 2022-10-31 10:48:06 +01:00
parent c6b91b1f96
commit b229a34787
20 changed files with 18 additions and 122 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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