mirror of
https://github.com/immich-app/immich.git
synced 2025-05-24 01:12:58 -04:00
Implement notification box for web (#533)
* Added test button * styling notification box * Added auto dismission and animation to each notificaiont list * Remove test button
This commit is contained in:
parent
68b1655e7f
commit
f9b1b12b10
@ -0,0 +1,70 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
|
import CloseCircleOutline from 'svelte-material-icons/CloseCircleOutline.svelte';
|
||||||
|
import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
|
||||||
|
|
||||||
|
import {
|
||||||
|
ImmichNotification,
|
||||||
|
notificationList,
|
||||||
|
NotificationType
|
||||||
|
} from '$lib/components/shared-components/notification/notification';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
export let notificationInfo: ImmichNotification;
|
||||||
|
|
||||||
|
let infoPrimaryColor = '#4250AF';
|
||||||
|
let errorPrimaryColor = '#E64132';
|
||||||
|
|
||||||
|
$: icon =
|
||||||
|
notificationInfo.type === NotificationType.Error ? CloseCircleOutline : InformationOutline;
|
||||||
|
|
||||||
|
$: backgroundColor = () => {
|
||||||
|
if (notificationInfo.type === NotificationType.Info) {
|
||||||
|
return '#E0E2F0';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationInfo.type === NotificationType.Error) {
|
||||||
|
return '#FBE8E6';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$: borderStyle = () => {
|
||||||
|
if (notificationInfo.type === NotificationType.Info) {
|
||||||
|
return '1px solid #D8DDFF';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationInfo.type === NotificationType.Error) {
|
||||||
|
return '1px solid #F0E8E7';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$: primaryColor = () => {
|
||||||
|
if (notificationInfo.type === NotificationType.Info) {
|
||||||
|
return infoPrimaryColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationInfo.type === NotificationType.Error) {
|
||||||
|
return errorPrimaryColor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
notificationList.removeNotificationById(notificationInfo.id);
|
||||||
|
}, 2500);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
transition:fade={{ duration: 250 }}
|
||||||
|
style:background-color={backgroundColor()}
|
||||||
|
style:border={borderStyle()}
|
||||||
|
class="min-h-[80px] w-[300px] rounded-2xl z-[999999] shadow-md p-4 mb-4"
|
||||||
|
>
|
||||||
|
<div class="flex gap-2 place-items-center">
|
||||||
|
<svelte:component this={icon} color={primaryColor()} size="20" />
|
||||||
|
<h2 style:color={primaryColor()} class="font-medium">{notificationInfo.type.toString()}</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="text-sm pl-[28px] pr-[16px]">{notificationInfo.message} {notificationInfo.id}</p>
|
||||||
|
</div>
|
@ -0,0 +1,22 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { notificationList } from './notification';
|
||||||
|
import { fade } from 'svelte/transition';
|
||||||
|
|
||||||
|
import NotificationCard from './notification-card.svelte';
|
||||||
|
import { flip } from 'svelte/animate';
|
||||||
|
import { quintOut } from 'svelte/easing';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if $notificationList?.length > 0}
|
||||||
|
<section
|
||||||
|
transition:fade={{ duration: 250 }}
|
||||||
|
id="notification-list"
|
||||||
|
class="absolute right-5 top-[80px] z-[99999999]"
|
||||||
|
>
|
||||||
|
{#each $notificationList as notificationInfo (notificationInfo.id)}
|
||||||
|
<div animate:flip={{ duration: 250, easing: quintOut }}>
|
||||||
|
<NotificationCard {notificationInfo} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</section>
|
||||||
|
{/if}
|
@ -0,0 +1,36 @@
|
|||||||
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
|
export enum NotificationType {
|
||||||
|
Info = 'Info',
|
||||||
|
Error = 'Error'
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ImmichNotification {
|
||||||
|
id = new Date().getTime();
|
||||||
|
type!: NotificationType;
|
||||||
|
message!: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createNotificationList() {
|
||||||
|
const { set, update, subscribe } = writable<ImmichNotification[]>([]);
|
||||||
|
|
||||||
|
const show = ({ message = '', type = NotificationType.Info }) => {
|
||||||
|
const notification = new ImmichNotification();
|
||||||
|
notification.message = message;
|
||||||
|
notification.type = type;
|
||||||
|
|
||||||
|
update((currentList) => [...currentList, notification]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeNotificationById = (id: number) => {
|
||||||
|
update((currentList) => currentList.filter((n) => n.id != id));
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
show,
|
||||||
|
removeNotificationById,
|
||||||
|
subscribe
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const notificationList = createNotificationList();
|
@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
|
||||||
import { AppSideBarSelection } from '$lib/models/admin-sidebar-selection';
|
import { AppSideBarSelection } from '$lib/models/admin-sidebar-selection';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
@ -50,8 +49,8 @@
|
|||||||
isSelected={selectedAction === AppSideBarSelection.ALBUMS}
|
isSelected={selectedAction === AppSideBarSelection.ALBUMS}
|
||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
<!-- Status Box -->
|
|
||||||
|
|
||||||
|
<!-- Status Box -->
|
||||||
<div class="mb-6 mt-auto">
|
<div class="mb-6 mt-auto">
|
||||||
<StatusBox />
|
<StatusBox />
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
const { data: serverInfoRes } = await api.serverInfoApi.getServerInfo();
|
const { data: serverInfoRes } = await api.serverInfoApi.getServerInfo();
|
||||||
serverInfo = serverInfoRes;
|
serverInfo = serverInfoRes;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Error [StatusBox] [pingServerInterval]');
|
console.log('Error [StatusBox] [pingServerInterval]', e);
|
||||||
isServerOk = false;
|
isServerOk = false;
|
||||||
}
|
}
|
||||||
}, 10000);
|
}, 10000);
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { afterNavigate, beforeNavigate } from '$app/navigation';
|
import { afterNavigate, beforeNavigate } from '$app/navigation';
|
||||||
import NavigationLoadingBar from '$lib/components/shared-components/navigation-loading-bar.svelte';
|
import NavigationLoadingBar from '$lib/components/shared-components/navigation-loading-bar.svelte';
|
||||||
|
import NotificationList from '$lib/components/shared-components/notification/notification-list.svelte';
|
||||||
|
|
||||||
let shouldShowAnnouncement: boolean;
|
let shouldShowAnnouncement: boolean;
|
||||||
let localVersion: string;
|
let localVersion: string;
|
||||||
@ -44,7 +45,7 @@
|
|||||||
|
|
||||||
<DownloadPanel />
|
<DownloadPanel />
|
||||||
<UploadPanel />
|
<UploadPanel />
|
||||||
|
<NotificationList />
|
||||||
{#if shouldShowAnnouncement}
|
{#if shouldShowAnnouncement}
|
||||||
<AnnouncementBox
|
<AnnouncementBox
|
||||||
{localVersion}
|
{localVersion}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user