feat(adhoc-column): add resize option (#23748)

This commit is contained in:
Ville Brofeldt 2023-04-20 17:03:18 +03:00 committed by GitHub
parent b2b8c3e05b
commit 60c9d68403
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 152 additions and 8 deletions

View File

@ -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>
);

View File

@ -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,
];
}

View File

@ -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,
),
});

View File

@ -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,
),
});

View File

@ -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;