@prenta/admin 2.1.0 → 2.2.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 (26) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/__tests__/components/document-locale-switcher.test.d.ts +2 -0
  3. package/dist/__tests__/components/document-locale-switcher.test.d.ts.map +1 -0
  4. package/dist/__tests__/components/document-locale-switcher.test.js +78 -0
  5. package/dist/__tests__/components/document-locale-switcher.test.js.map +1 -0
  6. package/dist/components/DocumentLocaleSwitcher.d.ts +15 -0
  7. package/dist/components/DocumentLocaleSwitcher.d.ts.map +1 -0
  8. package/dist/components/DocumentLocaleSwitcher.js +66 -0
  9. package/dist/components/DocumentLocaleSwitcher.js.map +1 -0
  10. package/dist/prenta-admin.css +1 -1
  11. package/dist/views/page-editor/EditorTopBar.d.ts +4 -1
  12. package/dist/views/page-editor/EditorTopBar.d.ts.map +1 -1
  13. package/dist/views/page-editor/EditorTopBar.js +2 -2
  14. package/dist/views/page-editor/EditorTopBar.js.map +1 -1
  15. package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
  16. package/dist/views/page-editor/PageSectionEditor.js +2 -1
  17. package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
  18. package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
  19. package/dist/views/post-editor/PostSectionEditor.js +2 -1
  20. package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
  21. package/package.json +4 -4
  22. package/src/__tests__/components/document-locale-switcher.test.tsx +111 -0
  23. package/src/components/DocumentLocaleSwitcher.tsx +140 -0
  24. package/src/views/page-editor/EditorTopBar.tsx +4 -0
  25. package/src/views/page-editor/PageSectionEditor.tsx +12 -0
  26. package/src/views/post-editor/PostSectionEditor.tsx +12 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @actuate-media/cms-admin
2
2
 
3
+ ## 2.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 8cf5922: Page and post editors can switch to another locale of the same document. Choosing a locale that does not exist yet creates a draft translation in that locale.
8
+
3
9
  ## 2.1.0
4
10
 
5
11
  ### Minor Changes
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=document-locale-switcher.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-locale-switcher.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/components/document-locale-switcher.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,78 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // @vitest-environment happy-dom
3
+ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
4
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
5
+ import { DocumentLocaleSwitcher } from '../../components/DocumentLocaleSwitcher.js';
6
+ import { LocaleProvider } from '../../components/LocaleProvider.js';
7
+ import { cmsApi } from '../../lib/api.js';
8
+ vi.mock('../../lib/api.js', () => ({
9
+ cmsApi: vi.fn(),
10
+ }));
11
+ const cmsApiMock = vi.mocked(cmsApi);
12
+ const locales = {
13
+ i18n: {
14
+ defaultLocale: 'en',
15
+ locales: [
16
+ { code: 'en', label: 'English' },
17
+ { code: 'es', label: 'Spanish' },
18
+ ],
19
+ },
20
+ };
21
+ function renderSwitcher(onNavigate = vi.fn()) {
22
+ render(_jsx(LocaleProvider, { config: locales, children: _jsx(DocumentLocaleSwitcher, { collection: "pages", documentId: "page-1", canCreate: true, editorPath: (id) => `/pages/${id}/edit`, onNavigate: onNavigate }) }));
23
+ return onNavigate;
24
+ }
25
+ describe('DocumentLocaleSwitcher', () => {
26
+ beforeEach(() => {
27
+ cmsApiMock.mockReset();
28
+ cmsApiMock.mockResolvedValue({
29
+ data: {
30
+ locale: 'en',
31
+ translations: [{ id: 'page-1', locale: 'en', status: 'PUBLISHED', title: 'About' }],
32
+ },
33
+ status: 200,
34
+ });
35
+ });
36
+ it('hides itself when the site has a single locale', () => {
37
+ render(_jsx(LocaleProvider, { config: { i18n: { defaultLocale: 'en', locales: [{ code: 'en', label: 'English' }] } }, children: _jsx(DocumentLocaleSwitcher, { collection: "pages", documentId: "page-1", canCreate: true, editorPath: (id) => `/pages/${id}/edit`, onNavigate: vi.fn() }) }));
38
+ expect(screen.queryByRole('button', { name: /Translations/ })).toBeNull();
39
+ });
40
+ it('opens an existing translation', async () => {
41
+ cmsApiMock.mockResolvedValue({
42
+ data: {
43
+ locale: 'en',
44
+ translations: [
45
+ { id: 'page-1', locale: 'en', status: 'PUBLISHED', title: 'About' },
46
+ { id: 'page-es', locale: 'es', status: 'DRAFT', title: 'About' },
47
+ ],
48
+ },
49
+ status: 200,
50
+ });
51
+ const onNavigate = renderSwitcher();
52
+ await waitFor(() => expect(screen.getByRole('button', { name: 'Translations, English' })).toBeTruthy());
53
+ fireEvent.keyDown(screen.getByRole('button', { name: 'Translations, English' }), {
54
+ key: 'Enter',
55
+ });
56
+ fireEvent.click(screen.getByRole('menuitem', { name: /Spanish/ }));
57
+ expect(onNavigate).toHaveBeenCalledWith('/pages/page-es/edit');
58
+ expect(cmsApiMock).toHaveBeenCalledTimes(1);
59
+ });
60
+ it('creates a draft and opens it', async () => {
61
+ const onNavigate = renderSwitcher();
62
+ await waitFor(() => expect(screen.getByRole('button', { name: 'Translations, English' })).toBeTruthy());
63
+ cmsApiMock.mockResolvedValueOnce({
64
+ data: { id: 'page-es', locale: 'es', created: true },
65
+ status: 201,
66
+ });
67
+ fireEvent.keyDown(screen.getByRole('button', { name: 'Translations, English' }), {
68
+ key: 'Enter',
69
+ });
70
+ fireEvent.click(screen.getByRole('menuitem', { name: /Spanish/ }));
71
+ await waitFor(() => expect(onNavigate).toHaveBeenCalledWith('/pages/page-es/edit'));
72
+ expect(cmsApiMock).toHaveBeenLastCalledWith('/collections/pages/page-1/translations', {
73
+ method: 'POST',
74
+ body: JSON.stringify({ locale: 'es' }),
75
+ });
76
+ });
77
+ });
78
+ //# sourceMappingURL=document-locale-switcher.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-locale-switcher.test.js","sourceRoot":"","sources":["../../../src/__tests__/components/document-locale-switcher.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ interface DocumentLocaleSwitcherProps {
2
+ collection: string;
3
+ documentId: string;
4
+ canCreate: boolean;
5
+ editorPath: (id: string) => string;
6
+ onNavigate: (path: string) => void;
7
+ }
8
+ /**
9
+ * Switches the open document to another locale, creating a draft translation
10
+ * when that locale does not exist yet. Hidden when the site has fewer than
11
+ * two locales — the header language control is a different setting.
12
+ */
13
+ export declare function DocumentLocaleSwitcher({ collection, documentId, canCreate, editorPath, onNavigate, }: DocumentLocaleSwitcherProps): import("react/jsx-runtime").JSX.Element | null;
14
+ export {};
15
+ //# sourceMappingURL=DocumentLocaleSwitcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentLocaleSwitcher.d.ts","sourceRoot":"","sources":["../../src/components/DocumentLocaleSwitcher.tsx"],"names":[],"mappings":"AA4BA,UAAU,2BAA2B;IACnC,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;IAClC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACnC;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,UAAU,EACV,UAAU,EACV,SAAS,EACT,UAAU,EACV,UAAU,GACX,EAAE,2BAA2B,kDA4F7B"}
@@ -0,0 +1,66 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from 'react';
4
+ import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
5
+ import { ChevronDown, Globe } from 'lucide-react';
6
+ import { toast } from 'sonner';
7
+ import { cmsApi } from '../lib/api.js';
8
+ import { adminPortalContainer } from '../lib/portal-container.js';
9
+ import { useLocale } from './LocaleProvider.js';
10
+ /**
11
+ * Switches the open document to another locale, creating a draft translation
12
+ * when that locale does not exist yet. Hidden when the site has fewer than
13
+ * two locales — the header language control is a different setting.
14
+ */
15
+ export function DocumentLocaleSwitcher({ collection, documentId, canCreate, editorPath, onNavigate, }) {
16
+ const { locales } = useLocale();
17
+ const enabled = locales.length > 1;
18
+ const [currentLocale, setCurrentLocale] = useState(null);
19
+ const [siblings, setSiblings] = useState([]);
20
+ const [busy, setBusy] = useState(false);
21
+ useEffect(() => {
22
+ if (!enabled)
23
+ return;
24
+ let cancelled = false;
25
+ cmsApi(`/collections/${encodeURIComponent(collection)}/${encodeURIComponent(documentId)}/translations`).then((result) => {
26
+ if (cancelled || !result.data)
27
+ return;
28
+ setCurrentLocale(result.data.locale);
29
+ setSiblings(result.data.translations);
30
+ });
31
+ return () => {
32
+ cancelled = true;
33
+ };
34
+ }, [collection, documentId, enabled]);
35
+ if (!enabled)
36
+ return null;
37
+ const current = locales.find((locale) => locale.code === currentLocale);
38
+ const label = current?.code.toUpperCase() ?? 'Locale';
39
+ async function choose(code) {
40
+ const sibling = siblings.find((row) => row.locale === code);
41
+ if (sibling) {
42
+ if (sibling.id !== documentId)
43
+ onNavigate(editorPath(sibling.id));
44
+ return;
45
+ }
46
+ if (!canCreate || busy)
47
+ return;
48
+ setBusy(true);
49
+ const result = await cmsApi(`/collections/${encodeURIComponent(collection)}/${encodeURIComponent(documentId)}/translations`, { method: 'POST', body: JSON.stringify({ locale: code }) });
50
+ setBusy(false);
51
+ if (result.error || !result.data?.id) {
52
+ toast.error(result.error ?? 'Could not create the translation');
53
+ return;
54
+ }
55
+ onNavigate(editorPath(result.data.id));
56
+ }
57
+ return (_jsxs(DropdownMenu.Root, { children: [_jsx(DropdownMenu.Trigger, { asChild: true, children: _jsxs("button", { type: "button", disabled: busy, "aria-label": `Translations, ${current?.label ?? 'locale not set'}`, title: "Open or create a translation", className: "text-muted-foreground hover:text-foreground hover:bg-accent inline-flex shrink-0 items-center gap-1 rounded-lg px-2 py-1 text-sm disabled:cursor-not-allowed disabled:opacity-50", children: [_jsx(Globe, { className: "h-4 w-4", "aria-hidden": true }), label, _jsx(ChevronDown, { className: "h-3.5 w-3.5", "aria-hidden": true })] }) }), _jsx(DropdownMenu.Portal, { container: adminPortalContainer(), children: _jsx(DropdownMenu.Content, { align: "start", sideOffset: 6, className: "border-border bg-popover z-[120] min-w-40 rounded-lg border p-1 shadow-md", children: locales.map((locale) => {
58
+ const sibling = siblings.find((row) => row.locale === locale.code);
59
+ const isCurrent = locale.code === currentLocale;
60
+ const canChoose = Boolean(sibling) || canCreate;
61
+ return (_jsxs(DropdownMenu.Item, { disabled: !canChoose || busy, onSelect: () => {
62
+ void choose(locale.code);
63
+ }, className: "hover:bg-accent focus:bg-accent data-[disabled]:text-muted-foreground flex cursor-pointer items-center justify-between gap-3 rounded-md px-2.5 py-1.5 text-sm outline-none data-[disabled]:cursor-not-allowed", children: [_jsx("span", { children: locale.label }), _jsx("span", { className: "text-muted-foreground text-xs", children: isCurrent ? 'Current' : sibling ? sibling.status : 'New draft' })] }, locale.code));
64
+ }) }) })] }));
65
+ }
66
+ //# sourceMappingURL=DocumentLocaleSwitcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentLocaleSwitcher.js","sourceRoot":"","sources":["../../src/components/DocumentLocaleSwitcher.tsx"],"names":[],"mappings":"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"}