diff --git a/app/controllers/reviews_controller.rb b/app/controllers/reviews_controller.rb index b8bdc1c..1b4486b 100644 --- a/app/controllers/reviews_controller.rb +++ b/app/controllers/reviews_controller.rb @@ -3,6 +3,11 @@ def index end def create + unless Harness.configuration&.api_key.present? + return render json: { error: "OPENAI_API_KEY is not configured on the server." }, + status: :service_unavailable + end + review = Review.create!(pr_url: params[:pr_url], status: Review::PENDING) ReviewJob.perform_later(review.id) render json: { id: review.id, status: review.status } @@ -51,8 +56,8 @@ def review_json(review) { id: s.id, filename: s.filename, language: s.language, priority: s.priority, walkthrough: s.walkthrough, - findings: s.findings, human_comments: s.human_comments, - status: s.status + patch_text: s.patch_text, findings: s.findings, + human_comments: s.human_comments, status: s.status } end } diff --git a/app/javascript/components/review/DiffPanel.jsx b/app/javascript/components/review/DiffPanel.jsx index 909372e..0905d1e 100644 --- a/app/javascript/components/review/DiffPanel.jsx +++ b/app/javascript/components/review/DiffPanel.jsx @@ -1,6 +1,13 @@ import React, { useState, useRef, useEffect } from 'react' -const DiffPanel = ({ sections, highlightFile, highlightRange }) => { +const lineStyle = (line) => { + if (line.startsWith('+')) return 'bg-green-50 text-green-800' + if (line.startsWith('-')) return 'bg-red-50 text-red-800' + if (line.startsWith('@@')) return 'bg-blue-50 text-blue-600 font-medium' + return 'text-gray-700' +} + +const DiffPanel = ({ sections, status, highlightFile, highlightRange }) => { const [collapsed, setCollapsed] = useState({}) const fileRefs = useRef({}) @@ -15,30 +22,52 @@ const DiffPanel = ({ sections, highlightFile, highlightRange }) => { } if (!sections || sections.length === 0) { - return
No diff data available
+ if (status === 'reviewing' || status === 'submitting') { + return ( +
+ + Fetching diff... +
+ ) + } + return ( +
+ Submit a PR URL to see the diff here. +
+ ) } return ( -
+
{sections.map((section) => (
fileRefs.current[section.filename] = el} - className="border border-gray-200 rounded" + className="border border-gray-200 rounded overflow-hidden" > - {!collapsed[section.filename] && section.findings && ( -
- {section.findings.length} finding{section.findings.length !== 1 ? 's' : ''} - {section.findings.some(f => f.severity === 'red_flag') && ( - contains red flags + {!collapsed[section.filename] && ( +
+ {section.patch_text ? ( +
+                  {section.patch_text.split('\n').map((line, i) => (
+                    
{line || ' '}
+ ))} +
+ ) : ( +
No diff content available
)}
)} diff --git a/app/javascript/components/review/ReviewApp.jsx b/app/javascript/components/review/ReviewApp.jsx index 8fbbf22..a7352f3 100644 --- a/app/javascript/components/review/ReviewApp.jsx +++ b/app/javascript/components/review/ReviewApp.jsx @@ -121,17 +121,30 @@ const ReviewApp = () => { {error && ( -
+
{error}
)} + {status === 'failed' && !error && ( +
+ Review failed. This could be a GitHub API issue or an invalid PR URL. Try again. +
+ )} + + {!reviewId && status === 'idle' && !error && ( +
+ Paste a public GitHub PR URL above to start an AI-powered code review. +
+ )} + {reviewId && (
-

Files

+

Diff

diff --git a/app/javascript/components/review/ReviewPanel.jsx b/app/javascript/components/review/ReviewPanel.jsx index c280c30..58c3bd5 100644 --- a/app/javascript/components/review/ReviewPanel.jsx +++ b/app/javascript/components/review/ReviewPanel.jsx @@ -7,17 +7,30 @@ const ReviewPanel = ({ sections, synthesis, reviewId, status, onSynthesize, onFi const canSynthesize = status === 'complete' && hasSections && !synthesis?.verdict return ( -
+
{!hasSections && status === 'reviewing' && (
- Reviewing pull request... + Triaging files and starting review... +
+ )} + + {hasSections && status === 'reviewing' && ( +
+ + Reviewing more files... +
+ )} + + {status === 'complete' && !hasSections && ( +
+ No files were flagged for review.
)} {sections.map((section) => (