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

move mapping options function into own utils file (#18638)

* move mapping options function into own utils file

* pull out option-building logic into own functions
parent b12e7260
No related branches found
No related tags found
No related merge requests found
......@@ -4,7 +4,7 @@ import React from "react";
import ParameterTargetWidget from "metabase/parameters/components/ParameterTargetWidget";
import { QuestionLoaderHOC } from "metabase/containers/QuestionLoader";
import * as Dashboard from "metabase/meta/Dashboard";
import { getParameterMappingOptions } from "metabase/parameters/utils/mapping-options";
import type { ParameterTarget } from "metabase-types/types/Parameter";
......@@ -23,11 +23,7 @@ export default class QuestionParameterTargetWidget extends React.Component {
render() {
const { question, ...props } = this.props;
const mappingOptions = question
? Dashboard.getParameterMappingOptions(
question.metadata(),
null,
question.card(),
)
? getParameterMappingOptions(question.metadata(), null, question.card())
: [];
return <ParameterTargetWidget {...props} mappingOptions={mappingOptions} />;
}
......
......@@ -5,10 +5,10 @@ import { createSelector } from "reselect";
import { getMetadata } from "metabase/selectors/metadata";
import {
getParameterMappingOptions as _getParameterMappingOptions,
getMappingsByParameter as _getMappingsByParameter,
getDashboardParametersWithFieldMetadata,
} from "metabase/meta/Dashboard";
import { getParameterMappingOptions as _getParameterMappingOptions } from "metabase/parameters/utils/mapping-options";
import { SIDEBAR_NAME } from "metabase/dashboard/constants";
......
......@@ -3,23 +3,11 @@ import { setIn } from "icepick";
import Question from "metabase-lib/lib/Question";
import { ExpressionDimension } from "metabase-lib/lib/Dimension";
import type Metadata from "metabase-lib/lib/metadata/Metadata";
import type { Card } from "metabase-types/types/Card";
import type {
ParameterOption,
Parameter,
ParameterMappingUIOption,
} from "metabase-types/types/Parameter";
import { getParameterTargetField } from "metabase/meta/Parameter";
import {
dimensionFilterForParameter,
getTagOperatorFilterForParameter,
variableFilterForParameter,
} from "metabase/parameters/utils/filters";
import { slugify } from "metabase/lib/formatting";
export type ParameterSection = {
......@@ -29,74 +17,6 @@ export type ParameterSection = {
options: ParameterOption[],
};
export function getParameterMappingOptions(
metadata: Metadata,
parameter: ?Parameter = null,
card: Card,
): ParameterMappingUIOption[] {
const options = [];
if (card.display === "text") {
// text cards don't have parameters
return [];
}
const question = new Question(card, metadata);
const query = question.query();
if (question.isStructured()) {
options.push(
...query
.dimensionOptions(
parameter ? dimensionFilterForParameter(parameter) : undefined,
)
.sections()
.flatMap(section =>
section.items.map(({ dimension }) => ({
sectionName: section.name,
name: dimension.displayName(),
icon: dimension.icon(),
target: ["dimension", dimension.mbql()],
// these methods don't exist on instances of ExpressionDimension
isForeign: !!(dimension instanceof ExpressionDimension
? false
: dimension.fk() || dimension.joinAlias()),
})),
),
);
} else {
options.push(
...query
.variables(
parameter ? variableFilterForParameter(parameter) : undefined,
)
.map(variable => ({
name: variable.displayName(),
icon: variable.icon(),
isForeign: false,
target: ["variable", variable.mbql()],
})),
);
options.push(
...query
.dimensionOptions(
parameter ? dimensionFilterForParameter(parameter) : undefined,
parameter ? getTagOperatorFilterForParameter(parameter) : undefined,
)
.sections()
.flatMap(section =>
section.items.map(({ dimension }) => ({
name: dimension.displayName(),
icon: dimension.icon(),
isForeign: false,
target: ["dimension", dimension.mbql()],
})),
),
);
}
return options;
}
export function createParameter(
option: ParameterOption,
parameters: Parameter[] = [],
......
import Question from "metabase-lib/lib/Question";
import { ExpressionDimension } from "metabase-lib/lib/Dimension";
import {
dimensionFilterForParameter,
getTagOperatorFilterForParameter,
variableFilterForParameter,
} from "./filters";
function buildStructuredQuerySectionOptions(section) {
return section.items.map(({ dimension }) => ({
sectionName: section.name,
name: dimension.displayName(),
icon: dimension.icon(),
target: ["dimension", dimension.mbql()],
// these methods don't exist on instances of ExpressionDimension
isForeign: !!(dimension instanceof ExpressionDimension
? false
: dimension.fk() || dimension.joinAlias()),
}));
}
function buildNativeQuerySectionOptions(section) {
return section.items.map(({ dimension }) => ({
name: dimension.displayName(),
icon: dimension.icon(),
isForeign: false,
target: ["dimension", dimension.mbql()],
}));
}
function buildVariableOption(variable) {
return {
name: variable.displayName(),
icon: variable.icon(),
isForeign: false,
target: ["variable", variable.mbql()],
};
}
export function getParameterMappingOptions(metadata, parameter = null, card) {
const options = [];
if (card.display === "text") {
// text cards don't have parameters
return [];
}
const question = new Question(card, metadata);
const query = question.query();
if (question.isStructured()) {
options.push(
...query
.dimensionOptions(
parameter ? dimensionFilterForParameter(parameter) : undefined,
)
.sections()
.flatMap(section => buildStructuredQuerySectionOptions(section)),
);
} else {
options.push(
...query
.variables(
parameter ? variableFilterForParameter(parameter) : undefined,
)
.map(buildVariableOption),
);
options.push(
...query
.dimensionOptions(
parameter ? dimensionFilterForParameter(parameter) : undefined,
parameter ? getTagOperatorFilterForParameter(parameter) : undefined,
)
.sections()
.flatMap(section => buildNativeQuerySectionOptions(section)),
);
}
return options;
}
import {
metadata,
SAMPLE_DATASET,
REVIEWS,
ORDERS,
PRODUCTS,
} from "__support__/sample_dataset_fixture";
import { getParameterMappingOptions } from "./mapping-options";
function structured(query) {
return SAMPLE_DATASET.question(query).card();
}
function native(native) {
return SAMPLE_DATASET.nativeQuestion(native).card();
}
describe("parameters/utils/mapping-options", () => {
describe("getParameterMappingOptions", () => {
describe("Structured Query", () => {
it("should return field-id and fk-> dimensions", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
structured({
"source-table": REVIEWS.id,
}),
);
expect(options).toEqual([
{
sectionName: "Review",
icon: "calendar",
name: "Created At",
target: ["dimension", ["field", REVIEWS.CREATED_AT.id, null]],
isForeign: false,
},
{
sectionName: "Product",
name: "Created At",
icon: "calendar",
target: [
"dimension",
[
"field",
PRODUCTS.CREATED_AT.id,
{ "source-field": REVIEWS.PRODUCT_ID.id },
],
],
isForeign: true,
},
]);
});
it("should also return fields from explicitly joined tables", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
structured({
"source-table": REVIEWS.id,
joins: [
{
alias: "Joined Table",
"source-table": ORDERS.id,
},
],
}),
);
expect(options).toEqual([
{
sectionName: "Review",
name: "Created At",
icon: "calendar",
target: ["dimension", ["field", 30, null]],
isForeign: false,
},
{
sectionName: "Joined Table",
name: "Created At",
icon: "calendar",
target: [
"dimension",
["field", 1, { "join-alias": "Joined Table" }],
],
isForeign: true,
},
{
sectionName: "Product",
name: "Created At",
icon: "calendar",
target: ["dimension", ["field", 22, { "source-field": 32 }]],
isForeign: true,
},
]);
});
it("should return fields in nested query", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
structured({
"source-query": {
"source-table": ORDERS.id,
},
}),
);
expect(options).toEqual([
{
sectionName: null,
name: "Created At",
icon: "calendar",
target: [
"dimension",
["field", "CREATED_AT", { "base-type": "type/DateTime" }],
],
isForeign: false,
},
]);
});
});
describe("NativeQuery", () => {
it("should return variables for non-dimension template-tags", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
native({
query: "select * from ORDERS where CREATED_AT = {{created}}",
"template-tags": {
created: {
type: "date",
name: "created",
},
},
}),
);
expect(options).toEqual([
{
name: "created",
icon: "calendar",
target: ["variable", ["template-tag", "created"]],
isForeign: false,
},
]);
});
});
it("should return dimensions for dimension template-tags", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
native({
query: "select * from ORDERS where CREATED_AT = {{created}}",
"template-tags": {
created: {
type: "dimension",
name: "created",
dimension: ["field", ORDERS.CREATED_AT.id, null],
},
},
}),
);
expect(options).toEqual([
{
name: "Created At",
icon: "calendar",
target: ["dimension", ["template-tag", "created"]],
isForeign: false,
},
]);
});
});
});
import {
metadata,
SAMPLE_DATASET,
REVIEWS,
ORDERS,
PRODUCTS,
} from "__support__/sample_dataset_fixture";
import {
createParameter,
setParameterName,
setParameterDefaultValue,
getParameterMappingOptions,
hasMapping,
isDashboardParameterWithoutMapping,
getMappingsByParameter,
......@@ -18,14 +10,6 @@ import DASHBOARD_WITH_BOOLEAN_PARAMETER from "./dashboard-with-boolean-parameter
import Field from "metabase-lib/lib/metadata/Field";
function structured(query) {
return SAMPLE_DATASET.question(query).card();
}
function native(native) {
return SAMPLE_DATASET.nativeQuestion(native).card();
}
describe("meta/Dashboard", () => {
describe("createParameter", () => {
it("should create a new parameter using the given parameter option", () => {
......@@ -122,157 +106,6 @@ describe("meta/Dashboard", () => {
});
});
describe("getParameterMappingOptions", () => {
describe("Structured Query", () => {
it("should return field-id and fk-> dimensions", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
structured({
"source-table": REVIEWS.id,
}),
);
expect(options).toEqual([
{
sectionName: "Review",
icon: "calendar",
name: "Created At",
target: ["dimension", ["field", REVIEWS.CREATED_AT.id, null]],
isForeign: false,
},
{
sectionName: "Product",
name: "Created At",
icon: "calendar",
target: [
"dimension",
[
"field",
PRODUCTS.CREATED_AT.id,
{ "source-field": REVIEWS.PRODUCT_ID.id },
],
],
isForeign: true,
},
]);
});
it("should also return fields from explicitly joined tables", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
structured({
"source-table": REVIEWS.id,
joins: [
{
alias: "Joined Table",
"source-table": ORDERS.id,
},
],
}),
);
expect(options).toEqual([
{
sectionName: "Review",
name: "Created At",
icon: "calendar",
target: ["dimension", ["field", 30, null]],
isForeign: false,
},
{
sectionName: "Joined Table",
name: "Created At",
icon: "calendar",
target: [
"dimension",
["field", 1, { "join-alias": "Joined Table" }],
],
isForeign: true,
},
{
sectionName: "Product",
name: "Created At",
icon: "calendar",
target: ["dimension", ["field", 22, { "source-field": 32 }]],
isForeign: true,
},
]);
});
it("should return fields in nested query", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
structured({
"source-query": {
"source-table": ORDERS.id,
},
}),
);
expect(options).toEqual([
{
sectionName: null,
name: "Created At",
icon: "calendar",
target: [
"dimension",
["field", "CREATED_AT", { "base-type": "type/DateTime" }],
],
isForeign: false,
},
]);
});
});
describe("NativeQuery", () => {
it("should return variables for non-dimension template-tags", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
native({
query: "select * from ORDERS where CREATED_AT = {{created}}",
"template-tags": {
created: {
type: "date",
name: "created",
},
},
}),
);
expect(options).toEqual([
{
name: "created",
icon: "calendar",
target: ["variable", ["template-tag", "created"]],
isForeign: false,
},
]);
});
});
it("should return dimensions for dimension template-tags", () => {
const options = getParameterMappingOptions(
metadata,
{ type: "date/single" },
native({
query: "select * from ORDERS where CREATED_AT = {{created}}",
"template-tags": {
created: {
type: "dimension",
name: "created",
dimension: ["field", ORDERS.CREATED_AT.id, null],
},
},
}),
);
expect(options).toEqual([
{
name: "Created At",
icon: "calendar",
target: ["dimension", ["template-tag", "created"]],
isForeign: false,
},
]);
});
});
describe("hasMapping", () => {
const parameter = { id: "foo" };
......
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