mirror of
https://github.com/apache/superset.git
synced 2026-05-07 00:44:26 +00:00
Checkpoint
This commit is contained in:
@@ -54,6 +54,12 @@ let createColumnsVerification: any = null;
|
||||
let createSemanticLayerOnChange: any = null;
|
||||
let SEMANTIC_LAYER_CONTROL_FIELDS: any = null;
|
||||
|
||||
// Notification system for when utilities are set
|
||||
const enhancedControls: Array<{
|
||||
controlName: string;
|
||||
invalidateCache: () => void;
|
||||
}> = [];
|
||||
|
||||
// Export function to set semantic layer utilities from main app
|
||||
export function setSemanticLayerUtilities(utilities: {
|
||||
withAsyncVerification: any;
|
||||
@@ -69,6 +75,11 @@ export function setSemanticLayerUtilities(utilities: {
|
||||
createSemanticLayerOnChange,
|
||||
SEMANTIC_LAYER_CONTROL_FIELDS,
|
||||
} = utilities);
|
||||
|
||||
// Notify all enhanced controls that utilities are now available
|
||||
enhancedControls.forEach(control => {
|
||||
control.invalidateCache();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,27 +103,52 @@ function enhanceControlWithSemanticLayer(
|
||||
controlName: string,
|
||||
verificationType: 'metrics' | 'columns',
|
||||
) {
|
||||
// Cache for the enhanced control type
|
||||
let cachedEnhancedType: any = null;
|
||||
let utilitiesWereAvailable = false;
|
||||
|
||||
// Register with notification system
|
||||
enhancedControls.push({
|
||||
controlName,
|
||||
invalidateCache: () => {
|
||||
cachedEnhancedType = null;
|
||||
utilitiesWereAvailable = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Return a control that will be enhanced at runtime if utilities are available
|
||||
return {
|
||||
...baseControl,
|
||||
// Override the type to use a function that checks for enhancement at runtime
|
||||
get type() {
|
||||
if (withAsyncVerification) {
|
||||
const verificationFn =
|
||||
verificationType === 'metrics'
|
||||
? createMetricsVerification(controlName)
|
||||
: createColumnsVerification(controlName);
|
||||
|
||||
return withAsyncVerification({
|
||||
baseControl: baseControl.type,
|
||||
verify: verificationFn,
|
||||
onChange: createSemanticLayerOnChange(
|
||||
controlName,
|
||||
SEMANTIC_LAYER_CONTROL_FIELDS,
|
||||
),
|
||||
showLoadingState: true,
|
||||
});
|
||||
// Check if utilities became available since last call
|
||||
const utilitiesAvailableNow = !!withAsyncVerification;
|
||||
|
||||
if (utilitiesAvailableNow) {
|
||||
// If utilities just became available or we haven't cached yet, create enhanced control
|
||||
if (!utilitiesWereAvailable || !cachedEnhancedType) {
|
||||
const verificationFn =
|
||||
verificationType === 'metrics'
|
||||
? createMetricsVerification(controlName)
|
||||
: createColumnsVerification(controlName);
|
||||
|
||||
cachedEnhancedType = withAsyncVerification({
|
||||
baseControl: baseControl.type,
|
||||
verify: verificationFn,
|
||||
onChange: createSemanticLayerOnChange(
|
||||
controlName,
|
||||
SEMANTIC_LAYER_CONTROL_FIELDS,
|
||||
),
|
||||
showLoadingState: true,
|
||||
});
|
||||
|
||||
utilitiesWereAvailable = true;
|
||||
}
|
||||
|
||||
return cachedEnhancedType;
|
||||
}
|
||||
|
||||
utilitiesWereAvailable = false;
|
||||
return baseControl.type;
|
||||
},
|
||||
mapStateToProps: (state: any, controlState: any) => {
|
||||
@@ -131,6 +167,7 @@ function enhanceControlWithSemanticLayer(
|
||||
...originalProps,
|
||||
needAsyncVerification: needsVerification,
|
||||
form_data: state.form_data,
|
||||
datasource: state.datasource, // Pass datasource to verification function
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,9 @@ function supportsSemanticLayerVerification(datasource: Dataset): boolean {
|
||||
return Boolean(database.engine_information?.supports_dynamic_columns);
|
||||
}
|
||||
|
||||
// Cache for API calls to prevent duplicates
|
||||
const apiCallCache = new Map<string, Promise<{ dimensions: string[]; metrics: string[] } | null>>();
|
||||
|
||||
/**
|
||||
* Call the validation API
|
||||
*/
|
||||
@@ -112,19 +115,40 @@ async function callValidationAPI(
|
||||
return null;
|
||||
}
|
||||
|
||||
// Create cache key based on the request parameters
|
||||
const cacheKey = JSON.stringify({
|
||||
datasource_id: datasource.id,
|
||||
dimensions: selectedDimensions.sort(),
|
||||
metrics: selectedMetrics.sort(),
|
||||
});
|
||||
|
||||
// Check if we already have a pending request for the same parameters
|
||||
if (apiCallCache.has(cacheKey)) {
|
||||
return apiCallCache.get(cacheKey)!;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await SupersetClient.post({
|
||||
const apiPromise = SupersetClient.post({
|
||||
endpoint: `/api/v1/database/${databaseId}/valid_metrics_and_dimensions/`,
|
||||
jsonPayload: {
|
||||
datasource_id: datasource.id,
|
||||
dimensions: selectedDimensions,
|
||||
metrics: selectedMetrics,
|
||||
},
|
||||
});
|
||||
}).then(response => response.json as { dimensions: string[]; metrics: string[] });
|
||||
|
||||
return response.json as { dimensions: string[]; metrics: string[] };
|
||||
// Cache the promise
|
||||
apiCallCache.set(cacheKey, apiPromise);
|
||||
|
||||
// Remove from cache after a short delay to allow for immediate duplicates
|
||||
setTimeout(() => {
|
||||
apiCallCache.delete(cacheKey);
|
||||
}, 100);
|
||||
|
||||
return await apiPromise;
|
||||
} catch (error) {
|
||||
console.warn('Failed to fetch valid metrics and dimensions:', error);
|
||||
apiCallCache.delete(cacheKey);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -233,6 +257,7 @@ export function createColumnsVerification(controlName?: string): AsyncVerify {
|
||||
const queryFields = collectQueryFields(updatedFormData || {});
|
||||
|
||||
// Call validation API
|
||||
|
||||
const validationResult = await callValidationAPI(
|
||||
datasource as Dataset,
|
||||
queryFields.dimensions,
|
||||
|
||||
@@ -146,6 +146,7 @@ export default function withAsyncVerification({
|
||||
const [isLoading, setIsLoading] = useState<boolean>(initialIsLoading);
|
||||
const { addWarningToast } = restProps.actions;
|
||||
const verificationTriggeredByChange = useRef(false);
|
||||
|
||||
|
||||
// memoize `restProps`, so that verification only triggers when material
|
||||
// props are actually updated.
|
||||
|
||||
Reference in New Issue
Block a user