@actuate-media/cms-admin 0.76.0 → 0.76.1
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 +28 -0
- package/dist/__tests__/layout/sidebar-plugin-nav.test.d.ts +2 -0
- package/dist/__tests__/layout/sidebar-plugin-nav.test.d.ts.map +1 -0
- package/dist/__tests__/layout/sidebar-plugin-nav.test.js +46 -0
- package/dist/__tests__/layout/sidebar-plugin-nav.test.js.map +1 -0
- package/dist/__tests__/router/navigation-blocker.test.d.ts +2 -0
- package/dist/__tests__/router/navigation-blocker.test.d.ts.map +1 -0
- package/dist/__tests__/router/navigation-blocker.test.js +69 -0
- package/dist/__tests__/router/navigation-blocker.test.js.map +1 -0
- package/dist/__tests__/views/article-body-section.render.test.d.ts +2 -0
- package/dist/__tests__/views/article-body-section.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/article-body-section.render.test.js +24 -0
- package/dist/__tests__/views/article-body-section.render.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Sidebar.js +17 -0
- package/dist/layout/Sidebar.js.map +1 -1
- package/dist/router/index.d.ts +13 -0
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +49 -0
- package/dist/router/index.js.map +1 -1
- package/dist/views/DocumentEdit.d.ts.map +1 -1
- package/dist/views/DocumentEdit.js +4 -9
- package/dist/views/DocumentEdit.js.map +1 -1
- package/dist/views/page-builder/PageBuilder.d.ts.map +1 -1
- package/dist/views/page-builder/PageBuilder.js +3 -0
- package/dist/views/page-builder/PageBuilder.js.map +1 -1
- package/dist/views/page-editor/PageSectionEditor.d.ts.map +1 -1
- package/dist/views/page-editor/PageSectionEditor.js +3 -11
- package/dist/views/page-editor/PageSectionEditor.js.map +1 -1
- package/dist/views/page-editor/sections/ArticleBodySection.d.ts.map +1 -1
- package/dist/views/page-editor/sections/ArticleBodySection.js +1 -1
- package/dist/views/page-editor/sections/ArticleBodySection.js.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.d.ts.map +1 -1
- package/dist/views/post-editor/PostSectionEditor.js +3 -11
- package/dist/views/post-editor/PostSectionEditor.js.map +1 -1
- package/dist/views/post-editor/PostTemplateEditor.d.ts.map +1 -1
- package/dist/views/post-editor/PostTemplateEditor.js +3 -10
- package/dist/views/post-editor/PostTemplateEditor.js.map +1 -1
- package/package.json +4 -3
- package/src/__tests__/layout/sidebar-plugin-nav.test.ts +50 -0
- package/src/__tests__/router/navigation-blocker.test.ts +80 -0
- package/src/__tests__/views/article-body-section.render.test.tsx +32 -0
- package/src/layout/Sidebar.tsx +19 -0
- package/src/router/index.ts +61 -0
- package/src/styles/theme.css +91 -0
- package/src/views/DocumentEdit.tsx +4 -8
- package/src/views/page-builder/PageBuilder.tsx +4 -0
- package/src/views/page-editor/PageSectionEditor.tsx +3 -10
- package/src/views/page-editor/sections/ArticleBodySection.tsx +1 -4
- package/src/views/post-editor/PostSectionEditor.tsx +3 -10
- package/src/views/post-editor/PostTemplateEditor.tsx +3 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @actuate-media/cms-admin
|
|
2
2
|
|
|
3
|
+
## 0.76.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f75df17: Prevent silent data loss when navigating away from an editor with unsaved
|
|
8
|
+
changes. The editors previously guarded only against browser unload/refresh
|
|
9
|
+
(`beforeunload`), which never fires on the admin's client-side (SPA) navigation —
|
|
10
|
+
so clicking Cancel, a sidebar/breadcrumb link, or a command-palette entry with
|
|
11
|
+
unsaved edits discarded them without warning. `navigate()` now confirms before
|
|
12
|
+
leaving when any editor has unsaved changes, via a shared `useNavigationBlocker`
|
|
13
|
+
hook wired into the document, page, post, post-template, and page-builder
|
|
14
|
+
editors (also fixing the page builder, which had no guard at all).
|
|
15
|
+
- 31bdfbd: Fix article body canvas preview so rich-text headings render with typography matching the TipTap editor. Replaces non-functional `prose` classes with scoped `actuate-rich-text` styles.
|
|
16
|
+
- 041a228: Add the MIT `license` field to every published package (previously missing) and correct `repository.url` to `github.com/actuate-media/actuatecms` (13 packages carried the wrong org).
|
|
17
|
+
- 898a3f8: Make plugins actually extend the CMS. Previously `config.plugins` only had their
|
|
18
|
+
`hooks` harvested — a plugin's `collections`, `init`, `fields`, and
|
|
19
|
+
`adminNavItems` were declared on the type but never consumed, so adding a plugin
|
|
20
|
+
registered nothing.
|
|
21
|
+
|
|
22
|
+
`defineConfig` now runs a plugin runner (`applyPlugins`): for each plugin, in
|
|
23
|
+
order, it applies `init(config)`, merges the plugin's `collections` (the
|
|
24
|
+
consumer's config and earlier plugins win on slug conflicts, so a plugin can
|
|
25
|
+
never clobber your collection), and accumulates reusable `fields` presets and
|
|
26
|
+
`adminNavItems`. Merged plugin collections flow through the existing collection
|
|
27
|
+
registry, so they are immediately manageable in the admin (the sidebar derives
|
|
28
|
+
its Content nav from `config.collections`) and queryable over REST. The admin
|
|
29
|
+
sidebar also renders plugin-contributed `adminNavItems` (deduped by path).
|
|
30
|
+
|
|
3
31
|
## 0.76.0
|
|
4
32
|
|
|
5
33
|
### Minor Changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar-plugin-nav.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/layout/sidebar-plugin-nav.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { buildNavItems } from '../../layout/Sidebar.js';
|
|
3
|
+
// Plugin adminNavItems (collected onto `_pluginNavItems` by cms-core's
|
|
4
|
+
// applyPlugins) must surface in the admin sidebar, without doubling a built-in
|
|
5
|
+
// destination or one of the plugin's own collections.
|
|
6
|
+
const baseCollections = {
|
|
7
|
+
collections: {
|
|
8
|
+
pages: { slug: 'pages', labels: { singular: 'Page', plural: 'Pages' }, type: 'page' },
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
describe('buildNavItems — plugin nav items', () => {
|
|
12
|
+
it('adds a plugin-contributed custom nav link', () => {
|
|
13
|
+
const items = buildNavItems({
|
|
14
|
+
...baseCollections,
|
|
15
|
+
_pluginNavItems: [{ label: 'Redirects', icon: 'arrow-right-left', path: '/redirects' }],
|
|
16
|
+
});
|
|
17
|
+
const redirects = items.find((i) => i.path === '/redirects');
|
|
18
|
+
expect(redirects).toBeDefined();
|
|
19
|
+
expect(redirects?.label).toBe('Redirects');
|
|
20
|
+
expect(redirects?.group).toBe('Content');
|
|
21
|
+
});
|
|
22
|
+
it('does not double a built-in destination path', () => {
|
|
23
|
+
const items = buildNavItems({
|
|
24
|
+
...baseCollections,
|
|
25
|
+
_pluginNavItems: [{ label: 'Media Library', icon: 'image', path: '/media' }],
|
|
26
|
+
});
|
|
27
|
+
expect(items.filter((i) => i.path === '/media')).toHaveLength(1);
|
|
28
|
+
});
|
|
29
|
+
it('falls back to a default icon for an unknown icon string and still renders', () => {
|
|
30
|
+
const items = buildNavItems({
|
|
31
|
+
...baseCollections,
|
|
32
|
+
_pluginNavItems: [{ label: 'Custom', icon: 'no-such-icon', path: '/custom' }],
|
|
33
|
+
});
|
|
34
|
+
const custom = items.find((i) => i.path === '/custom');
|
|
35
|
+
expect(custom).toBeDefined();
|
|
36
|
+
expect(custom?.icon).toBeTruthy();
|
|
37
|
+
});
|
|
38
|
+
it('ignores malformed plugin nav entries', () => {
|
|
39
|
+
const items = buildNavItems({
|
|
40
|
+
...baseCollections,
|
|
41
|
+
_pluginNavItems: [{ label: 'No path' }, null, { path: '/ok', label: 'Ok', icon: 'menu' }],
|
|
42
|
+
});
|
|
43
|
+
expect(items.find((i) => i.path === '/ok')).toBeDefined();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
//# sourceMappingURL=sidebar-plugin-nav.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar-plugin-nav.test.js","sourceRoot":"","sources":["../../../src/__tests__/layout/sidebar-plugin-nav.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAEvD,uEAAuE;AACvE,+EAA+E;AAC/E,sDAAsD;AACtD,MAAM,eAAe,GAAG;IACtB,WAAW,EAAE;QACX,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;KACtF;CACF,CAAA;AAED,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,KAAK,GAAG,aAAa,CAAC;YAC1B,GAAG,eAAe;YAClB,eAAe,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;SACxF,CAAC,CAAA;QACF,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;QAC5D,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAA;QAC/B,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAA;QAC1C,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACrD,MAAM,KAAK,GAAG,aAAa,CAAC;YAC1B,GAAG,eAAe;YAClB,eAAe,EAAE,CAAC,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;SAC7E,CAAC,CAAA;QACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;IAClE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2EAA2E,EAAE,GAAG,EAAE;QACnF,MAAM,KAAK,GAAG,aAAa,CAAC;YAC1B,GAAG,eAAe;YAClB,eAAe,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;SAC9E,CAAC,CAAA;QACF,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAA;QACtD,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAA;QAC5B,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,UAAU,EAAE,CAAA;IACnC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,KAAK,GAAG,aAAa,CAAC;YAC1B,GAAG,eAAe;YAClB,eAAe,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SAC1F,CAAC,CAAA;QACF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IAC3D,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation-blocker.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/router/navigation-blocker.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import { act, renderHook } from '@testing-library/react';
|
|
4
|
+
import { hasBlockingNavigation, NAVIGATION_CONFIRM_MESSAGE, registerNavigationBlocker, useAdminRouter, useNavigationBlocker, } from '../../router/index.js';
|
|
5
|
+
// Guards against silent data loss: an in-app route change (Cancel, sidebar /
|
|
6
|
+
// breadcrumb links, command palette) must confirm before discarding an editor's
|
|
7
|
+
// unsaved changes — beforeunload only covers hard reloads, never SPA navigation.
|
|
8
|
+
describe('navigation blocker', () => {
|
|
9
|
+
let confirmMock;
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
// Reset the URL so each test's router mounts at '/' (pushState from a prior
|
|
12
|
+
// test would otherwise leak into window.location and skew currentPath).
|
|
13
|
+
window.history.replaceState(null, '', '/admin');
|
|
14
|
+
confirmMock = vi.fn(() => true);
|
|
15
|
+
window.confirm =
|
|
16
|
+
confirmMock;
|
|
17
|
+
});
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
// Ensure no blocker leaks into the next test.
|
|
20
|
+
expect(hasBlockingNavigation()).toBe(false);
|
|
21
|
+
});
|
|
22
|
+
it('navigates freely and never prompts when nothing is dirty', () => {
|
|
23
|
+
const { result } = renderHook(() => useAdminRouter('/admin', '/'));
|
|
24
|
+
act(() => result.current.navigate('/collections/posts'));
|
|
25
|
+
expect(result.current.currentPath).toBe('/collections/posts');
|
|
26
|
+
expect(confirmMock).not.toHaveBeenCalled();
|
|
27
|
+
});
|
|
28
|
+
it('aborts the navigation when a dirty editor is registered and the user cancels', () => {
|
|
29
|
+
confirmMock.mockReturnValue(false);
|
|
30
|
+
const unregister = registerNavigationBlocker(() => true);
|
|
31
|
+
try {
|
|
32
|
+
const { result } = renderHook(() => useAdminRouter('/admin', '/'));
|
|
33
|
+
act(() => result.current.navigate('/collections/posts'));
|
|
34
|
+
expect(confirmMock).toHaveBeenCalledWith(NAVIGATION_CONFIRM_MESSAGE);
|
|
35
|
+
expect(result.current.currentPath).toBe('/');
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
unregister();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
it('proceeds with the navigation when the user confirms leaving', () => {
|
|
42
|
+
confirmMock.mockReturnValue(true);
|
|
43
|
+
const unregister = registerNavigationBlocker(() => true);
|
|
44
|
+
try {
|
|
45
|
+
const { result } = renderHook(() => useAdminRouter('/admin', '/'));
|
|
46
|
+
act(() => result.current.navigate('/settings'));
|
|
47
|
+
expect(confirmMock).toHaveBeenCalledOnce();
|
|
48
|
+
expect(result.current.currentPath).toBe('/settings');
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
unregister();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
it('useNavigationBlocker only blocks while dirty and cleans up on unmount', () => {
|
|
55
|
+
const { rerender, unmount } = renderHook(({ dirty }) => useNavigationBlocker(dirty), {
|
|
56
|
+
initialProps: { dirty: false },
|
|
57
|
+
});
|
|
58
|
+
expect(hasBlockingNavigation()).toBe(false);
|
|
59
|
+
rerender({ dirty: true });
|
|
60
|
+
expect(hasBlockingNavigation()).toBe(true);
|
|
61
|
+
rerender({ dirty: false });
|
|
62
|
+
expect(hasBlockingNavigation()).toBe(false);
|
|
63
|
+
rerender({ dirty: true });
|
|
64
|
+
expect(hasBlockingNavigation()).toBe(true);
|
|
65
|
+
unmount();
|
|
66
|
+
expect(hasBlockingNavigation()).toBe(false);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
//# sourceMappingURL=navigation-blocker.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"navigation-blocker.test.js","sourceRoot":"","sources":["../../../src/__tests__/router/navigation-blocker.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"article-body-section.render.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/views/article-body-section.render.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// @vitest-environment happy-dom
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { ArticleBodySection } from '../../views/page-editor/sections/ArticleBodySection.js';
|
|
6
|
+
function section(content = {}) {
|
|
7
|
+
return {
|
|
8
|
+
id: 's1',
|
|
9
|
+
sectionType: 'article-body',
|
|
10
|
+
name: 'Article Body',
|
|
11
|
+
visible: true,
|
|
12
|
+
content,
|
|
13
|
+
settings: {},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
describe('ArticleBodySection', () => {
|
|
17
|
+
it('renders post body HTML with rich-text preview class', () => {
|
|
18
|
+
const { container } = render(_jsx(ArticleBodySection, { section: section({ source: 'field' }), context: { body: '<h2>What is Lorem Ipsum?</h2><p>Body copy.</p>' } }));
|
|
19
|
+
expect(screen.getByRole('heading', { level: 2, name: 'What is Lorem Ipsum?' })).toBeTruthy();
|
|
20
|
+
expect(container.querySelector('.actuate-rich-text')).toBeTruthy();
|
|
21
|
+
expect(container.querySelector('.prose')).toBeNull();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=article-body-section.render.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"article-body-section.render.test.js","sourceRoot":"","sources":["../../../src/__tests__/views/article-body-section.render.test.tsx"],"names":[],"mappings":";AAAA,gCAAgC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wDAAwD,CAAA;AAG3F,SAAS,OAAO,CAAC,UAAmC,EAAE;IACpD,OAAO;QACL,EAAE,EAAE,IAAI;QACR,WAAW,EAAE,cAAc;QAC3B,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,IAAI;QACb,OAAO;QACP,QAAQ,EAAE,EAAE;KACb,CAAA;AACH,CAAC;AAED,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAC1B,KAAC,kBAAkB,IACjB,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EACrC,OAAO,EAAE,EAAE,IAAI,EAAE,gDAAgD,EAAE,GACnE,CACH,CAAA;QAED,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,sBAAsB,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;QAC5F,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;QAClE,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAA;IACtD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|