Skip to content

Commit 74536b3

Browse files
authored
chore: Add @eslint-react/eslint-plugin recommended rules (#2069)
1 parent 24767c5 commit 74536b3

12 files changed

+157
-152
lines changed

packages/app/eslint.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ export default [
122122
...nextPlugin.configs.recommended.rules,
123123
...nextPlugin.configs['core-web-vitals'].rules,
124124
...reactHooksPlugin.configs.recommended.rules,
125+
...eslintReactPlugin.configs.recommended.rules,
126+
// Disable rules from eslint-plugin-react-hooks that have equivalent rules in @eslint-react
127+
...eslintReactPlugin.configs['disable-conflict-eslint-plugin-react-hooks'].rules,
128+
...eslintReactPlugin.configs['recommended-type-checked'].rules,
125129
'react-hooks/set-state-in-effect': 'warn',
126130
'react-hooks/exhaustive-deps': 'error',
127131
'react-hook-form/no-use-watch': 'error',
@@ -206,6 +210,7 @@ export default [
206210
rules: {
207211
// Drop date rules — new Date() / Date.now() are fine in tests
208212
'no-restricted-syntax': ['error', ...UI_SYNTAX_RESTRICTIONS],
213+
'@eslint-react/component-hook-factories': 'off',
209214
},
210215
},
211216
{

packages/app/src/ClickhousePage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ function InsertsTab({
368368
}
369369
toolbarPrefix={[
370370
<SegmentedControl
371+
key="inserts-by-toolbar"
371372
size="xs"
372373
value={insertsBy ?? 'queries'}
373374
onChange={value => {

packages/app/src/DBSearchPage.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
FormEvent,
33
FormEventHandler,
4+
Fragment,
45
memo,
56
useCallback,
67
useEffect,
@@ -2005,7 +2006,7 @@ function DBSearchPage() {
20052006
</Text>
20062007
<Grid>
20072008
{whereSuggestions!.map(s => (
2008-
<>
2009+
<Fragment key={s.corrected()}>
20092010
<Grid.Col span={10}>
20102011
<Text>{s.userMessage('where')}</Text>
20112012
</Grid.Col>
@@ -2018,7 +2019,7 @@ function DBSearchPage() {
20182019
Accept
20192020
</Button>
20202021
</Grid.Col>
2021-
</>
2022+
</Fragment>
20222023
))}
20232024
</Grid>
20242025
</Box>

packages/app/src/HDXMultiSeriesTimeChart.tsx

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,20 @@ const LegendRenderer = memo<{
309309

310310
export const HARD_LINES_LIMIT = 60;
311311

312+
const StackedBarWithOverlap = (props: BarProps) => {
313+
const { x, y, width, height, fill } = props;
314+
// Add a tiny bit to the height to create overlap. Otherwise there's a gap
315+
return (
316+
<rect
317+
x={x}
318+
y={y}
319+
width={width}
320+
height={height && height > 0 ? height + 0.5 : 0}
321+
fill={fill}
322+
/>
323+
);
324+
};
325+
312326
export const MemoChart = memo(function MemoChart({
313327
graphResults,
314328
setIsClickActive,
@@ -375,20 +389,6 @@ export const MemoChart = memo(function MemoChart({
375389
const strokeDasharray = lineData[lineDataIndex]?.isDashed ? '4 3' : '0';
376390
const seriesName = lineData[lineDataIndex]?.displayName ?? key;
377391

378-
const StackedBarWithOverlap = (props: BarProps) => {
379-
const { x, y, width, height, fill } = props;
380-
// Add a tiny bit to the height to create overlap. Otherwise there's a gap
381-
return (
382-
<rect
383-
x={x}
384-
y={y}
385-
width={width}
386-
height={height && height > 0 ? height + 0.5 : 0}
387-
fill={fill}
388-
/>
389-
);
390-
};
391-
392392
return displayType === 'stacked_bar' ? (
393393
<Bar
394394
key={key}

packages/app/src/LogSidePanelElements.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export const SectionWrapper: React.FC<
5858
React.PropsWithChildren<{ title?: React.ReactNode }>
5959
> = ({ children, title }) => (
6060
<div className={styles.panelSectionWrapper}>
61-
{title && <div className={styles.panelSectionWrapperTitle}>{title}</div>}
61+
{!!title && <div className={styles.panelSectionWrapperTitle}>{title}</div>}
6262
{children}
6363
</div>
6464
);

packages/app/src/UserPreferencesModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ const SettingContainer = ({
4343
<Group align="center" justify="space-between">
4444
<div style={{ flex: 1 }}>
4545
{label}
46-
{description && (
46+
{!!description && (
4747
<Text size="xs" mt={2}>
4848
{description}
4949
</Text>

packages/app/src/__tests__/timeQuery.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable @eslint-react/no-create-ref */
12
import * as React from 'react';
23
import { useImperativeHandle } from 'react';
34
import { useRouter } from 'next/router';

packages/app/src/components/DBDeltaChart.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ export default function DBDeltaChart({
478478
{/* Legend */}
479479
<Flex gap="md" align="center" mt={2} mb="xs" wrap="wrap">
480480
{legendPrefix}
481-
{legendPrefix && (
481+
{!!legendPrefix && (
482482
<Box
483483
h={12}
484484
style={{

packages/app/src/components/DBSearchPageFilters.tsx

Lines changed: 125 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,11 @@ const DBSearchPageFiltersComponent = ({
13291329
);
13301330
}, [filterState, source, parentSpanIdExpr]);
13311331

1332+
const { grouped, nonGrouped } = useMemo(
1333+
() => groupFacetsByBaseName(shownFacets),
1334+
[shownFacets],
1335+
);
1336+
13321337
return (
13331338
<Box className={classes.filtersPanel} style={{ width: `${size}%` }}>
13341339
<div className={resizeStyles.resizeHandle} onMouseDown={startResize} />
@@ -1480,135 +1485,127 @@ const DBSearchPageFiltersComponent = ({
14801485
)
14811486
)}
14821487
{/* Show facets even when loading to ensure pinned filters are visible while loading */}
1483-
{(() => {
1484-
const { grouped, nonGrouped } = groupFacetsByBaseName(shownFacets);
1485-
1486-
return (
1487-
<>
1488-
{/* Render grouped facets as nested filter groups */}
1489-
{grouped.map(group => (
1490-
<NestedFilterGroup
1491-
key={group.key}
1492-
data-testid={`nested-filter-group-${group.key}`}
1493-
name={group.key}
1494-
childFilters={group.children}
1495-
selectedValues={group.children.reduce(
1496-
(acc, child) => {
1497-
acc[child.key] = filterState[child.key]
1498-
? filterState[child.key]
1499-
: { included: new Set(), excluded: new Set() };
1500-
return acc;
1501-
},
1502-
{} as Record<
1503-
string,
1504-
{
1505-
included: Set<string | boolean>;
1506-
excluded: Set<string | boolean>;
1507-
}
1508-
>,
1509-
)}
1510-
onChange={(key, value) => {
1511-
setFilterValue(key, value);
1512-
}}
1513-
onClearClick={key => clearFilter(key)}
1514-
onOnlyClick={(key, value) => {
1515-
setFilterValue(key, value, 'only');
1516-
}}
1517-
onExcludeClick={(key, value) => {
1518-
setFilterValue(key, value, 'exclude');
1519-
}}
1520-
onPinClick={(key, value) => toggleFilterPin(key, value)}
1521-
isPinned={(key, value) => isFilterPinned(key, value)}
1522-
onFieldPinClick={key => toggleFieldPin(key)}
1523-
isFieldPinned={key => isFieldPinned(key)}
1524-
onColumnToggle={onColumnToggle}
1525-
displayedColumns={displayedColumns}
1526-
onLoadMore={loadMoreFilterValuesForKey}
1527-
loadMoreLoading={group.children.reduce(
1528-
(acc, child) => {
1529-
acc[child.key] = loadMoreLoadingKeys.has(child.key);
1530-
return acc;
1531-
},
1532-
{} as Record<string, boolean>,
1533-
)}
1534-
hasLoadedMore={group.children.reduce(
1535-
(acc, child) => {
1536-
acc[child.key] = Boolean(extraFacets[child.key]);
1537-
return acc;
1538-
},
1539-
{} as Record<string, boolean>,
1540-
)}
1541-
isDefaultExpanded={
1542-
// open by default if has selected values or pinned children
1543-
group.children.some(
1544-
child =>
1545-
(filterState[child.key] &&
1546-
(filterState[child.key].included.size > 0 ||
1547-
filterState[child.key].excluded.size > 0)) ||
1548-
isFieldPinned(child.key),
1549-
)
1550-
}
1551-
chartConfig={chartConfig}
1552-
isLive={isLive}
1553-
/>
1554-
))}
1555-
1556-
{/* Render non-grouped facets as regular filter groups */}
1557-
{nonGrouped.map(facet => (
1558-
<FilterGroup
1559-
key={facet.key}
1560-
data-testid={`filter-group-${facet.key}`}
1561-
name={cleanedFacetName(facet.key)}
1562-
options={facet.value.map(value => ({
1563-
value,
1564-
label: value.toString(),
1565-
}))}
1566-
optionsLoading={isFacetsLoading}
1567-
selectedValues={
1568-
filterState[facet.key]
1569-
? filterState[facet.key]
1570-
: { included: new Set(), excluded: new Set() }
1571-
}
1572-
onChange={value => {
1573-
setFilterValue(facet.key, value);
1574-
}}
1575-
onClearClick={() => clearFilter(facet.key)}
1576-
onOnlyClick={value => {
1577-
setFilterValue(facet.key, value, 'only');
1578-
}}
1579-
onExcludeClick={value => {
1580-
setFilterValue(facet.key, value, 'exclude');
1581-
}}
1582-
onPinClick={value => toggleFilterPin(facet.key, value)}
1583-
isPinned={value => isFilterPinned(facet.key, value)}
1584-
onFieldPinClick={() => toggleFieldPin(facet.key)}
1585-
isFieldPinned={isFieldPinned(facet.key)}
1586-
onColumnToggle={
1587-
onColumnToggle
1588-
? () => onColumnToggle(facet.key)
1589-
: undefined
1590-
}
1591-
isColumnDisplayed={displayedColumns?.includes(facet.key)}
1592-
onLoadMore={loadMoreFilterValuesForKey}
1593-
loadMoreLoading={loadMoreLoadingKeys.has(facet.key)}
1594-
hasLoadedMore={Boolean(extraFacets[facet.key])}
1595-
isDefaultExpanded={
1596-
// open by default if PK, or has selected values
1597-
isFieldPrimary(tableMetadata, facet.key) ||
1598-
isFieldPinned(facet.key) ||
1599-
(filterState[facet.key] &&
1600-
(filterState[facet.key].included.size > 0 ||
1601-
filterState[facet.key].excluded.size > 0 ||
1602-
filterState[facet.key].range != null))
1488+
<>
1489+
{/* Render grouped facets as nested filter groups */}
1490+
{grouped.map(group => (
1491+
<NestedFilterGroup
1492+
key={group.key}
1493+
data-testid={`nested-filter-group-${group.key}`}
1494+
name={group.key}
1495+
childFilters={group.children}
1496+
selectedValues={group.children.reduce(
1497+
(acc, child) => {
1498+
acc[child.key] = filterState[child.key]
1499+
? filterState[child.key]
1500+
: { included: new Set(), excluded: new Set() };
1501+
return acc;
1502+
},
1503+
{} as Record<
1504+
string,
1505+
{
1506+
included: Set<string | boolean>;
1507+
excluded: Set<string | boolean>;
16031508
}
1604-
chartConfig={chartConfig}
1605-
isLive={isLive}
1606-
onRangeChange={range => setFilterRange(facet.key, range)}
1607-
/>
1608-
))}
1609-
</>
1610-
);
1611-
})()}
1509+
>,
1510+
)}
1511+
onChange={(key, value) => {
1512+
setFilterValue(key, value);
1513+
}}
1514+
onClearClick={key => clearFilter(key)}
1515+
onOnlyClick={(key, value) => {
1516+
setFilterValue(key, value, 'only');
1517+
}}
1518+
onExcludeClick={(key, value) => {
1519+
setFilterValue(key, value, 'exclude');
1520+
}}
1521+
onPinClick={(key, value) => toggleFilterPin(key, value)}
1522+
isPinned={(key, value) => isFilterPinned(key, value)}
1523+
onFieldPinClick={key => toggleFieldPin(key)}
1524+
isFieldPinned={key => isFieldPinned(key)}
1525+
onColumnToggle={onColumnToggle}
1526+
displayedColumns={displayedColumns}
1527+
onLoadMore={loadMoreFilterValuesForKey}
1528+
loadMoreLoading={group.children.reduce(
1529+
(acc, child) => {
1530+
acc[child.key] = loadMoreLoadingKeys.has(child.key);
1531+
return acc;
1532+
},
1533+
{} as Record<string, boolean>,
1534+
)}
1535+
hasLoadedMore={group.children.reduce(
1536+
(acc, child) => {
1537+
acc[child.key] = Boolean(extraFacets[child.key]);
1538+
return acc;
1539+
},
1540+
{} as Record<string, boolean>,
1541+
)}
1542+
isDefaultExpanded={
1543+
// open by default if has selected values or pinned children
1544+
group.children.some(
1545+
child =>
1546+
(filterState[child.key] &&
1547+
(filterState[child.key].included.size > 0 ||
1548+
filterState[child.key].excluded.size > 0)) ||
1549+
isFieldPinned(child.key),
1550+
)
1551+
}
1552+
chartConfig={chartConfig}
1553+
isLive={isLive}
1554+
/>
1555+
))}
1556+
1557+
{/* Render non-grouped facets as regular filter groups */}
1558+
{nonGrouped.map(facet => (
1559+
<FilterGroup
1560+
key={facet.key}
1561+
data-testid={`filter-group-${facet.key}`}
1562+
name={cleanedFacetName(facet.key)}
1563+
options={facet.value.map(value => ({
1564+
value,
1565+
label: value.toString(),
1566+
}))}
1567+
optionsLoading={isFacetsLoading}
1568+
selectedValues={
1569+
filterState[facet.key]
1570+
? filterState[facet.key]
1571+
: { included: new Set(), excluded: new Set() }
1572+
}
1573+
onChange={value => {
1574+
setFilterValue(facet.key, value);
1575+
}}
1576+
onClearClick={() => clearFilter(facet.key)}
1577+
onOnlyClick={value => {
1578+
setFilterValue(facet.key, value, 'only');
1579+
}}
1580+
onExcludeClick={value => {
1581+
setFilterValue(facet.key, value, 'exclude');
1582+
}}
1583+
onPinClick={value => toggleFilterPin(facet.key, value)}
1584+
isPinned={value => isFilterPinned(facet.key, value)}
1585+
onFieldPinClick={() => toggleFieldPin(facet.key)}
1586+
isFieldPinned={isFieldPinned(facet.key)}
1587+
onColumnToggle={
1588+
onColumnToggle ? () => onColumnToggle(facet.key) : undefined
1589+
}
1590+
isColumnDisplayed={displayedColumns?.includes(facet.key)}
1591+
onLoadMore={loadMoreFilterValuesForKey}
1592+
loadMoreLoading={loadMoreLoadingKeys.has(facet.key)}
1593+
hasLoadedMore={Boolean(extraFacets[facet.key])}
1594+
isDefaultExpanded={
1595+
// open by default if PK, or has selected values
1596+
isFieldPrimary(tableMetadata, facet.key) ||
1597+
isFieldPinned(facet.key) ||
1598+
(filterState[facet.key] &&
1599+
(filterState[facet.key].included.size > 0 ||
1600+
filterState[facet.key].excluded.size > 0 ||
1601+
filterState[facet.key].range != null))
1602+
}
1603+
chartConfig={chartConfig}
1604+
isLive={isLive}
1605+
onRangeChange={range => setFilterRange(facet.key, range)}
1606+
/>
1607+
))}
1608+
</>
16121609

16131610
<Button
16141611
variant="secondary"

0 commit comments

Comments
 (0)