Skip to content

Commit

Permalink
Add Drag Across Axis Functionality to Vis Builder
Browse files Browse the repository at this point in the history
Signed-off-by: Suchit Sahoo <[email protected]>
  • Loading branch information
LDrago27 committed Jun 25, 2024
1 parent e74ed2c commit c8a8c8f
Show file tree
Hide file tree
Showing 11 changed files with 562 additions and 145 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,15 @@

import { EuiForm } from '@elastic/eui';
import React from 'react';
import { useVisualizationType } from '../../utils/use';
import { useTypedSelector } from '../../utils/state_management';

import './config_panel.scss';
import { mapSchemaToAggPanel } from './schema_to_dropbox';
import { SecondaryPanel } from './secondary_panel';

export function ConfigPanel() {
const vizType = useVisualizationType();
const editingState = useTypedSelector(
(state) => state.visualization.activeVisualization?.draftAgg
);
const schemas = vizType.ui.containerConfig.data.schemas;

export function ConfigPanel({ schemas, editingState, aggProps, configStates }) {
if (!schemas) return null;

const mainPanel = mapSchemaToAggPanel(schemas);
const mainPanel = mapSchemaToAggPanel(schemas, aggProps, configStates);

return (
<EuiForm className={`vbConfig ${editingState ? 'showSecondary' : ''}`}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
border-bottom: none;
}

&__droppable {
min-height: 1px;
}

&__container {
display: grid;
grid-gap: calc($euiSizeXS / 2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
DropResult,
} from '@elastic/eui';
import React, { useCallback, useState } from 'react';
import { IDropAttributes, IDropState } from '../../utils/drag_drop';
import { IDropAttributes, IDropState, useDrag } from '../../utils/drag_drop';
import './dropbox.scss';
import { useDropbox } from './use';
import { UseDropboxProps } from './use/use_dropbox';
Expand Down Expand Up @@ -59,17 +59,6 @@ const DropboxComponent = ({
}: DropboxProps) => {
const prefersReducedMotion = usePrefersReducedMotion();
const [closing, setClosing] = useState<boolean | string>(false);
const handleDragEnd = useCallback(
({ source, destination }: DropResult) => {
if (!destination) return;

onReorderField({
sourceAggId: fields[source.index].id,
destinationAggId: fields[destination.index].id,
});
},
[fields, onReorderField]
);

const animateDelete = useCallback(
(id: string) => {
Expand All @@ -86,71 +75,72 @@ const DropboxComponent = ({
);

return (
<EuiDragDropContext onDragEnd={handleDragEnd}>
<EuiFormRow label={boxLabel} className="dropBox" fullWidth>
<div className="dropBox__container">
<EuiDroppable droppableId={dropboxId}>
{fields.map(({ id, label }, index) => (
<EuiDraggable
className={`dropBox__draggable ${id === closing && 'closing'}`}
key={id}
draggableId={id}
index={index}
>
<EuiPanel
key={index}
paddingSize="s"
className="dropBox__field"
data-test-subj={`dropBoxField-${dropboxId}-${index}`}
>
<EuiText size="s" className="dropBox__field_text" onClick={() => onEditField(id)}>
<a role="button" tabIndex={0}>
{label}
</a>
</EuiText>
<EuiButtonIcon
color="subdued"
iconType="cross"
aria-label="clear-field"
iconSize="s"
onClick={() => animateDelete(id)}
data-test-subj="dropBoxRemoveBtn"
/>
</EuiPanel>
</EuiDraggable>
))}
</EuiDroppable>
{fields.length < limit && (
<EuiPanel
data-test-subj={`dropBoxAddField-${dropboxId}`}
className={`dropBox__field dropBox__dropTarget ${
isValidDropTarget ? 'validField' : ''
} ${canDrop ? 'canDrop' : ''}`}
{...(isValidDropTarget && dropProps)}
<EuiFormRow label={boxLabel} className="dropBox" fullWidth>
<div className="dropBox__container">
<EuiDroppable
className="dropBox__droppable"
droppableId={dropboxId}
isCombineEnabled={true}
>
{fields.map(({ id, label }, index) => (
<EuiDraggable
className={`dropBox__draggable ${id === closing && 'closing'}`}
key={id}
draggableId={id}
index={index}
>
<EuiText size="s">
{i18n.translate('visBuilder.dropbox.addField.title', {
defaultMessage: 'Click or drop to add',
})}
</EuiText>
<EuiButtonIcon
iconType="plusInCircle"
aria-label="clear-field"
iconSize="s"
onClick={() => onAddField()}
data-test-subj="dropBoxAddBtn"
/>
</EuiPanel>
)}
</div>
</EuiFormRow>
</EuiDragDropContext>
<EuiPanel
key={index}
paddingSize="s"
className="dropBox__field"
data-test-subj={`dropBoxField-${dropboxId}-${index}`}
>
<EuiText size="s" className="dropBox__field_text" onClick={() => onEditField(id)}>
<a role="button" tabIndex={0}>
{label}
</a>
</EuiText>
<EuiButtonIcon
color="subdued"
iconType="cross"
aria-label="clear-field"
iconSize="s"
onClick={() => animateDelete(id)}
data-test-subj="dropBoxRemoveBtn"
/>
</EuiPanel>
</EuiDraggable>
))}
</EuiDroppable>
{fields.length < limit && (
<EuiPanel
data-test-subj={`dropBoxAddField-${dropboxId}`}
className={`dropBox__field dropBox__dropTarget ${
isValidDropTarget ? 'validField' : ''
} ${canDrop ? 'canDrop' : ''}`}
{...(isValidDropTarget && dropProps)}
>
<EuiText size="s">
{i18n.translate('visBuilder.dropbox.addField.title', {
defaultMessage: 'Click or drop to add',
})}
</EuiText>
<EuiButtonIcon
iconType="plusInCircle"
aria-label="clear-field"
iconSize="s"
onClick={() => onAddField()}
data-test-subj="dropBoxAddBtn"
/>
</EuiPanel>
)}
</div>
</EuiFormRow>
);
};

const Dropbox = React.memo((dropBox: UseDropboxProps) => {
const props = useDropbox(dropBox);

return <DropboxComponent {...props} />;
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
*/

import React, { useState } from 'react';
import { EuiPopover } from '@elastic/eui';
import { EuiDraggable, EuiPopover } from '@elastic/eui';

import { IndexPatternField } from '../../../../../data/public';
import {
Expand All @@ -46,10 +46,11 @@ import './field.scss';
export interface FieldProps {
field: IndexPatternField;
getDetails: (field) => FieldDetails;
id: number;
}

// TODO: Add field sections (Available fields, popular fields from src/plugins/discover/public/application/components/sidebar/discover_sidebar.tsx)
export const Field = ({ field, getDetails }: FieldProps) => {
export const Field = ({ field, getDetails, id }: FieldProps) => {
const [infoIsOpen, setOpen] = useState(false);

function togglePopover() {
Expand All @@ -60,7 +61,14 @@ export const Field = ({ field, getDetails }: FieldProps) => {
<EuiPopover
ownFocus
display="block"
button={<DraggableFieldButton isActive={infoIsOpen} onClick={togglePopover} field={field} />}
button={
<DraggableFieldButton
isActive={infoIsOpen}
onClick={togglePopover}
field={field}
index={id}
/>
}
isOpen={infoIsOpen}
closePopover={() => setOpen(false)}
anchorPosition="rightUp"
Expand All @@ -77,9 +85,15 @@ export const Field = ({ field, getDetails }: FieldProps) => {
export interface DraggableFieldButtonProps extends Partial<FieldButtonProps> {
dragValue?: IndexPatternField['name'] | null | typeof COUNT_FIELD;
field: Partial<IndexPatternField> & Pick<IndexPatternField, 'displayName' | 'name' | 'type'>;
index: number;
}

export const DraggableFieldButton = ({ dragValue, field, ...rest }: DraggableFieldButtonProps) => {
export const DraggableFieldButton = ({
dragValue,
field,
index,
...rest
}: DraggableFieldButtonProps) => {
const { name, displayName, type, scripted = false } = field;
const [dragProps] = useDrag({
namespace: 'field-data',
Expand Down Expand Up @@ -109,5 +123,14 @@ export const DraggableFieldButton = ({ dragValue, field, ...rest }: DraggableFie
onClick: () => {},
};

return <FieldButton {...defaultProps} {...rest} {...dragProps} />;
return (
<EuiDraggable
draggableId={name}
index={index}
disableInteractiveElementBlocking={true}
shouldRespectForcePress
>
<FieldButton {...defaultProps} {...rest} {...dragProps} />
</EuiDraggable>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
padding: $euiSizeS;

&__fieldGroups {
@include euiYScrollWithShadows;

overflow-y: auto;
margin-right: -$euiSizeS;
Expand Down
Loading

0 comments on commit c8a8c8f

Please sign in to comment.