Compare commits

...

3 Commits

Author SHA1 Message Date
Maxime Beauchemin
ddd08b5fe7 style(dataset-modal): fix prettier formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 01:14:09 +00:00
Maxime Beauchemin
63901941ff fix(dataset-modal): fix Source tab spacing per sc-101861
- Add bottom margin to radio buttons section so lock icon/text has
  more separation from the divider line (issue 1)
- Remove last FormItem bottom margin in both virtual and physical
  datasource views to reduce excess whitespace below the SQL text box
  and table selector (issue 2)
- Move search inputs into CollectionTable toolbar via new toolbarExtra
  prop so search and "Add item" button sit on the same row
- Update CrudButtonWrapper to use flex layout with space-between for
  proper toolbar alignment

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 19:47:21 +00:00
Maxime Beauchemin
42f1af87bf fix(dataset-modal): fix UI alignment issues in Edit Dataset modal
- Remove negative margin hack on .ant-tabs-top that caused tabs to overlap
  with the warning alert, replace with tighter alert bottom margin
- Remove width calc(100%-34px) and marginTop:-16 hacks on Source tab's
  table_name field that caused it to be misaligned with the database selector
- Align Columns tab search input and "Sync columns" button on the same row
  using Flex for consistent layout
- Replace hardcoded inline style={{ marginBottom: 16, width: 300 }} on
  search inputs with theme-token-based css props
- Remove leading whitespace in warning alert text
- Remove unused ColumnButtonWrapper and StyledButtonWrapper styled components
- Use css prop instead of inline style for Settings tab overflow wrapper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 16:18:58 +00:00
4 changed files with 118 additions and 100 deletions

View File

@@ -65,10 +65,6 @@ const StyledDatasourceModal = styled(Modal)`
display: flex;
flex-direction: column;
}
.ant-tabs-top {
margin-top: -${({ theme }) => theme.sizeUnit * 4}px;
}
`;
function buildExtraJsonObject(

View File

@@ -38,7 +38,9 @@ import {
} from '../../types';
const CrudButtonWrapper = styled.div`
text-align: right;
display: flex;
justify-content: space-between;
align-items: center;
${({ theme }) => `margin-bottom: ${theme.sizeUnit * 2}px`}
`;
@@ -466,24 +468,27 @@ export default class CRUDCollection extends PureComponent<
return (
<>
<CrudButtonWrapper>
{this.props.allowAddItem && (
<StyledButtonWrapper>
<Button
buttonSize="small"
buttonStyle="secondary"
onClick={this.onAddItem}
data-test="add-item-button"
>
<Icons.PlusOutlined
iconSize="m"
data-test="crud-add-table-item"
/>
{t('Add item')}
</Button>
</StyledButtonWrapper>
)}
</CrudButtonWrapper>
{(this.props.toolbarExtra || this.props.allowAddItem) && (
<CrudButtonWrapper>
{this.props.toolbarExtra}
{this.props.allowAddItem && (
<StyledButtonWrapper>
<Button
buttonSize="small"
buttonStyle="secondary"
onClick={this.onAddItem}
data-test="add-item-button"
>
<Icons.PlusOutlined
iconSize="m"
data-test="crud-add-table-item"
/>
{t('Add item')}
</Button>
</StyledButtonWrapper>
)}
</CrudButtonWrapper>
)}
<Table<CollectionItem>
data-test="crud-table"
columns={tableColumns}

View File

@@ -311,6 +311,7 @@ interface ColumnCollectionTableProps {
columnLabelTooltips?: Record<string, string>;
filterTerm?: string;
filterFields?: string[];
toolbarExtra?: ReactNode;
}
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`
display: flex;
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 = (
d: boolean,
onChange: (value: boolean) => void,
@@ -532,6 +518,7 @@ function ColumnCollectionTable({
columnLabelTooltips,
filterTerm,
filterFields,
toolbarExtra,
}: ColumnCollectionTableProps): JSX.Element {
return (
<CollectionTable
@@ -566,6 +553,7 @@ function ColumnCollectionTable({
columnLabelTooltips={columnLabelTooltips}
filterTerm={filterTerm}
filterFields={filterFields}
toolbarExtra={toolbarExtra}
stickyHeader
expandFieldset={
<FormContainer>
@@ -1835,6 +1823,7 @@ class DatasourceEditor extends PureComponent<
<div
css={theme => css`
margin-top: ${theme.sizeUnit * 3}px;
margin-bottom: ${theme.sizeUnit * 2}px;
display: flex;
gap: ${theme.sizeUnit * 4}px;
`}
@@ -1854,7 +1843,13 @@ class DatasourceEditor extends PureComponent<
<Divider />
<Fieldset item={datasource} onChange={this.onDatasourceChange} compact>
{this.state.datasourceType === DATASOURCE_TYPES.virtual.key && (
<div>
<div
css={css`
.ant-form-item:last-child {
margin-bottom: 0;
}
`}
>
{this.state.isSqla && (
<>
<Col xs={24} md={12}>
@@ -1897,22 +1892,20 @@ class DatasourceEditor extends PureComponent<
</div>
}
/>
<div css={{ width: 'calc(100% - 34px)', marginTop: -16 }}>
<Field
fieldKey="table_name"
label={t('Name')}
control={
<TextControl
controlId="table_name"
onChange={table => {
this.onDatasourcePropChange('table_name', table);
}}
placeholder={t('Dataset name')}
disabled={!this.state.isEditMode}
/>
}
/>
</div>
<Field
fieldKey="table_name"
label={t('Name')}
control={
<TextControl
controlId="table_name"
onChange={table => {
this.onDatasourcePropChange('table_name', table);
}}
placeholder={t('Dataset name')}
disabled={!this.state.isEditMode}
/>
}
/>
</Col>
<Field
fieldKey="sql"
@@ -2053,7 +2046,15 @@ class DatasourceEditor extends PureComponent<
</div>
)}
{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 && (
<Field
fieldKey="tableSelector"
@@ -2148,18 +2149,24 @@ class DatasourceEditor extends PureComponent<
const sortedMetrics = metrics?.length ? this.sortMetrics(metrics) : [];
return (
<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
tableColumns={['metric_name', 'verbose_name', 'expression']}
sortColumns={['metric_name', 'verbose_name', 'expression']}
filterTerm={metricSearchTerm}
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={{
metric_name: t('Metric Key'),
verbose_name: t('Label'),
@@ -2336,11 +2343,10 @@ class DatasourceEditor extends PureComponent<
<DatasourceContainer data-test="datasource-editor">
{this.renderErrors()}
<Alert
css={theme => ({ marginBottom: theme.sizeUnit * 4 })}
css={theme => ({ marginBottom: theme.sizeUnit * 2 })}
type="warning"
message={
<>
{' '}
<strong>{t('Be careful.')} </strong>
{t(
'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: (
<StyledTableTabWrapper>
{this.renderDefaultColumnSettings()}
<ColumnButtonWrapper>
<StyledButtonWrapper>
<Button
buttonSize="small"
buttonStyle="tertiary"
onClick={this.syncMetadata}
className="sync-from-source"
disabled={this.state.isEditMode}
>
<Icons.DatabaseOutlined iconSize="m" />
{t('Sync columns from source')}
</Button>
</StyledButtonWrapper>
</ColumnButtonWrapper>
<Input.Search
placeholder={t('Search columns by name')}
value={this.state.columnSearchTerm}
onChange={e =>
this.setState({ columnSearchTerm: e.target.value })
}
style={{ marginBottom: 16, width: 300 }}
allowClear
/>
<Flex
justify="space-between"
align="center"
css={theme => ({
marginBottom: theme.sizeUnit * 4,
})}
>
<Input.Search
placeholder={t('Search columns by name')}
value={this.state.columnSearchTerm}
onChange={e =>
this.setState({ columnSearchTerm: e.target.value })
}
css={theme => ({
width: theme.sizeUnit * 75,
})}
allowClear
/>
<Button
buttonSize="small"
buttonStyle="tertiary"
onClick={this.syncMetadata}
className="sync-from-source"
disabled={this.state.isEditMode}
>
<Icons.DatabaseOutlined iconSize="m" />
{t('Sync columns from source')}
</Button>
</Flex>
<ColumnCollectionTable
className="columns-table"
columns={this.state.databaseColumns}
@@ -2429,21 +2441,25 @@ class DatasourceEditor extends PureComponent<
children: (
<StyledTableTabWrapper>
{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
columns={this.state.calculatedColumns}
filterTerm={this.state.calculatedColumnSearchTerm}
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 =>
this.setColumns({ calculatedColumns })
}
@@ -2526,7 +2542,7 @@ class DatasourceEditor extends PureComponent<
key: TABS_KEYS.SETTINGS,
label: t('Settings'),
children: (
<div style={{ overflowX: 'hidden' }}>
<div css={{ overflow: 'hidden' }}>
<Row gutter={16}>
<Col xs={24} md={12}>
<FormContainer>

View File

@@ -53,6 +53,7 @@ export interface CRUDCollectionProps {
emptyMessage?: ReactNode;
expandFieldset?: ReactNode;
extraButtons?: ReactNode;
toolbarExtra?: ReactNode;
itemGenerator?: () => any;
itemCellProps?: Record<
string,