@actuate-media/cms-admin 0.36.1 → 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/dist/__tests__/views/appearance-settings.render.test.js +4 -4
- package/dist/__tests__/views/updates-tab.render.test.d.ts +2 -0
- package/dist/__tests__/views/updates-tab.render.test.d.ts.map +1 -0
- package/dist/__tests__/views/updates-tab.render.test.js +132 -0
- package/dist/__tests__/views/updates-tab.render.test.js.map +1 -0
- package/dist/actuate-admin.css +1 -1
- package/dist/views/Settings.d.ts.map +1 -1
- package/dist/views/Settings.js +4 -112
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/settings/AdminThemeCard.js +1 -1
- package/dist/views/settings/BrandPreviewCard.js +1 -1
- package/dist/views/settings/BrandingCard.d.ts.map +1 -1
- package/dist/views/settings/BrandingCard.js +34 -19
- package/dist/views/settings/BrandingCard.js.map +1 -1
- package/dist/views/settings/TypographyMotionCard.js +1 -1
- package/dist/views/settings/UpdatesTab.d.ts +6 -0
- package/dist/views/settings/UpdatesTab.d.ts.map +1 -0
- package/dist/views/settings/UpdatesTab.js +80 -0
- package/dist/views/settings/UpdatesTab.js.map +1 -0
- package/dist/views/settings/components.d.ts +20 -0
- package/dist/views/settings/components.d.ts.map +1 -1
- package/dist/views/settings/components.js +11 -0
- package/dist/views/settings/components.js.map +1 -1
- package/dist/views/settings/useUpdates.d.ts +67 -0
- package/dist/views/settings/useUpdates.d.ts.map +1 -0
- package/dist/views/settings/useUpdates.js +127 -0
- package/dist/views/settings/useUpdates.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/views/appearance-settings.render.test.tsx +4 -4
- package/src/__tests__/views/updates-tab.render.test.tsx +161 -0
- package/src/views/Settings.tsx +2 -438
- package/src/views/settings/AdminThemeCard.tsx +1 -1
- package/src/views/settings/BrandPreviewCard.tsx +1 -1
- package/src/views/settings/BrandingCard.tsx +179 -180
- package/src/views/settings/TypographyMotionCard.tsx +1 -1
- package/src/views/settings/UpdatesTab.tsx +545 -0
- package/src/views/settings/components.tsx +51 -0
- package/src/views/settings/useUpdates.ts +183 -0
|
@@ -30,6 +30,26 @@ export declare function SettingsSubsection({ title, description, children, class
|
|
|
30
30
|
children?: ReactNode;
|
|
31
31
|
className?: string;
|
|
32
32
|
}): import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
/**
|
|
34
|
+
* A single setting row: an optional leading visual plus a label and
|
|
35
|
+
* description on the left, and a control aligned to the right edge. This is the
|
|
36
|
+
* uniform rhythm for compact controls (upload buttons, segmented toggles)
|
|
37
|
+
* inside a {@link SettingsCard} — mirror it everywhere so rows line up instead
|
|
38
|
+
* of stacking controls beneath their copy.
|
|
39
|
+
*/
|
|
40
|
+
export declare function SettingsControlRow({ label, description, control, leading, htmlFor, align, className, }: {
|
|
41
|
+
label: ReactNode;
|
|
42
|
+
description?: ReactNode;
|
|
43
|
+
/** Right-aligned control(s) for this row. */
|
|
44
|
+
control: ReactNode;
|
|
45
|
+
/** Optional visual (e.g. a logo thumbnail) shown before the label. */
|
|
46
|
+
leading?: ReactNode;
|
|
47
|
+
/** When set, the label renders as a `<label>` bound to this control id. */
|
|
48
|
+
htmlFor?: string;
|
|
49
|
+
/** Vertical alignment of the two columns. Defaults to centered. */
|
|
50
|
+
align?: 'center' | 'start';
|
|
51
|
+
className?: string;
|
|
52
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
33
53
|
/** Small badge showing where a setting's value comes from. */
|
|
34
54
|
export declare function SettingsSourceBadge({ meta }: {
|
|
35
55
|
meta?: SettingsSourceMetadata;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/views/settings/components.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC7C,OAAO,KAAK,EAAE,sBAAsB,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEtF;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,WAAW,EACX,OAAO,EACP,QAAQ,EACR,SAAS,EACT,YAAY,EAAE,OAAc,GAC7B,EAAE;IACD,KAAK,EAAE,SAAS,CAAA;IAChB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yEAAyE;IACzE,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;CAC3B,2CAmBA;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,WAAW,EACX,QAAQ,EACR,SAAS,GACV,EAAE;IACD,KAAK,EAAE,SAAS,CAAA;IAChB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,2CAQA;AAUD,8DAA8D;AAC9D,wBAAgB,mBAAmB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,sBAAsB,CAAA;CAAE,kDAY9E;AAED,yEAAyE;AACzE,wBAAgB,iBAAiB,CAAC,EAChC,KAAK,EACL,WAAW,EACX,OAAO,EACP,QAAQ,EACR,QAAgB,EAChB,KAAK,GACN,EAAE;IACD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAClC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB,2CA6BA;AAED,4DAA4D;AAC5D,wBAAgB,yBAAyB,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,eAAe,EAAE,CAAA;CAAE,kDAuBlF;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,OAAO,EACP,SAAS,EACT,SAAS,EACT,MAAM,EACN,OAAO,GACR,EAAE;IACD,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,OAAO,CAAA;IAChB,SAAS,EAAE,OAAO,CAAA;IAClB,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAA;IAClD,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,2CA4BA;AAED,0DAA0D;AAC1D,wBAAgB,6BAA6B,CAAC,EAC5C,IAAI,EACJ,KAAK,EACL,WAAW,EACX,YAAyB,EACzB,SAAS,EACT,QAAQ,GACT,EAAE;IACD,IAAI,EAAE,OAAO,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,2CAmCA"}
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../../src/views/settings/components.tsx"],"names":[],"mappings":"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"}
|
|
@@ -24,6 +24,17 @@ export function SettingsCard({ title, description, actions, children, className,
|
|
|
24
24
|
export function SettingsSubsection({ title, description, children, className, }) {
|
|
25
25
|
return (_jsxs("div", { className: `border-border border-t pt-4 ${className ?? ''}`, children: [_jsx("div", { className: "text-foreground text-base font-medium", children: title }), description && _jsx("p", { className: "text-muted-foreground mt-0.5 text-sm", children: description }), children] }));
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* A single setting row: an optional leading visual plus a label and
|
|
29
|
+
* description on the left, and a control aligned to the right edge. This is the
|
|
30
|
+
* uniform rhythm for compact controls (upload buttons, segmented toggles)
|
|
31
|
+
* inside a {@link SettingsCard} — mirror it everywhere so rows line up instead
|
|
32
|
+
* of stacking controls beneath their copy.
|
|
33
|
+
*/
|
|
34
|
+
export function SettingsControlRow({ label, description, control, leading, htmlFor, align = 'center', className, }) {
|
|
35
|
+
const labelClass = 'text-foreground block text-base font-medium';
|
|
36
|
+
return (_jsxs("div", { className: `flex justify-between gap-4 ${align === 'center' ? 'items-center' : 'items-start'} ${className ?? ''}`, children: [_jsxs("div", { className: "flex min-w-0 items-center gap-4", children: [leading, _jsxs("div", { className: "min-w-0", children: [htmlFor ? (_jsx("label", { htmlFor: htmlFor, className: labelClass, children: label })) : (_jsx("span", { className: labelClass, children: label })), description && _jsx("p", { className: "text-muted-foreground mt-0.5 text-sm", children: description })] })] }), _jsx("div", { className: "flex shrink-0 items-center gap-2", children: control })] }));
|
|
37
|
+
}
|
|
27
38
|
const SOURCE_LABEL = {
|
|
28
39
|
config: 'Config-managed',
|
|
29
40
|
environment: 'Environment-managed',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/views/settings/components.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../../src/views/settings/components.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export type UpdateChangeType = 'feature' | 'fix' | 'improvement' | 'breaking' | 'security' | 'deprecation';
|
|
2
|
+
export interface UpdateChangelogItem {
|
|
3
|
+
version: string;
|
|
4
|
+
date: string;
|
|
5
|
+
summary: string;
|
|
6
|
+
type?: UpdateChangeType;
|
|
7
|
+
}
|
|
8
|
+
export interface UpdatePluginCompatibility {
|
|
9
|
+
name: string;
|
|
10
|
+
compatible: boolean;
|
|
11
|
+
minVersion?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface UpdateInfo {
|
|
14
|
+
current: string;
|
|
15
|
+
latest: string;
|
|
16
|
+
updateAvailable: boolean;
|
|
17
|
+
severity?: 'patch' | 'minor' | 'major' | 'security';
|
|
18
|
+
releaseDate?: string;
|
|
19
|
+
changelog?: UpdateChangelogItem[];
|
|
20
|
+
updateCommand?: string;
|
|
21
|
+
breakingChanges?: string[];
|
|
22
|
+
hasMigrations?: boolean;
|
|
23
|
+
pluginCompatibility?: UpdatePluginCompatibility[];
|
|
24
|
+
source?: 'update-server' | 'npm';
|
|
25
|
+
/** Whether the current session may manage updates (admin/owner). */
|
|
26
|
+
canManage?: boolean;
|
|
27
|
+
hasGithubToken?: boolean;
|
|
28
|
+
githubRepo?: string;
|
|
29
|
+
}
|
|
30
|
+
interface GithubForm {
|
|
31
|
+
githubRepo: string;
|
|
32
|
+
githubToken: string;
|
|
33
|
+
}
|
|
34
|
+
/** Admin/Owner may manage updates (matches the server's `requireAdminScope`). */
|
|
35
|
+
export declare function canManageUpdates(role: string | null | undefined): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* State + actions for the Settings → Updates tab. Owns the update-status check,
|
|
38
|
+
* the GitHub-integration config form (with dirty tracking for the shared save
|
|
39
|
+
* bar), and the "Create Update PR" action. All writes are gated on `canManage`,
|
|
40
|
+
* which the server confirms in the check response.
|
|
41
|
+
*/
|
|
42
|
+
export declare function useUpdates({ role }: {
|
|
43
|
+
role?: string;
|
|
44
|
+
}): {
|
|
45
|
+
info: UpdateInfo | null;
|
|
46
|
+
checking: boolean;
|
|
47
|
+
hasChecked: boolean;
|
|
48
|
+
error: string;
|
|
49
|
+
applying: boolean;
|
|
50
|
+
prResult: {
|
|
51
|
+
prUrl: string;
|
|
52
|
+
prNumber: number;
|
|
53
|
+
} | null;
|
|
54
|
+
canManage: boolean;
|
|
55
|
+
form: GithubForm;
|
|
56
|
+
setField: (key: keyof GithubForm, value: string) => void;
|
|
57
|
+
dirty: boolean;
|
|
58
|
+
repoError: string;
|
|
59
|
+
hasErrors: boolean;
|
|
60
|
+
saveState: "error" | "success" | "idle" | "saving";
|
|
61
|
+
save: () => Promise<void>;
|
|
62
|
+
reset: () => void;
|
|
63
|
+
check: () => Promise<void>;
|
|
64
|
+
apply: () => Promise<void>;
|
|
65
|
+
};
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=useUpdates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUpdates.d.ts","sourceRoot":"","sources":["../../../src/views/settings/useUpdates.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,gBAAgB,GACxB,SAAS,GACT,KAAK,GACL,aAAa,GACb,UAAU,GACV,UAAU,GACV,aAAa,CAAA;AAEjB,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,gBAAgB,CAAA;CACxB;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,eAAe,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,CAAA;IACnD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,mBAAmB,EAAE,CAAA;IACjC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,mBAAmB,CAAC,EAAE,yBAAyB,EAAE,CAAA;IACjD,MAAM,CAAC,EAAE,eAAe,GAAG,KAAK,CAAA;IAChC,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,UAAU,UAAU;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;CACpB;AAID,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAGzE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;eAMF,MAAM;kBAAY,MAAM;;;;oBAqCvC,MAAM,UAAU,SAAS,MAAM;;;;;;;;;EA0EnE"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
3
|
+
import { toast } from 'sonner';
|
|
4
|
+
import { cmsApi } from '../../lib/api.js';
|
|
5
|
+
const REPO_PATTERN = /^[a-zA-Z0-9._-]+\/[a-zA-Z0-9._-]+$/;
|
|
6
|
+
/** Admin/Owner may manage updates (matches the server's `requireAdminScope`). */
|
|
7
|
+
export function canManageUpdates(role) {
|
|
8
|
+
const r = (role ?? '').toUpperCase();
|
|
9
|
+
return r === 'ADMIN' || r === 'OWNER';
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* State + actions for the Settings → Updates tab. Owns the update-status check,
|
|
13
|
+
* the GitHub-integration config form (with dirty tracking for the shared save
|
|
14
|
+
* bar), and the "Create Update PR" action. All writes are gated on `canManage`,
|
|
15
|
+
* which the server confirms in the check response.
|
|
16
|
+
*/
|
|
17
|
+
export function useUpdates({ role }) {
|
|
18
|
+
const [info, setInfo] = useState(null);
|
|
19
|
+
const [checking, setChecking] = useState(false);
|
|
20
|
+
const [hasChecked, setHasChecked] = useState(false);
|
|
21
|
+
const [error, setError] = useState('');
|
|
22
|
+
const [applying, setApplying] = useState(false);
|
|
23
|
+
const [prResult, setPrResult] = useState(null);
|
|
24
|
+
const [form, setForm] = useState({ githubRepo: '', githubToken: '' });
|
|
25
|
+
const [baseline, setBaseline] = useState({ githubRepo: '', githubToken: '' });
|
|
26
|
+
const [saveState, setSaveState] = useState('idle');
|
|
27
|
+
// Optimistic until the check response confirms the server-side permission.
|
|
28
|
+
const canManage = info?.canManage ?? canManageUpdates(role);
|
|
29
|
+
const check = useCallback(async () => {
|
|
30
|
+
setChecking(true);
|
|
31
|
+
setError('');
|
|
32
|
+
setPrResult(null);
|
|
33
|
+
const res = await cmsApi('/updates/check');
|
|
34
|
+
if (res.error) {
|
|
35
|
+
setError(res.error);
|
|
36
|
+
}
|
|
37
|
+
else if (res.data) {
|
|
38
|
+
setInfo(res.data);
|
|
39
|
+
const repo = res.data.githubRepo ?? '';
|
|
40
|
+
setForm({ githubRepo: repo, githubToken: '' });
|
|
41
|
+
setBaseline({ githubRepo: repo, githubToken: '' });
|
|
42
|
+
}
|
|
43
|
+
setChecking(false);
|
|
44
|
+
setHasChecked(true);
|
|
45
|
+
}, []);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
check();
|
|
48
|
+
}, [check]);
|
|
49
|
+
const repoError = form.githubRepo.trim() && !REPO_PATTERN.test(form.githubRepo.trim())
|
|
50
|
+
? 'Use the owner/repo format (e.g. actuate-media/my-site).'
|
|
51
|
+
: '';
|
|
52
|
+
const hasErrors = Boolean(repoError);
|
|
53
|
+
const dirty = form.githubRepo !== baseline.githubRepo || form.githubToken.trim() !== '';
|
|
54
|
+
const setField = useCallback((key, value) => {
|
|
55
|
+
setForm((f) => ({ ...f, [key]: value }));
|
|
56
|
+
setSaveState('idle');
|
|
57
|
+
}, []);
|
|
58
|
+
const save = useCallback(async () => {
|
|
59
|
+
if (hasErrors || !dirty)
|
|
60
|
+
return;
|
|
61
|
+
setSaveState('saving');
|
|
62
|
+
const body = {};
|
|
63
|
+
if (form.githubToken.trim())
|
|
64
|
+
body.githubToken = form.githubToken.trim();
|
|
65
|
+
if (form.githubRepo.trim())
|
|
66
|
+
body.githubRepo = form.githubRepo.trim();
|
|
67
|
+
const res = await cmsApi('/updates/config', { method: 'PUT', body: JSON.stringify(body) });
|
|
68
|
+
if (res.error) {
|
|
69
|
+
setSaveState('error');
|
|
70
|
+
toast.error(res.error);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
setSaveState('success');
|
|
74
|
+
toast.success('GitHub configuration saved and encrypted.');
|
|
75
|
+
const savedRepo = form.githubRepo.trim();
|
|
76
|
+
setBaseline({ githubRepo: savedRepo, githubToken: '' });
|
|
77
|
+
setForm({ githubRepo: savedRepo, githubToken: '' });
|
|
78
|
+
setInfo((prev) => prev
|
|
79
|
+
? {
|
|
80
|
+
...prev,
|
|
81
|
+
githubRepo: savedRepo,
|
|
82
|
+
hasGithubToken: prev.hasGithubToken || Boolean(body.githubToken),
|
|
83
|
+
}
|
|
84
|
+
: prev);
|
|
85
|
+
}, [dirty, form.githubRepo, form.githubToken, hasErrors]);
|
|
86
|
+
const reset = useCallback(() => {
|
|
87
|
+
setForm({ ...baseline });
|
|
88
|
+
setSaveState('idle');
|
|
89
|
+
}, [baseline]);
|
|
90
|
+
const apply = useCallback(async () => {
|
|
91
|
+
if (!info?.latest || !canManage)
|
|
92
|
+
return;
|
|
93
|
+
setApplying(true);
|
|
94
|
+
const res = await cmsApi('/updates/apply', {
|
|
95
|
+
method: 'POST',
|
|
96
|
+
body: JSON.stringify({ targetVersion: info.latest }),
|
|
97
|
+
});
|
|
98
|
+
if (res.error) {
|
|
99
|
+
toast.error(res.error);
|
|
100
|
+
}
|
|
101
|
+
else if (res.data) {
|
|
102
|
+
setPrResult(res.data);
|
|
103
|
+
toast.success('Update PR created.');
|
|
104
|
+
}
|
|
105
|
+
setApplying(false);
|
|
106
|
+
}, [info, canManage]);
|
|
107
|
+
return {
|
|
108
|
+
info,
|
|
109
|
+
checking,
|
|
110
|
+
hasChecked,
|
|
111
|
+
error,
|
|
112
|
+
applying,
|
|
113
|
+
prResult,
|
|
114
|
+
canManage,
|
|
115
|
+
form,
|
|
116
|
+
setField,
|
|
117
|
+
dirty,
|
|
118
|
+
repoError,
|
|
119
|
+
hasErrors,
|
|
120
|
+
saveState,
|
|
121
|
+
save,
|
|
122
|
+
reset,
|
|
123
|
+
check,
|
|
124
|
+
apply,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=useUpdates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useUpdates.js","sourceRoot":"","sources":["../../../src/views/settings/useUpdates.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actuate-media/cms-admin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.37.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/actuate-media/actuatecms.git",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"tailwindcss": "^4.0.0",
|
|
89
89
|
"typescript": "^5.7.0",
|
|
90
90
|
"vitest": "^4.1.0",
|
|
91
|
-
"@actuate-media/cms-core": "0.
|
|
91
|
+
"@actuate-media/cms-core": "0.47.0",
|
|
92
92
|
"@actuate-media/component-blocks": "0.2.0"
|
|
93
93
|
},
|
|
94
94
|
"scripts": {
|
|
@@ -51,9 +51,9 @@ describe('AppearanceTab', () => {
|
|
|
51
51
|
render(<AppearanceTab role="ADMIN" />)
|
|
52
52
|
|
|
53
53
|
await screen.findByText('Branding')
|
|
54
|
-
expect(screen.getByText('Admin
|
|
55
|
-
expect(screen.getByText('Typography &
|
|
56
|
-
expect(screen.getByText('Brand
|
|
54
|
+
expect(screen.getByText('Admin theme')).toBeTruthy()
|
|
55
|
+
expect(screen.getByText('Typography & motion')).toBeTruthy()
|
|
56
|
+
expect(screen.getByText('Brand preview')).toBeTruthy()
|
|
57
57
|
expect(
|
|
58
58
|
(screen.getByRole('button', { name: 'Save Changes' }) as HTMLButtonElement).disabled,
|
|
59
59
|
).toBe(true)
|
|
@@ -99,7 +99,7 @@ describe('AppearanceTab', () => {
|
|
|
99
99
|
render(<AppearanceTab role="ADMIN" />)
|
|
100
100
|
await screen.findByText('Branding')
|
|
101
101
|
|
|
102
|
-
const input = screen.getByLabelText('Primary
|
|
102
|
+
const input = screen.getByLabelText('Primary logo') as HTMLInputElement
|
|
103
103
|
const file = new File(
|
|
104
104
|
['<svg viewBox="0 0 400 100" xmlns="http://www.w3.org/2000/svg"></svg>'],
|
|
105
105
|
'logo.svg',
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
|
+
import { fireEvent, render, screen, waitFor } from '@testing-library/react'
|
|
4
|
+
|
|
5
|
+
// The Updates tab reads `/updates/check`, saves GitHub config via
|
|
6
|
+
// PUT `/updates/config`, and opens an upgrade PR via POST `/updates/apply`.
|
|
7
|
+
let checkData: any
|
|
8
|
+
|
|
9
|
+
const cmsApi = vi.fn(async (endpoint: string, options?: { method?: string; body?: unknown }) => {
|
|
10
|
+
const method = options?.method ?? 'GET'
|
|
11
|
+
if (endpoint === '/updates/check' && method === 'GET') return { data: checkData, status: 200 }
|
|
12
|
+
if (endpoint === '/updates/config' && method === 'PUT')
|
|
13
|
+
return { data: { success: true }, status: 200 }
|
|
14
|
+
if (endpoint === '/updates/apply' && method === 'POST')
|
|
15
|
+
return { data: { prUrl: 'https://github.com/x/y/pull/1', prNumber: 1 }, status: 200 }
|
|
16
|
+
return { data: {}, status: 200 }
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
vi.mock('../../lib/api.js', () => ({ cmsApi: (e: string, o?: unknown) => cmsApi(e, o as any) }))
|
|
20
|
+
vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn(), loading: vi.fn() } }))
|
|
21
|
+
|
|
22
|
+
const { UpdatesTab } = await import('../../views/settings/UpdatesTab.js')
|
|
23
|
+
|
|
24
|
+
function upToDate(overrides: Record<string, unknown> = {}) {
|
|
25
|
+
return {
|
|
26
|
+
current: '0.46.0',
|
|
27
|
+
latest: '0.46.0',
|
|
28
|
+
updateAvailable: false,
|
|
29
|
+
canManage: true,
|
|
30
|
+
hasGithubToken: false,
|
|
31
|
+
githubRepo: '',
|
|
32
|
+
source: 'update-server',
|
|
33
|
+
...overrides,
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function updateAvailable(overrides: Record<string, unknown> = {}) {
|
|
38
|
+
return {
|
|
39
|
+
current: '0.45.0',
|
|
40
|
+
latest: '0.46.0',
|
|
41
|
+
updateAvailable: true,
|
|
42
|
+
severity: 'minor',
|
|
43
|
+
releaseDate: '2026-01-02',
|
|
44
|
+
changelog: [
|
|
45
|
+
{
|
|
46
|
+
version: '0.46.0',
|
|
47
|
+
date: '2026-01-02',
|
|
48
|
+
summary: 'Add Brand Voice training',
|
|
49
|
+
type: 'feature',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
hasMigrations: true,
|
|
53
|
+
breakingChanges: ['Removed the legacy provider API'],
|
|
54
|
+
pluginCompatibility: [
|
|
55
|
+
{ name: '@actuate-media/plugin-seo', compatible: true, minVersion: '0.46.0' },
|
|
56
|
+
],
|
|
57
|
+
updateCommand: 'npm update @actuate-media/cms-core',
|
|
58
|
+
canManage: true,
|
|
59
|
+
hasGithubToken: false,
|
|
60
|
+
githubRepo: '',
|
|
61
|
+
source: 'update-server',
|
|
62
|
+
...overrides,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
beforeEach(() => {
|
|
67
|
+
cmsApi.mockClear()
|
|
68
|
+
checkData = upToDate()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
describe('UpdatesTab', () => {
|
|
72
|
+
it('shows the current version and an up-to-date banner', async () => {
|
|
73
|
+
render(<UpdatesTab role="ADMIN" />)
|
|
74
|
+
await screen.findByText("You're up to date!")
|
|
75
|
+
expect(screen.getAllByText('0.46.0').length).toBeGreaterThan(0)
|
|
76
|
+
// Admins see the GitHub integration card.
|
|
77
|
+
expect(screen.getByText('GitHub Integration')).toBeTruthy()
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('surfaces severity, real changelog, migrations and breaking changes', async () => {
|
|
81
|
+
checkData = updateAvailable()
|
|
82
|
+
render(<UpdatesTab role="ADMIN" />)
|
|
83
|
+
|
|
84
|
+
await screen.findByText('Update available')
|
|
85
|
+
expect(screen.getByText('Minor')).toBeTruthy()
|
|
86
|
+
expect(screen.getByText('Add Brand Voice training')).toBeTruthy()
|
|
87
|
+
expect(screen.getByText('Database migrations required')).toBeTruthy()
|
|
88
|
+
expect(screen.getByText('Breaking changes in this release')).toBeTruthy()
|
|
89
|
+
expect(screen.getByText('Removed the legacy provider API')).toBeTruthy()
|
|
90
|
+
// Plugin compatibility surfaced.
|
|
91
|
+
expect(screen.getByText('plugin-seo')).toBeTruthy()
|
|
92
|
+
expect(screen.getByRole('button', { name: 'Create Update PR' })).toBeTruthy()
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
it('flags a security release prominently', async () => {
|
|
96
|
+
checkData = updateAvailable({ severity: 'security' })
|
|
97
|
+
render(<UpdatesTab role="ADMIN" />)
|
|
98
|
+
await screen.findByText('Security update available')
|
|
99
|
+
expect(screen.getByText('Security')).toBeTruthy()
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('is permission-aware: non-admins cannot manage updates', async () => {
|
|
103
|
+
checkData = updateAvailable({ canManage: false })
|
|
104
|
+
render(<UpdatesTab role="EDITOR" />)
|
|
105
|
+
|
|
106
|
+
await screen.findByText('Update available')
|
|
107
|
+
expect(screen.queryByText('GitHub Integration')).toBeNull()
|
|
108
|
+
expect(screen.queryByRole('button', { name: 'Create Update PR' })).toBeNull()
|
|
109
|
+
expect(screen.getByText(/Ask an administrator/i)).toBeTruthy()
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('enables Save when the repo changes and persists via PUT /updates/config', async () => {
|
|
113
|
+
render(<UpdatesTab role="ADMIN" />)
|
|
114
|
+
await screen.findByText('GitHub Integration')
|
|
115
|
+
|
|
116
|
+
const save = screen.getByRole('button', { name: 'Save Changes' }) as HTMLButtonElement
|
|
117
|
+
expect(save.disabled).toBe(true)
|
|
118
|
+
|
|
119
|
+
const repo = screen.getByLabelText('Repository') as HTMLInputElement
|
|
120
|
+
fireEvent.change(repo, { target: { value: 'actuate-media/site' } })
|
|
121
|
+
expect(save.disabled).toBe(false)
|
|
122
|
+
|
|
123
|
+
fireEvent.click(save)
|
|
124
|
+
await waitFor(() =>
|
|
125
|
+
expect(cmsApi).toHaveBeenCalledWith(
|
|
126
|
+
'/updates/config',
|
|
127
|
+
expect.objectContaining({
|
|
128
|
+
method: 'PUT',
|
|
129
|
+
body: expect.stringContaining('actuate-media/site'),
|
|
130
|
+
}),
|
|
131
|
+
),
|
|
132
|
+
)
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
it('blocks Save on an invalid repository format', async () => {
|
|
136
|
+
render(<UpdatesTab role="ADMIN" />)
|
|
137
|
+
await screen.findByText('GitHub Integration')
|
|
138
|
+
|
|
139
|
+
const repo = screen.getByLabelText('Repository') as HTMLInputElement
|
|
140
|
+
fireEvent.change(repo, { target: { value: 'not a repo' } })
|
|
141
|
+
|
|
142
|
+
expect(screen.getByText(/owner\/repo format/i)).toBeTruthy()
|
|
143
|
+
const save = screen.getByRole('button', { name: 'Save Changes' }) as HTMLButtonElement
|
|
144
|
+
expect(save.disabled).toBe(true)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
it('creates an update PR via POST /updates/apply', async () => {
|
|
148
|
+
checkData = updateAvailable()
|
|
149
|
+
render(<UpdatesTab role="ADMIN" />)
|
|
150
|
+
await screen.findByText('Update available')
|
|
151
|
+
|
|
152
|
+
fireEvent.click(screen.getByRole('button', { name: 'Create Update PR' }))
|
|
153
|
+
await waitFor(() =>
|
|
154
|
+
expect(cmsApi).toHaveBeenCalledWith(
|
|
155
|
+
'/updates/apply',
|
|
156
|
+
expect.objectContaining({ method: 'POST', body: expect.stringContaining('0.46.0') }),
|
|
157
|
+
),
|
|
158
|
+
)
|
|
159
|
+
await screen.findByText('Pull Request Created')
|
|
160
|
+
})
|
|
161
|
+
})
|