@iobroker/gui-components 10.2.0 → 10.2.1

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.
Files changed (41) hide show
  1. package/README.md +7 -1
  2. package/build/Components/ColorPicker.d.ts +94 -12
  3. package/build/Components/ColorPicker.js +567 -111
  4. package/build/Components/ColorPicker.js.map +1 -1
  5. package/build/Components/ObjectBrowser/dialogs.js +7 -3
  6. package/build/Components/ObjectBrowser/dialogs.js.map +1 -1
  7. package/build/Components/ObjectBrowser/renderLeaf.js +29 -10
  8. package/build/Components/ObjectBrowser/renderLeaf.js.map +1 -1
  9. package/build/Components/Schedule.js +176 -78
  10. package/build/Components/Schedule.js.map +1 -1
  11. package/build/Components/TreeTable.d.ts +6 -2
  12. package/build/Components/TreeTable.js +183 -103
  13. package/build/Components/TreeTable.js.map +1 -1
  14. package/build/Dialogs/Error.js +26 -5
  15. package/build/Dialogs/Error.js.map +1 -1
  16. package/build/i18n/de.json +20 -0
  17. package/build/i18n/en.json +20 -0
  18. package/build/i18n/es.json +20 -0
  19. package/build/i18n/fr.json +20 -0
  20. package/build/i18n/it.json +20 -0
  21. package/build/i18n/nl.json +20 -0
  22. package/build/i18n/pl.json +20 -0
  23. package/build/i18n/pt.json +20 -0
  24. package/build/i18n/ru.json +20 -0
  25. package/build/i18n/uk.json +20 -0
  26. package/build/i18n/zh-cn.json +20 -0
  27. package/build/index.d.ts +2 -1
  28. package/build/index.js +1 -1
  29. package/build/index.js.map +1 -1
  30. package/i18n/de.json +20 -0
  31. package/i18n/en.json +20 -0
  32. package/i18n/es.json +20 -0
  33. package/i18n/fr.json +20 -0
  34. package/i18n/it.json +20 -0
  35. package/i18n/nl.json +20 -0
  36. package/i18n/pl.json +20 -0
  37. package/i18n/pt.json +20 -0
  38. package/i18n/ru.json +20 -0
  39. package/i18n/uk.json +20 -0
  40. package/i18n/zh-cn.json +20 -0
  41. package/package.json +1 -3
@@ -47,7 +47,6 @@ interface TreeTableState {
47
47
  order: 'desc' | 'asc';
48
48
  update: string[] | null;
49
49
  orderBy: string;
50
- showSelectColor: boolean;
51
50
  selectIdValue?: string | null;
52
51
  showSelectId?: boolean;
53
52
  data?: Record<string, any>[];
@@ -65,10 +64,15 @@ export declare class TreeTable extends Component<TreeTableProps, TreeTableState>
65
64
  renderCellEditNumber(col: Column, val: number): JSX.Element;
66
65
  renderCellEditCustom(col: Column, val: any, item: Record<string, any>): JSX.Element | null;
67
66
  renderCellEditBoolean(col: Column, val: boolean): JSX.Element;
68
- renderSelectColorDialog(): JSX.Element;
69
67
  renderCellEditColor(col: Column, val: string): JSX.Element;
70
68
  renderSelectIdDialog(): JSX.Element | null;
71
69
  renderCellEditObjectID(col: Column, val: string): JSX.Element;
70
+ /**
71
+ * Show a color as swatch together with its value.
72
+ *
73
+ * @param color The color in any CSS notation.
74
+ */
75
+ static renderColorValue(color: string): JSX.Element;
72
76
  static renderCellNonEdit(item: Record<string, any>, col: Column): JSX.Element | string | number | null;
73
77
  renderCell(item: Record<string, any>, col: Column, level: number, i: number): JSX.Element;
74
78
  static renderCellWithSubField(item: Record<string, any>, col: Column): JSX.Element;
@@ -1,8 +1,9 @@
1
1
  import React, { Component } from 'react';
2
- import { HexColorPicker as ColorPicker } from 'react-colorful';
3
- import { Fab, Table, TableBody, TableCell, TableHead, TableRow, TableSortLabel, IconButton, Select, MenuItem, TextField, Checkbox, Dialog, } from '@mui/material';
4
- import { Edit as IconEdit, Delete as IconDelete, NavigateNext as IconExpand, ExpandMore as IconCollapse, Check as IconCheck, Close as IconClose, Add as IconAdd, ViewHeadline as IconList, Colorize as IconColor, } from '@mui/icons-material';
2
+ import { Box, Fab, Table, TableBody, TableCell, TableHead, TableRow, TableSortLabel, IconButton, Select, MenuItem, TextField, Checkbox, Tooltip, } from '@mui/material';
3
+ import { Edit as IconEdit, Delete as IconDelete, NavigateNext as IconExpand, Check as IconCheck, Close as IconClose, Add as IconAdd, ViewHeadline as IconList, } from '@mui/icons-material';
5
4
  import { DialogSelectID } from '../Dialogs/SelectID';
5
+ import { ColorPicker, parseColor } from './ColorPicker';
6
+ import { I18n } from '../i18n';
6
7
  import { Utils } from './Utils';
7
8
  function getAttr(obj, attr, lookup) {
8
9
  if (typeof attr === 'string') {
@@ -33,6 +34,8 @@ function setAttr(obj, attr, value) {
33
34
  }
34
35
  return setAttr(obj[name], attr, value);
35
36
  }
37
+ /** Checkerboard, so a semi-transparent color is recognizable as such */
38
+ const ALPHA_BACKGROUND = 'linear-gradient(45deg, #c0c0c0 25%, transparent 25%), linear-gradient(-45deg, #c0c0c0 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #c0c0c0 75%), linear-gradient(-45deg, transparent 75%, #c0c0c0 75%)';
36
39
  const styles = {
37
40
  tableContainer: {
38
41
  width: '100%',
@@ -43,32 +46,66 @@ const styles = {
43
46
  width: '100%',
44
47
  minWidth: 800,
45
48
  maxWidth: 1920,
49
+ borderCollapse: 'separate',
46
50
  },
47
- cell: {
48
- paddingTop: 0,
49
- paddingBottom: 0,
50
- paddingLeft: 4,
51
- paddingRight: 4,
52
- },
51
+ cell: (theme) => ({
52
+ py: '4px',
53
+ px: '8px',
54
+ borderBottom: `1px solid ${theme.palette.divider}`,
55
+ }),
56
+ row: (theme) => ({
57
+ transition: 'background-color 0.15s ease-in-out',
58
+ '&:hover': {
59
+ backgroundColor: theme.palette.action.hover,
60
+ },
61
+ // Show the row actions only while the row is hovered or focused. Only the buttons are faded out -
62
+ // the cell itself must stay visible, else its bottom border would disappear too.
63
+ '& .iob-table-actions .MuiIconButton-root': {
64
+ opacity: 0,
65
+ transition: 'opacity 0.15s ease-in-out',
66
+ },
67
+ '&:hover .iob-table-actions .MuiIconButton-root, &:focus-within .iob-table-actions .MuiIconButton-root': {
68
+ opacity: 1,
69
+ },
70
+ }),
53
71
  rowMainWithChildren: {},
54
72
  rowMainWithoutChildren: {},
55
73
  rowNoEdit: {
56
- opacity: 0.3,
74
+ opacity: 0.35,
57
75
  },
76
+ rowEditing: (theme) => ({
77
+ backgroundColor: theme.palette.action.selected,
78
+ '& .iob-table-actions .MuiIconButton-root': {
79
+ opacity: 1,
80
+ },
81
+ }),
58
82
  cellExpand: {
59
- width: 30,
83
+ width: 36,
84
+ pr: 0,
60
85
  },
61
86
  cellButton: {
62
- width: 30,
87
+ width: 40,
88
+ textAlign: 'center',
63
89
  },
64
- cellHeader: {
65
- fontWeight: 'bold',
66
- background: (theme) => (theme.palette.mode === 'dark' ? '#888' : '#888'),
67
- color: (theme) => (theme.palette.mode === 'dark' ? '#EEE' : '#111'),
68
- height: 48,
90
+ cellHeader: (theme) => ({
91
+ fontWeight: 600,
92
+ fontSize: '0.72rem',
93
+ textTransform: 'uppercase',
94
+ letterSpacing: '0.06em',
95
+ lineHeight: 1.4,
96
+ backgroundColor: theme.palette.background.default,
97
+ color: theme.palette.text.secondary,
98
+ borderBottom: `2px solid ${theme.palette.divider}`,
99
+ height: 44,
69
100
  wordBreak: 'break-word',
70
- whiteSpace: 'pre',
71
- },
101
+ whiteSpace: 'nowrap',
102
+ '& .MuiTableSortLabel-root': {
103
+ color: 'inherit',
104
+ },
105
+ '& .MuiTableSortLabel-root:hover, & .MuiTableSortLabel-root.Mui-active': {
106
+ color: theme.palette.text.primary,
107
+ },
108
+ }),
72
109
  width_name_nicknames: {
73
110
  maxWidth: 150,
74
111
  },
@@ -84,11 +121,24 @@ const styles = {
84
121
  width_roomHint: {
85
122
  maxWidth: 100,
86
123
  },
87
- rowSecondary: {
88
- fontStyle: 'italic',
124
+ rowSecondary: {},
125
+ cellSecondary: (theme) => ({
126
+ fontSize: '0.8rem',
127
+ color: theme.palette.text.secondary,
128
+ }),
129
+ /** Vertical guide in front of a child row, so the hierarchy stays readable */
130
+ childIndent: (theme) => ({
131
+ display: 'inline-block',
132
+ borderLeft: `1px solid ${theme.palette.divider}`,
133
+ height: 20,
134
+ mr: '8px',
135
+ verticalAlign: 'middle',
136
+ }),
137
+ expandButton: {
138
+ transition: 'transform 0.15s ease-in-out',
89
139
  },
90
- cellSecondary: {
91
- fontSize: 10,
140
+ expandButtonOpened: {
141
+ transform: 'rotate(90deg)',
92
142
  },
93
143
  visuallyHidden: {
94
144
  border: 0,
@@ -108,20 +158,53 @@ const styles = {
108
158
  fieldEdit: {
109
159
  width: '100%',
110
160
  display: 'inline-block',
111
- lineHeight: '50px',
112
161
  verticalAlign: 'middle',
113
162
  },
114
163
  fieldButton: {
115
164
  width: 30,
116
165
  display: 'inline-block',
117
166
  },
118
- colorDialog: {
119
- overflow: 'hidden',
120
- padding: 15,
167
+ mainText: {
168
+ fontSize: '0.875rem',
121
169
  },
122
170
  subText: {
123
- fontSize: 10,
124
- fontStyle: 'italic',
171
+ fontSize: '0.7rem',
172
+ opacity: 0.7,
173
+ },
174
+ /** Color cell: swatch plus the value in a monospace font */
175
+ colorCell: {
176
+ display: 'flex',
177
+ alignItems: 'center',
178
+ gap: '8px',
179
+ },
180
+ colorSwatch: {
181
+ width: 22,
182
+ height: 22,
183
+ flexShrink: 0,
184
+ borderRadius: '5px',
185
+ boxShadow: '0 0 0 1px rgba(128,128,128,.35) inset',
186
+ backgroundImage: ALPHA_BACKGROUND,
187
+ backgroundSize: '8px 8px',
188
+ backgroundPosition: '0 0, 0 4px, 4px -4px, -4px 0px',
189
+ },
190
+ colorSwatchEmpty: {
191
+ border: '1px dashed',
192
+ borderColor: 'divider',
193
+ backgroundImage: 'none',
194
+ boxSizing: 'border-box',
195
+ },
196
+ colorSwatchFill: {
197
+ width: '100%',
198
+ height: '100%',
199
+ borderRadius: 'inherit',
200
+ },
201
+ colorValue: {
202
+ fontFamily: 'monospace',
203
+ fontSize: '0.78rem',
204
+ whiteSpace: 'nowrap',
205
+ },
206
+ colorValueInvalid: {
207
+ color: 'error.main',
125
208
  },
126
209
  glow: {
127
210
  animation: 'glow 0.2s 2 alternate',
@@ -177,7 +260,6 @@ export class TreeTable extends Component {
177
260
  order: 'asc',
178
261
  update: null,
179
262
  orderBy: this.props.columns[0].field,
180
- showSelectColor: false,
181
263
  };
182
264
  }
183
265
  componentWillUnmount() {
@@ -275,33 +357,9 @@ export class TreeTable extends Component {
275
357
  ? !!this.state.editData[col.field]
276
358
  : !!val, onChange: e => this.onChange(col, !!val, e.target.checked), slotProps: { input: { 'aria-label': 'checkbox' } } }));
277
359
  }
278
- renderSelectColorDialog() {
279
- return (React.createElement(Dialog, { sx: {
280
- '& .MuiPaper-root': styles.root,
281
- '& .MuiPaper-paper': styles.paper,
282
- }, onClose: () => {
283
- this.selectCallback = null;
284
- this.setState({ showSelectColor: false });
285
- }, open: this.state.showSelectColor },
286
- React.createElement(ColorPicker, { color: this.state.selectIdValue || undefined, onChange: color => this.setState({ selectIdValue: color }, () => {
287
- if (this.selectCallback) {
288
- this.selectCallback(color);
289
- }
290
- }) })));
291
- }
292
360
  renderCellEditColor(col, val) {
293
361
  const _val = this.state.editData && this.state.editData[col.field] !== undefined ? this.state.editData[col.field] : val;
294
- return (React.createElement("div", { style: styles.fieldEdit },
295
- React.createElement(TextField, { variant: "standard", fullWidth: true, style: styles.fieldEditWithButton, value: _val, slotProps: {
296
- htmlInput: {
297
- style: { backgroundColor: _val, color: Utils.isUseBright(_val) ? '#FFF' : '#000' },
298
- },
299
- }, onChange: e => this.onChange(col, !!val, e.target.value) }),
300
- React.createElement(IconButton, { style: styles.fieldButton, onClick: () => {
301
- this.selectCallback = newColor => this.onChange(col, val, newColor);
302
- this.setState({ showSelectColor: true, selectIdValue: val });
303
- }, size: "large" },
304
- React.createElement(IconColor, null))));
362
+ return (React.createElement(ColorPicker, { id: `ar_tree_table_color_${col.field}`, style: styles.fieldEdit, value: _val || '', onChange: color => this.onChange(col, val, color) }));
305
363
  }
306
364
  renderSelectIdDialog() {
307
365
  if (this.state.showSelectId && this.props.socket) {
@@ -327,21 +385,33 @@ export class TreeTable extends Component {
327
385
  }, size: "large" },
328
386
  React.createElement(IconList, null))));
329
387
  }
388
+ /**
389
+ * Show a color as swatch together with its value.
390
+ *
391
+ * @param color The color in any CSS notation.
392
+ */
393
+ static renderColorValue(color) {
394
+ const isValid = !!color && !!parseColor(color);
395
+ return (React.createElement(Box, { component: "div", sx: styles.colorCell },
396
+ React.createElement(Box, { component: "div", sx: { ...styles.colorSwatch, ...(isValid ? undefined : styles.colorSwatchEmpty) }, title: color || undefined }, isValid ? (React.createElement(Box, { component: "div", sx: styles.colorSwatchFill, style: { background: color } })) : null),
397
+ React.createElement(Box, { component: "span", sx: { ...styles.colorValue, ...(color && !isValid ? styles.colorValueInvalid : undefined) } }, color || '')));
398
+ }
330
399
  static renderCellNonEdit(item, col) {
331
400
  let val = getAttr(item, col.field, col.lookup);
332
401
  if (Array.isArray(val)) {
333
402
  val = val[0];
334
403
  }
335
404
  if (col.type === 'boolean') {
336
- return (React.createElement(Checkbox, { checked: !!val, disabled: true, slotProps: { input: { 'aria-label': 'checkbox' } } }));
405
+ return (React.createElement(Checkbox, { checked: !!val, disabled: true, size: "small", slotProps: { input: { 'aria-label': 'checkbox' } } }));
406
+ }
407
+ if (col.type === 'color') {
408
+ return TreeTable.renderColorValue(typeof val === 'string' ? val : '');
337
409
  }
338
410
  return val;
339
411
  }
340
412
  renderCell(item, col, level, i) {
341
- if (this.state.editMode === i && col.editable !== 'never' && col.editable !== false) {
342
- return (React.createElement(TableCell, { key: col.field, style: { ...styles.cell, ...(level ? styles.cellSecondary : undefined), ...col.cellStyle }, component: "th" }, this.renderCellEdit(item, col)));
343
- }
344
- return (React.createElement(TableCell, { key: col.field, style: { ...styles.cell, ...(level ? styles.cellSecondary : undefined), ...col.cellStyle }, component: "th" }, TreeTable.renderCellNonEdit(item, col)));
413
+ const isEdit = this.state.editMode === i && col.editable !== 'never' && col.editable !== false;
414
+ return (React.createElement(TableCell, { key: col.field, sx: Utils.getStyle(this.props.theme, styles.cell, level ? styles.cellSecondary : undefined), style: col.cellStyle, component: "th" }, isEdit ? this.renderCellEdit(item, col) : TreeTable.renderCellNonEdit(item, col)));
345
415
  }
346
416
  static renderCellWithSubField(item, col) {
347
417
  const main = getAttr(item, col.field, col.lookup);
@@ -370,16 +440,16 @@ export class TreeTable extends Component {
370
440
  // try to find children
371
441
  const opened = this.state.opened.includes(item.id);
372
442
  const children = this.props.data.filter(it => it.parentId === item.id);
373
- const row = (React.createElement(TableRow, { key: item.id, className: `table-row-${(item.id || '').toString().replace(/[.$]/g, '_')}`, style: {
374
- ...((this.state.update && this.state.update.includes(item.id) && styles.glow) || undefined),
375
- ...styles.row,
376
- ...(level ? styles.rowSecondary : undefined),
377
- ...(!level && children.length ? styles.rowMainWithChildren : undefined),
378
- ...(!level && !children.length ? styles.rowMainWithoutChildren : undefined),
379
- ...(this.state.editMode !== false && this.state.editMode !== i ? styles.rowNoEdit : undefined),
380
- ...(this.state.deleteMode !== false && this.state.deleteMode !== i ? styles.rowNoEdit : undefined),
381
- } },
382
- React.createElement(TableCell, { style: { ...styles.cell, ...styles.cellExpand, ...(level ? styles.cellSecondary : undefined) } }, children.length ? (React.createElement(IconButton, { onClick: () => {
443
+ const isEditingThis = this.state.editMode === i || this.state.deleteMode === i;
444
+ const isBlurred = (this.state.editMode !== false && this.state.editMode !== i) ||
445
+ (this.state.deleteMode !== false && this.state.deleteMode !== i);
446
+ const row = (React.createElement(TableRow, { key: item.id, className: `table-row-${(item.id || '').toString().replace(/[.$]/g, '_')}`, sx: Utils.getStyle(this.props.theme, styles.row, level ? styles.rowSecondary : undefined, !level && children.length ? styles.rowMainWithChildren : undefined, !level && !children.length ? styles.rowMainWithoutChildren : undefined, isEditingThis ? styles.rowEditing : undefined, isBlurred ? styles.rowNoEdit : undefined), style: this.state.update && this.state.update.includes(item.id)
447
+ ? { ...styles.glow }
448
+ : undefined },
449
+ React.createElement(TableCell, { sx: Utils.getStyle(this.props.theme, styles.cell, styles.cellExpand, level ? styles.cellSecondary : undefined) }, children.length ? (React.createElement(IconButton, { sx: {
450
+ ...styles.expandButton,
451
+ ...(opened ? styles.expandButtonOpened : undefined),
452
+ }, title: I18n.t(opened ? 'ra_Collapse' : 'ra_Expand'), onClick: () => {
383
453
  const _opened = [...this.state.opened];
384
454
  const pos = _opened.indexOf(item.id);
385
455
  if (pos === -1) {
@@ -391,36 +461,44 @@ export class TreeTable extends Component {
391
461
  }
392
462
  (window._localStorage || window.localStorage).setItem(this.props.name || 'iob-table', JSON.stringify(_opened));
393
463
  this.setState({ opened: _opened });
394
- }, size: "small" }, opened ? React.createElement(IconCollapse, null) : React.createElement(IconExpand, null))) : null),
395
- React.createElement(TableCell, { scope: "row", style: {
396
- ...styles.cell,
397
- ...(level ? styles.cellSecondary : undefined),
398
- ...this.props.columns[0].cellStyle,
399
- paddingLeft: levelShift * level,
400
- } }, this.props.columns[0].subField
401
- ? TreeTable.renderCellWithSubField(item, this.props.columns[0])
402
- : getAttr(item, this.props.columns[0].field, this.props.columns[0].lookup)),
464
+ }, size: "small" },
465
+ React.createElement(IconExpand, { fontSize: "small" }))) : null),
466
+ React.createElement(TableCell, { scope: "row", sx: Utils.getStyle(this.props.theme, styles.cell, level ? styles.cellSecondary : undefined), style: { ...this.props.columns[0].cellStyle, paddingLeft: levelShift * level } },
467
+ React.createElement(Box, { component: "div", sx: { display: 'flex', alignItems: 'center' } },
468
+ level ? (React.createElement(Box, { component: "span", sx: styles.childIndent })) : null,
469
+ this.props.columns[0].subField
470
+ ? TreeTable.renderCellWithSubField(item, this.props.columns[0])
471
+ : getAttr(item, this.props.columns[0].field, this.props.columns[0].lookup))),
403
472
  this.props.columns.map((col, ii) => !ii && !col.hidden ? null : this.renderCell(item, col, level, i)),
404
- this.props.onUpdate ? (React.createElement(TableCell, { style: { ...styles.cell, ...styles.cellButton } }, this.state.editMode === i || this.state.deleteMode === i ? (React.createElement(IconButton, { disabled: this.state.editMode !== false &&
405
- (!this.state.editData || !Object.keys(this.state.editData).length), onClick: () => {
406
- if (this.state.editMode !== false) {
407
- const newData = JSON.parse(JSON.stringify(item));
408
- this.state.editData &&
409
- Object.keys(this.state.editData).forEach(attr => setAttr(newData, attr, this.state.editData?.[attr]));
410
- this.setState({ editMode: false }, () => this.props.onUpdate && this.props.onUpdate(newData, item));
411
- }
412
- else {
413
- this.setState({ deleteMode: false }, () => this.props.onDelete && this.props.onDelete(item));
414
- }
415
- }, size: "large" },
416
- React.createElement(IconCheck, null))) : (React.createElement(IconButton, { disabled: this.state.editMode !== false, onClick: () => this.setState({ editMode: i, editData: null }), size: "large" },
417
- React.createElement(IconEdit, null))))) : null,
418
- this.props.onDelete && !this.props.onUpdate ? (React.createElement(TableCell, { style: { ...styles.cell, ...styles.cellButton } }, this.state.deleteMode === i ? (React.createElement(IconButton, { disabled: this.state.editMode !== false &&
419
- (!this.state.editData || !Object.keys(this.state.editData).length), onClick: () => this.setState({ deleteMode: false }, () => this.props.onDelete && this.props.onDelete(item)), size: "large" },
420
- React.createElement(IconCheck, null))) : null)) : null,
421
- this.props.onUpdate || this.props.onDelete ? (React.createElement(TableCell, { style: { ...styles.cell, ...styles.cellButton } }, this.state.editMode === i || this.state.deleteMode === i ? (React.createElement(IconButton, { onClick: () => this.setState({ editMode: false, deleteMode: false }), size: "large" },
422
- React.createElement(IconClose, null))) : this.props.onDelete ? (React.createElement(IconButton, { disabled: this.state.deleteMode !== false, onClick: () => this.setState({ deleteMode: i }), size: "large" },
423
- React.createElement(IconDelete, null))) : null)) : null));
473
+ this.props.onUpdate ? (React.createElement(TableCell, { className: "iob-table-actions", sx: Utils.getStyle(this.props.theme, styles.cell, styles.cellButton) }, isEditingThis ? (React.createElement(Tooltip, { title: I18n.t(this.state.editMode !== false ? 'ra_Save' : 'ra_Delete') },
474
+ React.createElement("span", null,
475
+ React.createElement(IconButton, { color: this.state.deleteMode !== false ? 'error' : 'primary', disabled: this.state.editMode !== false &&
476
+ (!this.state.editData || !Object.keys(this.state.editData).length), onClick: () => {
477
+ if (this.state.editMode !== false) {
478
+ const newData = JSON.parse(JSON.stringify(item));
479
+ this.state.editData &&
480
+ Object.keys(this.state.editData).forEach(attr => setAttr(newData, attr, this.state.editData?.[attr]));
481
+ this.setState({ editMode: false }, () => this.props.onUpdate && this.props.onUpdate(newData, item));
482
+ }
483
+ else {
484
+ this.setState({ deleteMode: false }, () => this.props.onDelete && this.props.onDelete(item));
485
+ }
486
+ }, size: "small" },
487
+ React.createElement(IconCheck, { fontSize: "small" }))))) : (React.createElement(Tooltip, { title: I18n.t('ra_Edit') },
488
+ React.createElement("span", null,
489
+ React.createElement(IconButton, { disabled: this.state.editMode !== false, onClick: () => this.setState({ editMode: i, editData: null }), size: "small" },
490
+ React.createElement(IconEdit, { fontSize: "small" }))))))) : null,
491
+ this.props.onDelete && !this.props.onUpdate ? (React.createElement(TableCell, { className: "iob-table-actions", sx: Utils.getStyle(this.props.theme, styles.cell, styles.cellButton) }, this.state.deleteMode === i ? (React.createElement(Tooltip, { title: I18n.t('ra_Delete') },
492
+ React.createElement("span", null,
493
+ React.createElement(IconButton, { color: "error", disabled: this.state.editMode !== false &&
494
+ (!this.state.editData || !Object.keys(this.state.editData).length), onClick: () => this.setState({ deleteMode: false }, () => this.props.onDelete && this.props.onDelete(item)), size: "small" },
495
+ React.createElement(IconCheck, { fontSize: "small" }))))) : null)) : null,
496
+ this.props.onUpdate || this.props.onDelete ? (React.createElement(TableCell, { className: "iob-table-actions", sx: Utils.getStyle(this.props.theme, styles.cell, styles.cellButton) }, isEditingThis ? (React.createElement(Tooltip, { title: I18n.t('ra_Cancel') },
497
+ React.createElement(IconButton, { onClick: () => this.setState({ editMode: false, deleteMode: false }), size: "small" },
498
+ React.createElement(IconClose, { fontSize: "small" })))) : this.props.onDelete ? (React.createElement(Tooltip, { title: I18n.t('ra_Delete') },
499
+ React.createElement("span", null,
500
+ React.createElement(IconButton, { disabled: this.state.deleteMode !== false, onClick: () => this.setState({ deleteMode: i }), size: "small" },
501
+ React.createElement(IconDelete, { fontSize: "small" }))))) : null)) : null));
424
502
  if (!level && opened) {
425
503
  const items = children.map(it => this.renderLine(it, level + 1));
426
504
  items.unshift(row);
@@ -446,8 +524,11 @@ export class TreeTable extends Component {
446
524
  this.props.columns.map((col, i) => !i && !col.hidden ? null : (React.createElement(TableCell, { key: col.field, sx: Utils.getStyle(this.props.theme, styles.cell, styles.cellHeader, styles[`width_${col.field.replace(/\./g, '_')}`]), style: col.headerStyle || col.cellStyle, component: "th" }, this.props.noSort ? null : (React.createElement(TableSortLabel, { active: this.state.orderBy === col.field, direction: this.state.orderBy === col.field ? this.state.order : 'asc', onClick: () => this.handleRequestSort(col.field) },
447
525
  col.title || col.field,
448
526
  this.state.orderBy === col.field ? (React.createElement("span", { style: styles.visuallyHidden }, this.state.order === 'desc' ? 'sorted descending' : 'sorted ascending')) : null))))),
449
- this.props.onUpdate ? (React.createElement(TableCell, { component: "th", sx: Utils.getStyle(this.props.theme, styles.cell, styles.cellHeader, styles.cellButton) }, !this.props.noAdd ? (React.createElement(Fab, { color: "primary", size: "small", disabled: this.state.editMode !== false, onClick: () => this.props.onUpdate && this.props.onUpdate(true) },
450
- React.createElement(IconAdd, null))) : null)) : null,
527
+ this.props.onUpdate ? (React.createElement(TableCell, { component: "th", sx: Utils.getStyle(this.props.theme, styles.cell, styles.cellHeader, styles.cellButton) }, !this.props.noAdd ? (React.createElement(Tooltip, { title: I18n.t('ra_Add') },
528
+ React.createElement("span", null,
529
+ React.createElement(Fab, { color: "primary", size: "small", sx: { width: 30, height: 30, minHeight: 30, boxShadow: 2 }, disabled: this.state.editMode !== false, onClick: () => this.props.onUpdate &&
530
+ this.props.onUpdate(true) },
531
+ React.createElement(IconAdd, { fontSize: "small" }))))) : null)) : null,
451
532
  this.props.onDelete || this.props.onUpdate ? (React.createElement(TableCell, { component: "th", sx: Utils.getStyle(this.props.theme, styles.cell, styles.cellHeader, styles.cellButton) })) : null)));
452
533
  }
453
534
  render() {
@@ -466,8 +547,7 @@ export class TreeTable extends Component {
466
547
  React.createElement(Table, { style: styles.table, "aria-label": "simple table", size: "small", stickyHeader: true },
467
548
  this.renderHead(),
468
549
  React.createElement(TableBody, null, table.map(it => this.renderLine(it)))),
469
- this.renderSelectIdDialog(),
470
- this.renderSelectColorDialog()));
550
+ this.renderSelectIdDialog()));
471
551
  }
472
552
  return null;
473
553
  }