/** * Datart * * Copyright 2021 * * Licensed 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 { GithubOutlined } from '@ant-design/icons'; import { Alert, Button, Popover, Space, Spin } from 'antd'; import useI18NPrefix from 'app/hooks/useI18NPrefix'; import useResizeObserver from 'app/hooks/useResizeObserver'; import { selectSystemInfo } from 'app/slice/selectors'; import { transparentize } from 'polished'; import React, { memo, useCallback } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import styled from 'styled-components/macro'; import { SPACE_MD, SPACE_TIMES, SPACE_XS } from 'styles/StyleConstants'; import { newIssueUrl } from 'utils/utils'; import { ViewViewModelStages } from '../../constants'; import { useViewSlice } from '../../slice'; import { selectCurrentEditingViewAttr } from '../../slice/selectors'; import { Error } from './Error'; import { Results } from './Results'; export const Outputs = memo(() => { const { actions } = useViewSlice(); const dispatch = useDispatch(); const systemInfo = useSelector(selectSystemInfo); const t = useI18NPrefix('view'); const error = useSelector(state => selectCurrentEditingViewAttr(state, { name: 'error' }), ) as string; const stage = useSelector(state => selectCurrentEditingViewAttr(state, { name: 'stage' }), ) as ViewViewModelStages; const warnings = useSelector(state => selectCurrentEditingViewAttr(state, { name: 'warnings' }), ) as string[]; const { width, height, ref } = useResizeObserver({ refreshMode: 'debounce', refreshRate: 200, }); const removeViewWarnings = useCallback(() => { dispatch( actions.changeCurrentEditingView({ warnings: null, }), ); }, [dispatch, actions]); const submitIssue = useCallback( type => { let params: any = { type: type, title: 'Sql parse bug', }; if (type === 'github') { params.body = `version: ${systemInfo?.version}\n` + warnings.join(''); } else { params.description = `version: ${systemInfo?.version}\n` + warnings.join(''); } let url = newIssueUrl(params); window.open(url); }, [warnings, systemInfo], ); return ( <Wrapper ref={ref}> {warnings && ( <Alert className="warningBox" message="" description={ <p> {t('sqlRunWraning')} <Popover trigger={['click']} placement="top" overlayStyle={{ width: SPACE_TIMES(96) }} content={t('warningDescription')} > <Button className="detail" type="link" size="small"> {t('detail')} </Button> </Popover> </p> } type="warning" closable={false} action={ <Space> <Button type="primary" icon={<GithubOutlined />} onClick={() => submitIssue('github')} > Github </Button> <Button type="primary" onClick={() => submitIssue('gitee')}> Gitee </Button> <Button onClick={removeViewWarnings}>{t('close')}</Button> </Space> } /> )} <Results width={width} height={height} /> {error && <Error />} {stage === ViewViewModelStages.Running && ( <LoadingMask> <Spin /> </LoadingMask> )} </Wrapper> ); }); const Wrapper = styled.div` position: relative; display: flex; flex-direction: column; border-top: 1px solid ${p => p.theme.borderColorSplit}; .warningBox { padding: ${SPACE_XS} ${SPACE_MD}; .detail { padding: 0; } } `; const LoadingMask = styled.div` position: absolute; top: 0; right: 0; bottom: 0; left: 0; display: flex; align-items: center; justify-content: center; background-color: ${p => transparentize(0.5, p.theme.componentBackground)}; `;