@centreon/ui 23.10.91 → 23.10.92

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centreon/ui",
3
- "version": "23.10.91",
3
+ "version": "23.10.92",
4
4
  "description": "Centreon UI Components",
5
5
  "scripts": {
6
6
  "eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx --max-warnings 0",
@@ -67,21 +67,23 @@ const mountListing = (): void => {
67
67
 
68
68
  cy.mount({
69
69
  Component: (
70
- <Listing
71
- checkable
72
- columns={columnsWithSubItems}
73
- currentPage={1}
74
- limit={10}
75
- rows={listingWithSubItems}
76
- subItems={{
77
- canCheckSubItems: false,
78
- enable: true,
79
- labelCollapse: 'Collapse',
80
- labelExpand: 'Expand',
81
- rowProperty: 'subItems'
82
- }}
83
- totalRows={10}
84
- />
70
+ <div style={{ height: '100vh' }}>
71
+ <Listing
72
+ checkable
73
+ columns={columnsWithSubItems}
74
+ currentPage={1}
75
+ limit={10}
76
+ rows={listingWithSubItems}
77
+ subItems={{
78
+ canCheckSubItems: false,
79
+ enable: true,
80
+ labelCollapse: 'Collapse',
81
+ labelExpand: 'Expand',
82
+ rowProperty: 'subItems'
83
+ }}
84
+ totalRows={10}
85
+ />
86
+ </div>
85
87
  )
86
88
  });
87
89
  };
@@ -30,6 +30,11 @@ const useListingStyles = makeStyles<StylesProps>()(
30
30
  height: '100%',
31
31
  width: '100%'
32
32
  },
33
+ listingContainer: {
34
+ height: '100%',
35
+ overflow: 'hidden',
36
+ width: '100%'
37
+ },
33
38
  loadingIndicator: {
34
39
  height: loadingIndicatorHeight,
35
40
  width: '100%'
@@ -34,7 +34,8 @@ type Story = StoryObj<typeof Listing>;
34
34
 
35
35
  const useStyles = makeStyles()((theme) => ({
36
36
  listing: {
37
- backgroundColor: theme.palette.background.default
37
+ backgroundColor: theme.palette.background.default,
38
+ height: '100vh'
38
39
  }
39
40
  }));
40
41
 
@@ -35,12 +35,12 @@ import { Box, LinearProgress, Table, TableBody } from '@mui/material';
35
35
  import { ListingVariant } from '@centreon/ui-context';
36
36
 
37
37
  import { useKeyObserver, useMemoComponent } from '../utils';
38
+ import { ParentSize } from '..';
38
39
 
39
40
  import ListingActionBar from './ActionBar';
40
41
  import Cell from './Cell';
41
42
  import DataCell from './Cell/DataCell';
42
43
  import Checkbox from './Checkbox';
43
- import getCumulativeOffset from './getCumulativeOffset';
44
44
  import {
45
45
  Column,
46
46
  ColumnConfiguration,
@@ -51,9 +51,8 @@ import {
51
51
  } from './models';
52
52
  import ListingRow from './Row/Row';
53
53
  import { labelNoResultFound } from './translatedLabels';
54
- import useResizeObserver from './useResizeObserver';
55
54
  import useStyleTable from './useStyleTable';
56
- import { loadingIndicatorHeight, useListingStyles } from './Listing.styles';
55
+ import { useListingStyles } from './Listing.styles';
57
56
  import { EmptyResult } from './EmptyResult/EmptyResult';
58
57
  import { SkeletonLoader } from './Row/SkeletonLoaderRows';
59
58
  import { ListingHeader } from './Header';
@@ -194,7 +193,6 @@ const Listing = <TRow extends { id: RowId }>({
194
193
 
195
194
  const { t } = useTranslation();
196
195
 
197
- const [tableTopOffset, setTableTopOffset] = React.useState(0);
198
196
  const [hoveredRowId, setHoveredRowId] = React.useState<RowId | null>(null);
199
197
  const [shiftKeyDownRowPivot, setShiftKeyDownRowPivot] = React.useState<
200
198
  number | null
@@ -228,7 +226,7 @@ const Listing = <TRow extends { id: RowId }>({
228
226
  [rows, subItemsPivots, subItems]
229
227
  );
230
228
 
231
- const { classes, theme } = useListingStyles({
229
+ const { classes } = useListingStyles({
232
230
  dataStyle,
233
231
  getGridTemplateColumn,
234
232
  limit,
@@ -236,13 +234,6 @@ const Listing = <TRow extends { id: RowId }>({
236
234
  rows: rowsToDisplay
237
235
  });
238
236
 
239
- useResizeObserver({
240
- onResize: () => {
241
- setTableTopOffset(getCumulativeOffset(containerRef.current));
242
- },
243
- ref: containerRef
244
- });
245
-
246
237
  const { isShiftKeyDown } = useKeyObserver();
247
238
 
248
239
  const haveSameId = (row: TRow, rowToCompare: TRow): boolean =>
@@ -434,18 +425,6 @@ const Listing = <TRow extends { id: RowId }>({
434
425
 
435
426
  const emptyRows = limit - Math.min(limit, totalRows - currentPage * limit);
436
427
 
437
- const tableMaxHeight = (): string => {
438
- if (innerScrollDisabled) {
439
- return '100%';
440
- }
441
-
442
- return `calc(100vh - ${tableTopOffset}px - ${
443
- actionBarRef.current?.offsetHeight
444
- }px - ${
445
- dataStyle.header.height
446
- }px - ${loadingIndicatorHeight}px - ${theme.spacing(1)})`;
447
- };
448
-
449
428
  const changeLimit = (updatedLimit: string): void => {
450
429
  onLimitChange?.(Number(updatedLimit));
451
430
  };
@@ -480,7 +459,7 @@ const Listing = <TRow extends { id: RowId }>({
480
459
  );
481
460
 
482
461
  return (
483
- <>
462
+ <div className={classes.listingContainer}>
484
463
  {loading && rows.length > 0 && (
485
464
  <LinearProgress className={classes.loadingIndicator} />
486
465
  )}
@@ -516,142 +495,152 @@ const Listing = <TRow extends { id: RowId }>({
516
495
  onSelectColumns={onSelectColumns}
517
496
  />
518
497
  </div>
519
- <Box
520
- className={classes.tableWrapper}
521
- component="div"
522
- style={{
523
- maxHeight: tableMaxHeight()
498
+ <ParentSize
499
+ parentSizeStyles={{
500
+ height: '100%',
501
+ overflowY: 'auto',
502
+ width: '100%'
524
503
  }}
525
504
  >
526
- <Table
527
- stickyHeader
528
- className={classes.table}
529
- component="div"
530
- role={undefined}
531
- size="small"
532
- >
533
- <ListingHeader
534
- areColumnsEditable={areColumnsEditable}
535
- checkable={checkable}
536
- columnConfiguration={columnConfiguration}
537
- columns={columns}
538
- listingVariant={listingVariant}
539
- memoProps={headerMemoProps}
540
- predefinedRowsSelection={predefinedRowsSelection}
541
- rowCount={limit - emptyRows}
542
- selectedRowCount={selectedRows.length}
543
- sortField={sortField}
544
- sortOrder={sortOrder}
545
- onSelectAllClick={selectAllRows}
546
- onSelectColumns={onSelectColumns}
547
- onSelectRowsWithCondition={onSelectRowsWithCondition}
548
- onSort={onSort}
549
- />
550
-
551
- <TableBody
552
- className={classes.tableBody}
505
+ {({ height }) => (
506
+ <Box
507
+ className={classes.tableWrapper}
553
508
  component="div"
554
- onMouseLeave={clearHoveredRow}
509
+ style={{
510
+ height: innerScrollDisabled ? '100%' : `calc(${height}px - 4px)`
511
+ }}
555
512
  >
556
- {rowsToDisplay.map((row, index) => {
557
- const isRowSelected = isSelected(row);
558
- const isRowHovered = equals(hoveredRowId, getId(row));
559
- const isSubItem = allSubItemIds.includes(row.id);
560
-
561
- return (
562
- <ListingRow
563
- checkable={
564
- checkable && (!isSubItem || subItems.canCheckSubItems)
565
- }
566
- columnConfiguration={columnConfiguration}
567
- columnIds={columns.map(prop('id'))}
568
- disableRowCondition={disableRowCondition}
569
- isHovered={isRowHovered}
570
- isSelected={isRowSelected}
571
- isShiftKeyDown={isShiftKeyDown}
572
- key={
573
- gte(limit, performanceRowsLimit)
574
- ? `row_${index}`
575
- : getId(row)
576
- }
577
- lastSelectionIndex={lastSelectionIndex}
578
- limit={limit}
579
- listingVariant={listingVariant}
580
- row={row}
581
- rowColorConditions={rowColorConditions}
582
- shiftKeyDownRowPivot={shiftKeyDownRowPivot}
583
- subItemsPivots={subItemsPivots}
584
- tabIndex={-1}
585
- visibleColumns={visibleColumns}
586
- onClick={(): void => {
587
- onRowClick(row);
588
- }}
589
- onFocus={(): void => hoverRow(row)}
590
- onMouseOver={(): void => hoverRow(row)}
591
- >
592
- {checkable &&
593
- (!isSubItem || subItems.canCheckSubItems ? (
594
- <Cell
595
- align="left"
596
- className={classes.checkbox}
597
- disableRowCondition={disableRowCondition}
598
- isRowHovered={isRowHovered}
599
- row={row}
600
- rowColorConditions={rowColorConditions}
601
- onClick={(event): void => selectRow(event, row)}
602
- >
603
- <Checkbox
604
- checked={isRowSelected}
605
- disabled={
606
- disableRowCheckCondition(row) ||
607
- disableRowCondition(row)
608
- }
609
- inputProps={{
610
- 'aria-label': `Select row ${getId(row)}`
611
- }}
612
- />
613
- </Cell>
614
- ) : (
615
- <Cell
616
- align="left"
617
- disableRowCondition={disableRowCondition}
618
- isRowHovered={isRowHovered}
619
- row={row}
620
- rowColorConditions={rowColorConditions}
621
- />
622
- ))}
623
-
624
- {visibleColumns.map((column) => (
625
- <DataCell
626
- column={column}
513
+ <Table
514
+ stickyHeader
515
+ className={classes.table}
516
+ component="div"
517
+ role={undefined}
518
+ size="small"
519
+ >
520
+ <ListingHeader
521
+ areColumnsEditable={areColumnsEditable}
522
+ checkable={checkable}
523
+ columnConfiguration={columnConfiguration}
524
+ columns={columns}
525
+ listingVariant={listingVariant}
526
+ memoProps={headerMemoProps}
527
+ predefinedRowsSelection={predefinedRowsSelection}
528
+ rowCount={limit - emptyRows}
529
+ selectedRowCount={selectedRows.length}
530
+ sortField={sortField}
531
+ sortOrder={sortOrder}
532
+ onSelectAllClick={selectAllRows}
533
+ onSelectColumns={onSelectColumns}
534
+ onSelectRowsWithCondition={onSelectRowsWithCondition}
535
+ onSort={onSort}
536
+ />
537
+
538
+ <TableBody
539
+ className={classes.tableBody}
540
+ component="div"
541
+ onMouseLeave={clearHoveredRow}
542
+ >
543
+ {rowsToDisplay.map((row, index) => {
544
+ const isRowSelected = isSelected(row);
545
+ const isRowHovered = equals(hoveredRowId, getId(row));
546
+ const isSubItem = allSubItemIds.includes(row.id);
547
+
548
+ return (
549
+ <ListingRow
550
+ checkable={
551
+ checkable && (!isSubItem || subItems.canCheckSubItems)
552
+ }
553
+ columnConfiguration={columnConfiguration}
554
+ columnIds={columns.map(prop('id'))}
627
555
  disableRowCondition={disableRowCondition}
628
- getHighlightRowCondition={getHighlightRowCondition}
629
- isRowHovered={isRowHovered}
630
- isRowSelected={isRowSelected}
631
- key={`${getId(row)}-${column.id}`}
632
- labelCollapse={subItems.labelCollapse}
633
- labelExpand={subItems.labelExpand}
556
+ isHovered={isRowHovered}
557
+ isSelected={isRowSelected}
558
+ isShiftKeyDown={isShiftKeyDown}
559
+ key={
560
+ gte(limit, performanceRowsLimit)
561
+ ? `row_${index}`
562
+ : getId(row)
563
+ }
564
+ lastSelectionIndex={lastSelectionIndex}
565
+ limit={limit}
634
566
  listingVariant={listingVariant}
635
567
  row={row}
636
568
  rowColorConditions={rowColorConditions}
637
- subItemsRowProperty={subItems?.rowProperty}
638
- />
569
+ shiftKeyDownRowPivot={shiftKeyDownRowPivot}
570
+ subItemsPivots={subItemsPivots}
571
+ tabIndex={-1}
572
+ visibleColumns={visibleColumns}
573
+ onClick={(): void => {
574
+ onRowClick(row);
575
+ }}
576
+ onFocus={(): void => hoverRow(row)}
577
+ onMouseOver={(): void => hoverRow(row)}
578
+ >
579
+ {checkable &&
580
+ (!isSubItem || subItems.canCheckSubItems ? (
581
+ <Cell
582
+ align="left"
583
+ className={classes.checkbox}
584
+ disableRowCondition={disableRowCondition}
585
+ isRowHovered={isRowHovered}
586
+ row={row}
587
+ rowColorConditions={rowColorConditions}
588
+ onClick={(event): void => selectRow(event, row)}
589
+ >
590
+ <Checkbox
591
+ checked={isRowSelected}
592
+ disabled={
593
+ disableRowCheckCondition(row) ||
594
+ disableRowCondition(row)
595
+ }
596
+ inputProps={{
597
+ 'aria-label': `Select row ${getId(row)}`
598
+ }}
599
+ />
600
+ </Cell>
601
+ ) : (
602
+ <Cell
603
+ align="left"
604
+ disableRowCondition={disableRowCondition}
605
+ isRowHovered={isRowHovered}
606
+ row={row}
607
+ rowColorConditions={rowColorConditions}
608
+ />
609
+ ))}
610
+
611
+ {visibleColumns.map((column) => (
612
+ <DataCell
613
+ column={column}
614
+ disableRowCondition={disableRowCondition}
615
+ getHighlightRowCondition={getHighlightRowCondition}
616
+ isRowHovered={isRowHovered}
617
+ isRowSelected={isRowSelected}
618
+ key={`${getId(row)}-${column.id}`}
619
+ labelCollapse={subItems.labelCollapse}
620
+ labelExpand={subItems.labelExpand}
621
+ listingVariant={listingVariant}
622
+ row={row}
623
+ rowColorConditions={rowColorConditions}
624
+ subItemsRowProperty={subItems?.rowProperty}
625
+ />
626
+ ))}
627
+ </ListingRow>
628
+ );
629
+ })}
630
+
631
+ {rows.length < 1 &&
632
+ (loading ? (
633
+ <SkeletonLoader rows={limit} />
634
+ ) : (
635
+ <EmptyResult label={t(labelNoResultFound)} />
639
636
  ))}
640
- </ListingRow>
641
- );
642
- })}
643
-
644
- {rows.length < 1 &&
645
- (loading ? (
646
- <SkeletonLoader rows={limit} />
647
- ) : (
648
- <EmptyResult label={t(labelNoResultFound)} />
649
- ))}
650
- </TableBody>
651
- </Table>
652
- </Box>
637
+ </TableBody>
638
+ </Table>
639
+ </Box>
640
+ )}
641
+ </ParentSize>
653
642
  </div>
654
- </>
643
+ </div>
655
644
  );
656
645
  };
657
646
 
@@ -14,7 +14,7 @@ import Panel from '../Panel';
14
14
 
15
15
  import Filter from './Filter';
16
16
 
17
- import ListingPage from '.';
17
+ import ListingPage, { ListingPageProps } from '.';
18
18
 
19
19
  export default { title: 'Listing Page' };
20
20
 
@@ -59,6 +59,9 @@ const useStyles = makeStyles()((theme) => ({
59
59
  gridGap: theme.spacing(2),
60
60
  gridTemplateColumns: 'auto auto 1fr'
61
61
  },
62
+ page: {
63
+ height: '100vh'
64
+ },
62
65
  title: {
63
66
  alignItems: 'center',
64
67
  gridArea: 'title',
@@ -251,8 +254,18 @@ const DetailsPanelWithTabs = (): JSX.Element => (
251
254
  />
252
255
  );
253
256
 
257
+ const Template = (args: ListingPageProps): JSX.Element => {
258
+ const { classes } = useStyles();
259
+
260
+ return (
261
+ <div className={classes.page}>
262
+ <ListingPage {...args} />
263
+ </div>
264
+ );
265
+ };
266
+
254
267
  export const normal = (): JSX.Element => (
255
- <ListingPage
268
+ <Template
256
269
  filter={<FilterWithContent />}
257
270
  listing={listing}
258
271
  panelOpen={false}
@@ -260,7 +273,7 @@ export const normal = (): JSX.Element => (
260
273
  );
261
274
 
262
275
  export const withOpenPanel = (): JSX.Element => (
263
- <ListingPage
276
+ <Template
264
277
  panelOpen
265
278
  filter={<FilterWithContent />}
266
279
  listing={listing}
@@ -269,7 +282,7 @@ export const withOpenPanel = (): JSX.Element => (
269
282
  );
270
283
 
271
284
  export const withOpenPanelAndTabs = (): JSX.Element => (
272
- <ListingPage
285
+ <Template
273
286
  panelOpen
274
287
  filter={<FilterWithContent />}
275
288
  listing={listing}
@@ -278,7 +291,7 @@ export const withOpenPanelAndTabs = (): JSX.Element => (
278
291
  );
279
292
 
280
293
  export const withFilterDetailsAndOpenPanel = (): JSX.Element => (
281
- <ListingPage
294
+ <Template
282
295
  panelOpen
283
296
  filter={<FilterWithContent />}
284
297
  listing={listing}
@@ -290,7 +303,7 @@ export const withFixedPanel = (): JSX.Element => {
290
303
  const [open, setOpen] = useState(true);
291
304
 
292
305
  return (
293
- <ListingPage
306
+ <Template
294
307
  panelFixed
295
308
  filter={<FilterWithOpenButton onOpen={(): void => setOpen(true)} />}
296
309
  listing={listing}
@@ -304,7 +317,7 @@ export const withResponsivePaginationTable = (): JSX.Element => {
304
317
  const [open, setOpen] = useState(true);
305
318
 
306
319
  return (
307
- <ListingPage
320
+ <Template
308
321
  filter={<FilterWithOpenButton onOpen={(): void => setOpen(true)} />}
309
322
  listing={
310
323
  <Listing
@@ -326,7 +339,7 @@ export const withResponsivePaginationTable = (): JSX.Element => {
326
339
  };
327
340
 
328
341
  export const withALongContent = (): JSX.Element => (
329
- <ListingPage
342
+ <Template
330
343
  filter={<FilterWithContent />}
331
344
  listing={
332
345
  <div>
@@ -1,4 +1,4 @@
1
- import { Suspense, useEffect, useRef, useState } from 'react';
1
+ import { Suspense, useRef } from 'react';
2
2
 
3
3
  import { makeStyles } from 'tss-react/mui';
4
4
 
@@ -6,6 +6,7 @@ import { Box } from '@mui/material';
6
6
 
7
7
  import { useMemoComponent } from '../utils';
8
8
  import WithPanel from '../Panel/WithPanel';
9
+ import { ParentSize } from '..';
9
10
 
10
11
  import FilterSkeleton from './FilterSkeleton';
11
12
  import ListingSkeleton from './ListingSkeleton';
@@ -30,7 +31,7 @@ const useStyles = makeStyles()((theme) => {
30
31
  };
31
32
  });
32
33
 
33
- interface Props {
34
+ export interface ListingPageProps {
34
35
  filter: JSX.Element;
35
36
  fullHeight?: boolean;
36
37
  listing: JSX.Element;
@@ -52,32 +53,10 @@ const ListingPage = ({
52
53
  listingScrollOffset = 16,
53
54
  fullHeight = false,
54
55
  memoListingProps = []
55
- }: Props): JSX.Element => {
56
+ }: ListingPageProps): JSX.Element => {
56
57
  const { classes, cx } = useStyles();
57
- const [listingHeight, setListingHeight] = useState(0);
58
- const listingRef = useRef<HTMLDivElement | null>(null);
59
58
  const filtersRef = useRef<HTMLDivElement | null>(null);
60
59
 
61
- const resize = (): void => {
62
- setListingHeight(window.innerHeight);
63
- };
64
-
65
- useEffect(() => {
66
- window.addEventListener('resize', resize);
67
-
68
- setListingHeight(window.innerHeight);
69
-
70
- return () => {
71
- window.removeEventListener('resize', resize);
72
- };
73
- }, []);
74
-
75
- const listingContainerHeight =
76
- listingHeight -
77
- (filtersRef.current?.getBoundingClientRect().height || 0) -
78
- (filtersRef.current?.getBoundingClientRect().top || 0) -
79
- listingScrollOffset;
80
-
81
60
  const memoListingComponent = useMemoComponent({
82
61
  Component: listing,
83
62
  memoProps: [...memoListingProps]
@@ -90,18 +69,21 @@ const ListingPage = ({
90
69
  </div>
91
70
 
92
71
  <WithPanel fixed={panelFixed} open={panelOpen} panel={panel}>
93
- <Box
94
- className={classes.listing}
95
- ref={listingRef}
96
- sx={{
97
- ...(fullHeight && { height: '100%' }),
98
- maxHeight: listingContainerHeight
99
- }}
100
- >
101
- <Suspense fallback={<ListingSkeleton />}>
102
- {memoListingComponent}
103
- </Suspense>
104
- </Box>
72
+ <ParentSize>
73
+ {({ height }) => (
74
+ <Box
75
+ className={classes.listing}
76
+ sx={{
77
+ height: `calc(${height}px - ${listingScrollOffset}px)`,
78
+ ...(fullHeight && { height: '100%' })
79
+ }}
80
+ >
81
+ <Suspense fallback={<ListingSkeleton />}>
82
+ {memoListingComponent}
83
+ </Suspense>
84
+ </Box>
85
+ )}
86
+ </ParentSize>
105
87
  </WithPanel>
106
88
  </div>
107
89
  );