in superset-frontend/src/explore/components/DatasourcePanel/index.tsx [138:342]
export default function DataSourcePanel({
datasource,
formData,
controls: { datasource: datasourceControl },
actions,
width,
}: Props) {
const [dropzones] = useContext(DropzoneContext);
const { columns: _columns, metrics, folders: _folders } = datasource;
const allowedColumns = useMemo(() => {
const validators = Object.values(dropzones);
if (!Array.isArray(_columns)) return [];
return _columns.filter(column =>
validators.some(validator =>
validator({
value: column as DndItemValue,
type: DndItemType.Column,
}),
),
);
}, [dropzones, _columns]);
const allowedMetrics = useMemo(() => {
const validators = Object.values(dropzones);
return metrics.filter(metric =>
validators.some(validator =>
validator({ value: metric, type: DndItemType.Metric }),
),
);
}, [dropzones, metrics]);
const [showSaveDatasetModal, setShowSaveDatasetModal] = useState(false);
const [inputValue, setInputValue] = useState('');
const searchKeyword = useDebounceValue(inputValue, FAST_DEBOUNCE);
const filteredColumns = useMemo(() => {
if (!searchKeyword) {
return allowedColumns ?? [];
}
return matchSorter(allowedColumns, searchKeyword, {
keys: [
{
key: 'verbose_name',
threshold: rankings.CONTAINS,
},
{
key: 'column_name',
threshold: rankings.CONTAINS,
},
{
key: item =>
[item?.description ?? '', item?.expression ?? ''].map(
x => x?.replace(/[_\n\s]+/g, ' ') || '',
),
threshold: rankings.CONTAINS,
maxRanking: rankings.CONTAINS,
},
],
keepDiacritics: true,
});
}, [allowedColumns, searchKeyword]);
const filteredMetrics = useMemo(() => {
if (!searchKeyword) {
return allowedMetrics ?? [];
}
return matchSorter(allowedMetrics, searchKeyword, {
keys: [
{
key: 'verbose_name',
threshold: rankings.CONTAINS,
},
{
key: 'metric_name',
threshold: rankings.CONTAINS,
},
{
key: item =>
[item?.description ?? '', item?.expression ?? ''].map(
x => x?.replace(/[_\n\s]+/g, ' ') || '',
),
threshold: rankings.CONTAINS,
maxRanking: rankings.CONTAINS,
},
],
keepDiacritics: true,
baseSort: (a, b) =>
Number(b?.item?.is_certified ?? 0) -
Number(a?.item?.is_certified ?? 0) ||
String(a?.rankedValue ?? '').localeCompare(b?.rankedValue ?? ''),
});
}, [allowedMetrics, searchKeyword]);
const sortedColumns = useMemo(
() => sortColumns(filteredColumns),
[filteredColumns],
);
const folders = useMemo(
() =>
transformDatasourceWithFolders(
filteredMetrics,
sortedColumns,
_folders,
allowedMetrics,
allowedColumns,
),
[_folders, filteredMetrics, sortedColumns],
);
const showInfoboxCheck = () => {
try {
if (sessionStorage.getItem('showInfobox') === 'false') return false;
} catch (error) {
// continue regardless of error
}
return true;
};
const saveableDatasets = {
query: DatasourceType.Query,
saved_query: DatasourceType.SavedQuery,
};
const datasourceIsSaveable =
datasource.type &&
saveableDatasets[datasource.type as keyof typeof saveableDatasets];
const mainBody = useMemo(
() => (
<>
<Input
allowClear
onChange={evt => {
setInputValue(evt.target.value);
}}
value={inputValue}
className="form-control input-md"
placeholder={t('Search Metrics & Columns')}
/>
<div className="field-selections" data-test="fieldSelections">
{datasourceIsSaveable && showInfoboxCheck() && (
<StyledInfoboxWrapper>
<Alert
closable
onClose={() => {
try {
sessionStorage.setItem('showInfobox', 'false');
} catch (error) {
// continue regardless of error
}
}}
type="info"
message=""
description={
<>
<span
role="button"
tabIndex={0}
onClick={() => setShowSaveDatasetModal(true)}
className="add-dataset-alert-description"
>
{t('Create a dataset')}
</span>
{t(' to edit or add columns and metrics.')}
</>
}
/>
</StyledInfoboxWrapper>
)}
<AutoSizer>
{({ height }: { height: number }) => (
<DatasourceItems
width={width - BORDER_WIDTH}
height={height}
folders={folders}
/>
)}
</AutoSizer>
</div>
</>
),
[inputValue, datasourceIsSaveable, width, folders],
);
return (
<DatasourceContainer>
{datasourceIsSaveable && showSaveDatasetModal && (
<SaveDatasetModal
visible={showSaveDatasetModal}
onHide={() => setShowSaveDatasetModal(false)}
buttonTextOnSave={t('Save')}
buttonTextOnOverwrite={t('Overwrite')}
datasource={getDatasourceAsSaveableDataset(datasource)}
openWindow={false}
formData={formData}
/>
)}
{/* @ts-ignore */}
<Control {...datasourceControl} name="datasource" actions={actions} />
{datasource.id != null && mainBody}
</DatasourceContainer>
);
}