Compare commits

...

1 Commits

Author SHA1 Message Date
Beto Dealmeida
418cd809e3 feat(semantic-layer): add frontend support for semantic views
Update frontend to support semantic layer datasources:
- Add SemanticView to DatasourceType enum
- Extend DatasourceKey to handle semantic_view type
- Update datasource ID type to support string UUIDs
- Update DrillBy modal for semantic view compatibility
- Update explore utilities for semantic view form data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 21:59:21 -05:00
7 changed files with 34 additions and 15 deletions

View File

@@ -19,16 +19,27 @@
import { DatasourceType } from './types/Datasource';
const DATASOURCE_TYPE_MAP: Record<string, DatasourceType> = {
table: DatasourceType.Table,
query: DatasourceType.Query,
dataset: DatasourceType.Dataset,
sl_table: DatasourceType.SlTable,
saved_query: DatasourceType.SavedQuery,
semantic_view: DatasourceType.SemanticView,
};
export default class DatasourceKey {
readonly id: number;
readonly id: number | string;
readonly type: DatasourceType;
constructor(key: string) {
const [idStr, typeStr] = key.split('__');
this.id = parseInt(idStr, 10);
this.type = DatasourceType.Table; // default to SqlaTable model
this.type = typeStr === 'query' ? DatasourceType.Query : this.type;
// Only parse as integer if the entire string is numeric
// (parseInt would incorrectly parse "85d3139f..." as 85)
const isNumeric = /^\d+$/.test(idStr);
this.id = isNumeric ? parseInt(idStr, 10) : idStr;
this.type = DATASOURCE_TYPE_MAP[typeStr] ?? DatasourceType.Table;
}
public toString() {

View File

@@ -26,6 +26,7 @@ export enum DatasourceType {
Dataset = 'dataset',
SlTable = 'sl_table',
SavedQuery = 'saved_query',
SemanticView = 'semantic_view',
}
export interface Currency {
@@ -37,7 +38,7 @@ export interface Currency {
* Datasource metadata.
*/
export interface Datasource {
id: number;
id: number | string;
name: string;
type: DatasourceType;
columns: Column[];

View File

@@ -159,7 +159,7 @@ export interface QueryObject
export interface QueryContext {
datasource: {
id: number;
id: number | string;
type: DatasourceType;
};
/** Force refresh of all queries */

View File

@@ -90,11 +90,16 @@ const ModalFooter = ({ formData, closeModal }: ModalFooterProps) => {
findPermission('can_explore', 'Superset', state.user?.roles),
);
const [datasource_id, datasource_type] = formData.datasource.split('__');
const [datasourceIdStr, datasource_type] = formData.datasource.split('__');
// Try to parse as integer, fall back to string (UUID) if NaN
const parsedDatasourceId = parseInt(datasourceIdStr, 10);
const datasource_id = Number.isNaN(parsedDatasourceId)
? datasourceIdStr
: parsedDatasourceId;
useEffect(() => {
// short circuit if the user is embedded as explore is not available
if (isEmbedded()) return;
postFormData(Number(datasource_id), datasource_type, formData, 0)
postFormData(datasource_id, datasource_type, formData, 0)
.then(key => {
setUrl(
`/explore/?form_data_key=${key}&dashboard_page_id=${dashboardPageId}`,

View File

@@ -272,7 +272,7 @@ export type Slice = {
changed_on: number;
changed_on_humanized: string;
modified: string;
datasource_id: number;
datasource_id: number | string;
datasource_type: DatasourceType;
datasource_url: string;
datasource_name: string;

View File

@@ -144,12 +144,14 @@ export const getSlicePayload = async (
...adhocFilters,
dashboards,
};
let datasourceId = 0;
let datasourceId: number | string = 0;
let datasourceType: DatasourceType = DatasourceType.Table;
if (formData.datasource) {
const [id, typeString] = formData.datasource.split('__');
datasourceId = parseInt(id, 10);
// Try to parse as integer, fall back to string (UUID) if NaN
const parsedId = parseInt(id, 10);
datasourceId = Number.isNaN(parsedId) ? id : parsedId;
const formattedTypeString =
typeString.charAt(0).toUpperCase() + typeString.slice(1);

View File

@@ -20,7 +20,7 @@ import { SupersetClient, JsonObject, JsonResponse } from '@superset-ui/core';
import { sanitizeFormData } from 'src/utils/sanitizeFormData';
type Payload = {
datasource_id: number;
datasource_id: number | string;
datasource_type: string;
form_data: string;
chart_id?: number;
@@ -36,7 +36,7 @@ const assembleEndpoint = (key?: string, tabId?: string) => {
};
const assemblePayload = (
datasourceId: number,
datasourceId: number | string,
datasourceType: string,
formData: JsonObject,
chartId?: number,
@@ -53,7 +53,7 @@ const assemblePayload = (
};
export const postFormData = (
datasourceId: number,
datasourceId: number | string,
datasourceType: string,
formData: JsonObject,
chartId?: number,
@@ -70,7 +70,7 @@ export const postFormData = (
}).then((r: JsonResponse) => r.json.key);
export const putFormData = (
datasourceId: number,
datasourceId: number | string,
datasourceType: string,
key: string,
formData: JsonObject,