This is an automated email from the ASF dual-hosted git repository.

maximebeauchemin pushed a commit to branch fire-alert
in repository https://gitbox.apache.org/repos/asf/superset.git

commit ad23b18b1024b6926fb281ea55ebe46a3597e06e
Author: Maxime Beauchemin <[email protected]>
AuthorDate: Wed Sep 10 00:26:03 2025 -0700

    refactor: Migrate key AlertReportModal fields to ModalFormField pattern
    
    Migrate critical form fields in AlertReportModal to use the modern 
ModalFormField pattern
    for consistent styling and dynamic validation feedback:
    
    - Database field (Sections.Content validation)
    - SQL Query field (Sections.Content validation)
    - Trigger Alert If... condition (Sections.Alert validation)
    - Value threshold (Sections.Alert validation)
    - Timezone (Sections.Schedule validation)
    - Log retention (Sections.Schedule validation)
    - Working timeout/Grace period (Sections.Schedule validation)
    
    Benefits:
    - Dynamic asterisk coloring: subtle by default, red on validation errors
    - Consistent form field styling across all Superset modals
    - Better accessibility and user experience
    - Proper tooltip integration in ModalFormField
    - Cleaner code by removing custom StyledInputContainer usage
    - Removed unused imports and CSS for cleaner codebase
    
    This continues the migration from custom form styling to the
    standard ModalFormField pattern used by Chart/Dashboard properties modals.
    
    🤖 Generated with [Claude Code](https://claude.ai/code)
    
    Co-Authored-By: Claude <[email protected]>
---
 .../src/features/alerts/AlertReportModal.tsx       | 283 +++++++++++----------
 1 file changed, 143 insertions(+), 140 deletions(-)

diff --git a/superset-frontend/src/features/alerts/AlertReportModal.tsx 
b/superset-frontend/src/features/alerts/AlertReportModal.tsx
index ace9501303..79dc5d5a02 100644
--- a/superset-frontend/src/features/alerts/AlertReportModal.tsx
+++ b/superset-frontend/src/features/alerts/AlertReportModal.tsx
@@ -32,7 +32,6 @@ import {
   FeatureFlag,
   styled,
   SupersetClient,
-  SupersetTheme,
   t,
   VizType,
   useTheme,
@@ -44,7 +43,6 @@ import {
   Checkbox,
   Collapse,
   CollapseLabelInModal,
-  InfoTooltip,
   Input,
   InputNumber,
   Select,
@@ -300,10 +298,6 @@ const StyledNotificationMethodWrapper = styled.div`
   }
 `;
 
-const inputSpacer = (theme: SupersetTheme) => css`
-  margin-right: ${theme.sizeUnit * 3}px;
-`;
-
 type NotificationAddStatus = 'active' | 'disabled' | 'hidden';
 
 interface NotificationMethodAddProps {
@@ -1499,40 +1493,46 @@ const AlertReportModal: 
FunctionComponent<AlertReportModalProps> = ({
                     ),
                     children: (
                       <div>
-                        <StyledInputContainer>
-                          <div className="control-label">
-                            {t('Database')}
-                            <span className="required">*</span>
-                          </div>
-                          <div className="input-container">
-                            <AsyncSelect
-                              ariaLabel={t('Database')}
-                              name="source"
-                              placeholder={t('Select database')}
-                              value={
-                                currentAlert?.database?.label &&
-                                currentAlert?.database?.value
-                                  ? {
-                                      value: currentAlert.database.value,
-                                      label: currentAlert.database.label,
-                                    }
-                                  : undefined
-                              }
-                              options={loadSourceOptions}
-                              onChange={onSourceChange}
-                            />
-                          </div>
-                        </StyledInputContainer>
-                        <StyledInputContainer>
-                          <div className="control-label">
-                            {t('SQL Query')}
-                            <InfoTooltip
-                              tooltip={t(
-                                'The result of this query must be a value 
capable of numeric interpretation e.g. 1, 1.0, or "1" (compatible with 
Python\'s float() function).',
-                              )}
-                            />
-                            <span className="required">*</span>
-                          </div>
+                        <ModalFormField
+                          label={t('Database')}
+                          required
+                          error={
+                            validationStatus[Sections.Content]?.hasErrors &&
+                            !currentAlert?.database
+                              ? t('Database is required')
+                              : undefined
+                          }
+                        >
+                          <AsyncSelect
+                            ariaLabel={t('Database')}
+                            name="source"
+                            placeholder={t('Select database')}
+                            value={
+                              currentAlert?.database?.label &&
+                              currentAlert?.database?.value
+                                ? {
+                                    value: currentAlert.database.value,
+                                    label: currentAlert.database.label,
+                                  }
+                                : undefined
+                            }
+                            options={loadSourceOptions}
+                            onChange={onSourceChange}
+                          />
+                        </ModalFormField>
+                        <ModalFormField
+                          label={t('SQL Query')}
+                          required
+                          tooltip={t(
+                            'The result of this query must be a value capable 
of numeric interpretation e.g. 1, 1.0, or "1" (compatible with Python\'s 
float() function).',
+                          )}
+                          error={
+                            validationStatus[Sections.Content]?.hasErrors &&
+                            !resource?.sql
+                              ? t('SQL Query is required')
+                              : undefined
+                          }
+                        >
                           <TextAreaControl
                             name="sql"
                             language="sql"
@@ -1544,57 +1544,60 @@ const AlertReportModal: 
FunctionComponent<AlertReportModalProps> = ({
                             initialValue={resource?.sql}
                             key={currentAlert?.id}
                           />
-                        </StyledInputContainer>
+                        </ModalFormField>
                         <div
                           className="inline-container wrap"
                           css={css`
                             gap: ${theme.sizeUnit}px;
                           `}
                         >
-                          <StyledInputContainer css={noMarginBottom}>
-                            <div className="control-label" css={inputSpacer}>
-                              {t('Trigger Alert If...')}
-                              <span className="required">*</span>
-                            </div>
-                            <div className="input-container">
-                              <Select
-                                ariaLabel={t('Condition')}
-                                onChange={onConditionChange}
-                                placeholder={t('Condition')}
-                                value={
-                                  currentAlert?.validator_config_json?.op ||
-                                  undefined
-                                }
-                                options={CONDITIONS}
-                              />
-                            </div>
-                          </StyledInputContainer>
-                          <StyledInputContainer css={noMarginBottom}>
-                            <div className="control-label">
-                              {t('Value')}{' '}
-                              {!conditionNotNull && (
-                                <span className="required">*</span>
-                              )}
-                            </div>
-                            <div className="input-container">
-                              <InputNumber
-                                disabled={conditionNotNull}
-                                type="number"
-                                name="threshold"
-                                value={
-                                  currentAlert?.validator_config_json
-                                    ?.threshold !== undefined &&
-                                  !conditionNotNull
-                                    ? currentAlert.validator_config_json
-                                        .threshold
-                                    : ''
-                                }
-                                min={0}
-                                placeholder={t('Value')}
-                                onChange={onThresholdChange}
-                              />
-                            </div>
-                          </StyledInputContainer>
+                          <ModalFormField
+                            label={t('Trigger Alert If...')}
+                            required
+                            error={
+                              validationStatus[Sections.Alert]?.hasErrors &&
+                              !currentAlert?.validator_config_json?.op
+                                ? t('Condition is required')
+                                : undefined
+                            }
+                          >
+                            <Select
+                              ariaLabel={t('Condition')}
+                              onChange={onConditionChange}
+                              placeholder={t('Condition')}
+                              value={
+                                currentAlert?.validator_config_json?.op ||
+                                undefined
+                              }
+                              options={CONDITIONS}
+                            />
+                          </ModalFormField>
+                          <ModalFormField
+                            label={t('Value')}
+                            required={!conditionNotNull}
+                            error={
+                              validationStatus[Sections.Alert]?.hasErrors &&
+                              !conditionNotNull &&
+                              !currentAlert?.validator_config_json?.threshold
+                                ? t('Value is required')
+                                : undefined
+                            }
+                          >
+                            <InputNumber
+                              disabled={conditionNotNull}
+                              type="number"
+                              name="threshold"
+                              value={
+                                currentAlert?.validator_config_json
+                                  ?.threshold !== undefined && 
!conditionNotNull
+                                  ? 
currentAlert.validator_config_json.threshold
+                                  : ''
+                              }
+                              min={0}
+                              placeholder={t('Value')}
+                              onChange={onThresholdChange}
+                            />
+                          </ModalFormField>
                         </div>
                       </div>
                     ),
@@ -1791,66 +1794,66 @@ const AlertReportModal: 
FunctionComponent<AlertReportModalProps> = ({
                     value={currentAlert?.crontab || ''}
                     onChange={newVal => updateAlertState('crontab', newVal)}
                   />
-                  <StyledInputContainer>
-                    <div className="control-label">
-                      {t('Timezone')} <span className="required">*</span>
-                    </div>
+                  <ModalFormField
+                    label={t('Timezone')}
+                    required
+                    error={
+                      validationStatus[Sections.Schedule]?.hasErrors &&
+                      !currentAlert?.timezone
+                        ? t('Timezone is required')
+                        : undefined
+                    }
+                  >
                     <TimezoneSelector
                       onTimezoneChange={onTimezoneChange}
                       timezone={currentAlert?.timezone}
                       minWidth="100%"
                     />
-                  </StyledInputContainer>
-                  <StyledInputContainer>
-                    <div className="control-label">
-                      {t('Log retention')}
-                      <span className="required">*</span>
-                    </div>
-                    <div className="input-container">
-                      <Select
-                        ariaLabel={t('Log retention')}
-                        placeholder={t('Log retention')}
-                        onChange={onLogRetentionChange}
-                        value={currentAlert?.log_retention}
-                        options={RETENTION_OPTIONS}
-                        sortComparator={propertyComparator('value')}
-                      />
-                    </div>
-                  </StyledInputContainer>
-                  <StyledInputContainer css={noMarginBottom}>
-                    {isReport ? (
-                      <>
-                        <div className="control-label">
-                          {t('Working timeout')}
-                          <span className="required">*</span>
-                        </div>
-                        <div className="input-container">
-                          <NumberInput
-                            min={1}
-                            name="working_timeout"
-                            value={currentAlert?.working_timeout || ''}
-                            placeholder={t('Time in seconds')}
-                            onChange={onTimeoutVerifyChange}
-                            timeUnit={t('seconds')}
-                          />
-                        </div>
-                      </>
-                    ) : (
-                      <>
-                        <div className="control-label">{t('Grace 
period')}</div>
-                        <div className="input-container">
-                          <NumberInput
-                            min={1}
-                            name="grace_period"
-                            value={currentAlert?.grace_period || ''}
-                            placeholder={t('Time in seconds')}
-                            onChange={onTimeoutVerifyChange}
-                            timeUnit={t('seconds')}
-                          />
-                        </div>
-                      </>
-                    )}
-                  </StyledInputContainer>
+                  </ModalFormField>
+                  <ModalFormField
+                    label={t('Log retention')}
+                    required
+                    error={
+                      validationStatus[Sections.Schedule]?.hasErrors &&
+                      !currentAlert?.log_retention
+                        ? t('Log retention is required')
+                        : undefined
+                    }
+                  >
+                    <Select
+                      ariaLabel={t('Log retention')}
+                      placeholder={t('Log retention')}
+                      onChange={onLogRetentionChange}
+                      value={currentAlert?.log_retention}
+                      options={RETENTION_OPTIONS}
+                      sortComparator={propertyComparator('value')}
+                    />
+                  </ModalFormField>
+                  <ModalFormField
+                    label={isReport ? t('Working timeout') : t('Grace period')}
+                    required={isReport}
+                    error={
+                      validationStatus[Sections.Schedule]?.hasErrors &&
+                      isReport &&
+                      !currentAlert?.working_timeout
+                        ? t('Working timeout is required')
+                        : undefined
+                    }
+                    bottomSpacing={false}
+                  >
+                    <NumberInput
+                      min={1}
+                      name={isReport ? 'working_timeout' : 'grace_period'}
+                      value={
+                        isReport
+                          ? currentAlert?.working_timeout || ''
+                          : currentAlert?.grace_period || ''
+                      }
+                      placeholder={t('Time in seconds')}
+                      onChange={onTimeoutVerifyChange}
+                      timeUnit={t('seconds')}
+                    />
+                  </ModalFormField>
                 </>
               ),
             },

Reply via email to