| ... | ... | @@ -116,10 +116,17 @@ export function PullRequestReviewForm({ |
| 116 | 116 | }; |
| 117 | 117 | |
| 118 | 118 | // Forgejo requires a summary when requesting changes, even with inline comments. |
| 119 | | const canSubmit = (verdict: PullRequestReviewVerdict) => |
| 119 | const canSubmit = (verdict: PullRequestReviewVerdict, summary: string) => |
| 120 | 120 | verdict === "request-changes" && requestChangesSummaryRequired |
| 121 | | ? body.trim().length > 0 |
| 122 | | : verdict === "approve" || body.trim().length > 0 || comments.length > 0; |
| 121 | ? summary.trim().length > 0 |
| 122 | : verdict === "approve" || summary.trim().length > 0 || comments.length > 0; |
| 123 | // The placeholder asks for exactly what the submit button is waiting on. |
| 124 | const placeholder = |
| 125 | selectedVerdict === undefined || canSubmit(selectedVerdict.value, "") |
| 126 | ? "Summarize your review (optional)" |
| 127 | : selectedVerdict.value === "request-changes" && requestChangesSummaryRequired |
| 128 | ? "Summarize your review (required to request changes)" |
| 129 | : "Summarize your review or add line comments"; |
| 123 | 130 | |
| 124 | 131 | return ( |
| 125 | 132 | <> |
| ... | ... | @@ -127,42 +134,42 @@ export function PullRequestReviewForm({ |
| 127 | 134 | ref={textareaRef} |
| 128 | 135 | rows={3} |
| 129 | 136 | value={body} |
| 130 | | placeholder={ |
| 131 | | requestChangesSummaryRequired && verdicts.includes("request-changes") |
| 132 | | ? "Summarize your review (required to request changes)" |
| 133 | | : "Summarize your review (optional)" |
| 134 | | } |
| 137 | placeholder={placeholder} |
| 135 | 138 | aria-label="Review summary" |
| 136 | 139 | onChange={(event) => setSummary(reviewKey, event.target.value)} |
| 137 | 140 | /> |
| 138 | | <div className="mt-2 flex justify-between gap-2"> |
| 139 | | <Select |
| 140 | | value={selectedVerdict?.value ?? null} |
| 141 | | disabled={pending} |
| 142 | | onValueChange={(value) => { |
| 143 | | if (value !== null) setRequestedVerdict(value); |
| 144 | | }} |
| 145 | | > |
| 146 | | <SelectTrigger size="xs" className="w-auto min-w-0" aria-label="Review verdict"> |
| 147 | | <span className="flex items-center gap-1.5"> |
| 148 | | {selectedVerdict?.icon} |
| 149 | | {selectedVerdict?.label} |
| 150 | | </span> |
| 151 | | </SelectTrigger> |
| 152 | | <SelectPopup side="top" alignItemWithTrigger={false}> |
| 153 | | {offered.map((verdict) => ( |
| 154 | | <SelectItem key={verdict.value} value={verdict.value}> |
| 155 | | <span className="flex items-center gap-1.5"> |
| 156 | | {verdict.icon} |
| 157 | | {verdict.label} |
| 158 | | </span> |
| 159 | | </SelectItem> |
| 160 | | ))} |
| 161 | | </SelectPopup> |
| 162 | | </Select> |
| 141 | <div className="mt-2 flex justify-end gap-2"> |
| 142 | {offered.length > 1 ? ( |
| 143 | <Select |
| 144 | value={selectedVerdict?.value ?? null} |
| 145 | disabled={pending} |
| 146 | onValueChange={(value) => { |
| 147 | if (value !== null) setRequestedVerdict(value); |
| 148 | }} |
| 149 | > |
| 150 | <SelectTrigger size="xs" className="mr-auto w-auto min-w-0" aria-label="Review verdict"> |
| 151 | <span className="flex items-center gap-1.5"> |
| 152 | {selectedVerdict?.icon} |
| 153 | {selectedVerdict?.label} |
| 154 | </span> |
| 155 | </SelectTrigger> |
| 156 | <SelectPopup side="top" alignItemWithTrigger={false}> |
| 157 | {offered.map((verdict) => ( |
| 158 | <SelectItem key={verdict.value} value={verdict.value}> |
| 159 | <span className="flex items-center gap-1.5"> |
| 160 | {verdict.icon} |
| 161 | {verdict.label} |
| 162 | </span> |
| 163 | </SelectItem> |
| 164 | ))} |
| 165 | </SelectPopup> |
| 166 | </Select> |
| 167 | ) : null} |
| 163 | 168 | <Button |
| 164 | 169 | size="xs" |
| 165 | | disabled={pending || selectedVerdict === undefined || !canSubmit(selectedVerdict.value)} |
| 170 | disabled={ |
| 171 | pending || selectedVerdict === undefined || !canSubmit(selectedVerdict.value, body) |
| 172 | } |
| 166 | 173 | onClick={() => { |
| 167 | 174 | if (selectedVerdict !== undefined) void submit(selectedVerdict); |
| 168 | 175 | }} |