includio-cms 0.0.68 → 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.
- package/CHANGELOG.md +181 -0
- package/ROADMAP.md +92 -0
- package/dist/admin/client/account/lang.d.ts +0 -5
- package/dist/admin/client/account/lang.js +2 -12
- package/dist/admin/client/account/preferences-section.svelte +27 -24
- package/dist/admin/client/account/profile-section.svelte +11 -15
- package/dist/admin/client/account/security-section.svelte +0 -11
- package/dist/admin/client/account/sessions-section.svelte +2 -1
- package/dist/admin/client/collection/collection-entries.svelte +168 -43
- package/dist/admin/client/collection/collection-view.svelte.d.ts +5 -0
- package/dist/admin/client/collection/collection-view.svelte.js +22 -5
- package/dist/admin/client/collection/collection.svelte +2 -2
- package/dist/admin/client/collection/data-table.svelte +15 -3
- package/dist/admin/client/collection/data-table.svelte.d.ts +3 -0
- package/dist/admin/client/entry/entry.svelte +11 -7
- package/dist/admin/client/entry/header/status-badge.svelte +6 -3
- package/dist/admin/client/entry/header/version-history-sheet.svelte +6 -3
- package/dist/admin/client/form/form-submissions.svelte +3 -26
- package/dist/admin/components/dashboard/form-submissions-widget.svelte +2 -12
- package/dist/admin/components/dashboard/recent-activity.svelte +2 -12
- package/dist/admin/components/fields/array-field.svelte +126 -71
- package/dist/admin/components/fields/relation-field.svelte +6 -10
- package/dist/admin/components/layout/header-actions.svelte +4 -3
- package/dist/admin/components/layout/nav-search.svelte +43 -31
- package/dist/admin/components/media/media-library.svelte +17 -6
- package/dist/admin/remote/entry.remote.d.ts +10 -1
- package/dist/admin/remote/entry.remote.js +16 -4
- package/dist/admin/state/interface-language.svelte.d.ts +4 -7
- package/dist/admin/state/interface-language.svelte.js +19 -18
- package/dist/admin/utils/arrayMove.d.ts +5 -0
- package/dist/admin/utils/arrayMove.js +12 -0
- package/dist/admin/utils/formatDate.d.ts +1 -0
- package/dist/admin/utils/formatDate.js +5 -1
- package/dist/components/ui/input-group/input-group-input.svelte.d.ts +1 -1
- package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +1 -1
- package/dist/core/server/entries/operations/get.d.ts +2 -0
- package/dist/core/server/entries/operations/get.js +6 -0
- package/dist/db-postgres/index.js +26 -1
- package/dist/sveltekit/components/hybrid-context.d.ts +4 -0
- package/dist/sveltekit/components/hybrid-context.js +9 -0
- package/dist/sveltekit/components/hybrid-target.svelte +4 -1
- package/dist/sveltekit/components/image.svelte +5 -2
- package/dist/sveltekit/components/preview.svelte +3 -0
- package/dist/sveltekit/components/video.svelte +4 -1
- package/dist/sveltekit/index.d.ts +1 -0
- package/dist/sveltekit/index.js +1 -0
- package/dist/types/adapters/db.d.ts +3 -1
- package/dist/types/entries.d.ts +10 -2
- package/dist/types/languages.d.ts +2 -1
- package/dist/updates/0.0.69/index.d.ts +2 -0
- package/dist/updates/0.0.69/index.js +12 -0
- package/dist/updates/0.1.0/index.d.ts +2 -0
- package/dist/updates/0.1.0/index.js +25 -0
- package/dist/updates/index.js +3 -1
- package/package.json +7 -2
|
@@ -117,6 +117,46 @@
|
|
|
117
117
|
let deleteDialogOpen = $state(false);
|
|
118
118
|
let pendingDeleteId = $state<string | null>(null);
|
|
119
119
|
|
|
120
|
+
// Determine if we need fetch-all fallback (search active or sorting by name)
|
|
121
|
+
const isSortingByName = $derived(
|
|
122
|
+
viewState.sorting.length > 0 && viewState.sorting[0].id === 'name'
|
|
123
|
+
);
|
|
124
|
+
const useServerPagination = $derived(!searchQuery && !isSortingByName);
|
|
125
|
+
|
|
126
|
+
// Build orderBy from sorting state for server-side mode
|
|
127
|
+
const serverOrderBy = $derived.by(() => {
|
|
128
|
+
if (!viewState.sorting.length) return undefined;
|
|
129
|
+
const { id, desc } = viewState.sorting[0];
|
|
130
|
+
if (id === 'createdAt' || id === 'updatedAt') {
|
|
131
|
+
return { column: id as 'createdAt' | 'updatedAt', direction: (desc ? 'desc' : 'asc') as 'asc' | 'desc' };
|
|
132
|
+
}
|
|
133
|
+
return undefined;
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Server-side query params
|
|
137
|
+
const activeQueryParams = $derived(
|
|
138
|
+
useServerPagination
|
|
139
|
+
? {
|
|
140
|
+
slug: collection.slug,
|
|
141
|
+
limit: viewState.pageSize,
|
|
142
|
+
offset: viewState.pageIndex * viewState.pageSize,
|
|
143
|
+
orderBy: serverOrderBy
|
|
144
|
+
}
|
|
145
|
+
: { slug: collection.slug }
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
const archivedQueryParams = $derived(
|
|
149
|
+
useServerPagination
|
|
150
|
+
? {
|
|
151
|
+
slug: collection.slug,
|
|
152
|
+
onlyArchived: true as const,
|
|
153
|
+
limit: viewState.pageSize,
|
|
154
|
+
offset: viewState.pageIndex * viewState.pageSize,
|
|
155
|
+
orderBy: serverOrderBy
|
|
156
|
+
}
|
|
157
|
+
: { slug: collection.slug, onlyArchived: true as const }
|
|
158
|
+
);
|
|
159
|
+
|
|
120
160
|
const columns: ColumnDef<CollectionDataTableRow>[] = $derived([
|
|
121
161
|
{
|
|
122
162
|
id: 'select',
|
|
@@ -232,13 +272,15 @@
|
|
|
232
272
|
}
|
|
233
273
|
]);
|
|
234
274
|
|
|
235
|
-
|
|
275
|
+
function refreshQueries() {
|
|
276
|
+
remotes.getRawEntries(activeQueryParams).refresh();
|
|
277
|
+
remotes.getRawEntries(archivedQueryParams).refresh();
|
|
278
|
+
}
|
|
236
279
|
|
|
237
280
|
async function handleRestore(id: string) {
|
|
238
281
|
await remotes.unarchiveEntryCommand(id);
|
|
239
282
|
toast.success(lang[interfaceLanguage.current].entryRestored);
|
|
240
|
-
|
|
241
|
-
remotes.getRawEntries({ slug: collection.slug }).refresh();
|
|
283
|
+
refreshQueries();
|
|
242
284
|
}
|
|
243
285
|
|
|
244
286
|
function handleDelete(id: string) {
|
|
@@ -250,7 +292,7 @@
|
|
|
250
292
|
if (!pendingDeleteId) return;
|
|
251
293
|
await remotes.deleteEntryCommand(pendingDeleteId);
|
|
252
294
|
toast.success(lang[interfaceLanguage.current].entryDeleted);
|
|
253
|
-
|
|
295
|
+
refreshQueries();
|
|
254
296
|
deleteDialogOpen = false;
|
|
255
297
|
pendingDeleteId = null;
|
|
256
298
|
}
|
|
@@ -319,12 +361,18 @@
|
|
|
319
361
|
}
|
|
320
362
|
toast.success(lang[interfaceLanguage.current].entriesArchived);
|
|
321
363
|
rowSelection = {};
|
|
322
|
-
|
|
323
|
-
remotes.getRawEntries({ slug: collection.slug, onlyArchived: true }).refresh();
|
|
364
|
+
refreshQueries();
|
|
324
365
|
}
|
|
366
|
+
|
|
325
367
|
</script>
|
|
326
368
|
|
|
327
|
-
<Tabs.Root
|
|
369
|
+
<Tabs.Root
|
|
370
|
+
value={viewState.activeTab}
|
|
371
|
+
onValueChange={(v) => {
|
|
372
|
+
if (v === 'active' || v === 'archived') viewState.activeTab = v;
|
|
373
|
+
}}
|
|
374
|
+
class="w-full"
|
|
375
|
+
>
|
|
328
376
|
<div class="flex items-center justify-between border-b border-slate-200/50 px-4 py-3 dark:border-white/10">
|
|
329
377
|
<Tabs.List class="h-auto gap-1 bg-transparent p-0">
|
|
330
378
|
<Tabs.Trigger value="active" class="rounded-lg px-3 py-1.5 text-sm font-medium data-[state=active]:bg-slate-100 data-[state=active]:text-slate-900 dark:data-[state=active]:bg-slate-800 dark:data-[state=active]:text-white">{lang[interfaceLanguage.current].active}</Tabs.Trigger>
|
|
@@ -336,57 +384,94 @@
|
|
|
336
384
|
</div>
|
|
337
385
|
|
|
338
386
|
<Tabs.Content value="active" class="mt-0">
|
|
339
|
-
{#await remotes.getRawEntries(
|
|
340
|
-
{@const
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
387
|
+
{#await remotes.getRawEntries(activeQueryParams) then result}
|
|
388
|
+
{@const allRows = result.entries.map(mapEntryToRow)}
|
|
389
|
+
{@const items = useServerPagination
|
|
390
|
+
? allRows
|
|
391
|
+
: (() => {
|
|
392
|
+
let filtered = searchQuery
|
|
393
|
+
? allRows.filter((item) => item.searchText.includes(searchQuery.toLowerCase()))
|
|
394
|
+
: allRows;
|
|
395
|
+
return sortItems(filtered, viewState.sorting);
|
|
396
|
+
})()}
|
|
397
|
+
{@const totalItems = useServerPagination ? result.total : items.length}
|
|
347
398
|
{@const pageCount = Math.ceil(totalItems / viewState.pageSize)}
|
|
348
399
|
|
|
349
400
|
<TableToolbar
|
|
350
401
|
{searchQuery}
|
|
351
|
-
onSearchChange={(q) =>
|
|
402
|
+
onSearchChange={(q) => {
|
|
403
|
+
searchQuery = q;
|
|
404
|
+
viewState.pageIndex = 0;
|
|
405
|
+
}}
|
|
352
406
|
viewMode={viewState.viewMode}
|
|
353
407
|
onViewModeChange={(m) => (viewState.viewMode = m)}
|
|
354
408
|
dateFormat={viewState.dateFormat}
|
|
355
409
|
onDateFormatChange={(f) => (viewState.dateFormat = f)}
|
|
356
410
|
{selectedCount}
|
|
357
|
-
onBulkArchive={() => handleBulkArchive(
|
|
411
|
+
onBulkArchive={() => handleBulkArchive(items)}
|
|
358
412
|
/>
|
|
359
413
|
|
|
360
414
|
{#if viewState.viewMode === 'list'}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
415
|
+
{#if useServerPagination}
|
|
416
|
+
<DataTable
|
|
417
|
+
data={items}
|
|
418
|
+
{columns}
|
|
419
|
+
enableSorting
|
|
420
|
+
enableFiltering
|
|
421
|
+
enableSelection
|
|
422
|
+
enablePagination
|
|
423
|
+
manualPagination={true}
|
|
424
|
+
pageCount={pageCount}
|
|
425
|
+
rowCount={totalItems}
|
|
426
|
+
sorting={viewState.sorting}
|
|
427
|
+
onSortingChange={(s) => (viewState.sorting = s)}
|
|
428
|
+
{rowSelection}
|
|
429
|
+
onRowSelectionChange={(s) => (rowSelection = s)}
|
|
430
|
+
pagination={{ pageIndex: viewState.pageIndex, pageSize: viewState.pageSize }}
|
|
431
|
+
onPaginationChange={(p) => {
|
|
432
|
+
viewState.pageIndex = p.pageIndex;
|
|
433
|
+
}}
|
|
434
|
+
tableRef={(t) => (tableInstance = t)}
|
|
435
|
+
/>
|
|
436
|
+
{:else}
|
|
437
|
+
<DataTable
|
|
438
|
+
data={items}
|
|
439
|
+
{columns}
|
|
440
|
+
enableSorting
|
|
441
|
+
enableFiltering
|
|
442
|
+
enableSelection
|
|
443
|
+
enablePagination
|
|
444
|
+
sorting={viewState.sorting}
|
|
445
|
+
onSortingChange={(s) => (viewState.sorting = s)}
|
|
446
|
+
{rowSelection}
|
|
447
|
+
onRowSelectionChange={(s) => (rowSelection = s)}
|
|
448
|
+
pagination={{ pageIndex: viewState.pageIndex, pageSize: viewState.pageSize }}
|
|
449
|
+
onPaginationChange={(p) => {
|
|
450
|
+
viewState.pageIndex = p.pageIndex;
|
|
451
|
+
}}
|
|
452
|
+
tableRef={(t) => (tableInstance = t)}
|
|
453
|
+
/>
|
|
454
|
+
{/if}
|
|
375
455
|
|
|
376
456
|
<TablePagination
|
|
377
|
-
pageIndex={
|
|
457
|
+
pageIndex={viewState.pageIndex}
|
|
378
458
|
pageSize={viewState.pageSize}
|
|
379
459
|
{pageCount}
|
|
380
460
|
{totalItems}
|
|
381
|
-
onPageChange={(p) =>
|
|
461
|
+
onPageChange={(p) => (viewState.pageIndex = p)}
|
|
382
462
|
onPageSizeChange={(s) => {
|
|
383
463
|
viewState.pageSize = s;
|
|
384
|
-
tableInstance?.setPageSize(s);
|
|
385
464
|
}}
|
|
386
465
|
/>
|
|
387
466
|
{:else}
|
|
467
|
+
{@const displayItems = useServerPagination
|
|
468
|
+
? items
|
|
469
|
+
: items.slice(
|
|
470
|
+
viewState.pageIndex * viewState.pageSize,
|
|
471
|
+
(viewState.pageIndex + 1) * viewState.pageSize
|
|
472
|
+
)}
|
|
388
473
|
<GridView
|
|
389
|
-
items={
|
|
474
|
+
items={displayItems.map((item) => ({
|
|
390
475
|
id: item.id,
|
|
391
476
|
name: item.name,
|
|
392
477
|
status: item.status,
|
|
@@ -396,12 +481,11 @@
|
|
|
396
481
|
}))}
|
|
397
482
|
dateFormat={viewState.dateFormat}
|
|
398
483
|
enableSelection
|
|
399
|
-
selectedIds={new Set(selectedIndices.map((idx) =>
|
|
484
|
+
selectedIds={new Set(selectedIndices.map((idx) => items[idx]?.id).filter(Boolean))}
|
|
400
485
|
onSelectionChange={(ids) => {
|
|
401
|
-
const sorted = sortItems(filteredItems, viewState.sorting);
|
|
402
486
|
const newSelection: RowSelectionState = {};
|
|
403
487
|
for (const id of ids) {
|
|
404
|
-
const idx =
|
|
488
|
+
const idx = items.findIndex((i) => i.id === id);
|
|
405
489
|
if (idx !== -1) {
|
|
406
490
|
newSelection[idx] = true;
|
|
407
491
|
}
|
|
@@ -409,20 +493,61 @@
|
|
|
409
493
|
rowSelection = newSelection;
|
|
410
494
|
}}
|
|
411
495
|
/>
|
|
496
|
+
|
|
497
|
+
<TablePagination
|
|
498
|
+
pageIndex={viewState.pageIndex}
|
|
499
|
+
pageSize={viewState.pageSize}
|
|
500
|
+
{pageCount}
|
|
501
|
+
{totalItems}
|
|
502
|
+
onPageChange={(p) => (viewState.pageIndex = p)}
|
|
503
|
+
onPageSizeChange={(s) => {
|
|
504
|
+
viewState.pageSize = s;
|
|
505
|
+
}}
|
|
506
|
+
/>
|
|
412
507
|
{/if}
|
|
413
508
|
{/await}
|
|
414
509
|
</Tabs.Content>
|
|
415
510
|
|
|
416
511
|
<Tabs.Content value="archived" class="mt-0">
|
|
417
|
-
{#await remotes.getRawEntries(
|
|
418
|
-
{@const items = entries.map((entry) => ({
|
|
512
|
+
{#await remotes.getRawEntries(archivedQueryParams) then result}
|
|
513
|
+
{@const items = result.entries.map((entry) => ({
|
|
419
514
|
...mapEntryToRow(entry),
|
|
420
515
|
onRestore: () => handleRestore(entry.id),
|
|
421
516
|
onDelete: () => handleDelete(entry.id)
|
|
422
517
|
}))}
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
518
|
+
{@const totalItems = result.total}
|
|
519
|
+
{@const pageCount = Math.ceil(totalItems / viewState.pageSize)}
|
|
520
|
+
|
|
521
|
+
{#if useServerPagination}
|
|
522
|
+
<div class="p-4">
|
|
523
|
+
<DataTable
|
|
524
|
+
data={items}
|
|
525
|
+
columns={archivedColumns}
|
|
526
|
+
manualPagination={true}
|
|
527
|
+
pageCount={pageCount}
|
|
528
|
+
rowCount={totalItems}
|
|
529
|
+
enablePagination
|
|
530
|
+
pagination={{ pageIndex: viewState.pageIndex, pageSize: viewState.pageSize }}
|
|
531
|
+
onPaginationChange={(p) => {
|
|
532
|
+
viewState.pageIndex = p.pageIndex;
|
|
533
|
+
}}
|
|
534
|
+
/>
|
|
535
|
+
</div>
|
|
536
|
+
<TablePagination
|
|
537
|
+
pageIndex={viewState.pageIndex}
|
|
538
|
+
pageSize={viewState.pageSize}
|
|
539
|
+
{pageCount}
|
|
540
|
+
{totalItems}
|
|
541
|
+
onPageChange={(p) => (viewState.pageIndex = p)}
|
|
542
|
+
onPageSizeChange={(s) => {
|
|
543
|
+
viewState.pageSize = s;
|
|
544
|
+
}}
|
|
545
|
+
/>
|
|
546
|
+
{:else}
|
|
547
|
+
<div class="p-4">
|
|
548
|
+
<DataTable data={items} columns={archivedColumns} />
|
|
549
|
+
</div>
|
|
550
|
+
{/if}
|
|
426
551
|
{/await}
|
|
427
552
|
</Tabs.Content>
|
|
428
553
|
</Tabs.Root>
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import type { SortingState } from '@tanstack/table-core';
|
|
2
2
|
export type ViewMode = 'list' | 'grid';
|
|
3
3
|
export type DateFormat = 'relative' | 'absolute';
|
|
4
|
+
export type ActiveTab = 'active' | 'archived';
|
|
4
5
|
export interface CollectionViewState {
|
|
5
6
|
viewMode: ViewMode;
|
|
6
7
|
dateFormat: DateFormat;
|
|
7
8
|
pageSize: number;
|
|
8
9
|
sorting: SortingState;
|
|
10
|
+
pageIndex: number;
|
|
11
|
+
activeTab: ActiveTab;
|
|
9
12
|
}
|
|
10
13
|
export declare function createCollectionViewState(collectionSlug: string): {
|
|
11
14
|
viewMode: ViewMode;
|
|
12
15
|
dateFormat: DateFormat;
|
|
13
16
|
pageSize: number;
|
|
14
17
|
sorting: SortingState;
|
|
18
|
+
pageIndex: number;
|
|
19
|
+
activeTab: ActiveTab;
|
|
15
20
|
};
|
|
@@ -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 =
|
|
47
|
+
state.viewMode = value;
|
|
46
48
|
},
|
|
47
49
|
get dateFormat() {
|
|
48
50
|
return state.dateFormat;
|
|
49
51
|
},
|
|
50
52
|
set dateFormat(value) {
|
|
51
|
-
state =
|
|
53
|
+
state.dateFormat = value;
|
|
52
54
|
},
|
|
53
55
|
get pageSize() {
|
|
54
56
|
return state.pageSize;
|
|
55
57
|
},
|
|
56
58
|
set pageSize(value) {
|
|
57
|
-
state =
|
|
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 =
|
|
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((
|
|
49
|
-
entryCount =
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|