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


##########
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:
   Probably, would be nice to force this in this context, though the parent 
component can just pass the prop too. That may be a thing I didn't fully sort 
out here -> making sure close is only available where it make sense. Might be 
worth a sweep reviewing everywhere `ErrorAlert` is use and double checking that 
we set this right in that context.



-- 
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