mirror of https://github.com/apache/superset.git
feat(adhoc-column): add resize option (#23748)
This commit is contained in:
parent
b2b8c3e05b
commit
60c9d68403
|
@ -46,9 +46,10 @@ import { EmptyStateSmall } from 'src/components/EmptyState';
|
|||
import { StyledColumnOption } from 'src/explore/components/optionRenderers';
|
||||
import {
|
||||
POPOVER_INITIAL_HEIGHT,
|
||||
UNRESIZABLE_POPOVER_WIDTH,
|
||||
POPOVER_INITIAL_WIDTH,
|
||||
} from 'src/explore/constants';
|
||||
import { ExplorePageState } from 'src/explore/types';
|
||||
import useResizeButton from './useResizeButton';
|
||||
|
||||
const StyledSelect = styled(Select)`
|
||||
.metric-option {
|
||||
|
@ -117,6 +118,11 @@ const ColumnSelectPopover = ({
|
|||
ColumnMeta | undefined
|
||||
>(initialSimpleColumn);
|
||||
|
||||
const [resizeButton, width, height] = useResizeButton(
|
||||
POPOVER_INITIAL_WIDTH,
|
||||
POPOVER_INITIAL_HEIGHT,
|
||||
);
|
||||
|
||||
const sqlEditorRef = useRef(null);
|
||||
|
||||
const [calculatedColumns, simpleColumns] = useMemo(
|
||||
|
@ -258,8 +264,8 @@ const ColumnSelectPopover = ({
|
|||
className="adhoc-metric-edit-tabs"
|
||||
allowOverflow
|
||||
css={css`
|
||||
height: ${POPOVER_INITIAL_HEIGHT}px;
|
||||
width: ${UNRESIZABLE_POPOVER_WIDTH}px;
|
||||
height: ${height}px;
|
||||
width: ${width}px;
|
||||
`}
|
||||
>
|
||||
<Tabs.TabPane key="saved" tab={t('Saved')}>
|
||||
|
@ -393,7 +399,7 @@ const ColumnSelectPopover = ({
|
|||
showLoadingForImport
|
||||
onChange={onSqlExpressionChange}
|
||||
width="100%"
|
||||
height={`${POPOVER_INITIAL_HEIGHT - 80}px`}
|
||||
height={`${height - 80}px`}
|
||||
showGutter={false}
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
enableLiveAutocompletion
|
||||
|
@ -417,6 +423,7 @@ const ColumnSelectPopover = ({
|
|||
>
|
||||
{t('Save')}
|
||||
</Button>
|
||||
{resizeButton}
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* 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 React, { useCallback, useEffect, useState } from 'react';
|
||||
import throttle from 'lodash/throttle';
|
||||
import {
|
||||
POPOVER_INITIAL_HEIGHT,
|
||||
POPOVER_INITIAL_WIDTH,
|
||||
} from 'src/explore/constants';
|
||||
|
||||
const RESIZE_THROTTLE_MS = 50;
|
||||
|
||||
export default function useResizeButton(
|
||||
minWidth: number,
|
||||
minHeight: number,
|
||||
): [JSX.Element, number, number] {
|
||||
const [width, setWidth] = useState(POPOVER_INITIAL_WIDTH);
|
||||
const [height, setHeight] = useState(POPOVER_INITIAL_HEIGHT);
|
||||
const [clientX, setClientX] = useState(0);
|
||||
const [clientY, setClientY] = useState(0);
|
||||
const [dragStartX, setDragStartX] = useState(0);
|
||||
const [dragStartY, setDragStartY] = useState(0);
|
||||
const [dragStartWidth, setDragStartWidth] = useState(width);
|
||||
const [dragStartHeight, setDragStartHeight] = useState(height);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
|
||||
const onMouseMove = useCallback((ev: MouseEvent): void => {
|
||||
ev.preventDefault();
|
||||
setClientX(ev.clientX);
|
||||
setClientY(ev.clientY);
|
||||
}, []);
|
||||
|
||||
const onMouseUp = useCallback(() => {
|
||||
setIsDragging(false);
|
||||
}, []);
|
||||
|
||||
const onDragDown = useCallback((ev: React.MouseEvent): void => {
|
||||
setDragStartX(ev.clientX);
|
||||
setDragStartY(ev.clientY);
|
||||
setIsDragging(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDragging) {
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
} else {
|
||||
setDragStartWidth(width);
|
||||
setDragStartHeight(height);
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
}
|
||||
}, [onMouseMove, isDragging]);
|
||||
|
||||
const handleResize = useCallback(
|
||||
throttle(
|
||||
({
|
||||
dragStartX,
|
||||
dragStartY,
|
||||
dragStartWidth,
|
||||
dragStartHeight,
|
||||
clientX,
|
||||
clientY,
|
||||
minWidth,
|
||||
minHeight,
|
||||
}: {
|
||||
dragStartX: number;
|
||||
dragStartY: number;
|
||||
dragStartWidth: number;
|
||||
dragStartHeight: number;
|
||||
clientX: number;
|
||||
clientY: number;
|
||||
minWidth: number;
|
||||
minHeight: number;
|
||||
}): void => {
|
||||
setWidth(Math.max(dragStartWidth + (clientX - dragStartX), minWidth));
|
||||
setHeight(
|
||||
Math.max(dragStartHeight + (clientY - dragStartY), minHeight),
|
||||
);
|
||||
},
|
||||
RESIZE_THROTTLE_MS,
|
||||
),
|
||||
[setHeight, setWidth],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDragging) {
|
||||
handleResize({
|
||||
dragStartX,
|
||||
dragStartY,
|
||||
dragStartWidth,
|
||||
dragStartHeight,
|
||||
clientX,
|
||||
clientY,
|
||||
minWidth,
|
||||
minHeight,
|
||||
});
|
||||
}
|
||||
}, [
|
||||
isDragging,
|
||||
clientX,
|
||||
clientY,
|
||||
dragStartWidth,
|
||||
dragStartHeight,
|
||||
dragStartX,
|
||||
dragStartY,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
return () => document.removeEventListener('mouseup', onMouseUp);
|
||||
}, [onMouseUp]);
|
||||
|
||||
return [
|
||||
<i
|
||||
role="button"
|
||||
aria-label="Resize"
|
||||
tabIndex={0}
|
||||
onMouseDown={onDragDown}
|
||||
className="fa fa-expand edit-popover-resize text-muted"
|
||||
/>,
|
||||
width,
|
||||
height,
|
||||
];
|
||||
}
|
|
@ -150,7 +150,7 @@ export default class AdhocFilterEditPopover extends React.Component {
|
|||
POPOVER_INITIAL_WIDTH,
|
||||
),
|
||||
height: Math.max(
|
||||
this.dragStartHeight + (e.clientY - this.dragStartY) * 2,
|
||||
this.dragStartHeight + (e.clientY - this.dragStartY),
|
||||
POPOVER_INITIAL_HEIGHT,
|
||||
),
|
||||
});
|
||||
|
|
|
@ -248,7 +248,7 @@ export default class AdhocMetricEditPopover extends React.PureComponent {
|
|||
POPOVER_INITIAL_WIDTH,
|
||||
),
|
||||
height: Math.max(
|
||||
this.dragStartHeight + (e.clientY - this.dragStartY) * 2,
|
||||
this.dragStartHeight + (e.clientY - this.dragStartY),
|
||||
POPOVER_INITIAL_HEIGHT,
|
||||
),
|
||||
});
|
||||
|
|
|
@ -158,6 +158,4 @@ export const TIME_FILTER_MAP = {
|
|||
|
||||
export const POPOVER_INITIAL_HEIGHT = 240;
|
||||
export const POPOVER_INITIAL_WIDTH = 320;
|
||||
export const UNRESIZABLE_POPOVER_WIDTH = 296;
|
||||
|
||||
export const UNSAVED_CHART_ID = 0;
|
||||
|
|
Loading…
Reference in New Issue