Skip to content
Snippets Groups Projects
Unverified Commit ca839750 authored by Nick Fitzpatrick's avatar Nick Fitzpatrick Committed by GitHub
Browse files

40232 sortable with popovers (#40378)

* custom sensor

* e2e test, moving sortable

* e2e test adjustment

* combining props
parent 5c946b30
No related branches found
No related tags found
No related merge requests found
import {
restore,
openNativeEditor,
filterWidget,
popover,
moveDnDKitElement,
} from "e2e/support/helpers";
import * as SQLFilter from "../helpers/e2e-sql-filter-helpers";
describe("issue 31606", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
it("should not start drag and drop from clicks on popovers", () => {
openNativeEditor();
SQLFilter.enterParameterizedQuery("{{foo}} {{bar}}");
cy.findAllByRole("radio", { name: "Search box" }).first().click();
filterWidget().first().click();
moveDnDKitElement(popover().findByText("Add filter"), {
horizontal: 300,
});
filterWidget()
.should("have.length", 2)
.first()
.should("contain.text", "Foo");
});
});
......@@ -16,6 +16,7 @@ describe("issue 9357", () => {
// Drag the firstparameter to last position
cy.get("fieldset")
.findAllByRole("listitem")
.first()
.trigger("pointerdown", 0, 0, { force: true, isPrimary: true, button: 0 })
.wait(200)
......
......@@ -11,6 +11,7 @@ import { DateRelativeWidget } from "metabase/components/DateRelativeWidget";
import { DateSingleWidget } from "metabase/components/DateSingleWidget";
import PopoverWithTrigger from "metabase/components/PopoverWithTrigger";
import { TextWidget } from "metabase/components/TextWidget";
import { Sortable } from "metabase/core/components/Sortable";
import FormattedParameterValue from "metabase/parameters/components/FormattedParameterValue";
import { WidgetStatusIcon } from "metabase/parameters/components/WidgetStatusIcon";
import { NumberInputWidget } from "metabase/parameters/components/widgets/NumberInputWidget";
......@@ -60,6 +61,7 @@ class ParameterValueWidget extends Component {
// Don't use in settings sidebars.
enableRequiredBehavior: PropTypes.bool,
mimicMantine: PropTypes.bool,
isSortable: PropTypes.bool,
};
state = { isFocused: false };
......@@ -154,6 +156,21 @@ class ParameterValueWidget extends Component {
}
}
wrapSortable(children) {
const { isSortable = false, parameter } = this.props;
return (
<Sortable
id={parameter.id}
draggingStyle={{ opacity: 0.5 }}
disabled={!isSortable}
role="listitem"
>
{children}
</Sortable>
);
}
render() {
const {
parameter,
......@@ -170,7 +187,7 @@ class ParameterValueWidget extends Component {
const showTypeIcon = !isEditing && !hasValue && !isFocused;
if (noPopover) {
return (
return this.wrapSortable(
<ParameterValueWidgetTrigger
className={cx(S.noPopover, className)}
hasValue={hasValue}
......@@ -189,7 +206,7 @@ class ParameterValueWidget extends Component {
onPopoverClose={this.onPopoverClose}
/>
{this.getActionIcon()}
</ParameterValueWidgetTrigger>
</ParameterValueWidgetTrigger>,
);
}
......@@ -203,7 +220,7 @@ class ParameterValueWidget extends Component {
<PopoverWithTrigger
ref={this.valuePopover}
targetOffsetX={16}
triggerElement={
triggerElement={this.wrapSortable(
<ParameterValueWidgetTrigger
ref={this.trigger}
hasValue={hasValue}
......@@ -226,8 +243,8 @@ class ParameterValueWidget extends Component {
/>
</div>
{this.getActionIcon()}
</ParameterValueWidgetTrigger>
}
</ParameterValueWidgetTrigger>,
)}
target={this.getTargetRef}
// make sure the full date picker will expand to fit the dual calendars
autoWidth={parameter.type === "date/all-options"}
......
......@@ -2,6 +2,8 @@
import PropTypes from "prop-types";
import { Component } from "react";
import { Sortable } from "metabase/core/components/Sortable";
import ParameterValueWidget from "../ParameterValueWidget";
import {
......@@ -27,6 +29,7 @@ export class ParameterWidget extends Component {
static defaultProps = {
parameter: null,
commitImmediately: false,
isSortable: false,
};
renderPopover(value, setValue, placeholder, isFullscreen) {
......@@ -39,6 +42,8 @@ export class ParameterWidget extends Component {
parameters,
setParameterValueToDefault,
enableParameterRequiredBehavior,
isSortable,
isEditing,
} = this.props;
const isEditingParameter = editingParameter?.id === parameter.id;
......@@ -59,6 +64,7 @@ export class ParameterWidget extends Component {
commitImmediately={commitImmediately}
setParameterValueToDefault={setParameterValueToDefault}
enableRequiredBehavior={enableParameterRequiredBehavior}
isSortable={isSortable && isEditing}
/>
);
}
......@@ -109,18 +115,25 @@ export class ParameterWidget extends Component {
};
const renderEditing = () => (
<ParameterContainer
isEditingParameter={isEditingParameter}
onClick={() =>
setEditingParameter(isEditingParameter ? null : parameter.id)
}
<Sortable
id={parameter.id}
draggingStyle={{ opacity: 0.5 }}
disabled={!isEditing}
role="listitem"
>
<div className="mr1" onClick={e => e.stopPropagation()}>
{dragHandle}
</div>
{parameter.name}
<SettingsIcon name="gear" size={16} />
</ParameterContainer>
<ParameterContainer
isEditingParameter={isEditingParameter}
onClick={() =>
setEditingParameter(isEditingParameter ? null : parameter.id)
}
>
<div className="mr1" onClick={e => e.stopPropagation()}>
{dragHandle}
</div>
{parameter.name}
<SettingsIcon name="gear" size={16} />
</ParameterContainer>
</Sortable>
);
if (isFullscreen) {
......
......@@ -3,7 +3,7 @@ import { useSensor, PointerSensor } from "@dnd-kit/core";
import cx from "classnames";
import { useCallback, useMemo } from "react";
import { SortableList, Sortable } from "metabase/core/components/Sortable";
import { SortableList } from "metabase/core/components/Sortable";
import { getVisibleParameters } from "metabase/parameters/utils/ui";
import { Icon } from "metabase/ui";
......@@ -33,8 +33,9 @@ function ParametersList({
enableParameterRequiredBehavior,
}) {
const pointerSensor = useSensor(PointerSensor, {
activationConstraint: { distance: 0 },
activationConstraint: { distance: 5 },
});
const visibleValuePopulatedParameters = useMemo(
() => getVisibleParameters(parameters, hideParameters),
[parameters, hideParameters],
......@@ -50,40 +51,34 @@ function ParametersList({
);
const renderItem = ({ item: valuePopulatedParameter, id }) => (
<Sortable
id={id}
<ParameterWidget
key={`sortable-${id}`}
disabled={!isEditing}
draggingStyle={{ opacity: 0.5 }}
role="listitem"
>
<ParameterWidget
className={cx({ mb2: vertical })}
isEditing={isEditing}
isFullscreen={isFullscreen}
isNightMode={isNightMode}
parameter={valuePopulatedParameter}
parameters={parameters}
question={question}
dashboard={dashboard}
editingParameter={editingParameter}
setEditingParameter={setEditingParameter}
setValue={
setParameterValue &&
(value => setParameterValue(valuePopulatedParameter.id, value))
}
setParameterValueToDefault={setParameterValueToDefault}
enableParameterRequiredBehavior={enableParameterRequiredBehavior}
commitImmediately={commitImmediately}
dragHandle={
isEditing && setParameterIndex ? (
<div className="flex layout-centered cursor-grab text-inherit">
<Icon name="grabber" />
</div>
) : null
}
/>
</Sortable>
className={cx({ mb2: vertical })}
isEditing={isEditing}
isFullscreen={isFullscreen}
isNightMode={isNightMode}
parameter={valuePopulatedParameter}
parameters={parameters}
question={question}
dashboard={dashboard}
editingParameter={editingParameter}
setEditingParameter={setEditingParameter}
setValue={
setParameterValue &&
(value => setParameterValue(valuePopulatedParameter.id, value))
}
setParameterValueToDefault={setParameterValueToDefault}
enableParameterRequiredBehavior={enableParameterRequiredBehavior}
commitImmediately={commitImmediately}
dragHandle={
isEditing && setParameterIndex ? (
<div className="flex layout-centered cursor-grab text-inherit">
<Icon name="grabber" />
</div>
) : null
}
isSortable
/>
);
return visibleValuePopulatedParameters.length > 0 ? (
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment