diff --git a/frontend/src/metabase-types/types/Parameter.ts b/frontend/src/metabase-types/types/Parameter.ts index 8f3e8e1778d142c480c21363565144a14277ce4b..fdf8770ad814b6d7d5165cf5903efface7bb28fd 100644 --- a/frontend/src/metabase-types/types/Parameter.ts +++ b/frontend/src/metabase-types/types/Parameter.ts @@ -8,7 +8,10 @@ export type ParameterType = string; export type VariableTarget = ["template-tag", string]; export type ParameterVariableTarget = ["variable", VariableTarget]; export type DimensionTarget = LocalFieldReference | ForeignFieldReference; -export type ParameterDimensionTarget = ["dimension", DimensionTarget]; +export type ParameterDimensionTarget = [ + "dimension", + DimensionTarget | VariableTarget, +]; export type ParameterValueOrArray = string | Array<any>; diff --git a/frontend/src/metabase-types/types/Query.ts b/frontend/src/metabase-types/types/Query.ts index f0df0b0e1b4279e693551b41c5c99469742803c5..9b533783e4f51bf86358e10af1551b5e242c13be 100644 --- a/frontend/src/metabase-types/types/Query.ts +++ b/frontend/src/metabase-types/types/Query.ts @@ -47,7 +47,13 @@ export type DatetimeUnit = export type TemplateTagId = string; export type TemplateTagName = string; -export type TemplateTagType = "card" | "text" | "number" | "date" | "dimension"; +export type TemplateTagType = + | "card" + | "text" + | "number" + | "date" + | "dimension" + | "snippet"; export type TemplateTag = { id: TemplateTagId; diff --git a/frontend/src/metabase/parameters/utils/cards.js b/frontend/src/metabase/parameters/utils/cards.ts similarity index 60% rename from frontend/src/metabase/parameters/utils/cards.js rename to frontend/src/metabase/parameters/utils/cards.ts index eeee751c6473b8c1ab46a3b53da388d2f0bfb6dc..265bed63523f7755ab9d63e4a3de5703615761f1 100644 --- a/frontend/src/metabase/parameters/utils/cards.js +++ b/frontend/src/metabase/parameters/utils/cards.ts @@ -10,35 +10,45 @@ import { getValuePopulatedParameters, hasParameterValue, } from "metabase/parameters/utils/parameter-values"; +import { ParameterWithTarget } from "metabase/parameters/types"; +import { Parameter, ParameterTarget } from "metabase-types/types/Parameter"; +import { Card } from "metabase-types/types/Card"; +import { TemplateTag } from "metabase-types/types/Query"; +import Metadata from "metabase-lib/lib/metadata/Metadata"; -// NOTE: this should mirror `template-tag-parameters` in src/metabase/api/embed.clj -export function getTemplateTagParameters(tags) { - function getTemplateTagType(tag) { - const { type } = tag; - if (type === "date") { - return "date/single"; - } else if (type === "string") { - return "string/="; - } else if (type === "number") { - return "number/="; - } else { - return "category"; - } +function getTemplateTagType(tag: TemplateTag) { + const { type } = tag; + if (type === "date") { + return "date/single"; + // @ts-expect-error -- preserving preexisting incorrect types (for now) + } else if (type === "string") { + return "string/="; + } else if (type === "number") { + return "number/="; + } else { + return "category"; } +} +// NOTE: this should mirror `template-tag-parameters` in src/metabase/api/embed.clj +export function getTemplateTagParameters( + tags: TemplateTag[], +): ParameterWithTarget[] { return tags .filter( tag => tag.type != null && (tag["widget-type"] || tag.type !== "dimension"), ) .map(tag => { + const target: ParameterTarget = + tag.type === "dimension" + ? ["dimension", ["template-tag", tag.name]] + : ["variable", ["template-tag", tag.name]]; + return { id: tag.id, type: tag["widget-type"] || getTemplateTagType(tag), - target: - tag.type === "dimension" - ? ["dimension", ["template-tag", tag.name]] - : ["variable", ["template-tag", tag.name]], + target, name: tag["display-name"], slug: tag.name, default: tag.default, @@ -46,21 +56,24 @@ export function getTemplateTagParameters(tags) { }); } -export function getTemplateTagsForParameters(card) { - const templateTags = +export function getTemplateTagsForParameters(card: Card) { + const templateTags: TemplateTag[] = card && card.dataset_query && card.dataset_query.type === "native" && card.dataset_query.native["template-tags"] ? Object.values(card.dataset_query.native["template-tags"]) : []; + return templateTags.filter( // this should only return template tags that define a parameter of the card tag => tag.type !== "card" && tag.type !== "snippet", ); } -export function getParametersFromCard(card) { +export function getParametersFromCard( + card: Card, +): Parameter[] | ParameterWithTarget[] { if (card && card.parameters) { return card.parameters; } @@ -70,23 +83,25 @@ export function getParametersFromCard(card) { } export function getValueAndFieldIdPopulatedParametersFromCard( - card, - metadata, - parameterValues, + card: Card, + metadata: Metadata, + parameterValues: { [key: string]: any }, ) { if (!card) { return []; } const parameters = getParametersFromCard(card); - const valuePopulatedParameters = getValuePopulatedParameters( - parameters, - parameterValues, - ); + const valuePopulatedParameters: (Parameter[] | ParameterWithTarget[]) & { + value?: any; + } = getValuePopulatedParameters(parameters, parameterValues); const question = new Question(card, metadata); return valuePopulatedParameters.map(parameter => { - const field = getParameterTargetField(parameter.target, metadata, question); + const target: + | ParameterTarget + | undefined = (parameter as ParameterWithTarget).target; + const field = getParameterTargetField(target, metadata, question); return { ...parameter, fields: field == null ? [] : [field], @@ -101,11 +116,15 @@ export function getValueAndFieldIdPopulatedParametersFromCard( // we need to transform this into a map of template tag ids to parameter values // so that we popoulate the template tags in the native editor export function remapParameterValuesToTemplateTags( - templateTags, - dashboardParameters, - parameterValuesByDashboardParameterId, + templateTags: TemplateTag[], + dashboardParameters: ParameterWithTarget[], + parameterValuesByDashboardParameterId: { + [key: string]: any; + }, ) { - const parameterValues = {}; + const parameterValues: { + [key: string]: any; + } = {}; const templateTagParametersByName = _.indexBy(templateTags, "name"); dashboardParameters.forEach(dashboardParameter => {