0
# Dashboard Components
1
2
This module provides comprehensive type definitions and utilities for dashboard functionality within Superset applications. It focuses on native filters, data masks, filter sets, and dashboard component metadata that enable interactive filtering and cross-filter capabilities across dashboard charts.
3
4
## Overview
5
6
The dashboard module defines the core types and interfaces that power Superset's dashboard filtering system. It supports native filters (dashboard-level filters), cross-filters (chart-to-chart filtering), filter sets (saved filter configurations), and the data mask system that applies filters to charts.
7
8
## Core Filter Types
9
10
### Filter Structure { .api }
11
12
Core filter definition that represents a native dashboard filter:
13
14
```typescript
15
import { Filter, Divider, NativeFilterType } from '@superset-ui/core';
16
17
interface Filter {
18
// Identity and metadata
19
id: string; // Randomly generated unique identifier
20
name: string; // Display name for the filter
21
description: string; // User-friendly description
22
type: typeof NativeFilterType.NATIVE_FILTER;
23
24
// Filter configuration
25
filterType: string; // Type of filter component (select, time, etc.)
26
controlValues: { [key: string]: any }; // Filter-specific configuration
27
28
// Target configuration
29
targets: [Partial<NativeFilterTarget>]; // Currently single target, array for future multi-target support
30
scope: NativeFilterScope; // Which charts this filter applies to
31
32
// Cascade and dependencies
33
cascadeParentIds: string[]; // Parent filters for cascading behavior
34
defaultDataMask: DataMask; // Default filter state
35
36
// Time-specific properties (for time filters)
37
sortMetric?: string | null;
38
adhoc_filters?: AdhocFilter[];
39
granularity_sqla?: string;
40
granularity?: string;
41
druid_time_origin?: string;
42
time_grain_sqla?: string;
43
time_range?: string;
44
45
// Behavior configuration
46
requiredFirst?: boolean; // Must be set before other filters
47
tabsInScope?: string[]; // Dashboard tabs this filter applies to
48
chartsInScope?: number[]; // Specific charts this filter applies to
49
}
50
51
// Divider for organizing filters in the filter panel
52
interface Divider extends Partial<Omit<Filter, 'id' | 'type'>> {
53
id: string;
54
title: string;
55
description: string;
56
type: typeof NativeFilterType.DIVIDER;
57
}
58
59
enum NativeFilterType {
60
NATIVE_FILTER = 'NATIVE_FILTER',
61
DIVIDER = 'DIVIDER'
62
}
63
```
64
65
### Filter Target System { .api }
66
67
System for defining what data sources and columns filters operate on:
68
69
```typescript
70
interface NativeFilterTarget {
71
datasetId: number; // ID of the dataset being filtered
72
column: NativeFilterColumn; // Column being filtered
73
}
74
75
interface NativeFilterColumn {
76
name: string; // Column name in the dataset
77
displayName?: string; // Human-readable column name
78
}
79
80
interface NativeFilterScope {
81
rootPath: string[]; // Path to scope root in dashboard component tree
82
excluded: number[]; // Chart IDs excluded from filter scope
83
}
84
```
85
86
## Data Mask System
87
88
### DataMask Interface { .api }
89
90
The data mask system applies filter values to charts and tracks filter state:
91
92
```typescript
93
interface DataMask {
94
extraFormData?: QueryFormData; // Additional query parameters from filter
95
filterState?: { // Current filter state
96
value?: any; // Filter value (selected items, date range, etc.)
97
label?: string; // Display label for current selection
98
};
99
ownState?: { // Filter component internal state
100
coltypes?: string[]; // Column data types
101
[key: string]: any;
102
};
103
}
104
105
// Data mask types for different filter sources
106
enum DataMaskType {
107
NativeFilters = 'nativeFilters', // Dashboard-level native filters
108
CrossFilters = 'crossFilters' // Chart-to-chart cross filters
109
}
110
111
// Data mask state management
112
type DataMaskState = { [id: string]: DataMask };
113
114
type DataMaskWithId = { id: string } & DataMask;
115
type DataMaskStateWithId = { [filterId: string]: DataMaskWithId };
116
```
117
118
## Filter Collections and Sets
119
120
### Filter Organization { .api }
121
122
Types for organizing and managing collections of filters:
123
124
```typescript
125
// Collection of all filters in a dashboard
126
type Filters = {
127
[filterId: string]: Filter | Divider;
128
};
129
130
// Array configuration format for filter ordering
131
type FilterConfiguration = Array<Filter | Divider>;
132
133
// Saved filter sets for quick filter application
134
interface FilterSet {
135
id: number; // Unique identifier for the filter set
136
name: string; // Display name
137
nativeFilters: Filters; // Filter configurations in this set
138
dataMask: DataMaskStateWithId; // Saved filter values and state
139
}
140
141
type FilterSets = {
142
[filtersSetId: string]: FilterSet;
143
};
144
```
145
146
## Dashboard State Management
147
148
### Native Filters State { .api }
149
150
Complete state structure for dashboard native filters:
151
152
```typescript
153
interface NativeFiltersState {
154
filters: Filters; // All filter definitions
155
filterSets: FilterSets; // Saved filter sets
156
focusedFilterId?: string; // Currently focused filter in config
157
}
158
159
interface DashboardComponentMetadata {
160
nativeFilters: NativeFiltersState; // Native filter state
161
dataMask: DataMaskStateWithId; // Applied data masks
162
}
163
```
164
165
## Type Guards and Utilities
166
167
### Filter Type Detection { .api }
168
169
Utility functions for working with filter objects:
170
171
```typescript
172
// Type guard to check if filter element is a native filter
173
function isNativeFilter(filterElement: Filter | Divider): filterElement is Filter;
174
175
// Type guard to check if filter element is a divider
176
function isFilterDivider(filterElement: Filter | Divider): filterElement is Divider;
177
```
178
179
## Usage Examples
180
181
### Creating Native Filters
182
183
```typescript
184
import {
185
Filter,
186
NativeFilterType,
187
NativeFilterScope,
188
DataMask
189
} from '@superset-ui/core';
190
191
// Create a select filter for a category column
192
const categoryFilter: Filter = {
193
id: 'filter_category_001',
194
name: 'Product Category',
195
description: 'Filter charts by product category',
196
type: NativeFilterType.NATIVE_FILTER,
197
filterType: 'filter_select',
198
199
// Target the 'category' column in dataset 5
200
targets: [{
201
datasetId: 5,
202
column: {
203
name: 'category',
204
displayName: 'Product Category'
205
}
206
}],
207
208
// Apply to all charts except chart 10
209
scope: {
210
rootPath: ['ROOT_ID'],
211
excluded: [10]
212
},
213
214
// No parent filters
215
cascadeParentIds: [],
216
217
// Default to no selection
218
defaultDataMask: {
219
filterState: {
220
value: null,
221
label: 'All Categories'
222
}
223
},
224
225
controlValues: {
226
enableEmptyFilter: true,
227
defaultToFirstItem: false,
228
multiSelect: true,
229
searchAllOptions: false,
230
inverseSelection: false
231
}
232
};
233
234
// Create a time range filter
235
const timeFilter: Filter = {
236
id: 'filter_time_001',
237
name: 'Time Range',
238
description: 'Select date range for analysis',
239
type: NativeFilterType.NATIVE_FILTER,
240
filterType: 'filter_timerange',
241
242
targets: [{
243
datasetId: 5,
244
column: {
245
name: 'created_at',
246
displayName: 'Creation Date'
247
}
248
}],
249
250
scope: {
251
rootPath: ['ROOT_ID'],
252
excluded: []
253
},
254
255
cascadeParentIds: [],
256
257
defaultDataMask: {
258
filterState: {
259
value: 'Last 30 days'
260
}
261
},
262
263
controlValues: {
264
defaultValue: 'Last 30 days'
265
},
266
267
// Time-specific configuration
268
time_range: 'Last 30 days',
269
granularity_sqla: 'created_at'
270
};
271
```
272
273
### Managing Filter Sets
274
275
```typescript
276
import { FilterSet, DataMaskStateWithId } from '@superset-ui/core';
277
278
// Create a saved filter set
279
const quarterlyReportFilters: FilterSet = {
280
id: 1,
281
name: 'Q1 2024 Report',
282
nativeFilters: {
283
'filter_time_001': timeFilter,
284
'filter_category_001': categoryFilter
285
},
286
dataMask: {
287
'filter_time_001': {
288
id: 'filter_time_001',
289
filterState: {
290
value: '2024-01-01 : 2024-03-31'
291
}
292
},
293
'filter_category_001': {
294
id: 'filter_category_001',
295
filterState: {
296
value: ['Electronics', 'Clothing'],
297
label: 'Electronics, Clothing'
298
}
299
}
300
}
301
};
302
303
// Apply filter set to dashboard
304
const applyFilterSet = (filterSet: FilterSet): DataMaskStateWithId => {
305
return filterSet.dataMask;
306
};
307
```
308
309
### Filter Scope Management
310
311
```typescript
312
import { NativeFilterScope, isNativeFilter } from '@superset-ui/core';
313
314
// Create scope that applies to specific charts only
315
const restrictedScope: NativeFilterScope = {
316
rootPath: ['ROOT_ID'],
317
excluded: [] // Empty means include all charts in scope
318
};
319
320
// Create scope that excludes specific charts
321
const excludedScope: NativeFilterScope = {
322
rootPath: ['ROOT_ID', 'TAB_001'], // Apply only to specific tab
323
excluded: [15, 20, 25] // Exclude these chart IDs
324
};
325
326
// Check which charts are in scope
327
const getChartsInScope = (
328
scope: NativeFilterScope,
329
allChartIds: number[]
330
): number[] => {
331
return allChartIds.filter(id => !scope.excluded.includes(id));
332
};
333
```
334
335
### Cross-Filter Integration
336
337
```typescript
338
import { DataMask, DataMaskType } from '@superset-ui/core';
339
340
// Handle cross-filter from chart interaction
341
const handleChartCrossFilter = (
342
chartId: number,
343
filterColumn: string,
344
filterValues: any[]
345
): DataMask => {
346
return {
347
extraFormData: {
348
filters: [{
349
col: filterColumn,
350
op: 'IN',
351
val: filterValues
352
}]
353
},
354
filterState: {
355
value: filterValues,
356
label: `${filterValues.length} selected`
357
}
358
};
359
};
360
361
// Apply cross-filter to dashboard state
362
const applyCrossFilter = (
363
currentDataMask: DataMaskStateWithId,
364
sourceChartId: number,
365
targetFilter: DataMask
366
): DataMaskStateWithId => {
367
return {
368
...currentDataMask,
369
[`cross_filter_${sourceChartId}`]: {
370
id: `cross_filter_${sourceChartId}`,
371
...targetFilter
372
}
373
};
374
};
375
```
376
377
### Cascading Filter Implementation
378
379
```typescript
380
import { Filter } from '@superset-ui/core';
381
382
// Create cascading filters (country -> state -> city)
383
const countryFilter: Filter = {
384
id: 'filter_country',
385
name: 'Country',
386
type: NativeFilterType.NATIVE_FILTER,
387
filterType: 'filter_select',
388
cascadeParentIds: [],
389
// ... other properties
390
} as Filter;
391
392
const stateFilter: Filter = {
393
id: 'filter_state',
394
name: 'State/Province',
395
type: NativeFilterType.NATIVE_FILTER,
396
filterType: 'filter_select',
397
cascadeParentIds: ['filter_country'], // Depends on country filter
398
// ... other properties
399
} as Filter;
400
401
const cityFilter: Filter = {
402
id: 'filter_city',
403
name: 'City',
404
type: NativeFilterType.NATIVE_FILTER,
405
filterType: 'filter_select',
406
cascadeParentIds: ['filter_country', 'filter_state'], // Depends on both
407
// ... other properties
408
} as Filter;
409
410
// Process cascade dependencies
411
const processCascadeUpdate = (
412
filters: Filter[],
413
updatedFilterId: string,
414
newValue: any
415
): DataMaskStateWithId => {
416
const updatedMasks: DataMaskStateWithId = {};
417
418
// Find child filters that depend on the updated filter
419
const childFilters = filters.filter(f =>
420
f.cascadeParentIds.includes(updatedFilterId)
421
);
422
423
// Reset child filters when parent changes
424
childFilters.forEach(child => {
425
updatedMasks[child.id] = {
426
id: child.id,
427
filterState: {
428
value: null,
429
label: 'All'
430
}
431
};
432
});
433
434
return updatedMasks;
435
};
436
```
437
438
### Filter Organization with Dividers
439
440
```typescript
441
import { Divider, NativeFilterType, FilterConfiguration } from '@superset-ui/core';
442
443
// Create filter dividers for organization
444
const timeDivider: Divider = {
445
id: 'divider_time',
446
title: 'Time Filters',
447
description: 'Date and time-based filtering options',
448
type: NativeFilterType.DIVIDER
449
};
450
451
const categoryDivider: Divider = {
452
id: 'divider_categories',
453
title: 'Category Filters',
454
description: 'Product and business category filters',
455
type: NativeFilterType.DIVIDER
456
};
457
458
// Organize filters with dividers
459
const filterConfiguration: FilterConfiguration = [
460
timeDivider,
461
timeFilter,
462
categoryDivider,
463
categoryFilter,
464
productFilter
465
];
466
467
// Process filter configuration
468
const organizeFilters = (config: FilterConfiguration) => {
469
const filters: Filter[] = [];
470
const dividers: Divider[] = [];
471
472
config.forEach(item => {
473
if (isNativeFilter(item)) {
474
filters.push(item);
475
} else if (isFilterDivider(item)) {
476
dividers.push(item);
477
}
478
});
479
480
return { filters, dividers };
481
};
482
```
483
484
## Related Documentation
485
486
- [Data Connection](./data-connection.md) - API integration for dashboard data
487
- [Core Models & Utilities](./core-models.md) - Registry system for dashboard components
488
- [Query System](./query.md) - Query building with dashboard filters
489
- [Plugin System](./plugin-system.md) - Dashboard component plugins