This is an automated email from the ASF dual-hosted git repository. beto pushed a commit to branch semantic-layer-rename-database-dataset in repository https://gitbox.apache.org/repos/asf/superset.git
commit e1b8abbb83ccc1d7e5ba2d9aabb285dac4fd3181 Author: Beto Dealmeida <[email protected]> AuthorDate: Thu Mar 12 10:12:32 2026 -0400 chore: rename database/database when using semantic layers --- superset-frontend/src/features/home/RightMenu.tsx | 14 ++-- superset-frontend/src/pages/DatabaseList/index.tsx | 28 +++++--- superset-frontend/src/pages/DatasetList/index.tsx | 82 ++++++++++++++++------ superset-frontend/src/utils/semanticLayerLabels.ts | 63 +++++++++++++++++ 4 files changed, 150 insertions(+), 37 deletions(-) diff --git a/superset-frontend/src/features/home/RightMenu.tsx b/superset-frontend/src/features/home/RightMenu.tsx index 28c25498642..ea35f46db16 100644 --- a/superset-frontend/src/features/home/RightMenu.tsx +++ b/superset-frontend/src/features/home/RightMenu.tsx @@ -66,6 +66,10 @@ import { RightMenuProps, } from './types'; import { NAVBAR_MENU_POPUP_OFFSET } from './commonMenuData'; +import { + datasetLabelLower, + databaseLabelLower, +} from 'src/utils/semanticLayerLabels'; const extensionsRegistry = getExtensionsRegistry(); @@ -176,12 +180,12 @@ const RightMenu = ({ icon: <Icons.DatabaseOutlined data-test={`menu-item-${t('Data')}`} />, childs: [ { - label: t('Connect database'), + label: t('Connect %s', databaseLabelLower()), name: GlobalMenuDataOptions.DbConnection, perm: canDatabase && !nonExamplesDBConnected, }, { - label: t('Create dataset'), + label: t('Create %s', datasetLabelLower()), name: GlobalMenuDataOptions.DatasetCreation, url: '/dataset/add/', perm: canDataset && nonExamplesDBConnected, @@ -192,19 +196,19 @@ const RightMenu = ({ perm: canDatabase && HAS_GSHEETS_INSTALLED, }, { - label: t('Upload CSV to database'), + label: t('Upload CSV to %s', databaseLabelLower()), name: GlobalMenuDataOptions.CSVUpload, perm: canUploadCSV && showUploads, disable: isAdmin && !allowUploads, }, { - label: t('Upload Excel to database'), + label: t('Upload Excel to %s', databaseLabelLower()), name: GlobalMenuDataOptions.ExcelUpload, perm: canUploadExcel && showUploads, disable: isAdmin && !allowUploads, }, { - label: t('Upload Columnar file to database'), + label: t('Upload Columnar file to %s', databaseLabelLower()), name: GlobalMenuDataOptions.ColumnarUpload, perm: canUploadColumnar && showUploads, disable: isAdmin && !allowUploads, diff --git a/superset-frontend/src/pages/DatabaseList/index.tsx b/superset-frontend/src/pages/DatabaseList/index.tsx index a263fe2d2b4..c428d84b229 100644 --- a/superset-frontend/src/pages/DatabaseList/index.tsx +++ b/superset-frontend/src/pages/DatabaseList/index.tsx @@ -68,6 +68,11 @@ import { DatabaseObject } from 'src/features/databases/types'; import { QueryObjectColumns } from 'src/views/CRUD/types'; import { WIDER_DROPDOWN_WIDTH } from 'src/components/ListView/utils'; import { ModalTitleWithIcon } from 'src/components/ModalTitleWithIcon'; +import { + databaseLabel, + databaseLabelLower, + databasesLabel, +} from 'src/utils/semanticLayerLabels'; const extensionsRegistry = getExtensionsRegistry(); const DatabaseDeleteRelatedExtension = extensionsRegistry.get( @@ -137,7 +142,7 @@ function DatabaseList({ refreshData: dbRefreshData, } = useListViewResource<DatabaseObject>( 'database', - t('database'), + databaseLabelLower(), addDangerToast, ); @@ -423,7 +428,7 @@ function DatabaseList({ const menuData: SubMenuProps = { activeChild: 'Databases', dropDownLinks: filteredDropDown, - name: t('Databases'), + name: databasesLabel(), }; if (canCreate) { @@ -441,7 +446,7 @@ function DatabaseList({ items: [ { key: 'database', - label: t('Database'), + label: databaseLabel(), onClick: openDatabaseModal, }, { @@ -478,7 +483,7 @@ function DatabaseList({ { 'data-test': 'btn-create-database', icon: <Icons.PlusOutlined iconSize="m" />, - name: t('Database'), + name: databaseLabel(), buttonStyle: 'primary', onClick: openDatabaseModal, }, @@ -499,7 +504,9 @@ function DatabaseList({ }); } catch (error) { setPreparingExport(false); - addDangerToast(t('There was an issue exporting the database')); + addDangerToast( + t('There was an issue exporting the %s', databaseLabelLower()), + ); } }, [addDangerToast, setPreparingExport], @@ -777,7 +784,7 @@ function DatabaseList({ > <Tooltip id="delete-action-tooltip" - title={t('Delete database')} + title={t('Delete %s', databaseLabelLower())} placement="bottom" > <Icons.DeleteOutlined iconSize="l" /> @@ -835,7 +842,7 @@ function DatabaseList({ operator: FilterOperator.Equals, unfilteredLabel: t('All'), selects: [ - { label: t('Database'), value: 'database' }, + { label: databaseLabel(), value: 'database' }, { label: t('Semantic Layer'), value: 'semantic_layer' }, ], }); @@ -887,7 +894,8 @@ function DatabaseList({ 'changed_by', createErrorHandler(errMsg => t( - 'An error occurred while fetching dataset datasource values: %s', + 'An error occurred while fetching %s values: %s', + databaseLabelLower(), errMsg, ), ), @@ -990,7 +998,7 @@ function DatabaseList({ description={ <> <p> - {t('The database')}{' '} + {t('The %s', databaseLabelLower())}{' '} <b>{databaseCurrentlyDeleting.database_name}</b>{' '} {t( 'is linked to %s charts that appear on %s dashboards and users have %s SQL Lab tabs using this database open. Are you sure you want to continue? Deleting the database will break those objects.', @@ -1098,7 +1106,7 @@ function DatabaseList({ title={ <ModalTitleWithIcon icon={<Icons.DeleteOutlined />} - title={t('Delete Database?')} + title={t('Delete %s?', databaseLabel())} /> } /> diff --git a/superset-frontend/src/pages/DatasetList/index.tsx b/superset-frontend/src/pages/DatasetList/index.tsx index 66a1f9662ab..ec5e359cf70 100644 --- a/superset-frontend/src/pages/DatasetList/index.tsx +++ b/superset-frontend/src/pages/DatasetList/index.tsx @@ -78,6 +78,13 @@ import DuplicateDatasetModal from 'src/features/datasets/DuplicateDatasetModal'; import type DatasetType from 'src/types/Dataset'; import SemanticViewEditModal from 'src/features/semanticViews/SemanticViewEditModal'; import AddSemanticViewModal from 'src/features/semanticViews/AddSemanticViewModal'; +import { + datasetLabel, + datasetLabelLower, + datasetsLabel, + datasetsLabelLower, + databaseLabel, +} from 'src/utils/semanticLayerLabels'; import { useSelector } from 'react-redux'; import { QueryObjectColumns } from 'src/views/CRUD/types'; import { WIDER_DROPDOWN_WIDTH } from 'src/components/ListView/utils'; @@ -169,7 +176,11 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ state: { bulkSelectEnabled }, hasPerm, toggleBulkSelect, - } = useListViewResource<Dataset>('dataset', t('dataset'), addDangerToast); + } = useListViewResource<Dataset>( + 'dataset', + datasetLabelLower(), + addDangerToast, + ); // Combined endpoint state const [datasets, setDatasets] = useState<Dataset[]>([]); @@ -236,7 +247,9 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ setDatasetCount(json.count); }) .catch(() => { - addDangerToast(t('An error occurred while fetching datasets')); + addDangerToast( + t('An error occurred while fetching %s', datasetsLabelLower()), + ); }) .finally(() => { setLoading(false); @@ -300,7 +313,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ const handleDatasetImport = () => { showImportModal(false); refreshData(); - addSuccessToast(t('Dataset imported')); + addSuccessToast(t('%s imported', datasetLabel())); }; const canEdit = hasPerm('can_write'); @@ -338,7 +351,10 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ }) .catch(() => { addDangerToast( - t('An error occurred while fetching dataset related data'), + t( + 'An error occurred while fetching %s related data', + datasetLabelLower(), + ), ); }); }, @@ -382,7 +398,12 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ }); } catch (error) { setPreparingExport(false); - addDangerToast(t('There was an issue exporting the selected datasets')); + addDangerToast( + t( + 'There was an issue exporting the selected %s', + datasetsLabelLower(), + ), + ); } }, [addDangerToast, setPreparingExport], @@ -485,7 +506,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ original: { database }, }, }: any) => database?.database_name || '-', - Header: t('Database'), + Header: databaseLabel(), accessor: 'database.database_name', size: 'xl', id: 'database.database_name', @@ -713,7 +734,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ operator: FilterOperator.Equals, unfilteredLabel: t('All'), selects: [ - { label: t('Database'), value: 'database' }, + { label: databaseLabel(), value: 'database' }, { label: t('Semantic Layer'), value: 'semantic_layer' }, ], }, @@ -763,7 +784,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ }, ]), { - Header: t('Database'), + Header: databaseLabel(), key: 'database', id: 'database', input: 'select', @@ -773,7 +794,11 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ 'dataset', 'database', createErrorHandler(errMsg => - t('An error occurred while fetching datasets: %s', errMsg), + t( + 'An error occurred while fetching %s: %s', + datasetsLabelLower(), + errMsg, + ), ), ), paginate: true, @@ -807,7 +832,8 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ 'dataset', createErrorHandler(errMsg => t( - 'An error occurred while fetching dataset owner values: %s', + 'An error occurred while fetching %s owner values: %s', + datasetLabelLower(), errMsg, ), ), @@ -842,7 +868,8 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ 'changed_by', createErrorHandler(errMsg => t( - 'An error occurred while fetching dataset datasource values: %s', + 'An error occurred while fetching %s values: %s', + datasetLabelLower(), errMsg, ), ), @@ -857,7 +884,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ const menuData: SubMenuProps = { activeChild: 'Datasets', - name: t('Datasets'), + name: datasetsLabel(), }; const buttonArr: Array<ButtonProps> = []; @@ -867,7 +894,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ name: ( <Tooltip id="import-tooltip" - title={t('Import datasets')} + title={t('Import %s', datasetsLabelLower())} placement="bottomRight" > <Icons.DownloadOutlined @@ -904,7 +931,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ items: [ { key: 'dataset', - label: t('Dataset'), + label: datasetLabel(), onClick: () => history.push('/dataset/add/'), }, { @@ -936,7 +963,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ } else { buttonArr.push({ icon: <Icons.PlusOutlined iconSize="m" />, - name: t('Dataset'), + name: datasetLabel(), onClick: () => { history.push('/dataset/add/'); }, @@ -1013,7 +1040,11 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ }, createErrorHandler(errMsg => addDangerToast( - t('There was an issue deleting the selected datasets: %s', errMsg), + t( + 'There was an issue deleting the selected %s: %s', + datasetsLabelLower(), + errMsg, + ), ), ), ); @@ -1021,7 +1052,9 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ const handleDatasetDuplicate = (newDatasetName: string) => { if (datasetCurrentlyDuplicating === null) { - addDangerToast(t('There was an issue duplicating the dataset.')); + addDangerToast( + t('There was an issue duplicating the %s.', datasetLabelLower()), + ); } SupersetClient.post({ @@ -1037,7 +1070,11 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ }, createErrorHandler(errMsg => addDangerToast( - t('There was an issue duplicating the selected datasets: %s', errMsg), + t( + 'There was an issue duplicating the selected %s: %s', + datasetsLabelLower(), + errMsg, + ), ), ), ); @@ -1051,7 +1088,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ description={ <> <p> - {t('The dataset')} + {t('The %s', datasetLabelLower())} <b> {datasetCurrentlyDeleting.table_name} </b> {t( 'is linked to %s charts that appear on %s dashboards. Are you sure you want to continue? Deleting the dataset will break those objects.', @@ -1157,7 +1194,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ }} onHide={closeDatasetDeleteModal} open - title={t('Delete Dataset?')} + title={t('Delete %s?', datasetLabel())} /> )} {datasetCurrentlyEditing && ( @@ -1191,7 +1228,8 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ <ConfirmStatusChange title={t('Please confirm')} description={t( - 'Are you sure you want to delete the selected datasets?', + 'Are you sure you want to delete the selected %s?', + datasetsLabelLower(), )} onConfirm={handleBulkDatasetDelete} > @@ -1274,7 +1312,7 @@ const DatasetList: FunctionComponent<DatasetListProps> = ({ <ImportModelsModal resourceName="dataset" - resourceLabel={t('dataset')} + resourceLabel={datasetLabelLower()} passwordsNeededMessage={PASSWORDS_NEEDED_MESSAGE} confirmOverwriteMessage={CONFIRM_OVERWRITE_MESSAGE} addDangerToast={addDangerToast} diff --git a/superset-frontend/src/utils/semanticLayerLabels.ts b/superset-frontend/src/utils/semanticLayerLabels.ts new file mode 100644 index 00000000000..e5ad52b3006 --- /dev/null +++ b/superset-frontend/src/utils/semanticLayerLabels.ts @@ -0,0 +1,63 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +import { isFeatureEnabled, FeatureFlag } from '@superset-ui/core'; +import { t } from '@apache-superset/core/translation'; + +/** + * When the SEMANTIC_LAYERS feature flag is enabled the UI broadens + * "dataset" → "datasource" and "database" → "data connection" so + * that semantic views and semantic layers feel like first-class + * citizens alongside traditional datasets and database connections. + */ +function sl<T>(legacy: T, semantic: T): T { + return isFeatureEnabled(FeatureFlag.SemanticLayers) ? semantic : legacy; +} + +// --------------------------------------------------------------------------- +// "dataset" family +// --------------------------------------------------------------------------- + +/** Capitalized singular: "Dataset" / "Datasource" */ +export const datasetLabel = () => sl(t('Dataset'), t('Datasource')); + +/** Lower-case singular: "dataset" / "datasource" */ +export const datasetLabelLower = () => sl(t('dataset'), t('datasource')); + +/** Capitalized plural: "Datasets" / "Datasources" */ +export const datasetsLabel = () => sl(t('Datasets'), t('Datasources')); + +/** Lower-case plural: "datasets" / "datasources" */ +export const datasetsLabelLower = () => sl(t('datasets'), t('datasources')); + +// --------------------------------------------------------------------------- +// "database" family +// --------------------------------------------------------------------------- + +/** Capitalized singular: "Database" / "Data connection" */ +export const databaseLabel = () => sl(t('Database'), t('Data connection')); + +/** Lower-case singular: "database" / "data connection" */ +export const databaseLabelLower = () => sl(t('database'), t('data connection')); + +/** Capitalized plural: "Databases" / "Data connections" */ +export const databasesLabel = () => sl(t('Databases'), t('Data connections')); + +/** Lower-case plural: "databases" / "data connections" */ +export const databasesLabelLower = () => + sl(t('databases'), t('data connections'));
