Skip to content
Snippets Groups Projects
Unverified Commit b50df813 authored by Dalton's avatar Dalton Committed by GitHub
Browse files

add Parameters list component that doesn't automatically update (#15411)

parent f95b5d36
No related branches found
No related tags found
No related merge requests found
......@@ -540,3 +540,14 @@ function splitType(parameterOrType) {
: (parameterOrType || {}).type || "";
return parameterType.split("/");
}
export function collateParametersWithValues(parameters, parameterValues) {
if (parameterValues) {
return parameters.map(p => ({
...p,
value: parameterValues[p.id],
}));
} else {
return parameters;
}
}
import React, { Component } from "react";
import { connect } from "react-redux";
import querystring from "querystring";
import StaticParameterWidget from "./ParameterWidget";
import Icon from "metabase/components/Icon";
import ParametersList from "metabase/parameters/components/ParametersList";
import { collateParametersWithValues } from "metabase/meta/Parameter";
import { getMetadata } from "metabase/selectors/metadata";
import querystring from "querystring";
import cx from "classnames";
import Dimension from "metabase-lib/lib/Dimension";
import type { QueryParams } from "metabase-types/types";
import type {
......@@ -16,9 +14,7 @@ import type {
ParameterValues,
ParameterValueOrArray,
} from "metabase-types/types/Parameter";
import type { DashboardWithCards } from "metabase-types/types/Dashboard";
import Dimension from "metabase-lib/lib/Dimension";
import type Field from "metabase-lib/lib/metadata/Field";
import type Metadata from "metabase-lib/lib/metadata/Metadata";
......@@ -58,11 +54,15 @@ export default class Parameters extends Component {
defaultProps = {
syncQueryString: false,
vertical: false,
commitImmediately: false,
};
UNSAFE_componentWillMount() {
constructor(props) {
super(props);
this.setParameterValuesFromQueryParamOrDefault();
}
setParameterValuesFromQueryParamOrDefault() {
// sync parameters from URL query string
const { parameters, setParameterValue, query, metadata } = this.props;
if (setParameterValue) {
......@@ -95,10 +95,15 @@ export default class Parameters extends Component {
}
componentDidUpdate() {
const { parameters, parameterValues } = this.props;
if (this.props.syncQueryString) {
// sync parameters to URL query string
const queryParams = {};
for (const parameter of this._parametersWithValues()) {
for (const parameter of collateParametersWithValues(
parameters,
parameterValues,
)) {
if (parameter.value) {
queryParams[parameter.slug] = parameter.value;
}
......@@ -117,142 +122,55 @@ export default class Parameters extends Component {
}
}
_parametersWithValues() {
const { parameters, parameterValues } = this.props;
if (parameterValues) {
return parameters.map(p => ({
...p,
value: parameterValues[p.id],
}));
} else {
return parameters;
}
}
handleSortStart = () => {
document.body.classList.add("grabbing");
};
handleSortEnd = ({
oldIndex,
newIndex,
}: {
oldIndex: number,
newIndex: number,
}) => {
document.body.classList.remove("grabbing");
const { parameters, setParameterIndex } = this.props;
if (setParameterIndex) {
setParameterIndex(parameters[oldIndex].id, newIndex);
}
};
render() {
const {
className,
parameters,
dashboard,
editingParameter,
setEditingParameter,
isEditing,
parameterValues,
isFullscreen,
isNightMode,
hideParameters,
isEditing,
isQB,
vertical,
commitImmediately,
setParameterName,
setParameterValue,
setParameterDefaultValue,
setParameterIndex,
removeParameter,
vertical,
commitImmediately,
setEditingParameter,
} = this.props;
const hiddenParameters = new Set((hideParameters || "").split(","));
const parameters = this._parametersWithValues();
let ParameterWidget;
let ParameterWidgetList;
if (isEditing) {
ParameterWidget = SortableParameterWidget;
ParameterWidgetList = SortableParameterWidgetList;
} else {
ParameterWidget = StaticParameterWidget;
ParameterWidgetList = StaticParameterWidgetList;
}
return (
<ParameterWidgetList
className={cx(
className,
"flex align-end flex-wrap",
vertical ? "flex-column" : "flex-row",
{ mt1: isQB },
)}
axis="x"
distance={9}
onSortStart={this.handleSortStart}
onSortEnd={this.handleSortEnd}
>
{parameters
.filter(p => !hiddenParameters.has(p.slug))
.map((parameter, index) => (
<ParameterWidget
key={parameter.id}
className={cx({ mb2: vertical })}
isEditing={isEditing}
isFullscreen={isFullscreen}
isNightMode={isNightMode}
parameter={parameter}
parameters={parameters}
dashboard={this.props.dashboard}
editingParameter={editingParameter}
setEditingParameter={setEditingParameter}
index={index}
setName={
setParameterName &&
(name => setParameterName(parameter.id, name))
}
setValue={
setParameterValue &&
(value => setParameterValue(parameter.id, value))
}
setDefaultValue={
setParameterDefaultValue &&
(value => setParameterDefaultValue(parameter.id, value))
}
remove={removeParameter && (() => removeParameter(parameter.id))}
commitImmediately={commitImmediately}
dragHandle={
isEditing && setParameterIndex ? (
<SortableParameterHandle />
) : null
}
/>
))}
</ParameterWidgetList>
<ParametersList
className={className}
parameters={parameters}
dashboard={dashboard}
editingParameter={editingParameter}
parameterValues={parameterValues}
isFullscreen={isFullscreen}
isNightMode={isNightMode}
hideParameters={hideParameters}
isEditing={isEditing}
isQB={isQB}
vertical={vertical}
commitImmediately={commitImmediately}
setParameterName={setParameterName}
setParameterValue={setParameterValue}
setParameterDefaultValue={setParameterDefaultValue}
setParameterIndex={setParameterIndex}
removeParameter={removeParameter}
setEditingParameter={setEditingParameter}
/>
);
}
}
import {
SortableContainer,
SortableElement,
SortableHandle,
} from "react-sortable-hoc";
const StaticParameterWidgetList = ({ children, ...props }) => {
return <div {...props}>{children}</div>;
};
const SortableParameterHandle = SortableHandle(() => (
<div className="flex layout-centered cursor-grab text-inherit">
<Icon name="grabber2" size={12} />
</div>
));
const SortableParameterWidget = SortableElement(StaticParameterWidget);
const SortableParameterWidgetList = SortableContainer(
StaticParameterWidgetList,
);
export function parseQueryParam(
value: ParameterValueOrArray,
......
import React from "react";
import {
SortableContainer,
SortableElement,
SortableHandle,
} from "react-sortable-hoc";
import cx from "classnames";
import StaticParameterWidget from "./ParameterWidget";
import Icon from "metabase/components/Icon";
import { collateParametersWithValues } from "metabase/meta/Parameter";
import type {
ParameterId,
Parameter,
ParameterValues,
} from "metabase-types/types/Parameter";
import type { DashboardWithCards } from "metabase-types/types/Dashboard";
type Props = {
className?: string,
parameters: Parameter[],
dashboard?: DashboardWithCards,
editingParameter?: ?Parameter,
parameterValues?: ParameterValues,
isFullscreen?: boolean,
isNightMode?: boolean,
hideParameters?: ?string, // comma separated list of slugs
isEditing?: boolean,
isQB?: boolean,
vertical?: boolean,
commitImmediately?: boolean,
setParameterName?: (parameterId: ParameterId, name: string) => void,
setParameterValue?: (parameterId: ParameterId, value: string) => void,
setParameterDefaultValue?: (
parameterId: ParameterId,
defaultValue: string,
) => void,
setParameterIndex?: (parameterId: ParameterId, index: number) => void,
removeParameter?: (parameterId: ParameterId) => void,
setEditingParameter?: (parameterId: ParameterId) => void,
};
const StaticParameterWidgetList = ({ children, ...props }) => {
return <div {...props}>{children}</div>;
};
const SortableParameterHandle = SortableHandle(() => (
<div className="flex layout-centered cursor-grab text-inherit">
<Icon name="grabber2" size={12} />
</div>
));
const SortableParameterWidget = SortableElement(StaticParameterWidget);
const SortableParameterWidgetList = SortableContainer(
StaticParameterWidgetList,
);
function ParametersList({
className,
parameters,
dashboard,
editingParameter,
parameterValues,
isFullscreen,
isNightMode,
hideParameters,
isEditing,
isQB,
vertical,
commitImmediately,
setParameterName,
setParameterValue,
setParameterDefaultValue,
setParameterIndex,
removeParameter,
setEditingParameter,
}: Props) {
const handleSortStart = () => {
document.body.classList.add("grabbing");
};
const handleSortEnd = ({
oldIndex,
newIndex,
}: {
oldIndex: number,
newIndex: number,
}) => {
document.body.classList.remove("grabbing");
if (setParameterIndex) {
setParameterIndex(parameters[oldIndex].id, newIndex);
}
};
const hiddenParameters = new Set((hideParameters || "").split(","));
const collatedParameters = collateParametersWithValues(
parameters,
parameterValues,
);
let ParameterWidget;
let ParameterWidgetList;
if (isEditing) {
ParameterWidget = SortableParameterWidget;
ParameterWidgetList = SortableParameterWidgetList;
} else {
ParameterWidget = StaticParameterWidget;
ParameterWidgetList = StaticParameterWidgetList;
}
return (
<ParameterWidgetList
className={cx(
className,
"flex align-end flex-wrap",
vertical ? "flex-column" : "flex-row",
{ mt1: isQB },
)}
axis="x"
distance={9}
onSortStart={handleSortStart}
onSortEnd={handleSortEnd}
>
{collatedParameters
.filter(p => !hiddenParameters.has(p.slug))
.map((parameter, index) => (
<ParameterWidget
key={parameter.id}
className={cx({ mb2: vertical })}
isEditing={isEditing}
isFullscreen={isFullscreen}
isNightMode={isNightMode}
parameter={parameter}
parameters={collatedParameters}
dashboard={dashboard}
editingParameter={editingParameter}
setEditingParameter={setEditingParameter}
index={index}
setName={
setParameterName && (name => setParameterName(parameter.id, name))
}
setValue={
setParameterValue &&
(value => setParameterValue(parameter.id, value))
}
setDefaultValue={
setParameterDefaultValue &&
(value => setParameterDefaultValue(parameter.id, value))
}
remove={removeParameter && (() => removeParameter(parameter.id))}
commitImmediately={commitImmediately}
dragHandle={
isEditing && setParameterIndex ? (
<SortableParameterHandle />
) : null
}
/>
))}
</ParameterWidgetList>
);
}
ParametersList.defaultProps = {
vertical: false,
commitImmediately: false,
};
export default ParametersList;
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