mirror of
https://github.com/apache/superset.git
synced 2026-05-01 14:04:21 +00:00
Compare commits
33 Commits
fix-webpac
...
describe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b6cf5ffb84 | ||
|
|
77a5969dc1 | ||
|
|
fb9032c05c | ||
|
|
7a9dbfe879 | ||
|
|
0de78d8203 | ||
|
|
abc2d46fed | ||
|
|
927cc1cda1 | ||
|
|
7f3840557a | ||
|
|
0defcb604b | ||
|
|
94686ddfbe | ||
|
|
ec322dfd8d | ||
|
|
cb88d886c7 | ||
|
|
608e3baf43 | ||
|
|
b6f6b75348 | ||
|
|
a5ad1d186c | ||
|
|
db88d80b3f | ||
|
|
4b71adaa9c | ||
|
|
5fbda3af40 | ||
|
|
bc0c40c80e | ||
|
|
f030d658c5 | ||
|
|
e85337c543 | ||
|
|
fe7f8062f3 | ||
|
|
dce74014da | ||
|
|
619b341cad | ||
|
|
9b6876be62 | ||
|
|
c601341520 | ||
|
|
78faaee685 | ||
|
|
4027bad1d6 | ||
|
|
ce55cc7dd7 | ||
|
|
48e1b1ff2c | ||
|
|
5ec8f9d886 | ||
|
|
ecb3ac68ff | ||
|
|
076e477fd4 |
10
.claude/commands/js-to-ts.md
Normal file
10
.claude/commands/js-to-ts.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# JavaScript to TypeScript Migration Command
|
||||
|
||||
## Usage
|
||||
```
|
||||
/js-to-ts <core-filename>
|
||||
```
|
||||
- `<core-filename>` - Path to CORE file relative to `superset-frontend/` (e.g., `src/utils/common.js`, `src/middleware/loggerMiddleware.js`)
|
||||
|
||||
## Agent Instructions
|
||||
**See:** [../projects/js-to-ts/AGENT.md](../projects/js-to-ts/AGENT.md) for complete migration guide.
|
||||
684
.claude/projects/js-to-ts/AGENT.md
Normal file
684
.claude/projects/js-to-ts/AGENT.md
Normal file
@@ -0,0 +1,684 @@
|
||||
# JavaScript to TypeScript Migration Agent Guide
|
||||
|
||||
**Complete technical reference for converting JavaScript/JSX files to TypeScript/TSX in Apache Superset frontend.**
|
||||
|
||||
**Agent Role:** Atomic migration unit - migrate the core file + ALL related tests/mocks as one cohesive unit. Use `git mv` to preserve history, NO `git commit`. NO global import changes. Report results upon completion.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Migration Principles
|
||||
|
||||
1. **Atomic migration units** - Core file + all related tests/mocks migrate together
|
||||
2. **Zero `any` types** - Use proper TypeScript throughout
|
||||
3. **Leverage existing types** - Reuse established definitions
|
||||
4. **Type inheritance** - Derivatives extend base component types
|
||||
5. **Strategic placement** - File types for maximum discoverability
|
||||
6. **Surgical improvements** - Enhance existing types during migration
|
||||
|
||||
---
|
||||
|
||||
## Step 0: Dependency Check (MANDATORY)
|
||||
|
||||
**Command:**
|
||||
```bash
|
||||
grep -E "from '\.\./.*\.jsx?'|from '\./.*\.jsx?'|from 'src/.*\.jsx?'" superset-frontend/{filename}
|
||||
```
|
||||
|
||||
**Decision:**
|
||||
- ✅ No matches → Proceed with atomic migration (core + tests + mocks)
|
||||
- ❌ Matches found → EXIT with dependency report (see format below)
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Identify Related Files (REQUIRED)
|
||||
|
||||
**Atomic Migration Scope:**
|
||||
For core file `src/utils/example.js`, also migrate:
|
||||
- `src/utils/example.test.js` / `src/utils/example.test.jsx`
|
||||
- `src/utils/example.spec.js` / `src/utils/example.spec.jsx`
|
||||
- `src/utils/__mocks__/example.js`
|
||||
- Any other related test/mock files found by pattern matching
|
||||
|
||||
**Find all related test and mock files:**
|
||||
```bash
|
||||
# Pattern-based search for related files
|
||||
basename=$(basename {filename} .js)
|
||||
dirname=$(dirname superset-frontend/{filename})
|
||||
|
||||
# Find test files
|
||||
find "$dirname" -name "${basename}.test.js" -o -name "${basename}.test.jsx"
|
||||
find "$dirname" -name "${basename}.spec.js" -o -name "${basename}.spec.jsx"
|
||||
|
||||
# Find mock files
|
||||
find "$dirname" -name "__mocks__/${basename}.js"
|
||||
find "$dirname" -name "${basename}.mock.js"
|
||||
```
|
||||
|
||||
**Migration Requirement:** All discovered related files MUST be migrated together as one atomic unit.
|
||||
|
||||
**Test File Creation:** If NO test files exist for the core file, CREATE a minimal test file using the following pattern:
|
||||
- Location: Same directory as core file
|
||||
- Name: `{basename}.test.ts` (e.g., `DebouncedMessageQueue.test.ts`)
|
||||
- Content: Basic test structure importing and testing the main functionality
|
||||
- Use proper TypeScript types in test file
|
||||
|
||||
---
|
||||
|
||||
## 🗺️ Type Reference Map
|
||||
|
||||
### From `@superset-ui/core`
|
||||
```typescript
|
||||
// Data & Query
|
||||
QueryFormData, QueryData, JsonObject, AnnotationData, AdhocMetric
|
||||
LatestQueryFormData, GenericDataType, DatasourceType, ExtraFormData
|
||||
DataMaskStateWithId, NativeFilterScope, NativeFiltersState, NativeFilterTarget
|
||||
|
||||
// UI & Theme
|
||||
FeatureFlagMap, LanguagePack, ColorSchemeConfig, SequentialSchemeConfig
|
||||
```
|
||||
|
||||
### From `@superset-ui/chart-controls`
|
||||
```typescript
|
||||
Dataset, ColumnMeta, ControlStateMapping
|
||||
```
|
||||
|
||||
### From Local Types (`src/types/`)
|
||||
```typescript
|
||||
// Authentication
|
||||
User, UserWithPermissionsAndRoles, BootstrapUser, PermissionsAndRoles
|
||||
|
||||
// Dashboard
|
||||
Dashboard, DashboardState, DashboardInfo, DashboardLayout, LayoutItem
|
||||
ComponentType, ChartConfiguration, ActiveFilters
|
||||
|
||||
// Charts
|
||||
Chart, ChartState, ChartStatus, ChartLinkedDashboard, Slice, SaveActionType
|
||||
|
||||
// Data
|
||||
Datasource, Database, Owner, Role
|
||||
|
||||
// UI Components
|
||||
TagType, FavoriteStatus, Filter, ImportResourceName
|
||||
```
|
||||
|
||||
### From Domain Types
|
||||
```typescript
|
||||
// src/dashboard/types.ts
|
||||
RootState, ChartsState, DatasourcesState, FilterBarOrientation
|
||||
ChartCrossFiltersConfig, ActiveTabs, MenuKeys
|
||||
|
||||
// src/explore/types.ts
|
||||
ExplorePageInitialData, ExplorePageState, ExploreResponsePayload, OptionSortType
|
||||
|
||||
// src/SqlLab/types.ts
|
||||
[SQL Lab specific types]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Type Organization Strategy
|
||||
|
||||
### Type Placement Hierarchy
|
||||
|
||||
1. **Component-Colocated** (90% of cases)
|
||||
```typescript
|
||||
// Same file as component
|
||||
interface MyComponentProps {
|
||||
title: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
2. **Feature-Shared**
|
||||
```typescript
|
||||
// src/[domain]/components/[Feature]/types.ts
|
||||
export interface FilterConfiguration {
|
||||
filterId: string;
|
||||
targets: NativeFilterTarget[];
|
||||
}
|
||||
```
|
||||
|
||||
3. **Domain-Wide**
|
||||
```typescript
|
||||
// src/[domain]/types.ts
|
||||
export interface ExploreFormData extends QueryFormData {
|
||||
viz_type: string;
|
||||
}
|
||||
```
|
||||
|
||||
4. **Global**
|
||||
```typescript
|
||||
// src/types/[TypeName].ts
|
||||
export interface ApiResponse<T> {
|
||||
result: T;
|
||||
count?: number;
|
||||
}
|
||||
```
|
||||
|
||||
### Type Discovery Commands
|
||||
```bash
|
||||
# Search existing types before creating
|
||||
find superset-frontend/src -name "types.ts" -exec grep -l "[TypeConcept]" {} \;
|
||||
grep -r "interface.*Props\|type.*Props" superset-frontend/src/
|
||||
```
|
||||
|
||||
### Derivative Component Patterns
|
||||
|
||||
**Rule:** Components that extend others should extend their type interfaces.
|
||||
|
||||
```typescript
|
||||
// ✅ Base component type
|
||||
interface SelectProps {
|
||||
value: string | number;
|
||||
options: SelectOption[];
|
||||
onChange: (value: string | number) => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
// ✅ Derivative extends base
|
||||
interface ChartSelectProps extends SelectProps {
|
||||
charts: Chart[];
|
||||
onChartSelect: (chart: Chart) => void;
|
||||
}
|
||||
|
||||
// ✅ Derivative with modified props
|
||||
interface DatabaseSelectProps extends Omit<SelectProps, 'value' | 'onChange'> {
|
||||
value: number; // Narrowed type
|
||||
onChange: (databaseId: number) => void; // Specific signature
|
||||
}
|
||||
```
|
||||
|
||||
**Common Patterns:**
|
||||
- **Extension:** `extends BaseProps` - adds new props
|
||||
- **Omission:** `Omit<BaseProps, 'prop'>` - removes props
|
||||
- **Modification:** `Omit<BaseProps, 'prop'> & { prop: NewType }` - changes prop type
|
||||
- **Restriction:** Override with narrower types (union → specific)
|
||||
|
||||
---
|
||||
|
||||
## 📋 Migration Recipe
|
||||
|
||||
### Step 2: File Conversion
|
||||
```bash
|
||||
# Use git mv to preserve history
|
||||
git mv component.js component.ts
|
||||
git mv Component.jsx Component.tsx
|
||||
```
|
||||
|
||||
### Step 3: Import & Type Setup
|
||||
```typescript
|
||||
// Import order (enforced by linting)
|
||||
import { FC, ReactNode } from 'react';
|
||||
import { JsonObject, QueryFormData } from '@superset-ui/core';
|
||||
import { Dataset } from '@superset-ui/chart-controls';
|
||||
import type { Dashboard } from 'src/types/Dashboard';
|
||||
```
|
||||
|
||||
### Step 4: Function & Component Typing
|
||||
```typescript
|
||||
// Functions with proper parameter/return types
|
||||
export function processData(
|
||||
data: Dataset[],
|
||||
config: JsonObject
|
||||
): ProcessedData[] {
|
||||
// implementation
|
||||
}
|
||||
|
||||
// Component props with inheritance
|
||||
interface ComponentProps extends BaseProps {
|
||||
data: Chart[];
|
||||
onSelect: (id: number) => void;
|
||||
}
|
||||
|
||||
const Component: FC<ComponentProps> = ({ data, onSelect }) => {
|
||||
// implementation
|
||||
};
|
||||
```
|
||||
|
||||
### Step 5: State & Redux Typing
|
||||
```typescript
|
||||
// Hooks with specific types
|
||||
const [data, setData] = useState<Chart[]>([]);
|
||||
const [selected, setSelected] = useState<number | null>(null);
|
||||
|
||||
// Redux with existing RootState
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
charts: state.charts,
|
||||
user: state.user,
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Type Debugging Strategies (Real-World Learnings)
|
||||
|
||||
### The Evolution of Type Approaches
|
||||
When you hit type errors, follow this debugging evolution:
|
||||
|
||||
#### 1. ❌ Idealized Union Types (First Attempt)
|
||||
```typescript
|
||||
// Looks clean but doesn't match reality
|
||||
type DatasourceInput = Datasource | QueryEditor;
|
||||
```
|
||||
**Problem**: Real calling sites pass variations, not exact types.
|
||||
|
||||
#### 2. ❌ Overly Precise Types (Second Attempt)
|
||||
```typescript
|
||||
// Tried to match exact calling signatures
|
||||
type DatasourceInput =
|
||||
| IDatasource // From DatasourcePanel
|
||||
| (QueryEditor & { columns: ColumnMeta[] }); // From SaveQuery
|
||||
```
|
||||
**Problem**: Too rigid, doesn't handle legacy variations.
|
||||
|
||||
#### 3. ✅ Flexible Interface (Final Solution)
|
||||
```typescript
|
||||
// Captures what the function actually needs
|
||||
interface DatasourceInput {
|
||||
name?: string | null; // Allow null for compatibility
|
||||
datasource_name?: string | null; // Legacy variations
|
||||
columns?: any[]; // Multiple column types accepted
|
||||
database?: { id?: number };
|
||||
// ... other optional properties
|
||||
}
|
||||
```
|
||||
**Success**: Works with all calling sites, focuses on function needs.
|
||||
|
||||
### Type Debugging Process
|
||||
1. **Start with compilation errors** - they show exact mismatches
|
||||
2. **Examine actual usage** - look at calling sites, not idealized types
|
||||
3. **Build flexible interfaces** - capture what functions need, not rigid contracts
|
||||
4. **Iterate based on downstream validation** - let calling sites guide your types
|
||||
|
||||
---
|
||||
|
||||
## 🚨 Anti-Patterns to Avoid
|
||||
|
||||
```typescript
|
||||
// ❌ Never use any
|
||||
const obj: any = {};
|
||||
|
||||
// ✅ Use proper types
|
||||
const obj: Record<string, JsonObject> = {};
|
||||
|
||||
// ❌ Don't recreate base component props
|
||||
interface ChartSelectProps {
|
||||
value: string; // Duplicated from SelectProps
|
||||
onChange: () => void; // Duplicated from SelectProps
|
||||
charts: Chart[]; // New prop
|
||||
}
|
||||
|
||||
// ✅ Inherit and extend
|
||||
interface ChartSelectProps extends SelectProps {
|
||||
charts: Chart[]; // Only new props
|
||||
}
|
||||
|
||||
// ❌ Don't create ad-hoc type variations
|
||||
interface UserInfo {
|
||||
name: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
// ✅ Extend existing types (DRY principle)
|
||||
import { User } from 'src/types/bootstrapTypes';
|
||||
type UserDisplayInfo = Pick<User, 'firstName' | 'lastName' | 'email'>;
|
||||
|
||||
// ❌ Don't create overly rigid unions
|
||||
type StrictInput = ExactTypeA | ExactTypeB;
|
||||
|
||||
// ✅ Create flexible interfaces for function parameters
|
||||
interface FlexibleInput {
|
||||
// Focus on what the function actually needs
|
||||
commonProperty: string;
|
||||
optionalVariations?: any; // Allow for legacy variations
|
||||
}
|
||||
```
|
||||
|
||||
## 📍 DRY Type Guidelines (WHERE TYPES BELONG)
|
||||
|
||||
### Type Placement Rules
|
||||
**CRITICAL**: Type variations must live close to where they belong, not scattered across files.
|
||||
|
||||
#### ✅ Proper Type Organization
|
||||
```typescript
|
||||
// ❌ Don't create one-off interfaces in utility files
|
||||
// src/utils/datasourceUtils.ts
|
||||
interface DatasourceInput { /* custom interface */ } // Wrong!
|
||||
|
||||
// ✅ Use existing types or extend them in their proper domain
|
||||
// src/utils/datasourceUtils.ts
|
||||
import { IDatasource } from 'src/explore/components/DatasourcePanel';
|
||||
import { QueryEditor } from 'src/SqlLab/types';
|
||||
|
||||
// Create flexible interface that references existing types
|
||||
interface FlexibleDatasourceInput {
|
||||
// Properties that actually exist across variations
|
||||
}
|
||||
```
|
||||
|
||||
#### Type Location Hierarchy
|
||||
1. **Domain Types**: `src/{domain}/types.ts` (dashboard, explore, SqlLab)
|
||||
2. **Component Types**: Co-located with components
|
||||
3. **Global Types**: `src/types/` directory
|
||||
4. **Utility Types**: Only when they truly don't belong elsewhere
|
||||
|
||||
#### ✅ DRY Type Patterns
|
||||
```typescript
|
||||
// ✅ Extend existing domain types
|
||||
interface SaveQueryData extends Pick<QueryEditor, 'sql' | 'dbId' | 'catalog'> {
|
||||
columns: ColumnMeta[]; // Add what's needed
|
||||
}
|
||||
|
||||
// ✅ Create flexible interfaces for cross-domain utilities
|
||||
interface CrossDomainInput {
|
||||
// Common properties that exist across different source types
|
||||
name?: string | null; // Accommodate legacy null values
|
||||
// Only include properties the function actually uses
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎯 PropTypes Auto-Generation (Elegant Approach)
|
||||
|
||||
**IMPORTANT**: Superset has `babel-plugin-typescript-to-proptypes` configured to automatically generate PropTypes from TypeScript interfaces. Use this instead of manual PropTypes duplication!
|
||||
|
||||
### ❌ Manual PropTypes Duplication (Avoid This)
|
||||
```typescript
|
||||
export interface MyComponentProps {
|
||||
title: string;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
// 8+ lines of manual PropTypes duplication 😱
|
||||
const propTypes = PropTypes.shape({
|
||||
title: PropTypes.string.isRequired,
|
||||
count: PropTypes.number,
|
||||
});
|
||||
|
||||
export default propTypes;
|
||||
```
|
||||
|
||||
### ✅ Auto-Generated PropTypes (Use This)
|
||||
```typescript
|
||||
import { InferProps } from 'prop-types';
|
||||
|
||||
export interface MyComponentProps {
|
||||
title: string;
|
||||
count?: number;
|
||||
}
|
||||
|
||||
// Single validator function - babel plugin auto-generates PropTypes! ✨
|
||||
export default function MyComponentValidator(props: MyComponentProps) {
|
||||
return null; // PropTypes auto-assigned by babel-plugin-typescript-to-proptypes
|
||||
}
|
||||
|
||||
// Optional: For consumers needing PropTypes type inference
|
||||
export type MyComponentPropsInferred = InferProps<typeof MyComponentValidator>;
|
||||
```
|
||||
|
||||
### Migration Pattern for Type-Only Files
|
||||
|
||||
**When migrating type-only files with manual PropTypes:**
|
||||
|
||||
1. **Keep the TypeScript interfaces** (single source of truth)
|
||||
2. **Replace manual PropTypes** with validator function
|
||||
3. **Remove PropTypes imports** and manual shape definitions
|
||||
4. **Add InferProps import** if type inference needed
|
||||
|
||||
**Example Migration:**
|
||||
```typescript
|
||||
// Before: 25+ lines with manual PropTypes duplication
|
||||
export interface AdhocFilterType { /* ... */ }
|
||||
const adhocFilterTypePropTypes = PropTypes.oneOfType([...]);
|
||||
|
||||
// After: 3 lines with auto-generation
|
||||
export interface AdhocFilterType { /* ... */ }
|
||||
export default function AdhocFilterValidator(props: { filter: AdhocFilterType }) {
|
||||
return null; // Auto-generated PropTypes by babel plugin
|
||||
}
|
||||
```
|
||||
|
||||
### Component PropTypes Pattern
|
||||
|
||||
**For React components, the babel plugin works automatically:**
|
||||
|
||||
```typescript
|
||||
interface ComponentProps {
|
||||
title: string;
|
||||
onClick: () => void;
|
||||
}
|
||||
|
||||
const MyComponent: FC<ComponentProps> = ({ title, onClick }) => {
|
||||
// Component implementation
|
||||
};
|
||||
|
||||
// PropTypes automatically generated by babel plugin - no manual work needed!
|
||||
export default MyComponent;
|
||||
```
|
||||
|
||||
### Auto-Generation Benefits
|
||||
|
||||
- ✅ **Single source of truth**: TypeScript interfaces drive PropTypes
|
||||
- ✅ **No duplication**: Eliminate 15-20 lines of manual PropTypes code
|
||||
- ✅ **Automatic updates**: Changes to TypeScript automatically update PropTypes
|
||||
- ✅ **Type safety**: Compile-time checking ensures PropTypes match interfaces
|
||||
- ✅ **Backward compatibility**: Existing JavaScript components continue working
|
||||
|
||||
### Babel Plugin Configuration
|
||||
|
||||
The plugin is already configured in `babel.config.js`:
|
||||
```javascript
|
||||
['babel-plugin-typescript-to-proptypes', { loose: true }]
|
||||
```
|
||||
|
||||
**No additional setup required** - just use TypeScript interfaces and the plugin handles the rest!
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Test File Migration Patterns
|
||||
|
||||
### Test File Priority
|
||||
- **Always migrate test files** alongside production files
|
||||
- **Test files are often leaf nodes** - good starting candidates
|
||||
- **Create tests if missing** - Leverage new TypeScript types for better test coverage
|
||||
|
||||
### Test-Specific Type Patterns
|
||||
```typescript
|
||||
// Mock interfaces for testing
|
||||
interface MockStore {
|
||||
getState: () => Partial<RootState>; // Partial allows minimal mocking
|
||||
}
|
||||
|
||||
// Type-safe mocking for complex objects
|
||||
const mockDashboardInfo: Partial<DashboardInfo> as DashboardInfo = {
|
||||
id: 123,
|
||||
json_metadata: '{}',
|
||||
};
|
||||
|
||||
// Sinon stub typing
|
||||
let postStub: sinon.SinonStub;
|
||||
beforeEach(() => {
|
||||
postStub = sinon.stub(SupersetClient, 'post');
|
||||
});
|
||||
|
||||
// Use stub reference instead of original method
|
||||
expect(postStub.callCount).toBe(1);
|
||||
expect(postStub.getCall(0).args[0].endpoint).toMatch('/api/');
|
||||
```
|
||||
|
||||
### Test Migration Recipe
|
||||
1. **Migrate production file first** (if both need migration)
|
||||
2. **Update test imports** to point to `.ts/.tsx` files
|
||||
3. **Add proper mock typing** using `Partial<T> as T` pattern
|
||||
4. **Fix stub typing** - Use stub references, not original methods
|
||||
5. **Verify all tests pass** with TypeScript compilation
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Type Conflict Resolution
|
||||
|
||||
### Multiple Type Definitions Issue
|
||||
**Problem**: Same type name defined in multiple files causes compilation errors.
|
||||
|
||||
**Example**: `DashboardInfo` defined in both:
|
||||
- `src/dashboard/reducers/types.ts` (minimal)
|
||||
- `src/dashboard/components/Header/types.ts` (different shape)
|
||||
- `src/dashboard/types.ts` (complete - used by RootState)
|
||||
|
||||
### Resolution Strategy
|
||||
1. **Identify the authoritative type**:
|
||||
```bash
|
||||
# Find which type is used by RootState/main interfaces
|
||||
grep -r "DashboardInfo" src/dashboard/types.ts
|
||||
```
|
||||
|
||||
2. **Use import from authoritative source**:
|
||||
```typescript
|
||||
// ✅ Import from main domain types
|
||||
import { RootState, DashboardInfo } from 'src/dashboard/types';
|
||||
|
||||
// ❌ Don't import from component-specific files
|
||||
import { DashboardInfo } from 'src/dashboard/components/Header/types';
|
||||
```
|
||||
|
||||
3. **Mock complex types in tests**:
|
||||
```typescript
|
||||
// For testing - provide minimal required fields
|
||||
const mockInfo: Partial<DashboardInfo> as DashboardInfo = {
|
||||
id: 123,
|
||||
json_metadata: '{}',
|
||||
// Only provide fields actually used in test
|
||||
};
|
||||
```
|
||||
|
||||
### Type Hierarchy Discovery Commands
|
||||
```bash
|
||||
# Find all definitions of a type
|
||||
grep -r "interface.*TypeName\|type.*TypeName" src/
|
||||
|
||||
# Find import usage patterns
|
||||
grep -r "import.*TypeName" src/
|
||||
|
||||
# Check what RootState uses
|
||||
grep -A 10 -B 10 "TypeName" src/*/types.ts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Agent Constraints (CRITICAL)
|
||||
|
||||
1. **Use git mv** - Run `git mv file.js file.ts` to preserve git history, but NO `git commit`
|
||||
2. **NO global import changes** - Don't update imports across codebase
|
||||
3. **Type files OK** - Can modify existing type files to improve/align types
|
||||
4. **Single-File TypeScript Validation** (CRITICAL) - tsc has known issues with multi-file compilation:
|
||||
- **Core Issue**: TypeScript's `tsc` has documented problems validating multiple files simultaneously in complex projects
|
||||
- **Solution**: ALWAYS validate files one at a time using individual `tsc` calls
|
||||
- **Command Pattern**: `cd superset-frontend && npx tscw --noEmit --allowJs --composite false --project tsconfig.json {single-file-path}`
|
||||
- **Why**: Multi-file validation can produce false positives, miss real errors, and conflict during parallel agent execution
|
||||
5. **Downstream Impact Validation** (CRITICAL) - Your migration affects calling sites:
|
||||
- **Find downstream files**: `find superset-frontend/src -name "*.tsx" -o -name "*.ts" | xargs grep -l "your-core-filename" 2>/dev/null || echo "No files found"`
|
||||
- **Validate each downstream file individually**: `cd superset-frontend && npx tscw --noEmit --allowJs --composite false --project tsconfig.json {each-downstream-file}`
|
||||
- **Fix type mismatches** you introduced in calling sites
|
||||
- **NEVER ignore downstream errors** - they indicate your types don't match reality
|
||||
6. **Avoid Project-Wide Validation During Migration**:
|
||||
- **NEVER use `npm run type`** during parallel agent execution - produces unreliable results
|
||||
- **Single-file validation is authoritative** - trust individual file checks over project-wide scans
|
||||
6. **ESLint validation** - Run `npm run eslint -- --fix {file}` for each migrated file to auto-fix formatting/linting issues
|
||||
6. Zero `any` types - use proper TypeScript types
|
||||
7. Search existing types before creating new ones
|
||||
8. Follow patterns from this guide
|
||||
|
||||
---
|
||||
|
||||
## Success Report Format
|
||||
|
||||
```
|
||||
SUCCESS: Atomic Migration of {core-filename}
|
||||
|
||||
## Files Migrated (Atomic Unit)
|
||||
- Core: {core-filename} → {core-filename.ts/tsx}
|
||||
- Tests: {list-of-test-files} → {list-of-test-files.ts/tsx} OR "CREATED: {basename}.test.ts"
|
||||
- Mocks: {list-of-mock-files} → {list-of-mock-files.ts}
|
||||
- Type files modified: {list-of-type-files}
|
||||
|
||||
## Types Created/Improved
|
||||
- {TypeName}: {location} ({scope}) - {rationale}
|
||||
- {ExistingType}: enhanced in {location} - {improvement-description}
|
||||
|
||||
## Documentation Recommendations
|
||||
- ADD_TO_DIRECTORY: {TypeName} - {reason}
|
||||
- NO_DOCUMENTATION: {TypeName} - {reason}
|
||||
|
||||
## Quality Validation
|
||||
- **Single-File TypeScript Validation**: ✅ PASS - Core files individually validated
|
||||
- Core file: `npx tscw --noEmit --allowJs --composite false --project tsconfig.json {core-file}`
|
||||
- Test files: `npx tscw --noEmit --allowJs --composite false --project tsconfig.json {test-file}` (if exists)
|
||||
- **Downstream Impact Check**: ✅ PASS - Found {N} files importing this module, all validate individually
|
||||
- Downstream files: {list-of-files-that-import-your-module}
|
||||
- Individual validation: `npx tscw --noEmit --allowJs --composite false --project tsconfig.json {each-downstream-file}`
|
||||
- **ESLint validation**: ✅ PASS (using `npm run eslint -- --fix {files}` to auto-fix formatting)
|
||||
- **Zero any types**: ✅ PASS
|
||||
- **Local imports resolved**: ✅ PASS
|
||||
- **Functionality preserved**: ✅ PASS
|
||||
- **Tests pass** (if test file): ✅ PASS
|
||||
- **Follow-up action required**: {YES/NO}
|
||||
|
||||
## Validation Strategy Notes
|
||||
- **Single-file approach used**: Avoided multi-file tsc validation due to known TypeScript compilation issues
|
||||
- **Project-wide validation skipped**: `npm run type` not used during parallel migration to prevent false positives
|
||||
|
||||
## Migration Learnings
|
||||
- Type conflicts encountered: {describe any multiple type definitions}
|
||||
- Mock patterns used: {describe test mocking approaches}
|
||||
- Import hierarchy decisions: {note authoritative type sources used}
|
||||
- PropTypes strategy: {AUTO_GENERATED via babel plugin | MANUAL_DUPLICATION_REMOVED | N/A}
|
||||
|
||||
## Improvement Suggestions for Documentation
|
||||
- AGENT.md enhancement: {suggest additions to migration guide}
|
||||
- Common pattern identified: {note reusable patterns for future migrations}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependency Block Report Format
|
||||
|
||||
```
|
||||
DEPENDENCY_BLOCK: Cannot migrate {filename}
|
||||
|
||||
## Blocking Dependencies
|
||||
- {path}: {type} - {usage} - {priority}
|
||||
|
||||
## Impact Analysis
|
||||
- Estimated types: {number}
|
||||
- Expected locations: {list}
|
||||
- Cross-domain: {YES/NO}
|
||||
|
||||
## Recommended Order
|
||||
{ordered-list}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Quick Reference
|
||||
|
||||
**Type Utilities:**
|
||||
- `Record<K, V>` - Object with specific key/value types
|
||||
- `Partial<T>` - All properties optional
|
||||
- `Pick<T, K>` - Subset of properties
|
||||
- `Omit<T, K>` - Exclude specific properties
|
||||
- `NonNullable<T>` - Exclude null/undefined
|
||||
|
||||
**Event Types:**
|
||||
- `MouseEvent<HTMLButtonElement>`
|
||||
- `ChangeEvent<HTMLInputElement>`
|
||||
- `FormEvent<HTMLFormElement>`
|
||||
|
||||
**React Types:**
|
||||
- `FC<Props>` - Functional component
|
||||
- `ReactNode` - Any renderable content
|
||||
- `CSSProperties` - Style objects
|
||||
|
||||
---
|
||||
|
||||
**Remember:** Every type should add value and clarity. The goal is meaningful type safety that catches bugs and improves developer experience.
|
||||
199
.claude/projects/js-to-ts/COORDINATOR.md
Normal file
199
.claude/projects/js-to-ts/COORDINATOR.md
Normal file
@@ -0,0 +1,199 @@
|
||||
# JS-to-TS Coordinator Workflow
|
||||
|
||||
**Role:** Strategic migration coordination - select leaf-node files, trigger agents, review results, handle integration, manage dependencies.
|
||||
|
||||
---
|
||||
|
||||
## 1. Core File Selection Strategy
|
||||
|
||||
**Target ONLY Core Files**: Coordinators identify core files (production code), agents handle related tests/mocks atomically.
|
||||
|
||||
**File Analysis Commands**:
|
||||
```bash
|
||||
# Find CORE files with no JS/JSX dependencies (exclude tests/mocks) - SIZE PRIORITIZED
|
||||
find superset-frontend/src -name "*.js" -o -name "*.jsx" | grep -v "test\|spec\|mock" | xargs wc -l | sort -n | head -20
|
||||
|
||||
# Alternative: Get file sizes in lines with paths
|
||||
find superset-frontend/src -name "*.js" -o -name "*.jsx" | grep -v "test\|spec\|mock" | while read file; do
|
||||
lines=$(wc -l < "$file")
|
||||
echo "$lines $file"
|
||||
done | sort -n | head -20
|
||||
|
||||
# Check dependencies for core files only (start with smallest)
|
||||
for file in <core-files-sorted-by-size>; do
|
||||
echo "=== $file ($(wc -l < "$file") lines) ==="
|
||||
grep -E "from '\.\./.*\.jsx?'|from '\./.*\.jsx?'|from 'src/.*\.jsx?'" "$file" || echo "✅ LEAF CANDIDATE"
|
||||
done
|
||||
|
||||
# Identify heavily imported files (migrate last)
|
||||
grep -r "from.*utils/common" superset-frontend/src/ | wc -l
|
||||
|
||||
# Quick leaf analysis with size priority
|
||||
find superset-frontend/src -name "*.js" -o -name "*.jsx" | grep -v "test\|spec\|mock" | head -30 | while read file; do
|
||||
deps=$(grep -E "from '\.\./.*\.jsx?'|from '\./.*\.jsx?'|from 'src/.*\.jsx?'" "$file" | wc -l)
|
||||
lines=$(wc -l < "$file")
|
||||
if [ "$deps" -eq 0 ]; then
|
||||
echo "✅ LEAF: $lines lines - $file"
|
||||
fi
|
||||
done | sort -n
|
||||
```
|
||||
|
||||
**Priority Order** (Smallest files first for easier wins):
|
||||
1. **Small leaf files** (<50 lines) - No JS/JSX imports, quick TypeScript conversion
|
||||
2. **Medium leaf files** (50-200 lines) - Self-contained utilities and helpers
|
||||
3. **Small dependency files** (<100 lines) - Import only already-migrated files
|
||||
4. **Larger components** (200+ lines) - Complex but well-contained functionality
|
||||
5. **Core foundational files** (utils/common.js, controls.jsx) - migrate last regardless of size
|
||||
|
||||
**Size-First Benefits**:
|
||||
- Faster completion builds momentum
|
||||
- Earlier validation of migration patterns
|
||||
- Easier rollback if issues arise
|
||||
- Better success rate for agent learning
|
||||
|
||||
**Migration Unit**: Each agent call migrates:
|
||||
- 1 core file (primary target)
|
||||
- All related `*.test.js/jsx` files
|
||||
- All related `*.mock.js` files
|
||||
- All related `__mocks__/` files
|
||||
|
||||
---
|
||||
|
||||
## 2. Task Creation & Agent Control
|
||||
|
||||
### Task Triggering
|
||||
When triggering the `/js-to-ts` command:
|
||||
- **Task Title**: Use the core filename as the task title (e.g., "DebouncedMessageQueue.js migration", "hostNamesConfig.js migration")
|
||||
- **Task Description**: Include the full relative path to help agent locate the file
|
||||
- **Reference**: Point agent to [AGENT.md](./AGENT.md) for technical instructions
|
||||
|
||||
### Post-Processing Workflow
|
||||
After each agent completes:
|
||||
|
||||
1. **Review Agent Report**: Always read and analyze the complete agent report
|
||||
2. **Share Summary**: Provide user with key highlights from agent's work:
|
||||
- Files migrated (core + tests/mocks)
|
||||
- Types created or improved
|
||||
- Any validation issues or coordinator actions needed
|
||||
3. **Quality Assessment**: Evaluate agent's TypeScript implementation against criteria:
|
||||
- ✅ **Type Usage**: Proper types used, no `any` types
|
||||
- ✅ **Type Filing**: Types placed in correct hierarchy (component → feature → domain → global)
|
||||
- ✅ **Side Effects**: No unintended changes to other files
|
||||
- ✅ **Import Alignment**: Proper .ts/.tsx import extensions
|
||||
4. **Integration Decision**:
|
||||
- **COMMIT**: If agent work is complete and high quality
|
||||
- **FIX & COMMIT**: If minor issues need coordinator fixes
|
||||
- **ROLLBACK**: If major issues require complete rework
|
||||
5. **Next Action**: Ask user preference - commit this work or trigger next migration
|
||||
|
||||
---
|
||||
|
||||
## 3. Integration Decision Framework
|
||||
|
||||
**Automatic Integration** ✅:
|
||||
- `npm run type` passes without errors
|
||||
- Agent created clean TypeScript with proper types
|
||||
- Types appropriately filed in hierarchy
|
||||
|
||||
**Coordinator Integration** (Fix Side-Effects) 🔧:
|
||||
- `npm run type` fails BUT agent's work is high quality
|
||||
- Good type usage, proper patterns, well-organized
|
||||
- Side-effects are manageable TypeScript compilation errors
|
||||
- **Coordinator Action**: Integrate the change, then fix global compilation issues
|
||||
|
||||
**Rollback Only** ❌:
|
||||
- Agent introduced `any` types or poor type choices
|
||||
- Types poorly organized or conflicting with existing patterns
|
||||
- Fundamental approach issues requiring complete rework
|
||||
|
||||
**Integration Process**:
|
||||
1. **Review**: Agent already used `git mv` to preserve history
|
||||
2. **Fix Side-Effects**: Update dependent files with proper import extensions
|
||||
3. **Resolve Types**: Fix any cascading type issues across codebase
|
||||
4. **Validate**: Ensure `npm run type` passes after fixes
|
||||
|
||||
---
|
||||
|
||||
## 4. Common Integration Patterns
|
||||
|
||||
**Common Side-Effects (Expect These)**:
|
||||
- **Type import conflicts**: Multiple definitions of same type name
|
||||
- **Mock object typing**: Tests need complete type satisfaction
|
||||
- **Stub method references**: Use stub vars instead of original methods
|
||||
|
||||
**Coordinator Fixes (Standard Process)**:
|
||||
1. **Import Resolution**:
|
||||
```bash
|
||||
# Find authoritative type source
|
||||
grep -r "TypeName" src/*/types.ts
|
||||
# Import from domain types (src/dashboard/types.ts) not component types
|
||||
```
|
||||
|
||||
2. **Test Mock Completion**:
|
||||
```typescript
|
||||
// Use Partial<T> as T pattern for minimal mocking
|
||||
const mockDashboard: Partial<DashboardInfo> as DashboardInfo = {
|
||||
id: 123,
|
||||
json_metadata: '{}',
|
||||
};
|
||||
```
|
||||
|
||||
3. **Stub Reference Fixes**:
|
||||
```typescript
|
||||
// ✅ Use stub variable
|
||||
expect(postStub.callCount).toBe(1);
|
||||
// ❌ Don't use original method
|
||||
expect(SupersetClient.post.callCount).toBe(1);
|
||||
```
|
||||
|
||||
4. **Validation Commands**:
|
||||
```bash
|
||||
npm run type # TypeScript compilation
|
||||
npm test -- filename # Test functionality
|
||||
git status # Should show rename, not add/delete
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. File Categories for Planning
|
||||
|
||||
### Leaf Files (Start Here)
|
||||
**Self-contained files with minimal JS/JSX dependencies**:
|
||||
- Test files (80 files) - Usually only import the file being tested
|
||||
- Utility files without internal dependencies
|
||||
- Components importing only external libraries
|
||||
|
||||
### Heavily Imported Files (Migrate Last)
|
||||
**Core files that many others depend on**:
|
||||
- `utils/common.js` - Core utility functions
|
||||
- `utils/reducerUtils.js` - Redux helpers
|
||||
- `@superset-ui/core` equivalent files
|
||||
- Major state management files (`explore/store.js`, `dashboard/actions/`)
|
||||
|
||||
### Complex Components (Middle Priority)
|
||||
**Large files requiring careful type analysis**:
|
||||
- `components/Datasource/DatasourceEditor.jsx` (1,809 lines)
|
||||
- `explore/components/controls/AnnotationLayerControl/AnnotationLayer.jsx` (1,031 lines)
|
||||
- `explore/components/ExploreViewContainer/index.jsx` (911 lines)
|
||||
|
||||
---
|
||||
|
||||
## 6. Success Metrics & Continuous Improvement
|
||||
|
||||
**Per-File Gates**:
|
||||
- ✅ `npm run type` passes after each migration
|
||||
- ✅ Zero `any` types introduced
|
||||
- ✅ All imports properly typed
|
||||
- ✅ Types filed in correct hierarchy
|
||||
|
||||
**Linear Scheduling**:
|
||||
When agents report `DEPENDENCY_BLOCK`:
|
||||
- Queue dependencies in linear order
|
||||
- Process one file at a time to avoid conflicts
|
||||
- Handle cascading type changes between files
|
||||
|
||||
**After Each Migration**:
|
||||
1. **Update guides** with new patterns discovered
|
||||
2. **Document coordinator fixes** that become common
|
||||
3. **Enhance agent instructions** based on recurring issues
|
||||
4. **Track success metrics** - automatic vs coordinator integration rates
|
||||
76
.claude/projects/js-to-ts/PROJECT.md
Normal file
76
.claude/projects/js-to-ts/PROJECT.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# JavaScript to TypeScript Migration Project
|
||||
|
||||
Progressive migration of 219 JS/JSX files to TypeScript in Apache Superset frontend.
|
||||
|
||||
## 📁 Project Documentation
|
||||
|
||||
- **[AGENT.md](./AGENT.md)** - Complete technical migration guide for agents (includes type reference, patterns, validation)
|
||||
- **[COORDINATOR.md](./COORDINATOR.md)** - Strategic workflow for coordinators (file selection, task management, integration)
|
||||
|
||||
## 🎯 Quick Start
|
||||
|
||||
**For Agents:** Read [AGENT.md](./AGENT.md) for complete migration instructions
|
||||
**For Coordinators:** Read [COORDINATOR.md](./COORDINATOR.md) for workflow and [AGENT.md](./AGENT.md) for supervision
|
||||
|
||||
**Command:** `/js-to-ts <filename>` - See [../../commands/js-to-ts.md](../../commands/js-to-ts.md)
|
||||
|
||||
## 📊 Migration Progress
|
||||
|
||||
**Scope**: 219 files total (112 JS + 107 JSX)
|
||||
- Production files: 139 (63%)
|
||||
- Test files: 80 (37%)
|
||||
|
||||
**Strategy**: Leaf-first migration with dependency-aware coordination
|
||||
|
||||
### Completed Migrations ✅
|
||||
|
||||
1. **roundDecimal** - `plugins/legacy-plugin-chart-map-box/src/utils/roundDecimal.js`
|
||||
- Migrated core + test files
|
||||
- Added proper TypeScript function signature with optional precision parameter
|
||||
- All tests pass
|
||||
|
||||
2. **timeGrainSqlaAnimationOverrides** - `src/explore/controlPanels/timeGrainSqlaAnimationOverrides.js`
|
||||
- Migrated to TypeScript with ControlPanelState and Dataset types
|
||||
- Added TimeGrainOverrideState interface for return type
|
||||
- Used type guards for safe property access
|
||||
|
||||
3. **DebouncedMessageQueue** - `src/utils/DebouncedMessageQueue.js`
|
||||
- Migrated to TypeScript with proper generics
|
||||
- Created DebouncedMessageQueueOptions interface
|
||||
- **CREATED test file** with 4 comprehensive test cases
|
||||
- Excellent class property typing with private/readonly modifiers
|
||||
|
||||
**Files Migrated**: 3/219 (1.4%)
|
||||
**Tests Created**: 2 (roundDecimal had existing, DebouncedMessageQueue created)
|
||||
|
||||
### Next Candidates (Leaf Nodes) 🎯
|
||||
|
||||
**Identified leaf files with no JS/JSX dependencies:**
|
||||
- `src/utils/hostNamesConfig.js` - Domain configuration utility
|
||||
- `src/explore/controlPanels/Separator.js` - Control panel configuration
|
||||
- `src/middleware/loggerMiddleware.js` - Logging middleware
|
||||
|
||||
**Migration Quality**: All completed migrations have:
|
||||
- ✅ Zero `any` types
|
||||
- ✅ Proper TypeScript compilation
|
||||
- ✅ ESLint validation passed
|
||||
- ✅ Test coverage (created where missing)
|
||||
|
||||
---
|
||||
|
||||
## 📈 Success Metrics
|
||||
|
||||
**Per-File Gates**:
|
||||
- ✅ `npm run type` passes after each migration
|
||||
- ✅ Zero `any` types introduced
|
||||
- ✅ All imports properly typed
|
||||
- ✅ Types filed in correct hierarchy
|
||||
|
||||
**Overall Progress**:
|
||||
- **Automatic Integration Rate**: 100% (3/3 migrations required no coordinator fixes)
|
||||
- **Test Coverage**: Improved (1 new test file created)
|
||||
- **Type Safety**: Enhanced with proper interfaces and generics
|
||||
|
||||
---
|
||||
|
||||
*This is a claudette-managed progressive refactor. All documentation and coordination resources are organized under `.claude/projects/js-to-ts/`*
|
||||
4
LLMS.md
4
LLMS.md
@@ -70,6 +70,10 @@ superset/
|
||||
- **New files require ASF license headers** - When creating new code files, include the standard Apache Software Foundation license header
|
||||
- **LLM instruction files are excluded** - Files like LLMS.md, CLAUDE.md, etc. are in `.rat-excludes` to avoid header token overhead
|
||||
|
||||
### Code Comments
|
||||
- **Avoid time-specific language** - Don't use words like "now", "currently", "today" in code comments as they become outdated
|
||||
- **Write timeless comments** - Comments should remain accurate regardless of when they're read
|
||||
|
||||
## Documentation Requirements
|
||||
|
||||
- **docs/**: Update for any user-facing changes
|
||||
|
||||
@@ -28,6 +28,7 @@ x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset
|
||||
x-superset-volumes:
|
||||
&superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||
- ./docker:/app/docker
|
||||
- ./superset-core:/app/superset-core
|
||||
- superset_home:/app/superset_home
|
||||
|
||||
services:
|
||||
|
||||
@@ -29,9 +29,11 @@ x-superset-volumes: &superset-volumes
|
||||
# /app/pythonpath_docker will be appended to the PYTHONPATH in the final container
|
||||
- ./docker:/app/docker
|
||||
- ./superset:/app/superset
|
||||
- ./superset-core:/app/superset-core
|
||||
- ./superset-frontend:/app/superset-frontend
|
||||
- superset_home:/app/superset_home
|
||||
- ./tests:/app/tests
|
||||
- superset_data:/app/data
|
||||
x-common-build: &common-build
|
||||
context: .
|
||||
target: ${SUPERSET_BUILD_TARGET:-dev} # can use `dev` (default) or `lean`
|
||||
@@ -274,3 +276,5 @@ volumes:
|
||||
external: false
|
||||
redis:
|
||||
external: false
|
||||
superset_data:
|
||||
external: false
|
||||
|
||||
@@ -21,8 +21,15 @@ set -eo pipefail
|
||||
# Make python interactive
|
||||
if [ "$DEV_MODE" == "true" ]; then
|
||||
if [ "$(whoami)" = "root" ] && command -v uv > /dev/null 2>&1; then
|
||||
echo "Reinstalling the app in editable mode"
|
||||
uv pip install -e .
|
||||
# Always ensure superset-core is available
|
||||
echo "Installing superset-core in editable mode"
|
||||
uv pip install --no-deps -e /app/superset-core
|
||||
|
||||
# Only reinstall the main app for non-worker processes
|
||||
if [ "$1" != "worker" ] && [ "$1" != "beat" ]; then
|
||||
echo "Reinstalling the app in editable mode"
|
||||
uv pip install -e .
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
REQUIREMENTS_LOCAL="/app/docker/requirements-local.txt"
|
||||
@@ -34,7 +41,8 @@ if [ "$CYPRESS_CONFIG" == "true" ]; then
|
||||
export SUPERSET__SQLALCHEMY_DATABASE_URI=postgresql+psycopg2://superset:superset@db:5432/superset_cypress
|
||||
PORT=8081
|
||||
fi
|
||||
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ]; then
|
||||
# Skip postgres requirements installation for workers to avoid conflicts
|
||||
if [[ "$DATABASE_DIALECT" == postgres* ]] && [ "$(whoami)" = "root" ] && [ "$1" != "worker" ] && [ "$1" != "beat" ]; then
|
||||
# older images may not have the postgres dev requirements installed
|
||||
echo "Installing postgres requirements"
|
||||
if command -v uv > /dev/null 2>&1; then
|
||||
|
||||
@@ -36,11 +36,11 @@ Screenshots will be taken but no messages actually sent as long as `ALERT_REPORT
|
||||
#### In your `Dockerfile`
|
||||
|
||||
You'll need to extend the Superset image to include a headless browser. Your options include:
|
||||
- Use Playwright with Chrome: this is the recommended approach as of version >=4.1.x. A working example of a Dockerfile that installs these tools is provided under “Building your own production Docker image” on the [Docker Builds](/docs/installation/docker-builds#building-your-own-production-docker-image) page. Read the code comments there as you'll also need to change a feature flag in your config.
|
||||
- Use Playwright with Chrome: this is the recommended approach as of version 4.1.x or greater. A working example of a Dockerfile that installs these tools is provided under "Building your own production Docker image" on the [Docker Builds](/docs/installation/docker-builds#building-your-own-production-docker-image) page. Read the code comments there as you'll also need to change a feature flag in your config.
|
||||
- Use Firefox: you'll need to install geckodriver and Firefox.
|
||||
- Use Chrome without Playwright: you'll need to install Chrome and set the value of `WEBDRIVER_TYPE` to `"chrome"` in your `superset_config.py`.
|
||||
|
||||
In Superset versions <=4.0x, users installed Firefox or Chrome and that was documented here.
|
||||
In Superset versions prior to 4.1, users installed Firefox or Chrome and that was documented here.
|
||||
|
||||
Only the worker container needs the browser.
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ are compatible with Superset.
|
||||
| [IBM Netezza Performance Server](/docs/configuration/databases#ibm-netezza-performance-server) | `pip install nzalchemy` | `netezza+nzpy://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||
| [MySQL](/docs/configuration/databases#mysql) | `pip install mysqlclient` | `mysql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||
| [OceanBase](/docs/configuration/databases#oceanbase) | `pip install oceanbase_py` | `oceanbase://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||
| [Oracle](/docs/configuration/databases#oracle) | `pip install cx_Oracle` | `oracle://<username>:<password>@<hostname>:<port>` |
|
||||
| [Oracle](/docs/configuration/databases#oracle) | `pip install oracledb` | `oracle://<username>:<password>@<hostname>:<port>` |
|
||||
| [Parseable](/docs/configuration/databases#parseable) | `pip install sqlalchemy-parseable` | `parseable://<UserName>:<DBPassword>@<Database Host>/<Stream Name>` |
|
||||
| [PostgreSQL](/docs/configuration/databases#postgres) | `pip install psycopg2` | `postgresql://<UserName>:<DBPassword>@<Database Host>/<Database Name>` |
|
||||
| [Presto](/docs/configuration/databases#presto) | `pip install pyhive` | `presto://{username}:{password}@{hostname}:{port}/{database}` |
|
||||
|
||||
@@ -7,7 +7,7 @@ version: 1
|
||||
# Theming Superset
|
||||
|
||||
:::note
|
||||
apache-superset>=6.0
|
||||
`apache-superset>=6.0`
|
||||
:::
|
||||
|
||||
Superset now rides on **Ant Design v5's token-based theming**.
|
||||
|
||||
@@ -130,7 +130,7 @@ Committers may also update title to reflect the issue/PR content if the author-p
|
||||
|
||||
If the PR passes CI tests and does not have any `need:` labels, it is ready for review, add label `review` and/or `design-review`.
|
||||
|
||||
If an issue/PR has been inactive for >=30 days, it will be closed. If it does not have any status label, add `inactive`.
|
||||
If an issue/PR has been inactive for at least 30 days, it will be closed. If it does not have any status label, add `inactive`.
|
||||
|
||||
When creating a PR, if you're aiming to have it included in a specific release, please tag it with the version label. For example, to have a PR considered for inclusion in Superset 1.1 use the label `v1.1`.
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ maintainers:
|
||||
- name: craig-rueda
|
||||
email: craig@craigrueda.com
|
||||
url: https://github.com/craig-rueda
|
||||
version: 0.15.0 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
|
||||
version: 0.15.1 # See [README](https://github.com/apache/superset/blob/master/helm/superset/README.md#versioning) for version details.
|
||||
dependencies:
|
||||
- name: postgresql
|
||||
version: 13.4.4
|
||||
|
||||
@@ -23,7 +23,7 @@ NOTE: This file is generated by helm-docs: https://github.com/norwoodj/helm-docs
|
||||
|
||||
# superset
|
||||
|
||||

|
||||

|
||||
|
||||
Apache Superset is a modern, enterprise-ready business intelligence web application
|
||||
|
||||
@@ -203,6 +203,7 @@ On helm this can be set on `extraSecretEnv.SUPERSET_SECRET_KEY` or `configOverri
|
||||
| supersetNode.connections.db_name | string | `"superset"` | |
|
||||
| supersetNode.connections.db_pass | string | `"superset"` | |
|
||||
| supersetNode.connections.db_port | string | `"5432"` | |
|
||||
| supersetNode.connections.db_type | string | `"postgresql"` | Database type for Superset metadata (Supported types: "postgresql", "mysql") |
|
||||
| supersetNode.connections.db_user | string | `"superset"` | |
|
||||
| supersetNode.connections.redis_cache_db | string | `"1"` | |
|
||||
| supersetNode.connections.redis_celery_db | string | `"0"` | |
|
||||
|
||||
@@ -96,7 +96,18 @@ CACHE_CONFIG = {
|
||||
}
|
||||
DATA_CACHE_CONFIG = CACHE_CONFIG
|
||||
|
||||
SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{env('DB_USER')}:{env('DB_PASS')}@{env('DB_HOST')}:{env('DB_PORT')}/{env('DB_NAME')}"
|
||||
|
||||
if os.getenv("SQLALCHEMY_DATABASE_URI"):
|
||||
SQLALCHEMY_DATABASE_URI = os.getenv("SQLALCHEMY_DATABASE_URI")
|
||||
else:
|
||||
{{- if eq .Values.supersetNode.connections.db_type "postgresql" }}
|
||||
SQLALCHEMY_DATABASE_URI = f"postgresql+psycopg2://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
|
||||
{{- else if eq .Values.supersetNode.connections.db_type "mysql" }}
|
||||
SQLALCHEMY_DATABASE_URI = f"mysql+mysqldb://{os.getenv('DB_USER')}:{os.getenv('DB_PASS')}@{os.getenv('DB_HOST')}:{os.getenv('DB_PORT')}/{os.getenv('DB_NAME')}"
|
||||
{{- else }}
|
||||
{{ fail (printf "Unsupported database type: %s. Please use 'postgresql' or 'mysql'." .Values.supersetNode.connections.db_type) }}
|
||||
{{- end }}
|
||||
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = True
|
||||
|
||||
class CeleryConfig:
|
||||
|
||||
@@ -289,6 +289,8 @@ supersetNode:
|
||||
enabled: false
|
||||
ssl_cert_reqs: CERT_NONE
|
||||
# You need to change below configuration incase bringing own PostgresSQL instance and also set postgresql.enabled:false
|
||||
# -- Database type for Superset metadata (Supported types: "postgresql", "mysql")
|
||||
db_type: "postgresql"
|
||||
db_host: "{{ .Release.Name }}-postgresql"
|
||||
db_port: "5432"
|
||||
db_user: superset
|
||||
|
||||
@@ -100,7 +100,7 @@ dependencies = [
|
||||
"slack_sdk>=3.19.0, <4",
|
||||
"sqlalchemy>=1.4, <2",
|
||||
"sqlalchemy-utils>=0.38.3, <0.39",
|
||||
"sqlglot>=27.3.0, <28",
|
||||
"sqlglot>=27.15.2, <28",
|
||||
# newer pandas needs 0.9+
|
||||
"tabulate>=0.9.0, <1.0",
|
||||
"typing-extensions>=4, <5",
|
||||
|
||||
@@ -395,7 +395,7 @@ sqlalchemy-utils==0.38.3
|
||||
# via
|
||||
# apache-superset (pyproject.toml)
|
||||
# flask-appbuilder
|
||||
sqlglot==27.3.0
|
||||
sqlglot==27.15.2
|
||||
# via apache-superset (pyproject.toml)
|
||||
sshtunnel==0.4.0
|
||||
# via apache-superset (pyproject.toml)
|
||||
|
||||
@@ -848,7 +848,7 @@ sqlalchemy-utils==0.38.3
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
# flask-appbuilder
|
||||
sqlglot==27.3.0
|
||||
sqlglot==27.15.2
|
||||
# via
|
||||
# -c requirements/base-constraint.txt
|
||||
# apache-superset
|
||||
|
||||
@@ -83,6 +83,7 @@ module.exports = {
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:react-prefer-function-component/recommended',
|
||||
'plugin:storybook/recommended',
|
||||
'plugin:react-you-might-not-need-an-effect/legacy-recommended',
|
||||
],
|
||||
parser: '@babel/eslint-parser',
|
||||
parserOptions: {
|
||||
@@ -348,6 +349,14 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
'no-only-tests/no-only-tests': 'error',
|
||||
'no-restricted-globals': [
|
||||
'error',
|
||||
{
|
||||
name: 'describe',
|
||||
message:
|
||||
'Use test() instead of describe() for better test organization',
|
||||
},
|
||||
],
|
||||
'max-classes-per-file': 0,
|
||||
// temporary rules to help with migration - please re-enable!
|
||||
'testing-library/await-async-queries': 0,
|
||||
@@ -412,13 +421,6 @@ module.exports = {
|
||||
'icons/no-fa-icons-usage': 'error',
|
||||
'i18n-strings/no-template-vars': ['error', true],
|
||||
'i18n-strings/sentence-case-buttons': 'error',
|
||||
camelcase: [
|
||||
'error',
|
||||
{
|
||||
allow: ['^UNSAFE_'],
|
||||
properties: 'never',
|
||||
},
|
||||
],
|
||||
'class-methods-use-this': 0,
|
||||
curly: 2,
|
||||
'func-names': 0,
|
||||
|
||||
1
superset-frontend/.gitignore
vendored
1
superset-frontend/.gitignore
vendored
@@ -3,3 +3,4 @@ cypress/screenshots
|
||||
cypress/videos
|
||||
src/temp
|
||||
.temp_cache/
|
||||
.tsbuildinfo
|
||||
|
||||
58
superset-frontend/package-lock.json
generated
58
superset-frontend/package-lock.json
generated
@@ -232,6 +232,7 @@
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-prefer-function-component": "^3.3.0",
|
||||
"eslint-plugin-react-you-might-not-need-an-effect": "^0.5.1",
|
||||
"eslint-plugin-storybook": "^0.8.0",
|
||||
"eslint-plugin-testing-library": "^6.4.0",
|
||||
"eslint-plugin-theme-colors": "file:eslint-rules/eslint-plugin-theme-colors",
|
||||
@@ -8885,9 +8886,9 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/@ndelangen/get-tarball/node_modules/tar-fs": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz",
|
||||
"integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==",
|
||||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
|
||||
"integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -25929,6 +25930,36 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eslint-plugin-react-you-might-not-need-an-effect": {
|
||||
"version": "0.5.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react-you-might-not-need-an-effect/-/eslint-plugin-react-you-might-not-need-an-effect-0.5.1.tgz",
|
||||
"integrity": "sha512-Gi2kfHLkXUT3j+IAwgb8TEhY10iMwsdwSsgbIxk98zPpuPW7M52ey9fU1oPZrWUlyekr5eXwUCjeTHekS6Isrw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eslint-utils": "^3.0.0",
|
||||
"globals": "^16.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=8.40.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react-you-might-not-need-an-effect/node_modules/globals": {
|
||||
"version": "16.4.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz",
|
||||
"integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-react/node_modules/doctrine": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
||||
@@ -26044,6 +26075,25 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-utils": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
||||
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mysticatea"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-visitor-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
|
||||
@@ -60690,7 +60740,7 @@
|
||||
},
|
||||
"packages/superset-core": {
|
||||
"name": "@apache-superset/core",
|
||||
"version": "0.0.1-rc4",
|
||||
"version": "0.0.1-rc5",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.26.4",
|
||||
|
||||
@@ -305,6 +305,7 @@
|
||||
"eslint-plugin-react": "^7.37.2",
|
||||
"eslint-plugin-react-hooks": "^4.6.2",
|
||||
"eslint-plugin-react-prefer-function-component": "^3.3.0",
|
||||
"eslint-plugin-react-you-might-not-need-an-effect": "^0.5.1",
|
||||
"eslint-plugin-storybook": "^0.8.0",
|
||||
"eslint-plugin-testing-library": "^6.4.0",
|
||||
"eslint-plugin-theme-colors": "file:eslint-rules/eslint-plugin-theme-colors",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@apache-superset/core",
|
||||
"version": "0.0.1-rc4",
|
||||
"version": "0.0.1-rc5",
|
||||
"description": "This package contains UI elements, APIs, and utility functions used by Superset.",
|
||||
"sideEffects": false,
|
||||
"main": "lib/index.js",
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||
"baseUrl": "../..",
|
||||
"outDir": "lib"
|
||||
|
||||
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||
// but packages need paths relative to their own directory
|
||||
"outDir": "lib",
|
||||
"rootDir": "src",
|
||||
"declarationDir": "lib"
|
||||
},
|
||||
"include": ["src/**/*", "types/**/*"],
|
||||
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"]
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
* under the License.
|
||||
*/
|
||||
import { ReactNode } from 'react';
|
||||
import { css, GenericDataType, styled, t } from '@superset-ui/core';
|
||||
import { css, styled, t } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import {
|
||||
ClockCircleOutlined,
|
||||
QuestionOutlined,
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Popover, type PopoverProps } from '@superset-ui/core/components';
|
||||
import type ReactAce from 'react-ace';
|
||||
import {
|
||||
Popover,
|
||||
type PopoverProps,
|
||||
SQLEditor,
|
||||
} from '@superset-ui/core/components';
|
||||
import { CalculatorOutlined } from '@ant-design/icons';
|
||||
import { css, styled, useTheme, t } from '@superset-ui/core';
|
||||
|
||||
@@ -35,24 +37,10 @@ const StyledCalculatorIcon = styled(CalculatorOutlined)`
|
||||
|
||||
export const SQLPopover = (props: PopoverProps & { sqlExpression: string }) => {
|
||||
const theme = useTheme();
|
||||
const [AceEditor, setAceEditor] = useState<typeof ReactAce | null>(null);
|
||||
useEffect(() => {
|
||||
Promise.all([
|
||||
import('react-ace'),
|
||||
import('ace-builds/src-min-noconflict/mode-sql'),
|
||||
]).then(([reactAceModule]) => {
|
||||
setAceEditor(() => reactAceModule.default);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (!AceEditor) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<Popover
|
||||
content={
|
||||
<AceEditor
|
||||
mode="sql"
|
||||
<SQLEditor
|
||||
value={props.sqlExpression}
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
setOptions={{
|
||||
@@ -65,7 +53,6 @@ export const SQLPopover = (props: PopoverProps & { sqlExpression: string }) => {
|
||||
wrapEnabled
|
||||
style={{
|
||||
border: `1px solid ${theme.colorBorder}`,
|
||||
background: theme.colorPrimaryBg,
|
||||
maxWidth: theme.sizeUnit * 100,
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -16,13 +16,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
DTTM_ALIAS,
|
||||
GenericDataType,
|
||||
QueryColumn,
|
||||
QueryMode,
|
||||
t,
|
||||
} from '@superset-ui/core';
|
||||
import { DTTM_ALIAS, QueryColumn, QueryMode, t } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { ColumnMeta, SortSeriesData, SortSeriesType } from './types';
|
||||
|
||||
export const DEFAULT_MAX_ROW = 100000;
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { DatasourceType, GenericDataType } from '@superset-ui/core';
|
||||
import { DatasourceType } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { Dataset } from './types';
|
||||
|
||||
export const TestDataset: Dataset = {
|
||||
|
||||
@@ -20,13 +20,13 @@
|
||||
import {
|
||||
ContributionType,
|
||||
ensureIsArray,
|
||||
GenericDataType,
|
||||
getColumnLabel,
|
||||
getMetricLabel,
|
||||
QueryFormColumn,
|
||||
QueryFormMetric,
|
||||
t,
|
||||
} from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import {
|
||||
ControlPanelState,
|
||||
ControlState,
|
||||
|
||||
@@ -17,12 +17,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
GenericDataType,
|
||||
QueryColumn,
|
||||
t,
|
||||
validateNonEmpty,
|
||||
} from '@superset-ui/core';
|
||||
import { QueryColumn, t, validateNonEmpty } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import {
|
||||
ExtraControlProps,
|
||||
SharedControlConfig,
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { ensureIsArray, GenericDataType, ValueOf } from '@superset-ui/core';
|
||||
import { ensureIsArray, ValueOf } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { ControlPanelState, isDataset, isQueryResponse } from '../types';
|
||||
|
||||
export function checkColumnType(
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { GenericDataType, QueryColumn, QueryResponse } from '@superset-ui/core';
|
||||
import { QueryColumn, QueryResponse } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { ColumnMeta, Dataset, isDataset, isQueryResponse } from '../types';
|
||||
|
||||
export function columnsByType(
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
GenericDataType,
|
||||
getColumnLabel,
|
||||
isPhysicalColumn,
|
||||
QueryFormColumn,
|
||||
} from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { checkColumnType, ControlStateMapping } from '..';
|
||||
|
||||
export function isSortable(controls: ControlStateMapping): boolean {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
*/
|
||||
import '@testing-library/jest-dom';
|
||||
import { render } from '@superset-ui/core/spec';
|
||||
import { GenericDataType } from '@superset-ui/core';
|
||||
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { ColumnOption, ColumnOptionProps } from '../../src';
|
||||
|
||||
jest.mock('@superset-ui/chart-controls/components/SQLPopover', () => ({
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
@@ -19,8 +20,7 @@
|
||||
import { isValidElement } from 'react';
|
||||
import { render, screen } from '@superset-ui/core/spec';
|
||||
import '@testing-library/jest-dom';
|
||||
import { GenericDataType } from '@superset-ui/core';
|
||||
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { ColumnTypeLabel, ColumnTypeLabelProps } from '../../src';
|
||||
|
||||
describe('ColumnOption', () => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { GenericDataType, testQueryResponse } from '@superset-ui/core';
|
||||
import { testQueryResponse } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { checkColumnType, TestDataset } from '../../src';
|
||||
|
||||
test('checkColumnType columns from a Dataset', () => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
@@ -16,11 +17,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
DatasourceType,
|
||||
GenericDataType,
|
||||
testQueryResponse,
|
||||
} from '@superset-ui/core';
|
||||
import { DatasourceType, testQueryResponse } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { columnChoices } from '../../src';
|
||||
|
||||
describe('columnChoices()', () => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import {
|
||||
GenericDataType,
|
||||
testQueryResponse,
|
||||
testQueryResults,
|
||||
} from '@superset-ui/core';
|
||||
import { testQueryResponse, testQueryResults } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import {
|
||||
Dataset,
|
||||
getTemporalColumns,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
import { ControlStateMapping } from '@superset-ui/chart-controls';
|
||||
import { GenericDataType } from '@superset-ui/core';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { isSortable } from '../../src/utils/isSortable';
|
||||
|
||||
const controls: ControlStateMapping = {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
// Path Resolution: Override baseUrl to maintain correct path mappings from parent config
|
||||
// (e.g., "@apache-superset/core" -> "./packages/superset-core/src")
|
||||
"baseUrl": "../..",
|
||||
"outDir": "lib"
|
||||
|
||||
// Directory Overrides: Parent config paths are relative to frontend root,
|
||||
// but packages need paths relative to their own directory
|
||||
"outDir": "lib",
|
||||
"rootDir": "src",
|
||||
"declarationDir": "lib"
|
||||
},
|
||||
"include": ["src/**/*", "types/**/*"],
|
||||
"exclude": ["src/**/*.test.*", "src/**/*.stories.*"],
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -127,13 +127,9 @@ const Select = forwardRef(
|
||||
const shouldShowSearch = allowNewOptions ? true : showSearch;
|
||||
const [selectValue, setSelectValue] = useState(value);
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [isLoading, setIsLoading] = useState(loading);
|
||||
const [isDropdownVisible, setIsDropdownVisible] = useState(false);
|
||||
const [isSearching, setIsSearching] = useState(false);
|
||||
const [visibleOptions, setVisibleOptions] = useState<SelectOptionsType>([]);
|
||||
const [maxTagCount, setMaxTagCount] = useState(
|
||||
propsMaxTagCount ?? MAX_TAG_COUNT,
|
||||
);
|
||||
const [onChangeCount, setOnChangeCount] = useState(0);
|
||||
const previousChangeCount = usePrevious(onChangeCount, 0);
|
||||
const fireOnChange = useCallback(
|
||||
@@ -141,11 +137,11 @@ const Select = forwardRef(
|
||||
[onChangeCount],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (oneLine) {
|
||||
setMaxTagCount(isDropdownVisible ? 0 : 1);
|
||||
}
|
||||
}, [isDropdownVisible, oneLine]);
|
||||
const maxTagCount = oneLine
|
||||
? isDropdownVisible
|
||||
? 0
|
||||
: 1
|
||||
: (propsMaxTagCount ?? MAX_TAG_COUNT);
|
||||
|
||||
const mappedMode = isSingleMode ? undefined : 'multiple';
|
||||
|
||||
@@ -510,6 +506,8 @@ const Select = forwardRef(
|
||||
],
|
||||
);
|
||||
|
||||
const isLoading = loading ?? false;
|
||||
|
||||
const popupRender = (
|
||||
originNode: ReactElement & { ref?: RefObject<HTMLElement> },
|
||||
) =>
|
||||
@@ -536,12 +534,6 @@ const Select = forwardRef(
|
||||
setVisibleOptions(initialOptions);
|
||||
}, [initialOptions]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loading !== undefined && loading !== isLoading) {
|
||||
setIsLoading(loading);
|
||||
}
|
||||
}, [isLoading, loading]);
|
||||
|
||||
useEffect(() => {
|
||||
setSelectValue(value);
|
||||
}, [value]);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { GenericDataType } from './QueryResponse';
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { QueryFormColumn } from './QueryFormData';
|
||||
|
||||
export interface AdhocColumn {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { DatasourceType } from './Datasource';
|
||||
import { BinaryOperator, SetOperator, UnaryOperator } from './Operator';
|
||||
import { AppliedTimeExtras, TimeRange } from './Time';
|
||||
@@ -31,7 +32,7 @@ import { Maybe } from '../../types';
|
||||
import { PostProcessingRule } from './PostProcessing';
|
||||
import { JsonObject } from '../../connection';
|
||||
import { TimeGranularity } from '../../time-format';
|
||||
import { GenericDataType, DataRecordValue } from './QueryResponse';
|
||||
import { DataRecordValue } from './QueryResponse';
|
||||
|
||||
export type BaseQueryObjectFilterClause = {
|
||||
col: QueryFormColumn;
|
||||
|
||||
@@ -17,19 +17,10 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { GenericDataType } from '@apache-superset/core/api/core';
|
||||
import { TimeseriesDataRecord } from '../../chart';
|
||||
import { AnnotationData } from './AnnotationLayer';
|
||||
|
||||
/**
|
||||
* Generic data types, see enum of the same name in superset/utils/core.py.
|
||||
*/
|
||||
export enum GenericDataType {
|
||||
Numeric = 0,
|
||||
String = 1,
|
||||
Temporal = 2,
|
||||
Boolean = 3,
|
||||
}
|
||||
|
||||
/**
|
||||
* Primitive types for data field values.
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-restricted-globals */
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user