-
Notifications
You must be signed in to change notification settings - Fork 41
π Replace all window.confirm() with styled ConfirmDialog #4057
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,7 +2,7 @@ import { useState } from 'react' | |||||||||||||||||
| import { useTranslation } from 'react-i18next' | ||||||||||||||||||
| import { Trash2, Server, Bell, BellOff, Bot, Slack, Webhook, Siren, ShieldAlert } from 'lucide-react' | ||||||||||||||||||
| import { useClusters } from '../../hooks/useMCP' | ||||||||||||||||||
| import { BaseModal } from '../../lib/modals' | ||||||||||||||||||
| import { BaseModal, ConfirmDialog } from '../../lib/modals' | ||||||||||||||||||
| import type { | ||||||||||||||||||
| AlertRule, | ||||||||||||||||||
| AlertCondition, | ||||||||||||||||||
|
|
@@ -80,10 +80,17 @@ export function AlertRuleEditor({ isOpen = true, rule, onSave, onCancel }: Alert | |||||||||||||||||
|
|
||||||||||||||||||
| // Validation | ||||||||||||||||||
| const [errors, setErrors] = useState<Record<string, string>>({}) | ||||||||||||||||||
| const [showDiscardConfirm, setShowDiscardConfirm] = useState(false) | ||||||||||||||||||
|
|
||||||||||||||||||
| const forceClose = () => { | ||||||||||||||||||
| setShowDiscardConfirm(false) | ||||||||||||||||||
| onCancel() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const handleClose = () => { | ||||||||||||||||||
| const hasChanges = name.trim() !== '' || description.trim() !== '' | ||||||||||||||||||
| if (hasChanges && !window.confirm(t('common:common.discardUnsavedChanges', 'Discard unsaved changes?'))) { | ||||||||||||||||||
| if (hasChanges) { | ||||||||||||||||||
| setShowDiscardConfirm(true) | ||||||||||||||||||
| return | ||||||||||||||||||
| } | ||||||||||||||||||
| onCancel() | ||||||||||||||||||
|
|
@@ -176,6 +183,16 @@ export function AlertRuleEditor({ isOpen = true, rule, onSave, onCancel }: Alert | |||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
| <BaseModal isOpen={isOpen} onClose={handleClose} size="lg" closeOnBackdrop={false} closeOnEscape={true}> | ||||||||||||||||||
| <ConfirmDialog | ||||||||||||||||||
| isOpen={showDiscardConfirm} | ||||||||||||||||||
| onClose={() => setShowDiscardConfirm(false)} | ||||||||||||||||||
| onConfirm={forceClose} | ||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | ||||||||||||||||||
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | ||||||||||||||||||
| confirmLabel={t('common:common.discard', 'Discard')} | ||||||||||||||||||
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | ||||||||||||||||||
|
Comment on lines
+190
to
+193
|
||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:common.discard', 'Discard')} | |
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | |
| title={t('common:discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:discard', 'Discard')} | |
| cancelLabel={t('common:keepEditing', 'Keep editing')} |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,7 +2,7 @@ import { useState, useEffect, useRef, useCallback } from 'react' | |||||||||||||||||
| import { X, Bug, Sparkles, Loader2, ExternalLink, Bell, Check, Clock, GitPullRequest, GitMerge, Eye, Pencil, RefreshCw, MessageSquare, Settings, Github, Coins, Lightbulb, AlertCircle, AlertTriangle, Linkedin, Trophy, Monitor, BookOpen, ImagePlus, Trash2, Copy, Maximize2 } from 'lucide-react' | ||||||||||||||||||
| import { Button } from '../ui/Button' | ||||||||||||||||||
| import { StatusBadge } from '../ui/StatusBadge' | ||||||||||||||||||
| import { BaseModal } from '../../lib/modals' | ||||||||||||||||||
| import { BaseModal, ConfirmDialog } from '../../lib/modals' | ||||||||||||||||||
| import { | ||||||||||||||||||
| useFeatureRequests, | ||||||||||||||||||
| useNotifications, | ||||||||||||||||||
|
|
@@ -116,6 +116,7 @@ export function FeatureRequestModal({ isOpen, onClose, initialTab, initialReques | |||||||||||||||||
| const [error, setError] = useState<string | null>(null) | ||||||||||||||||||
| const [success, setSuccess] = useState<{ issueUrl?: string } | null>(null) | ||||||||||||||||||
| const [confirmClose, setConfirmClose] = useState<string | null>(null) // request ID to confirm close | ||||||||||||||||||
| const [showDiscardConfirm, setShowDiscardConfirm] = useState(false) | ||||||||||||||||||
| const [actionLoading, setActionLoading] = useState<string | null>(null) // request ID being acted on | ||||||||||||||||||
| const [actionError, setActionError] = useState<string | null>(null) | ||||||||||||||||||
| const [showLoginPrompt, setShowLoginPrompt] = useState(false) | ||||||||||||||||||
|
|
@@ -370,25 +371,41 @@ export function FeatureRequestModal({ isOpen, onClose, initialTab, initialReques | |||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const forceClose = () => { | ||||||||||||||||||
| setShowDiscardConfirm(false) | ||||||||||||||||||
| setDescription('') | ||||||||||||||||||
| setDescriptionTab('write') | ||||||||||||||||||
| setRequestType(initialRequestType || 'bug') | ||||||||||||||||||
| setTargetRepo('console') | ||||||||||||||||||
| setError(null) | ||||||||||||||||||
| setSuccess(null) | ||||||||||||||||||
| setScreenshots([]) | ||||||||||||||||||
| setActiveTab(initialTab || 'submit') | ||||||||||||||||||
| onClose() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const handleClose = () => { | ||||||||||||||||||
| if (!isSubmitting) { | ||||||||||||||||||
| if (description.trim() !== '' && !window.confirm(t('common:common.discardUnsavedChanges', 'Discard unsaved changes?'))) { | ||||||||||||||||||
| if (description.trim() !== '') { | ||||||||||||||||||
| setShowDiscardConfirm(true) | ||||||||||||||||||
| return | ||||||||||||||||||
| } | ||||||||||||||||||
| setDescription('') | ||||||||||||||||||
| setDescriptionTab('write') | ||||||||||||||||||
| setRequestType(initialRequestType || 'bug') | ||||||||||||||||||
| setTargetRepo('console') | ||||||||||||||||||
| setError(null) | ||||||||||||||||||
| setSuccess(null) | ||||||||||||||||||
| setScreenshots([]) | ||||||||||||||||||
| setActiveTab(initialTab || 'submit') | ||||||||||||||||||
| onClose() | ||||||||||||||||||
| forceClose() | ||||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
| <BaseModal isOpen={isOpen} onClose={handleClose} size="lg" closeOnBackdrop={false} closeOnEscape={true} className="!h-[80vh]"> | ||||||||||||||||||
| <ConfirmDialog | ||||||||||||||||||
| isOpen={showDiscardConfirm} | ||||||||||||||||||
| onClose={() => setShowDiscardConfirm(false)} | ||||||||||||||||||
| onConfirm={forceClose} | ||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | ||||||||||||||||||
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | ||||||||||||||||||
| confirmLabel={t('common:common.discard', 'Discard')} | ||||||||||||||||||
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | ||||||||||||||||||
|
Comment on lines
+403
to
+406
|
||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:common.discard', 'Discard')} | |
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | |
| title={t('feedback.discardUnsavedChangesTitle', 'Discard unsaved changes?')} | |
| message={t('feedback.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('feedback.discard', 'Discard')} | |
| cancelLabel={t('feedback.keepEditing', 'Keep editing')} |
Copilot
AI
Apr 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ConfirmDialog uses BaseModal with z-[9999], but this component also renders the login prompt overlay at z-[10001]. If the user attempts to close with unsaved changes while the login prompt is open, the discard confirmation can render behind the login overlay and be non-interactive. Consider handling close by dismissing the login prompt first, or ensure the discard confirmation renders above any in-modal overlays (e.g., allow ConfirmDialog/BaseModal to take a higher z-index).
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,6 +13,7 @@ import { useState, useEffect, useRef } from 'react' | |||||||||||||||||
| import { useTranslation } from 'react-i18next' | ||||||||||||||||||
| import { createPortal } from 'react-dom' | ||||||||||||||||||
| import { X, Bug, Lightbulb, Send, CheckCircle2, ExternalLink, Linkedin, ImagePlus, Trash2, Copy, Check, AlertTriangle, Loader2 } from 'lucide-react' | ||||||||||||||||||
| import { ConfirmDialog } from '../../lib/modals' | ||||||||||||||||||
| import { StatusBadge } from '../ui/StatusBadge' | ||||||||||||||||||
| import { useRewards, REWARD_ACTIONS } from '../../hooks/useRewards' | ||||||||||||||||||
| import { useToast } from '../ui/Toast' | ||||||||||||||||||
|
|
@@ -54,6 +55,7 @@ export function FeedbackModal({ isOpen, onClose, initialType = 'feature' }: Feed | |||||||||||||||||
| const [screenshots, setScreenshots] = useState<{ file: File; preview: string }[]>([]) | ||||||||||||||||||
| const [isDragOver, setIsDragOver] = useState(false) | ||||||||||||||||||
| const [copiedIndex, setCopiedIndex] = useState<number | null>(null) | ||||||||||||||||||
| const [showDiscardConfirm, setShowDiscardConfirm] = useState(false) | ||||||||||||||||||
| const fileInputRef = useRef<HTMLInputElement>(null) | ||||||||||||||||||
|
|
||||||||||||||||||
| const handleScreenshotFiles = (files: FileList | null) => { | ||||||||||||||||||
|
|
@@ -183,10 +185,8 @@ export function FeedbackModal({ isOpen, onClose, initialType = 'feature' }: Feed | |||||||||||||||||
| } | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const handleClose = () => { | ||||||||||||||||||
| if (!success && (title.trim() !== '' || description.trim() !== '') && !window.confirm(t('common:common.discardUnsavedChanges', 'Discard unsaved changes?'))) { | ||||||||||||||||||
| return | ||||||||||||||||||
| } | ||||||||||||||||||
| const forceClose = () => { | ||||||||||||||||||
| setShowDiscardConfirm(false) | ||||||||||||||||||
| localStorage.removeItem(DRAFT_KEY) | ||||||||||||||||||
| setSuccess(null) | ||||||||||||||||||
| setSubmitError(null) | ||||||||||||||||||
|
|
@@ -196,6 +196,14 @@ export function FeedbackModal({ isOpen, onClose, initialType = 'feature' }: Feed | |||||||||||||||||
| onClose() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const handleClose = () => { | ||||||||||||||||||
| if (!success && (title.trim() !== '' || description.trim() !== '')) { | ||||||||||||||||||
| setShowDiscardConfirm(true) | ||||||||||||||||||
| return | ||||||||||||||||||
| } | ||||||||||||||||||
| forceClose() | ||||||||||||||||||
| } | ||||||||||||||||||
|
Comment on lines
+199
to
+205
|
||||||||||||||||||
|
|
||||||||||||||||||
| // Keyboard navigation - ESC to close, Space to close when not typing | ||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||
| if (!isOpen) return | ||||||||||||||||||
|
|
@@ -232,6 +240,16 @@ export function FeedbackModal({ isOpen, onClose, initialType = 'feature' }: Feed | |||||||||||||||||
|
|
||||||||||||||||||
| return createPortal( | ||||||||||||||||||
| <div className="fixed inset-0 z-[9999] flex items-center justify-center bg-black/60 backdrop-blur-2xl"> | ||||||||||||||||||
| <ConfirmDialog | ||||||||||||||||||
| isOpen={showDiscardConfirm} | ||||||||||||||||||
| onClose={() => setShowDiscardConfirm(false)} | ||||||||||||||||||
| onConfirm={forceClose} | ||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | ||||||||||||||||||
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | ||||||||||||||||||
| confirmLabel={t('common:common.discard', 'Discard')} | ||||||||||||||||||
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | ||||||||||||||||||
|
Comment on lines
+247
to
+250
|
||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:common.discard', 'Discard')} | |
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | |
| title="Discard unsaved changes?" | |
| message="You have unsaved changes that will be lost." | |
| confirmLabel="Discard" | |
| cancelLabel="Keep editing" |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,7 +7,7 @@ import { | |||||||||||||||||
| Trash2, | ||||||||||||||||||
| Loader2, | ||||||||||||||||||
| } from 'lucide-react' | ||||||||||||||||||
| import { BaseModal } from '../../lib/modals' | ||||||||||||||||||
| import { BaseModal, ConfirmDialog } from '../../lib/modals' | ||||||||||||||||||
| import { | ||||||||||||||||||
| useNamespaces, | ||||||||||||||||||
| createOrUpdateResourceQuota, | ||||||||||||||||||
|
|
@@ -72,10 +72,17 @@ export function ReservationFormModal({ | |||||||||||||||||
| const [extraResources, setExtraResources] = useState<Array<{ key: string; value: string }>>([]) | ||||||||||||||||||
| const [isSaving, setIsSaving] = useState(false) | ||||||||||||||||||
| const [error, setError] = useState<string | null>(null) | ||||||||||||||||||
| const [showDiscardConfirm, setShowDiscardConfirm] = useState(false) | ||||||||||||||||||
|
|
||||||||||||||||||
| const forceClose = () => { | ||||||||||||||||||
| setShowDiscardConfirm(false) | ||||||||||||||||||
| onClose() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const handleClose = () => { | ||||||||||||||||||
| const hasChanges = title.trim() !== '' || description.trim() !== '' | ||||||||||||||||||
| if (hasChanges && !window.confirm(t('common:common.discardUnsavedChanges', 'Discard unsaved changes?'))) { | ||||||||||||||||||
| if (hasChanges) { | ||||||||||||||||||
| setShowDiscardConfirm(true) | ||||||||||||||||||
| return | ||||||||||||||||||
| } | ||||||||||||||||||
| onClose() | ||||||||||||||||||
|
|
@@ -218,6 +225,16 @@ export function ReservationFormModal({ | |||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
| <BaseModal isOpen={isOpen} onClose={handleClose} size="lg" closeOnBackdrop={false} closeOnEscape={true}> | ||||||||||||||||||
| <ConfirmDialog | ||||||||||||||||||
| isOpen={showDiscardConfirm} | ||||||||||||||||||
| onClose={() => setShowDiscardConfirm(false)} | ||||||||||||||||||
| onConfirm={forceClose} | ||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | ||||||||||||||||||
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | ||||||||||||||||||
| confirmLabel={t('common:common.discard', 'Discard')} | ||||||||||||||||||
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | ||||||||||||||||||
|
Comment on lines
+232
to
+235
|
||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:common.discard', 'Discard')} | |
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | |
| title={t('common:discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:discard', 'Discard')} | |
| cancelLabel={t('common:keepEditing', 'Keep editing')} |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,7 @@ | ||||||||||||||||||
| import { useState } from 'react' | ||||||||||||||||||
| import { Folder, UserPlus, Shield, X } from 'lucide-react' | ||||||||||||||||||
| import { Button } from '../ui/Button' | ||||||||||||||||||
| import { BaseModal } from '../../lib/modals' | ||||||||||||||||||
| import { BaseModal, ConfirmDialog } from '../../lib/modals' | ||||||||||||||||||
| import { api } from '../../lib/api' | ||||||||||||||||||
| import { useTranslation } from 'react-i18next' | ||||||||||||||||||
|
|
||||||||||||||||||
|
|
@@ -101,15 +101,33 @@ export function CreateNamespaceModal({ clusters, onClose, onCreated }: CreateNam | |||||||||||||||||
| g => !initialAccess.some(a => a.type === 'Group' && a.name === g) | ||||||||||||||||||
| ) | ||||||||||||||||||
|
|
||||||||||||||||||
| const [showDiscardConfirm, setShowDiscardConfirm] = useState(false) | ||||||||||||||||||
|
|
||||||||||||||||||
| const forceClose = () => { | ||||||||||||||||||
| setShowDiscardConfirm(false) | ||||||||||||||||||
| onClose() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const handleClose = () => { | ||||||||||||||||||
| if ((name.trim() !== '' || teamLabel.trim() !== '') && !window.confirm(t('common:common.discardUnsavedChanges', 'Discard unsaved changes?'))) { | ||||||||||||||||||
| if (name.trim() !== '' || teamLabel.trim() !== '') { | ||||||||||||||||||
| setShowDiscardConfirm(true) | ||||||||||||||||||
| return | ||||||||||||||||||
| } | ||||||||||||||||||
| onClose() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
| <BaseModal isOpen={true} onClose={handleClose} size="lg" closeOnBackdrop={false} closeOnEscape={true}> | ||||||||||||||||||
| <ConfirmDialog | ||||||||||||||||||
| isOpen={showDiscardConfirm} | ||||||||||||||||||
| onClose={() => setShowDiscardConfirm(false)} | ||||||||||||||||||
| onConfirm={forceClose} | ||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | ||||||||||||||||||
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | ||||||||||||||||||
| confirmLabel={t('common:common.discard', 'Discard')} | ||||||||||||||||||
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | ||||||||||||||||||
|
Comment on lines
+125
to
+128
|
||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:common.discard', 'Discard')} | |
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | |
| title={t('common:discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:discard', 'Discard')} | |
| cancelLabel={t('common:keepEditing', 'Keep editing')} |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,7 @@ | ||||||||||||||||||
| import { useState } from 'react' | ||||||||||||||||||
| import { Shield } from 'lucide-react' | ||||||||||||||||||
| import { Button } from '../ui/Button' | ||||||||||||||||||
| import { BaseModal } from '../../lib/modals' | ||||||||||||||||||
| import { BaseModal, ConfirmDialog } from '../../lib/modals' | ||||||||||||||||||
| import { api } from '../../lib/api' | ||||||||||||||||||
| import { useTranslation } from 'react-i18next' | ||||||||||||||||||
| import type { NamespaceDetails, NamespaceAccessEntry } from './types' | ||||||||||||||||||
|
|
@@ -88,15 +88,33 @@ export function GrantAccessModal({ namespace, existingAccess, onClose, onGranted | |||||||||||||||||
| setShowDropdown(false) | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const [showDiscardConfirm, setShowDiscardConfirm] = useState(false) | ||||||||||||||||||
|
|
||||||||||||||||||
| const forceClose = () => { | ||||||||||||||||||
| setShowDiscardConfirm(false) | ||||||||||||||||||
| onClose() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| const handleClose = () => { | ||||||||||||||||||
| if (subjectName.trim() !== '' && !window.confirm(t('common:common.discardUnsavedChanges', 'Discard unsaved changes?'))) { | ||||||||||||||||||
| if (subjectName.trim() !== '') { | ||||||||||||||||||
| setShowDiscardConfirm(true) | ||||||||||||||||||
| return | ||||||||||||||||||
| } | ||||||||||||||||||
| onClose() | ||||||||||||||||||
| } | ||||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
| <BaseModal isOpen={true} onClose={handleClose} size="md" closeOnBackdrop={false} closeOnEscape={true}> | ||||||||||||||||||
| <ConfirmDialog | ||||||||||||||||||
| isOpen={showDiscardConfirm} | ||||||||||||||||||
| onClose={() => setShowDiscardConfirm(false)} | ||||||||||||||||||
| onConfirm={forceClose} | ||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | ||||||||||||||||||
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | ||||||||||||||||||
| confirmLabel={t('common:common.discard', 'Discard')} | ||||||||||||||||||
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | ||||||||||||||||||
|
Comment on lines
+112
to
+115
|
||||||||||||||||||
| title={t('common:common.discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:common.discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:common.discard', 'Discard')} | |
| cancelLabel={t('common:common.keepEditing', 'Keep editing')} | |
| title={t('common:discardUnsavedChanges', 'Discard unsaved changes?')} | |
| message={t('common:discardUnsavedChangesMessage', 'You have unsaved changes that will be lost.')} | |
| confirmLabel={t('common:discard', 'Discard')} | |
| cancelLabel={t('common:keepEditing', 'Keep editing')} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new
no-restricted-globalsrule will blockconfirm()/alert()/prompt()as bare globals, but it will not catch the pattern previously used in this codebase (window.confirm(...)). To actually prevent regressions, add a restriction forwindow.confirm/alert/promptas well (e.g.,no-restricted-propertiesforwindow/globalThis, or ano-restricted-syntaxselector targetingMemberExpression[property.name="confirm"]).