1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
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();
}
|