web: completed is green everywhere; typed-confirmation actually gates
CommandStatusBadge joins the inline timelines (Casey ruling). SecuritySettings CONFIRM/RESET input was theater — border colors changed, Confirm worked regardless. Now controlled state, button disabled until the phrase matches.
This commit is contained in:
parent
6fb7e7c81f
commit
0669b4d6b1
3 changed files with 25 additions and 21 deletions
|
|
@ -13,7 +13,7 @@ export function getCommandStatus(status: CommandStatus): StatusInfo {
|
|||
case 'pending': return { text: 'Pending', color: 'text-amber-600 bg-amber-50 border-amber-200' };
|
||||
case 'sent': return { text: 'Sent to agent', color: 'text-blue-600 bg-blue-50 border-blue-200' };
|
||||
case 'running': return { text: 'Running', color: 'text-green-600 bg-green-50 border-green-200' };
|
||||
case 'completed': return { text: 'Completed', color: 'text-gray-600 bg-gray-50 border-gray-200' };
|
||||
case 'completed': return { text: 'Completed', color: 'text-green-700 bg-green-50 border-green-200' };
|
||||
case 'failed': return { text: 'Failed', color: 'text-red-600 bg-red-50 border-red-200' };
|
||||
case 'timed_out': return { text: 'Timed out', color: 'text-red-600 bg-red-50 border-red-200' };
|
||||
default: return { text: status, color: 'text-gray-600 bg-gray-50 border-gray-200' };
|
||||
|
|
|
|||
|
|
@ -117,12 +117,8 @@ export function lifecycleHistoryStatusColor(status: string): string {
|
|||
// DOMAIN: command status (inline badge, not CommandStatusBadge primitive)
|
||||
// (completed / failed / timed_out / cancelled / pending / sent / running)
|
||||
//
|
||||
// DISCREPANCY: CommandStatusBadge (primitives/CommandStatusBadge.tsx) maps
|
||||
// 'completed' -> text-gray-600 bg-gray-50 border-gray-200. Both inline sites
|
||||
// (PackageDetail.tsx and Updates.tsx) map 'completed' -> bg-green-50
|
||||
// text-green-700 border-green-200. The two inline sites agree with each
|
||||
// other. The primitives/CommandStatusBadge.tsx is the odd one out.
|
||||
// Kept as-is per task constraint: deduplication, not restyle.
|
||||
// 'completed' is green everywhere — ruled 2026-06-12 (Casey); the gray
|
||||
// rendering CommandStatusBadge used to carry was the odd one out.
|
||||
// ---------------------------------------------------------------------------
|
||||
export function commandStatusInlineColor(status: string): string {
|
||||
switch (status) {
|
||||
|
|
|
|||
|
|
@ -61,8 +61,14 @@ const SecuritySettings: React.FC = () => {
|
|||
onConfirm: () => {},
|
||||
onCancel: () => {},
|
||||
});
|
||||
const [confirmationTyped, setConfirmationTyped] = useState('');
|
||||
const [showAdvanced, setShowAdvanced] = useState(false);
|
||||
|
||||
// Fresh typed-confirmation field every time the dialog opens or closes.
|
||||
useEffect(() => {
|
||||
setConfirmationTyped('');
|
||||
}, [confirmationDialog.isOpen]);
|
||||
|
||||
// Sync URL tab with state
|
||||
useEffect(() => {
|
||||
if (tab !== activeTab) {
|
||||
|
|
@ -613,17 +619,15 @@ const SecuritySettings: React.FC = () => {
|
|||
</label>
|
||||
<input
|
||||
type="text"
|
||||
className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-red-500"
|
||||
onChange={(e) => {
|
||||
const expected = confirmationDialog.title === 'Rotate Security Key' ? 'CONFIRM' : 'RESET';
|
||||
if (e.target.value === expected) {
|
||||
e.target.classList.remove('border-red-300');
|
||||
e.target.classList.add('border-green-300');
|
||||
} else {
|
||||
e.target.classList.remove('border-green-300');
|
||||
e.target.classList.add('border-red-300');
|
||||
}
|
||||
}}
|
||||
value={confirmationTyped}
|
||||
onChange={(e) => setConfirmationTyped(e.target.value)}
|
||||
className={`w-full px-3 py-2 border rounded-md focus:outline-none focus:ring-2 focus:ring-red-500 ${
|
||||
confirmationTyped === ''
|
||||
? 'border-gray-300'
|
||||
: confirmationTyped === (confirmationDialog.title === 'Rotate Security Key' ? 'CONFIRM' : 'RESET')
|
||||
? 'border-green-300'
|
||||
: 'border-red-300'
|
||||
}`}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -631,10 +635,14 @@ const SecuritySettings: React.FC = () => {
|
|||
<Modal.Footer>
|
||||
<button
|
||||
onClick={confirmationDialog.onConfirm}
|
||||
className={`inline-flex items-center px-4 py-2 rounded border text-white ${
|
||||
disabled={
|
||||
confirmationDialog.requiresConfirmation &&
|
||||
confirmationTyped !== (confirmationDialog.title === 'Rotate Security Key' ? 'CONFIRM' : 'RESET')
|
||||
}
|
||||
className={`inline-flex items-center px-4 py-2 rounded border text-white disabled:opacity-50 disabled:cursor-not-allowed ${
|
||||
confirmationDialog.severity === 'danger'
|
||||
? 'bg-red-600 border-red-700 hover:bg-red-700'
|
||||
: 'bg-blue-600 border-blue-700 hover:bg-blue-700'
|
||||
? 'bg-red-600 border-red-700 hover:bg-red-700 disabled:hover:bg-red-600'
|
||||
: 'bg-blue-600 border-blue-700 hover:bg-blue-700 disabled:hover:bg-blue-600'
|
||||
}`}
|
||||
>
|
||||
Confirm
|
||||
|
|
|
|||
Loading…
Reference in a new issue