diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/SupersetControlRenderers.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/SupersetControlRenderers.tsx deleted file mode 100644 index 90144cbd84f..00000000000 --- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/components/SupersetControlRenderers.tsx +++ /dev/null @@ -1,267 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { rankWith, isControl, and } from '@jsonforms/core'; -import { withJsonFormsControlProps } from '@jsonforms/react'; -import { - MetricsControl, - MetricControl, - AdhocFiltersControl, - GroupByControl, - ColumnsControl, - ColorSchemeControl, - LinearColorSchemeControl, - RowLimitControl, - SortByMetricControl, - TimeRangeControl, - TimeGrainSqlaControl, - VizTypeControl, - DatasourceControl, - ColorPickerControl, - CurrencyFormatControl, - YAxisFormatControl, - XAxisControl, - SeriesControl, - EntityControl, - SecondaryMetricControl, - TooltipColumnsControl, - TooltipMetricsControl, -} from './SharedControlComponents'; -import { ControlHeader } from '../../components/ControlHeader'; - -/** - * Helper to create a renderer for a Superset control - */ -const createSupersetControlRenderer = ( - controlType: string, - ControlComponent: () => any, -) => { - const Renderer = (props: any) => { - const { schema, uischema, visible } = props; - - if (!visible) { - return null; - } - - const control = ControlComponent(); - const label = uischema.label || schema.title; - const { description } = schema; - - return ( -
- {label && } -
- {/* Render the control configuration */} - {control.config.type} - {/* This would actually render the real control component */} -
-
- ); - }; - - return withJsonFormsControlProps(Renderer); -}; - -/** - * Tester to check if a control is a specific Superset control type - */ -const isSupersetControl = (controlType: string) => - and( - isControl, - (uischema: any) => uischema.options?.controlType === controlType, - ); - -/** - * Custom renderers for all Superset-specific controls - */ -export const supersetControlRenderers = [ - // Metrics and dimensions - { - tester: rankWith(10, isSupersetControl('MetricsControl')), - renderer: createSupersetControlRenderer('MetricsControl', MetricsControl), - }, - { - tester: rankWith(10, isSupersetControl('MetricControl')), - renderer: createSupersetControlRenderer('MetricControl', MetricControl), - }, - { - tester: rankWith(10, isSupersetControl('GroupByControl')), - renderer: createSupersetControlRenderer('GroupByControl', GroupByControl), - }, - { - tester: rankWith(10, isSupersetControl('ColumnsControl')), - renderer: createSupersetControlRenderer('ColumnsControl', ColumnsControl), - }, - { - tester: rankWith(10, isSupersetControl('AdhocFiltersControl')), - renderer: createSupersetControlRenderer( - 'AdhocFiltersControl', - AdhocFiltersControl, - ), - }, - - // Sorting and limits - { - tester: rankWith(10, isSupersetControl('RowLimitControl')), - renderer: createSupersetControlRenderer('RowLimitControl', RowLimitControl), - }, - { - tester: rankWith(10, isSupersetControl('SortByMetricControl')), - renderer: createSupersetControlRenderer( - 'SortByMetricControl', - SortByMetricControl, - ), - }, - - // Time controls - { - tester: rankWith(10, isSupersetControl('TimeRangeControl')), - renderer: createSupersetControlRenderer( - 'TimeRangeControl', - TimeRangeControl, - ), - }, - { - tester: rankWith(10, isSupersetControl('TimeGrainSqlaControl')), - renderer: createSupersetControlRenderer( - 'TimeGrainSqlaControl', - TimeGrainSqlaControl, - ), - }, - - // Color controls - { - tester: rankWith(10, isSupersetControl('ColorSchemeControl')), - renderer: createSupersetControlRenderer( - 'ColorSchemeControl', - ColorSchemeControl, - ), - }, - { - tester: rankWith(10, isSupersetControl('LinearColorSchemeControl')), - renderer: createSupersetControlRenderer( - 'LinearColorSchemeControl', - LinearColorSchemeControl, - ), - }, - { - tester: rankWith(10, isSupersetControl('ColorPickerControl')), - renderer: createSupersetControlRenderer( - 'ColorPickerControl', - ColorPickerControl, - ), - }, - - // Format controls - { - tester: rankWith(10, isSupersetControl('YAxisFormatControl')), - renderer: createSupersetControlRenderer( - 'YAxisFormatControl', - YAxisFormatControl, - ), - }, - { - tester: rankWith(10, isSupersetControl('CurrencyFormatControl')), - renderer: createSupersetControlRenderer( - 'CurrencyFormatControl', - CurrencyFormatControl, - ), - }, - - // Data source controls - { - tester: rankWith(10, isSupersetControl('DatasourceControl')), - renderer: createSupersetControlRenderer( - 'DatasourceControl', - DatasourceControl, - ), - }, - { - tester: rankWith(10, isSupersetControl('VizTypeControl')), - renderer: createSupersetControlRenderer('VizTypeControl', VizTypeControl), - }, - - // Series and entity controls - { - tester: rankWith(10, isSupersetControl('SeriesControl')), - renderer: createSupersetControlRenderer('SeriesControl', SeriesControl), - }, - { - tester: rankWith(10, isSupersetControl('EntityControl')), - renderer: createSupersetControlRenderer('EntityControl', EntityControl), - }, - { - tester: rankWith(10, isSupersetControl('XAxisControl')), - renderer: createSupersetControlRenderer('XAxisControl', XAxisControl), - }, - { - tester: rankWith(10, isSupersetControl('SecondaryMetricControl')), - renderer: createSupersetControlRenderer( - 'SecondaryMetricControl', - SecondaryMetricControl, - ), - }, - - // Tooltip controls - { - tester: rankWith(10, isSupersetControl('TooltipColumnsControl')), - renderer: createSupersetControlRenderer( - 'TooltipColumnsControl', - TooltipColumnsControl, - ), - }, - { - tester: rankWith(10, isSupersetControl('TooltipMetricsControl')), - renderer: createSupersetControlRenderer( - 'TooltipMetricsControl', - TooltipMetricsControl, - ), - }, -]; - -/** - * Get the control type for a given control name - */ -export function getControlType(controlName: string): string | undefined { - const controlTypeMap: Record = { - metrics: 'MetricsControl', - metric: 'MetricControl', - groupby: 'GroupByControl', - columns: 'ColumnsControl', - adhoc_filters: 'AdhocFiltersControl', - row_limit: 'RowLimitControl', - sort_by_metric: 'SortByMetricControl', - time_range: 'TimeRangeControl', - time_grain_sqla: 'TimeGrainSqlaControl', - color_scheme: 'ColorSchemeControl', - linear_color_scheme: 'LinearColorSchemeControl', - color_picker: 'ColorPickerControl', - y_axis_format: 'YAxisFormatControl', - currency_format: 'CurrencyFormatControl', - datasource: 'DatasourceControl', - viz_type: 'VizTypeControl', - series: 'SeriesControl', - entity: 'EntityControl', - x_axis: 'XAxisControl', - secondary_metric: 'SecondaryMetricControl', - tooltip_columns: 'TooltipColumnsControl', - tooltip_metrics: 'TooltipMetricsControl', - }; - - return controlTypeMap[controlName]; -} diff --git a/superset-frontend/scripts/migrate-control-panels.js b/superset-frontend/scripts/migrate-control-panels.js deleted file mode 100644 index 3c190affa64..00000000000 --- a/superset-frontend/scripts/migrate-control-panels.js +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env node -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -const fs = require('fs'); -const path = require('path'); -const glob = require('glob'); - -/** - * Migration template for control panels - */ -const TEMPLATE = `/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -import { t } from '@superset-ui/core'; -import { JsonSchema, UISchemaElement } from '@jsonforms/core'; -import { - JsonFormsControlPanelConfig, - createVerticalLayout, - createCollapsibleGroup, - createControl, - createHorizontalLayout, -} from '@superset-ui/chart-controls'; - -// AUTO-MIGRATED: Please review and adjust the control types and layout - -{{CONTENT}} - -const controlPanel: JsonFormsControlPanelConfig = { - schema, - uischema, - {{EXTRAS}} -}; - -export default controlPanel; -`; - -/** - * Extract control information from AST-like analysis - */ -function extractControls(content) { - const controls = []; - - // Find control references like [MetricControl()], [GroupByControl()], etc. - const controlMatches = content.matchAll(/\[(\w+Control)\(\)\]/g); - for (const match of controlMatches) { - const controlName = match[1]; - controls.push({ - type: controlName, - name: controlName.replace('Control', '').toLowerCase(), - }); - } - - // Find custom control items - const customMatches = content.matchAll(/name:\s*['"](\w+)['"]/g); - for (const match of customMatches) { - controls.push({ - type: 'CustomControl', - name: match[1], - }); - } - - return controls; -} - -/** - * Extract sections from content - */ -function extractSections(content) { - const sections = []; - - // Find section labels - const sectionMatches = content.matchAll(/label:\s*t\(['"]([^'"]+)['"]\)/g); - for (const match of sectionMatches) { - sections.push({ - label: match[1], - expanded: content.includes(`label: t('${match[1]}')`), - }); - } - - return sections; -} - -/** - * Generate schema from controls - */ -function generateSchema(controls) { - const properties = {}; - - const typeMap = { - metric: { type: 'string', title: 'Metric' }, - metrics: { type: 'array', title: 'Metrics' }, - groupby: { type: 'array', title: 'Group By' }, - columns: { type: 'array', title: 'Columns' }, - adhoc_filters: { type: 'array', title: 'Filters' }, - row_limit: { type: 'integer', title: 'Row Limit', default: 10000 }, - sort_by_metric: { type: 'boolean', title: 'Sort by Metric' }, - color_scheme: { type: 'string', title: 'Color Scheme' }, - y_axis_format: { type: 'string', title: 'Number Format' }, - }; - - controls.forEach(control => { - const { name } = control; - properties[name] = typeMap[name] || { type: 'string', title: name }; - }); - - return { - type: 'object', - properties, - }; -} - -/** - * Generate UI schema from sections and controls - */ -function generateUISchema(sections, controls) { - const elements = sections.map(section => { - const sectionControls = controls.map(control => ({ - type: 'Control', - scope: `#/properties/${control.name}`, - options: { - controlType: control.type, - }, - })); - - return `createCollapsibleGroup( - t('${section.label}'), - [ - ${sectionControls - .map( - c => - `createControl('${c.scope}', { controlType: '${c.options.controlType}' })`, - ) - .join(',\n ')} - ], - ${section.expanded} - )`; - }); - - return `createVerticalLayout([ - ${elements.join(',\n ')} -])`; -} - -/** - * Migrate a single control panel file - */ -function migrateFile(filePath) { - console.log(`Migrating: ${filePath}`); - - try { - const content = fs.readFileSync(filePath, 'utf-8'); - - // Skip if already migrated - if (content.includes('JsonFormsControlPanelConfig')) { - console.log(` ✓ Already migrated`); - return true; - } - - // Skip JsonForms files - if (filePath.includes('JsonForms') || filePath.includes('jsonForms')) { - console.log(` ✓ Skipping JSON Forms file`); - return true; - } - - // Extract information - const controls = extractControls(content); - const sections = extractSections(content); - - if (controls.length === 0) { - console.log(` ⚠ No controls found`); - return false; - } - - // Generate new content - const schema = generateSchema(controls); - const uischema = generateUISchema(sections, controls); - - const schemaStr = `export const schema: JsonSchema = ${JSON.stringify(schema, null, 2)};`; - const uischemaStr = `export const uischema: UISchemaElement = ${uischema};`; - - // Check for extras - const extras = []; - if (content.includes('controlOverrides')) { - extras.push('// TODO: Migrate controlOverrides'); - } - if (content.includes('formDataOverrides')) { - extras.push('// TODO: Migrate formDataOverrides'); - } - - const newContent = TEMPLATE.replace( - '{{CONTENT}}', - `${schemaStr}\n\n${uischemaStr}`, - ).replace('{{EXTRAS}}', extras.join(',\n ')); - - // Write new file - const newPath = filePath.replace('.ts', '.ts').replace('.tsx', '.tsx'); - fs.writeFileSync(newPath, newContent); - - console.log(` ✓ Migrated successfully`); - return true; - } catch (error) { - console.error(` ✗ Error: ${error.message}`); - return false; - } -} - -/** - * Main migration function - */ -function main() { - const pattern = process.argv[2] || 'plugins/**/controlPanel*.{ts,tsx}'; - const dryRun = process.argv.includes('--dry-run'); - - console.log('Control Panel Migration to JSON Forms'); - console.log('====================================='); - console.log(`Pattern: ${pattern}`); - console.log(`Dry run: ${dryRun}`); - console.log(''); - - const files = glob.sync(pattern, { - ignore: ['**/node_modules/**', '**/*.test.*', '**/*JsonForms*'], - }); - - console.log(`Found ${files.length} control panel files`); - console.log(''); - - let successCount = 0; - let failedCount = 0; - - files.forEach(file => { - if (dryRun) { - console.log(`Would migrate: ${file}`); - successCount++; - } else if (migrateFile(file)) { - successCount++; - } else { - failedCount++; - } - }); - - console.log(''); - console.log('Summary:'); - console.log(` Success: ${successCount}`); - console.log(` Failed: ${failedCount}`); - console.log(` Total: ${files.length}`); -} - -// Run the migration -main();