@actuate-media/cms-admin 0.35.0 → 0.36.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/dist/__tests__/views/ai-settings.render.test.js +22 -0
- package/dist/__tests__/views/ai-settings.render.test.js.map +1 -1
- package/dist/actuate-admin.css +1 -1
- package/dist/views/ApiKeys.d.ts.map +1 -1
- package/dist/views/ApiKeys.js +14 -13
- package/dist/views/ApiKeys.js.map +1 -1
- package/dist/views/Profile.d.ts.map +1 -1
- package/dist/views/Profile.js +1 -1
- package/dist/views/Profile.js.map +1 -1
- package/dist/views/Settings.d.ts.map +1 -1
- package/dist/views/Settings.js +25 -20
- package/dist/views/Settings.js.map +1 -1
- package/dist/views/Users.js +1 -1
- package/dist/views/Users.js.map +1 -1
- package/dist/views/settings/AISettingsTab.d.ts.map +1 -1
- package/dist/views/settings/AISettingsTab.js +42 -43
- package/dist/views/settings/AISettingsTab.js.map +1 -1
- package/dist/views/settings/AiFeaturesCard.d.ts.map +1 -1
- package/dist/views/settings/AiFeaturesCard.js +2 -3
- package/dist/views/settings/AiFeaturesCard.js.map +1 -1
- package/dist/views/settings/BrandVoiceCard.d.ts +12 -0
- package/dist/views/settings/BrandVoiceCard.d.ts.map +1 -0
- package/dist/views/settings/BrandVoiceCard.js +25 -0
- package/dist/views/settings/BrandVoiceCard.js.map +1 -0
- package/dist/views/settings/GeneralSettingsTab.js +1 -1
- package/dist/views/settings/LanguageRegionCard.d.ts.map +1 -1
- package/dist/views/settings/LanguageRegionCard.js +2 -1
- package/dist/views/settings/LanguageRegionCard.js.map +1 -1
- package/dist/views/settings/MonthlyUsageCard.d.ts.map +1 -1
- package/dist/views/settings/MonthlyUsageCard.js +3 -3
- package/dist/views/settings/MonthlyUsageCard.js.map +1 -1
- package/dist/views/settings/ProviderConnectionCard.js +1 -1
- package/dist/views/settings/ProviderConnectionCard.js.map +1 -1
- package/dist/views/settings/SecurityStatusCard.d.ts.map +1 -1
- package/dist/views/settings/SecurityStatusCard.js +2 -3
- package/dist/views/settings/SecurityStatusCard.js.map +1 -1
- package/dist/views/settings/SecurityTab.js +1 -1
- package/dist/views/settings/SeoRobotsDefaultsCard.d.ts.map +1 -1
- package/dist/views/settings/SeoRobotsDefaultsCard.js +3 -4
- package/dist/views/settings/SeoRobotsDefaultsCard.js.map +1 -1
- package/dist/views/settings/SeoSettingsTab.d.ts.map +1 -1
- package/dist/views/settings/SeoSettingsTab.js +5 -8
- package/dist/views/settings/SeoSettingsTab.js.map +1 -1
- package/dist/views/settings/SiteIndexStatusCard.d.ts.map +1 -1
- package/dist/views/settings/SiteIndexStatusCard.js +3 -2
- package/dist/views/settings/SiteIndexStatusCard.js.map +1 -1
- package/dist/views/settings/SiteInformationCard.d.ts.map +1 -1
- package/dist/views/settings/SiteInformationCard.js +4 -4
- package/dist/views/settings/SiteInformationCard.js.map +1 -1
- package/dist/views/settings/components.d.ts +31 -1
- package/dist/views/settings/components.d.ts.map +1 -1
- package/dist/views/settings/components.js +22 -0
- package/dist/views/settings/components.js.map +1 -1
- package/dist/views/settings/securityPrimitives.d.ts +11 -3
- package/dist/views/settings/securityPrimitives.d.ts.map +1 -1
- package/dist/views/settings/securityPrimitives.js +10 -3
- package/dist/views/settings/securityPrimitives.js.map +1 -1
- package/dist/views/settings/useAiSettings.d.ts +12 -0
- package/dist/views/settings/useAiSettings.d.ts.map +1 -1
- package/dist/views/settings/useAiSettings.js +51 -0
- package/dist/views/settings/useAiSettings.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/views/ai-settings.render.test.tsx +36 -0
- package/src/views/ApiKeys.tsx +190 -154
- package/src/views/Profile.tsx +4 -2
- package/src/views/Settings.tsx +154 -143
- package/src/views/Users.tsx +1 -1
- package/src/views/settings/AISettingsTab.tsx +66 -76
- package/src/views/settings/AiFeaturesCard.tsx +6 -12
- package/src/views/settings/BrandVoiceCard.tsx +139 -0
- package/src/views/settings/GeneralSettingsTab.tsx +1 -1
- package/src/views/settings/LanguageRegionCard.tsx +5 -7
- package/src/views/settings/MonthlyUsageCard.tsx +6 -10
- package/src/views/settings/ProviderConnectionCard.tsx +1 -1
- package/src/views/settings/SecurityStatusCard.tsx +8 -11
- package/src/views/settings/SecurityTab.tsx +1 -1
- package/src/views/settings/SeoRobotsDefaultsCard.tsx +7 -14
- package/src/views/settings/SeoSettingsTab.tsx +17 -26
- package/src/views/settings/SiteIndexStatusCard.tsx +10 -22
- package/src/views/settings/SiteInformationCard.tsx +3 -9
- package/src/views/settings/components.tsx +72 -1
- package/src/views/settings/securityPrimitives.tsx +14 -9
- package/src/views/settings/useAiSettings.ts +76 -0
package/src/views/Settings.tsx
CHANGED
|
@@ -27,6 +27,7 @@ import { SeoSettingsTab } from './settings/SeoSettingsTab.js'
|
|
|
27
27
|
import { AISettingsTab } from './settings/AISettingsTab.js'
|
|
28
28
|
import { AppearanceTab } from './settings/AppearanceTab.js'
|
|
29
29
|
import { SecurityTab } from './settings/SecurityTab.js'
|
|
30
|
+
import { SettingsCard } from './settings/components.js'
|
|
30
31
|
import { Users as UsersView } from './Users.js'
|
|
31
32
|
import { ApiKeys as ApiKeysView } from './ApiKeys.js'
|
|
32
33
|
|
|
@@ -165,12 +166,15 @@ export function Settings({
|
|
|
165
166
|
return (
|
|
166
167
|
<div className="p-3 pr-6 sm:p-4 sm:pr-8">
|
|
167
168
|
{error && (
|
|
168
|
-
<div
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
<div
|
|
170
|
+
role="alert"
|
|
171
|
+
className="border-destructive/30 bg-destructive/10 text-destructive mb-4 flex items-center gap-3 rounded-lg border p-3 text-sm"
|
|
172
|
+
>
|
|
173
|
+
<AlertTriangle size={20} className="shrink-0" aria-hidden="true" />
|
|
174
|
+
<span className="flex-1">{error}</span>
|
|
171
175
|
<button
|
|
172
176
|
onClick={refetch}
|
|
173
|
-
className="rounded-
|
|
177
|
+
className="border-destructive/40 rounded-md border px-3 py-1 transition-colors hover:opacity-80"
|
|
174
178
|
>
|
|
175
179
|
Retry
|
|
176
180
|
</button>
|
|
@@ -178,12 +182,12 @@ export function Settings({
|
|
|
178
182
|
)}
|
|
179
183
|
|
|
180
184
|
<div className="mb-4">
|
|
181
|
-
<h1 className="mb-1 text-2xl font-
|
|
182
|
-
<p className="text-
|
|
185
|
+
<h1 className="text-foreground mb-1 text-2xl font-medium">Settings</h1>
|
|
186
|
+
<p className="text-muted-foreground text-sm">Manage your CMS configuration</p>
|
|
183
187
|
</div>
|
|
184
188
|
|
|
185
189
|
<Tabs.Root value={activeTab} onValueChange={changeTab}>
|
|
186
|
-
<Tabs.List className="mb-4 flex gap-1 overflow-x-auto border-b
|
|
190
|
+
<Tabs.List className="border-border mb-4 flex gap-1 overflow-x-auto border-b">
|
|
187
191
|
<Tabs.Trigger value="general" className={tabTriggerClass}>
|
|
188
192
|
General
|
|
189
193
|
</Tabs.Trigger>
|
|
@@ -240,12 +244,10 @@ export function Settings({
|
|
|
240
244
|
|
|
241
245
|
{hasLayoutRegions && (
|
|
242
246
|
<Tabs.Content value="layout" className="space-y-4">
|
|
243
|
-
<
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
can override these individually or inherit from parent pages.
|
|
248
|
-
</p>
|
|
247
|
+
<SettingsCard
|
|
248
|
+
title="Default Layout Variants"
|
|
249
|
+
description="Select the default header, footer, and other layout variants used site-wide. Pages can override these individually or inherit from parent pages."
|
|
250
|
+
>
|
|
249
251
|
<div className="space-y-4">
|
|
250
252
|
{layoutRegions.map((region) => (
|
|
251
253
|
<RelationshipField
|
|
@@ -268,14 +270,11 @@ export function Settings({
|
|
|
268
270
|
/>
|
|
269
271
|
))}
|
|
270
272
|
</div>
|
|
271
|
-
</
|
|
272
|
-
<
|
|
273
|
-
<
|
|
274
|
-
How Layout Inheritance Works
|
|
275
|
-
</h3>
|
|
276
|
-
<ul className="space-y-1.5 text-xs text-gray-600">
|
|
273
|
+
</SettingsCard>
|
|
274
|
+
<SettingsCard title="How Layout Inheritance Works">
|
|
275
|
+
<ul className="text-muted-foreground space-y-1.5 text-sm">
|
|
277
276
|
<li className="flex items-start gap-2">
|
|
278
|
-
<span className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full
|
|
277
|
+
<span className="bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium">
|
|
279
278
|
1
|
|
280
279
|
</span>
|
|
281
280
|
<span>
|
|
@@ -284,20 +283,20 @@ export function Settings({
|
|
|
284
283
|
</span>
|
|
285
284
|
</li>
|
|
286
285
|
<li className="flex items-start gap-2">
|
|
287
|
-
<span className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full
|
|
286
|
+
<span className="bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium">
|
|
288
287
|
2
|
|
289
288
|
</span>
|
|
290
289
|
<span>
|
|
291
290
|
Child pages automatically inherit their parent's layout. For example,{' '}
|
|
292
|
-
<code className="
|
|
291
|
+
<code className="bg-muted rounded px-1 font-mono">
|
|
293
292
|
/hampton-roads/thank-you
|
|
294
293
|
</code>{' '}
|
|
295
294
|
inherits from{' '}
|
|
296
|
-
<code className="
|
|
295
|
+
<code className="bg-muted rounded px-1 font-mono">/hampton-roads</code>.
|
|
297
296
|
</span>
|
|
298
297
|
</li>
|
|
299
298
|
<li className="flex items-start gap-2">
|
|
300
|
-
<span className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full
|
|
299
|
+
<span className="bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium">
|
|
301
300
|
3
|
|
302
301
|
</span>
|
|
303
302
|
<span>
|
|
@@ -306,7 +305,7 @@ export function Settings({
|
|
|
306
305
|
</span>
|
|
307
306
|
</li>
|
|
308
307
|
</ul>
|
|
309
|
-
</
|
|
308
|
+
</SettingsCard>
|
|
310
309
|
</Tabs.Content>
|
|
311
310
|
)}
|
|
312
311
|
|
|
@@ -458,52 +457,59 @@ function UpdatesPanel() {
|
|
|
458
457
|
checkForUpdates()
|
|
459
458
|
}, [])
|
|
460
459
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
patch: {
|
|
466
|
-
minor: {
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
label: '
|
|
460
|
+
// Semantic severity tokens so update banners match the rest of the admin in
|
|
461
|
+
// both light and dark mode (no raw palette colors). Concrete keys (not a
|
|
462
|
+
// string-index Record) keep the lookup non-nullable.
|
|
463
|
+
const severityColors = {
|
|
464
|
+
patch: { banner: 'border-brand/30 bg-brand/10', text: 'text-brand', label: 'Patch' },
|
|
465
|
+
minor: { banner: 'border-warning/30 bg-warning/10', text: 'text-warning', label: 'Minor' },
|
|
466
|
+
major: {
|
|
467
|
+
banner: 'border-destructive/30 bg-destructive/10',
|
|
468
|
+
text: 'text-destructive',
|
|
469
|
+
label: 'Major',
|
|
471
470
|
},
|
|
472
|
-
major: { bg: 'bg-red-50', text: 'text-red-700', border: 'border-red-200', label: 'Major' },
|
|
473
471
|
}
|
|
472
|
+
const sev = severityColors[updateInfo?.severity ?? 'patch']
|
|
473
|
+
const ghInputClass =
|
|
474
|
+
'w-full rounded-md border border-border bg-input-background px-3 py-2 text-base text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none'
|
|
474
475
|
|
|
475
476
|
return (
|
|
476
477
|
<>
|
|
477
478
|
{/* Current Version Card */}
|
|
478
|
-
<
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
<p className="mt-1 text-sm text-gray-600">
|
|
483
|
-
Current version:{' '}
|
|
484
|
-
<span className="font-mono font-medium">{updateInfo?.current ?? '...'}</span>
|
|
485
|
-
</p>
|
|
486
|
-
</div>
|
|
479
|
+
<SettingsCard
|
|
480
|
+
title="Actuate CMS"
|
|
481
|
+
description="Keep your CMS up to date with the latest features and security patches."
|
|
482
|
+
actions={
|
|
487
483
|
<button
|
|
488
484
|
type="button"
|
|
489
485
|
onClick={checkForUpdates}
|
|
490
486
|
disabled={checking}
|
|
491
|
-
className="flex items-center gap-2 rounded-
|
|
487
|
+
className="border-border text-foreground hover:bg-accent inline-flex items-center gap-2 rounded-md border px-4 py-2 text-sm font-medium transition-colors disabled:opacity-50"
|
|
492
488
|
>
|
|
493
|
-
<RefreshCw
|
|
494
|
-
{checking ? 'Checking
|
|
489
|
+
<RefreshCw size={16} className={checking ? 'animate-spin' : ''} aria-hidden="true" />
|
|
490
|
+
{checking ? 'Checking…' : 'Check for Updates'}
|
|
495
491
|
</button>
|
|
496
|
-
|
|
497
|
-
|
|
492
|
+
}
|
|
493
|
+
>
|
|
494
|
+
<p className="text-muted-foreground text-sm">
|
|
495
|
+
Current version:{' '}
|
|
496
|
+
<span className="text-foreground font-mono font-medium">
|
|
497
|
+
{updateInfo?.current ?? '…'}
|
|
498
|
+
</span>
|
|
499
|
+
</p>
|
|
500
|
+
</SettingsCard>
|
|
498
501
|
|
|
499
502
|
{/* Error State */}
|
|
500
503
|
{checkError && (
|
|
501
|
-
<div
|
|
502
|
-
|
|
503
|
-
|
|
504
|
+
<div
|
|
505
|
+
role="alert"
|
|
506
|
+
className="border-destructive/30 bg-destructive/10 text-destructive flex items-center gap-3 rounded-lg border p-3 text-sm"
|
|
507
|
+
>
|
|
508
|
+
<AlertTriangle size={20} className="shrink-0" aria-hidden="true" />
|
|
509
|
+
<span className="flex-1">{checkError}</span>
|
|
504
510
|
<button
|
|
505
511
|
onClick={checkForUpdates}
|
|
506
|
-
className="rounded-
|
|
512
|
+
className="border-destructive/40 rounded-md border px-3 py-1 transition-colors hover:opacity-80"
|
|
507
513
|
>
|
|
508
514
|
Retry
|
|
509
515
|
</button>
|
|
@@ -512,11 +518,11 @@ function UpdatesPanel() {
|
|
|
512
518
|
|
|
513
519
|
{/* Up to Date */}
|
|
514
520
|
{hasChecked && updateInfo && !updateInfo.updateAvailable && !checkError && (
|
|
515
|
-
<div className="flex items-center gap-3 rounded-lg border
|
|
516
|
-
<CheckCircle2 className="
|
|
521
|
+
<div className="border-success/30 bg-success/10 text-success flex items-center gap-3 rounded-lg border p-4">
|
|
522
|
+
<CheckCircle2 size={24} className="shrink-0" aria-hidden="true" />
|
|
517
523
|
<div>
|
|
518
|
-
<h3 className="text-
|
|
519
|
-
<p className="mt-0.5 text-sm
|
|
524
|
+
<h3 className="text-foreground font-medium">You're up to date!</h3>
|
|
525
|
+
<p className="text-muted-foreground mt-0.5 text-sm">
|
|
520
526
|
Actuate CMS <span className="font-mono">{updateInfo.current}</span> is the latest
|
|
521
527
|
version.
|
|
522
528
|
</p>
|
|
@@ -527,29 +533,25 @@ function UpdatesPanel() {
|
|
|
527
533
|
{/* Update Available */}
|
|
528
534
|
{updateInfo?.updateAvailable && (
|
|
529
535
|
<>
|
|
530
|
-
<div
|
|
531
|
-
className={`rounded-lg border p-4 ${severityColors[updateInfo.severity ?? 'patch']?.border ?? 'border-blue-200'} ${severityColors[updateInfo.severity ?? 'patch']?.bg ?? 'bg-blue-50'}`}
|
|
532
|
-
>
|
|
536
|
+
<div className={`rounded-lg border p-4 ${sev.banner}`}>
|
|
533
537
|
<div className="flex items-start gap-3">
|
|
534
538
|
<ArrowUpCircle
|
|
535
|
-
|
|
539
|
+
size={24}
|
|
540
|
+
className={`mt-0.5 shrink-0 ${sev.text}`}
|
|
541
|
+
aria-hidden="true"
|
|
536
542
|
/>
|
|
537
543
|
<div className="flex-1">
|
|
538
544
|
<div className="flex items-center gap-2">
|
|
539
|
-
<h3
|
|
540
|
-
className={`text-sm font-semibold ${severityColors[updateInfo.severity ?? 'patch']?.text ?? 'text-blue-700'}`}
|
|
541
|
-
>
|
|
542
|
-
Update Available
|
|
543
|
-
</h3>
|
|
545
|
+
<h3 className={`font-medium ${sev.text}`}>Update Available</h3>
|
|
544
546
|
<span
|
|
545
|
-
className={`inline-flex items-center rounded px-2 py-0.5 text-xs font-medium ${
|
|
547
|
+
className={`inline-flex items-center rounded border px-2 py-0.5 text-xs font-medium ${sev.banner} ${sev.text}`}
|
|
546
548
|
>
|
|
547
|
-
{
|
|
549
|
+
{sev.label}
|
|
548
550
|
</span>
|
|
549
551
|
</div>
|
|
550
|
-
<p className="mt-1 text-sm"
|
|
552
|
+
<p className="text-muted-foreground mt-1 text-sm">
|
|
551
553
|
<span className="font-mono">{updateInfo.current}</span> →{' '}
|
|
552
|
-
<span className="font-mono font-
|
|
554
|
+
<span className="text-foreground font-mono font-medium">{updateInfo.latest}</span>
|
|
553
555
|
{updateInfo.releaseDate && (
|
|
554
556
|
<span className="ml-2 text-xs opacity-70">
|
|
555
557
|
Released {updateInfo.releaseDate}
|
|
@@ -564,27 +566,29 @@ function UpdatesPanel() {
|
|
|
564
566
|
type="button"
|
|
565
567
|
onClick={applyUpdate}
|
|
566
568
|
disabled={applying}
|
|
567
|
-
className="flex items-center gap-2 rounded-
|
|
569
|
+
className="bg-brand text-brand-foreground inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-opacity hover:opacity-90 disabled:opacity-50"
|
|
568
570
|
>
|
|
569
571
|
{applying ? (
|
|
570
572
|
<>
|
|
571
|
-
<Loader2 className="
|
|
572
|
-
Creating PR
|
|
573
|
+
<Loader2 size={16} className="animate-spin" aria-hidden="true" />
|
|
574
|
+
Creating PR…
|
|
573
575
|
</>
|
|
574
576
|
) : (
|
|
575
577
|
<>
|
|
576
|
-
<GitPullRequest
|
|
578
|
+
<GitPullRequest size={16} aria-hidden="true" />
|
|
577
579
|
Create Update PR
|
|
578
580
|
</>
|
|
579
581
|
)}
|
|
580
582
|
</button>
|
|
581
|
-
<span className="text-
|
|
583
|
+
<span className="text-muted-foreground text-xs">
|
|
584
|
+
Opens a pull request on your repository
|
|
585
|
+
</span>
|
|
582
586
|
</div>
|
|
583
587
|
|
|
584
588
|
{updateInfo.updateCommand && (
|
|
585
|
-
<div className="mt-3 rounded border
|
|
586
|
-
<p className="mb-1 text-xs
|
|
587
|
-
<code className="block rounded
|
|
589
|
+
<div className="border-border bg-card mt-3 rounded-md border p-3">
|
|
590
|
+
<p className="text-muted-foreground mb-1 text-xs">Or update manually:</p>
|
|
591
|
+
<code className="bg-muted text-foreground block rounded px-2 py-1.5 font-mono text-xs select-all">
|
|
588
592
|
{updateInfo.updateCommand}
|
|
589
593
|
</code>
|
|
590
594
|
</div>
|
|
@@ -593,35 +597,36 @@ function UpdatesPanel() {
|
|
|
593
597
|
|
|
594
598
|
{/* Changelog */}
|
|
595
599
|
{updateInfo.changelog && updateInfo.changelog.length > 0 && (
|
|
596
|
-
<
|
|
597
|
-
<h3 className="mb-3 text-sm font-semibold text-gray-900">Changelog</h3>
|
|
600
|
+
<SettingsCard title="Changelog">
|
|
598
601
|
<div className="max-h-64 space-y-2 overflow-y-auto">
|
|
599
602
|
{updateInfo.changelog.map((entry) => (
|
|
600
603
|
<div key={entry.version} className="flex items-baseline gap-3 text-sm">
|
|
601
|
-
<span className="w-14 shrink-0 font-mono text-xs
|
|
604
|
+
<span className="text-muted-foreground w-14 shrink-0 font-mono text-xs">
|
|
602
605
|
{entry.version}
|
|
603
606
|
</span>
|
|
604
|
-
<span className="w-20 shrink-0 text-xs
|
|
605
|
-
|
|
607
|
+
<span className="text-muted-foreground w-20 shrink-0 text-xs">
|
|
608
|
+
{entry.date}
|
|
609
|
+
</span>
|
|
610
|
+
<span className="text-foreground">{entry.summary}</span>
|
|
606
611
|
</div>
|
|
607
612
|
))}
|
|
608
613
|
</div>
|
|
609
|
-
</
|
|
614
|
+
</SettingsCard>
|
|
610
615
|
)}
|
|
611
616
|
</>
|
|
612
617
|
)}
|
|
613
618
|
|
|
614
619
|
{/* PR Created */}
|
|
615
620
|
{prResult && (
|
|
616
|
-
<div className="
|
|
621
|
+
<div className="border-success/30 bg-success/10 rounded-lg border p-4">
|
|
617
622
|
<div className="flex items-start gap-3">
|
|
618
|
-
<GitPullRequest className="mt-0.5
|
|
623
|
+
<GitPullRequest size={20} className="text-success mt-0.5 shrink-0" aria-hidden="true" />
|
|
619
624
|
<div>
|
|
620
|
-
<h3 className="text-
|
|
621
|
-
<p className="mt-1 text-sm
|
|
625
|
+
<h3 className="text-foreground font-medium">Pull Request Created</h3>
|
|
626
|
+
<p className="text-muted-foreground mt-1 text-sm">
|
|
622
627
|
PR #{prResult.prNumber} has been created on your repository. Review and merge it to
|
|
623
628
|
apply the update, then run{' '}
|
|
624
|
-
<code className="
|
|
629
|
+
<code className="bg-muted rounded px-1 font-mono text-xs">
|
|
625
630
|
npx prisma migrate deploy
|
|
626
631
|
</code>
|
|
627
632
|
.
|
|
@@ -630,9 +635,9 @@ function UpdatesPanel() {
|
|
|
630
635
|
href={prResult.prUrl}
|
|
631
636
|
target="_blank"
|
|
632
637
|
rel="noopener noreferrer"
|
|
633
|
-
className="mt-2 inline-flex items-center gap-1.5 text-sm font-medium
|
|
638
|
+
className="text-brand mt-2 inline-flex items-center gap-1.5 text-sm font-medium hover:underline"
|
|
634
639
|
>
|
|
635
|
-
<ExternalLink
|
|
640
|
+
<ExternalLink size={16} aria-hidden="true" />
|
|
636
641
|
View Pull Request
|
|
637
642
|
</a>
|
|
638
643
|
</div>
|
|
@@ -641,65 +646,72 @@ function UpdatesPanel() {
|
|
|
641
646
|
)}
|
|
642
647
|
|
|
643
648
|
{/* GitHub Configuration */}
|
|
644
|
-
<
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
(AES-256-GCM).
|
|
649
|
-
</p>
|
|
650
|
-
|
|
649
|
+
<SettingsCard
|
|
650
|
+
title="GitHub Integration"
|
|
651
|
+
description="Connect your repository to enable one-click update PRs. Credentials are encrypted at rest (AES-256-GCM)."
|
|
652
|
+
>
|
|
651
653
|
<div className="space-y-4">
|
|
652
654
|
<div>
|
|
653
|
-
<label
|
|
655
|
+
<label
|
|
656
|
+
htmlFor="updates-gh-repo"
|
|
657
|
+
className="text-foreground mb-1 block text-sm font-medium"
|
|
658
|
+
>
|
|
659
|
+
Repository
|
|
660
|
+
</label>
|
|
654
661
|
<input
|
|
662
|
+
id="updates-gh-repo"
|
|
655
663
|
type="text"
|
|
656
664
|
value={ghRepo}
|
|
657
665
|
onChange={(e) => setGhRepo(e.target.value)}
|
|
658
666
|
placeholder="owner/repo"
|
|
659
|
-
className=
|
|
667
|
+
className={ghInputClass}
|
|
660
668
|
/>
|
|
661
|
-
<p className="mt-1 text-
|
|
669
|
+
<p className="text-muted-foreground mt-1 text-sm">
|
|
662
670
|
e.g.{' '}
|
|
663
|
-
<code className="
|
|
664
|
-
actuate-media/my-client-site
|
|
665
|
-
</code>
|
|
671
|
+
<code className="bg-muted rounded px-1 font-mono">actuate-media/my-client-site</code>
|
|
666
672
|
</p>
|
|
667
673
|
</div>
|
|
668
674
|
<div>
|
|
669
|
-
<label
|
|
675
|
+
<label
|
|
676
|
+
htmlFor="updates-gh-token"
|
|
677
|
+
className="text-foreground mb-1 block text-sm font-medium"
|
|
678
|
+
>
|
|
670
679
|
GitHub Token
|
|
671
680
|
{updateInfo?.hasGithubToken && !ghToken && (
|
|
672
|
-
<span className="ml-2 text-xs font-normal
|
|
681
|
+
<span className="text-success ml-2 text-xs font-normal">Saved</span>
|
|
673
682
|
)}
|
|
674
683
|
</label>
|
|
675
|
-
<div className="
|
|
676
|
-
<
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
684
|
+
<div className="relative">
|
|
685
|
+
<input
|
|
686
|
+
id="updates-gh-token"
|
|
687
|
+
type={showGhToken ? 'text' : 'password'}
|
|
688
|
+
value={ghToken}
|
|
689
|
+
onChange={(e) => setGhToken(e.target.value)}
|
|
690
|
+
placeholder={
|
|
691
|
+
updateInfo?.hasGithubToken ? '••••••••••••••••' : 'ghp_... or github_pat_...'
|
|
692
|
+
}
|
|
693
|
+
className={`${ghInputClass} pr-10`}
|
|
694
|
+
/>
|
|
695
|
+
<button
|
|
696
|
+
type="button"
|
|
697
|
+
onClick={() => setShowGhToken(!showGhToken)}
|
|
698
|
+
aria-label={showGhToken ? 'Hide token' : 'Show token'}
|
|
699
|
+
className="text-muted-foreground hover:text-foreground absolute top-1/2 right-2 -translate-y-1/2 p-1"
|
|
700
|
+
>
|
|
701
|
+
{showGhToken ? (
|
|
702
|
+
<EyeOff size={16} aria-hidden="true" />
|
|
703
|
+
) : (
|
|
704
|
+
<Eye size={16} aria-hidden="true" />
|
|
705
|
+
)}
|
|
706
|
+
</button>
|
|
694
707
|
</div>
|
|
695
|
-
<p className="mt-1 text-
|
|
696
|
-
Needs <code className="
|
|
697
|
-
at{' '}
|
|
708
|
+
<p className="text-muted-foreground mt-1 text-sm">
|
|
709
|
+
Needs <code className="bg-muted rounded px-1 font-mono">repo</code> scope. Create at{' '}
|
|
698
710
|
<a
|
|
699
711
|
href="https://github.com/settings/tokens"
|
|
700
712
|
target="_blank"
|
|
701
713
|
rel="noopener noreferrer"
|
|
702
|
-
className="text-
|
|
714
|
+
className="text-brand hover:underline"
|
|
703
715
|
>
|
|
704
716
|
github.com/settings/tokens
|
|
705
717
|
</a>
|
|
@@ -710,26 +722,25 @@ function UpdatesPanel() {
|
|
|
710
722
|
type="button"
|
|
711
723
|
onClick={saveGitHubConfig}
|
|
712
724
|
disabled={savingConfig || (!ghToken && !ghRepo)}
|
|
713
|
-
className="flex items-center gap-2 rounded-
|
|
725
|
+
className="bg-brand text-brand-foreground inline-flex items-center gap-2 rounded-md px-4 py-2 text-sm font-medium transition-opacity hover:opacity-90 disabled:opacity-50"
|
|
714
726
|
>
|
|
715
727
|
{savingConfig ? (
|
|
716
728
|
<>
|
|
717
|
-
<Loader2 className="
|
|
718
|
-
Encrypting & Saving
|
|
729
|
+
<Loader2 size={16} className="animate-spin" aria-hidden="true" />
|
|
730
|
+
Encrypting & Saving…
|
|
719
731
|
</>
|
|
720
732
|
) : (
|
|
721
733
|
'Save Configuration'
|
|
722
734
|
)}
|
|
723
735
|
</button>
|
|
724
736
|
</div>
|
|
725
|
-
</
|
|
737
|
+
</SettingsCard>
|
|
726
738
|
|
|
727
739
|
{/* Help Text */}
|
|
728
|
-
<
|
|
729
|
-
<
|
|
730
|
-
<ul className="space-y-1.5 text-xs text-gray-600">
|
|
740
|
+
<SettingsCard title="How Updates Work">
|
|
741
|
+
<ul className="text-muted-foreground space-y-1.5 text-sm">
|
|
731
742
|
<li className="flex items-start gap-2">
|
|
732
|
-
<span className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full
|
|
743
|
+
<span className="bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium">
|
|
733
744
|
1
|
|
734
745
|
</span>
|
|
735
746
|
<span>
|
|
@@ -737,7 +748,7 @@ function UpdatesPanel() {
|
|
|
737
748
|
</span>
|
|
738
749
|
</li>
|
|
739
750
|
<li className="flex items-start gap-2">
|
|
740
|
-
<span className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full
|
|
751
|
+
<span className="bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium">
|
|
741
752
|
2
|
|
742
753
|
</span>
|
|
743
754
|
<span>
|
|
@@ -746,7 +757,7 @@ function UpdatesPanel() {
|
|
|
746
757
|
</span>
|
|
747
758
|
</li>
|
|
748
759
|
<li className="flex items-start gap-2">
|
|
749
|
-
<span className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full
|
|
760
|
+
<span className="bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium">
|
|
750
761
|
3
|
|
751
762
|
</span>
|
|
752
763
|
<span>
|
|
@@ -755,16 +766,16 @@ function UpdatesPanel() {
|
|
|
755
766
|
</span>
|
|
756
767
|
</li>
|
|
757
768
|
<li className="flex items-start gap-2">
|
|
758
|
-
<span className="mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full
|
|
769
|
+
<span className="bg-brand/10 text-brand mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center rounded-full text-[10px] font-medium">
|
|
759
770
|
4
|
|
760
771
|
</span>
|
|
761
772
|
<span>
|
|
762
773
|
Review and merge the PR, then deploy. Database migrations run automatically via{' '}
|
|
763
|
-
<code className="
|
|
774
|
+
<code className="bg-muted rounded px-1 font-mono">prisma migrate deploy</code>.
|
|
764
775
|
</span>
|
|
765
776
|
</li>
|
|
766
777
|
</ul>
|
|
767
|
-
</
|
|
778
|
+
</SettingsCard>
|
|
768
779
|
</>
|
|
769
780
|
)
|
|
770
781
|
}
|
package/src/views/Users.tsx
CHANGED
|
@@ -923,7 +923,7 @@ export function Users({ embedded = false }: UsersProps = {}) {
|
|
|
923
923
|
{/* Header */}
|
|
924
924
|
<div className="border-border flex flex-col gap-3 border-b p-4 lg:flex-row lg:items-center lg:justify-between">
|
|
925
925
|
<div>
|
|
926
|
-
<h2 className="text-card-foreground text-
|
|
926
|
+
<h2 className="text-card-foreground text-lg font-medium">Team members</h2>
|
|
927
927
|
<p className="text-muted-foreground text-sm">
|
|
928
928
|
{peopleCount} {peopleCount === 1 ? 'person has' : 'people have'} access to this
|
|
929
929
|
workspace
|