Skip to content
Snippets Groups Projects
Unverified Commit cde7b48c authored by Uladzimir Havenchyk's avatar Uladzimir Havenchyk Committed by GitHub
Browse files

Add don't bin option for temporal bucketing (#35549)

parent aa2c4ec1
No related branches found
No related tags found
No related merge requests found
......@@ -79,6 +79,7 @@ const TIME_BUCKETS = [
"Week of year",
"Month of year",
"Quarter of year",
"Don't bin",
];
const LONGITUDE_BUCKETS = [
......@@ -191,7 +192,8 @@ describe("scenarios > binning > binning options", () => {
});
context("via time series footer (metabase#11183)", () => {
it("should render time series binning options correctly", () => {
// TODO: enable again when metabase#35546 is completed
it.skip("should render time series binning options correctly", () => {
openTable({ table: ORDERS_ID });
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
......
......@@ -95,6 +95,10 @@ export const findTemporalBucket = (
column: ML.ColumnMetadata,
bucketName: string,
) => {
if (bucketName === "Don't bin") {
return null;
}
const buckets = ML.availableTemporalBuckets(query, 0, column);
const bucket = buckets.find(
bucket => ML.displayInfo(query, 0, bucket).displayName === bucketName,
......
......@@ -62,7 +62,9 @@ describe("BucketPickerPopover", () => {
userEvent.click(screen.getByRole("button", { name: "More…" }));
expect(screen.getAllByRole("menuitem")).toHaveLength(buckets.length);
expect(screen.getAllByRole("menuitem")).toHaveLength(
[...buckets, "Don't bin"].length,
);
});
it("shouldn't show the More button if there are a few buckets", async () => {
......@@ -81,7 +83,9 @@ describe("BucketPickerPopover", () => {
const column = Lib.withTemporalBucket(dateColumn, lastBucket);
await setupTemporalBucketPicker({ column });
expect(screen.getAllByRole("menuitem")).toHaveLength(buckets.length);
expect(screen.getAllByRole("menuitem")).toHaveLength(
[...buckets, "Don't bin"].length,
);
expect(screen.queryByText("More…")).not.toBeInTheDocument();
});
......@@ -116,6 +120,8 @@ describe("BucketPickerPopover", () => {
userEvent.click(screen.getByLabelText("Temporal bucket"));
await screen.findByText("Month");
expect(screen.getAllByRole("menuitem")).toHaveLength(buckets.length);
expect(screen.getAllByRole("menuitem")).toHaveLength(
[...buckets, "Don't bin"].length,
);
});
});
......@@ -17,14 +17,22 @@ export function TemporalBucketPickerPopover({
stageIndex,
column,
buckets,
isEditing,
onSelect,
...props
}: CommonBucketPickerProps) {
const selectedBucket = useMemo(() => Lib.temporalBucket(column), [column]);
const items = useMemo(
() => buckets.map(bucket => getBucketListItem(query, stageIndex, bucket)),
[query, stageIndex, buckets],
() => [
...buckets.map(bucket => getBucketListItem(query, stageIndex, bucket)),
{
displayName: t`Don't bin`,
bucket: null,
selected: !selectedBucket && isEditing,
},
],
[buckets, selectedBucket, isEditing, query, stageIndex],
);
const handleBucketSelect = useCallback(
......@@ -38,6 +46,7 @@ export function TemporalBucketPickerPopover({
<BaseBucketPickerPopover
{...props}
query={query}
isEditing={isEditing}
stageIndex={stageIndex}
items={items}
selectedBucket={selectedBucket}
......@@ -50,5 +59,5 @@ export function TemporalBucketPickerPopover({
}
function renderTriggerContent(bucket?: Lib.BucketDisplayInfo) {
return bucket ? t`by ${bucket.displayName.toLowerCase()}` : null;
return bucket ? t`by ${bucket.displayName.toLowerCase()}` : t`Unbinned`;
}
......@@ -35,14 +35,14 @@ function createQueryWithBinning(bucketName = "10 bins") {
return { query, columnInfo: Lib.displayInfo(query, 0, columnWithBinning) };
}
function createQueryWithTemporalBreakout() {
function createQueryWithTemporalBreakout(bucketName: string) {
const initialQuery = createQuery();
const findColumn = columnFinder(
initialQuery,
Lib.breakoutableColumns(initialQuery, 0),
);
const column = findColumn("ORDERS", "CREATED_AT");
const bucket = findTemporalBucket(initialQuery, column, "Quarter");
const bucket = findTemporalBucket(initialQuery, column, bucketName);
const columnWithTemporalBucket = Lib.withTemporalBucket(column, bucket);
const query = Lib.breakout(initialQuery, 0, columnWithTemporalBucket);
return {
......@@ -217,7 +217,7 @@ describe("BreakoutStep", () => {
expect(updateQuery).not.toHaveBeenCalled();
});
it("should highlight the 'Do not bin' option when a column is not binned", async () => {
it("should highlight the `Don't bin` option when a column is not binned", async () => {
const { query, columnInfo } = createQueryWithBinning("Don't bin");
setup(createMockNotebookStep({ topLevelQuery: query }));
......@@ -260,7 +260,7 @@ describe("BreakoutStep", () => {
});
it("should highlight selected temporal bucket", async () => {
const { query } = createQueryWithTemporalBreakout();
const { query } = createQueryWithTemporalBreakout("Quarter");
setup(createMockNotebookStep({ topLevelQuery: query }));
userEvent.click(screen.getByText("Created At: Quarter"));
......@@ -272,8 +272,30 @@ describe("BreakoutStep", () => {
).toHaveAttribute("aria-selected", "true");
});
it("should handle `Don't bin` option for temporal bucket (metabase#19684)", async () => {
const { query } = createQueryWithTemporalBreakout("Don't bin");
setup(createMockNotebookStep({ topLevelQuery: query }));
userEvent.click(screen.getByText("Created At"));
const option = screen.getByRole("option", {
name: "Created At",
});
expect(within(option).getByText("Unbinned")).toBeInTheDocument();
userEvent.click(within(option).getByLabelText("Temporal bucket"));
// click on More... item as Don't bin is hidden
// userEvent.click closes popup
fireEvent.click(await screen.findByText("More…"));
expect(
await screen.findByRole("menuitem", { name: "Don't bin" }),
).toHaveAttribute("aria-selected", "true");
});
it("shouldn't update a query when clicking a selected column with temporal bucketing", async () => {
const { query } = createQueryWithTemporalBreakout();
const { query } = createQueryWithTemporalBreakout("Quarter");
const { updateQuery } = setup(
createMockNotebookStep({ topLevelQuery: query }),
);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment