jettypod 4.4.118 → 4.4.121
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/.env +4 -3
- package/Cargo.lock +6450 -0
- package/Cargo.toml +35 -0
- package/README.md +5 -1
- package/TAURI-MIGRATION-PLAN.md +840 -0
- package/apps/dashboard/app/connect-claude/page.tsx +5 -6
- package/apps/dashboard/app/decision/[id]/page.tsx +63 -58
- package/apps/dashboard/app/demo/gates/page.tsx +43 -45
- package/apps/dashboard/app/design-system/page.tsx +868 -0
- package/apps/dashboard/app/globals.css +80 -4
- package/apps/dashboard/app/install-claude/page.tsx +4 -6
- package/apps/dashboard/app/login/page.tsx +72 -54
- package/apps/dashboard/app/page.tsx +101 -48
- package/apps/dashboard/app/settings/page.tsx +61 -13
- package/apps/dashboard/app/signup/page.tsx +242 -0
- package/apps/dashboard/app/subscribe/page.tsx +0 -2
- package/apps/dashboard/app/tests/page.tsx +37 -4
- package/apps/dashboard/app/welcome/page.tsx +13 -16
- package/apps/dashboard/app/work/[id]/page.tsx +117 -118
- package/apps/dashboard/app/work/[id]/proof/page.tsx +1489 -0
- package/apps/dashboard/components/AppShell.tsx +92 -85
- package/apps/dashboard/components/CardMenu.tsx +45 -12
- package/apps/dashboard/components/ClaudePanel.tsx +771 -850
- package/apps/dashboard/components/ClaudePanelInput.tsx +43 -15
- package/apps/dashboard/components/ConnectClaudeScreen.tsx +17 -34
- package/apps/dashboard/components/CopyableId.tsx +3 -4
- package/apps/dashboard/components/DetailReviewActions.tsx +100 -0
- package/apps/dashboard/components/DragContext.tsx +134 -63
- package/apps/dashboard/components/DraggableCard.tsx +3 -5
- package/apps/dashboard/components/DropZone.tsx +6 -7
- package/apps/dashboard/components/EditableDetailDescription.tsx +7 -13
- package/apps/dashboard/components/EditableDetailTitle.tsx +6 -13
- package/apps/dashboard/components/EditableTitle.tsx +26 -7
- package/apps/dashboard/components/ElapsedTimer.tsx +66 -0
- package/apps/dashboard/components/EpicGroup.tsx +359 -0
- package/apps/dashboard/components/GateCard.tsx +79 -17
- package/apps/dashboard/components/GateChoiceCard.tsx +15 -18
- package/apps/dashboard/components/InstallClaudeScreen.tsx +15 -32
- package/apps/dashboard/components/JettyLoader.tsx +37 -0
- package/apps/dashboard/components/KanbanBoard.tsx +368 -958
- package/apps/dashboard/components/KanbanCard.tsx +740 -0
- package/apps/dashboard/components/LazyCard.tsx +62 -0
- package/apps/dashboard/components/LazyMarkdown.tsx +11 -0
- package/apps/dashboard/components/MainNav.tsx +38 -73
- package/apps/dashboard/components/MessageBlock.tsx +468 -0
- package/apps/dashboard/components/ModeStartCard.tsx +15 -16
- package/apps/dashboard/components/OnboardingWelcome.tsx +213 -0
- package/apps/dashboard/components/PlaceholderCard.tsx +3 -4
- package/apps/dashboard/components/ProjectSwitcher.tsx +30 -30
- package/apps/dashboard/components/PrototypeTimeline.tsx +72 -51
- package/apps/dashboard/components/RealTimeKanbanWrapper.tsx +406 -388
- package/apps/dashboard/components/RealTimeTestsWrapper.tsx +373 -235
- package/apps/dashboard/components/ReviewFooter.tsx +139 -0
- package/apps/dashboard/components/SessionList.tsx +19 -19
- package/apps/dashboard/components/SubscribeContent.tsx +91 -47
- package/apps/dashboard/components/TestTree.tsx +16 -16
- package/apps/dashboard/components/TipCard.tsx +16 -17
- package/apps/dashboard/components/Toast.tsx +5 -6
- package/apps/dashboard/components/TypeIcon.tsx +55 -0
- package/apps/dashboard/components/ViewModeToolbar.tsx +104 -0
- package/apps/dashboard/components/WaveCompletionAnimation.tsx +52 -65
- package/apps/dashboard/components/WelcomeScreen.tsx +19 -35
- package/apps/dashboard/components/WorkItemHeader.tsx +4 -5
- package/apps/dashboard/components/WorkItemTree.tsx +11 -32
- package/apps/dashboard/components/settings/AccountSection.tsx +55 -35
- package/apps/dashboard/components/settings/AiContextSection.tsx +89 -0
- package/apps/dashboard/components/settings/ContextDocumentsSection.tsx +317 -0
- package/apps/dashboard/components/settings/EnvVarsSection.tsx +74 -152
- package/apps/dashboard/components/settings/GeneralSection.tsx +162 -56
- package/apps/dashboard/components/settings/ProjectStackSection.tsx +948 -0
- package/apps/dashboard/components/settings/SettingsLayout.tsx +4 -5
- package/apps/dashboard/components/ui/Button.tsx +104 -0
- package/apps/dashboard/components/ui/Input.tsx +78 -0
- package/apps/dashboard/components.json +1 -1
- package/apps/dashboard/contexts/ClaudeSessionContext.tsx +711 -418
- package/apps/dashboard/contexts/ConnectionStatusContext.tsx +25 -5
- package/apps/dashboard/contexts/UsageContext.tsx +87 -32
- package/apps/dashboard/dev.sh +35 -0
- package/apps/dashboard/eslint.config.mjs +9 -9
- package/apps/dashboard/hooks/useKanbanAnimation.ts +29 -0
- package/apps/dashboard/hooks/useKanbanUndo.ts +83 -0
- package/apps/dashboard/hooks/useWebSocket.ts +138 -83
- package/apps/dashboard/index.html +73 -0
- package/apps/dashboard/lib/constants.ts +43 -0
- package/apps/dashboard/lib/data-bridge.ts +722 -0
- package/apps/dashboard/lib/db.ts +69 -1265
- package/apps/dashboard/lib/environment-config.ts +173 -0
- package/apps/dashboard/lib/environment-verification.ts +119 -0
- package/apps/dashboard/lib/kanban-utils.ts +270 -0
- package/apps/dashboard/lib/proof-run.ts +495 -0
- package/apps/dashboard/lib/proof-scenario-runner.ts +346 -0
- package/apps/dashboard/lib/run-migrations.js +27 -2
- package/apps/dashboard/lib/service-recovery.ts +326 -0
- package/apps/dashboard/lib/session-state-machine.ts +1 -0
- package/apps/dashboard/lib/session-state-utils.ts +0 -164
- package/apps/dashboard/lib/session-stream-manager.ts +308 -134
- package/apps/dashboard/lib/shadows.ts +7 -0
- package/apps/dashboard/lib/stream-manager-registry.ts +46 -6
- package/apps/dashboard/lib/tauri-bridge.ts +102 -0
- package/apps/dashboard/lib/tauri.ts +106 -0
- package/apps/dashboard/lib/utils.ts +6 -0
- package/apps/dashboard/next-env.d.ts +1 -1
- package/apps/dashboard/package.json +21 -32
- package/apps/dashboard/public/bug-icon.png +0 -0
- package/apps/dashboard/public/buoy-icon.png +0 -0
- package/apps/dashboard/public/fonts/Satoshi-Variable.woff2 +0 -0
- package/apps/dashboard/public/fonts/Satoshi-VariableItalic.woff2 +0 -0
- package/apps/dashboard/public/in-flight-seagull.png +0 -0
- package/apps/dashboard/public/jetty-icon-loading-alt.svg +11 -0
- package/apps/dashboard/public/jetty-icon-loading.svg +11 -0
- package/apps/dashboard/public/jettypod_logo.png +0 -0
- package/apps/dashboard/public/pier-icon.png +0 -0
- package/apps/dashboard/public/star-icon.png +0 -0
- package/apps/dashboard/public/wrench-icon.png +0 -0
- package/apps/dashboard/scripts/tauri-build.js +228 -0
- package/apps/dashboard/scripts/upload-tauri-to-r2.js +125 -0
- package/apps/dashboard/scripts/ws-server.js +191 -0
- package/apps/dashboard/src/main.tsx +12 -0
- package/apps/dashboard/src/router.tsx +107 -0
- package/apps/dashboard/src/vite-env.d.ts +1 -0
- package/apps/dashboard/tsconfig.json +7 -12
- package/apps/dashboard/tsconfig.tsbuildinfo +1 -1
- package/apps/dashboard/vite.config.ts +33 -0
- package/apps/update-server/src/index.ts +228 -80
- package/claude-hooks/global-guardrails.js +14 -13
- package/crates/jettypod-cli/Cargo.toml +19 -0
- package/crates/jettypod-cli/src/commands.rs +1249 -0
- package/crates/jettypod-cli/src/main.rs +595 -0
- package/crates/jettypod-core/Cargo.toml +26 -0
- package/crates/jettypod-core/build.rs +98 -0
- package/crates/jettypod-core/migrations/V1__baseline.sql +197 -0
- package/crates/jettypod-core/migrations/V2__work_items_indexes.sql +6 -0
- package/crates/jettypod-core/migrations/V3__qa_steps.sql +2 -0
- package/crates/jettypod-core/src/auth.rs +294 -0
- package/crates/jettypod-core/src/config.rs +397 -0
- package/crates/jettypod-core/src/db/mod.rs +507 -0
- package/crates/jettypod-core/src/db/recovery.rs +114 -0
- package/crates/jettypod-core/src/db/startup.rs +101 -0
- package/crates/jettypod-core/src/db/validate.rs +149 -0
- package/crates/jettypod-core/src/error.rs +76 -0
- package/crates/jettypod-core/src/git.rs +458 -0
- package/crates/jettypod-core/src/lib.rs +20 -0
- package/crates/jettypod-core/src/sessions.rs +625 -0
- package/crates/jettypod-core/src/skills.rs +556 -0
- package/crates/jettypod-core/src/work.rs +1086 -0
- package/crates/jettypod-core/src/worktree.rs +628 -0
- package/crates/jettypod-core/src/ws.rs +767 -0
- package/cucumber-test.cjs +6 -0
- package/cucumber.js +9 -3
- package/docs/COMMAND_REFERENCE.md +34 -0
- package/hooks/post-checkout +32 -75
- package/hooks/post-merge +111 -10
- package/jest.setup.js +1 -0
- package/jettypod.js +145 -116
- package/lib/bdd-preflight.js +96 -0
- package/lib/chore-taxonomy.js +33 -10
- package/lib/database.js +36 -16
- package/lib/db-watcher.js +1 -1
- package/lib/git-hooks/pre-commit +1 -1
- package/lib/jettypod-backup.js +27 -4
- package/lib/merge-lock.js +111 -253
- package/lib/migrations/027-plan-at-creation-column.js +3 -1
- package/lib/migrations/029-remove-autoincrement.js +307 -0
- package/lib/migrations/029-rename-corrupted-to-cleaned.js +149 -0
- package/lib/migrations/030-rejection-round-columns.js +54 -0
- package/lib/migrations/031-session-isolation-index.js +17 -0
- package/lib/migrations/index.js +47 -4
- package/lib/schema.js +10 -5
- package/lib/seed-onboarding.js +1 -1
- package/lib/update-command/index.js +9 -175
- package/lib/work-commands/index.js +144 -19
- package/lib/work-tracking/index.js +148 -27
- package/lib/worktree-diagnostics.js +16 -16
- package/lib/worktree-facade.js +1 -1
- package/lib/worktree-manager.js +8 -8
- package/lib/worktree-reconciler.js +5 -5
- package/package.json +9 -2
- package/scripts/ndjson-to-cucumber-json.js +152 -0
- package/scripts/postinstall.js +25 -0
- package/skills-templates/bug-mode/SKILL.md +79 -20
- package/skills-templates/bug-planning/SKILL.md +25 -29
- package/skills-templates/chore-mode/SKILL.md +171 -69
- package/skills-templates/chore-mode/verification.js +51 -10
- package/skills-templates/chore-planning/SKILL.md +47 -18
- package/skills-templates/design-system-selection/SKILL.md +273 -0
- package/skills-templates/epic-planning/SKILL.md +82 -48
- package/skills-templates/external-transition/SKILL.md +47 -47
- package/skills-templates/feature-planning/SKILL.md +173 -74
- package/skills-templates/production-mode/SKILL.md +69 -49
- package/skills-templates/request-routing/SKILL.md +4 -4
- package/skills-templates/simple-improvement/SKILL.md +74 -29
- package/skills-templates/speed-mode/SKILL.md +217 -141
- package/skills-templates/stable-mode/SKILL.md +148 -89
- package/apps/dashboard/README.md +0 -36
- package/apps/dashboard/app/api/claude/[workItemId]/message/route.ts +0 -386
- package/apps/dashboard/app/api/claude/[workItemId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/[workItemId]/route.ts +0 -167
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/content/route.ts +0 -52
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/message/route.ts +0 -378
- package/apps/dashboard/app/api/claude/sessions/[sessionId]/pin/route.ts +0 -24
- package/apps/dashboard/app/api/claude/sessions/cleanup/route.ts +0 -34
- package/apps/dashboard/app/api/claude/sessions/route.ts +0 -184
- package/apps/dashboard/app/api/decisions/[id]/route.ts +0 -25
- package/apps/dashboard/app/api/internal/set-project/route.ts +0 -17
- package/apps/dashboard/app/api/kanban/route.ts +0 -15
- package/apps/dashboard/app/api/settings/env-vars/route.ts +0 -125
- package/apps/dashboard/app/api/settings/general/route.ts +0 -21
- package/apps/dashboard/app/api/tests/route.ts +0 -9
- package/apps/dashboard/app/api/tests/run/route.ts +0 -82
- package/apps/dashboard/app/api/tests/run/stream/route.ts +0 -71
- package/apps/dashboard/app/api/tests/undefined/route.ts +0 -9
- package/apps/dashboard/app/api/usage/route.ts +0 -17
- package/apps/dashboard/app/api/work/[id]/description/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/epic/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/order/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/status/route.ts +0 -21
- package/apps/dashboard/app/api/work/[id]/title/route.ts +0 -21
- package/apps/dashboard/app/layout.tsx +0 -43
- package/apps/dashboard/components/UpgradeBanner.tsx +0 -29
- package/apps/dashboard/electron/ipc-handlers.js +0 -1028
- package/apps/dashboard/electron/main.js +0 -2124
- package/apps/dashboard/electron/preload.js +0 -123
- package/apps/dashboard/electron/session-manager.js +0 -141
- package/apps/dashboard/electron-builder.config.js +0 -357
- package/apps/dashboard/hooks/useClaudeSessions.ts +0 -299
- package/apps/dashboard/lib/claude-process-manager.ts +0 -492
- package/apps/dashboard/lib/db-bridge.ts +0 -282
- package/apps/dashboard/lib/prototypes.ts +0 -202
- package/apps/dashboard/lib/test-results-db.ts +0 -307
- package/apps/dashboard/lib/tests.ts +0 -282
- package/apps/dashboard/next.config.js +0 -50
- package/apps/dashboard/postcss.config.mjs +0 -7
- package/apps/dashboard/public/file.svg +0 -1
- package/apps/dashboard/public/globe.svg +0 -1
- package/apps/dashboard/public/next.svg +0 -1
- package/apps/dashboard/public/vercel.svg +0 -1
- package/apps/dashboard/public/window.svg +0 -1
- package/apps/dashboard/scripts/download-node.js +0 -104
- package/apps/dashboard/scripts/upload-to-r2.js +0 -89
- package/docs/bdd-guidance.md +0 -390
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
'use client';
|
|
2
1
|
|
|
3
2
|
import { useState } from 'react';
|
|
3
|
+
import { invoke } from '@/lib/tauri';
|
|
4
|
+
import { Input } from '@/components/ui/Input';
|
|
5
|
+
import { Button } from '@/components/ui/Button';
|
|
6
|
+
import { dataBridge } from '@/lib/data-bridge';
|
|
4
7
|
|
|
5
8
|
interface EnvVar {
|
|
6
9
|
name: string;
|
|
@@ -41,22 +44,8 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
41
44
|
setCurrentFile(filename);
|
|
42
45
|
setErrorMessage(null);
|
|
43
46
|
try {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
method: 'POST',
|
|
47
|
-
headers: { 'Content-Type': 'application/json' },
|
|
48
|
-
body: JSON.stringify({ action: 'select', file: filename }),
|
|
49
|
-
});
|
|
50
|
-
// Load vars from selected file
|
|
51
|
-
const res = await fetch(`/api/settings/env-vars?file=${encodeURIComponent(filename)}`);
|
|
52
|
-
if (!res.ok) {
|
|
53
|
-
const data = await res.json();
|
|
54
|
-
setErrorMessage(data.error || 'Failed to load environment variables');
|
|
55
|
-
setEnvVars([]);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const vars = await res.json();
|
|
59
|
-
setEnvVars(vars);
|
|
47
|
+
const vars = await dataBridge.getEnvVars(filename);
|
|
48
|
+
setEnvVars(vars.map(v => ({ name: v.key, value: v.value })));
|
|
60
49
|
} catch {
|
|
61
50
|
setErrorMessage('Failed to load environment variables');
|
|
62
51
|
setEnvVars([]);
|
|
@@ -65,22 +54,16 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
65
54
|
|
|
66
55
|
const refreshFiles = async () => {
|
|
67
56
|
try {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if (varsRes.ok) {
|
|
79
|
-
setEnvVars(await varsRes.json());
|
|
80
|
-
}
|
|
81
|
-
} else {
|
|
82
|
-
setEnvVars([]);
|
|
83
|
-
}
|
|
57
|
+
const files = await dataBridge.discoverEnvFiles();
|
|
58
|
+
setEnvFiles(files);
|
|
59
|
+
if (currentFile && !files.includes(currentFile)) {
|
|
60
|
+
const fallback = files[0] || null;
|
|
61
|
+
setCurrentFile(fallback);
|
|
62
|
+
if (fallback) {
|
|
63
|
+
const vars = await dataBridge.getEnvVars(fallback);
|
|
64
|
+
setEnvVars(vars.map(v => ({ name: v.key, value: v.value })));
|
|
65
|
+
} else {
|
|
66
|
+
setEnvVars([]);
|
|
84
67
|
}
|
|
85
68
|
}
|
|
86
69
|
} catch {
|
|
@@ -91,16 +74,9 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
91
74
|
const handleCreateEnvFile = async () => {
|
|
92
75
|
setErrorMessage(null);
|
|
93
76
|
try {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
body: JSON.stringify({ action: 'create', file: '.env' }),
|
|
98
|
-
});
|
|
99
|
-
if (!res.ok) {
|
|
100
|
-
setErrorMessage('Failed to create .env file');
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
setEnvFiles(['.env']);
|
|
77
|
+
await invoke('db_create_env_file', { filename: '.env' });
|
|
78
|
+
const files = await dataBridge.discoverEnvFiles();
|
|
79
|
+
setEnvFiles(files);
|
|
104
80
|
setCurrentFile('.env');
|
|
105
81
|
setEnvVars([]);
|
|
106
82
|
showSuccess('.env file created');
|
|
@@ -126,16 +102,7 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
126
102
|
|
|
127
103
|
setErrorMessage(null);
|
|
128
104
|
try {
|
|
129
|
-
|
|
130
|
-
method: 'POST',
|
|
131
|
-
headers: { 'Content-Type': 'application/json' },
|
|
132
|
-
body: JSON.stringify({ action: 'add', name: formName, value: formValue, file: currentFile }),
|
|
133
|
-
});
|
|
134
|
-
if (!res.ok) {
|
|
135
|
-
const data = await res.json();
|
|
136
|
-
setErrorMessage(data.error || 'Failed to add variable');
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
105
|
+
await invoke('db_create_env_var', { file: currentFile, key: formName, value: formValue });
|
|
139
106
|
setEnvVars([...envVars, { name: formName, value: formValue }]);
|
|
140
107
|
setFormName('');
|
|
141
108
|
setFormValue('');
|
|
@@ -150,16 +117,7 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
150
117
|
if (!editingName) return;
|
|
151
118
|
setErrorMessage(null);
|
|
152
119
|
try {
|
|
153
|
-
|
|
154
|
-
method: 'POST',
|
|
155
|
-
headers: { 'Content-Type': 'application/json' },
|
|
156
|
-
body: JSON.stringify({ name: editingName, value: formValue, file: currentFile }),
|
|
157
|
-
});
|
|
158
|
-
if (!res.ok) {
|
|
159
|
-
const data = await res.json();
|
|
160
|
-
setErrorMessage(data.error || 'Failed to update variable');
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
120
|
+
await invoke('db_update_env_var', { file: currentFile, key: editingName, value: formValue });
|
|
163
121
|
setEnvVars(envVars.map(v => v.name === editingName ? { ...v, value: formValue } : v));
|
|
164
122
|
setFormValue('');
|
|
165
123
|
setEditingName(null);
|
|
@@ -173,16 +131,7 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
173
131
|
if (!deletingName) return;
|
|
174
132
|
setErrorMessage(null);
|
|
175
133
|
try {
|
|
176
|
-
|
|
177
|
-
method: 'DELETE',
|
|
178
|
-
headers: { 'Content-Type': 'application/json' },
|
|
179
|
-
body: JSON.stringify({ name: deletingName, file: currentFile }),
|
|
180
|
-
});
|
|
181
|
-
if (!res.ok) {
|
|
182
|
-
const data = await res.json();
|
|
183
|
-
setErrorMessage(data.error || 'Failed to delete variable');
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
134
|
+
await invoke('db_delete_env_var', { file: currentFile, key: deletingName });
|
|
186
135
|
setEnvVars(envVars.filter(v => v.name !== deletingName));
|
|
187
136
|
setDeletingName(null);
|
|
188
137
|
showSuccess('Variable deleted successfully');
|
|
@@ -200,21 +149,18 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
200
149
|
if (!hasFiles) {
|
|
201
150
|
return (
|
|
202
151
|
<section id="env-vars">
|
|
203
|
-
<div className="flex items-center justify-between mb-
|
|
152
|
+
<div className="flex items-center justify-between mb-6">
|
|
204
153
|
<h2 className="text-lg font-medium text-zinc-900 dark:text-zinc-100">
|
|
205
154
|
Environment Variables
|
|
206
155
|
</h2>
|
|
207
156
|
</div>
|
|
208
157
|
<div className="text-center py-8">
|
|
209
|
-
<p className="text-
|
|
158
|
+
<p className="text-base text-zinc-500 dark:text-zinc-400 mb-6">
|
|
210
159
|
No .env files found
|
|
211
160
|
</p>
|
|
212
|
-
<
|
|
213
|
-
onClick={handleCreateEnvFile}
|
|
214
|
-
className="px-4 py-2 text-sm font-medium bg-blue-600 hover:bg-blue-500 text-white rounded transition-colors"
|
|
215
|
-
>
|
|
161
|
+
<Button onClick={handleCreateEnvFile} size="sm">
|
|
216
162
|
Create .env file
|
|
217
|
-
</
|
|
163
|
+
</Button>
|
|
218
164
|
</div>
|
|
219
165
|
</section>
|
|
220
166
|
);
|
|
@@ -222,28 +168,28 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
222
168
|
|
|
223
169
|
return (
|
|
224
170
|
<section id="env-vars">
|
|
225
|
-
<div className="flex items-center justify-between mb-
|
|
171
|
+
<div className="flex items-center justify-between mb-6">
|
|
226
172
|
<h2 className="text-lg font-medium text-zinc-900 dark:text-zinc-100">
|
|
227
173
|
Environment Variables
|
|
228
174
|
</h2>
|
|
229
|
-
<
|
|
175
|
+
<Button
|
|
230
176
|
onClick={() => { setIsAdding(true); setFormName(''); setFormValue(''); setErrorMessage(null); }}
|
|
231
|
-
|
|
177
|
+
size="sm"
|
|
232
178
|
>
|
|
233
179
|
Add Variable
|
|
234
|
-
</
|
|
180
|
+
</Button>
|
|
235
181
|
</div>
|
|
236
182
|
|
|
237
183
|
{/* File Selector */}
|
|
238
184
|
{envFiles.length > 0 && (
|
|
239
|
-
<div className="mb-
|
|
240
|
-
<label className="block text-
|
|
185
|
+
<div className="mb-6">
|
|
186
|
+
<label className="block text-base font-medium text-zinc-700 dark:text-zinc-300 mb-1.5">
|
|
241
187
|
File
|
|
242
188
|
</label>
|
|
243
189
|
<select
|
|
244
190
|
value={currentFile || ''}
|
|
245
191
|
onChange={(e) => handleFileChange(e.target.value)}
|
|
246
|
-
className="w-full px-
|
|
192
|
+
className="w-full px-4 py-3 border-2 border-zinc-300 dark:border-zinc-600 rounded-lg bg-white dark:bg-zinc-800 text-zinc-900 dark:text-zinc-100 text-base"
|
|
247
193
|
>
|
|
248
194
|
{envFiles.map((file) => (
|
|
249
195
|
<option key={file} value={file}>
|
|
@@ -255,58 +201,52 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
255
201
|
)}
|
|
256
202
|
|
|
257
203
|
{successMessage && (
|
|
258
|
-
<div className="mb-
|
|
204
|
+
<div className="mb-6 px-6 py-3 bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-300 rounded-lg text-base">
|
|
259
205
|
{successMessage}
|
|
260
206
|
</div>
|
|
261
207
|
)}
|
|
262
208
|
|
|
263
209
|
{errorMessage && (
|
|
264
|
-
<div className="mb-
|
|
210
|
+
<div className="mb-6 px-6 py-3 bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-300 rounded-lg text-base">
|
|
265
211
|
{errorMessage}
|
|
266
212
|
</div>
|
|
267
213
|
)}
|
|
268
214
|
|
|
269
215
|
{/* Add Form */}
|
|
270
216
|
{isAdding && (
|
|
271
|
-
<div className="mb-
|
|
272
|
-
<div className="space-y-
|
|
217
|
+
<div className="mb-6 p-6 bg-zinc-50 dark:bg-zinc-800/50 rounded-lg">
|
|
218
|
+
<div className="space-y-4">
|
|
273
219
|
<div>
|
|
274
|
-
<label className="block text-
|
|
220
|
+
<label className="block text-base font-medium text-zinc-700 dark:text-zinc-300 mb-1.5">
|
|
275
221
|
Variable Name
|
|
276
222
|
</label>
|
|
277
|
-
<
|
|
223
|
+
<Input
|
|
278
224
|
type="text"
|
|
279
225
|
value={formName}
|
|
280
226
|
onChange={(e) => { setFormName(e.target.value); setErrorMessage(null); }}
|
|
281
|
-
|
|
227
|
+
size="sm"
|
|
282
228
|
placeholder="API_KEY"
|
|
283
229
|
/>
|
|
284
230
|
</div>
|
|
285
231
|
<div>
|
|
286
|
-
<label className="block text-
|
|
232
|
+
<label className="block text-base font-medium text-zinc-700 dark:text-zinc-300 mb-1.5">
|
|
287
233
|
Value
|
|
288
234
|
</label>
|
|
289
|
-
<
|
|
235
|
+
<Input
|
|
290
236
|
type="text"
|
|
291
237
|
value={formValue}
|
|
292
238
|
onChange={(e) => { setFormValue(e.target.value); setErrorMessage(null); }}
|
|
293
|
-
|
|
239
|
+
size="sm"
|
|
294
240
|
placeholder="your-secret-value"
|
|
295
241
|
/>
|
|
296
242
|
</div>
|
|
297
|
-
<div className="flex gap-
|
|
298
|
-
<
|
|
299
|
-
onClick={handleAdd}
|
|
300
|
-
className="px-3 py-1.5 text-sm font-medium bg-blue-600 hover:bg-blue-500 text-white rounded transition-colors"
|
|
301
|
-
>
|
|
243
|
+
<div className="flex gap-3">
|
|
244
|
+
<Button onClick={handleAdd} size="sm">
|
|
302
245
|
Save
|
|
303
|
-
</
|
|
304
|
-
<
|
|
305
|
-
onClick={() => { setIsAdding(false); setErrorMessage(null); }}
|
|
306
|
-
className="px-3 py-1.5 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
|
|
307
|
-
>
|
|
246
|
+
</Button>
|
|
247
|
+
<Button onClick={() => { setIsAdding(false); setErrorMessage(null); }} variant="ghost" size="sm">
|
|
308
248
|
Cancel
|
|
309
|
-
</
|
|
249
|
+
</Button>
|
|
310
250
|
</div>
|
|
311
251
|
</div>
|
|
312
252
|
</div>
|
|
@@ -314,33 +254,27 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
314
254
|
|
|
315
255
|
{/* Edit Form */}
|
|
316
256
|
{editingName && (
|
|
317
|
-
<div className="mb-
|
|
318
|
-
<div className="space-y-
|
|
257
|
+
<div className="mb-6 p-6 bg-zinc-50 dark:bg-zinc-800/50 rounded-lg">
|
|
258
|
+
<div className="space-y-4">
|
|
319
259
|
<div>
|
|
320
|
-
<label className="block text-
|
|
260
|
+
<label className="block text-base font-medium text-zinc-700 dark:text-zinc-300 mb-1.5">
|
|
321
261
|
Editing: {editingName}
|
|
322
262
|
</label>
|
|
323
|
-
<
|
|
263
|
+
<Input
|
|
324
264
|
type="text"
|
|
325
265
|
value={formValue}
|
|
326
266
|
onChange={(e) => setFormValue(e.target.value)}
|
|
327
|
-
|
|
267
|
+
size="sm"
|
|
328
268
|
placeholder="new-value"
|
|
329
269
|
/>
|
|
330
270
|
</div>
|
|
331
|
-
<div className="flex gap-
|
|
332
|
-
<
|
|
333
|
-
onClick={handleEdit}
|
|
334
|
-
className="px-3 py-1.5 text-sm font-medium bg-blue-600 hover:bg-blue-500 text-white rounded transition-colors"
|
|
335
|
-
>
|
|
271
|
+
<div className="flex gap-3">
|
|
272
|
+
<Button onClick={handleEdit} size="sm">
|
|
336
273
|
Save
|
|
337
|
-
</
|
|
338
|
-
<
|
|
339
|
-
onClick={() => setEditingName(null)}
|
|
340
|
-
className="px-3 py-1.5 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
|
|
341
|
-
>
|
|
274
|
+
</Button>
|
|
275
|
+
<Button onClick={() => setEditingName(null)} variant="ghost" size="sm">
|
|
342
276
|
Cancel
|
|
343
|
-
</
|
|
277
|
+
</Button>
|
|
344
278
|
</div>
|
|
345
279
|
</div>
|
|
346
280
|
</div>
|
|
@@ -348,30 +282,24 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
348
282
|
|
|
349
283
|
{/* Delete Confirmation */}
|
|
350
284
|
{deletingName && (
|
|
351
|
-
<div className="mb-
|
|
352
|
-
<p className="text-
|
|
285
|
+
<div className="mb-6 p-6 bg-red-50 dark:bg-red-900/20 rounded-lg">
|
|
286
|
+
<p className="text-base text-red-700 dark:text-red-300 mb-3">
|
|
353
287
|
Are you sure you want to delete "{deletingName}"?
|
|
354
288
|
</p>
|
|
355
|
-
<div className="flex gap-
|
|
356
|
-
<
|
|
357
|
-
onClick={handleDelete}
|
|
358
|
-
className="px-3 py-1.5 text-sm font-medium bg-red-600 hover:bg-red-500 text-white rounded transition-colors"
|
|
359
|
-
>
|
|
289
|
+
<div className="flex gap-3">
|
|
290
|
+
<Button onClick={handleDelete} variant="destructive" size="sm">
|
|
360
291
|
Delete
|
|
361
|
-
</
|
|
362
|
-
<
|
|
363
|
-
onClick={() => setDeletingName(null)}
|
|
364
|
-
className="px-3 py-1.5 text-sm font-medium text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
|
|
365
|
-
>
|
|
292
|
+
</Button>
|
|
293
|
+
<Button onClick={() => setDeletingName(null)} variant="ghost" size="sm">
|
|
366
294
|
Cancel
|
|
367
|
-
</
|
|
295
|
+
</Button>
|
|
368
296
|
</div>
|
|
369
297
|
</div>
|
|
370
298
|
)}
|
|
371
299
|
|
|
372
300
|
{/* Env Vars List */}
|
|
373
301
|
{envVars.length === 0 ? (
|
|
374
|
-
<p className="text-
|
|
302
|
+
<p className="text-base text-zinc-500 dark:text-zinc-400">
|
|
375
303
|
No environment variables in this file yet.
|
|
376
304
|
</p>
|
|
377
305
|
) : (
|
|
@@ -379,30 +307,24 @@ export function EnvVarsSection({ initialEnvVars, envFiles: initialEnvFiles, sele
|
|
|
379
307
|
{envVars.map((envVar) => (
|
|
380
308
|
<div
|
|
381
309
|
key={envVar.name}
|
|
382
|
-
className="flex items-center justify-between p-
|
|
310
|
+
className="flex items-center justify-between p-4 bg-zinc-50 dark:bg-zinc-800/50 rounded-lg"
|
|
383
311
|
>
|
|
384
312
|
<div>
|
|
385
|
-
<span className="font-mono text-
|
|
313
|
+
<span className="font-mono text-base font-medium text-zinc-900 dark:text-zinc-100">
|
|
386
314
|
{envVar.name}
|
|
387
315
|
</span>
|
|
388
316
|
<span className="mx-2 text-zinc-400">=</span>
|
|
389
|
-
<span className="font-mono text-
|
|
317
|
+
<span className="font-mono text-base text-zinc-500 dark:text-zinc-400">
|
|
390
318
|
{maskValue(envVar.value)}
|
|
391
319
|
</span>
|
|
392
320
|
</div>
|
|
393
|
-
<div className="flex gap-
|
|
394
|
-
<
|
|
395
|
-
onClick={() => startEdit(envVar)}
|
|
396
|
-
className="px-2 py-1 text-xs text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100 transition-colors"
|
|
397
|
-
>
|
|
321
|
+
<div className="flex gap-3">
|
|
322
|
+
<Button onClick={() => startEdit(envVar)} variant="ghost" size="sm">
|
|
398
323
|
Edit
|
|
399
|
-
</
|
|
400
|
-
<
|
|
401
|
-
onClick={() => setDeletingName(envVar.name)}
|
|
402
|
-
className="px-2 py-1 text-xs text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 transition-colors"
|
|
403
|
-
>
|
|
324
|
+
</Button>
|
|
325
|
+
<Button onClick={() => setDeletingName(envVar.name)} variant="destructive" size="sm">
|
|
404
326
|
Delete
|
|
405
|
-
</
|
|
327
|
+
</Button>
|
|
406
328
|
</div>
|
|
407
329
|
</div>
|
|
408
330
|
))}
|