✨ feat: improve WorkflowSettings.tsx

swadhinbiswas committed 3 months ago
aa542bc
1 parent ed4f8fd
commit aa542bc
1 file changed
+53 -3
▼src/components/repo/settings/WorkflowSettings.tsx
+53-3
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
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
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
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
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
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