mirror of
https://github.com/apache/superset.git
synced 2026-05-06 16:34:32 +00:00
chore: Moves TableSelector tests to component's folder (#13411)
This commit is contained in:
committed by
GitHub
parent
dc1eb305b1
commit
cfc83c271c
@@ -0,0 +1,291 @@
|
||||
/**
|
||||
* 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 configureStore from 'redux-mock-store';
|
||||
import { mount } from 'enzyme';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import sinon from 'sinon';
|
||||
import fetchMock from 'fetch-mock';
|
||||
import thunk from 'redux-thunk';
|
||||
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
|
||||
|
||||
import waitForComponentToPaint from 'spec/helpers/waitForComponentToPaint';
|
||||
|
||||
import DatabaseSelector from 'src/components/DatabaseSelector';
|
||||
import TableSelector from 'src/components/TableSelector';
|
||||
import { initialState, tables } from 'spec/javascripts/sqllab/fixtures';
|
||||
|
||||
const mockStore = configureStore([thunk]);
|
||||
const store = mockStore(initialState);
|
||||
|
||||
const FETCH_SCHEMAS_ENDPOINT = 'glob:*/api/v1/database/*/schemas/*';
|
||||
const GET_TABLE_ENDPOINT = 'glob:*/superset/tables/1/*/*';
|
||||
const GET_TABLE_NAMES_ENDPOINT = 'glob:*/superset/tables/1/main/*';
|
||||
|
||||
const mockedProps = {
|
||||
clearable: false,
|
||||
database: { id: 1, database_name: 'main' },
|
||||
dbId: 1,
|
||||
formMode: false,
|
||||
getDbList: sinon.stub(),
|
||||
handleError: sinon.stub(),
|
||||
horizontal: false,
|
||||
onChange: sinon.stub(),
|
||||
onDbChange: sinon.stub(),
|
||||
onSchemaChange: sinon.stub(),
|
||||
onTableChange: sinon.stub(),
|
||||
sqlLabMode: true,
|
||||
tableName: '',
|
||||
tableNameSticky: true,
|
||||
};
|
||||
|
||||
const schemaOptions = {
|
||||
result: ['main', 'erf', 'superset'],
|
||||
};
|
||||
const selectedSchema = { label: 'main', title: 'main', value: 'main' };
|
||||
const selectedTable = {
|
||||
extra: null,
|
||||
label: 'birth_names',
|
||||
schema: 'main',
|
||||
title: 'birth_names',
|
||||
type: undefined,
|
||||
value: 'birth_names',
|
||||
};
|
||||
|
||||
async function mountAndWait(props = mockedProps) {
|
||||
const mounted = mount(<TableSelector {...props} />, {
|
||||
context: { store },
|
||||
wrappingComponent: ThemeProvider,
|
||||
wrappingComponentProps: { theme: supersetTheme },
|
||||
});
|
||||
await waitForComponentToPaint(mounted);
|
||||
|
||||
return mounted;
|
||||
}
|
||||
|
||||
describe('TableSelector', () => {
|
||||
let wrapper;
|
||||
|
||||
beforeEach(async () => {
|
||||
fetchMock.reset();
|
||||
wrapper = await mountAndWait();
|
||||
});
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.find(TableSelector)).toExist();
|
||||
expect(wrapper.find(DatabaseSelector)).toExist();
|
||||
});
|
||||
|
||||
describe('change database', () => {
|
||||
afterEach(fetchMock.resetHistory);
|
||||
afterAll(fetchMock.reset);
|
||||
|
||||
it('should fetch schemas', async () => {
|
||||
fetchMock.get(FETCH_SCHEMAS_ENDPOINT, { overwriteRoutes: true });
|
||||
act(() => {
|
||||
wrapper.find('[data-test="select-database"]').first().props().onChange({
|
||||
id: 1,
|
||||
database_name: 'main',
|
||||
});
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
expect(fetchMock.calls(FETCH_SCHEMAS_ENDPOINT)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should fetch schema options', async () => {
|
||||
fetchMock.get(FETCH_SCHEMAS_ENDPOINT, schemaOptions, {
|
||||
overwriteRoutes: true,
|
||||
});
|
||||
act(() => {
|
||||
wrapper.find('[data-test="select-database"]').first().props().onChange({
|
||||
id: 1,
|
||||
database_name: 'main',
|
||||
});
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
wrapper.update();
|
||||
expect(fetchMock.calls(FETCH_SCHEMAS_ENDPOINT)).toHaveLength(1);
|
||||
|
||||
expect(
|
||||
wrapper.find('[name="select-schema"]').first().props().options,
|
||||
).toEqual([
|
||||
{ value: 'main', label: 'main', title: 'main' },
|
||||
{ value: 'erf', label: 'erf', title: 'erf' },
|
||||
{ value: 'superset', label: 'superset', title: 'superset' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('should clear table options', async () => {
|
||||
act(() => {
|
||||
wrapper.find('[data-test="select-database"]').first().props().onChange({
|
||||
id: 1,
|
||||
database_name: 'main',
|
||||
});
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
const props = wrapper.find('[name="async-select-table"]').first().props();
|
||||
expect(props.isDisabled).toBe(true);
|
||||
expect(props.value).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('change schema', () => {
|
||||
beforeEach(async () => {
|
||||
fetchMock.get(FETCH_SCHEMAS_ENDPOINT, schemaOptions, {
|
||||
overwriteRoutes: true,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(fetchMock.resetHistory);
|
||||
afterAll(fetchMock.reset);
|
||||
|
||||
it('should fetch table', async () => {
|
||||
fetchMock.get(GET_TABLE_NAMES_ENDPOINT, { overwriteRoutes: true });
|
||||
act(() => {
|
||||
wrapper.find('[data-test="select-database"]').first().props().onChange({
|
||||
id: 1,
|
||||
database_name: 'main',
|
||||
});
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('[name="select-schema"]')
|
||||
.first()
|
||||
.props()
|
||||
.onChange(selectedSchema);
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
expect(fetchMock.calls(GET_TABLE_NAMES_ENDPOINT)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should fetch table options', async () => {
|
||||
fetchMock.get(GET_TABLE_NAMES_ENDPOINT, tables, {
|
||||
overwriteRoutes: true,
|
||||
});
|
||||
act(() => {
|
||||
wrapper.find('[data-test="select-database"]').first().props().onChange({
|
||||
id: 1,
|
||||
database_name: 'main',
|
||||
});
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('[name="select-schema"]')
|
||||
.first()
|
||||
.props()
|
||||
.onChange(selectedSchema);
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
expect(
|
||||
wrapper.find('[name="select-schema"]').first().props().value[0],
|
||||
).toEqual(selectedSchema);
|
||||
expect(fetchMock.calls(GET_TABLE_NAMES_ENDPOINT)).toHaveLength(1);
|
||||
const { options } = wrapper.find('[name="select-table"]').first().props();
|
||||
expect({ options }).toEqual(tables);
|
||||
});
|
||||
});
|
||||
|
||||
describe('change table', () => {
|
||||
beforeEach(async () => {
|
||||
fetchMock.get(GET_TABLE_NAMES_ENDPOINT, tables, {
|
||||
overwriteRoutes: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should change table value', async () => {
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('[name="select-schema"]')
|
||||
.first()
|
||||
.props()
|
||||
.onChange(selectedSchema);
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('[name="select-table"]')
|
||||
.first()
|
||||
.props()
|
||||
.onChange(selectedTable);
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
expect(
|
||||
wrapper.find('[name="select-table"]').first().props().value,
|
||||
).toEqual('birth_names');
|
||||
});
|
||||
|
||||
it('should call onTableChange with schema from table object', async () => {
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('[name="select-schema"]')
|
||||
.first()
|
||||
.props()
|
||||
.onChange(selectedSchema);
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('[name="select-table"]')
|
||||
.first()
|
||||
.props()
|
||||
.onChange(selectedTable);
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
expect(mockedProps.onTableChange.getCall(0).args[0]).toBe('birth_names');
|
||||
expect(mockedProps.onTableChange.getCall(0).args[1]).toBe('main');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTableNamesBySubStr', () => {
|
||||
afterEach(fetchMock.resetHistory);
|
||||
afterAll(fetchMock.reset);
|
||||
|
||||
it('should handle empty', async () => {
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('[name="async-select-table"]')
|
||||
.first()
|
||||
.props()
|
||||
.loadOptions();
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
const props = wrapper.find('[name="async-select-table"]').first().props();
|
||||
expect(props.isDisabled).toBe(true);
|
||||
expect(props.value).toEqual('');
|
||||
});
|
||||
|
||||
it('should handle table name', async () => {
|
||||
wrapper.setProps({ schema: 'main' });
|
||||
fetchMock.get(GET_TABLE_ENDPOINT, tables, {
|
||||
overwriteRoutes: true,
|
||||
});
|
||||
act(() => {
|
||||
wrapper
|
||||
.find('[name="async-select-table"]')
|
||||
.first()
|
||||
.props()
|
||||
.loadOptions();
|
||||
});
|
||||
await waitForComponentToPaint(wrapper);
|
||||
expect(fetchMock.calls(GET_TABLE_ENDPOINT)).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
398
superset-frontend/src/components/TableSelector/index.tsx
Normal file
398
superset-frontend/src/components/TableSelector/index.tsx
Normal file
@@ -0,0 +1,398 @@
|
||||
/**
|
||||
* 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, {
|
||||
FunctionComponent,
|
||||
useEffect,
|
||||
useState,
|
||||
ReactNode,
|
||||
} from 'react';
|
||||
import { styled, SupersetClient, t } from '@superset-ui/core';
|
||||
import { AsyncSelect, CreatableSelect, Select } from 'src/components/Select';
|
||||
|
||||
import FormLabel from 'src/components/FormLabel';
|
||||
|
||||
import DatabaseSelector from 'src/components/DatabaseSelector';
|
||||
import RefreshLabel from 'src/components/RefreshLabel';
|
||||
import CertifiedIconWithTooltip from 'src/components/CertifiedIconWithTooltip';
|
||||
|
||||
const FieldTitle = styled.p`
|
||||
color: ${({ theme }) => theme.colors.secondary.light2};
|
||||
font-size: ${({ theme }) => theme.typography.sizes.s}px;
|
||||
margin: 20px 0 10px 0;
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
|
||||
const TableSelectorWrapper = styled.div`
|
||||
.fa-refresh {
|
||||
padding-left: 9px;
|
||||
}
|
||||
|
||||
.refresh-col {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
.section {
|
||||
padding-bottom: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.select {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.divider {
|
||||
border-bottom: 1px solid ${({ theme }) => theme.colors.secondary.light5};
|
||||
margin: 15px 0;
|
||||
}
|
||||
`;
|
||||
|
||||
const TableLabel = styled.span`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
white-space: nowrap;
|
||||
|
||||
> svg,
|
||||
> small {
|
||||
margin-right: ${({ theme }) => theme.gridUnit}px;
|
||||
}
|
||||
`;
|
||||
|
||||
interface TableSelectorProps {
|
||||
clearable?: boolean;
|
||||
database?: any;
|
||||
dbId: number;
|
||||
formMode?: boolean;
|
||||
getDbList?: (arg0: any) => {};
|
||||
handleError: (msg: string) => void;
|
||||
isDatabaseSelectEnabled?: boolean;
|
||||
onChange?: ({
|
||||
dbId,
|
||||
schema,
|
||||
}: {
|
||||
dbId: number;
|
||||
schema?: string;
|
||||
tableName?: string;
|
||||
}) => void;
|
||||
onDbChange?: (db: any) => void;
|
||||
onSchemaChange?: (arg0?: any) => {};
|
||||
onSchemasLoad?: () => void;
|
||||
onTableChange?: (tableName: string, schema: string) => void;
|
||||
onTablesLoad?: (options: Array<any>) => {};
|
||||
readOnly?: boolean;
|
||||
schema?: string;
|
||||
sqlLabMode?: boolean;
|
||||
tableName?: string;
|
||||
tableNameSticky?: boolean;
|
||||
}
|
||||
|
||||
const TableSelector: FunctionComponent<TableSelectorProps> = ({
|
||||
database,
|
||||
dbId,
|
||||
formMode = false,
|
||||
getDbList,
|
||||
handleError,
|
||||
isDatabaseSelectEnabled = true,
|
||||
onChange,
|
||||
onDbChange,
|
||||
onSchemaChange,
|
||||
onSchemasLoad,
|
||||
onTableChange,
|
||||
onTablesLoad,
|
||||
readOnly = false,
|
||||
schema,
|
||||
sqlLabMode = true,
|
||||
tableName,
|
||||
tableNameSticky = true,
|
||||
}) => {
|
||||
const [currentSchema, setCurrentSchema] = useState<string | undefined>(
|
||||
schema,
|
||||
);
|
||||
const [currentTableName, setCurrentTableName] = useState<string | undefined>(
|
||||
tableName,
|
||||
);
|
||||
const [tableLoading, setTableLoading] = useState(false);
|
||||
const [tableOptions, setTableOptions] = useState([]);
|
||||
|
||||
function fetchTables(
|
||||
databaseId?: number,
|
||||
schema?: string,
|
||||
forceRefresh = false,
|
||||
substr = 'undefined',
|
||||
) {
|
||||
const dbSchema = schema || currentSchema;
|
||||
const actualDbId = databaseId || dbId;
|
||||
if (actualDbId && dbSchema) {
|
||||
const encodedSchema = encodeURIComponent(dbSchema);
|
||||
const encodedSubstr = encodeURIComponent(substr);
|
||||
setTableLoading(true);
|
||||
setTableOptions([]);
|
||||
const endpoint = encodeURI(
|
||||
`/superset/tables/${actualDbId}/${encodedSchema}/${encodedSubstr}/${!!forceRefresh}/`,
|
||||
);
|
||||
return SupersetClient.get({ endpoint })
|
||||
.then(({ json }) => {
|
||||
const options = json.options.map((o: any) => ({
|
||||
value: o.value,
|
||||
schema: o.schema,
|
||||
label: o.label,
|
||||
title: o.title,
|
||||
type: o.type,
|
||||
extra: o?.extra,
|
||||
}));
|
||||
setTableLoading(false);
|
||||
setTableOptions(options);
|
||||
if (onTablesLoad) {
|
||||
onTablesLoad(json.options);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setTableLoading(false);
|
||||
setTableOptions([]);
|
||||
handleError(t('Error while fetching table list'));
|
||||
});
|
||||
}
|
||||
setTableLoading(false);
|
||||
setTableOptions([]);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (dbId && schema) {
|
||||
fetchTables();
|
||||
}
|
||||
}, [dbId, schema]);
|
||||
|
||||
function onSelectionChange({
|
||||
dbId,
|
||||
schema,
|
||||
tableName,
|
||||
}: {
|
||||
dbId: number;
|
||||
schema?: string;
|
||||
tableName?: string;
|
||||
}) {
|
||||
setCurrentTableName(tableName);
|
||||
setCurrentSchema(schema);
|
||||
if (onChange) {
|
||||
onChange({ dbId, schema, tableName });
|
||||
}
|
||||
}
|
||||
|
||||
function getTableNamesBySubStr(substr = 'undefined') {
|
||||
if (!dbId || !substr) {
|
||||
const options: any[] = [];
|
||||
return Promise.resolve({ options });
|
||||
}
|
||||
const encodedSchema = encodeURIComponent(schema || '');
|
||||
const encodedSubstr = encodeURIComponent(substr);
|
||||
return SupersetClient.get({
|
||||
endpoint: encodeURI(
|
||||
`/superset/tables/${dbId}/${encodedSchema}/${encodedSubstr}`,
|
||||
),
|
||||
}).then(({ json }) => {
|
||||
const options = json.options.map((o: any) => ({
|
||||
value: o.value,
|
||||
schema: o.schema,
|
||||
label: o.label,
|
||||
title: o.title,
|
||||
type: o.type,
|
||||
}));
|
||||
return { options };
|
||||
});
|
||||
}
|
||||
|
||||
function changeTable(tableOpt: any) {
|
||||
if (!tableOpt) {
|
||||
setCurrentTableName('');
|
||||
return;
|
||||
}
|
||||
const schemaName = tableOpt.schema;
|
||||
const tableOptTableName = tableOpt.value;
|
||||
if (tableNameSticky) {
|
||||
onSelectionChange({
|
||||
dbId,
|
||||
schema: schemaName,
|
||||
tableName: tableOptTableName,
|
||||
});
|
||||
}
|
||||
if (onTableChange) {
|
||||
onTableChange(tableOptTableName, schemaName);
|
||||
}
|
||||
}
|
||||
|
||||
function changeSchema(schemaOpt: any, force = false) {
|
||||
const value = schemaOpt ? schemaOpt.value : null;
|
||||
if (onSchemaChange) {
|
||||
onSchemaChange(value);
|
||||
}
|
||||
onSelectionChange({
|
||||
dbId,
|
||||
schema: value,
|
||||
tableName: undefined,
|
||||
});
|
||||
fetchTables(dbId, currentSchema, force);
|
||||
}
|
||||
|
||||
function renderTableOption(option: any) {
|
||||
return (
|
||||
<TableLabel title={option.label}>
|
||||
<small className="text-muted">
|
||||
<i className={`fa fa-${option.type === 'view' ? 'eye' : 'table'}`} />
|
||||
</small>
|
||||
{option.extra?.certification && (
|
||||
<CertifiedIconWithTooltip
|
||||
certifiedBy={option.extra.certification.certified_by}
|
||||
details={option.extra.certification.details}
|
||||
size={20}
|
||||
/>
|
||||
)}
|
||||
{option.label}
|
||||
</TableLabel>
|
||||
);
|
||||
}
|
||||
|
||||
function renderSelectRow(select: ReactNode, refreshBtn: ReactNode) {
|
||||
return (
|
||||
<div className="section">
|
||||
<span className="select">{select}</span>
|
||||
<span className="refresh-col">{refreshBtn}</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function renderDatabaseSelector() {
|
||||
return (
|
||||
<DatabaseSelector
|
||||
dbId={dbId}
|
||||
formMode={formMode}
|
||||
getDbList={getDbList}
|
||||
getTableList={fetchTables}
|
||||
handleError={handleError}
|
||||
onChange={onSelectionChange}
|
||||
onDbChange={readOnly ? undefined : onDbChange}
|
||||
onSchemaChange={readOnly ? undefined : onSchemaChange}
|
||||
onSchemasLoad={onSchemasLoad}
|
||||
schema={currentSchema}
|
||||
sqlLabMode={sqlLabMode}
|
||||
isDatabaseSelectEnabled={isDatabaseSelectEnabled && !readOnly}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function renderTableSelect() {
|
||||
const options = tableOptions;
|
||||
let select = null;
|
||||
if (currentSchema && !formMode) {
|
||||
// dataset editor
|
||||
select = (
|
||||
<Select
|
||||
name="select-table"
|
||||
isLoading={tableLoading}
|
||||
ignoreAccents={false}
|
||||
placeholder={t('Select table or type table name')}
|
||||
autosize={false}
|
||||
onChange={changeTable}
|
||||
options={options}
|
||||
// @ts-ignore
|
||||
value={currentTableName}
|
||||
optionRenderer={renderTableOption}
|
||||
valueRenderer={renderTableOption}
|
||||
isDisabled={readOnly}
|
||||
/>
|
||||
);
|
||||
} else if (formMode) {
|
||||
select = (
|
||||
<CreatableSelect
|
||||
name="select-table"
|
||||
isLoading={tableLoading}
|
||||
ignoreAccents={false}
|
||||
placeholder={t('Select table or type table name')}
|
||||
autosize={false}
|
||||
onChange={changeTable}
|
||||
options={options}
|
||||
// @ts-ignore
|
||||
value={currentTableName}
|
||||
optionRenderer={renderTableOption}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
// sql lab
|
||||
let tableSelectPlaceholder;
|
||||
let tableSelectDisabled = false;
|
||||
if (database && database.allow_multi_schema_metadata_fetch) {
|
||||
tableSelectPlaceholder = t('Type to search ...');
|
||||
} else {
|
||||
tableSelectPlaceholder = t('Select table ');
|
||||
tableSelectDisabled = true;
|
||||
}
|
||||
select = (
|
||||
<AsyncSelect
|
||||
name="async-select-table"
|
||||
placeholder={tableSelectPlaceholder}
|
||||
isDisabled={tableSelectDisabled}
|
||||
autosize={false}
|
||||
onChange={changeTable}
|
||||
// @ts-ignore
|
||||
value={currentTableName}
|
||||
loadOptions={getTableNamesBySubStr}
|
||||
optionRenderer={renderTableOption}
|
||||
/>
|
||||
);
|
||||
}
|
||||
const refresh = !formMode && !readOnly && (
|
||||
<RefreshLabel
|
||||
onClick={() => changeSchema({ value: schema }, true)}
|
||||
tooltipContent={t('Force refresh table list')}
|
||||
/>
|
||||
);
|
||||
return renderSelectRow(select, refresh);
|
||||
}
|
||||
|
||||
function renderSeeTableLabel() {
|
||||
return (
|
||||
<div className="section">
|
||||
<FormLabel>
|
||||
{t('See table schema')}{' '}
|
||||
{schema && (
|
||||
<small>
|
||||
{tableOptions.length} in
|
||||
<i>{schema}</i>
|
||||
</small>
|
||||
)}
|
||||
</FormLabel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TableSelectorWrapper>
|
||||
{renderDatabaseSelector()}
|
||||
{!formMode && <div className="divider" />}
|
||||
{sqlLabMode && renderSeeTableLabel()}
|
||||
{formMode && <FieldTitle>{t('Table')}</FieldTitle>}
|
||||
{renderTableSelect()}
|
||||
</TableSelectorWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default TableSelector;
|
||||
Reference in New Issue
Block a user