diff --git a/frontend/src/metabase-lib/lib/queries/drills/object-detail-drill.js b/frontend/src/metabase-lib/lib/queries/drills/object-detail-drill.js new file mode 100644 index 0000000000000000000000000000000000000000..9d244b425c29071187cb694cbbcb35ea2fd3e71f --- /dev/null +++ b/frontend/src/metabase-lib/lib/queries/drills/object-detail-drill.js @@ -0,0 +1,68 @@ +import { isFK, isPK } from "metabase-lib/lib/types/utils/isa"; + +export function objectDetailDrill({ question, clicked }) { + const type = objectDetailDrillType({ question, clicked }); + if (!type) { + return null; + } + + return { + type, + objectId: clicked.value, + hasManyPKColumns: hasManyPKColumns(question), + }; +} + +export function objectDetailPKDrillQuestion({ question, clicked }) { + const { column, value: objectId } = clicked; + return question.filter("=", column, objectId); +} + +export function objectDetailFKDrillQuestion({ question, clicked }) { + const { column, value: objectId } = clicked; + const targetField = getFKTargetField(column, question.metadata()); + return question.drillPK(targetField, objectId); +} + +function objectDetailDrillType({ question, clicked }) { + if (!clicked) { + return null; + } + + const { column, value } = clicked; + if (column == null || value === undefined || !question.query().isEditable()) { + return null; + } + + const { extraData } = clicked; + if (isPK(column) && hasManyPKColumns(question)) { + return "pk"; + } else if (isPK(column) && extraData?.dashboard != null) { + return "dashboard"; + } else if (isPK(column)) { + return "zoom"; + } else if (isFK(column)) { + return "fk"; + } else { + return null; + } +} + +function getFKTargetField(column, metadata) { + const fkField = metadata.field(column.id); + if (fkField?.target) { + return fkField.target; + } + if (column.fk_target_field_id) { + return metadata.field(column.fk_target_field_id); + } + return null; +} + +function hasManyPKColumns(question) { + const fields = question.isDataset() + ? question.getResultMetadata() ?? question.query().table?.()?.fields + : question.query().table?.()?.fields ?? question.getResultMetadata(); + + return fields.filter(field => isPK(field)).length > 1; +} diff --git a/frontend/src/metabase/modes/components/drill/ObjectDetailDrill.jsx b/frontend/src/metabase/modes/components/drill/ObjectDetailDrill.jsx index ffe185e333242041c2ee9aa23666b17df6842cdf..49ef33ea9631468ac81945ea2d8b57199fda8863 100644 --- a/frontend/src/metabase/modes/components/drill/ObjectDetailDrill.jsx +++ b/frontend/src/metabase/modes/components/drill/ObjectDetailDrill.jsx @@ -1,89 +1,54 @@ import { t } from "ttag"; import { zoomInRow } from "metabase/query_builder/actions"; -import { isFK, isPK } from "metabase-lib/lib/types/utils/isa"; - -function hasManyPKColumns(question) { - const fields = question.isDataset() - ? question.getResultMetadata() ?? question.query().table?.()?.fields - : question.query().table?.()?.fields ?? question.getResultMetadata(); - - return fields.filter(field => isPK(field)).length > 1; -} - -function getActionForPKColumn({ question, column, objectId, extraData }) { - if (hasManyPKColumns(question)) { - return ["question", () => question.filter("=", column, objectId)]; - } - - const isDashboard = !!extraData?.dashboard; - - // the question from the dashboard may have filters applied already - if (isDashboard) { - return ["question", () => question]; - } - - return ["action", () => zoomInRow({ objectId })]; -} - -function getBaseActionObject() { - return { - name: "object-detail", - section: "details", - title: t`View details`, - buttonType: "horizontal", - icon: "document", - default: true, - }; -} - -function getPKAction({ question, column, objectId, extraData }) { - const actionObject = getBaseActionObject(); - const [actionKey, action] = getActionForPKColumn({ - question, - column, - objectId, - extraData, - }); - actionObject[actionKey] = action; - return actionObject; -} - -function getFKTargetField(column, metadata) { - const fkField = metadata.field(column.id); - if (fkField?.target) { - return fkField.target; - } - if (column.fk_target_field_id) { - const targetField = metadata.field(column.fk_target_field_id); - return targetField; +import { + objectDetailDrill, + objectDetailFKDrillQuestion, + objectDetailPKDrillQuestion, +} from "metabase-lib/lib/queries/drills/object-detail-drill"; + +function getAction({ question, clicked, type, objectId }) { + switch (type) { + case "pk": + return { + question: () => objectDetailPKDrillQuestion({ question, clicked }), + }; + case "fk": + return { + question: () => objectDetailFKDrillQuestion({ question, clicked }), + }; + case "zoom": + return { action: () => zoomInRow({ objectId }) }; + case "dashboard": + return { question: () => question }; } - return null; } -function getFKAction({ question, column, objectId }) { - const actionObject = getBaseActionObject(); - const targetField = getFKTargetField(column, question.metadata()); - if (!targetField) { - return; +function getActionExtraData({ objectId, hasManyPKColumns }) { + if (!hasManyPKColumns) { + return { + extra: () => ({ objectId }), + }; } - actionObject.question = () => question.drillPK(targetField, objectId); - return actionObject; } export default ({ question, clicked }) => { - if ( - !clicked?.column || - clicked?.value === undefined || - !(isFK(clicked.column) || isPK(clicked.column)) || - !question.query().isEditable() - ) { + const drill = objectDetailDrill({ question, clicked }); + if (!drill) { return []; } - const { column, value: objectId, extraData } = clicked; - const params = { question, column, objectId, extraData }; - const actionObject = isPK(column) ? getPKAction(params) : getFKAction(params); - if (!hasManyPKColumns(question)) { - actionObject.extra = () => ({ objectId }); - } - return actionObject ? [actionObject] : []; + + const { type, objectId, hasManyPKColumns } = drill; + + return [ + { + name: "object-detail", + section: "details", + title: t`View details`, + buttonType: "horizontal", + icon: "document", + default: true, + ...getAction({ question, clicked, type, objectId }), + ...getActionExtraData({ objectId, hasManyPKColumns }), + }, + ]; };