geido commented on code in PR #31858:
URL: https://github.com/apache/superset/pull/31858#discussion_r1916998728


##########
superset-frontend/src/components/ErrorMessage/ErrorAlert.tsx:
##########
@@ -16,250 +16,128 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { useState, ReactNode } from 'react';
-import {
-  ErrorLevel,
-  ErrorSource,
-  styled,
-  useTheme,
-  t,
-} from '@superset-ui/core';
-import { noOp } from 'src/utils/common';
-import Modal from 'src/components/Modal';
-import Button from 'src/components/Button';
-import { isCurrentUserBot } from 'src/utils/isBot';
-
-import Icons from 'src/components/Icons';
-import CopyToClipboard from '../CopyToClipboard';
-
-const ErrorAlertDiv = styled.div<{ level: ErrorLevel }>`
-  align-items: center;
-  background-color: ${({ level, theme }) => theme.colors[level].light2};
-  border-radius: ${({ theme }) => theme.borderRadius}px;
-  border: 1px solid ${({ level, theme }) => theme.colors[level].base};
-  color: ${({ level, theme }) => theme.colors[level].dark2};
-  padding: ${({ theme }) => 2 * theme.gridUnit}px;
-  width: 100%;
-
-  .top-row {
-    display: flex;
-    justify-content: space-between;
-  }
-
-  .error-body {
-    padding-top: ${({ theme }) => theme.gridUnit}px;
-    padding-left: ${({ theme }) => 8 * theme.gridUnit}px;
-  }
-
-  .icon {
-    margin-right: ${({ theme }) => 2 * theme.gridUnit}px;
-  }
-
-  .link {
-    color: ${({ level, theme }) => theme.colors[level].dark2};
-    text-decoration: underline;
-    &:focus-visible {
-      border: 1px solid ${({ theme }) => theme.colors.primary.base};
-      padding: ${({ theme }) => theme.gridUnit / 2}px;
-      margin: -${({ theme }) => theme.gridUnit / 2 + 1}px;
-      border-radius: ${({ theme }) => theme.borderRadius}px;
-  }
-`;
-
-const ErrorModal = styled(Modal)<{ level: ErrorLevel }>`
-  color: ${({ level, theme }) => theme.colors[level].dark2};
-  overflow-wrap: break-word;
-
-  .antd5-modal-header {
-    background-color: ${({ level, theme }) => theme.colors[level].light2};
-    padding: ${({ theme }) => 4 * theme.gridUnit}px;
-  }
-
-  .icon {
-    margin-right: ${({ theme }) => 2 * theme.gridUnit}px;
-  }
-
-  .header {
-    display: flex;
-    align-items: center;
-    font-size: ${({ theme }) => theme.typography.sizes.l}px;
-  }
-`;
-
-const LeftSideContent = styled.div`
-  align-items: center;
-  display: flex;
-`;
-
-interface ErrorAlertProps {
-  body: ReactNode;
-  copyText?: string;
-  level: ErrorLevel;
-  source?: ErrorSource;
-  subtitle: ReactNode;
-  title: ReactNode;
-  description?: string;
+import { useState } from 'react';
+import { Modal, Tooltip } from 'antd';
+import { ExclamationCircleOutlined, WarningOutlined } from '@ant-design/icons';
+import Alert from 'src/components/Alert';
+import { t, useTheme } from '@superset-ui/core';
+
+export interface ErrorAlertProps {
+  errorType?: string; // Strong text on the first line
+  message: React.ReactNode | string; // Text shown on the first line
+  type?: 'warning' | 'error' | 'info'; // Allows only 'warning' or 'error'
+  description?: React.ReactNode; // Text shown under the first line, not 
collapsible
+  descriptionDetails?: React.ReactNode | string; // Text shown under the first 
line, collapsible
+  descriptionDetailsCollapsed?: boolean; // Hides the collapsible section 
unless "Show more" is clicked, default true
+  descriptionPre?: boolean; // Uses pre-style to break lines, default true
+  compact?: boolean; // Shows the error icon with tooltip and modal, default 
false
+  children?: React.ReactNode; // Additional content to show in the modal
+  closable?: boolean; // Show close button, default true
+  showIcon?: boolean; // Show icon, default true
 }
 
-export default function ErrorAlert({
-  body,
-  copyText,
-  level = 'error',
-  source = 'dashboard',
-  subtitle,
-  title,
+const ErrorAlert: React.FC<ErrorAlertProps> = ({
+  errorType = t('Error'),
+  message,
+  type = 'error',
   description,
-}: ErrorAlertProps) {
-  const theme = useTheme();
-
-  const [isModalOpen, setIsModalOpen] = useState(false);
-  const [isBodyExpanded, setIsBodyExpanded] = useState(isCurrentUserBot());
+  descriptionDetails,
+  descriptionDetailsCollapsed = true,
+  descriptionPre = true,
+  compact = false,
+  children,
+  closable = true,
+  showIcon = true,
+}) => {
+  const [isDescriptionVisible, setIsDescriptionVisible] = useState(
+    !descriptionDetailsCollapsed,
+  );
+  const [showModal, setShowModal] = useState(false);
 
-  const isExpandable =
-    isCurrentUserBot() || ['explore', 'sqllab'].includes(source);
-  const iconColor = theme.colors[level].base;
+  const toggleDescription = () => {
+    setIsDescriptionVisible(!isDescriptionVisible);
+  };
 
-  return (
-    <ErrorAlertDiv level={level} role="alert">
-      <div className="top-row">
-        <LeftSideContent>
-          {level === 'error' ? (
-            <Icons.ErrorSolid className="icon" iconColor={iconColor} />
-          ) : (
-            <Icons.WarningSolid className="icon" iconColor={iconColor} />
+  const theme = useTheme();
+  const renderTrigger = () => {
+    const icon =
+      type === 'warning' ? <WarningOutlined /> : <ExclamationCircleOutlined />;
+    const color =
+      type === 'warning' ? theme.colors.warning.base : theme.colors.error.base;
+    return (
+      <div style={{ cursor: 'pointer' }}>
+        <span style={{ color }}>{icon} </span>
+        {errorType}
+      </div>
+    );
+  };
+  const preStyle = {
+    whiteSpace: 'pre-wrap',
+    // fontFamily: theme.antd.fontFamilyCode,
+  };
+  const renderDescription = () => (
+    <div>
+      {description && (
+        <p style={descriptionPre ? preStyle : {}} data-testid="description">
+          {description}
+        </p>
+      )}
+      {descriptionDetails && (
+        <div>
+          {isDescriptionVisible && (
+            <p style={descriptionPre ? preStyle : {}}>{descriptionDetails}</p>
           )}
-          <strong>{title}</strong>
-        </LeftSideContent>
-        {!isExpandable && !description && (
           <span
             role="button"
             tabIndex={0}
-            className="link"
-            onClick={() => setIsModalOpen(true)}
-            onKeyDown={event => {
-              if (event.key === 'Enter') {
-                setIsModalOpen(true);
-              }
-            }}
+            onClick={toggleDescription}
+            style={{ textDecoration: 'underline', cursor: 'pointer' }}
           >
-            {t('See more')}
+            {isDescriptionVisible ? t('See less') : t('See more')}
           </span>
-        )}
-      </div>
-      {description && (
-        <div className="error-body">
-          <p>{description}</p>
-          {!isExpandable && (
-            <span
-              role="button"
-              tabIndex={0}
-              className="link"
-              onClick={() => setIsModalOpen(true)}
-              onKeyDown={event => {
-                if (event.key === 'Enter') {
-                  setIsModalOpen(true);
-                }
-              }}
-            >
-              {t('See more')}
-            </span>
-          )}
         </div>
       )}
-      {isExpandable ? (
-        <div className="error-body">
-          <p>{subtitle}</p>
-          {body && (
-            <>
-              {!isBodyExpanded && (
-                <span
-                  role="button"
-                  tabIndex={0}
-                  className="link"
-                  onClick={() => setIsBodyExpanded(true)}
-                  onKeyDown={event => {
-                    if (event.key === 'Enter') {
-                      setIsBodyExpanded(true);
-                    }
-                  }}
-                >
-                  {t('See more')}
-                </span>
-              )}
-              {isBodyExpanded && (
-                <>
-                  <br />
-                  {body}
-                  <span
-                    role="button"
-                    tabIndex={0}
-                    className="link"
-                    onClick={() => setIsBodyExpanded(false)}
-                    onKeyDown={event => {
-                      if (event.key === 'Enter') {
-                        setIsBodyExpanded(false);
-                      }
-                    }}
-                  >
-                    {t('See less')}
-                  </span>
-                </>
-              )}
-            </>
-          )}
-        </div>
-      ) : (
-        <ErrorModal
-          level={level}
-          show={isModalOpen}
-          onHide={() => setIsModalOpen(false)}
-          destroyOnClose
-          title={
-            <div className="header">
-              {level === 'error' ? (
-                <Icons.ErrorSolid className="icon" iconColor={iconColor} />
-              ) : (
-                <Icons.WarningSolid className="icon" iconColor={iconColor} />
-              )}
-              <div className="title">{title}</div>
-            </div>
-          }
-          footer={
-            <>
-              {copyText && (
-                <CopyToClipboard
-                  text={copyText}
-                  shouldShowText={false}
-                  wrapped={false}
-                  copyNode={<Button onClick={noOp}>{t('Copy 
message')}</Button>}
-                />
-              )}
-              <Button
-                cta
-                buttonStyle="primary"
-                onClick={() => setIsModalOpen(false)}
-                tabIndex={0}
-                onKeyDown={event => {
-                  if (event.key === 'Enter') {
-                    setIsModalOpen(false);
-                  }
-                }}
-              >
-                {t('Close')}
-              </Button>
-            </>
-          }
-        >
-          <>
-            <p>{subtitle}</p>
-            {/* This break was in the original design of the modal but
-            the spacing looks really off if there is only
-            subtitle or a body */}
-            {subtitle && body && <br />}
-            {body}
-          </>
-        </ErrorModal>
+    </div>
+  );
+
+  const renderAlert = () => (
+    <Alert
+      description={renderDescription()}
+      type={type}
+      showIcon
+      closable={closable}
+    >
+      <strong>{errorType}</strong>
+      {message && (
+        <>
+          : <span>{message}</span>
+        </>
       )}
-    </ErrorAlertDiv>
+    </Alert>
   );
-}
+
+  if (compact) {
+    return (
+      <>
+        <Tooltip title={`${errorType}: ${message}`}>
+          <span role="button" onClick={() => setShowModal(true)} tabIndex={0}>
+            {renderTrigger()}
+          </span>
+        </Tooltip>
+        <Modal

Review Comment:
   Should we remove the ability to close the alert within a Modal? It seems odd 
to be able to close an alert which is within a Modal container.
   
   <img width="760" alt="Screenshot 2025-01-15 at 17 39 58" 
src="https://github.com/user-attachments/assets/faeba9a9-c931-4a69-8a56-07063ad0d577";
 />
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to