@actuate-media/cms-admin 0.19.0 → 0.20.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/AdminRoot.d.ts.map +1 -1
- package/dist/AdminRoot.js +9 -5
- package/dist/AdminRoot.js.map +1 -1
- package/dist/actuate-admin.css +1 -1
- package/dist/components/seo/Drawer.d.ts +11 -0
- package/dist/components/seo/Drawer.d.ts.map +1 -0
- package/dist/components/seo/Drawer.js +13 -0
- package/dist/components/seo/Drawer.js.map +1 -0
- package/dist/components/seo/RedirectEditorDrawer.d.ts +9 -0
- package/dist/components/seo/RedirectEditorDrawer.d.ts.map +1 -0
- package/dist/components/seo/RedirectEditorDrawer.js +94 -0
- package/dist/components/seo/RedirectEditorDrawer.js.map +1 -0
- package/dist/components/seo/SeoCopilotDrawer.d.ts +10 -0
- package/dist/components/seo/SeoCopilotDrawer.d.ts.map +1 -0
- package/dist/components/seo/SeoCopilotDrawer.js +34 -0
- package/dist/components/seo/SeoCopilotDrawer.js.map +1 -0
- package/dist/components/seo/SeoEditorDrawer.d.ts +8 -0
- package/dist/components/seo/SeoEditorDrawer.d.ts.map +1 -0
- package/dist/components/seo/SeoEditorDrawer.js +111 -0
- package/dist/components/seo/SeoEditorDrawer.js.map +1 -0
- package/dist/components/seo/SeoIssueFixDrawer.d.ts +8 -0
- package/dist/components/seo/SeoIssueFixDrawer.d.ts.map +1 -0
- package/dist/components/seo/SeoIssueFixDrawer.js +111 -0
- package/dist/components/seo/SeoIssueFixDrawer.js.map +1 -0
- package/dist/components/seo/primitives.d.ts +53 -0
- package/dist/components/seo/primitives.d.ts.map +1 -0
- package/dist/components/seo/primitives.js +100 -0
- package/dist/components/seo/primitives.js.map +1 -0
- package/dist/layout/Sidebar.d.ts.map +1 -1
- package/dist/layout/Sidebar.js +3 -0
- package/dist/layout/Sidebar.js.map +1 -1
- package/dist/lib/seo-service.d.ts +322 -0
- package/dist/lib/seo-service.d.ts.map +1 -0
- package/dist/lib/seo-service.js +295 -0
- package/dist/lib/seo-service.js.map +1 -0
- package/dist/router/index.d.ts.map +1 -1
- package/dist/router/index.js +4 -1
- package/dist/router/index.js.map +1 -1
- package/dist/views/MediaBrowser.d.ts.map +1 -1
- package/dist/views/MediaBrowser.js +36 -25
- package/dist/views/MediaBrowser.js.map +1 -1
- package/dist/views/Posts/NewPostTypeInstructions.js +2 -2
- package/dist/views/Posts/post-type-presets.d.ts +5 -0
- package/dist/views/Posts/post-type-presets.d.ts.map +1 -1
- package/dist/views/Posts/post-type-presets.js +10 -64
- package/dist/views/Posts/post-type-presets.js.map +1 -1
- package/dist/views/SEO.d.ts.map +1 -1
- package/dist/views/SEO.js +89 -132
- package/dist/views/SEO.js.map +1 -1
- package/dist/views/seo/AuditTab.d.ts +6 -0
- package/dist/views/seo/AuditTab.d.ts.map +1 -0
- package/dist/views/seo/AuditTab.js +57 -0
- package/dist/views/seo/AuditTab.js.map +1 -0
- package/dist/views/seo/ContentTab.d.ts +5 -0
- package/dist/views/seo/ContentTab.d.ts.map +1 -0
- package/dist/views/seo/ContentTab.js +27 -0
- package/dist/views/seo/ContentTab.js.map +1 -0
- package/dist/views/seo/OverviewTab.d.ts +8 -0
- package/dist/views/seo/OverviewTab.d.ts.map +1 -0
- package/dist/views/seo/OverviewTab.js +35 -0
- package/dist/views/seo/OverviewTab.js.map +1 -0
- package/dist/views/seo/RedirectsTab.d.ts +2 -0
- package/dist/views/seo/RedirectsTab.d.ts.map +1 -0
- package/dist/views/seo/RedirectsTab.js +124 -0
- package/dist/views/seo/RedirectsTab.js.map +1 -0
- package/dist/views/seo/TechnicalTab.d.ts +2 -0
- package/dist/views/seo/TechnicalTab.d.ts.map +1 -0
- package/dist/views/seo/TechnicalTab.js +102 -0
- package/dist/views/seo/TechnicalTab.js.map +1 -0
- package/dist/views/seo/useSeoResource.d.ts +8 -0
- package/dist/views/seo/useSeoResource.d.ts.map +1 -0
- package/dist/views/seo/useSeoResource.js +42 -0
- package/dist/views/seo/useSeoResource.js.map +1 -0
- package/package.json +2 -2
- package/src/AdminRoot.tsx +9 -5
- package/src/components/seo/Drawer.tsx +61 -0
- package/src/components/seo/RedirectEditorDrawer.tsx +235 -0
- package/src/components/seo/SeoCopilotDrawer.tsx +76 -0
- package/src/components/seo/SeoEditorDrawer.tsx +347 -0
- package/src/components/seo/SeoIssueFixDrawer.tsx +244 -0
- package/src/components/seo/primitives.tsx +237 -0
- package/src/layout/Sidebar.tsx +3 -0
- package/src/lib/seo-service.ts +623 -0
- package/src/router/index.ts +4 -1
- package/src/views/MediaBrowser.tsx +89 -67
- package/src/views/Posts/NewPostTypeInstructions.tsx +2 -2
- package/src/views/Posts/post-type-presets.ts +15 -64
- package/src/views/SEO.tsx +186 -863
- package/src/views/seo/AuditTab.tsx +229 -0
- package/src/views/seo/ContentTab.tsx +164 -0
- package/src/views/seo/OverviewTab.tsx +257 -0
- package/src/views/seo/RedirectsTab.tsx +392 -0
- package/src/views/seo/TechnicalTab.tsx +303 -0
- package/src/views/seo/useSeoResource.ts +52 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SEO service — typed client over the cms-core SEO REST endpoints.
|
|
3
|
+
*
|
|
4
|
+
* Every SEO admin component reads/writes through this module (never raw
|
|
5
|
+
* `cmsApi` / `fetch`), so the network contract lives in one place. Fetchers
|
|
6
|
+
* return typed data with safe fallbacks; mutations return `{ error?: string }`.
|
|
7
|
+
*
|
|
8
|
+
* Endpoint paths here are the contract implemented by cms-core
|
|
9
|
+
* `packages/cms-core/src/api/handlers.ts` across phases 2-3 and 6.
|
|
10
|
+
*/
|
|
11
|
+
import { cmsApi } from './api.js';
|
|
12
|
+
const EMPTY_OVERVIEW = {
|
|
13
|
+
siteScore: { score: 0, grade: 'critical', delta: null, breakdown: [] },
|
|
14
|
+
metrics: [],
|
|
15
|
+
issues: [],
|
|
16
|
+
issuesSummary: { total: 0, critical: 0, warning: 0, info: 0 },
|
|
17
|
+
quickWins: [],
|
|
18
|
+
searchPerformance: [],
|
|
19
|
+
searchConsoleConnected: false,
|
|
20
|
+
lastAuditRunId: null,
|
|
21
|
+
};
|
|
22
|
+
export async function fetchSeoOverview() {
|
|
23
|
+
const res = await cmsApi('/seo/overview');
|
|
24
|
+
return res.data ?? EMPTY_OVERVIEW;
|
|
25
|
+
}
|
|
26
|
+
export async function fetchSearchPerformance(params = {}) {
|
|
27
|
+
const qs = params.limit ? `?limit=${params.limit}` : '';
|
|
28
|
+
const res = await cmsApi(`/seo/search-performance${qs}`);
|
|
29
|
+
return res.data?.rows ?? [];
|
|
30
|
+
}
|
|
31
|
+
export async function fetchSeoContentRecords() {
|
|
32
|
+
const res = await cmsApi('/seo/content');
|
|
33
|
+
return res.data?.records ?? [];
|
|
34
|
+
}
|
|
35
|
+
export async function fetchSeoContentRecord(entityType, entityId) {
|
|
36
|
+
const res = await cmsApi(`/seo/content/${entityType}/${encodeURIComponent(entityId)}`);
|
|
37
|
+
return res.data ?? null;
|
|
38
|
+
}
|
|
39
|
+
export async function updateSeoFields(entityType, entityId, payload) {
|
|
40
|
+
const res = await cmsApi(`/seo/content/${entityType}/${encodeURIComponent(entityId)}`, {
|
|
41
|
+
method: 'PUT',
|
|
42
|
+
body: JSON.stringify(payload),
|
|
43
|
+
});
|
|
44
|
+
return res.error ? { error: res.error } : {};
|
|
45
|
+
}
|
|
46
|
+
/** Pure search/filter over the content records (decoupled from network for tests). */
|
|
47
|
+
export function applyContentSeoQuery(records, query) {
|
|
48
|
+
const search = (query.search ?? '').trim().toLowerCase();
|
|
49
|
+
const filter = query.filter ?? 'all';
|
|
50
|
+
return records.filter((r) => {
|
|
51
|
+
if (filter === 'pages' && r.entityType !== 'page')
|
|
52
|
+
return false;
|
|
53
|
+
if (filter === 'posts' && r.entityType !== 'post')
|
|
54
|
+
return false;
|
|
55
|
+
if (search) {
|
|
56
|
+
const haystack = [
|
|
57
|
+
r.title,
|
|
58
|
+
r.url,
|
|
59
|
+
r.metaTitle ?? '',
|
|
60
|
+
r.metaDescription ?? '',
|
|
61
|
+
String(r.seoScore),
|
|
62
|
+
r.entityType,
|
|
63
|
+
]
|
|
64
|
+
.join(' ')
|
|
65
|
+
.toLowerCase();
|
|
66
|
+
if (!haystack.includes(search))
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
return true;
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
export async function runSeoAudit(scope = 'full') {
|
|
73
|
+
const res = await cmsApi('/seo/audit', {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
body: JSON.stringify({ scope }),
|
|
76
|
+
});
|
|
77
|
+
if (res.error)
|
|
78
|
+
return { error: res.error };
|
|
79
|
+
return { run: res.data };
|
|
80
|
+
}
|
|
81
|
+
export async function fetchSeoAuditRuns() {
|
|
82
|
+
const res = await cmsApi('/seo/audits');
|
|
83
|
+
return res.data?.runs ?? [];
|
|
84
|
+
}
|
|
85
|
+
export async function fetchSeoAuditRun(auditRunId) {
|
|
86
|
+
const res = await cmsApi(`/seo/audits/${encodeURIComponent(auditRunId)}`);
|
|
87
|
+
return res.data ?? null;
|
|
88
|
+
}
|
|
89
|
+
export async function fetchSeoIssues(query = {}) {
|
|
90
|
+
const params = new URLSearchParams();
|
|
91
|
+
if (query.severity && query.severity !== 'all')
|
|
92
|
+
params.set('severity', query.severity);
|
|
93
|
+
if (query.category && query.category !== 'all')
|
|
94
|
+
params.set('category', query.category);
|
|
95
|
+
if (query.status && query.status !== 'all')
|
|
96
|
+
params.set('status', query.status);
|
|
97
|
+
if (query.auditRunId)
|
|
98
|
+
params.set('auditRunId', query.auditRunId);
|
|
99
|
+
const qs = params.toString();
|
|
100
|
+
const res = await cmsApi(`/seo/issues${qs ? `?${qs}` : ''}`);
|
|
101
|
+
return res.data?.issues ?? [];
|
|
102
|
+
}
|
|
103
|
+
export async function fetchSeoIssue(issueId) {
|
|
104
|
+
const res = await cmsApi(`/seo/issues/${encodeURIComponent(issueId)}`);
|
|
105
|
+
return res.data ?? null;
|
|
106
|
+
}
|
|
107
|
+
export async function resolveSeoIssue(issueId) {
|
|
108
|
+
const res = await cmsApi(`/seo/issues/${encodeURIComponent(issueId)}/resolve`, { method: 'POST' });
|
|
109
|
+
return res.error ? { error: res.error } : {};
|
|
110
|
+
}
|
|
111
|
+
export async function ignoreSeoIssue(issueId) {
|
|
112
|
+
const res = await cmsApi(`/seo/issues/${encodeURIComponent(issueId)}/ignore`, { method: 'POST' });
|
|
113
|
+
return res.error ? { error: res.error } : {};
|
|
114
|
+
}
|
|
115
|
+
export async function reopenSeoIssue(issueId) {
|
|
116
|
+
const res = await cmsApi(`/seo/issues/${encodeURIComponent(issueId)}/reopen`, { method: 'POST' });
|
|
117
|
+
return res.error ? { error: res.error } : {};
|
|
118
|
+
}
|
|
119
|
+
export async function fetchSitemapStatus() {
|
|
120
|
+
const res = await cmsApi('/seo/sitemap/status');
|
|
121
|
+
return res.data ?? null;
|
|
122
|
+
}
|
|
123
|
+
export async function regenerateSitemap() {
|
|
124
|
+
const res = await cmsApi('/seo/sitemap/regenerate', { method: 'POST' });
|
|
125
|
+
if (res.error)
|
|
126
|
+
return { error: res.error };
|
|
127
|
+
return { status: res.data };
|
|
128
|
+
}
|
|
129
|
+
export async function fetchCrawlSettings() {
|
|
130
|
+
const res = await cmsApi('/seo/crawl-settings');
|
|
131
|
+
return res.data ?? null;
|
|
132
|
+
}
|
|
133
|
+
export async function updateCrawlSettings(payload) {
|
|
134
|
+
const res = await cmsApi('/seo/crawl-settings', {
|
|
135
|
+
method: 'PUT',
|
|
136
|
+
body: JSON.stringify(payload),
|
|
137
|
+
});
|
|
138
|
+
return res.error ? { error: res.error } : {};
|
|
139
|
+
}
|
|
140
|
+
export async function fetchRobotsTxt() {
|
|
141
|
+
const res = await cmsApi('/seo/robots');
|
|
142
|
+
return res.data ?? null;
|
|
143
|
+
}
|
|
144
|
+
export async function updateRobotsTxt(body) {
|
|
145
|
+
const res = await cmsApi('/seo/robots', { method: 'PUT', body: JSON.stringify({ body }) });
|
|
146
|
+
return res.error ? { error: res.error } : {};
|
|
147
|
+
}
|
|
148
|
+
/** Client-side robots.txt validation (mirrors server-side checks). */
|
|
149
|
+
export function validateRobotsTxt(body) {
|
|
150
|
+
const errors = [];
|
|
151
|
+
const warnings = [];
|
|
152
|
+
const lines = body.split(/\r?\n/);
|
|
153
|
+
let blocksEntireSite = false;
|
|
154
|
+
let sawUserAgent = false;
|
|
155
|
+
let starAgent = false;
|
|
156
|
+
for (const raw of lines) {
|
|
157
|
+
const line = raw.trim();
|
|
158
|
+
if (!line || line.startsWith('#'))
|
|
159
|
+
continue;
|
|
160
|
+
const colon = line.indexOf(':');
|
|
161
|
+
if (colon === -1) {
|
|
162
|
+
errors.push(`Invalid directive (missing ":"): "${line}"`);
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const directive = line.slice(0, colon).trim().toLowerCase();
|
|
166
|
+
const value = line.slice(colon + 1).trim();
|
|
167
|
+
if (directive === 'user-agent') {
|
|
168
|
+
sawUserAgent = true;
|
|
169
|
+
starAgent = value === '*';
|
|
170
|
+
}
|
|
171
|
+
else if (directive === 'disallow') {
|
|
172
|
+
if (value === '/' && starAgent)
|
|
173
|
+
blocksEntireSite = true;
|
|
174
|
+
}
|
|
175
|
+
else if (!['allow', 'sitemap', 'crawl-delay', 'host'].includes(directive)) {
|
|
176
|
+
warnings.push(`Unknown directive: "${directive}"`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (!sawUserAgent)
|
|
180
|
+
errors.push('No User-agent directive found.');
|
|
181
|
+
if (blocksEntireSite) {
|
|
182
|
+
warnings.push('This configuration blocks the entire site from all crawlers.');
|
|
183
|
+
}
|
|
184
|
+
return { valid: errors.length === 0, blocksEntireSite, errors, warnings };
|
|
185
|
+
}
|
|
186
|
+
export async function fetchRedirectOverview() {
|
|
187
|
+
const res = await cmsApi('/seo/redirects/overview');
|
|
188
|
+
return (res.data ?? {
|
|
189
|
+
activeRedirects: 0,
|
|
190
|
+
staleRedirects: 0,
|
|
191
|
+
notFoundCount: 0,
|
|
192
|
+
notFoundHits: 0,
|
|
193
|
+
chainsAndLoops: 0,
|
|
194
|
+
trafficRecovered: 0,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
export async function fetchRedirectRules() {
|
|
198
|
+
const res = await cmsApi('/seo/redirects');
|
|
199
|
+
return res.data?.rules ?? [];
|
|
200
|
+
}
|
|
201
|
+
export async function createRedirectRule(payload) {
|
|
202
|
+
const res = await cmsApi('/seo/redirects', { method: 'POST', body: JSON.stringify(payload) });
|
|
203
|
+
return res.error ? { error: res.error } : {};
|
|
204
|
+
}
|
|
205
|
+
export async function updateRedirectRule(redirectId, payload) {
|
|
206
|
+
const res = await cmsApi(`/seo/redirects/${encodeURIComponent(redirectId)}`, {
|
|
207
|
+
method: 'PUT',
|
|
208
|
+
body: JSON.stringify(payload),
|
|
209
|
+
});
|
|
210
|
+
return res.error ? { error: res.error } : {};
|
|
211
|
+
}
|
|
212
|
+
export async function deleteRedirectRule(redirectId) {
|
|
213
|
+
const res = await cmsApi(`/seo/redirects/${encodeURIComponent(redirectId)}`, {
|
|
214
|
+
method: 'DELETE',
|
|
215
|
+
});
|
|
216
|
+
return res.error ? { error: res.error } : {};
|
|
217
|
+
}
|
|
218
|
+
export async function fetchRedirectChains() {
|
|
219
|
+
const res = await cmsApi('/seo/redirects/chains');
|
|
220
|
+
return res.data?.chains ?? [];
|
|
221
|
+
}
|
|
222
|
+
export async function flattenRedirectChain(chainId) {
|
|
223
|
+
const res = await cmsApi('/seo/redirects/flatten', {
|
|
224
|
+
method: 'POST',
|
|
225
|
+
body: JSON.stringify({ chainId }),
|
|
226
|
+
});
|
|
227
|
+
return res.error ? { error: res.error } : {};
|
|
228
|
+
}
|
|
229
|
+
export async function fetchRedirectSuggestions() {
|
|
230
|
+
const res = await cmsApi('/seo/redirects/suggestions');
|
|
231
|
+
return res.data?.suggestions ?? [];
|
|
232
|
+
}
|
|
233
|
+
export async function generate404RecoverySuggestions() {
|
|
234
|
+
const res = await cmsApi('/seo/redirects/suggest', { method: 'POST' });
|
|
235
|
+
return res.error ? { error: res.error } : {};
|
|
236
|
+
}
|
|
237
|
+
export async function acceptRedirectSuggestion(suggestionId) {
|
|
238
|
+
const res = await cmsApi(`/seo/redirects/suggestions/${encodeURIComponent(suggestionId)}/accept`, {
|
|
239
|
+
method: 'POST',
|
|
240
|
+
});
|
|
241
|
+
return res.error ? { error: res.error } : {};
|
|
242
|
+
}
|
|
243
|
+
export async function dismissRedirectSuggestion(suggestionId) {
|
|
244
|
+
const res = await cmsApi(`/seo/redirects/suggestions/${encodeURIComponent(suggestionId)}/dismiss`, { method: 'POST' });
|
|
245
|
+
return res.error ? { error: res.error } : {};
|
|
246
|
+
}
|
|
247
|
+
export async function exportRedirectsCsv() {
|
|
248
|
+
const res = await cmsApi('/seo/redirects/export');
|
|
249
|
+
if (res.error)
|
|
250
|
+
return { error: res.error };
|
|
251
|
+
return { csv: res.data?.csv ?? '' };
|
|
252
|
+
}
|
|
253
|
+
export async function importRedirectsCsv(csv) {
|
|
254
|
+
const res = await cmsApi('/seo/redirects/import', {
|
|
255
|
+
method: 'POST',
|
|
256
|
+
body: JSON.stringify({ csv }),
|
|
257
|
+
});
|
|
258
|
+
if (res.error)
|
|
259
|
+
return { error: res.error };
|
|
260
|
+
return { imported: res.data?.imported ?? 0, errors: res.data?.errors ?? [] };
|
|
261
|
+
}
|
|
262
|
+
export async function generateSeoField(field, context) {
|
|
263
|
+
const res = await cmsApi('/ai/seo/generate-field', {
|
|
264
|
+
method: 'POST',
|
|
265
|
+
body: JSON.stringify({ field, ...context }),
|
|
266
|
+
});
|
|
267
|
+
if (res.status === 501)
|
|
268
|
+
return { unavailable: true };
|
|
269
|
+
return res.data ?? {};
|
|
270
|
+
}
|
|
271
|
+
export async function explainSeoIssue(issueId) {
|
|
272
|
+
const res = await cmsApi('/ai/seo/explain-issue', {
|
|
273
|
+
method: 'POST',
|
|
274
|
+
body: JSON.stringify({ issueId }),
|
|
275
|
+
});
|
|
276
|
+
if (res.status === 501)
|
|
277
|
+
return { unavailable: true };
|
|
278
|
+
return res.data ?? {};
|
|
279
|
+
}
|
|
280
|
+
export async function generateStructuredData(context) {
|
|
281
|
+
const res = await cmsApi('/ai/seo/generate-schema', {
|
|
282
|
+
method: 'POST',
|
|
283
|
+
body: JSON.stringify(context),
|
|
284
|
+
});
|
|
285
|
+
if (res.status === 501)
|
|
286
|
+
return { unavailable: true };
|
|
287
|
+
return res.data ?? {};
|
|
288
|
+
}
|
|
289
|
+
export async function summarizeSeoAudit() {
|
|
290
|
+
const res = await cmsApi('/ai/seo/summarize', { method: 'POST' });
|
|
291
|
+
if (res.status === 501)
|
|
292
|
+
return { unavailable: true };
|
|
293
|
+
return res.data ?? {};
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=seo-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seo-service.js","sourceRoot":"","sources":["../../src/lib/seo-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CACtB;AAUD,wBAAgB,cAAc,CAAC,QAAQ,SAAW,EAAE,UAAU,SAAM;;qBAsB9B,MAAM;0BAkB9B,MAAM,KAAG,WAAW,GAAG,IAAI;sBANF,MAAM;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAIA,UAAU,WAAW;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CACtB;AAUD,wBAAgB,cAAc,CAAC,QAAQ,SAAW,EAAE,UAAU,SAAM;;qBAsB9B,MAAM;0BAkB9B,MAAM,KAAG,WAAW,GAAG,IAAI;sBANF,MAAM;EAwC5C"}
|
package/dist/router/index.js
CHANGED
|
@@ -41,8 +41,11 @@ export function useAdminRouter(basePath = '/admin', serverPath = '/') {
|
|
|
41
41
|
return normalizedPath === '/' ? baseRef.current : `${baseRef.current}${normalizedPath}`;
|
|
42
42
|
}, []);
|
|
43
43
|
const matchRoute = useCallback((pattern) => {
|
|
44
|
+
// Match against the path only — query string / hash are state-bearing
|
|
45
|
+
// (e.g. `/seo?tab=audit`) and must not defeat route matching.
|
|
46
|
+
const pathname = currentPath.split('?')[0].split('#')[0];
|
|
44
47
|
const patternParts = pattern.split('/').filter(Boolean);
|
|
45
|
-
const pathParts =
|
|
48
|
+
const pathParts = pathname.split('/').filter(Boolean);
|
|
46
49
|
if (pattern === '/' && pathParts.length === 0) {
|
|
47
50
|
return {};
|
|
48
51
|
}
|
package/dist/router/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaBrowser.d.ts","sourceRoot":"","sources":["../../src/views/MediaBrowser.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MediaBrowser.d.ts","sourceRoot":"","sources":["../../src/views/MediaBrowser.tsx"],"names":[],"mappings":"AAiFA,MAAM,WAAW,iBAAiB;IAChC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAYD,wBAAgB,YAAY,CAAC,EAAE,UAAU,EAAE,EAAE,iBAAiB,2CA65B7D"}
|
|
@@ -7,7 +7,6 @@ import { sortByRelevance, toggleSort } from '../lib/search.js';
|
|
|
7
7
|
import { useApiData } from '../lib/useApiData.js';
|
|
8
8
|
import { cmsApi } from '../lib/api.js';
|
|
9
9
|
import { FolderTree } from '../components/FolderTree.js';
|
|
10
|
-
import { FocalPointPicker } from '../components/FocalPointPicker.js';
|
|
11
10
|
function isImageMedia(item) {
|
|
12
11
|
return (Boolean(item.url) &&
|
|
13
12
|
(item.type?.startsWith('image/') || /\.(avif|gif|jpe?g|png|webp|svg)$/i.test(item.url)));
|
|
@@ -56,8 +55,6 @@ export function MediaBrowser({ onNavigate }) {
|
|
|
56
55
|
const [editAlt, setEditAlt] = useState('');
|
|
57
56
|
const [editTitle, setEditTitle] = useState('');
|
|
58
57
|
const [editFilename, setEditFilename] = useState('');
|
|
59
|
-
const [focalX, setFocalX] = useState(0.5);
|
|
60
|
-
const [focalY, setFocalY] = useState(0.5);
|
|
61
58
|
const [saving, setSaving] = useState(false);
|
|
62
59
|
const [aiGenerating, setAiGenerating] = useState(null);
|
|
63
60
|
const [uploading, setUploading] = useState(false);
|
|
@@ -91,8 +88,6 @@ export function MediaBrowser({ onNavigate }) {
|
|
|
91
88
|
setEditAlt(item.altTag ?? '');
|
|
92
89
|
setEditTitle(item.title ?? '');
|
|
93
90
|
setEditFilename(item.name);
|
|
94
|
-
setFocalX(item.focalPointX ?? 0.5);
|
|
95
|
-
setFocalY(item.focalPointY ?? 0.5);
|
|
96
91
|
};
|
|
97
92
|
const closeDetail = () => {
|
|
98
93
|
setActiveItem(null);
|
|
@@ -114,8 +109,6 @@ export function MediaBrowser({ onNavigate }) {
|
|
|
114
109
|
alt: editAlt,
|
|
115
110
|
title: editTitle,
|
|
116
111
|
filename: editFilename,
|
|
117
|
-
focalX,
|
|
118
|
-
focalY,
|
|
119
112
|
}),
|
|
120
113
|
});
|
|
121
114
|
setSaving(false);
|
|
@@ -157,18 +150,34 @@ export function MediaBrowser({ onNavigate }) {
|
|
|
157
150
|
setAiGenerating(null);
|
|
158
151
|
return;
|
|
159
152
|
}
|
|
160
|
-
|
|
153
|
+
if (!activeItem) {
|
|
154
|
+
setAiGenerating(null);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const res = await cmsApi('/ai/media-metadata', { method: 'POST', body: JSON.stringify({ mediaId: activeItem.id }) });
|
|
158
|
+
if (res.error) {
|
|
159
|
+
// AI plugin/provider not configured (e.g. local dev): fall back to a
|
|
160
|
+
// basic filename-derived suggestion so the action still helps.
|
|
161
|
+
const base = (activeItem.name ?? '')
|
|
162
|
+
.replace(/\.\w+$/, '')
|
|
163
|
+
.replace(/[-_]/g, ' ')
|
|
164
|
+
.trim();
|
|
165
|
+
if (field === 'alt') {
|
|
166
|
+
setEditAlt(base ? `Image of ${base}` : '');
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
setEditTitle(base.replace(/\b\w/g, (c) => c.toUpperCase()));
|
|
170
|
+
}
|
|
171
|
+
toast.info('AI unavailable — generated a basic suggestion from the filename');
|
|
172
|
+
setAiGenerating(null);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
161
175
|
if (field === 'alt') {
|
|
162
|
-
|
|
163
|
-
setEditAlt(generated);
|
|
176
|
+
setEditAlt(res.data?.alt ?? '');
|
|
164
177
|
toast.success('Alt tag generated by AI');
|
|
165
178
|
}
|
|
166
|
-
else
|
|
167
|
-
|
|
168
|
-
.replace(/[-_]/g, ' ')
|
|
169
|
-
.replace(/\.\w+$/, '')
|
|
170
|
-
.replace(/\b\w/g, (c) => c.toUpperCase()) ?? '';
|
|
171
|
-
setEditTitle(generated);
|
|
179
|
+
else {
|
|
180
|
+
setEditTitle(res.data?.title ?? '');
|
|
172
181
|
toast.success('Title generated by AI');
|
|
173
182
|
}
|
|
174
183
|
setAiGenerating(null);
|
|
@@ -253,18 +262,23 @@ export function MediaBrowser({ onNavigate }) {
|
|
|
253
262
|
? 'No uncategorized media'
|
|
254
263
|
: folderSel.type === 'folder'
|
|
255
264
|
? 'No media in this folder'
|
|
256
|
-
: 'No media yet' }), _jsx("p", { className: "text-sm text-gray-500", children: "Upload your first file to get started." })] })) : (_jsxs("div", { className: "flex min-h-0 flex-1 gap-4 overflow-hidden", children: [_jsx("div", { className: `overflow-hidden rounded-lg border border-gray-200 bg-white transition-all duration-200 ${panelOpen ? 'min-w-0 flex-1' : 'w-full'}`, children: viewMode === 'grid' ? (_jsx("div", { className: `grid h-full gap-
|
|
265
|
+
: 'No media yet' }), _jsx("p", { className: "text-sm text-gray-500", children: "Upload your first file to get started." })] })) : (_jsxs("div", { className: "flex min-h-0 flex-1 gap-4 overflow-hidden", children: [_jsx("div", { className: `overflow-hidden rounded-lg border border-gray-200 bg-white transition-all duration-200 ${panelOpen ? 'min-w-0 flex-1' : 'w-full'}`, children: viewMode === 'grid' ? (_jsx("div", { className: `grid h-full auto-rows-min content-start gap-3 overflow-y-auto p-2 sm:gap-4 sm:p-3 ${panelOpen
|
|
257
266
|
? 'grid-cols-2 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4'
|
|
258
267
|
: 'grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 2xl:grid-cols-8'}`, children: filteredAndSorted.map((item) => {
|
|
259
268
|
const isActive = activeItem?.id === item.id;
|
|
260
269
|
const hasIssues = !item.altTag || !item.title || item.usedOn?.length === 0;
|
|
261
|
-
|
|
270
|
+
const typeLabel = (item.name.includes('.')
|
|
271
|
+
? item.name.split('.').pop()
|
|
272
|
+
: item.format || item.type || '')
|
|
273
|
+
.replace(/^.*\//, '')
|
|
274
|
+
.toUpperCase();
|
|
275
|
+
return (_jsxs("div", { className: `group relative flex cursor-pointer flex-col overflow-hidden rounded-lg border-2 transition-all ${isActive
|
|
262
276
|
? 'border-blue-500 ring-2 ring-blue-200'
|
|
263
277
|
: selectedMedia.includes(item.id)
|
|
264
278
|
? 'border-blue-400 ring-1 ring-blue-100'
|
|
265
|
-
: 'border-gray-200 hover:border-gray-300'}`, onClick: () => openDetail(item), draggable: true, onDragStart: (e) => handleDragStart(e, item.id), children: [
|
|
266
|
-
|
|
267
|
-
|
|
279
|
+
: 'border-gray-200 hover:border-gray-300'}`, onClick: () => openDetail(item), draggable: true, onDragStart: (e) => handleDragStart(e, item.id), children: [_jsxs("div", { className: "relative aspect-square w-full overflow-hidden", children: [_jsx("div", { className: "flex h-full w-full items-center justify-center bg-gray-100", children: _jsx(MediaPreview, { item: item }) }), hasIssues && (_jsx("div", { className: "absolute top-1.5 left-1.5 flex h-5 w-5 items-center justify-center rounded-full bg-yellow-500", title: "Needs attention", children: _jsx(AlertTriangle, { className: "h-3 w-3 text-white" }) })), _jsx("div", { className: "absolute top-1.5 right-1.5 opacity-0 transition-opacity group-hover:opacity-100", onClick: (e) => handleCheckbox(e, item.id), children: _jsx("div", { className: `flex h-5 w-5 items-center justify-center rounded border-2 transition-colors ${selectedMedia.includes(item.id)
|
|
280
|
+
? 'border-blue-600 bg-blue-600'
|
|
281
|
+
: 'border-gray-400 bg-white/80'}`, children: selectedMedia.includes(item.id) && (_jsx("svg", { className: "h-3 w-3 text-white", fill: "none", viewBox: "0 0 12 12", children: _jsx("path", { d: "M10 3L4.5 8.5L2 6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })) }) })] }), _jsxs("div", { className: "flex items-center gap-2 border-t border-gray-200 bg-white px-2 py-1.5", children: [_jsx("span", { className: `mt-0.5 h-2 w-2 shrink-0 self-start rounded-full ${hasIssues ? 'bg-yellow-500' : 'bg-green-500'}`, title: hasIssues ? 'Needs attention' : 'SEO complete' }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-xs font-medium text-gray-900", children: item.name }), _jsx("p", { className: "truncate text-xs text-gray-500", children: [typeLabel, item.size].filter(Boolean).join(' · ') })] })] })] }, item.id));
|
|
268
282
|
}) })) : (_jsx("div", { className: "h-full overflow-y-auto", children: _jsxs("table", { className: "w-full", children: [_jsx("thead", { className: "sticky top-0 border-b border-gray-200 bg-gray-50", children: _jsxs("tr", { children: [_jsx("th", { className: "w-8 px-3 py-2 text-left", children: _jsx("input", { type: "checkbox", checked: selectedMedia.length === filteredAndSorted.length &&
|
|
269
283
|
filteredAndSorted.length > 0, onChange: handleSelectAll, className: "rounded border-gray-300" }) }), _jsx("th", { className: "w-6 px-1 py-2" }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Name", sortKey: "name" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Type", sortKey: "type" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Size", sortKey: "size" }) }), _jsx("th", { className: "px-3 py-2 text-left", children: _jsx(SortHeader, { label: "Uploaded", sortKey: "date" }) }), _jsx("th", { className: "px-3 py-2 text-left text-xs font-medium text-gray-700", children: "Status" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-200", children: filteredAndSorted.map((item) => {
|
|
270
284
|
const isActive = activeItem?.id === item.id;
|
|
@@ -277,9 +291,6 @@ export function MediaBrowser({ onNavigate }) {
|
|
|
277
291
|
await handleAiGenerate('title');
|
|
278
292
|
if (activeItem.sizeBytes > 2000000)
|
|
279
293
|
await handleAiGenerate('optimize');
|
|
280
|
-
}, className: "mt-2 flex w-full items-center justify-center gap-1.5 rounded-lg bg-yellow-600 px-3 py-1.5 text-xs text-white transition-colors hover:bg-yellow-700", children: [_jsx(Sparkles, { className: "h-3.5 w-3.5" }), "AI Fix All Issues"] })] })), _jsxs("div", { className: "space-y-3 border-b border-gray-200 p-4", children: [_jsx("h4", { className: "text-xs font-semibold tracking-wide text-gray-500 uppercase", children: "File Information" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsxs("div", { children: [_jsx("div", { className: "mb-0.5 text-xs text-gray-500", children: "Format" }), _jsx("div", { className: "text-sm text-gray-900", children: activeItem.format ?? 'Unknown' })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-0.5 text-xs text-gray-500", children: "File Size" }), _jsxs("div", { className: "flex items-center gap-1 text-sm text-gray-900", children: [activeItem.size, activeItem.sizeBytes > 2000000 && (_jsx("span", { className: "text-xs text-yellow-600", children: "(large)" }))] })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-0.5 text-xs text-gray-500", children: "Dimensions" }), _jsx("div", { className: "text-sm text-gray-900", children: activeItem.dimensions ?? '—' })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-0.5 text-xs text-gray-500", children: "Uploaded" }), _jsx("div", { className: "text-sm text-gray-900", children: activeItem.date })] })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-1 text-xs text-gray-500", children: "URL" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("code", { className: "flex-1 truncate rounded border border-gray-200 bg-gray-50 px-2 py-1.5 text-xs text-gray-700", children: activeItem.url }), _jsx("button", { onClick: handleCopyUrl, className: "shrink-0 rounded p-1.5 transition-colors hover:bg-gray-100", title: "Copy URL", children: _jsx(Copy, { className: "h-3.5 w-3.5 text-gray-500" }) })] })] })] }), _jsxs("div", { className: "space-y-4 border-b border-gray-200 p-4", children: [_jsx("h4", { className: "text-xs font-semibold tracking-wide text-gray-500 uppercase", children: "SEO & Accessibility" }), _jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center justify-between", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Alt Tag" }), _jsxs("button", { type: "button", onClick: () => handleAiGenerate('alt'), disabled: aiGenerating === 'alt', className: "flex items-center gap-1 text-xs text-indigo-600 transition-colors hover:text-indigo-700 disabled:opacity-50", children: [_jsx(Bot, { className: "h-3.5 w-3.5" }), aiGenerating === 'alt' ? 'Generating...' : 'AI Generate'] })] }), _jsx("textarea", { value: editAlt, onChange: (e) => setEditAlt(e.target.value), placeholder: "Describe this image for accessibility...", rows: 2, className: "w-full resize-none rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" }), !editAlt && (_jsx("p", { className: "mt-1 text-xs text-red-500", children: "Required for accessibility and SEO" }))] }), _jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center justify-between", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Title" }), _jsxs("button", { type: "button", onClick: () => handleAiGenerate('title'), disabled: aiGenerating === 'title', className: "flex items-center gap-1 text-xs text-indigo-600 transition-colors hover:text-indigo-700 disabled:opacity-50", children: [_jsx(Bot, { className: "h-3.5 w-3.5" }), aiGenerating === 'title' ? 'Generating...' : 'AI Generate'] })] }), _jsx("input", { type: "text", value: editTitle, onChange: (e) => setEditTitle(e.target.value), placeholder: "Image title...", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "File Name" }), _jsx("input", { type: "text", value: editFilename, onChange: (e) => setEditFilename(e.target.value), className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] })] }),
|
|
281
|
-
setFocalX(x);
|
|
282
|
-
setFocalY(y);
|
|
283
|
-
} }) })), _jsxs("div", { className: "border-b border-gray-200 p-4", children: [_jsxs("h4", { className: "mb-3 text-xs font-semibold tracking-wide text-gray-500 uppercase", children: ["Used On ", activeItem.usedOn && `(${activeItem.usedOn.length})`] }), activeItem.usedOn && activeItem.usedOn.length > 0 ? (_jsx("div", { className: "space-y-2", children: activeItem.usedOn.map((usage, i) => (_jsxs("button", { type: "button", onClick: () => onNavigate?.(usage.path), className: "flex w-full items-center gap-2 rounded-lg border border-gray-200 p-2 text-left transition-colors hover:bg-gray-50", children: [_jsx(Link2, { className: "h-4 w-4 shrink-0 text-gray-400" }), _jsx("span", { className: "flex-1 truncate text-sm text-gray-900", children: usage.page }), _jsx(ExternalLink, { className: "h-3.5 w-3.5 shrink-0 text-gray-400" })] }, i))) })) : (_jsx("div", { className: "rounded-lg border border-orange-200 bg-orange-50 p-3", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-orange-600" }), _jsxs("div", { children: [_jsx("p", { className: "text-xs font-medium text-orange-900", children: "Orphaned media" }), _jsx("p", { className: "mt-0.5 text-xs text-orange-700", children: "This file isn't used on any page. Consider deleting it to save storage." })] })] }) }))] }), _jsxs("div", { className: "space-y-3 p-4", children: [_jsx("h4", { className: "text-xs font-semibold tracking-wide text-gray-500 uppercase", children: "AI Optimization" }), _jsxs("button", { type: "button", onClick: () => handleAiGenerate('optimize'), disabled: aiGenerating === 'optimize', className: "flex w-full items-center gap-2 rounded-lg border border-indigo-200 bg-indigo-50 p-3 text-left transition-colors hover:bg-indigo-100 disabled:opacity-50", children: [_jsx(Sparkles, { className: `h-5 w-5 shrink-0 text-indigo-600 ${aiGenerating === 'optimize' ? 'animate-spin' : ''}` }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-sm font-medium text-indigo-900", children: aiGenerating === 'optimize' ? 'Optimizing...' : 'Optimize Image' }), _jsx("div", { className: "mt-0.5 text-xs text-indigo-700", children: "Compress and convert to modern format (WebP/AVIF)" })] })] }), _jsxs("button", { type: "button", className: "flex w-full items-center gap-2 rounded-lg border border-gray-200 p-3 text-left transition-colors hover:bg-gray-50", children: [_jsx(Bot, { className: "h-5 w-5 shrink-0 text-gray-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-sm font-medium text-gray-900", children: "AI Content Analysis" }), _jsx("div", { className: "mt-0.5 text-xs text-gray-600", children: "Detect objects, faces, text, and suggest categories" })] })] })] })] }), _jsxs("div", { className: "sticky bottom-0 flex items-center gap-2 border-t border-gray-200 bg-white p-4", children: [_jsxs("button", { type: "button", onClick: handleSaveDetails, disabled: saving, className: "flex flex-1 items-center justify-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700 disabled:opacity-50", children: [saving && _jsx(Loader2, { className: "h-4 w-4 animate-spin" }), saving ? 'Saving...' : 'Save Changes'] }), _jsx("button", { type: "button", className: "rounded-lg p-2 transition-colors hover:bg-gray-100", title: "Download", children: _jsx(Download, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { type: "button", onClick: () => deleteMedia(activeItem.id), className: "rounded-lg p-2 transition-colors hover:bg-gray-100", title: "Delete", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] })] }))] }))] })] })] }));
|
|
294
|
+
}, className: "mt-2 flex w-full items-center justify-center gap-1.5 rounded-lg bg-yellow-600 px-3 py-1.5 text-xs text-white transition-colors hover:bg-yellow-700", children: [_jsx(Sparkles, { className: "h-3.5 w-3.5" }), "AI Fix All Issues"] })] })), _jsxs("div", { className: "space-y-3 border-b border-gray-200 p-4", children: [_jsx("h4", { className: "text-xs font-semibold tracking-wide text-gray-500 uppercase", children: "File Information" }), _jsxs("div", { className: "grid grid-cols-2 gap-3", children: [_jsxs("div", { children: [_jsx("div", { className: "mb-0.5 text-xs text-gray-500", children: "Format" }), _jsx("div", { className: "text-sm text-gray-900", children: activeItem.format ?? 'Unknown' })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-0.5 text-xs text-gray-500", children: "File Size" }), _jsxs("div", { className: "flex items-center gap-1 text-sm text-gray-900", children: [activeItem.size, activeItem.sizeBytes > 2000000 && (_jsx("span", { className: "text-xs text-yellow-600", children: "(large)" }))] })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-0.5 text-xs text-gray-500", children: "Dimensions" }), _jsx("div", { className: "text-sm text-gray-900", children: activeItem.dimensions ?? '—' })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-0.5 text-xs text-gray-500", children: "Uploaded" }), _jsx("div", { className: "text-sm text-gray-900", children: activeItem.date })] })] }), _jsxs("div", { children: [_jsx("div", { className: "mb-1 text-xs text-gray-500", children: "URL" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("code", { className: "flex-1 truncate rounded border border-gray-200 bg-gray-50 px-2 py-1.5 text-xs text-gray-700", children: activeItem.url }), _jsx("button", { onClick: handleCopyUrl, className: "shrink-0 rounded p-1.5 transition-colors hover:bg-gray-100", title: "Copy URL", children: _jsx(Copy, { className: "h-3.5 w-3.5 text-gray-500" }) })] })] })] }), _jsxs("div", { className: "space-y-4 border-b border-gray-200 p-4", children: [_jsx("h4", { className: "text-xs font-semibold tracking-wide text-gray-500 uppercase", children: "SEO & Accessibility" }), _jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center justify-between", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Alt Tag" }), _jsxs("button", { type: "button", onClick: () => handleAiGenerate('alt'), disabled: aiGenerating === 'alt', className: "flex items-center gap-1 text-xs text-indigo-600 transition-colors hover:text-indigo-700 disabled:opacity-50", children: [_jsx(Bot, { className: "h-3.5 w-3.5" }), aiGenerating === 'alt' ? 'Generating...' : 'AI Generate'] })] }), _jsx("textarea", { value: editAlt, onChange: (e) => setEditAlt(e.target.value), placeholder: "Describe this image for accessibility...", rows: 2, className: "w-full resize-none rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" }), !editAlt && (_jsx("p", { className: "mt-1 text-xs text-red-500", children: "Required for accessibility and SEO" }))] }), _jsxs("div", { children: [_jsxs("div", { className: "mb-1 flex items-center justify-between", children: [_jsx("label", { className: "text-sm font-medium text-gray-700", children: "Title" }), _jsxs("button", { type: "button", onClick: () => handleAiGenerate('title'), disabled: aiGenerating === 'title', className: "flex items-center gap-1 text-xs text-indigo-600 transition-colors hover:text-indigo-700 disabled:opacity-50", children: [_jsx(Bot, { className: "h-3.5 w-3.5" }), aiGenerating === 'title' ? 'Generating...' : 'AI Generate'] })] }), _jsx("input", { type: "text", value: editTitle, onChange: (e) => setEditTitle(e.target.value), placeholder: "Image title...", className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] }), _jsxs("div", { children: [_jsx("label", { className: "mb-1 block text-sm font-medium text-gray-700", children: "File Name" }), _jsx("input", { type: "text", value: editFilename, onChange: (e) => setEditFilename(e.target.value), className: "w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none" })] })] }), _jsxs("div", { className: "border-b border-gray-200 p-4", children: [_jsxs("h4", { className: "mb-3 text-xs font-semibold tracking-wide text-gray-500 uppercase", children: ["Used On ", activeItem.usedOn && `(${activeItem.usedOn.length})`] }), activeItem.usedOn && activeItem.usedOn.length > 0 ? (_jsx("div", { className: "space-y-2", children: activeItem.usedOn.map((usage, i) => (_jsxs("button", { type: "button", onClick: () => onNavigate?.(usage.path), className: "flex w-full items-center gap-2 rounded-lg border border-gray-200 p-2 text-left transition-colors hover:bg-gray-50", children: [_jsx(Link2, { className: "h-4 w-4 shrink-0 text-gray-400" }), _jsx("span", { className: "flex-1 truncate text-sm text-gray-900", children: usage.page }), _jsx(ExternalLink, { className: "h-3.5 w-3.5 shrink-0 text-gray-400" })] }, i))) })) : (_jsx("div", { className: "rounded-lg border border-orange-200 bg-orange-50 p-3", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(AlertTriangle, { className: "mt-0.5 h-4 w-4 shrink-0 text-orange-600" }), _jsxs("div", { children: [_jsx("p", { className: "text-xs font-medium text-orange-900", children: "Orphaned media" }), _jsx("p", { className: "mt-0.5 text-xs text-orange-700", children: "This file isn't used on any page. Consider deleting it to save storage." })] })] }) }))] }), _jsxs("div", { className: "space-y-3 p-4", children: [_jsx("h4", { className: "text-xs font-semibold tracking-wide text-gray-500 uppercase", children: "AI Optimization" }), _jsxs("button", { type: "button", onClick: () => handleAiGenerate('optimize'), disabled: aiGenerating === 'optimize', className: "flex w-full items-center gap-2 rounded-lg border border-indigo-200 bg-indigo-50 p-3 text-left transition-colors hover:bg-indigo-100 disabled:opacity-50", children: [_jsx(Sparkles, { className: `h-5 w-5 shrink-0 text-indigo-600 ${aiGenerating === 'optimize' ? 'animate-spin' : ''}` }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-sm font-medium text-indigo-900", children: aiGenerating === 'optimize' ? 'Optimizing...' : 'Optimize Image' }), _jsx("div", { className: "mt-0.5 text-xs text-indigo-700", children: "Compress and convert to modern format (WebP/AVIF)" })] })] }), _jsxs("button", { type: "button", className: "flex w-full items-center gap-2 rounded-lg border border-gray-200 p-3 text-left transition-colors hover:bg-gray-50", children: [_jsx(Bot, { className: "h-5 w-5 shrink-0 text-gray-500" }), _jsxs("div", { className: "flex-1", children: [_jsx("div", { className: "text-sm font-medium text-gray-900", children: "AI Content Analysis" }), _jsx("div", { className: "mt-0.5 text-xs text-gray-600", children: "Detect objects, faces, text, and suggest categories" })] })] })] })] }), _jsxs("div", { className: "sticky bottom-0 flex items-center gap-2 border-t border-gray-200 bg-white p-4", children: [_jsxs("button", { type: "button", onClick: handleSaveDetails, disabled: saving, className: "flex flex-1 items-center justify-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-sm text-white transition-colors hover:bg-blue-700 disabled:opacity-50", children: [saving && _jsx(Loader2, { className: "h-4 w-4 animate-spin" }), saving ? 'Saving...' : 'Save Changes'] }), _jsx("button", { type: "button", className: "rounded-lg p-2 transition-colors hover:bg-gray-100", title: "Download", children: _jsx(Download, { className: "h-4 w-4 text-gray-600" }) }), _jsx("button", { type: "button", onClick: () => deleteMedia(activeItem.id), className: "rounded-lg p-2 transition-colors hover:bg-gray-100", title: "Delete", children: _jsx(Trash2, { className: "h-4 w-4 text-red-600" }) })] })] }))] }))] })] })] }));
|
|
284
295
|
}
|
|
285
296
|
//# sourceMappingURL=MediaBrowser.js.map
|