mistercrunch commented on code in PR #31858:
URL: https://github.com/apache/superset/pull/31858#discussion_r1917397784
##########
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:
Ok i added a line of logic to handle this
--
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]