Skip to content
Snippets Groups Projects
Unverified Commit e3dffcc4 authored by Romeo Van Snick's avatar Romeo Van Snick Committed by GitHub
Browse files

Combine column shortcut (#42442)

* Add index file to CombineColumns

* Add CombinColumnAction

* Add CombinColumnsAction to default and embedding modes

* Fix outdated --color-brand references

* Set up sequenced close handler in combine columns

* Allow outside clicks to happen when popover is not open

* Add e2e test for combine column shortcut

* Remove unused prop

* Rename file to match component name: CombineColumnsAction

* Simplify test assertion

* Set width on combine columns action

* Remove superflouous ? check
parent f596f0b0
No related branches found
No related tags found
No related merge requests found
Showing
with 158 additions and 7 deletions
import _ from "underscore";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import { restore, popover, createQuestion } from "e2e/support/helpers";
const { PEOPLE, PEOPLE_ID } = SAMPLE_DATABASE;
describe("scenarios > visualizations > combine shortcut", () => {
beforeEach(() => {
restore();
cy.signInAsNormalUser();
});
it("should be possible add a new column through the combine columns shortcut", () => {
createQuestion(
{
query: {
"source-table": PEOPLE_ID,
limit: 1,
fields: [
["field", PEOPLE.ID, null],
["field", PEOPLE.EMAIL, null],
],
},
},
{
visitQuestion: true,
},
);
combineColumns({
columns: ["Email", "ID"],
newColumn: "Combined Email, ID",
example: "email@example.com12345",
newValue: "borer-hudson@yahoo.com1",
});
});
});
function combineColumns({
columns,
example,
newColumn,
newValue,
}: {
columns: string[];
example: string;
newColumn: string;
newValue?: string;
}) {
const requestAlias = _.uniqueId("dataset");
cy.intercept("POST", "/api/dataset").as(requestAlias);
cy.findByLabelText("Add column").click();
popover().findByText("Combine columns").click();
for (const column of columns) {
selectColumn(column);
}
if (example) {
popover().findByTestId("combine-example").should("have.text", example);
}
popover().button("Done").click();
cy.wait(`@${requestAlias}`);
cy.findByRole("columnheader", { name: newColumn }).should("be.visible");
if (newValue) {
cy.findByRole("gridcell", { name: newValue }).should("be.visible");
}
}
function selectColumn(name: string) {
popover().findAllByText("Select a column...").first().click();
popover().last().findByText(name).click();
}
......@@ -14,7 +14,7 @@ button.root {
&.open,
&:focus-visible {
border-color: var(--color-brand);
border-color: var(--mb-color-brand);
outline: none;
}
}
......@@ -125,7 +125,9 @@ export function ColumnInput({
{text}
</Button>
</Popover.Target>
<Popover.Dropdown>{dropdown}</Popover.Dropdown>
<Popover.Dropdown setupSequencedCloseHandler={open}>
{dropdown}
</Popover.Dropdown>
</Popover>
</Input.Wrapper>
);
......
......@@ -21,6 +21,7 @@ interface Props {
query: Lib.Query;
stageIndex: number;
onSubmit: (name: string, clause: Lib.ExpressionClause) => void;
width?: number;
}
type State = {
......@@ -35,6 +36,7 @@ export function CombineColumns({
query: originalQuery,
stageIndex: originalStageIndex,
onSubmit,
width,
}: Props) {
const [state, setState] = useState<State>({
columnsAndSeparators: [
......@@ -146,7 +148,7 @@ export function CombineColumns({
return (
<form onSubmit={handleSubmit}>
<Box maw="100vw" p="lg" pt={0}>
<Box maw="100vw" w={width} p="lg" pt={0}>
<Stack spacing="lg" mt="lg">
<Stack spacing="md">
<Box>
......
export { CombineColumns } from "./CombineColumns";
......@@ -14,7 +14,7 @@ import {
trackColumnExtractViaShortcut,
} from "../../analytics";
import { CombineColumns } from "./CombineColumns/CombineColumns";
import { CombineColumns } from "./CombineColumns";
import { ExpressionEditorTextfield } from "./ExpressionEditorTextfield";
import {
ActionButtonsWrapper,
......
......@@ -14,7 +14,7 @@ button.root {
&.open,
&:focus-visible {
border-color: var(--color-brand);
border-color: var(--mb-color-brand);
outline: none;
}
}
......@@ -129,7 +129,7 @@ export function ColumnPicker({
{text}
</Button>
</Popover.Target>
<Popover.Dropdown setupSequencedCloseHandler onBlur={handleBlur}>
<Popover.Dropdown setupSequencedCloseHandler={open} onBlur={handleBlur}>
{dropdown}
</Popover.Dropdown>
</Popover>
......
import { t } from "ttag";
import { CombineColumns } from "metabase/query_builder/components/expressions/CombineColumns";
import type { LegacyDrill } from "metabase/visualizations/types";
import type { ClickActionPopoverProps } from "metabase/visualizations/types/click-actions";
import * as Lib from "metabase-lib";
export const CombineColumnsAction: LegacyDrill = ({ question, clicked }) => {
const { isEditable } = Lib.queryDisplayInfo(question.query());
if (
!clicked ||
clicked.value !== undefined ||
!clicked.columnShortcuts ||
clicked.extraData?.isRawTable ||
!isEditable
) {
return [];
}
const Popover = ({
onChangeCardAndRun,
onClose,
}: ClickActionPopoverProps) => {
const query = question.query();
const stageIndex = -1;
function handleSubmit(name: string, clause: Lib.ExpressionClause) {
const newQuery = Lib.expression(query, stageIndex, name, clause);
const nextQuestion = question.setQuery(newQuery);
const nextCard = nextQuestion.card();
onChangeCardAndRun({ nextCard });
onClose();
}
return (
<CombineColumns
query={query}
stageIndex={stageIndex}
onSubmit={handleSubmit}
width={474}
/>
);
};
return [
{
name: "column-combine",
title: t`Combine columns`,
tooltip: t`Combine columns`,
buttonType: "horizontal",
icon: "combine",
default: true,
section: "new-column",
popover: Popover,
},
];
};
export { CombineColumnsAction } from "./CombineColumnsAction";
import type { QueryClickActionsMode } from "../../types";
import { ColumnFormattingAction } from "../actions/ColumnFormattingAction";
import { CombineColumnsAction } from "../actions/CombineColumnsAction";
import { DashboardClickAction } from "../actions/DashboardClickAction";
import { ExtractColumnAction } from "../actions/ExtractColumn";
import { HideColumnAction } from "../actions/HideColumnAction";
......@@ -13,6 +14,7 @@ export const DefaultMode: QueryClickActionsMode = {
ColumnFormattingAction,
DashboardClickAction,
ExtractColumnAction,
CombineColumnsAction,
],
fallback: NativeQueryClickFallback,
};
import type { QueryClickActionsMode } from "../../types";
import { CombineColumnsAction } from "../actions/CombineColumnsAction";
import { DashboardClickAction } from "../actions/DashboardClickAction";
import { ExtractColumnAction } from "../actions/ExtractColumn";
import { HideColumnAction } from "../actions/HideColumnAction";
......@@ -24,6 +25,11 @@ export const EmbeddingSdkMode: QueryClickActionsMode = {
"drill-thru/zoom-in.geographic",
"drill-thru/zoom-in.timeseries",
],
clickActions: [HideColumnAction, DashboardClickAction, ExtractColumnAction],
clickActions: [
HideColumnAction,
DashboardClickAction,
ExtractColumnAction,
CombineColumnsAction,
],
fallback: NativeQueryClickFallback,
};
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