chore(web): prettier (#2821)

Co-authored-by: Thomas Way <thomas@6f.io>
This commit is contained in:
Jason Rasmussen 2023-07-01 00:50:47 -04:00 committed by GitHub
parent 7c2f7d6c51
commit f55b3add80
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
242 changed files with 12794 additions and 13426 deletions

View file

@ -1,41 +1,41 @@
import { jest, describe, it } from '@jest/globals';
import { render, cleanup, RenderResult } from '@testing-library/svelte';
import { describe, it, jest } from '@jest/globals';
import '@testing-library/jest-dom';
import { cleanup, render, RenderResult } from '@testing-library/svelte';
import { NotificationType } from '../notification';
import NotificationCard from '../notification-card.svelte';
import '@testing-library/jest-dom';
describe('NotificationCard component', () => {
let sut: RenderResult<NotificationCard>;
let sut: RenderResult<NotificationCard>;
it('disposes timeout if already removed from the DOM', () => {
jest.spyOn(window, 'clearTimeout');
it('disposes timeout if already removed from the DOM', () => {
jest.spyOn(window, 'clearTimeout');
sut = render(NotificationCard, {
notificationInfo: {
id: 1234,
message: 'Notification message',
timeout: 1000,
type: NotificationType.Info,
action: { type: 'discard' }
}
});
sut = render(NotificationCard, {
notificationInfo: {
id: 1234,
message: 'Notification message',
timeout: 1000,
type: NotificationType.Info,
action: { type: 'discard' },
},
});
cleanup();
expect(window.clearTimeout).toHaveBeenCalledTimes(1);
});
cleanup();
expect(window.clearTimeout).toHaveBeenCalledTimes(1);
});
it('shows message and title', () => {
sut = render(NotificationCard, {
notificationInfo: {
id: 1234,
message: 'Notification message',
timeout: 1000,
type: NotificationType.Info,
action: { type: 'discard' }
}
});
it('shows message and title', () => {
sut = render(NotificationCard, {
notificationInfo: {
id: 1234,
message: 'Notification message',
timeout: 1000,
type: NotificationType.Info,
action: { type: 'discard' },
},
});
expect(sut.getByTestId('title')).toHaveTextContent('Info');
expect(sut.getByTestId('message')).toHaveTextContent('Notification message');
});
expect(sut.getByTestId('title')).toHaveTextContent('Info');
expect(sut.getByTestId('message')).toHaveTextContent('Notification message');
});
});

View file

@ -1,44 +1,42 @@
import { jest, describe, it } from '@jest/globals';
import { render, RenderResult, waitFor } from '@testing-library/svelte';
import { notificationController, NotificationType } from '../notification';
import { get } from 'svelte/store';
import NotificationList from '../notification-list.svelte';
import { describe, it, jest } from '@jest/globals';
import '@testing-library/jest-dom';
import { render, RenderResult, waitFor } from '@testing-library/svelte';
import { get } from 'svelte/store';
import { notificationController, NotificationType } from '../notification';
import NotificationList from '../notification-list.svelte';
function _getNotificationListElement(
sut: RenderResult<NotificationList>
): HTMLAnchorElement | null {
return sut.container.querySelector('#notification-list');
function _getNotificationListElement(sut: RenderResult<NotificationList>): HTMLAnchorElement | null {
return sut.container.querySelector('#notification-list');
}
describe('NotificationList component', () => {
const sut: RenderResult<NotificationList> = render(NotificationList);
const sut: RenderResult<NotificationList> = render(NotificationList);
beforeAll(() => {
jest.useFakeTimers();
});
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
});
afterAll(() => {
jest.useRealTimers();
});
it('shows a notification when added and closes it automatically after the delay timeout', async () => {
expect(_getNotificationListElement(sut)).not.toBeInTheDocument();
it('shows a notification when added and closes it automatically after the delay timeout', async () => {
expect(_getNotificationListElement(sut)).not.toBeInTheDocument();
notificationController.show({
message: 'Notification',
type: NotificationType.Info,
timeout: 3000
});
notificationController.show({
message: 'Notification',
type: NotificationType.Info,
timeout: 3000,
});
await waitFor(() => expect(_getNotificationListElement(sut)).toBeInTheDocument());
await waitFor(() => expect(_getNotificationListElement(sut)).toBeInTheDocument());
expect(_getNotificationListElement(sut)?.children).toHaveLength(1);
expect(_getNotificationListElement(sut)?.children).toHaveLength(1);
jest.advanceTimersByTime(3000);
// due to some weirdness in svelte (or testing-library) need to check if it has been removed from the store to make sure it works.
expect(get(notificationController.notificationList)).toHaveLength(0);
jest.advanceTimersByTime(3000);
// due to some weirdness in svelte (or testing-library) need to check if it has been removed from the store to make sure it works.
expect(get(notificationController.notificationList)).toHaveLength(0);
await waitFor(() => expect(_getNotificationListElement(sut)).not.toBeInTheDocument());
});
await waitFor(() => expect(_getNotificationListElement(sut)).not.toBeInTheDocument());
});
});

View file

@ -1,96 +1,95 @@
<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 WindowClose from 'svelte-material-icons/WindowClose.svelte';
import { fade } from 'svelte/transition';
import CloseCircleOutline from 'svelte-material-icons/CloseCircleOutline.svelte';
import InformationOutline from 'svelte-material-icons/InformationOutline.svelte';
import WindowClose from 'svelte-material-icons/WindowClose.svelte';
import {
ImmichNotification,
notificationController,
NotificationType
} from '$lib/components/shared-components/notification/notification';
import { onMount } from 'svelte';
import {
ImmichNotification,
notificationController,
NotificationType,
} from '$lib/components/shared-components/notification/notification';
import { onMount } from 'svelte';
export let notificationInfo: ImmichNotification;
export let notificationInfo: ImmichNotification;
let infoPrimaryColor = '#4250AF';
let errorPrimaryColor = '#E64132';
let infoPrimaryColor = '#4250AF';
let errorPrimaryColor = '#E64132';
$: icon =
notificationInfo.type === NotificationType.Error ? CloseCircleOutline : InformationOutline;
$: icon = notificationInfo.type === NotificationType.Error ? CloseCircleOutline : InformationOutline;
$: backgroundColor = () => {
if (notificationInfo.type === NotificationType.Info) {
return '#E0E2F0';
}
$: backgroundColor = () => {
if (notificationInfo.type === NotificationType.Info) {
return '#E0E2F0';
}
if (notificationInfo.type === NotificationType.Error) {
return '#FBE8E6';
}
};
if (notificationInfo.type === NotificationType.Error) {
return '#FBE8E6';
}
};
$: borderStyle = () => {
if (notificationInfo.type === NotificationType.Info) {
return '1px solid #D8DDFF';
}
$: borderStyle = () => {
if (notificationInfo.type === NotificationType.Info) {
return '1px solid #D8DDFF';
}
if (notificationInfo.type === NotificationType.Error) {
return '1px solid #F0E8E7';
}
};
if (notificationInfo.type === NotificationType.Error) {
return '1px solid #F0E8E7';
}
};
$: primaryColor = () => {
if (notificationInfo.type === NotificationType.Info) {
return infoPrimaryColor;
}
$: primaryColor = () => {
if (notificationInfo.type === NotificationType.Info) {
return infoPrimaryColor;
}
if (notificationInfo.type === NotificationType.Error) {
return errorPrimaryColor;
}
};
if (notificationInfo.type === NotificationType.Error) {
return errorPrimaryColor;
}
};
let removeNotificationTimeout: NodeJS.Timeout | undefined = undefined;
let removeNotificationTimeout: NodeJS.Timeout | undefined = undefined;
onMount(() => {
removeNotificationTimeout = setTimeout(discard, notificationInfo.timeout);
return () => clearTimeout(removeNotificationTimeout);
});
onMount(() => {
removeNotificationTimeout = setTimeout(discard, notificationInfo.timeout);
return () => clearTimeout(removeNotificationTimeout);
});
const discard = () => {
notificationController.removeNotificationById(notificationInfo.id);
};
const discard = () => {
notificationController.removeNotificationById(notificationInfo.id);
};
const handleClick = () => {
const action = notificationInfo.action;
if (action.type == 'discard') {
discard();
} else if (action.type == 'link') {
window.open(action.target);
}
};
const handleClick = () => {
const action = notificationInfo.action;
if (action.type == 'discard') {
discard();
} else if (action.type == 'link') {
window.open(action.target);
}
};
</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 hover:cursor-pointer"
on:click={handleClick}
on:keydown={handleClick}
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 hover:cursor-pointer"
on:click={handleClick}
on:keydown={handleClick}
>
<div class="flex justify-between">
<div class="flex gap-2 place-items-center">
<svelte:component this={icon} color={primaryColor()} size="20" />
<h2 style:color={primaryColor()} class="font-medium" data-testid="title">
{notificationInfo.type.toString()}
</h2>
</div>
<button on:click|stopPropagation={discard}>
<svelte:component this={WindowClose} size="20" />
</button>
</div>
<div class="flex justify-between">
<div class="flex gap-2 place-items-center">
<svelte:component this={icon} color={primaryColor()} size="20" />
<h2 style:color={primaryColor()} class="font-medium" data-testid="title">
{notificationInfo.type.toString()}
</h2>
</div>
<button on:click|stopPropagation={discard}>
<svelte:component this={WindowClose} size="20" />
</button>
</div>
<p class="whitespace-pre-wrap text-sm pl-[28px] pr-[16px]" data-testid="message">
{notificationInfo.message}
</p>
<p class="whitespace-pre-wrap text-sm pl-[28px] pr-[16px]" data-testid="message">
{notificationInfo.message}
</p>
</div>

View file

@ -1,24 +1,20 @@
<script lang="ts">
import { notificationController } from './notification';
import { fade } from 'svelte/transition';
import { notificationController } from './notification';
import { fade } from 'svelte/transition';
import NotificationCard from './notification-card.svelte';
import { flip } from 'svelte/animate';
import { quintOut } from 'svelte/easing';
import NotificationCard from './notification-card.svelte';
import { flip } from 'svelte/animate';
import { quintOut } from 'svelte/easing';
const { notificationList } = notificationController;
const { notificationList } = notificationController;
</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>
<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}

View file

@ -1,16 +1,16 @@
import { writable } from 'svelte/store';
export enum NotificationType {
Info = 'Info',
Error = 'Error'
Info = 'Info',
Error = 'Error',
}
export class ImmichNotification {
id = new Date().getTime();
type!: NotificationType;
message!: string;
action!: NotificationAction;
timeout = 3000;
id = new Date().getTime();
type!: NotificationType;
message!: string;
action!: NotificationAction;
timeout = 3000;
}
type DiscardAction = { type: 'discard' };
@ -19,50 +19,50 @@ type LinkAction = { type: 'link'; target: string };
export type NotificationAction = DiscardAction | NoopAction | LinkAction;
export class ImmichNotificationDto {
/**
* Notification type
* @type {NotificationType} [Info, Error]
*/
type: NotificationType = NotificationType.Info;
/**
* Notification type
* @type {NotificationType} [Info, Error]
*/
type: NotificationType = NotificationType.Info;
/**
* Notification message
*/
message = '';
/**
* Notification message
*/
message = '';
/**
* Timeout in miliseconds
*/
timeout?: number;
/**
* Timeout in miliseconds
*/
timeout?: number;
/**
* The action to take when the notification is clicked
*/
action?: NotificationAction;
/**
* The action to take when the notification is clicked
*/
action?: NotificationAction;
}
function createNotificationList() {
const notificationList = writable<ImmichNotification[]>([]);
const notificationList = writable<ImmichNotification[]>([]);
const show = (notificationInfo: ImmichNotificationDto) => {
const newNotification = new ImmichNotification();
newNotification.message = notificationInfo.message;
newNotification.type = notificationInfo.type;
newNotification.timeout = notificationInfo.timeout || 3000;
newNotification.action = notificationInfo.action || { type: 'discard' };
const show = (notificationInfo: ImmichNotificationDto) => {
const newNotification = new ImmichNotification();
newNotification.message = notificationInfo.message;
newNotification.type = notificationInfo.type;
newNotification.timeout = notificationInfo.timeout || 3000;
newNotification.action = notificationInfo.action || { type: 'discard' };
notificationList.update((currentList) => [...currentList, newNotification]);
};
notificationList.update((currentList) => [...currentList, newNotification]);
};
const removeNotificationById = (id: number) => {
notificationList.update((currentList) => currentList.filter((n) => n.id != id));
};
const removeNotificationById = (id: number) => {
notificationList.update((currentList) => currentList.filter((n) => n.id != id));
};
return {
show,
removeNotificationById,
notificationList
};
return {
show,
removeNotificationById,
notificationList,
};
}
export const notificationController = createNotificationList();