@centreon/ui 23.10.1 → 23.10.2

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.1",
3
+ "version": "23.10.2",
4
4
  "description": "Centreon UI Components",
5
5
  "main": "src/index.ts",
6
6
  "scripts": {
@@ -0,0 +1,24 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ const useStyles = makeStyles()((theme) => ({
4
+ cell: {
5
+ alignItems: 'center',
6
+ display: 'flex',
7
+ height: '100%',
8
+ overflow: 'hidden',
9
+ whiteSpace: 'nowrap'
10
+ },
11
+ componentColumn: {
12
+ width: theme.spacing(2.75)
13
+ },
14
+ rowNotHovered: {
15
+ color: theme.palette.text.secondary
16
+ },
17
+ text: {
18
+ overflow: 'hidden',
19
+ textOverflow: 'ellipsis',
20
+ whiteSpace: 'nowrap'
21
+ }
22
+ }));
23
+
24
+ export { useStyles };
@@ -1,13 +1,11 @@
1
1
  import { memo } from 'react';
2
2
 
3
3
  import { equals, props } from 'ramda';
4
- import { makeStyles } from 'tss-react/mui';
5
4
 
6
5
  import { Tooltip } from '@mui/material';
7
6
 
8
7
  import { ListingVariant } from '@centreon/ui-context';
9
8
 
10
- import DraggableIcon from '../Header/SortableCell/DraggableIcon';
11
9
  import {
12
10
  Column,
13
11
  ColumnType,
@@ -17,11 +15,11 @@ import {
17
15
  import useStyleTable from '../useStyleTable';
18
16
 
19
17
  import EllipsisTypography from './EllipsisTypography';
18
+ import { useStyles } from './DataCell.styles';
20
19
 
21
20
  import Cell from '.';
22
21
 
23
22
  interface Props {
24
- areColumnsEditable: boolean;
25
23
  column: Column;
26
24
  disableRowCondition: (row) => boolean;
27
25
  getHighlightRowCondition?: (row) => boolean;
@@ -32,31 +30,6 @@ interface Props {
32
30
  viewMode?: ListingVariant;
33
31
  }
34
32
 
35
- const useStyles = makeStyles()((theme) => ({
36
- cell: {
37
- alignItems: 'center',
38
- backgroundColor: 'transparent',
39
- display: 'flex',
40
- height: '100%',
41
- overflow: 'hidden',
42
- whiteSpace: 'nowrap'
43
- },
44
- componentColumn: {
45
- width: theme.spacing(2.75)
46
- },
47
- headerCell: {
48
- padding: theme.spacing(0, 0, 0, 1)
49
- },
50
- rowNotHovered: {
51
- color: theme.palette.text.secondary
52
- },
53
- text: {
54
- overflow: 'hidden',
55
- textOverflow: 'ellipsis',
56
- whiteSpace: 'nowrap'
57
- }
58
- }));
59
-
60
33
  const DataCell = ({
61
34
  row,
62
35
  column,
@@ -65,14 +38,12 @@ const DataCell = ({
65
38
  rowColorConditions,
66
39
  disableRowCondition,
67
40
  viewMode,
68
- getHighlightRowCondition,
69
- areColumnsEditable
41
+ getHighlightRowCondition
70
42
  }: Props): JSX.Element | null => {
71
- const { dataStyle } = useStyleTable({ viewMode });
72
43
  const { classes } = useStyles();
44
+ const { dataStyle } = useStyleTable({ viewMode });
73
45
 
74
46
  const commonCellProps = {
75
- align: 'left' as const,
76
47
  disableRowCondition,
77
48
  isRowHovered,
78
49
  row,
@@ -102,6 +73,7 @@ const DataCell = ({
102
73
 
103
74
  return (
104
75
  <Cell
76
+ className={classes.cell}
105
77
  isRowHighlighted={isRowHighlighted}
106
78
  style={{
107
79
  gridColumn
@@ -112,10 +84,7 @@ const DataCell = ({
112
84
  {isTruncated && (
113
85
  <Tooltip title={formattedString}>{typography}</Tooltip>
114
86
  )}
115
- <>
116
- {areColumnsEditable && <DraggableIcon />}
117
- {!isTruncated && typography}
118
- </>
87
+ {!isTruncated && typography}
119
88
  </Cell>
120
89
  );
121
90
  },
@@ -133,6 +102,7 @@ const DataCell = ({
133
102
 
134
103
  return (
135
104
  <Cell
105
+ className={classes.cell}
136
106
  isRowHighlighted={isRowHighlighted}
137
107
  viewMode={viewMode}
138
108
  onClick={(e): void => {
@@ -144,31 +114,25 @@ const DataCell = ({
144
114
  }}
145
115
  {...commonCellProps}
146
116
  >
147
- <>
148
- {areColumnsEditable && (
149
- <DraggableIcon className={classes.componentColumn} />
150
- )}
151
-
152
- <Component
153
- isHovered={isRowHovered}
154
- isSelected={isRowSelected}
155
- renderEllipsisTypography={({
156
- className,
157
- formattedString
158
- }): JSX.Element => {
159
- return (
160
- <EllipsisTypography
161
- className={className}
162
- dataStyle={dataStyle}
163
- disableRowCondition={disableRowCondition(row)}
164
- formattedString={formattedString}
165
- isRowHovered={isRowHovered}
166
- />
167
- );
168
- }}
169
- row={row}
170
- />
171
- </>
117
+ <Component
118
+ isHovered={isRowHovered}
119
+ isSelected={isRowSelected}
120
+ renderEllipsisTypography={({
121
+ className,
122
+ formattedString
123
+ }): JSX.Element => {
124
+ return (
125
+ <EllipsisTypography
126
+ className={className}
127
+ dataStyle={dataStyle}
128
+ disableRowCondition={disableRowCondition(row)}
129
+ formattedString={formattedString}
130
+ isRowHovered={isRowHovered}
131
+ />
132
+ );
133
+ }}
134
+ row={row}
135
+ />
172
136
  </Cell>
173
137
  );
174
138
  }
@@ -280,8 +244,7 @@ const MemoizedDataCell = memo<Props>(
280
244
  nextProps.disableRowCondition(nextProps.row)
281
245
  ) &&
282
246
  equals(previousIsRowHighlighted, nextIsRowHighlighted) &&
283
- equals(prevProps.viewMode, nextProps.viewMode) &&
284
- equals(prevProps.areColumnsEditable, nextProps.areColumnsEditable)
247
+ equals(prevProps.viewMode, nextProps.viewMode) // &&
285
248
  );
286
249
  }
287
250
  );
@@ -0,0 +1,71 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ import { ListingVariant } from '@centreon/ui-context';
4
+
5
+ import { getTextStyleByViewMode } from '../../useStyleTable';
6
+
7
+ interface StylesProps {
8
+ isDragging?: boolean;
9
+ isInDragOverlay?: boolean;
10
+ viewMode?: ListingVariant;
11
+ }
12
+
13
+ const useStyles = makeStyles<StylesProps>()(
14
+ (theme, { isDragging, isInDragOverlay, viewMode }) => ({
15
+ active: {
16
+ '&, &:hover, &:focus': {
17
+ color: theme.palette.common.white
18
+ },
19
+ '&.Mui-active': {
20
+ '& .MuiTableSortLabel-icon': {
21
+ color: theme.palette.common.white
22
+ },
23
+ color: theme.palette.common.white
24
+ }
25
+ },
26
+ content: {
27
+ alignItems: 'center',
28
+ borderRadius: isDragging && isInDragOverlay ? theme.spacing(0.5) : 0,
29
+ color: theme.palette.common.white,
30
+ display: 'flex',
31
+ height: '100%',
32
+ justifyContent: 'space-between'
33
+ },
34
+ dragHandle: {
35
+ '&, &.Mui-focus, &:focus': {
36
+ color: theme.palette.common.white
37
+ },
38
+ color: theme.palette.common.white,
39
+
40
+ cursor: isDragging ? 'grabbing' : 'grab',
41
+ opacity: 0,
42
+ padding: 0
43
+ },
44
+ simpleHeaderCellContent: {
45
+ alignItems: 'center',
46
+ display: 'inline-flex',
47
+ marginRight: theme.spacing(2),
48
+ userSelect: 'none'
49
+ },
50
+ tableCell: {
51
+ backgroundColor: isInDragOverlay
52
+ ? 'transparent'
53
+ : theme.palette.background.listingHeader,
54
+ borderBottom: 'none',
55
+ height: 'inherit',
56
+ padding: theme.spacing(0, 1),
57
+ ...getTextStyleByViewMode({ theme, viewMode }),
58
+ '&:hover, &:focus-within, &[data-isdragging=true]': {
59
+ '& .dragHandle': {
60
+ opacity: 1
61
+ }
62
+ },
63
+ '&[data-isindragoverlay=true]': {
64
+ display: 'block',
65
+ opacity: 0.7
66
+ }
67
+ }
68
+ })
69
+ );
70
+
71
+ export { useStyles, StylesProps };
@@ -1,7 +1,6 @@
1
1
  import * as React from 'react';
2
2
 
3
3
  import { always, and, equals, ifElse, isNil } from 'ramda';
4
- import { makeStyles } from 'tss-react/mui';
5
4
 
6
5
  import {
7
6
  TableCell,
@@ -10,64 +9,12 @@ import {
10
9
  Tooltip
11
10
  } from '@mui/material';
12
11
 
13
- import { ListingVariant } from '@centreon/ui-context';
14
-
15
12
  import { Props as ListingProps } from '../..';
16
13
  import { Column } from '../../models';
17
- import HeaderLabel from '../Label';
18
- import { getTextStyleByViewMode } from '../../useStyleTable';
19
-
20
- import DraggableIcon from './DraggableIcon';
21
-
22
- type StylesProps = Pick<Props, 'isDragging' | 'isInDragOverlay' | 'viewMode'>;
14
+ import HeaderLabel from '../_internals/Label';
15
+ import { DraggableIconButton } from '../_internals/DraggableIconButton';
23
16
 
24
- const useStyles = makeStyles<StylesProps>()(
25
- (theme, { isDragging, isInDragOverlay, viewMode }) => ({
26
- active: {
27
- '&.Mui-active': {
28
- '& .MuiTableSortLabel-icon': {
29
- color: theme.palette.common.white
30
- },
31
- color: theme.palette.common.white
32
- },
33
- '&:hover': {
34
- '& .MuiTableSortLabel-icon': {
35
- opacity: 1
36
- },
37
- color: theme.palette.common.white
38
- }
39
- },
40
- content: {
41
- alignItems: 'center',
42
- borderRadius: isDragging && isInDragOverlay ? theme.spacing(0.5) : 0,
43
- color: theme.palette.common.white,
44
- display: 'flex',
45
- height: '100%'
46
- },
47
- dragHandle: {
48
- '&, &.Mui-focus, &:focus': {
49
- outline: 'none'
50
- },
51
- alignSelf: 'center',
52
- cursor: isDragging ? 'grabbing' : 'grab',
53
- display: 'flex'
54
- },
55
- simpleHeaderCellContent: {
56
- alignItems: 'center',
57
- display: 'inline-flex',
58
- marginRight: theme.spacing(2)
59
- },
60
- tableCell: {
61
- backgroundColor: isInDragOverlay
62
- ? 'transparent'
63
- : theme.palette.background.listingHeader,
64
- borderBottom: 'none',
65
- height: 'inherit',
66
- padding: theme.spacing(0, 1),
67
- ...getTextStyleByViewMode({ theme, viewMode })
68
- }
69
- })
70
- );
17
+ import { StylesProps, useStyles } from './ListingHeaderCell.styles';
71
18
 
72
19
  type Props = Pick<
73
20
  ListingProps<unknown>,
@@ -76,14 +23,11 @@ type Props = Pick<
76
23
  areColumnsEditable: boolean;
77
24
  className: string;
78
25
  column: Column;
79
- isDragging?: boolean;
80
- isInDragOverlay?: boolean;
81
26
  itemRef: React.RefObject<HTMLDivElement>;
82
27
  style;
83
- viewMode?: ListingVariant;
84
- };
28
+ } & StylesProps;
85
29
 
86
- const SortableHeaderCellContent = ({
30
+ const ListingHeaderCell = ({
87
31
  column,
88
32
  columnConfiguration,
89
33
  sortField,
@@ -102,8 +46,6 @@ const SortableHeaderCellContent = ({
102
46
  isInDragOverlay,
103
47
  viewMode
104
48
  });
105
- const [cellHovered, setCellHovered] = React.useState(false);
106
-
107
49
  const columnLabel = column.shortLabel || column.label;
108
50
 
109
51
  const columnSortField = column.sortField || column.id;
@@ -122,14 +64,6 @@ const SortableHeaderCellContent = ({
122
64
  });
123
65
  };
124
66
 
125
- const mouseOver = (): void => {
126
- setCellHovered(true);
127
- };
128
-
129
- const mouseOut = (): void => {
130
- setCellHovered(false);
131
- };
132
-
133
67
  const headerContent = (
134
68
  <Tooltip placement="top" title={getTooltipLabel(column.shortLabel)}>
135
69
  <HeaderLabel>{columnLabel}</HeaderLabel>
@@ -140,22 +74,12 @@ const SortableHeaderCellContent = ({
140
74
  <TableCell
141
75
  className={classes.tableCell}
142
76
  component={'div' as unknown as React.ElementType<TableCellBaseProps>}
77
+ data-isdragging={isDragging}
78
+ data-isindragoverlay={isInDragOverlay}
143
79
  ref={itemRef}
144
80
  style={style}
145
- onMouseOut={mouseOut}
146
- onMouseOver={mouseOver}
147
81
  >
148
82
  <div className={classes.content}>
149
- {columnConfiguration?.sortable && areColumnsEditable && (
150
- <DraggableIcon
151
- visible={cellHovered}
152
- {...props}
153
- isInteractive
154
- className={cx(classes.dragHandle)}
155
- columnLabel={columnLabel}
156
- />
157
- )}
158
-
159
83
  {column.sortable ? (
160
84
  <TableSortLabel
161
85
  active={sortField === columnSortField}
@@ -169,9 +93,17 @@ const SortableHeaderCellContent = ({
169
93
  ) : (
170
94
  <div className={classes.simpleHeaderCellContent}>{headerContent}</div>
171
95
  )}
96
+
97
+ {columnConfiguration?.sortable && areColumnsEditable && (
98
+ <DraggableIconButton
99
+ {...props}
100
+ className={cx(classes.dragHandle, 'dragHandle')}
101
+ columnLabel={columnLabel}
102
+ />
103
+ )}
172
104
  </div>
173
105
  </TableCell>
174
106
  );
175
107
  };
176
108
 
177
- export default SortableHeaderCellContent;
109
+ export default ListingHeaderCell;
@@ -0,0 +1,26 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ const useStyles = makeStyles()((theme) => ({
4
+ checkbox: {
5
+ '&.Mui-checked': {
6
+ color: theme.palette.common.white
7
+ },
8
+ '&.MuiCheckbox-indeterminate': {
9
+ color: theme.palette.common.white
10
+ },
11
+ color: theme.palette.common.white
12
+ },
13
+ checkboxHeaderCell: {
14
+ alignItems: 'center',
15
+ backgroundColor: theme.palette.background.listingHeader,
16
+ borderBottom: 'none',
17
+ display: 'flex',
18
+ justifyContent: 'start',
19
+ lineHeight: 'inherit'
20
+ },
21
+ predefinedRowsMenu: {
22
+ color: theme.palette.common.white
23
+ }
24
+ }));
25
+
26
+ export { useStyles };
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+
3
+ import { equals, isEmpty, not } from 'ramda';
4
+
5
+ import { TableCell, TableCellBaseProps } from '@mui/material';
6
+ import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
7
+
8
+ import Checkbox from '../../Checkbox';
9
+ import PopoverMenu from '../../../PopoverMenu';
10
+ import { labelPredefinedRowsSelectionMenu } from '../../translatedLabels';
11
+ import PredefinedSelectionList from '../_internals/PredefinedSelectionList';
12
+ import { PredefinedRowSelection } from '../../models';
13
+
14
+ import { useStyles } from './SelectActionListingHeaderCell.styles';
15
+
16
+ export interface SelectActionListingHeaderCellProps {
17
+ onSelectAllClick: (event) => void;
18
+ onSelectRowsWithCondition: (condition) => void;
19
+ predefinedRowsSelection: Array<PredefinedRowSelection>;
20
+ rowCount: number;
21
+ selectedRowCount: number;
22
+ }
23
+
24
+ const SelectActionListingHeaderCell = ({
25
+ rowCount,
26
+ onSelectAllClick,
27
+ selectedRowCount,
28
+ predefinedRowsSelection,
29
+ onSelectRowsWithCondition
30
+ }: SelectActionListingHeaderCellProps): JSX.Element => {
31
+ const { classes } = useStyles();
32
+
33
+ const hasRows = not(equals(rowCount, 0));
34
+
35
+ return (
36
+ <TableCell
37
+ className={classes.checkboxHeaderCell}
38
+ component={'div' as unknown as React.ElementType<TableCellBaseProps>}
39
+ >
40
+ <Checkbox
41
+ checked={hasRows && selectedRowCount === rowCount}
42
+ className={classes.checkbox}
43
+ indeterminate={
44
+ hasRows && selectedRowCount > 0 && selectedRowCount < rowCount
45
+ }
46
+ inputProps={{ 'aria-label': 'Select all' }}
47
+ onChange={onSelectAllClick}
48
+ />
49
+ {not(isEmpty(predefinedRowsSelection)) ? (
50
+ <PopoverMenu
51
+ className={classes.predefinedRowsMenu}
52
+ icon={<ArrowDropDownIcon />}
53
+ title={labelPredefinedRowsSelectionMenu}
54
+ >
55
+ {({ close }): JSX.Element => (
56
+ <PredefinedSelectionList
57
+ close={close}
58
+ predefinedRowsSelection={predefinedRowsSelection}
59
+ onSelectRowsWithCondition={onSelectRowsWithCondition}
60
+ />
61
+ )}
62
+ </PopoverMenu>
63
+ ) : (
64
+ <div className={classes.predefinedRowsMenu} />
65
+ )}
66
+ </TableCell>
67
+ );
68
+ };
69
+
70
+ export { SelectActionListingHeaderCell };
@@ -0,0 +1,16 @@
1
+ import { makeStyles } from 'tss-react/mui';
2
+
3
+ const useStyles = makeStyles()((theme) => ({
4
+ headerLabelDragging: {
5
+ cursor: 'grabbing'
6
+ },
7
+ root: {
8
+ height: '100%',
9
+ padding: theme.spacing(0, 1)
10
+ },
11
+ row: {
12
+ display: 'contents'
13
+ }
14
+ }));
15
+
16
+ export { useStyles };
@@ -2,64 +2,22 @@ import * as React from 'react';
2
2
 
3
3
  import { closestCenter, DraggableSyntheticListeners } from '@dnd-kit/core';
4
4
  import { horizontalListSortingStrategy } from '@dnd-kit/sortable';
5
- import { equals, find, isEmpty, map, not, pick, propEq } from 'ramda';
6
- import { makeStyles } from 'tss-react/mui';
5
+ import { equals, find, map, pick, propEq } from 'ramda';
7
6
 
8
- import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
9
- import {
10
- TableCell,
11
- TableCellBaseProps,
12
- TableHead,
13
- TableRow
14
- } from '@mui/material';
7
+ import { TableHead, TableRow } from '@mui/material';
15
8
 
16
9
  import { ListingVariant } from '@centreon/ui-context';
17
10
 
18
11
  import { getVisibleColumns, Props as ListingProps } from '..';
19
- import PopoverMenu from '../../PopoverMenu';
20
12
  import SortableItems from '../../SortableItems';
21
- import Checkbox from '../Checkbox';
22
- import { Column, PredefinedRowSelection } from '../models';
23
- import { labelPredefinedRowsSelectionMenu } from '../translatedLabels';
24
-
25
- import PredefinedSelectionList from './PredefinedSelectionList';
26
- import SortableHeaderCellContent from './SortableCell/Content';
13
+ import { Column } from '../models';
27
14
 
28
- const useStyles = makeStyles()((theme) => ({
29
- checkbox: {
30
- '&.Mui-checked': {
31
- color: theme.palette.common.white
32
- },
33
- '&.MuiCheckbox-indeterminate': {
34
- color: theme.palette.common.white
35
- },
36
- color: theme.palette.common.white
37
- },
38
- checkboxHeaderCell: {
39
- alignItems: 'center',
40
- backgroundColor: theme.palette.background.listingHeader,
41
- borderBottom: 'none',
42
- display: 'flex',
43
- justifyContent: 'start',
44
- lineHeight: 'inherit',
45
- minWidth: theme.spacing(51 / 8),
46
- padding: 0
47
- },
48
- headerLabelDragging: {
49
- cursor: 'grabbing'
50
- },
51
- predefinedRowsMenu: {
52
- color: theme.palette.common.white,
53
- width: theme.spacing(2)
54
- },
55
- root: {
56
- height: '100%',
57
- padding: theme.spacing(0, 1)
58
- },
59
- row: {
60
- display: 'contents'
61
- }
62
- }));
15
+ import ListingHeaderCell from './Cell/ListingHeaderCell';
16
+ import { useStyles } from './ListingHeader.styles';
17
+ import {
18
+ SelectActionListingHeaderCell,
19
+ SelectActionListingHeaderCellProps
20
+ } from './Cell/SelectActionListingHeaderCell';
63
21
 
64
22
  type Props = Pick<
65
23
  ListingProps<unknown>,
@@ -74,13 +32,9 @@ type Props = Pick<
74
32
  > & {
75
33
  areColumnsEditable: boolean;
76
34
  memoProps: Array<unknown>;
77
- onSelectAllClick: (event) => void;
78
- onSelectRowsWithCondition: (condition) => void;
79
- predefinedRowsSelection: Array<PredefinedRowSelection>;
80
35
  rowCount: number;
81
- selectedRowCount: number;
82
36
  viewMode?: ListingVariant;
83
- };
37
+ } & SelectActionListingHeaderCellProps;
84
38
 
85
39
  interface ContentProps extends Pick<Props, 'sortField' | 'sortOrder'> {
86
40
  attributes;
@@ -93,21 +47,21 @@ interface ContentProps extends Pick<Props, 'sortField' | 'sortOrder'> {
93
47
  }
94
48
 
95
49
  const ListingHeader = ({
96
- onSelectAllClick,
97
50
  sortOrder,
98
51
  sortField,
99
- selectedRowCount,
100
52
  rowCount,
101
53
  columns,
102
54
  columnConfiguration,
103
55
  onSort,
104
56
  onSelectColumns,
105
57
  checkable,
106
- predefinedRowsSelection,
107
- onSelectRowsWithCondition,
108
58
  memoProps,
109
59
  areColumnsEditable,
110
- viewMode
60
+ viewMode,
61
+ onSelectAllClick,
62
+ selectedRowCount,
63
+ predefinedRowsSelection,
64
+ onSelectRowsWithCondition
111
65
  }: Props): JSX.Element => {
112
66
  const { classes, cx } = useStyles();
113
67
 
@@ -131,7 +85,7 @@ const ListingHeader = ({
131
85
  id
132
86
  }: ContentProps): JSX.Element => {
133
87
  return (
134
- <SortableHeaderCellContent
88
+ <ListingHeaderCell
135
89
  areColumnsEditable={areColumnsEditable}
136
90
  column={getColumnById(id)}
137
91
  columnConfiguration={columnConfiguration}
@@ -151,45 +105,17 @@ const ListingHeader = ({
151
105
  [columnConfiguration, columns, sortField, sortOrder]
152
106
  );
153
107
 
154
- const hasRows = not(equals(rowCount, 0));
155
-
156
108
  return (
157
109
  <TableHead className={cx(classes.row, 'listingHeader')} component="div">
158
110
  <TableRow className={classes.row} component="div">
159
111
  {checkable && (
160
- <TableCell
161
- className={classes.checkboxHeaderCell}
162
- component={
163
- 'div' as unknown as React.ElementType<TableCellBaseProps>
164
- }
165
- >
166
- <Checkbox
167
- checked={hasRows && selectedRowCount === rowCount}
168
- className={classes.checkbox}
169
- indeterminate={
170
- hasRows && selectedRowCount > 0 && selectedRowCount < rowCount
171
- }
172
- inputProps={{ 'aria-label': 'Select all' }}
173
- onChange={onSelectAllClick}
174
- />
175
- {not(isEmpty(predefinedRowsSelection)) ? (
176
- <PopoverMenu
177
- className={classes.predefinedRowsMenu}
178
- icon={<ArrowDropDownIcon />}
179
- title={labelPredefinedRowsSelectionMenu}
180
- >
181
- {({ close }): JSX.Element => (
182
- <PredefinedSelectionList
183
- close={close}
184
- predefinedRowsSelection={predefinedRowsSelection}
185
- onSelectRowsWithCondition={onSelectRowsWithCondition}
186
- />
187
- )}
188
- </PopoverMenu>
189
- ) : (
190
- <div className={classes.predefinedRowsMenu} />
191
- )}
192
- </TableCell>
112
+ <SelectActionListingHeaderCell
113
+ predefinedRowsSelection={predefinedRowsSelection}
114
+ rowCount={rowCount}
115
+ selectedRowCount={selectedRowCount}
116
+ onSelectAllClick={onSelectAllClick}
117
+ onSelectRowsWithCondition={onSelectRowsWithCondition}
118
+ />
193
119
  )}
194
120
  <SortableItems
195
121
  updateSortableItemsOnItemsChange
@@ -214,6 +140,7 @@ const columnMemoProps = [
214
140
  'label',
215
141
  'rowMemoProps',
216
142
  'sortField',
143
+ 'sortOrder',
217
144
  'sortable',
218
145
  'type'
219
146
  ];
@@ -236,4 +163,4 @@ const MemoizedListingHeader = React.memo<Props>(
236
163
  equals(prevProps.viewMode, nextProps.viewMode)
237
164
  );
238
165
 
239
- export default MemoizedListingHeader;
166
+ export { MemoizedListingHeader as ListingHeader };
@@ -0,0 +1,35 @@
1
+ import * as React from 'react';
2
+
3
+ import { useTranslation } from 'react-i18next';
4
+
5
+ import { SvgIcon, IconButton as MuiIconButton } from '@mui/material';
6
+ import DragIndicatorIcon from '@mui/icons-material/DragIndicator';
7
+
8
+ import { labelDragHandle } from '../../translatedLabels';
9
+
10
+ interface DraggableIconButtonProps {
11
+ className?: string;
12
+ columnLabel?: string;
13
+ }
14
+
15
+ const DraggableIconButton = ({
16
+ columnLabel,
17
+ className,
18
+ ...props
19
+ }: DraggableIconButtonProps): JSX.Element => {
20
+ const { t } = useTranslation();
21
+
22
+ return (
23
+ <MuiIconButton
24
+ className={className}
25
+ {...props}
26
+ aria-label={`${columnLabel} ${t(labelDragHandle)}`}
27
+ >
28
+ <SvgIcon fontSize="small">
29
+ <DragIndicatorIcon />
30
+ </SvgIcon>
31
+ </MuiIconButton>
32
+ );
33
+ };
34
+
35
+ export { DraggableIconButton };
@@ -1,6 +1,6 @@
1
1
  import { List, ListItem, ListItemText } from '@mui/material';
2
2
 
3
- import { PredefinedRowSelection } from '../models';
3
+ import { PredefinedRowSelection } from '../../models';
4
4
 
5
5
  interface Props {
6
6
  close: () => void;
@@ -0,0 +1 @@
1
+ export * from './ListingHeader';
@@ -37,7 +37,6 @@ const useStyles = makeStyles<StylesProps>()(
37
37
  table: {
38
38
  '.listingHeader': {
39
39
  backgroundColor: theme.palette.background.listingHeader,
40
- boxShadow: `-1px 0px 0px 0px ${theme.palette.background.listingHeader}`,
41
40
  padding: theme.spacing(0, 1)
42
41
  },
43
42
  '.listingHeader > div > div': {
@@ -46,7 +45,7 @@ const useStyles = makeStyles<StylesProps>()(
46
45
  },
47
46
  '.listingHeader > div > div:first-of-type': {
48
47
  height: '100%',
49
- paddingLeft: theme.spacing(1.5)
48
+ padding: theme.spacing(0, 0.5, 0, 1.5)
50
49
  },
51
50
  alignItems: 'center',
52
51
  display: 'grid',
@@ -12,7 +12,7 @@ import { ListingVariant } from '@centreon/ui-context';
12
12
 
13
13
  import { ListingProps } from '..';
14
14
 
15
- import { Column, ColumnType } from './models';
15
+ import { Column, ColumnType, SortOrder } from './models';
16
16
 
17
17
  import Listing from '.';
18
18
 
@@ -153,7 +153,7 @@ const Story = ({
153
153
  limit={listing.length}
154
154
  predefinedRowsSelection={predefinedRowsSelection}
155
155
  rowColorConditions={rowColorConditions}
156
- rows={listing}
156
+ rows={props.rows ?? listing}
157
157
  selectedRows={selected}
158
158
  totalRows={listing.length}
159
159
  viewerModeConfiguration={viewerModeConfiguration}
@@ -214,12 +214,14 @@ const editableColumns = [
214
214
  getFormattedString: ({ name }): string => name,
215
215
  id: 'name',
216
216
  label: 'Name',
217
+ sortable: true,
217
218
  type: ColumnType.string
218
219
  },
219
220
  {
220
221
  getFormattedString: ({ description }): string => description,
221
222
  id: 'description',
222
223
  label: 'Description',
224
+ sortable: true,
223
225
  type: ColumnType.string
224
226
  },
225
227
  {
@@ -247,6 +249,26 @@ const ListingWithEditableColumns = (): JSX.Element => {
247
249
  setSelectedColumnIds(defaultColumnIds);
248
250
  };
249
251
 
252
+ const [sortedRows, setSortedRows] = useState(listing);
253
+ const [sortParams, setSortParams] = useState({
254
+ sortField: editableColumns[0].id,
255
+ sortOrder: 'desc'
256
+ });
257
+
258
+ const onSort = (params: {
259
+ sortField: string;
260
+ sortOrder: SortOrder;
261
+ }): void => {
262
+ const rows = [...sortedRows];
263
+ rows.sort((a, b) =>
264
+ params.sortOrder === 'desc'
265
+ ? a[params.sortField]?.localeCompare(b[params.sortField])
266
+ : b[params.sortField]?.localeCompare(a[params.sortField])
267
+ );
268
+ setSortedRows(rows);
269
+ setSortParams(params);
270
+ };
271
+
250
272
  return (
251
273
  <Story
252
274
  columnConfiguration={{
@@ -254,13 +276,17 @@ const ListingWithEditableColumns = (): JSX.Element => {
254
276
  sortable: true
255
277
  }}
256
278
  columns={editableColumns}
279
+ rows={sortedRows}
280
+ sortField={sortParams.sortField}
281
+ sortOrder={sortParams.sortOrder as SortOrder}
257
282
  onResetColumns={resetColumns}
258
283
  onSelectColumns={setSelectedColumnIds}
284
+ onSort={onSort}
259
285
  />
260
286
  );
261
287
  };
262
288
 
263
- export const withEditableColumns = (): JSX.Element => (
289
+ export const withEditableAndSortableColumns = (): JSX.Element => (
264
290
  <ListingWithEditableColumns />
265
291
  );
266
292
 
@@ -27,7 +27,7 @@ import {
27
27
  } from 'ramda';
28
28
  import { useTranslation } from 'react-i18next';
29
29
 
30
- import { Box, LinearProgress, Table, TableBody, useTheme } from '@mui/material';
30
+ import { Box, LinearProgress, Table, TableBody } from '@mui/material';
31
31
 
32
32
  import { ListingVariant } from '@centreon/ui-context';
33
33
 
@@ -39,7 +39,6 @@ import Cell from './Cell';
39
39
  import DataCell from './Cell/DataCell';
40
40
  import Checkbox from './Checkbox';
41
41
  import getCumulativeOffset from './getCumulativeOffset';
42
- import ListingHeader from './Header/index';
43
42
  import {
44
43
  Column,
45
44
  ColumnConfiguration,
@@ -55,6 +54,7 @@ import useStyleTable from './useStyleTable';
55
54
  import { loadingIndicatorHeight, useStyles } from './Listing.styles';
56
55
  import { EmptyResult } from './EmptyResult/EmptyResult';
57
56
  import { SkeletonLoader } from './Row/SkeletonLoaderRows';
57
+ import { ListingHeader } from './Header';
58
58
 
59
59
  const getVisibleColumns = ({
60
60
  columnConfiguration,
@@ -107,7 +107,7 @@ export interface Props<TRow> {
107
107
  onRowClick?: (row: TRow) => void;
108
108
  onSelectColumns?: (selectedColumnIds: Array<string>) => void;
109
109
  onSelectRows?: (rows: Array<TRow>) => void;
110
- onSort?: (sortParams) => void;
110
+ onSort?: (sortParams: { sortField: string; sortOrder: SortOrder }) => void;
111
111
  paginated?: boolean;
112
112
  predefinedRowsSelection?: Array<PredefinedRowSelection>;
113
113
  rowColorConditions?: Array<RowColorCondition>;
@@ -173,7 +173,7 @@ const Listing = <TRow extends { id: RowId }>({
173
173
  viewMode
174
174
  });
175
175
 
176
- const { classes } = useStyles({
176
+ const { classes, theme } = useStyles({
177
177
  dataStyle,
178
178
  getGridTemplateColumn,
179
179
  limit,
@@ -193,8 +193,6 @@ const Listing = <TRow extends { id: RowId }>({
193
193
  const containerRef = React.useRef<HTMLDivElement>();
194
194
  const actionBarRef = React.useRef<HTMLDivElement>();
195
195
 
196
- const theme = useTheme();
197
-
198
196
  useResizeObserver({
199
197
  onResize: () => {
200
198
  setTableTopOffset(getCumulativeOffset(containerRef.current));
@@ -556,7 +554,6 @@ const Listing = <TRow extends { id: RowId }>({
556
554
 
557
555
  {visibleColumns.map((column) => (
558
556
  <DataCell
559
- areColumnsEditable={areColumnsEditable}
560
557
  column={column}
561
558
  disableRowCondition={disableRowCondition}
562
559
  getHighlightRowCondition={getHighlightRowCondition}
@@ -50,7 +50,7 @@ const useStyleTable = ({
50
50
  const updateStyleTable = useSetAtom(tableStyleDerivedAtom);
51
51
 
52
52
  const getGridTemplateColumn = (): string => {
53
- const checkbox = checkable ? '50px ' : '';
53
+ const checkbox = checkable ? 'fit-content(1rem) ' : ''; // SelectAction (checkbox) cell adjusts to content
54
54
 
55
55
  const columnTemplate = currentVisibleColumns
56
56
  ?.map(({ width, shortLabel }) => {
@@ -1,41 +0,0 @@
1
- import * as React from 'react';
2
-
3
- import { useTranslation } from 'react-i18next';
4
-
5
- import SvgIcon from '@mui/material/SvgIcon';
6
-
7
- import { labelDragHandle } from '../../translatedLabels';
8
-
9
- interface Icon {
10
- className?: string;
11
- columnLabel?: string;
12
- isInteractive?: boolean;
13
- visible?: boolean;
14
- }
15
-
16
- const DraggableIcon = ({
17
- visible = false,
18
- columnLabel,
19
- className,
20
- isInteractive = false,
21
- ...rest
22
- }: Icon): JSX.Element => {
23
- const { t } = useTranslation();
24
-
25
- return (
26
- <SvgIcon
27
- aria-label={`${columnLabel} ${t(labelDragHandle)}`}
28
- fontSize="medium"
29
- {...rest}
30
- className={className}
31
- role={isInteractive ? 'button' : undefined}
32
- tabIndex={isInteractive ? 0 : undefined}
33
- >
34
- {visible && (
35
- <path d="M 12 8 c 1.1 0 2 -0.9 2 -2 s -0.9 -2 -2 -2 s -2 0.9 -2 2 s 0.9 2 2 2 Z m 0 2 c -1.1 0 -2 0.9 -2 2 s 0.9 2 2 2 s 2 -0.9 2 -2 s -0.9 -2 -2 -2 Z m 0 6 c -1.1 0 -2 0.9 -2 2 s 0.9 2 2 2 s 2 -0.9 2 -2 s -0.9 -2 -2 -2 Z" />
36
- )}
37
- </SvgIcon>
38
- );
39
- };
40
-
41
- export default DraggableIcon;