fix(jira): correct browse URL, rename Procedure to Proof of Concept; feat(tempo): debug endpoint + UI
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Some checks failed
Aegis CI / lint-and-test (push) Has been cancelled
Jira URL fix: - JiraLinkPanel now fetches the configured Jira base URL via getJiraConfig() instead of hardcoding https://jira.atlassian.com; falls back to the old value if config is not yet loaded Description fix: - _build_test_description: renamed 'h3. Procedure' -> 'h3. Proof of Concept' so the procedure/tool block maps to the correct Jira field label Tempo debug: - New POST /system/tempo-test endpoint: checks TEMPO_ENABLED, token, user jira_account_id, and makes a real API call; always returns HTTP 200 with status field (Cloudflare-safe) - docker-compose.prod.yml: added TEMPO_ENABLED, TEMPO_API_TOKEN, TEMPO_DEFAULT_WORK_TYPE env vars (default off, ready to enable) - SettingsPage: added 'Test Tempo Connection' button in Jira admin tab with clear feedback showing what's missing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,7 @@ import {
|
||||
getJiraConfig,
|
||||
updateJiraConfig,
|
||||
testJiraConnection,
|
||||
testTempoConnection,
|
||||
type EmailConfigUpdate,
|
||||
type WebhookCreate,
|
||||
type WebhookOut,
|
||||
@@ -1024,6 +1025,8 @@ function JiraConfigSection() {
|
||||
const [toast, setToast] = useState<{ msg: string; type: "success" | "error" } | null>(null);
|
||||
const [testResult, setTestResult] = useState<{ connectedAs: string; url: string } | null>(null);
|
||||
const [testError, setTestError] = useState<string | null>(null);
|
||||
const [tempoResult, setTempoResult] = useState<string | null>(null);
|
||||
const [tempoError, setTempoError] = useState<string | null>(null);
|
||||
|
||||
const { data: cfg, isLoading } = useQuery({
|
||||
queryKey: ["jira-config"],
|
||||
@@ -1061,6 +1064,23 @@ function JiraConfigSection() {
|
||||
},
|
||||
});
|
||||
|
||||
const tempoTestMut = useMutation({
|
||||
mutationFn: testTempoConnection,
|
||||
onSuccess: (data) => {
|
||||
if (data.status === "ok") {
|
||||
setTempoResult(data.message ?? "Connected");
|
||||
setTempoError(null);
|
||||
} else {
|
||||
setTempoError(data.message ?? "Tempo test failed");
|
||||
setTempoResult(null);
|
||||
}
|
||||
},
|
||||
onError: (err: Error) => {
|
||||
setTempoError(err.message || "Tempo test failed");
|
||||
setTempoResult(null);
|
||||
},
|
||||
});
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<div className="flex justify-center py-8">
|
||||
@@ -1139,9 +1159,9 @@ function JiraConfigSection() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Test connection */}
|
||||
{/* Test Jira connection */}
|
||||
<div className="mt-4 rounded-lg border border-gray-700 bg-gray-800/50 p-4 space-y-3">
|
||||
<p className="text-sm font-medium text-gray-300">Test Connection</p>
|
||||
<p className="text-sm font-medium text-gray-300">Test Jira Connection</p>
|
||||
<div className="rounded-md bg-blue-900/20 border border-blue-800/50 px-3 py-2 text-xs text-blue-300">
|
||||
Uses your personal Jira API token (configured in the Profile tab)
|
||||
</div>
|
||||
@@ -1159,7 +1179,7 @@ function JiraConfigSection() {
|
||||
) : (
|
||||
<TestTube className="h-4 w-4" />
|
||||
)}
|
||||
Test Connection
|
||||
Test Jira Connection
|
||||
</button>
|
||||
|
||||
{testResult && (
|
||||
@@ -1175,6 +1195,43 @@ function JiraConfigSection() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Test Tempo connection */}
|
||||
<div className="mt-2 rounded-lg border border-gray-700 bg-gray-800/50 p-4 space-y-3">
|
||||
<p className="text-sm font-medium text-gray-300">Test Tempo Connection</p>
|
||||
<div className="rounded-md bg-blue-900/20 border border-blue-800/50 px-3 py-2 text-xs text-blue-300">
|
||||
Requires <code className="font-mono">TEMPO_ENABLED=true</code> and <code className="font-mono">TEMPO_API_TOKEN</code> set in the server environment, plus your Jira Account ID in the Profile tab.
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
setTempoResult(null);
|
||||
setTempoError(null);
|
||||
tempoTestMut.mutate();
|
||||
}}
|
||||
disabled={tempoTestMut.isPending}
|
||||
className="flex items-center gap-2 rounded-lg border border-purple-700 px-4 py-2 text-sm font-medium text-purple-400 hover:bg-purple-900/30 disabled:opacity-50 transition-colors"
|
||||
>
|
||||
{tempoTestMut.isPending ? (
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<TestTube className="h-4 w-4" />
|
||||
)}
|
||||
Test Tempo Connection
|
||||
</button>
|
||||
|
||||
{tempoResult && (
|
||||
<div className="flex items-center gap-2 rounded-md bg-emerald-900/30 border border-emerald-800/50 px-3 py-2 text-sm text-emerald-300">
|
||||
<CheckCircle className="h-4 w-4 shrink-0" />
|
||||
{tempoResult}
|
||||
</div>
|
||||
)}
|
||||
{tempoError && (
|
||||
<div className="flex items-center gap-2 rounded-md bg-red-900/30 border border-red-800/50 px-3 py-2 text-sm text-red-300">
|
||||
<XCircle className="h-4 w-4 shrink-0" />
|
||||
{tempoError}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user