mirror of
https://github.com/apache/superset.git
synced 2026-04-28 04:25:07 +00:00
refactor(Icons): Replaces custom icons with Ant Design 5 icons (#32112)
Replace custom icons with Ant Design 5 icons to standardize the icon
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useTheme, t } from '@superset-ui/core';
|
||||
import { t } from '@superset-ui/core';
|
||||
import { Dropdown } from 'src/components/Dropdown';
|
||||
import { Menu } from 'src/components/Menu';
|
||||
import Icons from 'src/components/Icons';
|
||||
@@ -64,7 +64,6 @@ const QueryLimitSelect = ({
|
||||
maxRow,
|
||||
defaultQueryLimit,
|
||||
}: QueryLimitSelectProps) => {
|
||||
const theme = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const queryEditor = useQueryEditor(queryEditorId, ['id', 'queryLimit']);
|
||||
@@ -82,7 +81,7 @@ const QueryLimitSelect = ({
|
||||
<span className="limitDropdown">
|
||||
{convertToNumWithSpaces(queryLimit)}
|
||||
</span>
|
||||
<Icons.TriangleDown iconColor={theme.colors.grayscale.base} />
|
||||
<Icons.CaretDownOutlined iconSize="m" />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ import ModalTrigger from 'src/components/ModalTrigger';
|
||||
import { UserWithPermissionsAndRoles as User } from 'src/types/bootstrapTypes';
|
||||
import ResultSet from '../ResultSet';
|
||||
import HighlightedSql from '../HighlightedSql';
|
||||
import { StaticPosition, verticalAlign, StyledTooltip } from './styles';
|
||||
import { StaticPosition, StyledTooltip } from './styles';
|
||||
|
||||
interface QueryTableQuery
|
||||
extends Omit<
|
||||
@@ -188,7 +188,10 @@ const QueryTable = ({
|
||||
timed_out: {
|
||||
config: {
|
||||
icon: (
|
||||
<Icons.Clock iconColor={theme.colors.error.base} iconSize="m" />
|
||||
<Icons.ClockCircleOutlined
|
||||
iconColor={theme.colors.error.base}
|
||||
iconSize="m"
|
||||
/>
|
||||
),
|
||||
label: t('Offline'),
|
||||
},
|
||||
@@ -277,9 +280,7 @@ const QueryTable = ({
|
||||
buttonStyle="link"
|
||||
onClick={() => openQuery(q.queryId)}
|
||||
>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-external-link m-r-3" />
|
||||
<Icons.Full iconSize="m" iconColor={theme.colors.primary.dark1} />
|
||||
{t('Edit')}
|
||||
</Button>
|
||||
);
|
||||
@@ -344,7 +345,7 @@ const QueryTable = ({
|
||||
placement="top"
|
||||
className="pointer"
|
||||
>
|
||||
<Icons.Edit iconSize="xl" />
|
||||
<Icons.EditOutlined iconSize="l" />
|
||||
</StyledTooltip>
|
||||
<StyledTooltip
|
||||
onClick={() => openQueryInNewTab(query)}
|
||||
@@ -352,7 +353,7 @@ const QueryTable = ({
|
||||
placement="top"
|
||||
className="pointer"
|
||||
>
|
||||
<Icons.PlusCircleOutlined iconSize="xl" css={verticalAlign} />
|
||||
<Icons.PlusCircleOutlined iconSize="l" />
|
||||
</StyledTooltip>
|
||||
{q.id !== latestQueryId && (
|
||||
<StyledTooltip
|
||||
@@ -360,7 +361,7 @@ const QueryTable = ({
|
||||
onClick={() => dispatch(removeQuery(query))}
|
||||
className="pointer"
|
||||
>
|
||||
<Icons.Trash iconSize="xl" />
|
||||
<Icons.DeleteOutlined iconSize="l" />
|
||||
</StyledTooltip>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -150,6 +150,15 @@ const ResultSetButtons = styled.div`
|
||||
padding-right: ${({ theme }) => 2 * theme.gridUnit}px;
|
||||
`;
|
||||
|
||||
const copyButtonStyles = css`
|
||||
&:hover {
|
||||
text-decoration: unset;
|
||||
}
|
||||
span > :first-of-type {
|
||||
margin: 0px;
|
||||
}
|
||||
`;
|
||||
|
||||
const ROWS_CHIP_WIDTH = 100;
|
||||
const GAP = 8;
|
||||
|
||||
@@ -342,6 +351,7 @@ const ResultSet = ({
|
||||
)}
|
||||
{csv && canExportData && (
|
||||
<Button
|
||||
css={copyButtonStyles}
|
||||
buttonSize="small"
|
||||
href={getExportCsvUrl(query.id)}
|
||||
data-test="export-csv-button"
|
||||
@@ -361,9 +371,11 @@ const ResultSet = ({
|
||||
}
|
||||
}}
|
||||
>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-file-text-o" /> {t('Download to CSV')}
|
||||
<Icons.DownloadOutlined
|
||||
iconSize="m"
|
||||
iconColor={theme.colors.primary.dark2}
|
||||
/>{' '}
|
||||
{t('Download to CSV')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
@@ -373,12 +385,15 @@ const ResultSet = ({
|
||||
wrapped={false}
|
||||
copyNode={
|
||||
<Button
|
||||
css={copyButtonStyles}
|
||||
buttonSize="small"
|
||||
data-test="copy-to-clipboard-button"
|
||||
>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-clipboard" /> {t('Copy to Clipboard')}
|
||||
<Icons.CopyOutlined
|
||||
iconSize="s"
|
||||
iconColor={theme.colors.primary.dark2}
|
||||
/>{' '}
|
||||
{t('Copy to Clipboard')}
|
||||
</Button>
|
||||
}
|
||||
hideTooltip
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
import { useMemo, FC, ReactElement } from 'react';
|
||||
|
||||
import { t, styled, useTheme } from '@superset-ui/core';
|
||||
import { t, styled, useTheme, SupersetTheme } from '@superset-ui/core';
|
||||
|
||||
import Button from 'src/components/Button';
|
||||
import Icons from 'src/components/Icons';
|
||||
@@ -44,13 +44,13 @@ export interface RunQueryActionButtonProps {
|
||||
const buildText = (
|
||||
shouldShowStopButton: boolean,
|
||||
selectedText: string | undefined,
|
||||
theme: SupersetTheme,
|
||||
): string | JSX.Element => {
|
||||
if (shouldShowStopButton) {
|
||||
return (
|
||||
<>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-stop" /> {t('Stop')}
|
||||
<Icons.Square iconSize="xs" iconColor={theme.colors.primary.light5} />
|
||||
{t('Stop')}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -150,13 +150,12 @@ const RunQueryActionButton = ({
|
||||
? {
|
||||
overlay: overlayCreateAsMenu,
|
||||
icon: (
|
||||
<Icons.CaretDown
|
||||
<Icons.DownOutlined
|
||||
iconColor={
|
||||
isDisabled
|
||||
? theme.colors.grayscale.base
|
||||
: theme.colors.grayscale.light5
|
||||
}
|
||||
name="caret-down"
|
||||
/>
|
||||
),
|
||||
trigger: 'click',
|
||||
@@ -165,7 +164,7 @@ const RunQueryActionButton = ({
|
||||
buttonStyle: shouldShowStopBtn ? 'warning' : 'primary',
|
||||
})}
|
||||
>
|
||||
{buildText(shouldShowStopBtn, selectedText)}
|
||||
{buildText(shouldShowStopBtn, selectedText, theme)}
|
||||
</ButtonComponent>
|
||||
</StyledButton>
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ describe('SaveDatasetActionButton', () => {
|
||||
);
|
||||
|
||||
const saveBtn = screen.getByRole('button', { name: /save/i });
|
||||
const caretBtn = screen.getByRole('button', { name: /caret-down/i });
|
||||
const caretBtn = screen.getByRole('button', { name: /down/i });
|
||||
|
||||
expect(
|
||||
await screen.findByRole('button', { name: /save/i }),
|
||||
@@ -53,9 +53,9 @@ describe('SaveDatasetActionButton', () => {
|
||||
/>,
|
||||
);
|
||||
|
||||
const caretBtn = screen.getByRole('button', { name: /caret-down/i });
|
||||
const caretBtn = screen.getByRole('button', { name: /down/i });
|
||||
expect(
|
||||
await screen.findByRole('button', { name: /caret-down/i }),
|
||||
await screen.findByRole('button', { name: /down/i }),
|
||||
).toBeInTheDocument();
|
||||
userEvent.click(caretBtn);
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@ const SaveDatasetActionButton = ({
|
||||
onClick={() => setShowSave(true)}
|
||||
dropdownRender={() => overlayMenu}
|
||||
icon={
|
||||
<Icons.CaretDown
|
||||
iconColor={theme.colors.grayscale.light5}
|
||||
name="caret-down"
|
||||
<Icons.DownOutlined
|
||||
iconSize="xs"
|
||||
iconColor={theme.colors.primary.dark2}
|
||||
/>
|
||||
}
|
||||
trigger={['click']}
|
||||
|
||||
@@ -179,7 +179,7 @@ describe('SavedQuery', () => {
|
||||
|
||||
await waitFor(() => {
|
||||
const saveBtn = screen.getByRole('button', { name: /save/i });
|
||||
const caretBtn = screen.getByRole('button', { name: /caret-down/i });
|
||||
const caretBtn = screen.getByRole('button', { name: /down/i });
|
||||
|
||||
expect(saveBtn).toBeVisible();
|
||||
expect(caretBtn).toBeVisible();
|
||||
@@ -192,7 +192,9 @@ describe('SavedQuery', () => {
|
||||
store: mockStore(mockState),
|
||||
});
|
||||
|
||||
const caretBtn = await screen.findByRole('button', { name: /caret-down/i });
|
||||
const caretBtn = await screen.findByRole('button', {
|
||||
name: /down/i,
|
||||
});
|
||||
userEvent.click(caretBtn);
|
||||
|
||||
const saveDatasetMenuItem = await screen.findByText(/save dataset/i);
|
||||
@@ -209,7 +211,9 @@ describe('SavedQuery', () => {
|
||||
store: mockStore(mockState),
|
||||
});
|
||||
|
||||
const caretBtn = await screen.findByRole('button', { name: /caret-down/i });
|
||||
const caretBtn = await screen.findByRole('button', {
|
||||
name: /down/i,
|
||||
});
|
||||
userEvent.click(caretBtn);
|
||||
|
||||
const saveDatasetMenuItem = await screen.findByText(/save dataset/i);
|
||||
|
||||
@@ -57,7 +57,7 @@ export type QueryPayload = {
|
||||
} & Pick<QueryEditor, 'dbId' | 'catalog' | 'schema' | 'sql'>;
|
||||
|
||||
const Styles = styled.span`
|
||||
span[role='img'] {
|
||||
span[role='img']:not([aria-label='down']) {
|
||||
display: flex;
|
||||
margin: 0;
|
||||
color: ${({ theme }) => theme.colors.grayscale.base};
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
styled,
|
||||
t,
|
||||
useTheme,
|
||||
getClientErrorObject,
|
||||
SupersetClient,
|
||||
css,
|
||||
} from '@superset-ui/core';
|
||||
import Button from 'src/components/Button';
|
||||
import Icons from 'src/components/Icons';
|
||||
@@ -36,16 +36,6 @@ interface ShareSqlLabQueryProps {
|
||||
addDangerToast: (msg: string) => void;
|
||||
}
|
||||
|
||||
const StyledIcon = styled(Icons.Link)`
|
||||
&:first-of-type {
|
||||
margin: 0;
|
||||
display: flex;
|
||||
svg {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ShareSqlLabQuery = ({
|
||||
queryEditorId,
|
||||
addDangerToast,
|
||||
@@ -85,8 +75,19 @@ const ShareSqlLabQuery = ({
|
||||
const buildButton = () => {
|
||||
const tooltip = t('Copy query link to your clipboard');
|
||||
return (
|
||||
<Button buttonSize="small" tooltip={tooltip}>
|
||||
<StyledIcon iconColor={theme.colors.primary.base} iconSize="xl" />
|
||||
<Button
|
||||
buttonSize="small"
|
||||
tooltip={tooltip}
|
||||
css={css`
|
||||
span > :first-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
`}
|
||||
>
|
||||
<Icons.LinkOutlined
|
||||
iconColor={theme.colors.primary.base}
|
||||
iconSize="m"
|
||||
/>
|
||||
{t('Copy link')}
|
||||
</Button>
|
||||
);
|
||||
|
||||
@@ -21,6 +21,7 @@ import sql from 'react-syntax-highlighter/dist/cjs/languages/hljs/sql';
|
||||
import github from 'react-syntax-highlighter/dist/cjs/styles/hljs/github';
|
||||
import { IconTooltip } from 'src/components/IconTooltip';
|
||||
import ModalTrigger from 'src/components/ModalTrigger';
|
||||
import Icons from 'src/components/Icons';
|
||||
|
||||
SyntaxHighlighter.registerLanguage('sql', sql);
|
||||
|
||||
@@ -42,10 +43,9 @@ export default function ShowSQL({
|
||||
modalTitle={title}
|
||||
triggerNode={
|
||||
triggerNode || (
|
||||
<IconTooltip
|
||||
className="fa fa-eye pull-left m-l-2"
|
||||
tooltip={tooltipText}
|
||||
/>
|
||||
<IconTooltip className="pull-left m-l-2" tooltip={tooltipText}>
|
||||
<Icons.EyeOutlined iconSize="s" />
|
||||
</IconTooltip>
|
||||
)
|
||||
}
|
||||
modalBody={
|
||||
|
||||
@@ -20,7 +20,7 @@ import { createRef, useCallback, useMemo } from 'react';
|
||||
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
|
||||
import { nanoid } from 'nanoid';
|
||||
import Tabs from 'src/components/Tabs';
|
||||
import { css, styled, t } from '@superset-ui/core';
|
||||
import { css, styled, t, useTheme } from '@superset-ui/core';
|
||||
|
||||
import { removeTables, setActiveSouthPaneTab } from 'src/SqlLab/actions/sqlLab';
|
||||
|
||||
@@ -91,6 +91,7 @@ const SouthPane = ({
|
||||
displayLimit,
|
||||
defaultQueryLimit,
|
||||
}: SouthPaneProps) => {
|
||||
const theme = useTheme();
|
||||
const dispatch = useDispatch();
|
||||
const { offline, tables } = useSelector(
|
||||
({ sqlLab: { offline, tables } }: SqlLabRootState) => ({
|
||||
@@ -180,11 +181,11 @@ const SouthPane = ({
|
||||
<Tabs.TabPane
|
||||
tab={
|
||||
<>
|
||||
<Icons.Table
|
||||
iconSize="s"
|
||||
<Icons.InsertRowAboveOutlined
|
||||
iconSize="l"
|
||||
css={css`
|
||||
margin-bottom: 2px;
|
||||
margin-right: 4px;
|
||||
margin-bottom: ${theme.gridUnit * 0.5}px;
|
||||
margin-right: ${theme.gridUnit}px;
|
||||
`}
|
||||
/>
|
||||
{`${schema}.${decodeURIComponent(name)}`}
|
||||
|
||||
@@ -874,7 +874,7 @@ const SqlEditor: FC<Props> = ({
|
||||
trigger={['click']}
|
||||
>
|
||||
<Button buttonSize="xsmall" type="link" showMarginRight={false}>
|
||||
<Icons.MoreHoriz iconColor={theme.colors.grayscale.base} />
|
||||
<Icons.EllipsisOutlined />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,14 @@ import { bindActionCreators } from 'redux';
|
||||
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
||||
import { MenuDotsDropdown } from 'src/components/Dropdown';
|
||||
import { Menu } from 'src/components/Menu';
|
||||
import { styled, t, QueryState } from '@superset-ui/core';
|
||||
import {
|
||||
styled,
|
||||
css,
|
||||
t,
|
||||
QueryState,
|
||||
SupersetTheme,
|
||||
useTheme,
|
||||
} from '@superset-ui/core';
|
||||
import {
|
||||
removeQueryEditor,
|
||||
removeAllOtherQueryEditors,
|
||||
@@ -31,11 +38,16 @@ import {
|
||||
toggleLeftBar,
|
||||
} from 'src/SqlLab/actions/sqlLab';
|
||||
import { QueryEditor, SqlLabRootState } from 'src/SqlLab/types';
|
||||
import TabStatusIcon from '../TabStatusIcon';
|
||||
import Icons, { IconType } from 'src/components/Icons';
|
||||
|
||||
const TabTitleWrapper = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
[aria-label='check-circle'],
|
||||
.status-icon {
|
||||
margin: 0px;
|
||||
}
|
||||
`;
|
||||
const TabTitle = styled.span`
|
||||
margin-right: ${({ theme }) => theme.gridUnit * 2}px;
|
||||
@@ -43,16 +55,29 @@ const TabTitle = styled.span`
|
||||
`;
|
||||
|
||||
const IconContainer = styled.div`
|
||||
display: inline-block;
|
||||
width: ${({ theme }) => theme.gridUnit * 8}px;
|
||||
text-align: center;
|
||||
${({ theme }) => css`
|
||||
display: inline-block;
|
||||
margin: 0 ${theme.gridUnit * 2}px 0 0px;
|
||||
`}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
queryEditor: QueryEditor;
|
||||
}
|
||||
|
||||
const STATE_ICONS: Record<string, FC<IconType>> = {
|
||||
started: Icons.CircleSolid,
|
||||
stopped: Icons.StopOutlined,
|
||||
pending: Icons.CircleSolid,
|
||||
scheduled: Icons.CalendarOutlined,
|
||||
fetching: Icons.CircleSolid,
|
||||
timedOut: Icons.FieldTimeOutlined,
|
||||
running: Icons.CircleSolid,
|
||||
success: Icons.CheckCircleOutlined,
|
||||
failed: Icons.CloseCircleOutlined,
|
||||
};
|
||||
|
||||
const SqlEditorTabHeader: FC<Props> = ({ queryEditor }) => {
|
||||
const theme = useTheme();
|
||||
const qe = useSelector<SqlLabRootState, QueryEditor>(
|
||||
({ sqlLab: { unsavedQueryEditor } }) => ({
|
||||
...queryEditor,
|
||||
@@ -63,6 +88,8 @@ const SqlEditorTabHeader: FC<Props> = ({ queryEditor }) => {
|
||||
const queryState = useSelector<SqlLabRootState, QueryState>(
|
||||
({ sqlLab }) => sqlLab.queries[qe.latestQueryId || '']?.state || '',
|
||||
);
|
||||
const StatusIcon = queryState ? STATE_ICONS[queryState] : STATE_ICONS.running;
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const actions = useMemo(
|
||||
() =>
|
||||
@@ -85,7 +112,21 @@ const SqlEditorTabHeader: FC<Props> = ({ queryEditor }) => {
|
||||
actions.queryEditorSetTitle(qe, newTitle, qe.id);
|
||||
}
|
||||
}
|
||||
const getStatusColor = (state: QueryState, theme: SupersetTheme): string => {
|
||||
const statusColors: Record<QueryState, string> = {
|
||||
[QueryState.Running]: theme.colors.info.base,
|
||||
[QueryState.Success]: theme.colors.success.base,
|
||||
[QueryState.Failed]: theme.colors.error.base,
|
||||
[QueryState.Started]: theme.colors.primary.base,
|
||||
[QueryState.Stopped]: theme.colors.warning.base,
|
||||
[QueryState.Pending]: theme.colors.grayscale.light1,
|
||||
[QueryState.Scheduled]: theme.colors.grayscale.light2,
|
||||
[QueryState.Fetching]: theme.colors.secondary.base,
|
||||
[QueryState.TimedOut]: theme.colors.error.dark1,
|
||||
};
|
||||
|
||||
return statusColors[state] || theme.colors.grayscale.light2;
|
||||
};
|
||||
return (
|
||||
<TabTitleWrapper>
|
||||
<MenuDotsDropdown
|
||||
@@ -99,9 +140,12 @@ const SqlEditorTabHeader: FC<Props> = ({ queryEditor }) => {
|
||||
data-test="close-tab-menu-option"
|
||||
>
|
||||
<IconContainer>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-close" />
|
||||
<Icons.CloseOutlined
|
||||
iconSize="l"
|
||||
css={css`
|
||||
verticalalign: middle;
|
||||
`}
|
||||
/>
|
||||
</IconContainer>
|
||||
{t('Close tab')}
|
||||
</Menu.Item>
|
||||
@@ -111,9 +155,12 @@ const SqlEditorTabHeader: FC<Props> = ({ queryEditor }) => {
|
||||
data-test="rename-tab-menu-option"
|
||||
>
|
||||
<IconContainer>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-i-cursor" />
|
||||
<Icons.EditOutlined
|
||||
css={css`
|
||||
verticalalign: middle;
|
||||
`}
|
||||
iconSize="l"
|
||||
/>
|
||||
</IconContainer>
|
||||
{t('Rename tab')}
|
||||
</Menu.Item>
|
||||
@@ -123,9 +170,12 @@ const SqlEditorTabHeader: FC<Props> = ({ queryEditor }) => {
|
||||
data-test="toggle-menu-option"
|
||||
>
|
||||
<IconContainer>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-cogs" />
|
||||
<Icons.VerticalAlignBottomOutlined
|
||||
iconSize="l"
|
||||
css={css`
|
||||
rotate: ${qe.hideLeftBar ? '-90deg;' : '90deg;'};
|
||||
`}
|
||||
/>
|
||||
</IconContainer>
|
||||
{qe.hideLeftBar ? t('Expand tool bar') : t('Hide tool bar')}
|
||||
</Menu.Item>
|
||||
@@ -135,9 +185,12 @@ const SqlEditorTabHeader: FC<Props> = ({ queryEditor }) => {
|
||||
data-test="close-all-other-menu-option"
|
||||
>
|
||||
<IconContainer>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-times-circle-o" />
|
||||
<Icons.CloseOutlined
|
||||
iconSize="l"
|
||||
css={css`
|
||||
vertical-align: middle;
|
||||
`}
|
||||
/>
|
||||
</IconContainer>
|
||||
{t('Close all other tabs')}
|
||||
</Menu.Item>
|
||||
@@ -147,17 +200,24 @@ const SqlEditorTabHeader: FC<Props> = ({ queryEditor }) => {
|
||||
data-test="clone-tab-menu-option"
|
||||
>
|
||||
<IconContainer>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i className="fa fa-files-o" />
|
||||
<Icons.CopyOutlined
|
||||
iconSize="l"
|
||||
css={css`
|
||||
vertical-align: middle;
|
||||
`}
|
||||
/>
|
||||
</IconContainer>
|
||||
{t('Duplicate tab')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
/>
|
||||
<TabTitle>{qe.name}</TabTitle>{' '}
|
||||
<TabStatusIcon tabState={queryState} />{' '}
|
||||
<TabTitle>{qe.name}</TabTitle>
|
||||
<StatusIcon
|
||||
className="status-icon"
|
||||
iconSize="xs"
|
||||
iconColor={getStatusColor(queryState, theme)}
|
||||
/>
|
||||
</TabTitleWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { QueryState } from '@superset-ui/core';
|
||||
|
||||
import { render } from 'spec/helpers/testing-library';
|
||||
import TabStatusIcon from 'src/SqlLab/components/TabStatusIcon';
|
||||
|
||||
function setup() {
|
||||
return render(<TabStatusIcon tabState={'running' as QueryState} />);
|
||||
}
|
||||
|
||||
describe('TabStatusIcon', () => {
|
||||
it('renders a circle without an x when hovered', () => {
|
||||
const { container } = setup();
|
||||
expect(container.getElementsByClassName('circle')[0]).toBeInTheDocument();
|
||||
expect(
|
||||
container.getElementsByClassName('circle')[0]?.textContent ?? 'undefined',
|
||||
).toBe('');
|
||||
});
|
||||
});
|
||||
@@ -1,78 +0,0 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { FC } from 'react';
|
||||
import { css, QueryState, styled } from '@superset-ui/core';
|
||||
import Icons, { IconType } from 'src/components/Icons';
|
||||
|
||||
const IconContainer = styled.span`
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
left: 1px;
|
||||
`;
|
||||
|
||||
const Circle = styled.div`
|
||||
${({ theme }) => css`
|
||||
border-radius: 50%;
|
||||
width: ${theme.gridUnit * 3}px;
|
||||
height: ${theme.gridUnit * 3}px;
|
||||
|
||||
display: inline-block;
|
||||
background-color: ${theme.colors.grayscale.light2};
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
font-size: ${theme.typography.sizes.m}px;
|
||||
font-weight: ${theme.typography.weights.bold};
|
||||
color: ${theme.colors.grayscale.light5};
|
||||
position: relative;
|
||||
|
||||
&.running {
|
||||
background-color: ${theme.colors.info.base};
|
||||
}
|
||||
|
||||
&.success {
|
||||
background-color: ${theme.colors.success.base};
|
||||
}
|
||||
|
||||
&.failed {
|
||||
background-color: ${theme.colors.error.base};
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
interface TabStatusIconProps {
|
||||
tabState: QueryState;
|
||||
}
|
||||
|
||||
const STATE_ICONS: Record<string, FC<IconType>> = {
|
||||
success: Icons.Check,
|
||||
failed: Icons.CancelX,
|
||||
};
|
||||
|
||||
export default function TabStatusIcon({ tabState }: TabStatusIconProps) {
|
||||
const StatusIcon = STATE_ICONS[tabState];
|
||||
return (
|
||||
<Circle className={`circle ${tabState}`}>
|
||||
{StatusIcon && (
|
||||
<IconContainer>
|
||||
<StatusIcon iconSize="xs" />
|
||||
</IconContainer>
|
||||
)}
|
||||
</Circle>
|
||||
);
|
||||
}
|
||||
@@ -22,7 +22,13 @@ import { EditableTabs } from 'src/components/Tabs';
|
||||
import { connect } from 'react-redux';
|
||||
import URI from 'urijs';
|
||||
import type { QueryEditor, SqlLabRootState } from 'src/SqlLab/types';
|
||||
import { FeatureFlag, styled, t, isFeatureEnabled } from '@superset-ui/core';
|
||||
import {
|
||||
FeatureFlag,
|
||||
styled,
|
||||
t,
|
||||
isFeatureEnabled,
|
||||
css,
|
||||
} from '@superset-ui/core';
|
||||
import { Logger } from 'src/logger/LogUtils';
|
||||
import { Tooltip } from 'src/components/Tooltip';
|
||||
import { detectOS } from 'src/utils/common';
|
||||
@@ -30,6 +36,7 @@ import * as Actions from 'src/SqlLab/actions/sqlLab';
|
||||
import { EmptyState } from 'src/components/EmptyState';
|
||||
import getBootstrapData from 'src/utils/getBootstrapData';
|
||||
import { locationContext } from 'src/pages/SqlLab/LocationContext';
|
||||
import Icons from 'src/components/Icons';
|
||||
import SqlEditor from '../SqlEditor';
|
||||
import SqlEditorTabHeader from '../SqlEditorTabHeader';
|
||||
|
||||
@@ -247,9 +254,13 @@ class TabbedSqlEditors extends PureComponent<TabbedSqlEditorsProps> {
|
||||
: t('New tab (Ctrl + t)')
|
||||
}
|
||||
>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i data-test="add-tab-icon" className="fa fa-plus-circle" />
|
||||
<Icons.PlusCircleOutlined
|
||||
iconSize="s"
|
||||
css={css`
|
||||
vertical-align: middle;
|
||||
`}
|
||||
data-test="add-tab-icon"
|
||||
/>
|
||||
</Tooltip>
|
||||
</StyledTab>
|
||||
);
|
||||
@@ -291,9 +302,13 @@ class TabbedSqlEditors extends PureComponent<TabbedSqlEditorsProps> {
|
||||
: t('New tab (Ctrl + t)')
|
||||
}
|
||||
>
|
||||
{/* TODO: Remove fa-icon */}
|
||||
{/* eslint-disable-next-line icons/no-fa-icons-usage */}
|
||||
<i data-test="add-tab-icon" className="fa fa-plus-circle" />
|
||||
<Icons.PlusCircleOutlined
|
||||
iconSize="l"
|
||||
css={css`
|
||||
vertical-align: middle;
|
||||
`}
|
||||
data-test="add-tab-icon"
|
||||
/>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
|
||||
@@ -45,6 +45,7 @@ import ModalTrigger from 'src/components/ModalTrigger';
|
||||
import Loading from 'src/components/Loading';
|
||||
import useEffectEvent from 'src/hooks/useEffectEvent';
|
||||
import { ActionType } from 'src/types/Action';
|
||||
import Icons from 'src/components/Icons';
|
||||
import ColumnElement, { ColumnKeyTypeType } from '../ColumnElement';
|
||||
import ShowSQL from '../ShowSQL';
|
||||
|
||||
@@ -202,7 +203,7 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
|
||||
text={partitionQuery}
|
||||
shouldShowText={false}
|
||||
tooltipText={tt}
|
||||
copyNode={<i className="fa fa-clipboard" />}
|
||||
copyNode={<Icons.CopyOutlined iconSize="s" />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -259,9 +260,11 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
|
||||
))}
|
||||
triggerNode={
|
||||
<IconTooltip
|
||||
className="fa fa-key pull-left m-l-2"
|
||||
className="pull-left m-l-2"
|
||||
tooltip={t('View keys & indexes (%s)', tableData.indexes.length)}
|
||||
/>
|
||||
>
|
||||
<Icons.KeyOutlined iconSize="s" />
|
||||
</IconTooltip>
|
||||
}
|
||||
/>
|
||||
);
|
||||
@@ -279,10 +282,15 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
|
||||
`}
|
||||
>
|
||||
<IconTooltip
|
||||
className="fa fa-refresh pull-left m-l-2 pointer"
|
||||
className="pull-left m-l-2 pointer"
|
||||
onClick={refreshTableMetadata}
|
||||
tooltip={t('Refresh table schema')}
|
||||
/>
|
||||
>
|
||||
<Icons.SyncOutlined
|
||||
iconSize="m"
|
||||
iconColor={theme.colors.primary.dark2}
|
||||
/>
|
||||
</IconTooltip>
|
||||
{keyLink}
|
||||
<IconTooltip
|
||||
className={
|
||||
@@ -303,7 +311,11 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
|
||||
aria-label="Copy"
|
||||
tooltip={t('Copy SELECT statement to the clipboard')}
|
||||
>
|
||||
<i aria-hidden className="fa fa-clipboard pull-left m-l-2" />
|
||||
<Icons.CopyOutlined
|
||||
iconSize="m"
|
||||
iconColor={theme.colors.primary.dark2}
|
||||
aria-hidden
|
||||
/>
|
||||
</IconTooltip>
|
||||
}
|
||||
text={tableData.selectStar}
|
||||
@@ -318,10 +330,16 @@ const TableElement = ({ table, ...props }: TableElementProps) => {
|
||||
/>
|
||||
)}
|
||||
<IconTooltip
|
||||
className="fa fa-times table-remove pull-left m-l-2 pointer"
|
||||
className=" table-remove pull-left m-l-2 pointer"
|
||||
onClick={removeTable}
|
||||
tooltip={t('Remove table preview')}
|
||||
/>
|
||||
>
|
||||
<Icons.CloseOutlined
|
||||
iconSize="m"
|
||||
iconColor={theme.colors.primary.dark2}
|
||||
aria-hidden
|
||||
/>
|
||||
</IconTooltip>
|
||||
</ButtonGroup>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -65,17 +65,17 @@ const MENUS = [
|
||||
{
|
||||
key: 'refresh-table',
|
||||
label: t('Refresh table schema'),
|
||||
icon: <i aria-hidden className="fa fa-refresh" />,
|
||||
icon: <Icons.SyncOutlined iconSize="s" aria-hidden />,
|
||||
},
|
||||
{
|
||||
key: 'copy-select-statement',
|
||||
label: t('Copy SELECT statement'),
|
||||
icon: <i aria-hidden className="fa fa-clipboard m-l-2" />,
|
||||
icon: <Icons.CopyOutlined iconSize="s" aria-hidden />,
|
||||
},
|
||||
{
|
||||
key: 'show-create-view-statement',
|
||||
label: t('Show CREATE VIEW statement'),
|
||||
icon: <i aria-hidden className="fa fa-eye" />,
|
||||
icon: <Icons.EyeOutlined iconSize="s" aria-hidden />,
|
||||
},
|
||||
];
|
||||
const TAB_HEADER_HEIGHT = 80;
|
||||
@@ -104,7 +104,7 @@ const renderWell = (partitions: TableMetaData['partitions']) => {
|
||||
text={partitionQuery}
|
||||
shouldShowText={false}
|
||||
tooltipText={tt}
|
||||
copyNode={<i className="fa fa-clipboard" />}
|
||||
copyNode={<Icons.CopyOutlined iconSize="s" />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -306,7 +306,7 @@ const TablePreview: FC<Props> = ({ dbId, catalog, schema, tableName }) => {
|
||||
)}
|
||||
</div>
|
||||
<Title>
|
||||
<Icons.Table iconSize="l" />
|
||||
<Icons.InsertRowAboveOutlined iconSize="l" />
|
||||
{tableName}
|
||||
<Dropdown
|
||||
dropdownRender={() => (
|
||||
|
||||
Reference in New Issue
Block a user