✨ feat: improve WorkflowSettings.tsx
swadhinbiswas committed 3 months ago
aa542bc
1 parent ed4f8fd
commit aa542bc
1 file changed
+53 -3
Showing 1 changed file+53-3
▼src/components/repo/settings/WorkflowSettings.tsx
+53-3
| @@ -4,7 +4,7 @@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/com | ||
4 | 4 | import { Input } from "@/components/ui/input"; |
5 | 5 | import { Label } from "@/components/ui/label"; |
6 | 6 | import { toast } from "sonner"; |
7 | -import { Loader2, Plus, GripVertical, Trash2 } from "lucide-react"; | |
7 | +import { Loader2, Plus, GripVertical, Trash2, Check, X } from "lucide-react"; | |
8 | 8 | import type { PRStateDefinition } from "@/db/schema/pr-states"; |
9 | 9 | |
10 | 10 | |
| @@ -18,6 +18,10 @@ export default function WorkflowSettings({ repositoryId, owner, repo }: Workflow | ||
18 | 18 | const [states, setStates] = useState<PRStateDefinition[]>([]); |
19 | 19 | const [loading, setLoading] = useState(true); |
20 | 20 | const [newStateName, setNewStateName] = useState(""); |
21 | + const [newStateDesc, setNewStateDesc] = useState(""); | |
22 | + const [allowMerge, setAllowMerge] = useState(false); | |
23 | + const [requireCodeOwner, setRequireCodeOwner] = useState(false); | |
24 | + const [reviewerUsernames, setReviewerUsernames] = useState(""); | |
21 | 25 | const [isSubmitting, setIsSubmitting] = useState(false); |
22 | 26 | |
23 | 27 | // Fetch existing states |
| @@ -50,7 +54,11 @@ export default function WorkflowSettings({ repositoryId, owner, repo }: Workflow | ||
50 | 54 | body: JSON.stringify({ |
51 | 55 | name: newStateName.toLowerCase().replace(/\s+/g, "_"), |
52 | 56 | displayName: newStateName, |
53 | - color: "#6B7280" // Default color for now, can add picker later | |
57 | + color: "#6B7280", // Default color for now, can add picker later | |
58 | + description: newStateDesc || undefined, | |
59 | + allowMerge, | |
60 | + requireCodeOwner, | |
61 | + reviewers: reviewerUsernames ? reviewerUsernames.split(",").map(u => ({ username: u.trim() })).filter(u => u.username) : undefined | |
54 | 62 | }) |
55 | 63 | }); |
56 | 64 | |
| @@ -62,6 +70,10 @@ export default function WorkflowSettings({ repositoryId, owner, repo }: Workflow | ||
62 | 70 | const newState = await res.json(); |
63 | 71 | setStates([...states, newState]); |
64 | 72 | setNewStateName(""); |
73 | + setNewStateDesc(""); | |
74 | + setReviewerUsernames(""); | |
75 | + setAllowMerge(false); | |
76 | + setRequireCodeOwner(false); | |
65 | 77 | toast.success("State created"); |
66 | 78 | } catch (e) { |
67 | 79 | console.error(e); |
| @@ -114,7 +126,15 @@ export default function WorkflowSettings({ repositoryId, owner, repo }: Workflow | ||
114 | 126 | <div className="h-3 w-3 rounded-full" style={{ backgroundColor: state.color }} /> |
115 | 127 | <div> |
116 | 128 | <p className="font-medium text-sm">{state.displayName}</p> |
117 | - <p className="text-xs text-muted-foreground">{state.name}</p> | |
129 | + <p className="text-xs text-muted-foreground">{state.name} {state.description ? `- ${state.description}` : ""}</p> | |
130 | + <div className="flex gap-2 mt-1"> | |
131 | + <span className={`text-[10px] px-1.5 py-0.5 rounded flex items-center gap-1 ${state.allowMerge ? 'bg-green-500/10 text-green-500' : 'bg-red-500/10 text-red-500'}`}> | |
132 | + {state.allowMerge ? <Check className="w-3 h-3"/> : <X className="w-3 h-3"/>} Merge | |
133 | + </span> | |
134 | + <span className={`text-[10px] px-1.5 py-0.5 rounded flex items-center gap-1 ${state.requireCodeOwner ? 'bg-purple-500/10 text-purple-500' : 'bg-gray-500/10 text-gray-500'}`}> | |
135 | + {state.requireCodeOwner ? <Check className="w-3 h-3"/> : <X className="w-3 h-3"/>} CodeOwner | |
136 | + </span> | |
137 | + </div> | |
118 | 138 | </div> |
119 | 139 | {state.isDefault && <span className="text-xs bg-secondary px-2 py-0.5 rounded text-secondary-foreground">Default</span>} |
120 | 140 | </div> |
| @@ -152,6 +172,36 @@ export default function WorkflowSettings({ repositoryId, owner, repo }: Workflow | ||
152 | 172 | disabled |
153 | 173 | /> |
154 | 174 | </div> |
175 | + <div className="grid gap-1.5 col-span-2"> | |
176 | + <Label htmlFor="state-desc">Description</Label> | |
177 | + <Input | |
178 | + id="state-desc" | |
179 | + placeholder="e.g. Code is currently under review" | |
180 | + value={newStateDesc} | |
181 | + onChange={(e) => setNewStateDesc(e.target.value)} | |
182 | + /> | |
183 | + </div> | |
184 | + <div className="grid gap-1.5 col-span-2"> | |
185 | + <Label htmlFor="state-reviewers">Required Reviewers (Usernames, comma separated)</Label> | |
186 | + <Input | |
187 | + id="state-reviewers" | |
188 | + placeholder="e.g. alice, bob" | |
189 | + value={reviewerUsernames} | |
190 | + onChange={(e) => setReviewerUsernames(e.target.value)} | |
191 | + /> | |
192 | + </div> | |
193 | + <div className="grid gap-1.5 col-span-2 mt-2"> | |
194 | + <label className="flex items-center gap-2 text-sm font-medium"> | |
195 | + <input type="checkbox" className="rounded border-gray-300" checked={allowMerge} onChange={(e) => setAllowMerge(e.target.checked)} /> | |
196 | + Allow Merging in this state | |
197 | + </label> | |
198 | + <p className="text-[0.8rem] text-muted-foreground ml-6">If unchecked, pull requests in this state cannot be merged.</p> | |
199 | + <label className="flex items-center gap-2 text-sm font-medium mt-2"> | |
200 | + <input type="checkbox" className="rounded border-gray-300" checked={requireCodeOwner} onChange={(e) => setRequireCodeOwner(e.target.checked)} /> | |
201 | + Enforce CODEOWNERS | |
202 | + </label> | |
203 | + <p className="text-[0.8rem] text-muted-foreground ml-6">Require approvals from CODEOWNERS before this state allows merging.</p> | |
204 | + </div> | |
155 | 205 | </div> |
156 | 206 | <Button disabled={!newStateName || isSubmitting} onClick={addState} className="w-full"> |
157 | 207 | {isSubmitting ? <Loader2 className="h-4 w-4 animate-spin" /> : <Plus className="h-4 w-4 mr-2" />} |
158 | 208 | |