Skip to content

Commit

Permalink
Merge pull request #13 from andreadelrio/controls-empty-state
Browse files Browse the repository at this point in the history
[Controls] Add empty state and do cleanup
  • Loading branch information
ThomThomson authored Oct 18, 2021
2 parents 0232bbe + 324bf11 commit e4f5711
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 138 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,10 @@ const panelStyle = {

const kqlBarStyle = { background: bar, padding: 16, minHeight, fontStyle: 'italic' };

const inputBarStyle = { background: '#fff', padding: 4 };

const layout = (OptionStory: Story) => (
<EuiFlexGroup style={{ background }} direction="column">
<EuiFlexItem style={kqlBarStyle}>KQL Bar</EuiFlexItem>
<EuiFlexItem style={inputBarStyle}>
<EuiFlexItem>
<OptionStory />
</EuiFlexItem>
<EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,21 +89,21 @@ export const ControlFrame = ({ customPrepend, enableActions, embeddableId }: Con

const form = (
<EuiFormControlLayout
className={'controlFrame--formControlLayout'}
className={'controlFrame__formControlLayout'}
fullWidth
prepend={
<>
{customPrepend ?? null}
{usingTwoLineLayout ? undefined : (
<EuiFormLabel className="controlFrame--formControlLayout__label" htmlFor={embeddableId}>
<EuiFormLabel className="controlFrame__formControlLayoutLabel" htmlFor={embeddableId}>
{title}
</EuiFormLabel>
)}
</>
}
>
<div
className={classNames('controlFrame--control', {
className={classNames('controlFrame__control', {
'controlFrame--twoLine': controlStyle === 'twoLine',
'controlFrame--oneLine': controlStyle === 'oneLine',
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@

import '../control_group.scss';

import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiToolTip } from '@elastic/eui';
import {
EuiButton,
EuiButtonIcon,
EuiFlexGroup,
EuiFlexItem,
EuiToolTip,
EuiPanel,
EuiText,
} from '@elastic/eui';
import React, { useMemo, useState } from 'react';
import classNames from 'classnames';
import {
Expand Down Expand Up @@ -57,7 +65,7 @@ export const ControlGroup = () => {
const dispatch = useEmbeddableDispatch();

// current state
const { panels } = useEmbeddableSelector((state) => state);
const { panels, controlStyle } = useEmbeddableSelector((state) => state);

const idsInOrder = useMemo(
() =>
Expand All @@ -71,10 +79,10 @@ export const ControlGroup = () => {
);

const [draggingId, setDraggingId] = useState<string | null>(null);
const draggingIndex = useMemo(
() => (draggingId ? idsInOrder.indexOf(draggingId) : -1),
[idsInOrder, draggingId]
);
const draggingIndex = useMemo(() => (draggingId ? idsInOrder.indexOf(draggingId) : -1), [
idsInOrder,
draggingId,
]);

const sensors = useSensors(
useSensor(PointerSensor),
Expand All @@ -92,63 +100,94 @@ export const ControlGroup = () => {
setDraggingId(null);
};

const emptyState = !(idsInOrder && idsInOrder.length > 0);

return (
<EuiFlexGroup wrap={false} direction="row" alignItems="center" className="superWrapper">
<EuiFlexItem>
<DndContext
onDragStart={({ active }) => setDraggingId(active.id)}
onDragEnd={onDragEnd}
onDragCancel={() => setDraggingId(null)}
sensors={sensors}
collisionDetection={closestCenter}
layoutMeasuring={{
strategy: LayoutMeasuringStrategy.Always,
}}
>
<SortableContext items={idsInOrder} strategy={rectSortingStrategy}>
<EuiFlexGroup
className={classNames('controlGroup', { 'controlGroup-isDragging': draggingId })}
alignItems="center"
gutterSize={'m'}
wrap={true}
>
{idsInOrder.map(
(controlId, index) =>
panels[controlId] && (
<SortableControl
dragInfo={{ index, draggingIndex }}
embeddableId={controlId}
key={controlId}
/>
)
)}
</EuiFlexGroup>
</SortableContext>
<DragOverlay>{draggingId ? <ControlClone draggingId={draggingId} /> : null}</DragOverlay>
</DndContext>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup alignItems="center" direction="row" gutterSize="xs">
<EuiPanel
borderRadius="m"
className={classNames('controlsWrapper', {
'controlsWrapper--empty': emptyState,
'controlsWrapper--twoLine': controlStyle === 'twoLine',
})}
>
{idsInOrder.length > 0 ? (
<EuiFlexGroup gutterSize="m" wrap={false} direction="row" alignItems="center">
<EuiFlexItem>
<EuiToolTip content={ControlGroupStrings.management.getManageButtonTitle()}>
<EuiButtonIcon
aria-label={ControlGroupStrings.management.getManageButtonTitle()}
iconType="gear"
color="text"
data-test-subj="inputControlsSortingButton"
onClick={() =>
openFlyout(forwardAllContext(<EditControlGroup />, reduxContainerContext))
}
/>
</EuiToolTip>
<DndContext
onDragStart={({ active }) => setDraggingId(active.id)}
onDragEnd={onDragEnd}
onDragCancel={() => setDraggingId(null)}
sensors={sensors}
collisionDetection={closestCenter}
layoutMeasuring={{
strategy: LayoutMeasuringStrategy.Always,
}}
>
<SortableContext items={idsInOrder} strategy={rectSortingStrategy}>
<EuiFlexGroup
className={classNames('controlGroup', { 'controlGroup-isDragging': draggingId })}
alignItems="center"
gutterSize={'m'}
wrap={true}
>
{idsInOrder.map(
(controlId, index) =>
panels[controlId] && (
<SortableControl
dragInfo={{ index, draggingIndex }}
embeddableId={controlId}
key={controlId}
/>
)
)}
</EuiFlexGroup>
</SortableContext>
<DragOverlay>
{draggingId ? <ControlClone draggingId={draggingId} /> : null}
</DragOverlay>
</DndContext>
</EuiFlexItem>
<EuiFlexItem>
<EuiToolTip content={ControlGroupStrings.management.getAddControlTitle()}>
<CreateControlButton />
</EuiToolTip>
<EuiFlexItem grow={false}>
<EuiFlexGroup className="groupEditActions" gutterSize="xs">
<EuiFlexItem>
<EuiToolTip content={ControlGroupStrings.management.getManageButtonTitle()}>
<EuiButtonIcon
aria-label={ControlGroupStrings.management.getManageButtonTitle()}
iconType="gear"
color="subdued"
data-test-subj="inputControlsSortingButton"
onClick={() =>
openFlyout(forwardAllContext(<EditControlGroup />, reduxContainerContext))
}
/>
</EuiToolTip>
</EuiFlexItem>
<EuiFlexItem>
<EuiToolTip content={ControlGroupStrings.management.getAddControlTitle()}>
<CreateControlButton />
</EuiToolTip>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
) : (
<>
<EuiFlexGroup alignItems="center" gutterSize="xs">
<EuiFlexItem grow={1}>
<EuiText className="emptyStateText eui-textCenter" size="s">
<p>Controls let you filter and interact with your dashboard data</p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<div className="addControlButton">
<EuiButton size="s" color="primary">
Add control
</EuiButton>
</div>
</EuiFlexItem>
</EuiFlexGroup>
</>
)}
</EuiPanel>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,19 @@ export type SortableControlProps = ControlFrameProps & {
*/
export const SortableControl = (frameProps: SortableControlProps) => {
const { embeddableId } = frameProps;
const { over, listeners, isSorting, transform, transition, attributes, isDragging, setNodeRef } =
useSortable({
id: embeddableId,
animateLayoutChanges: () => true,
});
const {
over,
listeners,
isSorting,
transform,
transition,
attributes,
isDragging,
setNodeRef,
} = useSortable({
id: embeddableId,
animateLayoutChanges: () => true,
});

frameProps.dragInfo = { ...frameProps.dragInfo, isOver: over?.id === embeddableId, isDragging };

Expand Down Expand Up @@ -74,13 +82,13 @@ const SortableControlInner = forwardRef<
return (
<EuiFlexItem
grow={width === 'auto'}
className={classNames('controlFrame--wrapper', {
'controlFrame--wrapper-isDragging': isDragging,
'controlFrame--wrapper-small': width === 'small',
'controlFrame--wrapper-medium': width === 'medium',
'controlFrame--wrapper-large': width === 'large',
'controlFrame--wrapper-insertBefore': isOver && (index ?? -1) < (draggingIndex ?? -1),
'controlFrame--wrapper-insertAfter': isOver && (index ?? -1) > (draggingIndex ?? -1),
className={classNames('controlFrame__wrapper', {
'controlFrame__wrapper-isDragging': isDragging,
'controlFrame__wrapper--small': width === 'small',
'controlFrame__wrapper--medium': width === 'medium',
'controlFrame__wrapper--large': width === 'large',
'controlFrame__wrapper--insertBefore': isOver && (index ?? -1) < (draggingIndex ?? -1),
'controlFrame__wrapper--insertAfter': isOver && (index ?? -1) > (draggingIndex ?? -1),
})}
style={style}
>
Expand All @@ -106,11 +114,11 @@ export const ControlClone = ({ draggingId }: { draggingId: string }) => {
const title = panels[draggingId].explicitInput.title;
return (
<EuiFlexItem
className={classNames('controlFrame--cloneWrapper', {
'controlFrame--cloneWrapper-small': width === 'small',
'controlFrame--cloneWrapper-medium': width === 'medium',
'controlFrame--cloneWrapper-large': width === 'large',
'controlFrame--cloneWrapper-twoLine': controlStyle === 'twoLine',
className={classNames('controlFrame__cloneWrapper', {
'controlFrame__cloneWrapper--small': width === 'small',
'controlFrame__cloneWrapper--medium': width === 'medium',
'controlFrame__cloneWrapper--large': width === 'large',
'controlFrame__cloneWrapper--twoLine': controlStyle === 'twoLine',
})}
>
{controlStyle === 'twoLine' ? <EuiFormLabel>{title}</EuiFormLabel> : undefined}
Expand Down
Loading

0 comments on commit e4f5711

Please sign in to comment.