diff options
Diffstat (limited to 'frontend/src/lib/Utils.ts')
-rw-r--r-- | frontend/src/lib/Utils.ts | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/frontend/src/lib/Utils.ts b/frontend/src/lib/Utils.ts new file mode 100644 index 0000000..1a07be1 --- /dev/null +++ b/frontend/src/lib/Utils.ts @@ -0,0 +1,108 @@ +import { isError } from '$gql/Utils'; +import type { ImageFragment } from '$gql/graphql'; +import type { BeforeNavigate } from '@sveltejs/kit'; +import type { OperationResultState } from '@urql/svelte'; +import { openModal } from 'svelte-modals'; +import ConfirmDeletion from './dialogs/ConfirmDeletion.svelte'; + +export function range(from: number, to: number) { + return Array.from({ length: to - from + 1 }, (_, k) => k + from); +} + +export function getRandomInt(min: number, max: number) { + const minCeiled = Math.ceil(min); + const maxFloored = Math.floor(max); + + return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled); +} + +export interface ListItem { + id: number | string; + name: string; +} + +export interface ResultState { + fetching: boolean; + message?: string; +} + +export function getResultState(state: OperationResultState): ResultState { + let message: string | undefined; + + if (state.error) { + message = `${state.error.name}: ${state.error.message}`; + } else if (state.data) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + const obj = Object.values(state.data)[0]; + if (isError(obj)) { + message = obj.message; + } + } + + return { fetching: state.fetching, message: message }; +} + +export function src(image: ImageFragment, type: 'full' | 'thumb' = 'thumb') { + const dir = image.hash.slice(0, 2); + const file = image.hash.slice(2); + + return `/objects/${dir}/${file}_${type}.webp`; +} + +export function numKeys(obj?: object | null, ignore: string[] = []) { + if (!obj) return 0; + + const len = Object.keys(obj).length; + let ignored = 0; + + for (const i of ignore) { + if (Object.hasOwn(obj, i)) ignored++; + } + + return len - ignored; +} + +export function confirmDeletion( + typename: string, + names: string | string[], + callback: () => void, + warning?: string +) { + openModal( + ConfirmDeletion, + { names: Array.isArray(names) ? names : [names], typename, callback: callback, warning }, + { replace: true } + ); +} + +export function idFromLabel(label: string) { + return label.toLowerCase().replaceAll(' ', '-'); +} + +export function pluralize(singular: string, size: number) { + return `${singular}${size > 1 ? 's' : ''}`; +} + +export function formatListSize(word: string, size: number) { + return `${size} ${pluralize(word, size)}`; +} + +export function joinText(items: string[], separator = ', ') { + return items.filter((i) => i).join(separator); +} + +export function confirmPending() { + return confirm('There are pending changes. Click Cancel to keep editing or OK to dismiss them.'); +} + +export function preventOnPending({ to, cancel }: BeforeNavigate, pending: boolean) { + if (!pending) return; + + if (to) { + if (confirmPending()) { + return; + } + } + + cancel(); +} |