mistercrunch commented on issue #32793:
URL: https://github.com/apache/superset/issues/32793#issuecomment-3180989806
NOTE: did some work around attaching a drill-to-details chart to a dataset.
If/when provided, it'll use that chart in place. Here's the project plan for
it:
# Custom Drill-Through Tables for Apache Superset
## Overview
Enable Superset users to define customized drill-through views by selecting
any existing chart as a drill target. Dataset owners can configure which chart
should be used when drilling through from any chart using their dataset. This
addresses the current limitation where drill-through displays ALL columns in a
generic table, which can be overwhelming for wide datasets.
## Goals
- **Simplify drill-through experience** - Show relevant data instead of all
columns
- **Flexible chart types** - Allow any chart type as drill target, not just
tables
- **Dataset owner control** - Dataset owners configure the drill experience
for their data
- **Maintain backwards compatibility** - Falls back to current behavior if
not configured
- **Simple implementation** - Avoid complex dynamic forms, ship quickly (2-3
days)
## Implementation: Dataset-Level Chart Selection
### User Workflow
1. Dataset owner creates a chart with the desired drill-through view (any
chart type)
2. Dataset owner navigates to DatasetEditor
3. Owner selects the chart from a dropdown (filtered to show charts using
this dataset)
4. When users drill through from any chart using this dataset (in any
dashboard), they see the configured chart with appropriate filters applied
5. If no configuration exists, falls back to system default (current "all
columns" behavior)
### Technical Design
#### Backend Changes
**Database Schema**
```sql
-- Add to datasets table (tables)
ALTER TABLE tables ADD COLUMN drill_through_chart_id INTEGER
REFERENCES slices(id) ON DELETE SET NULL;
```
**Model Update**
```python
# superset/models/core.py
class SqlaTable(Model, BaseDatasource):
# ... existing fields
drill_through_chart_id = Column(
Integer, ForeignKey("slices.id", ondelete="SET NULL"),
nullable=True
)
drill_through_chart = relationship(
"Slice",
foreign_keys=[drill_through_chart_id],
backref=backref("drill_through_datasets", passive_deletes=True)
)
```
**API Extension**
```python
# superset/datasets/api.py
@expose("/<pk>/drill_through_chart", methods=["PUT", "DELETE"])
def drill_through_chart(self, pk: int):
"""Set or clear the drill-through chart for this dataset"""
# Validate chart exists and uses same dataset
# PUT body: { "chart_id": 123 }
```
#### Frontend Changes
**DatasetEditor Component**
```typescript
// superset-frontend/src/features/datasets/DatasetEditor.tsx
// Get charts that use this dataset
const datasetCharts = useMemo(() => {
return charts
.filter(chart => chart.datasource_id === dataset.id)
.map(chart => ({
value: chart.id,
label: `${chart.slice_name} (${chart.viz_type})`,
viz_type: chart.viz_type
}));
}, [charts, dataset.id]);
// Drill-through configuration section
<FormSection title="Drill-Through Configuration">
<FormItem label="Default Drill-Through Chart">
<Select
ariaLabel="Select a chart as the drill-through view"
options={datasetCharts}
value={dataset.drill_through_chart_id}
onChange={handleDrillThroughChange}
allowClear
placeholder="Default (show all columns)"
/>
<HelperText>
Select any chart using this dataset as the drill-through target.
This will be used when users drill through from any chart using this
dataset.
Recommended: Use atomic-level data (table) or relevant aggregated view.
</HelperText>
</FormItem>
</FormSection>
```
**Drill-through Modal Update**
```typescript
// superset-frontend/src/components/DrillDetail/DrillDetailModal.tsx
const renderDrillThroughContent = () => {
const canEditDataset = dataset?.owners?.some(owner => owner.id === userId);
const canExploreDataset = dataset?.can_explore;
// Check dataset-level drill configuration
const drillThroughChartId = dataset?.drill_through_chart_id;
const drillThroughChart = drillThroughChartId ?
charts.find(c => c.id === drillThroughChartId) : null;
return (
<>
{/* Feature discoverability banner */}
{!drillThroughChartId && canEditDataset && (
<Alert
message="Customize this drill-through view"
description={
<>
Dataset owners can customize which chart appears in
drill-through views.{' '}
<a
href={`/superset/datasourceeditor/${dataset.datasource_type}/${dataset.id}/`}>
Edit dataset settings
</a> to select a chart as your drill-through target.
</>
}
type="info"
showIcon
closable
css={{ marginBottom: 16 }}
/>
)}
{/* Exploration action - always show if user has access */}
{canExploreDataset && (
<div css={{ textAlign: 'right', marginBottom: 16 }}>
<Button
type="link"
icon={<ExploreOutlined />}
onClick={() => {
const exploreUrl = buildExploreUrl({
datasource: `${dataset.id}__${dataset.datasource_type}`,
formData: {
viz_type: drillThroughChart ? drillThroughChart.viz_type :
'table',
adhoc_filters: drillFilters,
row_limit: drillRowLimit,
...(drillThroughChart ? drillThroughChart.formData : {}),
},
});
window.open(exploreUrl, '_blank');
}}
>
Explore this data
</Button>
</div>
)}
{drillThroughChart ? (
// Use configured chart from dataset
<SuperChart
chartType={drillThroughChart.viz_type}
formData={{
...drillThroughChart.formData,
// Override with drill-through filters
adhoc_filters: [...(drillThroughChart.formData.adhoc_filters ||
[]), ...drillFilters],
row_limit: drillRowLimit,
}}
queriesData={drillQueriesData}
height={400}
width="100%"
/>
// Option 2: Use StatefulChart if available (PR #34526)
// <StatefulChart
// chartId={drillThroughChartId}
// overrideFormData={{
// adhoc_filters: drillFilters,
// row_limit: drillRowLimit,
// }}
// />
) : (
// Fallback: current behavior with generic table showing all columns
<SuperChart chartType="table" formData={genericTableFormData} />
)}
</>
);
};
```
### Key Implementation Decisions
1. **Dataset-Level Configuration**: Single dropdown in DatasetEditor avoids
complex dynamic forms
2. **Any Chart Type Allowed**: No restriction to tables - users can drill to
any visualization type
3. **Chart Filtering**: Dropdown shows only charts using the current dataset
4. **Graceful Fallback**: If no configuration exists, falls back to current
"all columns" behavior
5. **Permission-Based Configuration**: Dataset owners control the
drill-through experience
6. **Rendering Approach**:
- Primary: Use `SuperChart` with target chart's formData and drill filters
- Alternative: Leverage `StatefulChart` from [PR
#34526](https://github.com/apache/superset/pull/34526) if available
7. **Feature Discoverability**: Show contextual prompt to dataset owners
when no config exists
8. **Simple Implementation**: Ship in 2-3 days instead of 2-3 weeks with
complex dynamic forms
### Files to Modify
1. **Backend**:
- `superset/models/core.py` - Add drill_through_chart_id field to
SqlaTable
- `superset/datasets/api.py` - Add drill-through chart endpoint
- `superset/datasets/schemas.py` - Include drill_through_chart_id in
serialization
- `superset/migrations/versions/` - New migration file for tables table
- `superset/datasets/dao.py` - Update queries to include drill-through
chart relationship
2. **Frontend**:
- `superset-frontend/src/features/datasets/DatasetEditor.tsx` - Add
drill-through dropdown
- `superset-frontend/src/components/DrillDetail/DrillDetailModal.tsx` -
Use dataset config
- `superset-frontend/src/types/Dataset.ts` - Update Dataset type with
drill_through_chart_id
- `superset-frontend/src/features/datasets/api.ts` - Drill-through chart
API calls
## Testing Strategy
### Unit Tests
- [ ] Dataset model drill_through_chart_id field and relationship
- [ ] API endpoint validation (chart exists, uses same dataset)
- [ ] Schema serialization with drill-through chart
- [ ] Null handling when chart is deleted (ON DELETE SET NULL)
### Integration Tests
- [ ] End-to-end: Configure dataset drill target → Drill through → See
configured chart
- [ ] Target chart deletion → Verify fallback to system default
- [ ] Cross-database compatibility
- [ ] Permission checks (dataset edit required for configuration)
- [ ] Same configuration used across multiple dashboards
### Manual Testing
- [ ] Various chart types as drill targets (table, bar, line, pie, etc.)
- [ ] Complex chart configurations (calculated columns, custom formatting)
- [ ] Performance comparison (configured vs. default drill-through)
- [ ] Dataset used in multiple dashboards shows same drill-through
- [ ] Mixed scenarios: Some datasets configured, others using defaults
## Current Status
- [x] Technical design complete
- [x] Implementation approach decided (Dataset-Level Chart Selection)
- [x] Simplified from dashboard-level to dataset-level to avoid dynamic forms
- [x] Future roadmap defined with dashboard overrides as Phase 2
- [ ] Database migration created
- [ ] Backend API implemented
- [ ] Frontend drill configuration added to DatasetEditor
- [ ] Drill-through modal updated for dataset config lookup
- [ ] Tests written
- [ ] Documentation updated
## Related PRs/Issues
- StatefulChart PR: [#34526](https://github.com/apache/superset/pull/34526)
- Could simplify implementation
- Original drill-through feature: [Reference needed]
- Discussion: [To be created]
## Future Enhancements
### Phase 2: Dashboard-Level Overrides (Contextual Control)
**Goal**: Allow dashboards to override dataset defaults for contextual drill
experiences
**Implementation**:
- Add `drill_through_overrides` JSON field to dashboard model
- Dashboard editor can optionally override dataset defaults
- Precedence: Dashboard override → Dataset default → System default
- Avoids complex dynamic forms - only configure overrides when needed
**Benefits**:
- Different dashboards can have different drill targets for same dataset
- Dashboard creators get contextual control when needed
- Dataset defaults still provide good baseline experience
- Simple UI - only show override option, not dynamic form for all datasets
**Example Structure**:
```typescript
dashboard.drill_through_overrides = {
"dataset_123": { chart_id: 789 }, // Override only this dataset
// Other datasets use their configured defaults
}
```
### Phase 3: Multiple Drill Targets & Submenu
**Goal**: Allow multiple drill-through options with contextual submenu
**Implementation**:
```typescript
// Dataset level - multiple default options
dataset.drill_through_targets = [
{ id: 'atomic', label: 'Order Line Details', chart_id: 456, icon: 'table'
},
{ id: 'summary', label: 'Order Summary', chart_id: 789, icon: 'bar-chart'
},
{ id: 'trends', label: 'Trend Analysis', chart_id: 101, icon: 'line-chart'
}
];
// Dashboard can still override with its own set
dashboard.drill_through_overrides = {
"dataset_123": {
targets: [...customTargets],
default_target: 'summary'
}
}
```
**UX**: Right-click drill menu with multiple options, or dropdown in
drill-through modal
### Phase 4: Cross-Dashboard Drilling
**Goal**: Enable drilling to entire dashboards with contextual filters
**Implementation**:
- Add dashboard targets to drill configuration
- Filter context preservation across dashboard navigation
- Dashboard embedding vs. new page navigation options
**Use Cases**:
- Executive summary → Operational deep-dive dashboard
- Regional KPI → Regional analysis dashboard
- Product performance → Product detail dashboard
### Phase 5: Smart Drill Suggestions
**Goal**: AI-powered suggestions for drill-through targets based on data
relationships
**Implementation**:
- Analyze dataset relationships and common query patterns
- Suggest relevant charts for drill-through configuration
- Auto-generate drill targets based on data model
### Phase 6: Advanced Configuration Features
- **Permission-based targets**: Different drill options for different user
roles
- **Conditional drilling**: Show different targets based on data values
- **Drill-through analytics**: Track which drill targets are most used
- **Template marketplace**: Share drill-through configurations across
organizations
## Feature Discoverability
To help users discover this new feature, we'll show an informational alert
in the drill-through modal when:
- No drill-through chart has been configured for the dataset
- Current user is an owner of the dataset
**Discoverability Strategy**:
- **Target Audience**: Only dataset owners (they have permission to
configure)
- **Timing**: When they encounter the default "all columns" drill-through
- **Action**: Direct link to DatasetEditor with clear instructions
- **Dismissible**: Users can close the alert if not interested
**Exploration Enhancement**:
- **"Explore this data" button**: Always shown if user has dataset
exploration permissions
- **Smart formData**: Carries over drill-through filters and configured
chart settings to Explore view
- **Opens in new tab**: Preserves current drill-through context while
allowing deeper exploration
This approach ensures:
- Feature is discovered organically during usage
- Only relevant users see the prompt (owners who can actually configure it)
- Clear call-to-action with direct navigation
- Non-intrusive (closable alert, only shows when relevant)
- Easy transition to full exploration when users want more control
## Notes
- **Architecture Decision**: Dataset-level approach avoids complex dynamic
forms while providing value quickly
- **No Chart Type Restrictions**: Users can drill to any chart type (table,
bar, line, pie, etc.) for maximum flexibility
- **Graceful Degradation**: System falls back to current behavior when no
configuration exists
- **Permission Model**: Dataset owners control drill experience (simpler
than dashboard-level permissions)
- **Future Extensibility**: Clear path to dashboard overrides, multiple
targets, and cross-dashboard drilling
- **Performance**: Minimal impact - just rendering different chart with same
data + filters
- **Discoverability**: Alert prompts dataset owners to configure
drill-through when using defaults
- **Exploration Flow**: "Explore this data" button provides seamless
transition to full analysis with context preserved
- **MVP Timeline**: 2-3 days implementation vs 2-3 weeks for dashboard-level
dynamic forms
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]