/** * 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 { useMemo, FC } from 'react'; import { bindActionCreators } from 'redux'; import { useSelector, useDispatch, shallowEqual } from 'react-redux'; import { MenuDotsDropdown } from '@superset-ui/core/components'; import { Menu, MenuItemType } from '@superset-ui/core/components/Menu'; import { t, QueryState } from '@superset-ui/core'; import { styled, css, SupersetTheme, useTheme } from '@apache-superset/core/ui'; import { removeQueryEditor, removeAllOtherQueryEditors, queryEditorSetTitle, cloneQueryToNewTab, toggleLeftBar, } from 'src/SqlLab/actions/sqlLab'; import { QueryEditor, SqlLabRootState } from 'src/SqlLab/types'; import { Icons, type IconType } from '@superset-ui/core/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.sizeUnit * 2}px; text-transform: none; `; const IconContainer = styled.div` ${({ theme }) => css` display: inline-block; margin: 0 ${theme.sizeUnit * 2}px 0 0px; `} `; interface Props { queryEditor: QueryEditor; } const STATE_ICONS: Record> = { 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 = ({ queryEditor }) => { const theme = useTheme(); const qe = useSelector( ({ sqlLab: { unsavedQueryEditor } }) => ({ ...queryEditor, ...(queryEditor.id === unsavedQueryEditor?.id && unsavedQueryEditor), }), shallowEqual, ); const queryState = useSelector( ({ sqlLab }) => sqlLab.queries[qe.latestQueryId || '']?.state || '', ); const StatusIcon = queryState ? STATE_ICONS[queryState] : STATE_ICONS.running; const dispatch = useDispatch(); const actions = useMemo( () => bindActionCreators( { removeQueryEditor, removeAllOtherQueryEditors, queryEditorSetTitle, cloneQueryToNewTab, toggleLeftBar, }, dispatch, ), [dispatch], ); function renameTab() { const newTitle = prompt(t('Enter a new title for the tab')); if (newTitle) { actions.queryEditorSetTitle(qe, newTitle, qe.id); } } const getStatusColor = (state: QueryState, theme: SupersetTheme): string => { const statusColors: Record = { [QueryState.Running]: theme.colorInfo, [QueryState.Success]: theme.colorSuccess, [QueryState.Failed]: theme.colorError, [QueryState.Started]: theme.colorPrimary, [QueryState.Stopped]: theme.colorWarning, [QueryState.Pending]: theme.colorIcon, [QueryState.Scheduled]: theme.colorIcon, [QueryState.Fetching]: theme.colorWarning, [QueryState.TimedOut]: theme.colorError, }; return statusColors[state] || theme.colorIcon; }; return ( actions.removeQueryEditor(qe), 'data-test': 'close-tab-menu-option', label: ( <> {t('Close tab')} ), } as MenuItemType, { key: '2', onClick: renameTab, 'data-test': 'rename-tab-menu-option', label: ( <> {t('Rename tab')} ), } as MenuItemType, { key: '4', onClick: () => actions.removeAllOtherQueryEditors(qe), 'data-test': 'close-all-other-menu-option', label: ( <> {t('Close all other tabs')} ), } as MenuItemType, { key: '5', onClick: () => actions.cloneQueryToNewTab(qe, false), 'data-test': 'clone-tab-menu-option', label: ( <> {t('Duplicate tab')} ), } as MenuItemType, ]} /> } /> {qe.name}{' '} {' '} ); }; export default SqlEditorTabHeader;