This is an automated email from the ASF dual-hosted git repository. villebro pushed a commit to branch 1.5 in repository https://gitbox.apache.org/repos/asf/superset.git
commit 3c8e65960f7c84f43c69d31c0302dc92e2aa50ff Author: Kamil Gabryjelski <[email protected]> AuthorDate: Wed Apr 13 14:22:46 2022 +0200 fix(dashboard): Fix BigNumber causing dashboard to crash when overflowing (#19688) * fix(dashboard): fix(plugin-chart-echarts): Fix BigNumber causing dashboard to crash when overflowing * Add tooltips for truncated titles * Fix type (cherry picked from commit ee85466f2ed45d3f51a7609ef4e30cf087c033e4) --- .../src/components/EditableTitle/index.tsx | 9 ++-- .../components/SliceHeader/SliceHeader.test.tsx | 2 + .../src/dashboard/components/SliceHeader/index.tsx | 49 +++++++++++++++------- .../dashboard/components/gridComponents/Chart.jsx | 17 ++++++-- .../src/dashboard/stylesheets/dashboard.less | 8 ++++ 5 files changed, 63 insertions(+), 22 deletions(-) diff --git a/superset-frontend/src/components/EditableTitle/index.tsx b/superset-frontend/src/components/EditableTitle/index.tsx index 6839b45c7d..ddd8587556 100644 --- a/superset-frontend/src/components/EditableTitle/index.tsx +++ b/superset-frontend/src/components/EditableTitle/index.tsx @@ -57,6 +57,8 @@ export default function EditableTitle({ placeholder = '', certifiedBy, certificationDetails, + // rest is related to title tooltip + ...rest }: EditableTitleProps) { const [isEditing, setIsEditing] = useState(editing); const [currentTitle, setCurrentTitle] = useState(title); @@ -214,11 +216,7 @@ export default function EditableTitle({ } if (!canEdit) { // don't actually want an input in this case - titleComponent = ( - <span data-test="editable-title-input" title={value}> - {value} - </span> - ); + titleComponent = <span data-test="editable-title-input">{value}</span>; } return ( <span @@ -230,6 +228,7 @@ export default function EditableTitle({ isEditing && 'editable-title--editing', )} style={style} + {...rest} > {certifiedBy && ( <> diff --git a/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx b/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx index 27abbd396f..b3b96a4fad 100644 --- a/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeader/SliceHeader.test.tsx @@ -159,6 +159,8 @@ const createProps = () => ({ exportCSV: jest.fn(), onExploreChart: jest.fn(), formData: { slice_id: 1, datasource: '58__table' }, + width: 100, + height: 100, }); test('Should render', () => { diff --git a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx index 88e9a4c69f..44ddf7b5ad 100644 --- a/superset-frontend/src/dashboard/components/SliceHeader/index.tsx +++ b/superset-frontend/src/dashboard/components/SliceHeader/index.tsx @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import React, { FC, useMemo } from 'react'; +import React, { FC, useEffect, useMemo, useRef, useState } from 'react'; import { styled, t } from '@superset-ui/core'; import { useUiConfig } from 'src/components/UiConfigContext'; import { Tooltip } from 'src/components/Tooltip'; @@ -41,6 +41,8 @@ type SliceHeaderProps = SliceHeaderControlsProps & { filters: object; handleToggleFullSize: () => void; formData: object; + width: number; + height: number; }; const annotationsLoading = t('Annotation layers are still loading.'); @@ -82,9 +84,13 @@ const SliceHeader: FC<SliceHeaderProps> = ({ isFullSize, chartStatus, formData, + width, + height, }) => { const dispatch = useDispatch(); const uiConfig = useUiConfig(); + const [headerTooltip, setHeaderTooltip] = useState<string | null>(null); + const headerRef = useRef<HTMLDivElement>(null); // TODO: change to indicator field after it will be implemented const crossFilterValue = useSelector<RootState, any>( state => state.dataMask[slice?.slice_id]?.filterState?.value, @@ -98,21 +104,36 @@ const SliceHeader: FC<SliceHeaderProps> = ({ [crossFilterValue], ); + useEffect(() => { + const headerElement = headerRef.current; + if ( + headerElement && + (headerElement.scrollWidth > headerElement.offsetWidth || + headerElement.scrollHeight > headerElement.offsetHeight) + ) { + setHeaderTooltip(sliceName ?? null); + } else { + setHeaderTooltip(null); + } + }, [sliceName, width, height]); + return ( <div className="chart-header" data-test="slice-header" ref={innerRef}> - <div className="header-title"> - <EditableTitle - title={ - sliceName || - (editMode - ? '---' // this makes an empty title clickable - : '') - } - canEdit={editMode} - emptyText="" - onSaveTitle={updateSliceName} - showTooltip={false} - /> + <div className="header-title" ref={headerRef}> + <Tooltip title={headerTooltip}> + <EditableTitle + title={ + sliceName || + (editMode + ? '---' // this makes an empty title clickable + : '') + } + canEdit={editMode} + emptyText="" + onSaveTitle={updateSliceName} + showTooltip={false} + /> + </Tooltip> {!!Object.values(annotationQuery).length && ( <Tooltip id="annotations-loading-tooltip" diff --git a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx index 134e026d7a..b212af44e5 100644 --- a/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx +++ b/superset-frontend/src/dashboard/components/gridComponents/Chart.jsx @@ -113,6 +113,12 @@ const ChartOverlay = styled.div` } `; +const SliceContainer = styled.div` + display: flex; + flex-direction: column; + max-height: 100%; +`; + export default class Chart extends React.Component { constructor(props) { super(props); @@ -210,7 +216,10 @@ export default class Chart extends React.Component { getChartHeight() { const headerHeight = this.getHeaderHeight(); - return this.state.height - headerHeight - this.state.descriptionHeight; + return Math.max( + this.state.height - headerHeight - this.state.descriptionHeight, + 20, + ); } getHeaderHeight() { @@ -370,7 +379,7 @@ export default class Chart extends React.Component { }) : {}; return ( - <div + <SliceContainer className="chart-slice" data-test="chart-grid-component" data-test-chart-id={id} @@ -407,6 +416,8 @@ export default class Chart extends React.Component { isFullSize={isFullSize} chartStatus={chart.chartStatus} formData={formData} + width={width} + height={this.getHeaderHeight()} /> {/* @@ -468,7 +479,7 @@ export default class Chart extends React.Component { datasetsStatus={datasetsStatus} /> </div> - </div> + </SliceContainer> ); } } diff --git a/superset-frontend/src/dashboard/stylesheets/dashboard.less b/superset-frontend/src/dashboard/stylesheets/dashboard.less index a3409c4d48..b9b2b0aab9 100644 --- a/superset-frontend/src/dashboard/stylesheets/dashboard.less +++ b/superset-frontend/src/dashboard/stylesheets/dashboard.less @@ -63,12 +63,20 @@ body { display: flex; max-width: 100%; align-items: flex-start; + min-height: 0; & > .header-title { overflow: hidden; text-overflow: ellipsis; max-width: 100%; flex-grow: 1; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + + & > span.ant-tooltip-open { + display: inline; + } } & > .header-controls {
