diff --git a/superset-frontend/src/addSlice/AddSliceContainer.test.tsx b/superset-frontend/src/addSlice/AddSliceContainer.test.tsx
index 2174a6b758ab9..00e7276a5864c 100644
--- a/superset-frontend/src/addSlice/AddSliceContainer.test.tsx
+++ b/superset-frontend/src/addSlice/AddSliceContainer.test.tsx
@@ -28,11 +28,9 @@ import VizTypeGallery from 'src/explore/components/controls/VizTypeControl/VizTy
import { styledMount as mount } from 'spec/helpers/theming';
import { act } from 'spec/helpers/testing-library';
-const defaultProps = {
- datasources: [
- { label: 'my first table', value: '1__table' },
- { label: 'another great table', value: '2__table' },
- ],
+const datasource = {
+ value: '1',
+ label: 'table',
};
describe('AddSliceContainer', () => {
@@ -43,7 +41,7 @@ describe('AddSliceContainer', () => {
>;
beforeEach(async () => {
- wrapper = mount() as ReactWrapper<
+ wrapper = mount() as ReactWrapper<
AddSliceContainerProps,
AddSliceContainerState,
AddSliceContainer
@@ -68,11 +66,8 @@ describe('AddSliceContainer', () => {
});
it('renders an enabled button if datasource and viz type is selected', () => {
- const datasourceValue = defaultProps.datasources[0].value;
wrapper.setState({
- datasourceValue,
- datasourceId: datasourceValue.split('__')[0],
- datasourceType: datasourceValue.split('__')[1],
+ datasource,
visType: 'table',
});
expect(
@@ -81,15 +76,12 @@ describe('AddSliceContainer', () => {
});
it('formats explore url', () => {
- const datasourceValue = defaultProps.datasources[0].value;
wrapper.setState({
- datasourceValue,
- datasourceId: datasourceValue.split('__')[0],
- datasourceType: datasourceValue.split('__')[1],
+ datasource,
visType: 'table',
});
const formattedUrl =
- '/superset/explore/?form_data=%7B%22viz_type%22%3A%22table%22%2C%22datasource%22%3A%221__table%22%7D';
+ '/superset/explore/?form_data=%7B%22viz_type%22%3A%22table%22%2C%22datasource%22%3A%221%22%7D';
expect(wrapper.instance().exploreUrl()).toBe(formattedUrl);
});
});
diff --git a/superset-frontend/src/addSlice/AddSliceContainer.tsx b/superset-frontend/src/addSlice/AddSliceContainer.tsx
index b06ceef2df69e..0198ab01c8729 100644
--- a/superset-frontend/src/addSlice/AddSliceContainer.tsx
+++ b/superset-frontend/src/addSlice/AddSliceContainer.tsx
@@ -17,28 +17,34 @@
* under the License.
*/
import React from 'react';
+import rison from 'rison';
import Button from 'src/components/Button';
import { Select } from 'src/components';
-import { css, styled, t } from '@superset-ui/core';
+import {
+ css,
+ styled,
+ t,
+ SupersetClient,
+ JsonResponse,
+} from '@superset-ui/core';
import { FormLabel } from 'src/components/Form';
+import { Tooltip } from 'src/components/Tooltip';
import VizTypeGallery, {
MAX_ADVISABLE_VIZ_GALLERY_WIDTH,
} from 'src/explore/components/controls/VizTypeControl/VizTypeGallery';
-interface Datasource {
- label: string;
- value: string;
-}
-
-export type AddSliceContainerProps = {
- datasources: Datasource[];
+type Dataset = {
+ id: number;
+ table_name: string;
+ description: string;
+ datasource_type: string;
};
+export type AddSliceContainerProps = {};
+
export type AddSliceContainerState = {
- datasourceId?: string;
- datasourceType?: string;
- datasourceValue?: string;
+ datasource?: { label: string; value: string };
visType: string | null;
};
@@ -81,6 +87,34 @@ const StyledContainer = styled.div`
margin-top: ${theme.gridUnit * 6}px;
}
}
+
+ & .ant-tooltip-open {
+ display: inline;
+ }
+ `}
+`;
+
+const TooltipContent = styled.div<{ hasDescription: boolean }>`
+ ${({ theme, hasDescription }) => `
+ .tooltip-header {
+ font-size: ${
+ hasDescription ? theme.typography.sizes.l : theme.typography.sizes.s
+ }px;
+ font-weight: ${
+ hasDescription
+ ? theme.typography.weights.bold
+ : theme.typography.weights.normal
+ };
+ }
+
+ .tooltip-description {
+ margin-top: ${theme.gridUnit * 2}px;
+ display: -webkit-box;
+ -webkit-line-clamp: 20;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
`}
`;
@@ -110,13 +144,15 @@ export default class AddSliceContainer extends React.PureComponent<
this.changeDatasource = this.changeDatasource.bind(this);
this.changeVisType = this.changeVisType.bind(this);
this.gotoSlice = this.gotoSlice.bind(this);
+ this.newLabel = this.newLabel.bind(this);
+ this.loadDatasources = this.loadDatasources.bind(this);
}
exploreUrl() {
const formData = encodeURIComponent(
JSON.stringify({
viz_type: this.state.visType,
- datasource: this.state.datasourceValue,
+ datasource: this.state.datasource?.value,
}),
);
return `/superset/explore/?form_data=${formData}`;
@@ -126,11 +162,8 @@ export default class AddSliceContainer extends React.PureComponent<
window.location.href = this.exploreUrl();
}
- changeDatasource(value: string) {
- this.setState({
- datasourceValue: value,
- datasourceId: value.split('__')[0],
- });
+ changeDatasource(datasource: { label: string; value: string }) {
+ this.setState({ datasource });
}
changeVisType(visType: string | null) {
@@ -138,7 +171,45 @@ export default class AddSliceContainer extends React.PureComponent<
}
isBtnDisabled() {
- return !(this.state.datasourceId && this.state.visType);
+ return !(this.state.datasource?.value && this.state.visType);
+ }
+
+ newLabel(item: Dataset) {
+ return (
+
+ {item.table_name}
+ {item.description && (
+ {item.description}
+ )}
+
+ }
+ >
+ {item.table_name}
+
+ );
+ }
+
+ loadDatasources(search: string, page: number, pageSize: number) {
+ const query = rison.encode({
+ columns: ['id', 'table_name', 'description', 'datasource_type'],
+ filter: search,
+ page,
+ page_size: pageSize,
+ });
+ return SupersetClient.get({
+ endpoint: `/api/v1/dataset?q=${query}`,
+ }).then((response: JsonResponse) => {
+ const list = response.json.result.map((item: Dataset) => ({
+ value: `${item.id}__${item.datasource_type}`,
+ label: this.newLabel(item),
+ }));
+ return {
+ data: list,
+ totalCount: response.json.count,
+ };
+ });
}
render() {
@@ -152,10 +223,10 @@ export default class AddSliceContainer extends React.PureComponent<
name="select-datasource"
header={{t('Choose a dataset')}}
onChange={this.changeDatasource}
- options={this.props.datasources}
+ options={this.loadDatasources}
placeholder={t('Choose a dataset')}
showSearch
- value={this.state.datasourceValue}
+ value={this.state.datasource}
/>
{t(
diff --git a/superset-frontend/src/addSlice/App.tsx b/superset-frontend/src/addSlice/App.tsx
index 9602670a08902..900cc36f446c8 100644
--- a/superset-frontend/src/addSlice/App.tsx
+++ b/superset-frontend/src/addSlice/App.tsx
@@ -39,7 +39,7 @@ initFeatureFlags(bootstrapData.common.feature_flags);
const App = () => (
-
+
);
diff --git a/superset/datasets/api.py b/superset/datasets/api.py
index 405f985493523..35d09448a397e 100644
--- a/superset/datasets/api.py
+++ b/superset/datasets/api.py
@@ -100,6 +100,8 @@ class DatasetRestApi(BaseSupersetModelRestApi):
"changed_on_utc",
"changed_on_delta_humanized",
"default_endpoint",
+ "description",
+ "datasource_type",
"explore_url",
"extra",
"kind",
diff --git a/tests/integration_tests/datasets/api_tests.py b/tests/integration_tests/datasets/api_tests.py
index 5275a87173030..385025e3835cc 100644
--- a/tests/integration_tests/datasets/api_tests.py
+++ b/tests/integration_tests/datasets/api_tests.py
@@ -179,7 +179,9 @@ def test_get_dataset_list(self):
"changed_on_delta_humanized",
"changed_on_utc",
"database",
+ "datasource_type",
"default_endpoint",
+ "description",
"explore_url",
"extra",
"id",