chore(style): Enforce optional chaining (#21614)

This commit is contained in:
Evan Rusackas 2022-10-03 08:17:20 -07:00 committed by GitHub
parent 3edc656f20
commit 4245bc3f38
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 83 additions and 114 deletions

View File

@ -96,6 +96,7 @@ module.exports = {
'@typescript-eslint/no-non-null-assertion': 0, // disabled temporarily
'@typescript-eslint/explicit-function-return-type': 0,
'@typescript-eslint/explicit-module-boundary-types': 0, // re-enable up for discussion
'@typescript-eslint/prefer-optional-chain': 2,
camelcase: 0,
'class-methods-use-this': 0,
'func-names': 0,

View File

@ -54,11 +54,7 @@ const TooltipSection = ({
);
export const isLabelTruncated = (labelRef?: React.RefObject<any>): boolean =>
!!(
labelRef &&
labelRef.current &&
labelRef.current.scrollWidth > labelRef.current.clientWidth
);
!!(labelRef?.current?.scrollWidth > labelRef?.current?.clientWidth);
export const getColumnLabelText = (column: ColumnMeta): string =>
column.verbose_name || column.column_name;

View File

@ -77,10 +77,8 @@ export const dndGroupByControl: SharedControlConfig<
valueKey: 'column_name',
allowAll: true,
filterOption: ({ data: opt }: FilterOption<ColumnMeta>, text: string) =>
(opt.column_name &&
opt.column_name.toLowerCase().includes(text.toLowerCase())) ||
(opt.verbose_name &&
opt.verbose_name.toLowerCase().includes(text.toLowerCase())) ||
opt.column_name?.toLowerCase().includes(text.toLowerCase()) ||
opt.verbose_name?.toLowerCase().includes(text.toLowerCase()) ||
false,
promptTextCreator: (label: unknown) => label,
mapStateToProps(state, controlState) {

View File

@ -67,8 +67,7 @@ class CategoricalColorScale extends ExtensibleFunction {
const cleanedValue = stringifyAndTrim(value);
const sharedLabelColor = getSharedLabelColor();
const parentColor =
this.parentForcedColors && this.parentForcedColors[cleanedValue];
const parentColor = this.parentForcedColors?.[cleanedValue];
if (parentColor) {
sharedLabelColor.addSlice(cleanedValue, parentColor, sliceId);
return parentColor;

View File

@ -94,7 +94,7 @@ export default async function callApi({
cache !== 'no-store' &&
cache !== 'reload' &&
CACHE_AVAILABLE &&
(window.location && window.location.protocol) === 'https:'
window.location?.protocol === 'https:'
) {
let supersetCache: Cache | null = null;
try {

View File

@ -169,7 +169,7 @@ export default class Registry<
const item = this.items[key];
if (item !== undefined) {
if ('loader' in item) {
return item.loader && item.loader();
return item.loader?.();
}
return item.value;

View File

@ -46,7 +46,7 @@ export default function transformProps(chartProps: BigNumberTotalChartProps) {
data.length === 0 ? null : parseMetricValue(data[0][metricName]);
let metricEntry;
if (chartProps.datasource && chartProps.datasource.metrics) {
if (chartProps.datasource?.metrics) {
metricEntry = chartProps.datasource.metrics.find(
metricItem => metricItem.metric_name === metric,
);

View File

@ -155,7 +155,7 @@ export default function transformProps(
}
let metricEntry;
if (chartProps.datasource && chartProps.datasource.metrics) {
if (chartProps.datasource?.metrics) {
metricEntry = chartProps.datasource.metrics.find(
metricEntry => metricEntry.metric_name === metric,
);

View File

@ -182,7 +182,7 @@ const AceEditorWrapper = ({
const tableWords = tables.map(t => {
const tableName = t.value;
const extendedTable = extendedTables.find(et => et.name === tableName);
const cols = (extendedTable && extendedTable.columns) || [];
const cols = extendedTable?.columns || [];
cols.forEach(col => {
columns[col.name] = null; // using an object as a unique set
});

View File

@ -130,10 +130,7 @@ export default function chartReducer(
return { ...state, latestQueryFormData: action.value };
},
[actions.ANNOTATION_QUERY_STARTED](state) {
if (
state.annotationQuery &&
state.annotationQuery[action.annotation.name]
) {
if (state.annotationQuery?.[action.annotation.name]) {
state.annotationQuery[action.annotation.name].abort();
}
const annotationQuery = {

View File

@ -69,7 +69,7 @@ export default function ConfirmStatusChange({
return (
<>
{children && children(showConfirm)}
{children?.(showConfirm)}
<DeleteModal
description={description}
onConfirm={confirm}

View File

@ -214,7 +214,7 @@ export default class CRUDCollection extends React.PureComponent<
getLabel(col: any) {
const { columnLabels } = this.props;
let label = columnLabels && columnLabels[col] ? columnLabels[col] : col;
let label = columnLabels?.[col] ? columnLabels[col] : col;
if (label.startsWith('__')) {
// special label-free columns (ie: caret for expand, delete cross)
label = '';
@ -350,7 +350,7 @@ export default class CRUDCollection extends React.PureComponent<
}
renderCell(record: any, col: any) {
const renderer = this.props.itemRenderers && this.props.itemRenderers[col];
const renderer = this.props.itemRenderers?.[col];
const val = record[col];
const onChange = this.onCellChange.bind(this, record.id, col);
return renderer ? renderer(val, onChange, this.getLabel(col), record) : val;

View File

@ -75,19 +75,18 @@ function DatabaseErrorMessage({
</>
);
const copyText =
extra && extra.issue_codes
? t('%(message)s\nThis may be triggered by: \n%(issues)s', {
message,
issues: extra.issue_codes
.map(issueCode => issueCode.message)
.join('\n'),
})
: message;
const copyText = extra?.issue_codes
? t('%(message)s\nThis may be triggered by: \n%(issues)s', {
message,
issues: extra.issue_codes
.map(issueCode => issueCode.message)
.join('\n'),
})
: message;
return (
<ErrorAlert
title={t('%s Error', (extra && extra.engine_name) || t('DB engine'))}
title={t('%s Error', extra?.engine_name || t('DB engine'))}
subtitle={subtitle}
level={level}
source={source}

View File

@ -67,8 +67,8 @@ export default function FacePile({ users, maxCount = 4 }: FacePileProps) {
borderColor: color,
}}
>
{first_name && first_name[0]?.toLocaleUpperCase()}
{last_name && last_name[0]?.toLocaleUpperCase()}
{first_name?.[0]?.toLocaleUpperCase()}
{last_name?.[0]?.toLocaleUpperCase()}
</StyledAvatar>
</Tooltip>
);

View File

@ -74,8 +74,7 @@ function UIFilters(
},
index,
) => {
const initialValue =
internalFilters[index] && internalFilters[index].value;
const initialValue = internalFilters?.[index]?.value;
if (input === 'select') {
return (
<SelectFilter

View File

@ -170,7 +170,7 @@ export const handleFilterOptionHelper = (
if (filterOption) {
const searchValue = search.trim().toLowerCase();
if (optionFilterProps && optionFilterProps.length) {
if (optionFilterProps?.length) {
return optionFilterProps.some(prop => {
const optionProp = option?.[prop]
? String(option[prop]).trim().toLowerCase()

View File

@ -292,9 +292,9 @@ export default React.memo(
{row.cells.map(cell => {
if (cell.column.hidden) return null;
const columnCellProps = cell.column.cellProps || {};
const isWrapText =
columnsForWrapText &&
columnsForWrapText.includes(cell.column.Header as string);
const isWrapText = columnsForWrapText?.includes(
cell.column.Header as string,
);
return (
<td

View File

@ -282,25 +282,22 @@ class SliceHeaderControls extends React.PureComponent<
break;
case MENU_KEYS.TOGGLE_CHART_DESCRIPTION:
// eslint-disable-next-line no-unused-expressions
this.props.toggleExpandSlice &&
this.props.toggleExpandSlice(this.props.slice.slice_id);
this.props.toggleExpandSlice?.(this.props.slice.slice_id);
break;
case MENU_KEYS.EXPLORE_CHART:
// eslint-disable-next-line no-unused-expressions
this.props.logExploreChart &&
this.props.logExploreChart(this.props.slice.slice_id);
this.props.logExploreChart?.(this.props.slice.slice_id);
break;
case MENU_KEYS.EXPORT_CSV:
// eslint-disable-next-line no-unused-expressions
this.props.exportCSV && this.props.exportCSV(this.props.slice.slice_id);
this.props.exportCSV?.(this.props.slice.slice_id);
break;
case MENU_KEYS.FULLSCREEN:
this.props.handleToggleFullSize();
break;
case MENU_KEYS.EXPORT_FULL_CSV:
// eslint-disable-next-line no-unused-expressions
this.props.exportFullCSV &&
this.props.exportFullCSV(this.props.slice.slice_id);
this.props.exportFullCSV?.(this.props.slice.slice_id);
break;
case MENU_KEYS.DOWNLOAD_AS_IMAGE: {
// menu closes with a delay, we need to hide it manually,

View File

@ -136,7 +136,7 @@ const FilterControl: React.FC<FilterProps> = ({
{name}
</StyledFilterControlTitle>
{isRequired && <RequiredFieldIndicator />}
{filter.description && filter.description.trim() && (
{filter.description?.trim() && (
<DescriptionToolTip description={filter.description} />
)}
<StyledIcon data-test="filter-icon">{icon}</StyledIcon>

View File

@ -62,10 +62,9 @@ export const useFilterScope = (filter: Filter) => {
if (
filter.scope.excluded.length === 0 &&
(filter.scope.rootPath[0] === DASHBOARD_ROOT_ID ||
(topLevelTabs &&
topLevelTabs.every(topLevelTab =>
filter.scope.rootPath.includes(topLevelTab),
)))
topLevelTabs?.every(topLevelTab =>
filter.scope.rootPath.includes(topLevelTab),
))
) {
return { all: [t('All charts')] };
}

View File

@ -396,7 +396,7 @@ export function FiltersConfigModal({
let array: string[] = [];
if (formItem && 'dependencies' in formItem) {
array = [...formItem.dependencies];
} else if (configItem && configItem.cascadeParentIds) {
} else if (configItem?.cascadeParentIds) {
array = [...configItem.cascadeParentIds];
}
dependencyMap.set(key, array);

View File

@ -209,9 +209,9 @@ export const DashboardPage: FC<PageProps> = ({ idOrSlug }: PageProps) => {
useEffect(() => {
// should convert filter_box to filter component?
const hasFilterBox =
charts &&
charts.some(chart => chart.form_data?.viz_type === 'filter_box');
const hasFilterBox = charts?.some(
chart => chart.form_data?.viz_type === 'filter_box',
);
const canEdit = dashboard && canUserEditDashboard(dashboard, user);
if (canEdit) {

View File

@ -99,10 +99,7 @@ enum FILTER_COMPONENT_FILTER_TYPES {
const getPreselectedValuesFromDashboard =
(preselectedFilters: PreselectedFiltersMeatadata) =>
(filterKey: string, column: string) => {
if (
preselectedFilters[filterKey] &&
preselectedFilters[filterKey][column]
) {
if (preselectedFilters[filterKey]?.[column]) {
// overwrite default values by dashboard default_filters
return preselectedFilters[filterKey][column];
}

View File

@ -151,13 +151,12 @@ const DndFilterSelect = (props: DndFilterSelectProps) => {
endpoint: `/api/v1/database/${dbId}/table_extra/${name}/${schema}/`,
})
.then(({ json }: { json: Record<string, any> }) => {
if (json && json.partitions) {
if (json?.partitions) {
const { partitions } = json;
// for now only show latest_partition option
// when table datasource has only 1 partition key.
if (
partitions &&
partitions.cols &&
partitions?.cols &&
Object.keys(partitions.cols).length === 1
) {
setPartitionColumn(partitions.cols[0]);

View File

@ -158,7 +158,7 @@ export const useSimpleTabFilterProps = (props: Props) => {
} else if (option && 'saved_metric_name' in option) {
subject = option.saved_metric_name;
clause = CLAUSES.HAVING;
} else if (option && option.label) {
} else if (option?.label) {
subject = option.label;
clause = CLAUSES.HAVING;
}

View File

@ -174,7 +174,7 @@ export function getAllControlsState(
getSectionsToRender(vizType, datasourceType).forEach(section =>
section.controlSetRows.forEach(fieldsetRow =>
fieldsetRow.forEach((field: CustomControlItem) => {
if (field && field.config && field.name) {
if (field?.config && field.name) {
const { config, name } = field;
controlsState[name] = getControlStateFromControlConfig(
config,

View File

@ -105,7 +105,7 @@ const getParsedExploreURLPathParams = (pathname: string) =>
Object.keys(EXPLORE_URL_PATH_PARAMS).reduce((acc, currentParam) => {
const re = new RegExp(`/(${currentParam})/(\\w+)`);
const pathGroups = pathname.match(re);
if (pathGroups && pathGroups[2]) {
if (pathGroups?.[2]) {
return { ...acc, [EXPLORE_URL_PATH_PARAMS[currentParam]]: pathGroups[2] };
}
return acc;

View File

@ -228,7 +228,7 @@ export default function PluginFilterSelect(props: PluginFilterSelectProps) {
: null;
// firstItem[0] !== undefined for a case when groupby changed but new data still not fetched
// TODO: still need repopulate default value in config modal when column changed
if (firstItem && firstItem[0] !== undefined) {
if (firstItem?.[0] !== undefined) {
updateDataMask(firstItem);
}
} else if (isDisabled) {

View File

@ -171,7 +171,7 @@ const loadEventsFromApi = async () => {
if (Object.keys(listenersByJobId).length) {
try {
const { result: events } = await fetchEvents(eventArgs);
if (events && events.length) await processEvents(events);
if (events?.length) await processEvents(events);
} catch (err) {
logging.warn(err);
}

View File

@ -52,7 +52,7 @@ if (typeof window !== 'undefined') {
bootstrapData = root
? JSON.parse(root.getAttribute('data-bootstrap') || '{}')
: {};
if (bootstrapData.common && bootstrapData.common.language_pack) {
if (bootstrapData?.common?.language_pack) {
const languagePack = bootstrapData.common.language_pack;
configure({ languagePack });
moment.locale(bootstrapData.common.locale);

View File

@ -52,7 +52,7 @@ function toggleCheckbox(apiUrlPrefix: string, selector: string) {
.then(() => undefined)
.catch(response =>
getClientErrorObject(response).then(parsedResp => {
if (parsedResp && parsedResp.message) {
if (parsedResp?.message) {
showApiMessage(parsedResp);
}
}),

View File

@ -30,7 +30,7 @@ function getDefaultConfiguration(): ClientConfig {
protocol: ['http:', 'https:'].includes(window?.location?.protocol)
? (window?.location?.protocol as 'http:' | 'https:')
: undefined,
host: (window.location && window.location.host) || '',
host: window.location?.host || '',
csrfToken: csrfToken || cookieCSRFToken,
};
}

View File

@ -191,7 +191,7 @@ function AlertList({
const toggleActive = useCallback(
(data: AlertObject, checked: boolean) => {
if (data && data.id) {
if (data?.id) {
const update_id = data.id;
const original = [...alerts];

View File

@ -544,7 +544,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
if (isEditMode) {
// Edit
if (currentAlert && currentAlert.id) {
if (currentAlert?.id) {
const update_id = currentAlert.id;
delete data.id;
@ -664,8 +664,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
[],
);
const databaseLabel =
currentAlert && currentAlert.database && !currentAlert.database.label;
const databaseLabel = currentAlert?.database && !currentAlert.database.label;
useEffect(() => {
// Find source if current alert has one set
if (databaseLabel) {
@ -738,8 +737,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
[chartOptions, currentAlert?.chart],
);
const noChartLabel =
currentAlert && currentAlert.chart && !currentAlert.chart.label;
const noChartLabel = currentAlert?.chart && !currentAlert?.chart.label;
useEffect(() => {
// Find source if current alert has one set
if (noChartLabel) {
@ -899,13 +897,12 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
const validate = () => {
if (
currentAlert &&
currentAlert.name?.length &&
currentAlert.owners?.length &&
currentAlert.crontab?.length &&
currentAlert.working_timeout !== undefined &&
((contentType === 'dashboard' && !!currentAlert.dashboard) ||
(contentType === 'chart' && !!currentAlert.chart)) &&
currentAlert?.name?.length &&
currentAlert?.owners?.length &&
currentAlert?.crontab?.length &&
currentAlert?.working_timeout !== undefined &&
((contentType === 'dashboard' && !!currentAlert?.dashboard) ||
(contentType === 'chart' && !!currentAlert?.chart)) &&
checkNotificationSettings()
) {
if (isReport) {
@ -932,7 +929,7 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
isEditMode &&
(!currentAlert?.id || alert?.id !== currentAlert.id || (isHidden && show))
) {
if (alert && alert.id !== null && !loading && !fetchError) {
if (alert?.id !== null && !loading && !fetchError) {
const id = alert.id || 0;
fetchResource(id);
}
@ -1214,10 +1211,8 @@ const AlertReportModal: FunctionComponent<AlertReportModalProps> = ({
name="threshold"
disabled={conditionNotNull}
value={
currentAlert &&
currentAlert.validator_config_json &&
currentAlert.validator_config_json.threshold !==
undefined
currentAlert?.validator_config_json?.threshold !==
undefined
? currentAlert.validator_config_json.threshold
: ''
}

View File

@ -130,7 +130,7 @@ const AnnotationModal: FunctionComponent<AnnotationModalProps> = ({
const onSave = () => {
if (isEditMode) {
// Edit
if (currentAnnotation && currentAnnotation.id) {
if (currentAnnotation?.id) {
const update_id = currentAnnotation.id;
delete currentAnnotation.id;
delete currentAnnotation.created_by;
@ -217,10 +217,9 @@ const AnnotationModal: FunctionComponent<AnnotationModalProps> = ({
const validate = () => {
if (
currentAnnotation &&
currentAnnotation.short_descr?.length &&
currentAnnotation.start_dttm?.length &&
currentAnnotation.end_dttm?.length
currentAnnotation?.short_descr?.length &&
currentAnnotation?.start_dttm?.length &&
currentAnnotation?.end_dttm?.length
) {
setDisableSave(false);
} else {
@ -237,7 +236,7 @@ const AnnotationModal: FunctionComponent<AnnotationModalProps> = ({
(annotation && annotation.id !== currentAnnotation.id) ||
show)
) {
if (annotation && annotation.id !== null && !loading) {
if (annotation?.id !== null && !loading) {
const id = annotation.id || 0;
fetchResource(id);
@ -337,7 +336,7 @@ const AnnotationModal: FunctionComponent<AnnotationModalProps> = ({
<StyledJsonEditor
onChange={onJsonChange}
value={
currentAnnotation && currentAnnotation.json_metadata
currentAnnotation?.json_metadata
? currentAnnotation.json_metadata
: ''
}

View File

@ -126,7 +126,7 @@ const AnnotationLayerModal: FunctionComponent<AnnotationLayerModalProps> = ({
const onSave = () => {
if (isEditMode) {
// Edit
if (currentLayer && currentLayer.id) {
if (currentLayer?.id) {
const update_id = currentLayer.id;
delete currentLayer.id;
delete currentLayer.created_by;
@ -173,7 +173,7 @@ const AnnotationLayerModal: FunctionComponent<AnnotationLayerModalProps> = ({
};
const validate = () => {
if (currentLayer && currentLayer.name?.length) {
if (currentLayer?.name?.length) {
setDisableSave(false);
} else {
setDisableSave(true);

View File

@ -101,7 +101,7 @@ const CssTemplateModal: FunctionComponent<CssTemplateModalProps> = ({
const onSave = () => {
if (isEditMode) {
// Edit
if (currentCssTemplate && currentCssTemplate.id) {
if (currentCssTemplate?.id) {
const update_id = currentCssTemplate.id;
delete currentCssTemplate.id;
delete currentCssTemplate.created_by;
@ -157,10 +157,8 @@ const CssTemplateModal: FunctionComponent<CssTemplateModalProps> = ({
const validate = () => {
if (
currentCssTemplate &&
currentCssTemplate.template_name.length &&
currentCssTemplate.css &&
currentCssTemplate.css.length
currentCssTemplate?.template_name.length &&
currentCssTemplate?.css?.length
) {
setDisableSave(false);
} else {
@ -174,10 +172,10 @@ const CssTemplateModal: FunctionComponent<CssTemplateModalProps> = ({
isEditMode &&
(!currentCssTemplate ||
!currentCssTemplate.id ||
(cssTemplate && cssTemplate.id !== currentCssTemplate.id) ||
(cssTemplate && cssTemplate?.id !== currentCssTemplate.id) ||
(isHidden && show))
) {
if (cssTemplate && cssTemplate.id !== null && !loading) {
if (cssTemplate?.id !== null && !loading) {
const id = cssTemplate.id || 0;
fetchResource(id);

View File

@ -78,9 +78,7 @@ function DashboardCard({
role="button"
tabIndex={0}
className="action-button"
onClick={() =>
openDashboardEditModal && openDashboardEditModal(dashboard)
}
onClick={() => openDashboardEditModal?.(dashboard)}
data-test="dashboard-card-option-edit-button"
>
<Icons.EditAlt iconSize="l" data-test="edit-alt" /> {t('Edit')}

View File

@ -227,10 +227,8 @@ export function createErrorHandler(
const errorsArray = parsedError?.errors;
const config = await SupersetText;
if (
errorsArray &&
errorsArray.length &&
config &&
config.ERRORS &&
errorsArray?.length &&
config?.ERRORS &&
errorsArray[0].error_type in config.ERRORS
) {
parsedError.message = config.ERRORS[errorsArray[0].error_type];

View File

@ -287,7 +287,7 @@ const RightMenu = ({
onDatabaseAdd={handleDatabaseAdd}
/>
)}
{environmentTag && environmentTag.text && (
{environmentTag?.text && (
<Label
css={{ borderRadius: `${theme.gridUnit * 125}px` }}
color={