includio-cms 0.36.8 → 0.37.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/API.md +179 -3
- package/CHANGELOG.md +64 -0
- package/DOCS.md +28 -3
- package/ROADMAP.md +18 -0
- package/dist/admin/client/booking/booking-dashboard.svelte +40 -0
- package/dist/admin/client/booking/booking-dashboard.svelte.d.ts +3 -0
- package/dist/admin/client/booking/customer-panel.svelte +102 -0
- package/dist/admin/client/booking/customer-panel.svelte.d.ts +11 -0
- package/dist/admin/client/booking/customer-view.d.ts +52 -0
- package/dist/admin/client/booking/customer-view.js +134 -0
- package/dist/admin/client/booking/participant-data-panel.svelte +330 -0
- package/dist/admin/client/booking/participant-data-panel.svelte.d.ts +22 -0
- package/dist/admin/client/booking/reservation-detail-page.svelte +637 -0
- package/dist/admin/client/booking/reservation-detail-page.svelte.d.ts +3 -0
- package/dist/admin/client/booking/reservations-page.svelte +221 -0
- package/dist/admin/client/booking/reservations-page.svelte.d.ts +3 -0
- package/dist/admin/client/collection/collection-entries.svelte +21 -2
- package/dist/admin/client/collection/entry-link.svelte +6 -4
- package/dist/admin/client/collection/entry-link.svelte.d.ts +3 -1
- package/dist/admin/client/collection/row-actions.svelte +12 -4
- package/dist/admin/client/collection/row-actions.svelte.d.ts +1 -0
- package/dist/admin/client/collection/status-badge.svelte +39 -3
- package/dist/admin/client/collection/status-badge.svelte.d.ts +5 -3
- package/dist/admin/client/entry/entry.svelte +26 -9
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte +73 -10
- package/dist/admin/client/entry/hybrid/hybrid-preview.svelte.d.ts +6 -5
- package/dist/admin/client/entry/preview-views-context.svelte.d.ts +22 -0
- package/dist/admin/client/entry/preview-views-context.svelte.js +58 -0
- package/dist/admin/client/entry/preview-views.d.ts +27 -0
- package/dist/admin/client/entry/preview-views.js +33 -0
- package/dist/admin/client/index.d.ts +3 -0
- package/dist/admin/client/index.js +3 -0
- package/dist/admin/client/modules/dashboard-registry.d.ts +7 -0
- package/dist/admin/client/modules/dashboard-registry.js +11 -0
- package/dist/admin/client/modules/module-dashboard-page.svelte +26 -0
- package/dist/admin/client/modules/module-dashboard-page.svelte.d.ts +6 -0
- package/dist/admin/client/modules/stat-card.svelte +22 -0
- package/dist/admin/client/modules/stat-card.svelte.d.ts +10 -0
- package/dist/admin/client/shop/shop-dashboard.svelte +29 -0
- package/dist/admin/client/shop/shop-dashboard.svelte.d.ts +3 -0
- package/dist/admin/components/fields/relation-field.svelte +11 -2
- package/dist/admin/components/icons/icon-map.js +8 -0
- package/dist/admin/components/layout/app-sidebar.svelte +45 -14
- package/dist/admin/components/layout/context-switcher.svelte +90 -0
- package/dist/admin/components/layout/context-switcher.svelte.d.ts +3 -0
- package/dist/admin/components/layout/lang.d.ts +4 -0
- package/dist/admin/components/layout/lang.js +8 -0
- package/dist/admin/components/layout/layout-renderer.svelte +2 -1
- package/dist/admin/components/layout/layout-tabs.svelte +14 -0
- package/dist/admin/components/layout/layout-tabs.svelte.d.ts +2 -0
- package/dist/admin/components/layout/nav-collections.svelte +16 -9
- package/dist/admin/components/layout/nav-collections.svelte.d.ts +5 -1
- package/dist/admin/components/layout/nav-global.svelte +45 -0
- package/dist/admin/components/layout/nav-global.svelte.d.ts +3 -0
- package/dist/admin/components/layout/nav-main.svelte +8 -32
- package/dist/admin/components/layout/nav-main.svelte.d.ts +6 -1
- package/dist/admin/components/layout/nav-module.svelte +57 -0
- package/dist/admin/components/layout/nav-module.svelte.d.ts +7 -0
- package/dist/admin/components/layout/nav-section.svelte +1 -1
- package/dist/admin/components/layout/nav-section.svelte.d.ts +1 -1
- package/dist/admin/components/layout/nav-singletons.svelte +14 -7
- package/dist/admin/components/layout/nav-singletons.svelte.d.ts +5 -1
- package/dist/admin/remote/booking.remote.d.ts +244 -0
- package/dist/admin/remote/booking.remote.js +283 -0
- package/dist/admin/remote/entry.remote.d.ts +3 -0
- package/dist/admin/remote/entry.remote.js +14 -3
- package/dist/admin/remote/index.d.ts +2 -0
- package/dist/admin/remote/index.js +2 -0
- package/dist/admin/remote/modules.remote.d.ts +10 -0
- package/dist/admin/remote/modules.remote.js +14 -0
- package/dist/admin/state/active-context-resolve.d.ts +37 -0
- package/dist/admin/state/active-context-resolve.js +66 -0
- package/dist/admin/state/active-context.svelte.d.ts +8 -0
- package/dist/admin/state/active-context.svelte.js +27 -0
- package/dist/booking/adjustments.d.ts +33 -0
- package/dist/booking/adjustments.js +26 -0
- package/dist/booking/capacity.d.ts +12 -0
- package/dist/booking/capacity.js +10 -0
- package/dist/booking/client/index.d.ts +39 -0
- package/dist/booking/client/index.js +44 -0
- package/dist/booking/client/use-booking.svelte.d.ts +25 -0
- package/dist/booking/client/use-booking.svelte.js +56 -0
- package/dist/booking/config.d.ts +156 -0
- package/dist/booking/config.js +36 -0
- package/dist/booking/draft.d.ts +77 -0
- package/dist/booking/draft.js +67 -0
- package/dist/booking/expiry-logic.d.ts +30 -0
- package/dist/booking/expiry-logic.js +33 -0
- package/dist/booking/index.d.ts +18 -0
- package/dist/booking/index.js +52 -0
- package/dist/booking/ledger.d.ts +46 -0
- package/dist/booking/ledger.js +60 -0
- package/dist/booking/number.d.ts +2 -0
- package/dist/booking/number.js +11 -0
- package/dist/booking/participant-fields/access.d.ts +10 -0
- package/dist/booking/participant-fields/access.js +14 -0
- package/dist/booking/participant-fields/age.d.ts +12 -0
- package/dist/booking/participant-fields/age.js +28 -0
- package/dist/booking/participant-fields/completeness.d.ts +8 -0
- package/dist/booking/participant-fields/completeness.js +13 -0
- package/dist/booking/participant-fields/group.d.ts +6 -0
- package/dist/booking/participant-fields/group.js +15 -0
- package/dist/booking/participant-fields/index.d.ts +6 -0
- package/dist/booking/participant-fields/index.js +6 -0
- package/dist/booking/participant-fields/types.d.ts +50 -0
- package/dist/booking/participant-fields/types.js +5 -0
- package/dist/booking/participant-fields/validate.d.ts +7 -0
- package/dist/booking/participant-fields/validate.js +44 -0
- package/dist/booking/participant-pricing.d.ts +93 -0
- package/dist/booking/participant-pricing.js +91 -0
- package/dist/booking/participants-view.d.ts +32 -0
- package/dist/booking/participants-view.js +22 -0
- package/dist/booking/payment-context.d.ts +19 -0
- package/dist/booking/payment-context.js +29 -0
- package/dist/booking/pricing-inputs.d.ts +28 -0
- package/dist/booking/pricing-inputs.js +35 -0
- package/dist/booking/pricing.d.ts +86 -0
- package/dist/booking/pricing.js +125 -0
- package/dist/booking/recompute.d.ts +22 -0
- package/dist/booking/recompute.js +31 -0
- package/dist/booking/reminders-schedule.d.ts +11 -0
- package/dist/booking/reminders-schedule.js +28 -0
- package/dist/booking/server/adjustments.d.ts +27 -0
- package/dist/booking/server/adjustments.js +136 -0
- package/dist/booking/server/bookings.d.ts +45 -0
- package/dist/booking/server/bookings.js +288 -0
- package/dist/booking/server/catalog.d.ts +9 -0
- package/dist/booking/server/catalog.js +20 -0
- package/dist/booking/server/db.d.ts +7 -0
- package/dist/booking/server/db.js +18 -0
- package/dist/booking/server/email.d.ts +23 -0
- package/dist/booking/server/email.js +59 -0
- package/dist/booking/server/emailTemplateRegistry.d.ts +29 -0
- package/dist/booking/server/emailTemplateRegistry.js +125 -0
- package/dist/booking/server/http/create-handler.d.ts +5 -0
- package/dist/booking/server/http/create-handler.js +68 -0
- package/dist/booking/server/http/index.d.ts +4 -0
- package/dist/booking/server/http/index.js +4 -0
- package/dist/booking/server/http/maintenance-handler.d.ts +9 -0
- package/dist/booking/server/http/maintenance-handler.js +36 -0
- package/dist/booking/server/http/portal-handler.d.ts +13 -0
- package/dist/booking/server/http/portal-handler.js +99 -0
- package/dist/booking/server/http/webhook-handler.d.ts +9 -0
- package/dist/booking/server/http/webhook-handler.js +39 -0
- package/dist/booking/server/index.d.ts +12 -0
- package/dist/booking/server/index.js +14 -0
- package/dist/booking/server/maintenance.d.ts +28 -0
- package/dist/booking/server/maintenance.js +134 -0
- package/dist/booking/server/participants.d.ts +26 -0
- package/dist/booking/server/participants.js +92 -0
- package/dist/booking/server/payments.d.ts +34 -0
- package/dist/booking/server/payments.js +207 -0
- package/dist/booking/server/portal-session.d.ts +16 -0
- package/dist/booking/server/portal-session.js +42 -0
- package/dist/booking/server/portal.d.ts +207 -0
- package/dist/booking/server/portal.js +234 -0
- package/dist/booking/server/refunds.d.ts +7 -0
- package/dist/booking/server/refunds.js +58 -0
- package/dist/booking/server/reminders.d.ts +9 -0
- package/dist/booking/server/reminders.js +24 -0
- package/dist/booking/server/validation.d.ts +17 -0
- package/dist/booking/server/validation.js +55 -0
- package/dist/booking/state-machine.d.ts +41 -0
- package/dist/booking/state-machine.js +73 -0
- package/dist/booking/templates/_partials/footer.en.html +4 -0
- package/dist/booking/templates/_partials/footer.pl.html +4 -0
- package/dist/booking/templates/_partials/header.en.html +4 -0
- package/dist/booking/templates/_partials/header.pl.html +4 -0
- package/dist/booking/templates/balance-due.en.html +10 -0
- package/dist/booking/templates/balance-due.pl.html +10 -0
- package/dist/booking/templates/balance-overdue-cancelled.en.html +5 -0
- package/dist/booking/templates/balance-overdue-cancelled.pl.html +5 -0
- package/dist/booking/templates/booking-received.en.html +9 -0
- package/dist/booking/templates/booking-received.pl.html +9 -0
- package/dist/booking/templates/deposit-paid.en.html +6 -0
- package/dist/booking/templates/deposit-paid.pl.html +6 -0
- package/dist/booking/templates/payment-link.en.html +5 -0
- package/dist/booking/templates/payment-link.pl.html +5 -0
- package/dist/booking/templates/payment-received.en.html +10 -0
- package/dist/booking/templates/payment-received.pl.html +10 -0
- package/dist/booking/totals.d.ts +38 -0
- package/dist/booking/totals.js +61 -0
- package/dist/booking/webhook-logic.d.ts +28 -0
- package/dist/booking/webhook-logic.js +50 -0
- package/dist/cli/create-user.d.ts +7 -1
- package/dist/cli/create-user.js +23 -15
- package/dist/cli/index.js +55 -7
- package/dist/cli/scaffold/admin.d.ts +6 -0
- package/dist/cli/scaffold/admin.js +5 -3
- package/dist/cli/scaffold/booking.d.ts +12 -0
- package/dist/cli/scaffold/booking.js +103 -0
- package/dist/core/cms.d.ts +24 -9
- package/dist/core/cms.js +72 -34
- package/dist/core/config/validatePreviews.d.ts +12 -0
- package/dist/core/config/validatePreviews.js +90 -0
- package/dist/core/fields/dotPath.d.ts +4 -0
- package/dist/core/fields/dotPath.js +18 -0
- package/dist/core/fields/slugPath.d.ts +9 -1
- package/dist/core/fields/slugPath.js +16 -2
- package/dist/core/fields/slugify.d.ts +3 -0
- package/dist/core/fields/slugify.js +4 -0
- package/dist/core/server/entries/operations/duplicate.d.ts +10 -0
- package/dist/core/server/entries/operations/duplicate.js +73 -0
- package/dist/core/server/entries/operations/slugNormalize.d.ts +8 -0
- package/dist/core/server/entries/operations/slugNormalize.js +20 -0
- package/dist/core/server/entries/operations/slugUniqueness.d.ts +17 -0
- package/dist/core/server/entries/operations/slugUniqueness.js +39 -0
- package/dist/core/server/fields/resolveRelationFields.d.ts +11 -2
- package/dist/core/server/fields/resolveRelationFields.js +12 -3
- package/dist/core/server/generator/generator.js +7 -2
- package/dist/db-postgres/schema/booking/bookingAdjustments.d.ts +186 -0
- package/dist/db-postgres/schema/booking/bookingAdjustments.js +22 -0
- package/dist/db-postgres/schema/booking/bookingItemPersons.d.ts +117 -0
- package/dist/db-postgres/schema/booking/bookingItemPersons.js +22 -0
- package/dist/db-postgres/schema/booking/bookingItems.d.ts +181 -0
- package/dist/db-postgres/schema/booking/bookingItems.js +22 -0
- package/dist/db-postgres/schema/booking/bookingPayments.d.ts +204 -0
- package/dist/db-postgres/schema/booking/bookingPayments.js +25 -0
- package/dist/db-postgres/schema/booking/bookingPersons.d.ts +99 -0
- package/dist/db-postgres/schema/booking/bookingPersons.js +17 -0
- package/dist/db-postgres/schema/booking/bookingReminders.d.ts +131 -0
- package/dist/db-postgres/schema/booking/bookingReminders.js +18 -0
- package/dist/db-postgres/schema/booking/bookings.d.ts +307 -0
- package/dist/db-postgres/schema/booking/bookings.js +40 -0
- package/dist/db-postgres/schema/booking/index.d.ts +7 -0
- package/dist/db-postgres/schema/booking/index.js +7 -0
- package/dist/db-postgres/schema/index.d.ts +1 -0
- package/dist/db-postgres/schema/index.js +1 -0
- package/dist/db-postgres/schema-booking.d.ts +1 -0
- package/dist/db-postgres/schema-booking.js +1 -0
- package/dist/server/security/rate-limit-handler.d.ts +19 -0
- package/dist/server/security/rate-limit-handler.js +34 -0
- package/dist/shop/adapters/payu/client.js +3 -1
- package/dist/shop/adapters/payu/index.js +37 -17
- package/dist/shop/adapters/payu/payload.d.ts +6 -0
- package/dist/shop/adapters/payu/payload.js +1 -1
- package/dist/shop/adapters/stripe/index.js +36 -21
- package/dist/shop/index.d.ts +11 -2
- package/dist/shop/index.js +43 -1
- package/dist/shop/rate-limit.d.ts +1 -9
- package/dist/shop/rate-limit.js +3 -28
- package/dist/shop/types.d.ts +19 -0
- package/dist/sveltekit/config.d.ts +4 -0
- package/dist/sveltekit/config.js +6 -0
- package/dist/types/cms.d.ts +15 -1
- package/dist/types/cms.schema.d.ts +96 -2
- package/dist/types/cms.schema.js +84 -1
- package/dist/types/config.d.ts +33 -0
- package/dist/types/layout.d.ts +6 -0
- package/dist/types/modules.d.ts +133 -0
- package/dist/types/modules.js +27 -0
- package/dist/updates/0.36.9/index.d.ts +2 -0
- package/dist/updates/0.36.9/index.js +12 -0
- package/dist/updates/0.37.0/index.d.ts +2 -0
- package/dist/updates/0.37.0/index.js +52 -0
- package/dist/updates/index.js +5 -1
- package/package.json +19 -1
- package/dist/admin/components/layout/nav-shop.svelte +0 -33
- package/dist/admin/components/layout/nav-shop.svelte.d.ts +0 -3
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getRemotes } from '../../../sveltekit/index.js';
|
|
3
|
+
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
4
|
+
import { formatCentsPrice, formatDateTime } from '../../utils/formatters.js';
|
|
5
|
+
import PageHeader from '../../components/layout/page-header.svelte';
|
|
6
|
+
import DataTable from '../collection/data-table.svelte';
|
|
7
|
+
import TableToolbar from '../collection/table-toolbar.svelte';
|
|
8
|
+
import TablePagination from '../collection/table-pagination.svelte';
|
|
9
|
+
import StateDisplay from '../collection/state-display.svelte';
|
|
10
|
+
import StatusBadge from '../collection/status-badge.svelte';
|
|
11
|
+
import EntryLink from '../collection/entry-link.svelte';
|
|
12
|
+
import { renderComponent } from '../../../components/ui/data-table/render-helpers.js';
|
|
13
|
+
import { customerSummary } from './customer-view.js';
|
|
14
|
+
import type { ColumnDef, PaginationState } from '@tanstack/table-core';
|
|
15
|
+
import type { BookingStatus } from '../../../booking/state-machine.js';
|
|
16
|
+
|
|
17
|
+
type BookingRow = {
|
|
18
|
+
id: string;
|
|
19
|
+
number: string;
|
|
20
|
+
status: BookingStatus;
|
|
21
|
+
currency: string;
|
|
22
|
+
customer: Record<string, unknown>;
|
|
23
|
+
totals: { gross: number; balance: number };
|
|
24
|
+
createdAt: Date | string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const remotes = getRemotes();
|
|
28
|
+
const interfaceLanguage = useInterfaceLanguage();
|
|
29
|
+
|
|
30
|
+
let statusFilter = $state<string | null>(null);
|
|
31
|
+
let searchQuery = $state('');
|
|
32
|
+
let appliedSearch = $state('');
|
|
33
|
+
let pagination = $state<PaginationState>({ pageIndex: 0, pageSize: 50 });
|
|
34
|
+
let searchDebounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
35
|
+
|
|
36
|
+
const bookingsQuery = $derived(
|
|
37
|
+
remotes.listBookings({
|
|
38
|
+
status: (statusFilter as BookingStatus | null) ?? undefined,
|
|
39
|
+
search: appliedSearch || undefined,
|
|
40
|
+
limit: pagination.pageSize,
|
|
41
|
+
offset: pagination.pageIndex * pagination.pageSize
|
|
42
|
+
})
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const items = $derived<BookingRow[]>((bookingsQuery.current?.items as BookingRow[]) ?? []);
|
|
46
|
+
const total = $derived(bookingsQuery.current?.total ?? 0);
|
|
47
|
+
const isLoading = $derived(!bookingsQuery.ready);
|
|
48
|
+
const isError = $derived(Boolean(bookingsQuery.error));
|
|
49
|
+
const pageCount = $derived(Math.max(1, Math.ceil(total / pagination.pageSize)));
|
|
50
|
+
|
|
51
|
+
const t = $derived(
|
|
52
|
+
interfaceLanguage.current === 'pl'
|
|
53
|
+
? {
|
|
54
|
+
title: 'Rezerwacje',
|
|
55
|
+
search: 'Szukaj',
|
|
56
|
+
searchPlaceholder: 'Szukaj po numerze, imieniu lub e-mailu…',
|
|
57
|
+
filterStatus: 'Status',
|
|
58
|
+
number: 'Numer',
|
|
59
|
+
created: 'Utworzono',
|
|
60
|
+
customer: 'Klient',
|
|
61
|
+
total: 'Wartość',
|
|
62
|
+
balance: 'Saldo',
|
|
63
|
+
status: 'Status',
|
|
64
|
+
emptyTitle: 'Brak rezerwacji',
|
|
65
|
+
emptyDescription: 'Gdy ktoś zarezerwuje, pojawi się tutaj.',
|
|
66
|
+
noResults: 'Brak wyników.',
|
|
67
|
+
statusDraft: 'Czeka na zaliczkę',
|
|
68
|
+
statusReserved: 'Zarezerwowane',
|
|
69
|
+
statusPartiallyPaid: 'Częściowo opłacone',
|
|
70
|
+
statusPaid: 'Opłacone',
|
|
71
|
+
statusCompleted: 'Zakończone',
|
|
72
|
+
statusCancelled: 'Anulowane'
|
|
73
|
+
}
|
|
74
|
+
: {
|
|
75
|
+
title: 'Reservations',
|
|
76
|
+
search: 'Search',
|
|
77
|
+
searchPlaceholder: 'Search by number, name or email…',
|
|
78
|
+
filterStatus: 'Status',
|
|
79
|
+
number: 'Number',
|
|
80
|
+
created: 'Created',
|
|
81
|
+
customer: 'Customer',
|
|
82
|
+
total: 'Total',
|
|
83
|
+
balance: 'Balance',
|
|
84
|
+
status: 'Status',
|
|
85
|
+
emptyTitle: 'No reservations yet',
|
|
86
|
+
emptyDescription: 'Reservations will appear here as soon as someone books.',
|
|
87
|
+
noResults: 'No results.',
|
|
88
|
+
statusDraft: 'Awaiting deposit',
|
|
89
|
+
statusReserved: 'Reserved',
|
|
90
|
+
statusPartiallyPaid: 'Partially paid',
|
|
91
|
+
statusPaid: 'Paid',
|
|
92
|
+
statusCompleted: 'Completed',
|
|
93
|
+
statusCancelled: 'Cancelled'
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const dataFilters = $derived([
|
|
98
|
+
{
|
|
99
|
+
slug: 'status',
|
|
100
|
+
label: t.filterStatus,
|
|
101
|
+
options: [
|
|
102
|
+
{ value: 'draft', label: t.statusDraft },
|
|
103
|
+
{ value: 'reserved', label: t.statusReserved },
|
|
104
|
+
{ value: 'partially_paid', label: t.statusPartiallyPaid },
|
|
105
|
+
{ value: 'paid', label: t.statusPaid },
|
|
106
|
+
{ value: 'completed', label: t.statusCompleted },
|
|
107
|
+
{ value: 'cancelled', label: t.statusCancelled }
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
]);
|
|
111
|
+
const activeDataFilters = $derived({ status: statusFilter });
|
|
112
|
+
|
|
113
|
+
function scheduleSearchUpdate(value: string) {
|
|
114
|
+
if (searchDebounceTimer) clearTimeout(searchDebounceTimer);
|
|
115
|
+
searchDebounceTimer = setTimeout(() => {
|
|
116
|
+
appliedSearch = value.trim();
|
|
117
|
+
pagination = { ...pagination, pageIndex: 0 };
|
|
118
|
+
}, 350);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const columns = $derived.by<ColumnDef<BookingRow>[]>(() => [
|
|
122
|
+
{
|
|
123
|
+
accessorKey: 'number',
|
|
124
|
+
header: t.number,
|
|
125
|
+
cell: (info) =>
|
|
126
|
+
renderComponent(EntryLink, {
|
|
127
|
+
name: info.row.original.number,
|
|
128
|
+
url: `/admin/booking/reservations/${info.row.original.id}`
|
|
129
|
+
})
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
accessorKey: 'createdAt',
|
|
133
|
+
header: t.created,
|
|
134
|
+
cell: (info) => formatDateTime(info.row.original.createdAt, interfaceLanguage.current)
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
id: 'customer',
|
|
138
|
+
header: t.customer,
|
|
139
|
+
cell: (info) => {
|
|
140
|
+
const row = info.row.original;
|
|
141
|
+
const s = customerSummary(row.customer ?? {});
|
|
142
|
+
return renderComponent(EntryLink, {
|
|
143
|
+
name: s.name ?? s.email ?? '—',
|
|
144
|
+
url: `/admin/booking/reservations/${row.id}`,
|
|
145
|
+
slug: s.name && s.email ? s.email : undefined
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
id: 'gross',
|
|
151
|
+
header: t.total,
|
|
152
|
+
cell: (info) => formatCentsPrice(info.row.original.totals.gross, info.row.original.currency)
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: 'balance',
|
|
156
|
+
header: t.balance,
|
|
157
|
+
cell: (info) => formatCentsPrice(info.row.original.totals.balance, info.row.original.currency)
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
accessorKey: 'status',
|
|
161
|
+
header: t.status,
|
|
162
|
+
cell: (info) =>
|
|
163
|
+
renderComponent(StatusBadge, { variant: 'booking', status: info.row.original.status })
|
|
164
|
+
}
|
|
165
|
+
]);
|
|
166
|
+
</script>
|
|
167
|
+
|
|
168
|
+
<div class="p-5 pb-24 md:p-7">
|
|
169
|
+
<PageHeader title={t.title} count={!isLoading && !isError ? total : undefined} />
|
|
170
|
+
|
|
171
|
+
{#if !isLoading && !isError && total === 0 && !statusFilter && !appliedSearch}
|
|
172
|
+
<StateDisplay kind="empty" title={t.emptyTitle} description={t.emptyDescription} />
|
|
173
|
+
{:else}
|
|
174
|
+
<TableToolbar
|
|
175
|
+
{searchQuery}
|
|
176
|
+
searchPlaceholder={t.searchPlaceholder}
|
|
177
|
+
searchLabel={t.search}
|
|
178
|
+
onSearchChange={(q) => {
|
|
179
|
+
searchQuery = q;
|
|
180
|
+
scheduleSearchUpdate(q);
|
|
181
|
+
}}
|
|
182
|
+
hideStatusFilter
|
|
183
|
+
hideViewToggle
|
|
184
|
+
{dataFilters}
|
|
185
|
+
{activeDataFilters}
|
|
186
|
+
onDataFilterChange={(_slug, value) => {
|
|
187
|
+
statusFilter = value;
|
|
188
|
+
pagination = { ...pagination, pageIndex: 0 };
|
|
189
|
+
}}
|
|
190
|
+
/>
|
|
191
|
+
|
|
192
|
+
<div class="bg-card overflow-hidden rounded-xl border shadow-sm">
|
|
193
|
+
{#if isError}
|
|
194
|
+
<StateDisplay kind="error" />
|
|
195
|
+
{:else if isLoading && items.length === 0}
|
|
196
|
+
<StateDisplay kind="loading" />
|
|
197
|
+
{:else}
|
|
198
|
+
<DataTable
|
|
199
|
+
data={items}
|
|
200
|
+
{columns}
|
|
201
|
+
enablePagination
|
|
202
|
+
manualPagination
|
|
203
|
+
{pageCount}
|
|
204
|
+
rowCount={total}
|
|
205
|
+
{pagination}
|
|
206
|
+
onPaginationChange={(p) => (pagination = p)}
|
|
207
|
+
emptyTitle={t.noResults}
|
|
208
|
+
/>
|
|
209
|
+
|
|
210
|
+
<TablePagination
|
|
211
|
+
pageIndex={pagination.pageIndex}
|
|
212
|
+
pageSize={pagination.pageSize}
|
|
213
|
+
{pageCount}
|
|
214
|
+
totalItems={total}
|
|
215
|
+
onPageChange={(p) => (pagination = { ...pagination, pageIndex: p })}
|
|
216
|
+
onPageSizeChange={(s) => (pagination = { pageIndex: 0, pageSize: s })}
|
|
217
|
+
/>
|
|
218
|
+
{/if}
|
|
219
|
+
</div>
|
|
220
|
+
{/if}
|
|
221
|
+
</div>
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { getEntryThumbnail, type MediaThumbnailLookup } from '../../utils/entryThumbnail.js';
|
|
5
5
|
import { arrayMove } from '../../utils/arrayMove.js';
|
|
6
6
|
import { getRemotes } from '../../../sveltekit/index.js';
|
|
7
|
+
import { goto } from '$app/navigation';
|
|
7
8
|
import type { CollectionConfigWithType } from '../../../types/collections.js';
|
|
8
9
|
import DataTable from './data-table.svelte';
|
|
9
10
|
import type { ColumnDef, RowSelectionState, Table } from '@tanstack/table-core';
|
|
@@ -54,6 +55,8 @@
|
|
|
54
55
|
entryRestored: string;
|
|
55
56
|
entriesRestored: string;
|
|
56
57
|
entryDeleted: string;
|
|
58
|
+
entryDuplicated: string;
|
|
59
|
+
entryDuplicateFailed: string;
|
|
57
60
|
deleteConfirmTitle: string;
|
|
58
61
|
deleteConfirmDescription: string;
|
|
59
62
|
cancel: string;
|
|
@@ -74,6 +77,8 @@
|
|
|
74
77
|
entryRestored: 'Entry restored',
|
|
75
78
|
entriesRestored: 'Entries restored',
|
|
76
79
|
entryDeleted: 'Entry permanently deleted',
|
|
80
|
+
entryDuplicated: 'Duplicate created (draft)',
|
|
81
|
+
entryDuplicateFailed: 'Failed to duplicate entry',
|
|
77
82
|
deleteConfirmTitle: 'Delete entry permanently?',
|
|
78
83
|
deleteConfirmDescription:
|
|
79
84
|
'This action cannot be undone. The entry will be permanently deleted.',
|
|
@@ -94,6 +99,8 @@
|
|
|
94
99
|
entryRestored: 'Wpis przywrócony',
|
|
95
100
|
entriesRestored: 'Wpisy przywrócone',
|
|
96
101
|
entryDeleted: 'Wpis trwale usunięty',
|
|
102
|
+
entryDuplicated: 'Utworzono duplikat (szkic)',
|
|
103
|
+
entryDuplicateFailed: 'Nie udało się zduplikować wpisu',
|
|
97
104
|
deleteConfirmTitle: 'Usunąć wpis na stałe?',
|
|
98
105
|
deleteConfirmDescription: 'Ta akcja jest nieodwracalna. Wpis zostanie trwale usunięty.',
|
|
99
106
|
cancel: 'Anuluj',
|
|
@@ -310,7 +317,7 @@
|
|
|
310
317
|
return renderComponent(EntryLink, {
|
|
311
318
|
name: info.row.original.name,
|
|
312
319
|
url: info.row.original.url,
|
|
313
|
-
|
|
320
|
+
path: info.row.original.slug
|
|
314
321
|
});
|
|
315
322
|
}
|
|
316
323
|
},
|
|
@@ -374,7 +381,9 @@
|
|
|
374
381
|
entryUrl: info.row.original.url,
|
|
375
382
|
entryName: info.row.original.name,
|
|
376
383
|
onArchive: () => handleArchiveSingle(info.row.original.id),
|
|
377
|
-
...(isArchivedFilter
|
|
384
|
+
...(isArchivedFilter
|
|
385
|
+
? { onDelete: () => handleDelete(info.row.original.id), onRestore: () => handleRestoreSingle(info.row.original.id) }
|
|
386
|
+
: { onDuplicate: () => handleDuplicate(info.row.original.id) })
|
|
378
387
|
}),
|
|
379
388
|
enableSorting: false,
|
|
380
389
|
size: 50
|
|
@@ -393,6 +402,16 @@
|
|
|
393
402
|
override.release();
|
|
394
403
|
}
|
|
395
404
|
|
|
405
|
+
async function handleDuplicate(id: string) {
|
|
406
|
+
try {
|
|
407
|
+
const { id: newId } = await remotes.duplicateEntryCommand(id);
|
|
408
|
+
toast.success(lang[interfaceLanguage.current].entryDuplicated);
|
|
409
|
+
await goto(`/admin/entries/${newId}`);
|
|
410
|
+
} catch {
|
|
411
|
+
toast.error(lang[interfaceLanguage.current].entryDuplicateFailed);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
396
415
|
async function handleRestoreSingle(id: string) {
|
|
397
416
|
const override = entriesQuery.withOverride((old) => ({
|
|
398
417
|
...old,
|
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
type Props = {
|
|
3
3
|
name: string;
|
|
4
|
+
/** Admin edit link for this entry. */
|
|
4
5
|
url: string;
|
|
5
|
-
|
|
6
|
+
/** Public path of the entry — already absolute (`resolveEntryUrl`), never prefix it. */
|
|
7
|
+
path?: string;
|
|
6
8
|
};
|
|
7
9
|
|
|
8
|
-
let { name, url,
|
|
10
|
+
let { name, url, path }: Props = $props();
|
|
9
11
|
</script>
|
|
10
12
|
|
|
11
13
|
<div>
|
|
12
14
|
<a href={url} class="font-medium text-foreground hover:text-primary hover:underline">
|
|
13
15
|
{name}
|
|
14
16
|
</a>
|
|
15
|
-
{#if
|
|
16
|
-
<div class="text-[11px] text-muted-foreground font-mono mt-0.5 truncate max-w-[200px]"
|
|
17
|
+
{#if path}
|
|
18
|
+
<div class="text-[11px] text-muted-foreground font-mono mt-0.5 truncate max-w-[200px]">{path}</div>
|
|
17
19
|
{/if}
|
|
18
20
|
</div>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
type Props = {
|
|
2
2
|
name: string;
|
|
3
|
+
/** Admin edit link for this entry. */
|
|
3
4
|
url: string;
|
|
4
|
-
|
|
5
|
+
/** Public path of the entry — already absolute (`resolveEntryUrl`), never prefix it. */
|
|
6
|
+
path?: string;
|
|
5
7
|
};
|
|
6
8
|
declare const EntryLink: import("svelte").Component<Props, {}, "">;
|
|
7
9
|
type EntryLink = ReturnType<typeof EntryLink>;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import Archive from '@tabler/icons-svelte/icons/archive';
|
|
5
5
|
import ArchiveOff from '@tabler/icons-svelte/icons/archive-off';
|
|
6
6
|
import Trash from '@tabler/icons-svelte/icons/trash';
|
|
7
|
+
import Copy from '@tabler/icons-svelte/icons/copy';
|
|
7
8
|
import Button from '../../../components/ui/button/button.svelte';
|
|
8
9
|
import * as DropdownMenu from '../../../components/ui/dropdown-menu/index.js';
|
|
9
10
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
@@ -14,17 +15,18 @@
|
|
|
14
15
|
entryUrl: string;
|
|
15
16
|
entryName: string;
|
|
16
17
|
onArchive: () => void;
|
|
18
|
+
onDuplicate?: () => void;
|
|
17
19
|
onDelete?: () => void;
|
|
18
20
|
onRestore?: () => void;
|
|
19
21
|
};
|
|
20
22
|
|
|
21
|
-
let { entryUrl, entryName, onArchive, onDelete, onRestore }: Props = $props();
|
|
23
|
+
let { entryUrl, entryName, onArchive, onDuplicate, onDelete, onRestore }: Props = $props();
|
|
22
24
|
|
|
23
25
|
const interfaceLanguage = useInterfaceLanguage();
|
|
24
26
|
|
|
25
|
-
const lang: Record<InterfaceLanguage, { open: string; archive: string; restore: string; delete: string; moreActions: string }> = {
|
|
26
|
-
en: { open: 'Open', archive: 'Archive', restore: 'Restore', delete: 'Delete', moreActions: 'More actions for' },
|
|
27
|
-
pl: { open: 'Otwórz', archive: 'Archiwizuj', restore: 'Przywróć', delete: 'Usuń', moreActions: 'Więcej akcji dla' }
|
|
27
|
+
const lang: Record<InterfaceLanguage, { open: string; duplicate: string; archive: string; restore: string; delete: string; moreActions: string }> = {
|
|
28
|
+
en: { open: 'Open', duplicate: 'Duplicate', archive: 'Archive', restore: 'Restore', delete: 'Delete', moreActions: 'More actions for' },
|
|
29
|
+
pl: { open: 'Otwórz', duplicate: 'Duplikuj', archive: 'Archiwizuj', restore: 'Przywróć', delete: 'Usuń', moreActions: 'Więcej akcji dla' }
|
|
28
30
|
};
|
|
29
31
|
|
|
30
32
|
const t = $derived(lang[interfaceLanguage.current]);
|
|
@@ -51,6 +53,12 @@
|
|
|
51
53
|
{t.open}
|
|
52
54
|
</DropdownMenu.Item>
|
|
53
55
|
<DropdownMenu.Separator />
|
|
56
|
+
{#if onDuplicate}
|
|
57
|
+
<DropdownMenu.Item onclick={onDuplicate} data-testid="row-action-duplicate">
|
|
58
|
+
<Copy class="mr-2 size-4" />
|
|
59
|
+
{t.duplicate}
|
|
60
|
+
</DropdownMenu.Item>
|
|
61
|
+
{/if}
|
|
54
62
|
{#if onRestore}
|
|
55
63
|
<DropdownMenu.Item onclick={onRestore} data-testid="row-action-restore">
|
|
56
64
|
<ArchiveOff class="mr-2 size-4" />
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { EntryStatus } from '../../../types/entries.js';
|
|
3
3
|
import type { OrderStatus } from '../../../shop/types.js';
|
|
4
|
+
import type { BookingStatus } from '../../../booking/state-machine.js';
|
|
4
5
|
import { useInterfaceLanguage } from '../../state/interface-language.svelte.js';
|
|
5
6
|
import type { InterfaceLanguage } from '../../../types/languages.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* StatusBadge accepts
|
|
9
|
+
* StatusBadge accepts four usage modes (variants):
|
|
9
10
|
* - entry (default): pass `status` as `EntryStatus`
|
|
10
11
|
* - order: pass `variant="order"` and `status` as `OrderStatus`
|
|
12
|
+
* - booking: pass `variant="booking"` and `status` as `BookingStatus`
|
|
11
13
|
* - boolean: pass `variant="boolean"` and `active: boolean`
|
|
12
14
|
*
|
|
13
15
|
* Type stays permissive (FlatProps) so consumers can pass any combination;
|
|
14
16
|
* runtime narrows by `variant` and falls back to muted style on unknown.
|
|
15
17
|
*/
|
|
16
18
|
type Props = {
|
|
17
|
-
variant?: 'entry' | 'order' | 'boolean';
|
|
18
|
-
status?: EntryStatus | OrderStatus;
|
|
19
|
+
variant?: 'entry' | 'order' | 'boolean' | 'booking';
|
|
20
|
+
status?: EntryStatus | OrderStatus | BookingStatus;
|
|
19
21
|
active?: boolean;
|
|
20
22
|
activeLabel?: string;
|
|
21
23
|
inactiveLabel?: string;
|
|
@@ -92,6 +94,35 @@
|
|
|
92
94
|
}
|
|
93
95
|
};
|
|
94
96
|
|
|
97
|
+
const bookingStyles: Record<BookingStatus, StatusStyle> = {
|
|
98
|
+
draft: { dot: '◐', classes: 'bg-warning-bg text-warning' },
|
|
99
|
+
reserved: { dot: '●', classes: 'bg-info-bg text-info' },
|
|
100
|
+
partially_paid: { dot: '◐', classes: 'bg-warning-bg text-warning' },
|
|
101
|
+
paid: { dot: '●', classes: 'bg-success-bg text-success' },
|
|
102
|
+
completed: { dot: '●', classes: 'bg-success-bg text-success' },
|
|
103
|
+
cancelled: { dot: '○', classes: 'bg-muted text-muted-foreground' }
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const bookingLabels: Record<InterfaceLanguage, Record<BookingStatus, string>> = {
|
|
107
|
+
en: {
|
|
108
|
+
draft: 'Awaiting deposit',
|
|
109
|
+
reserved: 'Reserved',
|
|
110
|
+
partially_paid: 'Partially paid',
|
|
111
|
+
paid: 'Paid',
|
|
112
|
+
completed: 'Completed',
|
|
113
|
+
cancelled: 'Cancelled'
|
|
114
|
+
},
|
|
115
|
+
pl: {
|
|
116
|
+
// „Szkic" nic nie mówi osobie prowadzącej rezerwacje — ona myśli „czeka na zaliczkę".
|
|
117
|
+
draft: 'Czeka na zaliczkę',
|
|
118
|
+
reserved: 'Zarezerwowane',
|
|
119
|
+
partially_paid: 'Częściowo opłacone',
|
|
120
|
+
paid: 'Opłacone',
|
|
121
|
+
completed: 'Zakończone',
|
|
122
|
+
cancelled: 'Anulowane'
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
95
126
|
const booleanDefaults: Record<InterfaceLanguage, { active: string; inactive: string }> = {
|
|
96
127
|
en: { active: 'Active', inactive: 'Inactive' },
|
|
97
128
|
pl: { active: 'Aktywny', inactive: 'Nieaktywny' }
|
|
@@ -106,6 +137,11 @@
|
|
|
106
137
|
if (!s || !(s in orderStyles)) return { style: fallbackStyle, label: String(s ?? '') };
|
|
107
138
|
return { style: orderStyles[s], label: orderLabels[lang][s] };
|
|
108
139
|
}
|
|
140
|
+
if (variant === 'booking') {
|
|
141
|
+
const s = status as BookingStatus | undefined;
|
|
142
|
+
if (!s || !(s in bookingStyles)) return { style: fallbackStyle, label: String(s ?? '') };
|
|
143
|
+
return { style: bookingStyles[s], label: bookingLabels[lang][s] };
|
|
144
|
+
}
|
|
109
145
|
if (variant === 'boolean') {
|
|
110
146
|
const isActive = active === true;
|
|
111
147
|
const fallback = booleanDefaults[lang];
|
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import type { EntryStatus } from '../../../types/entries.js';
|
|
2
2
|
import type { OrderStatus } from '../../../shop/types.js';
|
|
3
|
+
import type { BookingStatus } from '../../../booking/state-machine.js';
|
|
3
4
|
/**
|
|
4
|
-
* StatusBadge accepts
|
|
5
|
+
* StatusBadge accepts four usage modes (variants):
|
|
5
6
|
* - entry (default): pass `status` as `EntryStatus`
|
|
6
7
|
* - order: pass `variant="order"` and `status` as `OrderStatus`
|
|
8
|
+
* - booking: pass `variant="booking"` and `status` as `BookingStatus`
|
|
7
9
|
* - boolean: pass `variant="boolean"` and `active: boolean`
|
|
8
10
|
*
|
|
9
11
|
* Type stays permissive (FlatProps) so consumers can pass any combination;
|
|
10
12
|
* runtime narrows by `variant` and falls back to muted style on unknown.
|
|
11
13
|
*/
|
|
12
14
|
type Props = {
|
|
13
|
-
variant?: 'entry' | 'order' | 'boolean';
|
|
14
|
-
status?: EntryStatus | OrderStatus;
|
|
15
|
+
variant?: 'entry' | 'order' | 'boolean' | 'booking';
|
|
16
|
+
status?: EntryStatus | OrderStatus | BookingStatus;
|
|
15
17
|
active?: boolean;
|
|
16
18
|
activeLabel?: string;
|
|
17
19
|
inactiveLabel?: string;
|
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
import { getCollectionEntryDisplayLabel } from '../../utils/entryLabel.js';
|
|
34
34
|
import { getFieldsFromConfig, hasLayout } from '../../../core/fields/layoutUtils.js';
|
|
35
35
|
import { createHybridContext } from './hybrid/hybrid-context.svelte.js';
|
|
36
|
+
import { createPreviewViewsContext } from './preview-views-context.svelte.js';
|
|
37
|
+
import { normalizePreviews, buildPreviewUrl } from './preview-views.js';
|
|
36
38
|
import { onMount, setContext, tick } from 'svelte';
|
|
37
39
|
import { get } from 'svelte/store';
|
|
38
40
|
const contentLanguage = getContentLanguage();
|
|
@@ -111,6 +113,11 @@
|
|
|
111
113
|
let { collection } = entry;
|
|
112
114
|
const isArchived = $derived(!!entry.archivedAt);
|
|
113
115
|
|
|
116
|
+
// Preview views: `previewUrl` is normalized to a single view, so everything
|
|
117
|
+
// below only ever deals with an array. Empty array = collection has no preview.
|
|
118
|
+
const previewViews = createPreviewViewsContext(normalizePreviews(collection));
|
|
119
|
+
const hasPreview = previewViews.views.length > 0;
|
|
120
|
+
|
|
114
121
|
setContext('cms-path-template', collection.pathTemplate || null);
|
|
115
122
|
setContext('cms-entry-published', entry.publishedVersions[contentLanguage.current] != null);
|
|
116
123
|
setContext('cms-entry-id', entry.id);
|
|
@@ -431,9 +438,17 @@
|
|
|
431
438
|
}
|
|
432
439
|
}
|
|
433
440
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
441
|
+
// Src of the active view — switching a view swaps the iframe src, which reloads
|
|
442
|
+
// the preview page; it then asks for the current (unsaved) form data via
|
|
443
|
+
// `preview-ready`, so nothing in the editor is lost.
|
|
444
|
+
const previewSrc = $derived(
|
|
445
|
+
previewViews.activeView
|
|
446
|
+
? buildPreviewUrl(previewViews.activeView, String(editingEntry.id))
|
|
447
|
+
: ''
|
|
448
|
+
);
|
|
449
|
+
const previewOrigin = $derived(
|
|
450
|
+
previewSrc ? getOriginFromUrl(previewSrc) : window.location.origin
|
|
451
|
+
);
|
|
437
452
|
|
|
438
453
|
const updatePreview = useDebounce(
|
|
439
454
|
async (window: Window, form: SuperForm<Record<string, unknown>>) => {
|
|
@@ -466,16 +481,16 @@
|
|
|
466
481
|
|
|
467
482
|
// Subscribe to form changes for preview updates
|
|
468
483
|
onMount(() => {
|
|
469
|
-
if (!
|
|
484
|
+
if (!hasPreview) return;
|
|
470
485
|
const unsub = form.form.subscribe(() => {
|
|
471
486
|
onUpdate();
|
|
472
487
|
});
|
|
473
488
|
return () => unsub();
|
|
474
489
|
});
|
|
475
490
|
|
|
476
|
-
// Enable hybrid mode when collection has
|
|
491
|
+
// Enable hybrid mode when the collection has at least one preview view
|
|
477
492
|
$effect(() => {
|
|
478
|
-
hybridContext.enabled =
|
|
493
|
+
hybridContext.enabled = hasPreview;
|
|
479
494
|
});
|
|
480
495
|
|
|
481
496
|
// Send current form data + hybrid mode state to iframe
|
|
@@ -605,7 +620,7 @@
|
|
|
605
620
|
});
|
|
606
621
|
|
|
607
622
|
const t = $derived(lang[interfaceLanguage.current]);
|
|
608
|
-
const isHybrid = $derived(hybridContext.mode === 'hybrid' &&
|
|
623
|
+
const isHybrid = $derived(hybridContext.mode === 'hybrid' && hasPreview);
|
|
609
624
|
|
|
610
625
|
const errorPaths = $derived(new Set(validationErrors.map((e) => e.path)));
|
|
611
626
|
|
|
@@ -752,8 +767,10 @@
|
|
|
752
767
|
<div class="bg-accent h-full animate-pulse rounded-md"></div>
|
|
753
768
|
{:then { default: HybridPreview }}
|
|
754
769
|
<HybridPreview
|
|
755
|
-
{
|
|
756
|
-
{
|
|
770
|
+
{previewSrc}
|
|
771
|
+
views={previewViews.views}
|
|
772
|
+
activeName={previewViews.activeName}
|
|
773
|
+
onSelectView={(name) => previewViews.select(name)}
|
|
757
774
|
bind:previewIframe
|
|
758
775
|
bind:sizePreset
|
|
759
776
|
{size}
|