includio-cms 0.0.69 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/ROADMAP.md +24 -5
  3. package/dist/admin/client/account/lang.d.ts +0 -5
  4. package/dist/admin/client/account/lang.js +2 -12
  5. package/dist/admin/client/account/preferences-section.svelte +27 -24
  6. package/dist/admin/client/account/profile-section.svelte +11 -15
  7. package/dist/admin/client/account/security-section.svelte +0 -11
  8. package/dist/admin/client/account/sessions-section.svelte +2 -1
  9. package/dist/admin/client/collection/collection-entries.svelte +168 -43
  10. package/dist/admin/client/collection/collection-view.svelte.d.ts +5 -0
  11. package/dist/admin/client/collection/collection-view.svelte.js +22 -5
  12. package/dist/admin/client/collection/collection.svelte +2 -2
  13. package/dist/admin/client/collection/data-table.svelte +15 -3
  14. package/dist/admin/client/collection/data-table.svelte.d.ts +3 -0
  15. package/dist/admin/client/entry/entry.svelte +11 -7
  16. package/dist/admin/client/entry/header/status-badge.svelte +6 -3
  17. package/dist/admin/client/entry/header/version-history-sheet.svelte +6 -3
  18. package/dist/admin/client/form/form-submissions.svelte +3 -26
  19. package/dist/admin/components/dashboard/form-submissions-widget.svelte +2 -12
  20. package/dist/admin/components/dashboard/recent-activity.svelte +2 -12
  21. package/dist/admin/components/layout/header-actions.svelte +4 -3
  22. package/dist/admin/components/media/media-library.svelte +17 -6
  23. package/dist/admin/remote/entry.remote.d.ts +10 -1
  24. package/dist/admin/remote/entry.remote.js +16 -4
  25. package/dist/admin/state/interface-language.svelte.d.ts +4 -7
  26. package/dist/admin/state/interface-language.svelte.js +19 -18
  27. package/dist/admin/utils/formatDate.d.ts +1 -0
  28. package/dist/admin/utils/formatDate.js +5 -1
  29. package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
  30. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
  31. package/dist/core/server/entries/operations/get.d.ts +2 -0
  32. package/dist/core/server/entries/operations/get.js +6 -0
  33. package/dist/db-postgres/index.js +26 -1
  34. package/dist/sveltekit/components/hybrid-context.d.ts +4 -0
  35. package/dist/sveltekit/components/hybrid-context.js +9 -0
  36. package/dist/sveltekit/components/hybrid-target.svelte +4 -1
  37. package/dist/sveltekit/components/image.svelte +5 -2
  38. package/dist/sveltekit/components/preview.svelte +3 -0
  39. package/dist/sveltekit/components/video.svelte +4 -1
  40. package/dist/sveltekit/index.d.ts +1 -0
  41. package/dist/sveltekit/index.js +1 -0
  42. package/dist/types/adapters/db.d.ts +3 -1
  43. package/dist/types/entries.d.ts +10 -2
  44. package/dist/types/languages.d.ts +2 -1
  45. package/dist/updates/0.1.0/index.d.ts +2 -0
  46. package/dist/updates/0.1.0/index.js +25 -0
  47. package/dist/updates/index.js +2 -1
  48. package/package.json +1 -1
  49. package/dist/core/server/utils/sanitizeRichText.d.ts +0 -1
  50. package/dist/core/server/utils/sanitizeRichText.js +0 -67
@@ -2,7 +2,9 @@ const DEFAULT_STATE = {
2
2
  viewMode: 'list',
3
3
  dateFormat: 'relative',
4
4
  pageSize: 10,
5
- sorting: []
5
+ sorting: [],
6
+ pageIndex: 0,
7
+ activeTab: 'active'
6
8
  };
7
9
  function getStorageKey(collectionSlug) {
8
10
  return `includio-collection-${collectionSlug}-view`;
@@ -42,25 +44,40 @@ export function createCollectionViewState(collectionSlug) {
42
44
  return state.viewMode;
43
45
  },
44
46
  set viewMode(value) {
45
- state = { ...state, viewMode: value };
47
+ state.viewMode = value;
46
48
  },
47
49
  get dateFormat() {
48
50
  return state.dateFormat;
49
51
  },
50
52
  set dateFormat(value) {
51
- state = { ...state, dateFormat: value };
53
+ state.dateFormat = value;
52
54
  },
53
55
  get pageSize() {
54
56
  return state.pageSize;
55
57
  },
56
58
  set pageSize(value) {
57
- state = { ...state, pageSize: value };
59
+ state.pageSize = value;
60
+ state.pageIndex = 0;
58
61
  },
59
62
  get sorting() {
60
63
  return state.sorting;
61
64
  },
62
65
  set sorting(value) {
63
- state = { ...state, sorting: value };
66
+ state.sorting = value;
67
+ state.pageIndex = 0;
68
+ },
69
+ get pageIndex() {
70
+ return state.pageIndex;
71
+ },
72
+ set pageIndex(value) {
73
+ state.pageIndex = value;
74
+ },
75
+ get activeTab() {
76
+ return state.activeTab;
77
+ },
78
+ set activeTab(value) {
79
+ state.activeTab = value;
80
+ state.pageIndex = 0;
64
81
  }
65
82
  };
66
83
  }
@@ -45,8 +45,8 @@
45
45
  });
46
46
 
47
47
  $effect(() => {
48
- remotes.getRawEntries({ slug: collection.slug }).then((entries) => {
49
- entryCount = entries.filter((e) => e.archivedAt === null).length;
48
+ remotes.getRawEntries({ slug: collection.slug }).then(({ total }) => {
49
+ entryCount = total;
50
50
  });
51
51
  });
52
52
  </script>
@@ -29,6 +29,9 @@
29
29
  pagination?: PaginationState;
30
30
  onPaginationChange?: (pagination: PaginationState) => void;
31
31
  tableRef?: (table: TableType<TData>) => void;
32
+ manualPagination?: boolean;
33
+ pageCount?: number;
34
+ rowCount?: number;
32
35
  };
33
36
 
34
37
  let {
@@ -45,7 +48,10 @@
45
48
  onRowSelectionChange,
46
49
  pagination = { pageIndex: 0, pageSize: 10 },
47
50
  onPaginationChange,
48
- tableRef
51
+ tableRef,
52
+ manualPagination: manualPaginationProp = false,
53
+ pageCount: pageCountProp,
54
+ rowCount: rowCountProp
49
55
  }: DataTableProps<TData, TValue> = $props();
50
56
 
51
57
  const table = createSvelteTable({
@@ -81,8 +87,14 @@
81
87
  onPaginationChange?.(newPagination);
82
88
  },
83
89
  globalFilterFn: 'includesString',
84
- manualPagination: false,
85
- manualSorting: true
90
+ manualPagination: manualPaginationProp,
91
+ manualSorting: true,
92
+ get pageCount() {
93
+ return pageCountProp;
94
+ },
95
+ get rowCount() {
96
+ return rowCountProp;
97
+ }
86
98
  });
87
99
 
88
100
  $effect(() => {
@@ -14,6 +14,9 @@ type DataTableProps<TData, TValue> = {
14
14
  pagination?: PaginationState;
15
15
  onPaginationChange?: (pagination: PaginationState) => void;
16
16
  tableRef?: (table: TableType<TData>) => void;
17
+ manualPagination?: boolean;
18
+ pageCount?: number;
19
+ rowCount?: number;
17
20
  };
18
21
  declare function $$render<TData, TValue>(): {
19
22
  props: DataTableProps<TData, TValue>;
@@ -74,6 +74,8 @@
74
74
  saveDraftToast: string;
75
75
  publishToast: string;
76
76
  scheduledToast: string;
77
+ saveFailed: string;
78
+ cannotPublish: string;
77
79
  }
78
80
  > = {
79
81
  en: {
@@ -81,14 +83,18 @@
81
83
  saveToast: 'Entry saved successfully',
82
84
  saveDraftToast: 'Draft saved successfully',
83
85
  publishToast: 'Entry published successfully',
84
- scheduledToast: 'Entry scheduled successfully'
86
+ scheduledToast: 'Entry scheduled successfully',
87
+ saveFailed: 'Save failed',
88
+ cannotPublish: 'Cannot publish'
85
89
  },
86
90
  pl: {
87
91
  entryArchived: 'Wpis został zarchiwizowany pomyślnie',
88
92
  saveToast: 'Wpis został pomyślnie zapisany',
89
93
  saveDraftToast: 'Wersja robocza została pomyślnie zapisana',
90
94
  publishToast: 'Wpis został pomyślnie opublikowany',
91
- scheduledToast: 'Wpis został zaplanowany pomyślnie'
95
+ scheduledToast: 'Wpis został zaplanowany pomyślnie',
96
+ saveFailed: 'Błąd zapisu',
97
+ cannotPublish: 'Nie można opublikować'
92
98
  }
93
99
  };
94
100
 
@@ -199,7 +205,7 @@
199
205
  } catch (e) {
200
206
  console.error('Save error:', e);
201
207
  saveStatus = 'error';
202
- toast.error(interfaceLanguage.current === 'pl' ? 'Błąd zapisu' : 'Save failed', {
208
+ toast.error(lang[interfaceLanguage.current].saveFailed, {
203
209
  description: e instanceof Error ? e.message : undefined
204
210
  });
205
211
  }
@@ -234,16 +240,14 @@
234
240
  } catch (e) {
235
241
  console.error('Publish error:', e);
236
242
  saveStatus = 'error';
237
- toast.error(interfaceLanguage.current === 'pl' ? 'Błąd zapisu' : 'Save failed', {
243
+ toast.error(lang[interfaceLanguage.current].saveFailed, {
238
244
  description: e instanceof Error ? e.message : undefined
239
245
  });
240
246
  }
241
247
  } else {
242
248
  const errors = flattenErrors(validatedForm.errors, collection.fields);
243
249
  toast.error(
244
- interfaceLanguage.current === 'pl'
245
- ? 'Nie można opublikować'
246
- : 'Cannot publish',
250
+ lang[interfaceLanguage.current].cannotPublish,
247
251
  {
248
252
  description: errors.slice(0, 3).join('\n') + (errors.length > 3 ? '\n...' : ''),
249
253
  duration: 5000
@@ -17,6 +17,7 @@
17
17
  publishedBy: string;
18
18
  createdAt: string;
19
19
  scheduledFor: string;
20
+ publishedVersion: string;
20
21
  }
21
22
  > = {
22
23
  en: {
@@ -29,7 +30,8 @@
29
30
  publishedAt: 'Published at',
30
31
  publishedBy: 'Published by',
31
32
  createdAt: 'Created at',
32
- scheduledFor: 'Scheduled for'
33
+ scheduledFor: 'Scheduled for',
34
+ publishedVersion: 'Published version'
33
35
  },
34
36
  pl: {
35
37
  status: {
@@ -41,7 +43,8 @@
41
43
  publishedAt: 'Opublikowano',
42
44
  publishedBy: 'Opublikował',
43
45
  createdAt: 'Utworzono',
44
- scheduledFor: 'Zaplanowano na'
46
+ scheduledFor: 'Zaplanowano na',
47
+ publishedVersion: 'Opublikowana wersja'
45
48
  }
46
49
  };
47
50
 
@@ -152,7 +155,7 @@
152
155
  {#if entry.publishedVersion && entry.publishedVersion.id !== version.id}
153
156
  <div class="border-t pt-2 mt-2">
154
157
  <div class="text-muted-foreground text-xs">
155
- {interfaceLanguage.current === 'pl' ? 'Opublikowana wersja' : 'Published version'}: v{entry.publishedVersion.versionNumber}
158
+ {lang[interfaceLanguage.current].publishedVersion}: v{entry.publishedVersion.versionNumber}
156
159
  </div>
157
160
  </div>
158
161
  {/if}
@@ -22,6 +22,7 @@
22
22
  draft: string;
23
23
  changedFields: string;
24
24
  noChanges: string;
25
+ versionsCount: string;
25
26
  }
26
27
  > = {
27
28
  en: {
@@ -33,7 +34,8 @@
33
34
  scheduled: 'Scheduled',
34
35
  draft: 'Draft',
35
36
  changedFields: 'Changed fields',
36
- noChanges: 'No changes'
37
+ noChanges: 'No changes',
38
+ versionsCount: 'versions'
37
39
  },
38
40
  pl: {
39
41
  history: 'Historia wersji',
@@ -44,7 +46,8 @@
44
46
  scheduled: 'Zaplanowana',
45
47
  draft: 'Szkic',
46
48
  changedFields: 'Zmienione pola',
47
- noChanges: 'Brak zmian'
49
+ noChanges: 'Brak zmian',
50
+ versionsCount: 'wersji'
48
51
  }
49
52
  };
50
53
 
@@ -153,7 +156,7 @@
153
156
  <Sheet.Header>
154
157
  <Sheet.Title>{lang[interfaceLanguage.current].history}</Sheet.Title>
155
158
  <Sheet.Description>
156
- {sortedVersions.length} {interfaceLanguage.current === 'pl' ? 'wersji' : 'versions'}
159
+ {sortedVersions.length} {lang[interfaceLanguage.current].versionsCount}
157
160
  </Sheet.Description>
158
161
  </Sheet.Header>
159
162
 
@@ -10,6 +10,7 @@
10
10
  import { getLocalizedLabel } from '../../utils/collectionLabel.js';
11
11
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
12
12
  import type { InterfaceLanguage } from '../../../types/languages.js';
13
+ import { formatRelativeDate as formatRelativeDateUtil, formatAbsoluteDate as formatAbsoluteDateUtil } from '../../utils/formatDate.js';
13
14
  import type { DateFormat } from '../collection/collection-view.svelte.js';
14
15
  import Checkbox from '../../../components/ui/checkbox/checkbox.svelte';
15
16
  import { getRemotes } from '../../context/remotes.js';
@@ -188,35 +189,11 @@
188
189
  });
189
190
 
190
191
  function formatRelativeDate(date: Date): string {
191
- const now = new Date();
192
- const diff = now.getTime() - date.getTime();
193
- const minutes = Math.floor(diff / 60000);
194
- const hours = Math.floor(diff / 3600000);
195
- const days = Math.floor(diff / 86400000);
196
- const weeks = Math.floor(days / 7);
197
- const months = Math.floor(days / 30);
198
-
199
- if (minutes < 1) return interfaceLanguage.current === 'pl' ? 'teraz' : 'now';
200
- if (minutes < 60)
201
- return interfaceLanguage.current === 'pl' ? `${minutes} min temu` : `${minutes} min ago`;
202
- if (hours < 24)
203
- return interfaceLanguage.current === 'pl' ? `${hours} godz. temu` : `${hours}h ago`;
204
- if (days < 7) return interfaceLanguage.current === 'pl' ? `${days} dni temu` : `${days}d ago`;
205
- if (weeks < 5)
206
- return interfaceLanguage.current === 'pl' ? `${weeks} tyg. temu` : `${weeks}w ago`;
207
- if (months < 12)
208
- return interfaceLanguage.current === 'pl' ? `${months} mies. temu` : `${months}mo ago`;
209
- return formatAbsoluteDate(date);
192
+ return formatRelativeDateUtil(date, interfaceLanguage.current);
210
193
  }
211
194
 
212
195
  function formatAbsoluteDate(date: Date): string {
213
- return date.toLocaleString(interfaceLanguage.current === 'pl' ? 'pl-PL' : 'en-US', {
214
- year: 'numeric',
215
- month: '2-digit',
216
- day: '2-digit',
217
- hour: '2-digit',
218
- minute: '2-digit'
219
- });
196
+ return formatAbsoluteDateUtil(date, interfaceLanguage.current);
220
197
  }
221
198
 
222
199
  async function handleBulkDelete() {
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
3
+ import { formatRelativeDate as formatRelativeDateUtil } from '../../utils/formatDate.js';
3
4
  import * as Card from '../../../components/ui/card/index.js';
4
5
  import { Badge } from '../../../components/ui/badge/index.js';
5
6
  import { Button } from '../../../components/ui/button/index.js';
@@ -45,18 +46,7 @@
45
46
  };
46
47
 
47
48
  function formatRelativeDate(date: Date): string {
48
- const now = new Date();
49
- const diff = now.getTime() - date.getTime();
50
- const minutes = Math.floor(diff / 60000);
51
- const hours = Math.floor(diff / 3600000);
52
- const days = Math.floor(diff / 86400000);
53
-
54
- if (minutes < 1) return interfaceLanguage.current === 'pl' ? 'teraz' : 'now';
55
- if (minutes < 60)
56
- return interfaceLanguage.current === 'pl' ? `${minutes} min` : `${minutes}m`;
57
- if (hours < 24)
58
- return interfaceLanguage.current === 'pl' ? `${hours} godz.` : `${hours}h`;
59
- return interfaceLanguage.current === 'pl' ? `${days} dni` : `${days}d`;
49
+ return formatRelativeDateUtil(date, interfaceLanguage.current);
60
50
  }
61
51
  </script>
62
52
 
@@ -1,5 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
3
+ import { formatRelativeDate as formatRelativeDateUtil } from '../../utils/formatDate.js';
3
4
  import * as Card from '../../../components/ui/card/index.js';
4
5
  import Skeleton from '../../../components/ui/skeleton/skeleton.svelte';
5
6
  import { getRemotes } from '../../../sveltekit/index.js';
@@ -34,18 +35,7 @@
34
35
  };
35
36
 
36
37
  function formatRelativeDate(date: Date): string {
37
- const now = new Date();
38
- const diff = now.getTime() - date.getTime();
39
- const minutes = Math.floor(diff / 60000);
40
- const hours = Math.floor(diff / 3600000);
41
- const days = Math.floor(diff / 86400000);
42
-
43
- if (minutes < 1) return interfaceLanguage.current === 'pl' ? 'teraz' : 'now';
44
- if (minutes < 60)
45
- return interfaceLanguage.current === 'pl' ? `${minutes} min temu` : `${minutes}m ago`;
46
- if (hours < 24)
47
- return interfaceLanguage.current === 'pl' ? `${hours} godz. temu` : `${hours}h ago`;
48
- return interfaceLanguage.current === 'pl' ? `${days} dni temu` : `${days}d ago`;
38
+ return formatRelativeDateUtil(date, interfaceLanguage.current);
49
39
  }
50
40
  </script>
51
41
 
@@ -2,12 +2,13 @@
2
2
  import { toggleMode } from 'mode-watcher';
3
3
  import Sun from '@tabler/icons-svelte/icons/sun';
4
4
  import Moon from '@tabler/icons-svelte/icons/moon';
5
- import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
5
+ import { useInterfaceLanguage, locales } from '../../state/interface-language.svelte.js';
6
6
 
7
7
  const interfaceLanguage = useInterfaceLanguage();
8
8
 
9
9
  function toggleLanguage() {
10
- interfaceLanguage.current = interfaceLanguage.current === 'en' ? 'pl' : 'en';
10
+ const idx = locales.indexOf(interfaceLanguage.current);
11
+ interfaceLanguage.current = locales[(idx + 1) % locales.length];
11
12
  }
12
13
  </script>
13
14
 
@@ -23,6 +24,6 @@
23
24
  onclick={toggleLanguage}
24
25
  class="text-foreground/70 hover:text-foreground flex size-8 items-center justify-center rounded-md border border-black/10 text-xs font-semibold transition-colors hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/10"
25
26
  >
26
- {interfaceLanguage.current === 'en' ? 'EN' : 'PL'}
27
+ {interfaceLanguage.current.toUpperCase()}
27
28
  </button>
28
29
  </div>
@@ -65,6 +65,10 @@
65
65
  })
66
66
  );
67
67
 
68
+ const allFilesQuery = $derived(
69
+ remotes.getMediaFiles({ data: { mimeTypes: accept?.split(',') } })
70
+ );
71
+
68
72
  let tagsQuery = $derived(remotes.getMediaTags());
69
73
 
70
74
  // Multi-select with shift/ctrl
@@ -99,6 +103,7 @@
99
103
  await remotes.deleteMediaFile(currentFile.id);
100
104
  toast.success(lang[interfaceLanguage.current].fileDeletedToast);
101
105
  filesQuery.refresh();
106
+ allFilesQuery.refresh();
102
107
  currentFile = null;
103
108
  }
104
109
  }
@@ -109,6 +114,7 @@
109
114
  const tags = (await tagsQuery) as MediaTag[];
110
115
  currentFile = { ...currentFile, tags: tags.filter((t) => tagIds.includes(t.id)) };
111
116
  await filesQuery.refresh();
117
+ await allFilesQuery.refresh();
112
118
  }
113
119
  }
114
120
 
@@ -133,12 +139,14 @@
133
139
  await remotes.updateMediaTag({ id, name, color });
134
140
  await tagsQuery.refresh();
135
141
  await filesQuery.refresh();
142
+ await allFilesQuery.refresh();
136
143
  }
137
144
 
138
145
  async function handleDeleteTag(id: string) {
139
146
  await remotes.deleteMediaTag(id);
140
147
  await tagsQuery.refresh();
141
148
  await filesQuery.refresh();
149
+ await allFilesQuery.refresh();
142
150
  }
143
151
 
144
152
  // Bulk operations
@@ -146,6 +154,7 @@
146
154
  const fileIds = selectedFileIds;
147
155
  await remotes.bulkSetMediaFileTags({ fileIds, tagIds });
148
156
  await filesQuery.refresh();
157
+ await allFilesQuery.refresh();
149
158
  }
150
159
 
151
160
  async function handleBulkDelete() {
@@ -154,6 +163,7 @@
154
163
  selectedFileIds = [];
155
164
  currentFile = null;
156
165
  await filesQuery.refresh();
166
+ await allFilesQuery.refresh();
157
167
  }
158
168
 
159
169
  onMount(() => {
@@ -168,10 +178,10 @@
168
178
  <div class="flex h-full" bind:this={dropZoneRef}>
169
179
  <!-- Tag sidebar -->
170
180
  <div class="w-48 shrink-0 border-r p-3">
171
- {#await tagsQuery then tags}
181
+ {#await Promise.all([tagsQuery, allFilesQuery]) then [tags, allFiles]}
172
182
  <TagSidebar
173
183
  {tags}
174
- files={[]}
184
+ files={allFiles}
175
185
  activeFilter={activeTagFilter}
176
186
  onFilterChange={(f) => (activeTagFilter = f)}
177
187
  onCreateTag={handleCreateTag}
@@ -187,7 +197,7 @@
187
197
  <MediaSearch bind:value={searchQuery} />
188
198
  <MediaSort />
189
199
  <FileUpload
190
- onUpload={() => filesQuery.refresh()}
200
+ onUpload={() => { filesQuery.refresh(); allFilesQuery.refresh(); }}
191
201
  {accept}
192
202
  bind:dropZoneRef
193
203
  />
@@ -234,6 +244,7 @@
234
244
  onReplace={(updated) => {
235
245
  currentFile = updated;
236
246
  filesQuery.refresh();
247
+ allFilesQuery.refresh();
237
248
  }}
238
249
  {onTagUpdate}
239
250
  {onNameUpdate}
@@ -256,15 +267,15 @@
256
267
 
257
268
  <!-- Bulk action bar -->
258
269
  {#if selectedFileIds.length > 0}
259
- {#await tagsQuery then tags}
270
+ {#await Promise.all([tagsQuery, allFilesQuery]) then [tags, allFiles]}
260
271
  <BulkActionBar
261
272
  selectedCount={selectedFileIds.length}
262
- totalCount={0}
273
+ totalCount={allFiles.length}
263
274
  {tags}
264
275
  onBulkTag={handleBulkTag}
265
276
  onBulkDelete={handleBulkDelete}
266
277
  onClear={() => (selectedFileIds = [])}
267
- onSelectAll={() => {}}
278
+ onSelectAll={() => { selectedFileIds = allFiles.map((f) => f.id); }}
268
279
  onCreateTag={handleCreateTag}
269
280
  onUpdateTagColor={async (id, color) => {
270
281
  const tag = tags.find((t) => t.id === id);
@@ -3,7 +3,16 @@ export declare const getRawEntries: import("@sveltejs/kit").RemoteQueryFunction<
3
3
  ids?: string[] | undefined;
4
4
  slug?: string | undefined;
5
5
  onlyArchived?: boolean | undefined;
6
- }, RawEntry[]>;
6
+ limit?: number | undefined;
7
+ offset?: number | undefined;
8
+ orderBy?: {
9
+ column: "createdAt" | "updatedAt";
10
+ direction: "asc" | "desc";
11
+ } | undefined;
12
+ }, {
13
+ entries: RawEntry[];
14
+ total: number;
15
+ }>;
7
16
  export declare const getEntries: import("@sveltejs/kit").RemoteQueryFunction<{
8
17
  ids?: string[] | undefined;
9
18
  dataValues?: Record<string, unknown> | undefined;
@@ -1,6 +1,6 @@
1
1
  import { command, query } from '$app/server';
2
2
  import { createEntry as createEntryOperation, createEntrySchema, createEntryVersion } from '../../core/server/entries/operations/create.js';
3
- import { getRawEntries as getRawEntriesOperation, getRawEntry as getRawEntryOperation, getRawEntryOrThrow, getDbEntry, getDbEntryOrThrow, getEntries as getEntriesOperation, getEntry as getEntryOperation, getEntryVersion as getEntryVersionOperation } from '../../core/server/entries/operations/get.js';
3
+ import { getRawEntries as getRawEntriesOperation, countRawEntries as countRawEntriesOperation, getRawEntry as getRawEntryOperation, getRawEntryOrThrow, getDbEntry, getDbEntryOrThrow, getEntries as getEntriesOperation, getEntry as getEntryOperation, getEntryVersion as getEntryVersionOperation } from '../../core/server/entries/operations/get.js';
4
4
  import { getCMS } from '../../core/cms.js';
5
5
  import { pruneOldDraftVersions, unpublishEntry, updateEntry, updateEntrySchema, updateEntryVersionCommandTypes } from '../../core/server/entries/operations/update.js';
6
6
  import z from 'zod';
@@ -9,10 +9,22 @@ import { entryStatuses } from '../../types/entries.js';
9
9
  export const getRawEntries = query(z.object({
10
10
  ids: z.array(z.string().uuid()).optional(),
11
11
  slug: z.string().optional(),
12
- onlyArchived: z.boolean().optional()
12
+ onlyArchived: z.boolean().optional(),
13
+ limit: z.number().int().positive().optional(),
14
+ offset: z.number().int().nonnegative().optional(),
15
+ orderBy: z
16
+ .object({
17
+ column: z.enum(['createdAt', 'updatedAt']),
18
+ direction: z.enum(['asc', 'desc'])
19
+ })
20
+ .optional()
13
21
  }), async (input) => {
14
- // We return RawEntry[] here, transformation to populated Entry[] is done in the client
15
- return getRawEntriesOperation(input);
22
+ const { limit, offset, orderBy, ...filterOptions } = input;
23
+ const [entries, total] = await Promise.all([
24
+ getRawEntriesOperation(input),
25
+ countRawEntriesOperation(filterOptions)
26
+ ]);
27
+ return { entries, total };
16
28
  });
17
29
  export const getEntries = query(z.object({
18
30
  ids: z.array(z.string().uuid()).optional(),
@@ -1,8 +1,5 @@
1
1
  import type { InterfaceLanguage as InterfaceLanguageType } from '../../types/languages.js';
2
- export declare class InterfaceLanguage {
3
- #private;
4
- constructor();
5
- get current(): InterfaceLanguageType;
6
- set current(value: InterfaceLanguageType);
7
- }
8
- export declare function useInterfaceLanguage(): InterfaceLanguage;
2
+ export declare function useInterfaceLanguage(): {
3
+ current: InterfaceLanguageType;
4
+ };
5
+ export { locales } from '../../paraglide/runtime.js';
@@ -1,25 +1,26 @@
1
1
  import { PersistedState } from 'runed';
2
- import { createContext } from 'svelte';
3
- const [getInterfaceLanguage, setInterfaceLanguage] = createContext();
4
- export class InterfaceLanguage {
5
- #state;
6
- constructor() {
7
- const state = new PersistedState('interface-language', 'pl');
8
- this.#state = state;
2
+ import { locales, baseLocale } from '../../paraglide/runtime.js';
3
+ function detectDefaultLocale() {
4
+ if (typeof navigator === 'undefined')
5
+ return baseLocale;
6
+ const langs = navigator.languages ?? [navigator.language];
7
+ for (const lang of langs) {
8
+ const base = lang.split('-')[0].toLowerCase();
9
+ if (locales.includes(base))
10
+ return base;
9
11
  }
12
+ return baseLocale;
13
+ }
14
+ const state = new PersistedState('interface-language', detectDefaultLocale());
15
+ const interfaceLanguage = {
10
16
  get current() {
11
- return this.#state.current;
12
- }
17
+ return state.current;
18
+ },
13
19
  set current(value) {
14
- this.#state.current = value;
20
+ state.current = value;
15
21
  }
16
- }
22
+ };
17
23
  export function useInterfaceLanguage() {
18
- try {
19
- return getInterfaceLanguage();
20
- }
21
- catch {
22
- setInterfaceLanguage(new InterfaceLanguage());
23
- return getInterfaceLanguage();
24
- }
24
+ return interfaceLanguage;
25
25
  }
26
+ export { locales } from '../../paraglide/runtime.js';
@@ -1,3 +1,4 @@
1
1
  import type { InterfaceLanguage } from '../../types/languages.js';
2
+ export declare function toLocaleCode(lang: string): string;
2
3
  export declare function formatRelativeDate(date: Date | string, lang?: InterfaceLanguage): string;
3
4
  export declare function formatAbsoluteDate(date: Date | string, lang?: InterfaceLanguage): string;
@@ -1,3 +1,7 @@
1
+ export function toLocaleCode(lang) {
2
+ const map = { pl: 'pl-PL', en: 'en-US' };
3
+ return map[lang] ?? lang;
4
+ }
1
5
  const units = [
2
6
  { unit: 'year', ms: 365 * 24 * 60 * 60 * 1000 },
3
7
  { unit: 'month', ms: 30 * 24 * 60 * 60 * 1000 },
@@ -84,7 +88,7 @@ export function formatRelativeDate(date, lang = 'en') {
84
88
  }
85
89
  export function formatAbsoluteDate(date, lang = 'en') {
86
90
  const d = typeof date === 'string' ? new Date(date) : date;
87
- return d.toLocaleString(lang === 'pl' ? 'pl-PL' : 'en-US', {
91
+ return d.toLocaleString(toLocaleCode(lang), {
88
92
  year: 'numeric',
89
93
  month: 'short',
90
94
  day: 'numeric',
@@ -2,7 +2,7 @@ declare const InputGroupInput: import("svelte").Component<(Omit<import("svelte/e
2
2
  type: "file";
3
3
  files?: FileList;
4
4
  } | {
5
- type?: "number" | "image" | "text" | "date" | "radio" | "url" | "email" | "checkbox" | "hidden" | (string & {}) | "password" | "reset" | "search" | "time" | "color" | "button" | "submit" | "tel" | "datetime-local" | "month" | "range" | "week";
5
+ type?: "number" | "image" | "url" | "text" | "date" | "radio" | "email" | "checkbox" | "hidden" | (string & {}) | "password" | "reset" | "search" | "time" | "color" | "button" | "submit" | "tel" | "datetime-local" | "month" | "range" | "week";
6
6
  files?: undefined;
7
7
  })) & {
8
8
  ref?: HTMLElement | null | undefined;
@@ -2,7 +2,7 @@ declare const SidebarInput: import("svelte").Component<(Omit<import("svelte/elem
2
2
  type: "file";
3
3
  files?: FileList;
4
4
  } | {
5
- type?: "number" | "image" | "text" | "date" | "radio" | "url" | "email" | "checkbox" | "hidden" | (string & {}) | "password" | "reset" | "search" | "time" | "color" | "button" | "submit" | "tel" | "datetime-local" | "month" | "range" | "week";
5
+ type?: "number" | "image" | "url" | "text" | "date" | "radio" | "email" | "checkbox" | "hidden" | (string & {}) | "password" | "reset" | "search" | "time" | "color" | "button" | "submit" | "tel" | "datetime-local" | "month" | "range" | "week";
6
6
  files?: undefined;
7
7
  })) & {
8
8
  ref?: HTMLElement | null | undefined;
@@ -1,7 +1,9 @@
1
1
  import type { DbEntry, DbEntryVersion, Entry, GetDbEntriesOptions, GetDbEntryOptions, GetDbEntryVersionOptions, GetDbEntryVersionsOptions, GetEntriesOptions, GetEntryOptions, GetRawEntriesOptions, getRawEntryOptions, RawEntry } from '../../../../types/entries.js';
2
2
  export declare const getDbEntries: (options: GetDbEntriesOptions) => Promise<DbEntry[]>;
3
+ export declare const countDbEntries: (options: Omit<GetDbEntriesOptions, "limit" | "offset" | "orderBy">) => Promise<number>;
3
4
  export declare const getDbEntry: (options: GetDbEntryOptions) => Promise<DbEntry | null>;
4
5
  export declare const getDbEntryOrThrow: (options: GetDbEntryOptions) => Promise<DbEntry>;
6
+ export declare const countRawEntries: (options: Omit<GetRawEntriesOptions, "limit" | "offset" | "orderBy">) => Promise<number>;
5
7
  export declare const getRawEntries: (options: GetRawEntriesOptions) => Promise<RawEntry[]>;
6
8
  export declare const getRawEntry: (options: getRawEntryOptions) => Promise<RawEntry | null>;
7
9
  export declare const getRawEntryOrThrow: (options: getRawEntryOptions) => Promise<RawEntry>;