You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by be...@apache.org on 2026/02/17 16:06:51 UTC
(superset) 01/07: Add button
This is an automated email from the ASF dual-hosted git repository.
beto pushed a commit to branch semantic-layer-ui-semantic-layer
in repository https://gitbox.apache.org/repos/asf/superset.git
commit bd8aca85ce502998d75954bb430d8182e19fed81
Author: Beto Dealmeida <ro...@dealmeida.net>
AuthorDate: Fri Feb 13 10:23:36 2026 -0500
Add button
---
superset-frontend/src/features/home/SubMenu.tsx | 29 ++++----
superset-frontend/src/pages/DatabaseList/index.tsx | 83 ++++++++++++++++++----
superset/static/service-worker.js | 2 +-
3 files changed, 88 insertions(+), 26 deletions(-)
diff --git a/superset-frontend/src/features/home/SubMenu.tsx b/superset-frontend/src/features/home/SubMenu.tsx
index 107700a2539..bb27cc95a76 100644
--- a/superset-frontend/src/features/home/SubMenu.tsx
+++ b/superset-frontend/src/features/home/SubMenu.tsx
@@ -145,6 +145,7 @@ export interface ButtonProps {
buttonStyle: 'primary' | 'secondary' | 'dashed' | 'link' | 'tertiary';
loading?: boolean;
icon?: IconType;
+ component?: ReactNode;
}
export interface SubMenuProps {
@@ -295,18 +296,22 @@ const SubMenuComponent: FunctionComponent<SubMenuProps> = props => {
</SubMenu>
))}
</Menu>
- {props.buttons?.map((btn, i) => (
- <Button
- key={i}
- buttonStyle={btn.buttonStyle}
- icon={btn.icon}
- onClick={btn.onClick}
- data-test={btn['data-test']}
- loading={btn.loading ?? false}
- >
- {btn.name}
- </Button>
- ))}
+ {props.buttons?.map((btn, i) =>
+ btn.component ? (
+ <span key={i}>{btn.component}</span>
+ ) : (
+ <Button
+ key={i}
+ buttonStyle={btn.buttonStyle}
+ icon={btn.icon}
+ onClick={btn.onClick}
+ data-test={btn['data-test']}
+ loading={btn.loading ?? false}
+ >
+ {btn.name}
+ </Button>
+ ),
+ )}
</div>
</Row>
{props.children}
diff --git a/superset-frontend/src/pages/DatabaseList/index.tsx b/superset-frontend/src/pages/DatabaseList/index.tsx
index 84baa209bbe..521cdb1a8ae 100644
--- a/superset-frontend/src/pages/DatabaseList/index.tsx
+++ b/superset-frontend/src/pages/DatabaseList/index.tsx
@@ -17,8 +17,13 @@
* under the License.
*/
import { t } from '@apache-superset/core';
-import { getExtensionsRegistry, SupersetClient } from '@superset-ui/core';
-import { styled } from '@apache-superset/core/ui';
+import {
+ getExtensionsRegistry,
+ SupersetClient,
+ isFeatureEnabled,
+ FeatureFlag,
+} from '@superset-ui/core';
+import { styled, useTheme } from '@apache-superset/core/ui';
import { useState, useMemo, useEffect } from 'react';
import rison from 'rison';
import { useSelector } from 'react-redux';
@@ -34,6 +39,8 @@ import withToasts from 'src/components/MessageToasts/withToasts';
import SubMenu, { SubMenuProps } from 'src/features/home/SubMenu';
import {
DeleteModal,
+ DropdownButton,
+ Menu,
Tooltip,
List,
Loading,
@@ -108,6 +115,7 @@ function DatabaseList({
addSuccessToast,
user,
}: DatabaseListProps) {
+ const theme = useTheme();
const {
state: {
loading,
@@ -314,18 +322,67 @@ function DatabaseList({
};
if (canCreate) {
- menuData.buttons = [
- {
- 'data-test': 'btn-create-database',
- icon: <Icons.PlusOutlined iconSize="m" />,
- name: t('Database'),
- buttonStyle: 'primary',
- onClick: () => {
- // Ensure modal will be opened in add mode
- handleDatabaseEditModal({ modalOpen: true });
+ const openDatabaseModal = () =>
+ handleDatabaseEditModal({ modalOpen: true });
+
+ if (isFeatureEnabled(FeatureFlag.SemanticLayers)) {
+ const dropdownMenu = (
+ <Menu
+ items={[
+ {
+ key: 'database',
+ label: t('Database'),
+ onClick: openDatabaseModal,
+ },
+ {
+ key: 'semantic-layer',
+ label: t('Semantic Layer'),
+ onClick: () => {
+ // TODO: open semantic layer creation flow
+ },
+ },
+ ]}
+ />
+ );
+
+ menuData.buttons = [
+ {
+ name: t('New'),
+ buttonStyle: 'primary',
+ component: (
+ <DropdownButton
+ data-test="btn-create-new"
+ type="primary"
+ onClick={openDatabaseModal}
+ popupRender={() => dropdownMenu}
+ icon={
+ <Icons.DownOutlined
+ iconSize="xs"
+ iconColor={theme.colorTextLightSolid}
+ />
+ }
+ trigger={['click']}
+ >
+ <Icons.PlusOutlined
+ iconSize="m"
+ iconColor={theme.colorTextLightSolid}
+ />
+ {t('New')}
+ </DropdownButton>
+ ),
},
- },
- ];
+ ];
+ } else {
+ menuData.buttons = [
+ {
+ 'data-test': 'btn-create-database',
+ icon: <Icons.PlusOutlined iconSize="m" />,
+ name: t('Database'),
+ buttonStyle: 'primary',
+ onClick: openDatabaseModal,
+ },
+ ];
+ }
}
async function handleDatabaseExport(database: DatabaseObject) {
diff --git a/superset/static/service-worker.js b/superset/static/service-worker.js
index 85638a05975..41dd89372f5 100644
--- a/superset/static/service-worker.js
+++ b/superset/static/service-worker.js
@@ -170,7 +170,7 @@ eval("{/**\n * Licensed to the Apache Software Foundation (ASF) under one\n * or
/******/
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
-/******/ __webpack_require__.h = () => ("87e83073d75b3c4295d1")
+/******/ __webpack_require__.h = () => ("75932d3bc95431510a61")
/******/ })();
/******/
/******/ /* webpack/runtime/harmony module decorator */