99from ninja import Router , Schema , Field
1010from ninja .errors import HttpError
1111from django .shortcuts import get_object_or_404
12- from django .http import HttpResponse , StreamingHttpResponse
12+ from django .http import StreamingHttpResponse
1313
1414from ddpui .auth import has_permission
1515from ddpui .models .org_user import OrgUser
1616from ddpui .models .org import OrgWarehouse
17+ from ddpui .models .dashboard import DashboardFilter
1718from ddpui .models .visualization import Chart
1819from ddpui .core .charts import charts_service
1920from ddpui .core .charts .echarts_config_generator import EChartsConfigGenerator
@@ -571,8 +572,16 @@ def get_chart_data(request, payload: ChartDataPayload):
571572
572573@charts_router .post ("/chart-data-preview/" , response = DataPreviewResponse )
573574@has_permission (["can_view_charts" ])
574- def get_chart_data_preview (request , payload : ChartDataPayload , page : int = 0 , limit : int = 100 ):
575+ def get_chart_data_preview (
576+ request ,
577+ payload : ChartDataPayload ,
578+ page : int = 0 ,
579+ limit : int = 100 ,
580+ dashboard_filters : Optional [str ] = None ,
581+ ):
575582 """Get paginated data preview for chart using the same query as chart data"""
583+ import json
584+
576585 orguser = request .orguser
577586
578587 # Validate user has access to schema/table
@@ -583,9 +592,73 @@ def get_chart_data_preview(request, payload: ChartDataPayload, page: int = 0, li
583592 if not org_warehouse :
584593 raise HttpError (404 , "Warehouse not configured" )
585594
595+ # Parse and resolve dashboard filters if provided (same logic as chart data endpoint)
596+ resolved_dashboard_filters = None
597+ if dashboard_filters :
598+ try :
599+ filter_values = json .loads (dashboard_filters )
600+ logger .info (f"Applying dashboard filters to chart data preview: { filter_values } " )
601+
602+ # Resolve filter configurations to get column information
603+
604+ # Get warehouse client to check column existence
605+ warehouse_client = WarehouseFactory .get_warehouse_client (org_warehouse )
606+ resolved_filters = []
607+
608+ for filter_id , filter_value in filter_values .items ():
609+ if filter_value is not None :
610+ try :
611+ # Get the filter configuration from the database
612+ dashboard_filter = DashboardFilter .objects .get (id = filter_id )
613+
614+ # Only apply this filter if it applies to the same table as the chart
615+ if warehouse_client .column_exists (
616+ payload .schema_name , payload .table_name , dashboard_filter .column_name
617+ ):
618+ resolved_filters .append (
619+ {
620+ "filter_id" : filter_id ,
621+ "column" : dashboard_filter .column_name ,
622+ "type" : dashboard_filter .filter_type ,
623+ "value" : filter_value ,
624+ "settings" : dashboard_filter .settings ,
625+ }
626+ )
627+ except DashboardFilter .DoesNotExist :
628+ logger .warning (f"Dashboard filter { filter_id } not found" )
629+
630+ resolved_dashboard_filters = resolved_filters
631+
632+ except json .JSONDecodeError :
633+ logger .error (f"Invalid dashboard_filters JSON: { dashboard_filters } " )
634+ resolved_dashboard_filters = None
635+
636+ # Create a modified payload with dashboard filters
637+ modified_payload = ChartDataPayload (
638+ chart_type = payload .chart_type ,
639+ computation_type = payload .computation_type ,
640+ schema_name = payload .schema_name ,
641+ table_name = payload .table_name ,
642+ x_axis = payload .x_axis ,
643+ y_axis = payload .y_axis ,
644+ dimension_col = payload .dimension_col ,
645+ extra_dimension = payload .extra_dimension ,
646+ metrics = payload .metrics ,
647+ geographic_column = payload .geographic_column ,
648+ value_column = payload .value_column ,
649+ selected_geojson_id = payload .selected_geojson_id ,
650+ customizations = payload .customizations ,
651+ offset = payload .offset ,
652+ limit = payload .limit ,
653+ extra_config = payload .extra_config ,
654+ dashboard_filters = resolved_dashboard_filters , # Add resolved dashboard filters
655+ )
656+
586657 # Get table preview using the same query builder as chart data
587658 # This ensures preview shows exactly what will be used for the chart
588- preview_data = charts_service .get_chart_data_table_preview (org_warehouse , payload , page , limit )
659+ preview_data = charts_service .get_chart_data_table_preview (
660+ org_warehouse , modified_payload , page , limit
661+ )
589662
590663 return DataPreviewResponse (
591664 columns = preview_data ["columns" ],
@@ -598,8 +671,12 @@ def get_chart_data_preview(request, payload: ChartDataPayload, page: int = 0, li
598671
599672@charts_router .post ("/chart-data-preview/total-rows/" , response = int )
600673@has_permission (["can_view_charts" ])
601- def get_chart_data_preview_total_rows (request , payload : ChartDataPayload ):
674+ def get_chart_data_preview_total_rows (
675+ request , payload : ChartDataPayload , dashboard_filters : Optional [str ] = None
676+ ):
602677 """Get total rows for chart data preview"""
678+ import json
679+
603680 orguser = request .orguser
604681
605682 # Validate user has access to schema/table
@@ -610,8 +687,73 @@ def get_chart_data_preview_total_rows(request, payload: ChartDataPayload):
610687 if not org_warehouse :
611688 raise HttpError (404 , "Warehouse not configured" )
612689
690+ # Parse and resolve dashboard filters if provided (same logic as chart data endpoint)
691+ resolved_dashboard_filters = None
692+ if dashboard_filters :
693+ try :
694+ filter_values = json .loads (dashboard_filters )
695+ logger .info (
696+ f"Applying dashboard filters to chart data preview total rows: { filter_values } "
697+ )
698+
699+ # Resolve filter configurations to get column information
700+ from ddpui .models .dashboard import DashboardFilter
701+
702+ # Get warehouse client to check column existence
703+ warehouse_client = WarehouseFactory .get_warehouse_client (org_warehouse )
704+ resolved_filters = []
705+
706+ for filter_id , filter_value in filter_values .items ():
707+ if filter_value is not None :
708+ try :
709+ # Get the filter configuration from the database
710+ dashboard_filter = DashboardFilter .objects .get (id = filter_id )
711+
712+ # Only apply this filter if it applies to the same table as the chart
713+ if warehouse_client .column_exists (
714+ payload .schema_name , payload .table_name , dashboard_filter .column_name
715+ ):
716+ resolved_filters .append (
717+ {
718+ "filter_id" : filter_id ,
719+ "column" : dashboard_filter .column_name ,
720+ "type" : dashboard_filter .filter_type ,
721+ "value" : filter_value ,
722+ "settings" : dashboard_filter .settings ,
723+ }
724+ )
725+ except DashboardFilter .DoesNotExist :
726+ logger .warning (f"Dashboard filter { filter_id } not found" )
727+
728+ resolved_dashboard_filters = resolved_filters
729+
730+ except json .JSONDecodeError :
731+ logger .error (f"Invalid dashboard_filters JSON: { dashboard_filters } " )
732+ resolved_dashboard_filters = None
733+
734+ # Create a modified payload with dashboard filters
735+ modified_payload = ChartDataPayload (
736+ chart_type = payload .chart_type ,
737+ computation_type = payload .computation_type ,
738+ schema_name = payload .schema_name ,
739+ table_name = payload .table_name ,
740+ x_axis = payload .x_axis ,
741+ y_axis = payload .y_axis ,
742+ dimension_col = payload .dimension_col ,
743+ extra_dimension = payload .extra_dimension ,
744+ metrics = payload .metrics ,
745+ geographic_column = payload .geographic_column ,
746+ value_column = payload .value_column ,
747+ selected_geojson_id = payload .selected_geojson_id ,
748+ customizations = payload .customizations ,
749+ offset = payload .offset ,
750+ limit = payload .limit ,
751+ extra_config = payload .extra_config ,
752+ dashboard_filters = resolved_dashboard_filters , # Add resolved dashboard filters
753+ )
754+
613755 # Get total rows using the same query builder as chart data
614- total_rows = charts_service .get_chart_data_total_rows (org_warehouse , payload )
756+ total_rows = charts_service .get_chart_data_total_rows (org_warehouse , modified_payload )
615757
616758 return total_rows
617759
0 commit comments