mirror of
https://github.com/apache/superset.git
synced 2026-05-03 15:04:28 +00:00
Compare commits
3 Commits
fix/postgr
...
dataset-mo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ddd08b5fe7 | ||
|
|
63901941ff | ||
|
|
42f1af87bf |
@@ -65,10 +65,6 @@ const StyledDatasourceModal = styled(Modal)`
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-tabs-top {
|
|
||||||
margin-top: -${({ theme }) => theme.sizeUnit * 4}px;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
function buildExtraJsonObject(
|
function buildExtraJsonObject(
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ import {
|
|||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
const CrudButtonWrapper = styled.div`
|
const CrudButtonWrapper = styled.div`
|
||||||
text-align: right;
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
${({ theme }) => `margin-bottom: ${theme.sizeUnit * 2}px`}
|
${({ theme }) => `margin-bottom: ${theme.sizeUnit * 2}px`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@@ -466,24 +468,27 @@ export default class CRUDCollection extends PureComponent<
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<CrudButtonWrapper>
|
{(this.props.toolbarExtra || this.props.allowAddItem) && (
|
||||||
{this.props.allowAddItem && (
|
<CrudButtonWrapper>
|
||||||
<StyledButtonWrapper>
|
{this.props.toolbarExtra}
|
||||||
<Button
|
{this.props.allowAddItem && (
|
||||||
buttonSize="small"
|
<StyledButtonWrapper>
|
||||||
buttonStyle="secondary"
|
<Button
|
||||||
onClick={this.onAddItem}
|
buttonSize="small"
|
||||||
data-test="add-item-button"
|
buttonStyle="secondary"
|
||||||
>
|
onClick={this.onAddItem}
|
||||||
<Icons.PlusOutlined
|
data-test="add-item-button"
|
||||||
iconSize="m"
|
>
|
||||||
data-test="crud-add-table-item"
|
<Icons.PlusOutlined
|
||||||
/>
|
iconSize="m"
|
||||||
{t('Add item')}
|
data-test="crud-add-table-item"
|
||||||
</Button>
|
/>
|
||||||
</StyledButtonWrapper>
|
{t('Add item')}
|
||||||
)}
|
</Button>
|
||||||
</CrudButtonWrapper>
|
</StyledButtonWrapper>
|
||||||
|
)}
|
||||||
|
</CrudButtonWrapper>
|
||||||
|
)}
|
||||||
<Table<CollectionItem>
|
<Table<CollectionItem>
|
||||||
data-test="crud-table"
|
data-test="crud-table"
|
||||||
columns={tableColumns}
|
columns={tableColumns}
|
||||||
|
|||||||
@@ -311,6 +311,7 @@ interface ColumnCollectionTableProps {
|
|||||||
columnLabelTooltips?: Record<string, string>;
|
columnLabelTooltips?: Record<string, string>;
|
||||||
filterTerm?: string;
|
filterTerm?: string;
|
||||||
filterFields?: string[];
|
filterFields?: string[];
|
||||||
|
toolbarExtra?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface StackedFieldProps {
|
interface StackedFieldProps {
|
||||||
@@ -399,11 +400,6 @@ const EditLockContainer = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const ColumnButtonWrapper = styled.div`
|
|
||||||
text-align: right;
|
|
||||||
${({ theme }) => `margin-bottom: ${theme.sizeUnit * 2}px`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const StyledLabelWrapper = styled.div`
|
const StyledLabelWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -447,16 +443,6 @@ const FieldLabelWithTooltip = styled.div`
|
|||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledButtonWrapper = styled.span`
|
|
||||||
${({ theme }) => `
|
|
||||||
margin-top: ${theme.sizeUnit * 3}px;
|
|
||||||
margin-left: ${theme.sizeUnit * 3}px;
|
|
||||||
button>span>:first-of-type {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const checkboxGenerator = (
|
const checkboxGenerator = (
|
||||||
d: boolean,
|
d: boolean,
|
||||||
onChange: (value: boolean) => void,
|
onChange: (value: boolean) => void,
|
||||||
@@ -532,6 +518,7 @@ function ColumnCollectionTable({
|
|||||||
columnLabelTooltips,
|
columnLabelTooltips,
|
||||||
filterTerm,
|
filterTerm,
|
||||||
filterFields,
|
filterFields,
|
||||||
|
toolbarExtra,
|
||||||
}: ColumnCollectionTableProps): JSX.Element {
|
}: ColumnCollectionTableProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<CollectionTable
|
<CollectionTable
|
||||||
@@ -566,6 +553,7 @@ function ColumnCollectionTable({
|
|||||||
columnLabelTooltips={columnLabelTooltips}
|
columnLabelTooltips={columnLabelTooltips}
|
||||||
filterTerm={filterTerm}
|
filterTerm={filterTerm}
|
||||||
filterFields={filterFields}
|
filterFields={filterFields}
|
||||||
|
toolbarExtra={toolbarExtra}
|
||||||
stickyHeader
|
stickyHeader
|
||||||
expandFieldset={
|
expandFieldset={
|
||||||
<FormContainer>
|
<FormContainer>
|
||||||
@@ -1835,6 +1823,7 @@ class DatasourceEditor extends PureComponent<
|
|||||||
<div
|
<div
|
||||||
css={theme => css`
|
css={theme => css`
|
||||||
margin-top: ${theme.sizeUnit * 3}px;
|
margin-top: ${theme.sizeUnit * 3}px;
|
||||||
|
margin-bottom: ${theme.sizeUnit * 2}px;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: ${theme.sizeUnit * 4}px;
|
gap: ${theme.sizeUnit * 4}px;
|
||||||
`}
|
`}
|
||||||
@@ -1854,7 +1843,13 @@ class DatasourceEditor extends PureComponent<
|
|||||||
<Divider />
|
<Divider />
|
||||||
<Fieldset item={datasource} onChange={this.onDatasourceChange} compact>
|
<Fieldset item={datasource} onChange={this.onDatasourceChange} compact>
|
||||||
{this.state.datasourceType === DATASOURCE_TYPES.virtual.key && (
|
{this.state.datasourceType === DATASOURCE_TYPES.virtual.key && (
|
||||||
<div>
|
<div
|
||||||
|
css={css`
|
||||||
|
.ant-form-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
{this.state.isSqla && (
|
{this.state.isSqla && (
|
||||||
<>
|
<>
|
||||||
<Col xs={24} md={12}>
|
<Col xs={24} md={12}>
|
||||||
@@ -1897,22 +1892,20 @@ class DatasourceEditor extends PureComponent<
|
|||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<div css={{ width: 'calc(100% - 34px)', marginTop: -16 }}>
|
<Field
|
||||||
<Field
|
fieldKey="table_name"
|
||||||
fieldKey="table_name"
|
label={t('Name')}
|
||||||
label={t('Name')}
|
control={
|
||||||
control={
|
<TextControl
|
||||||
<TextControl
|
controlId="table_name"
|
||||||
controlId="table_name"
|
onChange={table => {
|
||||||
onChange={table => {
|
this.onDatasourcePropChange('table_name', table);
|
||||||
this.onDatasourcePropChange('table_name', table);
|
}}
|
||||||
}}
|
placeholder={t('Dataset name')}
|
||||||
placeholder={t('Dataset name')}
|
disabled={!this.state.isEditMode}
|
||||||
disabled={!this.state.isEditMode}
|
/>
|
||||||
/>
|
}
|
||||||
}
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Col>
|
</Col>
|
||||||
<Field
|
<Field
|
||||||
fieldKey="sql"
|
fieldKey="sql"
|
||||||
@@ -2053,7 +2046,15 @@ class DatasourceEditor extends PureComponent<
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{this.state.datasourceType === DATASOURCE_TYPES.physical.key && (
|
{this.state.datasourceType === DATASOURCE_TYPES.physical.key && (
|
||||||
<Col xs={24} md={12}>
|
<Col
|
||||||
|
xs={24}
|
||||||
|
md={12}
|
||||||
|
css={css`
|
||||||
|
.ant-form-item:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
>
|
||||||
{this.state.isSqla && (
|
{this.state.isSqla && (
|
||||||
<Field
|
<Field
|
||||||
fieldKey="tableSelector"
|
fieldKey="tableSelector"
|
||||||
@@ -2148,18 +2149,24 @@ class DatasourceEditor extends PureComponent<
|
|||||||
const sortedMetrics = metrics?.length ? this.sortMetrics(metrics) : [];
|
const sortedMetrics = metrics?.length ? this.sortMetrics(metrics) : [];
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Input.Search
|
|
||||||
placeholder={t('Search metrics by key or label')}
|
|
||||||
value={metricSearchTerm}
|
|
||||||
onChange={e => this.setState({ metricSearchTerm: e.target.value })}
|
|
||||||
style={{ marginBottom: 16, width: 300 }}
|
|
||||||
allowClear
|
|
||||||
/>
|
|
||||||
<CollectionTable
|
<CollectionTable
|
||||||
tableColumns={['metric_name', 'verbose_name', 'expression']}
|
tableColumns={['metric_name', 'verbose_name', 'expression']}
|
||||||
sortColumns={['metric_name', 'verbose_name', 'expression']}
|
sortColumns={['metric_name', 'verbose_name', 'expression']}
|
||||||
filterTerm={metricSearchTerm}
|
filterTerm={metricSearchTerm}
|
||||||
filterFields={['metric_name', 'verbose_name']}
|
filterFields={['metric_name', 'verbose_name']}
|
||||||
|
toolbarExtra={
|
||||||
|
<Input.Search
|
||||||
|
placeholder={t('Search metrics by key or label')}
|
||||||
|
value={metricSearchTerm}
|
||||||
|
onChange={e =>
|
||||||
|
this.setState({ metricSearchTerm: e.target.value })
|
||||||
|
}
|
||||||
|
css={theme => ({
|
||||||
|
width: theme.sizeUnit * 75,
|
||||||
|
})}
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
}
|
||||||
columnLabels={{
|
columnLabels={{
|
||||||
metric_name: t('Metric Key'),
|
metric_name: t('Metric Key'),
|
||||||
verbose_name: t('Label'),
|
verbose_name: t('Label'),
|
||||||
@@ -2336,11 +2343,10 @@ class DatasourceEditor extends PureComponent<
|
|||||||
<DatasourceContainer data-test="datasource-editor">
|
<DatasourceContainer data-test="datasource-editor">
|
||||||
{this.renderErrors()}
|
{this.renderErrors()}
|
||||||
<Alert
|
<Alert
|
||||||
css={theme => ({ marginBottom: theme.sizeUnit * 4 })}
|
css={theme => ({ marginBottom: theme.sizeUnit * 2 })}
|
||||||
type="warning"
|
type="warning"
|
||||||
message={
|
message={
|
||||||
<>
|
<>
|
||||||
{' '}
|
|
||||||
<strong>{t('Be careful.')} </strong>
|
<strong>{t('Be careful.')} </strong>
|
||||||
{t(
|
{t(
|
||||||
'Changing these settings will affect all charts using this dataset, including charts owned by other people.',
|
'Changing these settings will affect all charts using this dataset, including charts owned by other people.',
|
||||||
@@ -2380,29 +2386,35 @@ class DatasourceEditor extends PureComponent<
|
|||||||
children: (
|
children: (
|
||||||
<StyledTableTabWrapper>
|
<StyledTableTabWrapper>
|
||||||
{this.renderDefaultColumnSettings()}
|
{this.renderDefaultColumnSettings()}
|
||||||
<ColumnButtonWrapper>
|
<Flex
|
||||||
<StyledButtonWrapper>
|
justify="space-between"
|
||||||
<Button
|
align="center"
|
||||||
buttonSize="small"
|
css={theme => ({
|
||||||
buttonStyle="tertiary"
|
marginBottom: theme.sizeUnit * 4,
|
||||||
onClick={this.syncMetadata}
|
})}
|
||||||
className="sync-from-source"
|
>
|
||||||
disabled={this.state.isEditMode}
|
<Input.Search
|
||||||
>
|
placeholder={t('Search columns by name')}
|
||||||
<Icons.DatabaseOutlined iconSize="m" />
|
value={this.state.columnSearchTerm}
|
||||||
{t('Sync columns from source')}
|
onChange={e =>
|
||||||
</Button>
|
this.setState({ columnSearchTerm: e.target.value })
|
||||||
</StyledButtonWrapper>
|
}
|
||||||
</ColumnButtonWrapper>
|
css={theme => ({
|
||||||
<Input.Search
|
width: theme.sizeUnit * 75,
|
||||||
placeholder={t('Search columns by name')}
|
})}
|
||||||
value={this.state.columnSearchTerm}
|
allowClear
|
||||||
onChange={e =>
|
/>
|
||||||
this.setState({ columnSearchTerm: e.target.value })
|
<Button
|
||||||
}
|
buttonSize="small"
|
||||||
style={{ marginBottom: 16, width: 300 }}
|
buttonStyle="tertiary"
|
||||||
allowClear
|
onClick={this.syncMetadata}
|
||||||
/>
|
className="sync-from-source"
|
||||||
|
disabled={this.state.isEditMode}
|
||||||
|
>
|
||||||
|
<Icons.DatabaseOutlined iconSize="m" />
|
||||||
|
{t('Sync columns from source')}
|
||||||
|
</Button>
|
||||||
|
</Flex>
|
||||||
<ColumnCollectionTable
|
<ColumnCollectionTable
|
||||||
className="columns-table"
|
className="columns-table"
|
||||||
columns={this.state.databaseColumns}
|
columns={this.state.databaseColumns}
|
||||||
@@ -2429,21 +2441,25 @@ class DatasourceEditor extends PureComponent<
|
|||||||
children: (
|
children: (
|
||||||
<StyledTableTabWrapper>
|
<StyledTableTabWrapper>
|
||||||
{this.renderDefaultColumnSettings()}
|
{this.renderDefaultColumnSettings()}
|
||||||
<Input.Search
|
|
||||||
placeholder={t('Search calculated columns by name')}
|
|
||||||
value={this.state.calculatedColumnSearchTerm}
|
|
||||||
onChange={e =>
|
|
||||||
this.setState({
|
|
||||||
calculatedColumnSearchTerm: e.target.value,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
style={{ marginBottom: 16, width: 300 }}
|
|
||||||
allowClear
|
|
||||||
/>
|
|
||||||
<ColumnCollectionTable
|
<ColumnCollectionTable
|
||||||
columns={this.state.calculatedColumns}
|
columns={this.state.calculatedColumns}
|
||||||
filterTerm={this.state.calculatedColumnSearchTerm}
|
filterTerm={this.state.calculatedColumnSearchTerm}
|
||||||
filterFields={['column_name']}
|
filterFields={['column_name']}
|
||||||
|
toolbarExtra={
|
||||||
|
<Input.Search
|
||||||
|
placeholder={t('Search calculated columns by name')}
|
||||||
|
value={this.state.calculatedColumnSearchTerm}
|
||||||
|
onChange={e =>
|
||||||
|
this.setState({
|
||||||
|
calculatedColumnSearchTerm: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
css={theme => ({
|
||||||
|
width: theme.sizeUnit * 75,
|
||||||
|
})}
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
}
|
||||||
onColumnsChange={calculatedColumns =>
|
onColumnsChange={calculatedColumns =>
|
||||||
this.setColumns({ calculatedColumns })
|
this.setColumns({ calculatedColumns })
|
||||||
}
|
}
|
||||||
@@ -2526,7 +2542,7 @@ class DatasourceEditor extends PureComponent<
|
|||||||
key: TABS_KEYS.SETTINGS,
|
key: TABS_KEYS.SETTINGS,
|
||||||
label: t('Settings'),
|
label: t('Settings'),
|
||||||
children: (
|
children: (
|
||||||
<div style={{ overflowX: 'hidden' }}>
|
<div css={{ overflow: 'hidden' }}>
|
||||||
<Row gutter={16}>
|
<Row gutter={16}>
|
||||||
<Col xs={24} md={12}>
|
<Col xs={24} md={12}>
|
||||||
<FormContainer>
|
<FormContainer>
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export interface CRUDCollectionProps {
|
|||||||
emptyMessage?: ReactNode;
|
emptyMessage?: ReactNode;
|
||||||
expandFieldset?: ReactNode;
|
expandFieldset?: ReactNode;
|
||||||
extraButtons?: ReactNode;
|
extraButtons?: ReactNode;
|
||||||
|
toolbarExtra?: ReactNode;
|
||||||
itemGenerator?: () => any;
|
itemGenerator?: () => any;
|
||||||
itemCellProps?: Record<
|
itemCellProps?: Record<
|
||||||
string,
|
string,
|
||||||
|
|||||||
Reference in New Issue
Block a user