Skip to content

Commit 3e7611b

Browse files
authored
[Cases] Add eslintrule to enforce display names and ignore existing problems (elastic#123692)
1 parent f77355b commit 3e7611b

File tree

13 files changed

+671
-624
lines changed

13 files changed

+671
-624
lines changed

.eslintrc.js

+7
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,13 @@ module.exports = {
10701070
'@typescript-eslint/no-duplicate-imports': ['error'],
10711071
},
10721072
},
1073+
{
1074+
files: ['x-pack/plugins/cases/public/**/*.{js,mjs,ts,tsx}'],
1075+
excludedFiles: ['x-pack/plugins/cases/**/*.{test,mock,test_helper}.{ts,tsx}'],
1076+
rules: {
1077+
'react/display-name': ['error', { ignoreTranspilerName: true }],
1078+
},
1079+
},
10731080

10741081
/**
10751082
* Lists overrides. These rules below are maintained and owned by

x-pack/plugins/cases/public/common/mock/test_providers.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ export const createAppMockRenderer = ({
7979
</KibanaContextProvider>
8080
</I18nProvider>
8181
);
82+
AppWrapper.displayName = 'AppWrapper';
8283
const render: UiRender = (ui, options) => {
8384
return reactRender(ui, {
8485
wrapper: AppWrapper as React.ComponentType,

x-pack/plugins/cases/public/components/connectors/resilient/case_fields.tsx

+151-150
Original file line numberDiff line numberDiff line change
@@ -24,164 +24,165 @@ import * as i18n from './translations';
2424
import { ConnectorTypes, ResilientFieldsType } from '../../../../common/api';
2525
import { ConnectorCard } from '../card';
2626

27-
const ResilientFieldsComponent: React.FunctionComponent<
28-
ConnectorFieldsProps<ResilientFieldsType>
29-
> = ({ isEdit = true, fields, connector, onChange }) => {
30-
const init = useRef(true);
31-
const { incidentTypes = null, severityCode = null } = fields ?? {};
32-
33-
const { http, notifications } = useKibana().services;
27+
const ResilientFieldsComponent: React.FunctionComponent<ConnectorFieldsProps<ResilientFieldsType>> =
28+
// TODO: Fix this manually. Issue #123375
29+
// eslint-disable-next-line react/display-name
30+
({ isEdit = true, fields, connector, onChange }) => {
31+
const init = useRef(true);
32+
const { incidentTypes = null, severityCode = null } = fields ?? {};
33+
34+
const { http, notifications } = useKibana().services;
35+
36+
const { isLoading: isLoadingIncidentTypes, incidentTypes: allIncidentTypes } =
37+
useGetIncidentTypes({
38+
http,
39+
toastNotifications: notifications.toasts,
40+
connector,
41+
});
3442

35-
const { isLoading: isLoadingIncidentTypes, incidentTypes: allIncidentTypes } =
36-
useGetIncidentTypes({
43+
const { isLoading: isLoadingSeverity, severity } = useGetSeverity({
3744
http,
3845
toastNotifications: notifications.toasts,
3946
connector,
4047
});
4148

42-
const { isLoading: isLoadingSeverity, severity } = useGetSeverity({
43-
http,
44-
toastNotifications: notifications.toasts,
45-
connector,
46-
});
47-
48-
const severitySelectOptions: EuiSelectOption[] = useMemo(
49-
() =>
50-
severity.map((s) => ({
51-
value: s.id.toString(),
52-
text: s.name,
53-
})),
54-
[severity]
55-
);
56-
57-
const incidentTypesComboBoxOptions: Array<EuiComboBoxOptionOption<string>> = useMemo(
58-
() =>
59-
allIncidentTypes
60-
? allIncidentTypes.map((type: { id: number; name: string }) => ({
61-
label: type.name,
62-
value: type.id.toString(),
63-
}))
64-
: [],
65-
[allIncidentTypes]
66-
);
67-
const listItems = useMemo(
68-
() => [
69-
...(incidentTypes != null && incidentTypes.length > 0
70-
? [
71-
{
72-
title: i18n.INCIDENT_TYPES_LABEL,
73-
description: allIncidentTypes
74-
.filter((type) => incidentTypes.includes(type.id.toString()))
75-
.map((type) => type.name)
76-
.join(', '),
77-
},
78-
]
79-
: []),
80-
...(severityCode != null && severityCode.length > 0
81-
? [
82-
{
83-
title: i18n.SEVERITY_LABEL,
84-
description:
85-
severity.find((severityObj) => severityObj.id.toString() === severityCode)?.name ??
86-
'',
87-
},
88-
]
89-
: []),
90-
],
91-
[incidentTypes, severityCode, allIncidentTypes, severity]
92-
);
93-
94-
const onFieldChange = useCallback(
95-
(key, value) => {
96-
onChange({
97-
...fields,
98-
incidentTypes,
99-
severityCode,
100-
[key]: value,
101-
});
102-
},
103-
[incidentTypes, severityCode, onChange, fields]
104-
);
105-
106-
const selectedIncidentTypesComboBoxOptionsMemo = useMemo(() => {
107-
const allIncidentTypesAsObject = allIncidentTypes.reduce(
108-
(acc, type) => ({ ...acc, [type.id.toString()]: type.name }),
109-
{} as Record<string, string>
49+
const severitySelectOptions: EuiSelectOption[] = useMemo(
50+
() =>
51+
severity.map((s) => ({
52+
value: s.id.toString(),
53+
text: s.name,
54+
})),
55+
[severity]
56+
);
57+
58+
const incidentTypesComboBoxOptions: Array<EuiComboBoxOptionOption<string>> = useMemo(
59+
() =>
60+
allIncidentTypes
61+
? allIncidentTypes.map((type: { id: number; name: string }) => ({
62+
label: type.name,
63+
value: type.id.toString(),
64+
}))
65+
: [],
66+
[allIncidentTypes]
67+
);
68+
const listItems = useMemo(
69+
() => [
70+
...(incidentTypes != null && incidentTypes.length > 0
71+
? [
72+
{
73+
title: i18n.INCIDENT_TYPES_LABEL,
74+
description: allIncidentTypes
75+
.filter((type) => incidentTypes.includes(type.id.toString()))
76+
.map((type) => type.name)
77+
.join(', '),
78+
},
79+
]
80+
: []),
81+
...(severityCode != null && severityCode.length > 0
82+
? [
83+
{
84+
title: i18n.SEVERITY_LABEL,
85+
description:
86+
severity.find((severityObj) => severityObj.id.toString() === severityCode)
87+
?.name ?? '',
88+
},
89+
]
90+
: []),
91+
],
92+
[incidentTypes, severityCode, allIncidentTypes, severity]
11093
);
111-
return incidentTypes
112-
? incidentTypes
113-
.map((type) => ({
114-
label: allIncidentTypesAsObject[type.toString()],
115-
value: type.toString(),
116-
}))
117-
.filter((type) => type.label != null)
118-
: [];
119-
}, [allIncidentTypes, incidentTypes]);
120-
121-
const onIncidentChange = useCallback(
122-
(selectedOptions: Array<{ label: string; value?: string }>) => {
123-
onFieldChange(
124-
'incidentTypes',
125-
selectedOptions.map((selectedOption) => selectedOption.value ?? selectedOption.label)
94+
95+
const onFieldChange = useCallback(
96+
(key, value) => {
97+
onChange({
98+
...fields,
99+
incidentTypes,
100+
severityCode,
101+
[key]: value,
102+
});
103+
},
104+
[incidentTypes, severityCode, onChange, fields]
105+
);
106+
107+
const selectedIncidentTypesComboBoxOptionsMemo = useMemo(() => {
108+
const allIncidentTypesAsObject = allIncidentTypes.reduce(
109+
(acc, type) => ({ ...acc, [type.id.toString()]: type.name }),
110+
{} as Record<string, string>
126111
);
127-
},
128-
[onFieldChange]
129-
);
130-
131-
const onIncidentBlur = useCallback(() => {
132-
if (!incidentTypes) {
133-
onFieldChange('incidentTypes', []);
134-
}
135-
}, [incidentTypes, onFieldChange]);
136-
137-
// Set field at initialization
138-
useEffect(() => {
139-
if (init.current) {
140-
init.current = false;
141-
onChange({ incidentTypes, severityCode });
142-
}
143-
}, [incidentTypes, onChange, severityCode]);
144-
145-
return isEdit ? (
146-
<span data-test-subj={'connector-fields-resilient'}>
147-
<EuiFormRow fullWidth label={i18n.INCIDENT_TYPES_LABEL}>
148-
<EuiComboBox
149-
data-test-subj="incidentTypeComboBox"
150-
fullWidth
151-
isClearable={true}
152-
isDisabled={isLoadingIncidentTypes}
153-
isLoading={isLoadingIncidentTypes}
154-
onBlur={onIncidentBlur}
155-
onChange={onIncidentChange}
156-
options={incidentTypesComboBoxOptions}
157-
placeholder={i18n.INCIDENT_TYPES_PLACEHOLDER}
158-
selectedOptions={selectedIncidentTypesComboBoxOptionsMemo}
159-
/>
160-
</EuiFormRow>
161-
<EuiSpacer size="m" />
162-
<EuiFormRow fullWidth label={i18n.SEVERITY_LABEL}>
163-
<EuiSelect
164-
data-test-subj="severitySelect"
165-
disabled={isLoadingSeverity}
166-
fullWidth
167-
hasNoInitialSelection
168-
isLoading={isLoadingSeverity}
169-
onChange={(e) => onFieldChange('severityCode', e.target.value)}
170-
options={severitySelectOptions}
171-
value={severityCode ?? undefined}
172-
/>
173-
</EuiFormRow>
174-
<EuiSpacer size="m" />
175-
</span>
176-
) : (
177-
<ConnectorCard
178-
connectorType={ConnectorTypes.resilient}
179-
isLoading={isLoadingIncidentTypes || isLoadingSeverity}
180-
listItems={listItems}
181-
title={connector.name}
182-
/>
183-
);
184-
};
112+
return incidentTypes
113+
? incidentTypes
114+
.map((type) => ({
115+
label: allIncidentTypesAsObject[type.toString()],
116+
value: type.toString(),
117+
}))
118+
.filter((type) => type.label != null)
119+
: [];
120+
}, [allIncidentTypes, incidentTypes]);
121+
122+
const onIncidentChange = useCallback(
123+
(selectedOptions: Array<{ label: string; value?: string }>) => {
124+
onFieldChange(
125+
'incidentTypes',
126+
selectedOptions.map((selectedOption) => selectedOption.value ?? selectedOption.label)
127+
);
128+
},
129+
[onFieldChange]
130+
);
131+
132+
const onIncidentBlur = useCallback(() => {
133+
if (!incidentTypes) {
134+
onFieldChange('incidentTypes', []);
135+
}
136+
}, [incidentTypes, onFieldChange]);
137+
138+
// Set field at initialization
139+
useEffect(() => {
140+
if (init.current) {
141+
init.current = false;
142+
onChange({ incidentTypes, severityCode });
143+
}
144+
}, [incidentTypes, onChange, severityCode]);
145+
146+
return isEdit ? (
147+
<span data-test-subj={'connector-fields-resilient'}>
148+
<EuiFormRow fullWidth label={i18n.INCIDENT_TYPES_LABEL}>
149+
<EuiComboBox
150+
data-test-subj="incidentTypeComboBox"
151+
fullWidth
152+
isClearable={true}
153+
isDisabled={isLoadingIncidentTypes}
154+
isLoading={isLoadingIncidentTypes}
155+
onBlur={onIncidentBlur}
156+
onChange={onIncidentChange}
157+
options={incidentTypesComboBoxOptions}
158+
placeholder={i18n.INCIDENT_TYPES_PLACEHOLDER}
159+
selectedOptions={selectedIncidentTypesComboBoxOptionsMemo}
160+
/>
161+
</EuiFormRow>
162+
<EuiSpacer size="m" />
163+
<EuiFormRow fullWidth label={i18n.SEVERITY_LABEL}>
164+
<EuiSelect
165+
data-test-subj="severitySelect"
166+
disabled={isLoadingSeverity}
167+
fullWidth
168+
hasNoInitialSelection
169+
isLoading={isLoadingSeverity}
170+
onChange={(e) => onFieldChange('severityCode', e.target.value)}
171+
options={severitySelectOptions}
172+
value={severityCode ?? undefined}
173+
/>
174+
</EuiFormRow>
175+
<EuiSpacer size="m" />
176+
</span>
177+
) : (
178+
<ConnectorCard
179+
connectorType={ConnectorTypes.resilient}
180+
isLoading={isLoadingIncidentTypes || isLoadingSeverity}
181+
listItems={listItems}
182+
title={connector.name}
183+
/>
184+
);
185+
};
185186

186187
// eslint-disable-next-line import/no-default-export
187188
export { ResilientFieldsComponent as default };

0 commit comments

Comments
 (0)