You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by ju...@apache.org on 2023/10/13 14:06:03 UTC
[superset] branch sqllab-custom-result-table updated: pr 25569
This is an automated email from the ASF dual-hosted git repository.
justinpark pushed a commit to branch sqllab-custom-result-table
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/sqllab-custom-result-table by this push:
new c19e152a41 pr 25569
c19e152a41 is described below
commit c19e152a41856effef4c95169c824532316c34ab
Author: justinpark <ju...@gmail.com>
AuthorDate: Fri Oct 13 10:05:46 2023 -0400
pr 25569
---
.../FiltersConfigForm/DatasetLabel.tsx | 116 +++++++++++++++++++++
.../FiltersConfigForm/DatasetSelect.tsx | 37 +++++--
.../FiltersConfigForm/FiltersConfigForm.tsx | 3 +-
.../FiltersConfigModal/FiltersConfigForm/utils.ts | 12 ---
.../src/pages/ChartCreation/index.tsx | 86 +++++++++++----
5 files changed, 213 insertions(+), 41 deletions(-)
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetLabel.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetLabel.tsx
new file mode 100644
index 0000000000..fed323881d
--- /dev/null
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetLabel.tsx
@@ -0,0 +1,116 @@
+/**
+ * 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 React from 'react';
+import { Tooltip } from 'src/components/Tooltip';
+import { styled } from '@superset-ui/core';
+
+type Database = {
+ database_name: string;
+};
+
+type Dataset = {
+ id: number;
+ table_name: string;
+ schema: string;
+ database: Database;
+};
+
+const TooltipContent = styled.div`
+ ${({ theme }) => `
+ .tooltip-header {
+ font-size: ${theme.typography.sizes.m}px;
+ font-weight: ${theme.typography.weights.bold};
+ }
+
+ .tooltip-description {
+ margin-top: ${theme.gridUnit * 2}px;
+ display: -webkit-box;
+ -webkit-line-clamp: 20;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ `}
+`;
+
+const StyledLabel = styled.span`
+ ${({ theme }) => `
+ left: ${theme.gridUnit * 3}px;
+ right: ${theme.gridUnit * 3}px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: block;
+ `}
+`;
+
+const StyledLabelDetail = styled.span`
+ ${({
+ theme: {
+ typography: { sizes, weights },
+ },
+ }) => `
+ overflow: hidden;
+ display: inline-block;
+ text-overflow: ellipsis;
+ font-size: ${sizes.s}px;
+ font-weight: ${weights.light};
+ max-width: 50%;
+ line-height: 1.4;
+ `}
+`;
+
+const StyledLabelContainer = styled.div`
+ ${({ theme }) => `
+ left: ${theme.gridUnit * 3}px;
+ right: ${theme.gridUnit * 3}px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: block;
+ `}
+`;
+
+export const newLabel = (item: Dataset | Record<string, any>) => (
+ <Tooltip
+ mouseEnterDelay={1}
+ placement="right"
+ title={
+ <TooltipContent>
+ <div className="tooltip-header">{item.table_name}</div>
+ <div className="tooltip-description">
+ <div>Database: {item.database.database_name}</div>
+ <div>
+ Schema:{' '}
+ {item.schema &&
+ !['null', 'none'].includes(item.schema.toLowerCase())
+ ? item.schema
+ : 'Not defined'}
+ </div>
+ </div>
+ </TooltipContent>
+ }
+ >
+ <StyledLabelContainer>
+ <StyledLabel>{item.table_name}</StyledLabel>
+ <StyledLabelDetail>{item.database.database_name}</StyledLabelDetail>
+ {item.schema && !['null', 'none'].includes(item.schema.toLowerCase()) && (
+ <StyledLabelDetail> - {item.schema}</StyledLabelDetail>
+ )}
+ </StyledLabelContainer>
+ </Tooltip>
+);
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetSelect.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetSelect.tsx
index e5e62b008e..c478b5eba5 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetSelect.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/DatasetSelect.tsx
@@ -16,16 +16,27 @@
* specific language governing permissions and limitations
* under the License.
*/
-import React, { useCallback, useMemo } from 'react';
+import React, { useCallback, useMemo, ReactNode } from 'react';
import rison from 'rison';
-import { t } from '@superset-ui/core';
+import { t, JsonResponse } from '@superset-ui/core';
import { AsyncSelect } from 'src/components';
import {
ClientErrorObject,
getClientErrorObject,
} from 'src/utils/getClientErrorObject';
import { cachedSupersetGet } from 'src/utils/cachedSupersetGet';
-import { datasetToSelectOption } from './utils';
+import { newLabel } from './DatasetLabel';
+
+type Database = {
+ database_name: string;
+};
+
+type Dataset = {
+ id: number;
+ table_name: string;
+ schema: string;
+ database: Database;
+};
interface DatasetSelectProps {
onChange: (value: { label: string; value: number }) => void;
@@ -49,24 +60,29 @@ const DatasetSelect = ({ onChange, value }: DatasetSelectProps) => {
page: number,
pageSize: number,
) => {
- const searchColumn = 'table_name';
const query = rison.encode({
- filters: [{ col: searchColumn, opr: 'ct', value: search }],
+ columns: ['id', 'table_name', 'database.database_name', 'schema'],
+ filters: [{ col: 'table_name', opr: 'ct', value: search }],
page,
page_size: pageSize,
- order_column: searchColumn,
+ order_column: 'table_name',
order_direction: 'asc',
});
return cachedSupersetGet({
endpoint: `/api/v1/dataset/?q=${query}`,
})
- .then(response => {
- const data: {
+ .then((response: JsonResponse) => {
+ const list: {
+ customLabel: ReactNode;
label: string;
value: string | number;
- }[] = response.json.result.map(datasetToSelectOption);
+ }[] = response.json.result.map((item: Dataset) => ({
+ customLabel: newLabel(item),
+ label: item.table_name,
+ value: item.id,
+ }));
return {
- data,
+ data: list,
totalCount: response.json.count,
};
})
@@ -83,6 +99,7 @@ const DatasetSelect = ({ onChange, value }: DatasetSelectProps) => {
options={loadDatasetOptions}
onChange={onChange}
notFoundContent={t('No compatible datasets found')}
+ placeholder={t('Select a dataset')}
/>
);
};
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
index 94b336af92..ac75896d69 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/FiltersConfigForm.tsx
@@ -103,6 +103,7 @@ import {
} from './utils';
import { FILTER_SUPPORTED_TYPES, INPUT_WIDTH } from './constants';
import DependencyList from './DependencyList';
+import { newLabel } from './DatasetLabel';
const TabPane = styled(Tabs.TabPane)`
padding: ${({ theme }) => theme.gridUnit * 4}px 0px;
@@ -883,7 +884,7 @@ const FiltersConfigForm = (
initialValue={
datasetDetails
? {
- label: datasetDetails.table_name,
+ label: newLabel(datasetDetails),
value: datasetDetails.id,
}
: undefined
diff --git a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils.ts b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils.ts
index 92185039d8..b7aa2cab39 100644
--- a/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils.ts
+++ b/superset-frontend/src/dashboard/components/nativeFilters/FiltersConfigModal/FiltersConfigForm/utils.ts
@@ -66,18 +66,6 @@ export const getControlItems = (
[],
) as CustomControlItem[]) ?? [];
-type DatasetSelectValue = {
- value: number;
- label: string;
-};
-
-export const datasetToSelectOption = (
- item: Dataset & { table_name: string },
-): DatasetSelectValue => ({
- value: item.id,
- label: item.table_name,
-});
-
// TODO: add column_types field to Dataset
// We return true if column_types is undefined or empty as a precaution against backend failing to return column_types
export const hasTemporalColumns = (
diff --git a/superset-frontend/src/pages/ChartCreation/index.tsx b/superset-frontend/src/pages/ChartCreation/index.tsx
index c09172e99d..9a7917c65c 100644
--- a/superset-frontend/src/pages/ChartCreation/index.tsx
+++ b/superset-frontend/src/pages/ChartCreation/index.tsx
@@ -43,11 +43,16 @@ import { findPermission } from 'src/utils/findPermission';
import { UserWithPermissionsAndRoles } from 'src/types/bootstrapTypes';
import getBootstrapData from 'src/utils/getBootstrapData';
+type Database = {
+ database_name: string;
+};
+
type Dataset = {
id: number;
table_name: string;
- description: string;
datasource_type: string;
+ schema: string;
+ database: Database;
};
export interface ChartCreationProps extends RouteComponentProps {
@@ -169,20 +174,18 @@ const StyledContainer = styled.div`
&&&& .ant-select-selection-placeholder {
padding-left: ${theme.gridUnit * 3}px;
}
+
+ &&&& .ant-select-selection-item {
+ padding-left: ${theme.gridUnit * 3}px;
+ }
`}
`;
-const TooltipContent = styled.div<{ hasDescription: boolean }>`
- ${({ theme, hasDescription }) => `
+const TooltipContent = styled.div`
+ ${({ theme }) => `
.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
- };
+ font-size: ${theme.typography.sizes.m}px;
+ font-weight: ${theme.typography.weights.bold};
}
.tooltip-description {
@@ -198,7 +201,32 @@ const TooltipContent = styled.div<{ hasDescription: boolean }>`
const StyledLabel = styled.span`
${({ theme }) => `
- position: absolute;
+ display: block;
+ left: ${theme.gridUnit * 3}px;
+ right: ${theme.gridUnit * 3}px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ line-height: 1.4;
+ `}
+`;
+
+const StyledLabelDetail = styled.span`
+ ${({
+ theme: {
+ typography: { sizes, weights },
+ },
+ }) => `
+ overflow: hidden;
+ display: inline-block;
+ text-overflow: ellipsis;
+ font-size: ${sizes.s}px;
+ font-weight: ${weights.light};
+ max-width: 50%;
+ `}
+`;
+
+const StyledLabelContainer = styled.div`
+ ${({ theme }) => `
left: ${theme.gridUnit * 3}px;
right: ${theme.gridUnit * 3}px;
overflow: hidden;
@@ -299,22 +327,44 @@ export class ChartCreation extends React.PureComponent<
mouseEnterDelay={1}
placement="right"
title={
- <TooltipContent hasDescription={!!item.description}>
+ <TooltipContent>
<div className="tooltip-header">{item.table_name}</div>
- {item.description && (
- <div className="tooltip-description">{item.description}</div>
- )}
+ <div className="tooltip-description">
+ <div>Database: {item.database.database_name}</div>
+ <div>
+ Schema:{' '}
+ {item.schema &&
+ !['null', 'none'].includes(item.schema.toLowerCase())
+ ? item.schema
+ : 'Not defined'}
+ </div>
+ </div>
</TooltipContent>
}
>
- <StyledLabel>{item.table_name}</StyledLabel>
+ <StyledLabelContainer>
+ <StyledLabel>{item.table_name}</StyledLabel>
+ <StyledLabel>
+ <StyledLabelDetail>{item.database.database_name}</StyledLabelDetail>
+ {item.schema &&
+ !['null', 'none'].includes(item.schema.toLowerCase()) && (
+ <StyledLabelDetail> - {item.schema}</StyledLabelDetail>
+ )}
+ </StyledLabel>
+ </StyledLabelContainer>
</Tooltip>
);
}
loadDatasources(search: string, page: number, pageSize: number) {
const query = rison.encode({
- columns: ['id', 'table_name', 'description', 'datasource_type'],
+ columns: [
+ 'id',
+ 'table_name',
+ 'datasource_type',
+ 'database.database_name',
+ 'schema',
+ ],
filters: [{ col: 'table_name', opr: 'ct', value: search }],
page,
page_size: pageSize,