Skip to content
Snippets Groups Projects
Unverified Commit 270e37f1 authored by Aleksandr Lesnenko's avatar Aleksandr Lesnenko Committed by GitHub
Browse files

support sorting on funnel bar charts (#44943)

* support sorting on funnel bar charts

* fix funnel bar row display setting

* spec
parent 90039279
No related branches found
No related tags found
No related merge requests found
.loki/reference/chrome_laptop_static_viz_FunnelBarChart_Funnel_Bar_Ordered_Rows.png

14 KiB

.loki/reference/chrome_laptop_static_viz_FunnelBarChart_Funnel_Bar_Unordered_Rows.png

14.8 KiB

......@@ -37,3 +37,17 @@ Default.args = {
dashcardSettings: {},
renderingContext,
};
export const FunnelBarOrderedRows = Template.bind({});
FunnelBarOrderedRows.args = {
rawSeries: data.funnelBarOrderedRows as any,
dashcardSettings: {},
renderingContext,
};
export const FunnelBarUnorderedRows = Template.bind({});
FunnelBarUnorderedRows.args = {
rawSeries: data.funnelBarUnorderedRows as any,
dashcardSettings: {},
renderingContext,
};
[
{
"card": {
"original_card_id": 438,
"can_delete": false,
"public_uuid": null,
"parameter_usage_count": 0,
"created_at": "2024-06-29T01:50:01.337123Z",
"parameters": [],
"metabase_version": "v0.2.0-SNAPSHOT (aac751c)",
"collection": {
"metabase.models.collection.root/is-root?": true,
"authority_level": null,
"name": "Our analytics",
"is_personal": false,
"id": "root",
"can_write": true
},
"visualization_settings": {
"funnel.rows": [
{
"key": "Gizmo",
"name": "Gizmo",
"enabled": false
},
{
"key": "Gadget",
"name": "Gadget",
"enabled": true
},
{
"key": "Doohickey",
"name": "Doohickey",
"enabled": true
},
{
"key": "Widget",
"name": "Widget",
"enabled": true
}
],
"funnel.order_dimension": "CATEGORY",
"funnel.type": "bar"
},
"collection_preview": true,
"entity_id": "Hdp2_6fTuVCZNPrfu1iMa",
"archived_directly": false,
"display": "funnel",
"parameter_mappings": [],
"id": 438,
"dataset_query": {
"database": 1,
"type": "query",
"query": {
"source-table": 5,
"aggregation": [["count"]],
"breakout": [
[
"field",
58,
{
"base-type": "type/Text",
"source-field": 40
}
]
]
}
},
"cache_ttl": null,
"embedding_params": null,
"made_public_by_id": null,
"updated_at": "2024-06-29T01:50:01.337123Z",
"moderation_reviews": [],
"can_restore": false,
"creator_id": 1,
"average_query_time": null,
"type": "question",
"last_used_at": null,
"dashboard_count": 0,
"last_query_start": null,
"name": "funnel bar ordered",
"query_type": "query",
"collection_id": null,
"enable_embedding": false,
"database_id": 1,
"trashed_from_collection_id": null,
"can_write": true,
"initially_published_at": null,
"result_metadata": [
{
"description": "The type of product, valid values include: Doohicky, Gadget, Gizmo and Widget",
"semantic_type": "type/Category",
"coercion_strategy": null,
"name": "CATEGORY",
"settings": null,
"fk_target_field_id": null,
"field_ref": [
"field",
58,
{
"base-type": "type/Text",
"source-field": 40
}
],
"effective_type": "type/Text",
"id": 58,
"visibility_type": "normal",
"display_name": "Product → Category",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.375
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Count",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"name": "count",
"base_type": "type/BigInteger",
"effective_type": "type/BigInteger",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Number": {
"min": 3976,
"q1": 4380,
"q3": 5000,
"max": 5061,
"sd": 489.3103990992493,
"avg": 4690
}
}
}
}
],
"can_run_adhoc_query": true,
"table_id": 5,
"collection_position": null,
"view_count": 0,
"archived": false,
"description": null,
"cache_invalidated_at": null,
"displayIsLocked": true
},
"data": {
"rows": [
["Doohickey", 3976],
["Gadget", 4939],
["Gizmo", 4784],
["Widget", 5061]
],
"cols": [
{
"description": "The type of product, valid values include: Doohicky, Gadget, Gizmo and Widget",
"semantic_type": "type/Category",
"table_id": 8,
"coercion_strategy": null,
"name": "CATEGORY",
"settings": null,
"source": "breakout",
"fk_target_field_id": null,
"fk_field_id": 40,
"field_ref": [
"field",
58,
{
"base-type": "type/Text",
"source-field": 40
}
],
"effective_type": "type/Text",
"nfc_path": null,
"parent_id": null,
"id": 58,
"position": 3,
"visibility_type": "normal",
"display_name": "Product → Category",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.375
}
}
},
"base_type": "type/Text",
"source_alias": "PRODUCTS__via__PRODUCT_ID"
},
{
"base_type": "type/BigInteger",
"name": "count",
"display_name": "Count",
"semantic_type": "type/Quantity",
"source": "aggregation",
"field_ref": ["aggregation", 0],
"aggregation_index": 0,
"effective_type": "type/BigInteger"
}
],
"native_form": {
"query": "SELECT \"PRODUCTS__via__PRODUCT_ID\".\"CATEGORY\" AS \"PRODUCTS__via__PRODUCT_ID__CATEGORY\", COUNT(*) AS \"count\" FROM \"PUBLIC\".\"ORDERS\" LEFT JOIN \"PUBLIC\".\"PRODUCTS\" AS \"PRODUCTS__via__PRODUCT_ID\" ON \"PUBLIC\".\"ORDERS\".\"PRODUCT_ID\" = \"PRODUCTS__via__PRODUCT_ID\".\"ID\" GROUP BY \"PRODUCTS__via__PRODUCT_ID\".\"CATEGORY\" ORDER BY \"PRODUCTS__via__PRODUCT_ID\".\"CATEGORY\" ASC",
"params": null
},
"format-rows?": true,
"results_timezone": "America/Toronto",
"requested_timezone": "Etc/GMT",
"results_metadata": {
"columns": [
{
"description": "The type of product, valid values include: Doohicky, Gadget, Gizmo and Widget",
"semantic_type": "type/Category",
"coercion_strategy": null,
"name": "CATEGORY",
"settings": null,
"fk_target_field_id": null,
"field_ref": [
"field",
58,
{
"base-type": "type/Text",
"source-field": 40
}
],
"effective_type": "type/Text",
"id": 58,
"visibility_type": "normal",
"display_name": "Product → Category",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.375
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Count",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"name": "count",
"base_type": "type/BigInteger",
"effective_type": "type/BigInteger",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Number": {
"min": 3976,
"q1": 4380,
"q3": 5000,
"max": 5061,
"sd": 489.3103990992493,
"avg": 4690
}
}
}
}
]
},
"insights": null
}
}
]
[
{
"card": {
"original_card_id": 438,
"can_delete": false,
"public_uuid": null,
"parameter_usage_count": 0,
"created_at": "2024-06-29T01:50:01.337123Z",
"parameters": [],
"metabase_version": "v0.2.0-SNAPSHOT (aac751c)",
"collection": {
"metabase.models.collection.root/is-root?": true,
"authority_level": null,
"name": "Our analytics",
"is_personal": false,
"id": "root",
"can_write": true
},
"visualization_settings": {
"funnel.type": "bar"
},
"collection_preview": true,
"entity_id": "Hdp2_6fTuVCZNPrfu1iMa",
"archived_directly": false,
"display": "funnel",
"parameter_mappings": [],
"id": 438,
"dataset_query": {
"database": 1,
"type": "query",
"query": {
"source-table": 5,
"aggregation": [["count"]],
"breakout": [
[
"field",
58,
{
"base-type": "type/Text",
"source-field": 40
}
]
]
}
},
"cache_ttl": null,
"embedding_params": null,
"made_public_by_id": null,
"updated_at": "2024-06-29T01:50:01.337123Z",
"moderation_reviews": [],
"can_restore": false,
"creator_id": 1,
"average_query_time": null,
"type": "question",
"last_used_at": null,
"dashboard_count": 0,
"last_query_start": null,
"name": "funnel bar ordered",
"query_type": "query",
"collection_id": null,
"enable_embedding": false,
"database_id": 1,
"trashed_from_collection_id": null,
"can_write": true,
"initially_published_at": null,
"result_metadata": [
{
"description": "The type of product, valid values include: Doohicky, Gadget, Gizmo and Widget",
"semantic_type": "type/Category",
"coercion_strategy": null,
"name": "CATEGORY",
"settings": null,
"fk_target_field_id": null,
"field_ref": [
"field",
58,
{
"base-type": "type/Text",
"source-field": 40
}
],
"effective_type": "type/Text",
"id": 58,
"visibility_type": "normal",
"display_name": "Product → Category",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.375
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Count",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"name": "count",
"base_type": "type/BigInteger",
"effective_type": "type/BigInteger",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Number": {
"min": 3976,
"q1": 4380,
"q3": 5000,
"max": 5061,
"sd": 489.3103990992493,
"avg": 4690
}
}
}
}
],
"can_run_adhoc_query": true,
"table_id": 5,
"collection_position": null,
"view_count": 0,
"archived": false,
"description": null,
"cache_invalidated_at": null,
"displayIsLocked": true
},
"data": {
"rows": [
["Doohickey", 3976],
["Gadget", 4939],
["Gizmo", 4784],
["Widget", 5061]
],
"cols": [
{
"description": "The type of product, valid values include: Doohicky, Gadget, Gizmo and Widget",
"semantic_type": "type/Category",
"table_id": 8,
"coercion_strategy": null,
"name": "CATEGORY",
"settings": null,
"source": "breakout",
"fk_target_field_id": null,
"fk_field_id": 40,
"field_ref": [
"field",
58,
{
"base-type": "type/Text",
"source-field": 40
}
],
"effective_type": "type/Text",
"nfc_path": null,
"parent_id": null,
"id": 58,
"position": 3,
"visibility_type": "normal",
"display_name": "Product → Category",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.375
}
}
},
"base_type": "type/Text",
"source_alias": "PRODUCTS__via__PRODUCT_ID"
},
{
"base_type": "type/BigInteger",
"name": "count",
"display_name": "Count",
"semantic_type": "type/Quantity",
"source": "aggregation",
"field_ref": ["aggregation", 0],
"aggregation_index": 0,
"effective_type": "type/BigInteger"
}
],
"native_form": {
"query": "SELECT \"PRODUCTS__via__PRODUCT_ID\".\"CATEGORY\" AS \"PRODUCTS__via__PRODUCT_ID__CATEGORY\", COUNT(*) AS \"count\" FROM \"PUBLIC\".\"ORDERS\" LEFT JOIN \"PUBLIC\".\"PRODUCTS\" AS \"PRODUCTS__via__PRODUCT_ID\" ON \"PUBLIC\".\"ORDERS\".\"PRODUCT_ID\" = \"PRODUCTS__via__PRODUCT_ID\".\"ID\" GROUP BY \"PRODUCTS__via__PRODUCT_ID\".\"CATEGORY\" ORDER BY \"PRODUCTS__via__PRODUCT_ID\".\"CATEGORY\" ASC",
"params": null
},
"format-rows?": true,
"results_timezone": "America/Toronto",
"requested_timezone": "Etc/GMT",
"results_metadata": {
"columns": [
{
"description": "The type of product, valid values include: Doohicky, Gadget, Gizmo and Widget",
"semantic_type": "type/Category",
"coercion_strategy": null,
"name": "CATEGORY",
"settings": null,
"fk_target_field_id": null,
"field_ref": [
"field",
58,
{
"base-type": "type/Text",
"source-field": 40
}
],
"effective_type": "type/Text",
"id": 58,
"visibility_type": "normal",
"display_name": "Product → Category",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Text": {
"percent-json": 0,
"percent-url": 0,
"percent-email": 0,
"percent-state": 0,
"average-length": 6.375
}
}
},
"base_type": "type/Text"
},
{
"display_name": "Count",
"semantic_type": "type/Quantity",
"field_ref": ["aggregation", 0],
"name": "count",
"base_type": "type/BigInteger",
"effective_type": "type/BigInteger",
"fingerprint": {
"global": {
"distinct-count": 4,
"nil%": 0
},
"type": {
"type/Number": {
"min": 3976,
"q1": 4380,
"q3": 5000,
"max": 5061,
"sd": 489.3103990992493,
"avg": 4690
}
}
}
}
]
},
"insights": null
}
}
]
import funnelBarCategorical from "./funnel-bar-categorical.json";
import funnelBarOrderedRows from "./funnel-bar-ordered-rows.json";
import funnelBarUnorderedRows from "./funnel-bar-unordered-rows.json";
export const data = {
funnelBarCategorical,
funnelBarOrderedRows,
funnelBarUnorderedRows,
};
import { isNotNull } from "metabase/lib/types";
import type { TransformSeries } from "metabase/visualizations/components/TransformedVisualization";
import type { RowValue } from "metabase-types/api";
export const funnelToBarTransform: TransformSeries = (
rawSeries,
......@@ -18,7 +20,21 @@ export const funnelToBarTransform: TransformSeries = (
col => col.name === settings["funnel.metric"],
);
return rows.map(row => {
const rowByDimensionValue = rows.reduce((acc, row) => {
acc.set(row[dimensionIndex], row);
return acc;
}, new Map<RowValue, RowValue[]>());
const rowsOrder = settings["funnel.rows"];
const orderedRows =
Array.isArray(rowsOrder) && rowsOrder.length > 0
? rowsOrder
.map(rowOrder =>
rowOrder.enabled ? rowByDimensionValue.get(rowOrder.key) : null,
)
.filter(isNotNull)
: rows;
return orderedRows.map(row => {
const name = renderingContext.formatValue(row[dimensionIndex], {
column: cols[dimensionIndex],
});
......
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