goblin-desktop 2.0.21 → 2.0.24

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 (143) hide show
  1. package/.editorconfig +9 -9
  2. package/.eslintrc.js +28 -28
  3. package/.zou-flow +3 -3
  4. package/README.md +108 -108
  5. package/builders/builders.js +3 -3
  6. package/builders/wizard.js +457 -457
  7. package/contexts.js +13 -13
  8. package/desktop-manager.js +10 -10
  9. package/desktop-window.js +13 -13
  10. package/desktop.js +13 -13
  11. package/lib/service.js +137 -137
  12. package/package.json +36 -36
  13. package/password-wizard.js +13 -13
  14. package/quest-run-wizard.js +13 -13
  15. package/taskbar.js +13 -13
  16. package/widgets/audio/sfx.js +177 -177
  17. package/widgets/board/view.js +37 -37
  18. package/widgets/board/widget.js +65 -65
  19. package/widgets/contexts/logic-handlers.js +36 -36
  20. package/widgets/contexts/service.js +40 -40
  21. package/widgets/contexts/view.js +22 -22
  22. package/widgets/contexts/widget.js +147 -147
  23. package/widgets/datagrid/datagrid-entity.js +82 -82
  24. package/widgets/datagrid/datagrid-headers.js +272 -272
  25. package/widgets/datagrid/styles.js +13 -13
  26. package/widgets/datagrid/widget.js +192 -192
  27. package/widgets/datagrid-cell/styles.js +52 -52
  28. package/widgets/datagrid-cell/widget.js +41 -41
  29. package/widgets/datagrid-item/styles.js +15 -15
  30. package/widgets/datagrid-item/widget.js +74 -74
  31. package/widgets/default/view.js +95 -91
  32. package/widgets/desktop/compensator.js +9 -9
  33. package/widgets/desktop/logic-handlers.js +237 -237
  34. package/widgets/desktop/reducer.js +35 -35
  35. package/widgets/desktop/service.js +828 -828
  36. package/widgets/desktop/styles.js +28 -28
  37. package/widgets/desktop/widget.js +175 -175
  38. package/widgets/desktop-clock/styles.js +69 -69
  39. package/widgets/desktop-clock/widget.js +387 -387
  40. package/widgets/desktop-clock-clock/styles.js +56 -56
  41. package/widgets/desktop-clock-clock/widget.js +96 -96
  42. package/widgets/desktop-clock-menu/styles.js +129 -129
  43. package/widgets/desktop-clock-menu/widget.js +63 -63
  44. package/widgets/desktop-connection-status/reducer.js +15 -15
  45. package/widgets/desktop-connection-status/styles.js +44 -44
  46. package/widgets/desktop-connection-status/widget.js +129 -129
  47. package/widgets/desktop-content/widget.js +68 -68
  48. package/widgets/desktop-footer/reducer.js +31 -31
  49. package/widgets/desktop-footer/styles.js +36 -36
  50. package/widgets/desktop-footer/widget.js +52 -52
  51. package/widgets/desktop-monitors/styles.js +155 -155
  52. package/widgets/desktop-monitors/widget.js +272 -272
  53. package/widgets/desktop-notebook/styles.js +155 -155
  54. package/widgets/desktop-notebook/widget.js +252 -252
  55. package/widgets/desktop-notifications/styles.js +147 -147
  56. package/widgets/desktop-notifications/widget.js +231 -231
  57. package/widgets/desktop-scale/reducer.js +15 -15
  58. package/widgets/desktop-scale/styles.js +48 -48
  59. package/widgets/desktop-scale/widget.js +172 -172
  60. package/widgets/desktop-state-monitor/styles.js +72 -72
  61. package/widgets/desktop-state-monitor/widget.js +123 -123
  62. package/widgets/desktop-taskbar/widget.js +57 -57
  63. package/widgets/desktop-themes-menu/widget.js +121 -121
  64. package/widgets/desktop-topbar/widget.js +201 -201
  65. package/widgets/desktop-window/service.js +56 -56
  66. package/widgets/desktop-window/styles.js +22 -22
  67. package/widgets/desktop-window/widget.js +70 -70
  68. package/widgets/detail/compensator.js +17 -17
  69. package/widgets/detail/view.js +40 -40
  70. package/widgets/detail/widget.js +125 -125
  71. package/widgets/editor/widget.js +84 -80
  72. package/widgets/entity-alerts/styles.js +77 -77
  73. package/widgets/entity-alerts/widget.js +328 -328
  74. package/widgets/entity-list/styles.js +66 -66
  75. package/widgets/entity-list/view.js +36 -36
  76. package/widgets/entity-list/widget.js +209 -209
  77. package/widgets/entity-list-item/widget.js +68 -68
  78. package/widgets/entity-row/styles.js +105 -105
  79. package/widgets/entity-row/widget.js +524 -524
  80. package/widgets/entity-row-button/styles.js +46 -46
  81. package/widgets/entity-row-button/widget.js +57 -57
  82. package/widgets/entity-view/reducer.js +20 -20
  83. package/widgets/entity-view/styles.js +90 -90
  84. package/widgets/entity-view/widget.js +516 -516
  85. package/widgets/facet-checkbox/styles.js +17 -17
  86. package/widgets/facet-checkbox/widget.js +43 -43
  87. package/widgets/facet-filter/widget.js +94 -94
  88. package/widgets/facet-filter-add/styles.js +30 -30
  89. package/widgets/facet-filter-add/widget.js +105 -105
  90. package/widgets/facet-filter-button/styles.js +74 -74
  91. package/widgets/facet-filter-button/widget.js +214 -214
  92. package/widgets/facet-filter-list-dialog/styles.js +59 -59
  93. package/widgets/facet-filter-list-dialog/widget.js +253 -253
  94. package/widgets/facet-filter-list-dialog-footer/styles.js +22 -22
  95. package/widgets/facet-filter-list-dialog-footer/widget.js +105 -105
  96. package/widgets/facet-filter-range-dialog/styles.js +82 -82
  97. package/widgets/facet-filter-range-dialog/widget.js +399 -399
  98. package/widgets/facet-filter-range-dialog-footer/styles.js +22 -22
  99. package/widgets/facet-filter-range-dialog-footer/widget.js +182 -182
  100. package/widgets/gamepad/widget.js +75 -75
  101. package/widgets/helpers/facet-helpers.js +105 -105
  102. package/widgets/hinter/reducer.js +35 -35
  103. package/widgets/hinter/styles.js +79 -79
  104. package/widgets/hinter/view.js +31 -31
  105. package/widgets/hinter/widget.js +291 -291
  106. package/widgets/junction/styles.js +22 -22
  107. package/widgets/junction/widget.js +50 -50
  108. package/widgets/main-tab-menu/styles.js +17 -17
  109. package/widgets/main-tab-menu/widget.js +136 -136
  110. package/widgets/map/view.js +49 -49
  111. package/widgets/map/widget.js +65 -65
  112. package/widgets/monitor/reducer.js +15 -15
  113. package/widgets/monitor/widget.js +66 -66
  114. package/widgets/navigating-layer/widget.js +25 -25
  115. package/widgets/notifications-button/widget.js +44 -44
  116. package/widgets/password-wizard/service.js +53 -53
  117. package/widgets/password-wizard/ui.js +66 -66
  118. package/widgets/plugin/reducer.js +19 -19
  119. package/widgets/plugin/styles.js +294 -294
  120. package/widgets/plugin/widget.js +637 -636
  121. package/widgets/quest-run-wizard/service.js +49 -49
  122. package/widgets/quest-run-wizard/ui.js +25 -25
  123. package/widgets/search/styles.js +80 -80
  124. package/widgets/search/widget.js +285 -285
  125. package/widgets/simple/view.js +29 -29
  126. package/widgets/status-filters/widget.js +121 -121
  127. package/widgets/tab/styles.js +16 -16
  128. package/widgets/tab/widget.js +89 -89
  129. package/widgets/tab-content/widget.js +35 -35
  130. package/widgets/tabs/widget.js +48 -48
  131. package/widgets/taskbar/service.js +99 -99
  132. package/widgets/taskbar/view.js +24 -24
  133. package/widgets/taskbar/widget.js +167 -167
  134. package/widgets/widget-doc-caller/reducer.js +15 -15
  135. package/widgets/widget-doc-caller/styles.js +20 -20
  136. package/widgets/widget-doc-caller/widget.js +55 -55
  137. package/widgets/wizard/widget.js +299 -299
  138. package/widgets/wizard-buttons/widget.js +111 -107
  139. package/widgets/workitem/styles.js +281 -281
  140. package/widgets/workitem/view.js +62 -62
  141. package/widgets/workitem/widget.js +971 -971
  142. package/widgets/workitem-dialog/widget.js +86 -86
  143. package/widgets/workitem-fields/widget.js +63 -63
@@ -1,328 +1,328 @@
1
- import React from 'react';
2
- import Widget from 'goblin-laboratory/widgets/widget';
3
- import Shredder from 'xcraft-core-shredder';
4
- import T from 't';
5
- import {ColorManipulator} from 'goblin-theme';
6
- import StringBuilder from 'goblin-nabu/lib/string-builder';
7
-
8
- import Label from 'goblin-gadgets/widgets/label/widget';
9
- import Button from 'goblin-gadgets/widgets/button/widget';
10
- import RetroIlluminatedButton from 'goblin-gadgets/widgets/retro-illuminated-button/widget';
11
-
12
- /******************************************************************************/
13
-
14
- class EntityAlerts extends Widget {
15
- constructor() {
16
- super(...arguments);
17
-
18
- this.state = {
19
- extended: false,
20
- };
21
- }
22
-
23
- //#region get/set
24
- get extended() {
25
- return this.state.extended;
26
- }
27
- set extended(value) {
28
- this.setState({
29
- extended: value,
30
- });
31
- }
32
- //#endregion
33
-
34
- get isRetro() {
35
- return this.context.theme.look.name === 'retro';
36
- }
37
-
38
- getColor(type) {
39
- let color =
40
- {
41
- error: '#e60000', // red
42
- warning: '#ffc000', // orange
43
- info: '#00b42a', // green
44
- }[type] || '#888';
45
-
46
- if (this.isRetro) {
47
- color = ColorManipulator.darken(color, 0.4);
48
- }
49
-
50
- return color;
51
- }
52
-
53
- getColorBackground(type) {
54
- return (
55
- {
56
- error: '#fed9d9', // light red
57
- warning: '#fff4d3', // light orange
58
- info: '#d9fedb', // light green
59
- }[type] || '#888'
60
- );
61
- }
62
-
63
- getGlyph(type) {
64
- return (
65
- {
66
- error: 'solid/exclamation-triangle',
67
- warning: 'solid/info-square',
68
- info: 'solid/book',
69
- }[type] || 'solid/bug'
70
- );
71
- }
72
-
73
- /******************************************************************************/
74
-
75
- renderGlyph(type, width, index) {
76
- const color = this.getColor(type);
77
- const glyph = this.getGlyph(type);
78
-
79
- if (this.isRetro) {
80
- return (
81
- <>
82
- <RetroIlluminatedButton
83
- key={index}
84
- glyph={glyph}
85
- glyphSize="150%"
86
- width="40px"
87
- height="40px"
88
- material="led"
89
- color={color}
90
- backgroundColor={this.getColorBackground(type)}
91
- />
92
- <Label width={width ? null : '20px'} />
93
- </>
94
- );
95
- } else {
96
- return (
97
- <Label
98
- key={index}
99
- glyph={glyph}
100
- width={width || '50px'}
101
- glyphSize="120%"
102
- glyphColor={color}
103
- />
104
- );
105
- }
106
- }
107
-
108
- renderGlyphs(type, count) {
109
- const result = [];
110
-
111
- let overflow = false;
112
- if (count > 3) {
113
- count = 3;
114
- overflow = true;
115
- }
116
-
117
- for (let i = 0; i < count; i++) {
118
- result.push(this.renderGlyph(type, '40px', i));
119
- }
120
-
121
- if (overflow) {
122
- result.push(<Label key="last" text="..." fontSize="135%" />);
123
- }
124
-
125
- return result;
126
- }
127
-
128
- renderAlert(alert, index) {
129
- const {type, message} = alert.pick('type', 'message');
130
-
131
- const color = this.getColor(type);
132
- const style = {
133
- borderLeft: this.isRetro ? null : `10px solid ${color}`,
134
- backgroundColor: this.getColorBackground(type),
135
- };
136
-
137
- return (
138
- <div key={index} className={this.styles.classNames.alert} style={style}>
139
- {this.renderGlyph(type)}
140
- <Label kind="alert" text={message} />
141
- </div>
142
- );
143
- }
144
-
145
- renderAlerts(errors, warnings, infos) {
146
- return (
147
- <>
148
- {errors.map((alert, index) =>
149
- this.renderAlert(new Shredder(alert), index)
150
- )}
151
- {warnings.map((alert, index) =>
152
- this.renderAlert(new Shredder(alert), index)
153
- )}
154
- {infos.map((alert, index) =>
155
- this.renderAlert(new Shredder(alert), index)
156
- )}
157
- </>
158
- );
159
- }
160
-
161
- renderGroup(group, index) {
162
- const alerts = group.get('alerts');
163
- const errors = alerts.filter((a) => a.get('type') === 'error');
164
- const warnings = alerts.filter((a) => a.get('type') === 'warning');
165
- const infos = alerts.filter((a) => a.get('type') === 'info');
166
-
167
- if (errors.size === 0 && warnings.size === 0 && infos.size === 0) {
168
- return null;
169
- }
170
-
171
- let type = '#ccc';
172
- if (infos.size > 0) {
173
- type = 'info';
174
- }
175
- if (warnings.size > 0) {
176
- type = 'warning';
177
- }
178
- if (errors.size > 0) {
179
- type = 'error';
180
- }
181
-
182
- const color = this.getColor(type);
183
- const style = {
184
- borderLeft: this.isRetro ? `30px solid ${color}` : `10px solid ${color}`,
185
- backgroundColor: this.getColorBackground(type),
186
- };
187
-
188
- const title = group.get('title', null);
189
-
190
- return (
191
- <div key={index} className={this.styles.classNames.group} style={style}>
192
- {title ? (
193
- <div key={index} className={this.styles.classNames.title}>
194
- <Label textTransform="uppercase" fontWeight="bold" text={title} />
195
- </div>
196
- ) : null}
197
- {this.renderAlerts(errors, warnings, infos)}
198
- </div>
199
- );
200
- }
201
-
202
- renderAlertCompacted() {
203
- const {alerts} = this.props;
204
-
205
- const counts = alerts.reduce(
206
- (counts, group) => {
207
- counts.errors += group
208
- .get('alerts')
209
- .filter((a) => a.get('type') === 'error').size;
210
- counts.warnings += group
211
- .get('alerts')
212
- .filter((a) => a.get('type') === 'warning').size;
213
- counts.infos += group
214
- .get('alerts')
215
- .filter((a) => a.get('type') === 'info').size;
216
- return counts;
217
- },
218
- {errors: 0, warnings: 0, infos: 0}
219
- );
220
-
221
- const nError = counts.errors;
222
- const nWarning = counts.warnings;
223
- const nInfo = counts.infos;
224
-
225
- if (nError === 0 && nWarning === 0 && nInfo === 0) {
226
- return null;
227
- }
228
-
229
- const a = [];
230
- if (nError === 1) {
231
- a.push(T('1 erreur'));
232
- }
233
- if (nError > 1) {
234
- a.push(T('{nError} erreurs', null, {nError}));
235
- }
236
- if (nWarning === 1) {
237
- a.push(T('1 avertissement'));
238
- }
239
- if (nWarning > 1) {
240
- a.push(T('{nWarning} avertissements', null, {nWarning}));
241
- }
242
- if (nInfo === 1) {
243
- a.push(T('1 information'));
244
- }
245
- if (nInfo > 1) {
246
- a.push(T('{nInfo} informations', null, {nInfo}));
247
- }
248
- const message = StringBuilder.joinSentences(a);
249
-
250
- const type = nError > 0 ? 'error' : nWarning > 0 ? 'warning' : 'info';
251
-
252
- const color = this.getColor(type);
253
- const style = {
254
- borderLeft: this.isRetro ? `30px solid ${color}` : `10px solid ${color}`,
255
- backgroundColor: this.getColorBackground(type),
256
- };
257
-
258
- return (
259
- <div className={this.styles.classNames.compacted} style={style}>
260
- {this.renderGlyphs('error', nError)}
261
- {this.renderGlyphs('warning', nWarning)}
262
- {this.renderGlyphs('info', nInfo)}
263
- <Label width="20px" />
264
- <Label text={message} />
265
- </div>
266
- );
267
- }
268
-
269
- renderButton(total) {
270
- if (total === 1) {
271
- return null;
272
- }
273
-
274
- return (
275
- <div className={this.styles.classNames.button}>
276
- <Button
277
- glyph={this.extended ? 'solid/caret-up' : 'solid/caret-down'}
278
- border="none"
279
- width="30px"
280
- height="30px"
281
- onClick={() => (this.extended = !this.extended)}
282
- />
283
- </div>
284
- );
285
- }
286
-
287
- render() {
288
- const {alerts} = this.props;
289
- if (!alerts) {
290
- return null;
291
- }
292
-
293
- const total = alerts.reduce((count, group) => {
294
- count += group.get('alerts').size;
295
- return count;
296
- }, 0);
297
-
298
- if (total === 0) {
299
- return null;
300
- }
301
-
302
- return (
303
- <div className={this.styles.classNames.entityAlerts}>
304
- {this.extended || total === 1
305
- ? alerts.map((group, index) => this.renderGroup(group, index))
306
- : this.renderAlertCompacted()}
307
- {this.renderButton(total)}
308
- </div>
309
- );
310
- }
311
- }
312
-
313
- /******************************************************************************/
314
-
315
- const ConnectedEntityAlerts = Widget.connect((state, props) => {
316
- if (!props.entityId) {
317
- return {};
318
- }
319
- const alerts = state.get(`backend.${props.entityId}.meta.alerts`);
320
- if (!alerts) {
321
- return {};
322
- }
323
- return {
324
- alerts,
325
- };
326
- })(EntityAlerts);
327
-
328
- export default ConnectedEntityAlerts;
1
+ import React from 'react';
2
+ import Widget from 'goblin-laboratory/widgets/widget';
3
+ import Shredder from 'xcraft-core-shredder';
4
+ import T from 't';
5
+ import {ColorManipulator} from 'goblin-theme';
6
+ import StringBuilder from 'goblin-nabu/lib/string-builder';
7
+
8
+ import Label from 'goblin-gadgets/widgets/label/widget';
9
+ import Button from 'goblin-gadgets/widgets/button/widget';
10
+ import RetroIlluminatedButton from 'goblin-gadgets/widgets/retro-illuminated-button/widget';
11
+
12
+ /******************************************************************************/
13
+
14
+ class EntityAlerts extends Widget {
15
+ constructor() {
16
+ super(...arguments);
17
+
18
+ this.state = {
19
+ extended: false,
20
+ };
21
+ }
22
+
23
+ //#region get/set
24
+ get extended() {
25
+ return this.state.extended;
26
+ }
27
+ set extended(value) {
28
+ this.setState({
29
+ extended: value,
30
+ });
31
+ }
32
+ //#endregion
33
+
34
+ get isRetro() {
35
+ return this.context.theme.look.name === 'retro';
36
+ }
37
+
38
+ getColor(type) {
39
+ let color =
40
+ {
41
+ error: '#e60000', // red
42
+ warning: '#ffc000', // orange
43
+ info: '#00b42a', // green
44
+ }[type] || '#888';
45
+
46
+ if (this.isRetro) {
47
+ color = ColorManipulator.darken(color, 0.4);
48
+ }
49
+
50
+ return color;
51
+ }
52
+
53
+ getColorBackground(type) {
54
+ return (
55
+ {
56
+ error: '#fed9d9', // light red
57
+ warning: '#fff4d3', // light orange
58
+ info: '#d9fedb', // light green
59
+ }[type] || '#888'
60
+ );
61
+ }
62
+
63
+ getGlyph(type) {
64
+ return (
65
+ {
66
+ error: 'solid/exclamation-triangle',
67
+ warning: 'solid/info-square',
68
+ info: 'solid/book',
69
+ }[type] || 'solid/bug'
70
+ );
71
+ }
72
+
73
+ /******************************************************************************/
74
+
75
+ renderGlyph(type, width, index) {
76
+ const color = this.getColor(type);
77
+ const glyph = this.getGlyph(type);
78
+
79
+ if (this.isRetro) {
80
+ return (
81
+ <>
82
+ <RetroIlluminatedButton
83
+ key={index}
84
+ glyph={glyph}
85
+ glyphSize="150%"
86
+ width="40px"
87
+ height="40px"
88
+ material="led"
89
+ color={color}
90
+ backgroundColor={this.getColorBackground(type)}
91
+ />
92
+ <Label width={width ? null : '20px'} />
93
+ </>
94
+ );
95
+ } else {
96
+ return (
97
+ <Label
98
+ key={index}
99
+ glyph={glyph}
100
+ width={width || '50px'}
101
+ glyphSize="120%"
102
+ glyphColor={color}
103
+ />
104
+ );
105
+ }
106
+ }
107
+
108
+ renderGlyphs(type, count) {
109
+ const result = [];
110
+
111
+ let overflow = false;
112
+ if (count > 3) {
113
+ count = 3;
114
+ overflow = true;
115
+ }
116
+
117
+ for (let i = 0; i < count; i++) {
118
+ result.push(this.renderGlyph(type, '40px', i));
119
+ }
120
+
121
+ if (overflow) {
122
+ result.push(<Label key="last" text="..." fontSize="135%" />);
123
+ }
124
+
125
+ return result;
126
+ }
127
+
128
+ renderAlert(alert, index) {
129
+ const {type, message} = alert.pick('type', 'message');
130
+
131
+ const color = this.getColor(type);
132
+ const style = {
133
+ borderLeft: this.isRetro ? null : `10px solid ${color}`,
134
+ backgroundColor: this.getColorBackground(type),
135
+ };
136
+
137
+ return (
138
+ <div key={index} className={this.styles.classNames.alert} style={style}>
139
+ {this.renderGlyph(type)}
140
+ <Label kind="alert" text={message} />
141
+ </div>
142
+ );
143
+ }
144
+
145
+ renderAlerts(errors, warnings, infos) {
146
+ return (
147
+ <>
148
+ {errors.map((alert, index) =>
149
+ this.renderAlert(new Shredder(alert), index)
150
+ )}
151
+ {warnings.map((alert, index) =>
152
+ this.renderAlert(new Shredder(alert), index)
153
+ )}
154
+ {infos.map((alert, index) =>
155
+ this.renderAlert(new Shredder(alert), index)
156
+ )}
157
+ </>
158
+ );
159
+ }
160
+
161
+ renderGroup(group, index) {
162
+ const alerts = group.get('alerts');
163
+ const errors = alerts.filter((a) => a.get('type') === 'error');
164
+ const warnings = alerts.filter((a) => a.get('type') === 'warning');
165
+ const infos = alerts.filter((a) => a.get('type') === 'info');
166
+
167
+ if (errors.size === 0 && warnings.size === 0 && infos.size === 0) {
168
+ return null;
169
+ }
170
+
171
+ let type = '#ccc';
172
+ if (infos.size > 0) {
173
+ type = 'info';
174
+ }
175
+ if (warnings.size > 0) {
176
+ type = 'warning';
177
+ }
178
+ if (errors.size > 0) {
179
+ type = 'error';
180
+ }
181
+
182
+ const color = this.getColor(type);
183
+ const style = {
184
+ borderLeft: this.isRetro ? `30px solid ${color}` : `10px solid ${color}`,
185
+ backgroundColor: this.getColorBackground(type),
186
+ };
187
+
188
+ const title = group.get('title', null);
189
+
190
+ return (
191
+ <div key={index} className={this.styles.classNames.group} style={style}>
192
+ {title ? (
193
+ <div key={index} className={this.styles.classNames.title}>
194
+ <Label textTransform="uppercase" fontWeight="bold" text={title} />
195
+ </div>
196
+ ) : null}
197
+ {this.renderAlerts(errors, warnings, infos)}
198
+ </div>
199
+ );
200
+ }
201
+
202
+ renderAlertCompacted() {
203
+ const {alerts} = this.props;
204
+
205
+ const counts = alerts.reduce(
206
+ (counts, group) => {
207
+ counts.errors += group
208
+ .get('alerts')
209
+ .filter((a) => a.get('type') === 'error').size;
210
+ counts.warnings += group
211
+ .get('alerts')
212
+ .filter((a) => a.get('type') === 'warning').size;
213
+ counts.infos += group
214
+ .get('alerts')
215
+ .filter((a) => a.get('type') === 'info').size;
216
+ return counts;
217
+ },
218
+ {errors: 0, warnings: 0, infos: 0}
219
+ );
220
+
221
+ const nError = counts.errors;
222
+ const nWarning = counts.warnings;
223
+ const nInfo = counts.infos;
224
+
225
+ if (nError === 0 && nWarning === 0 && nInfo === 0) {
226
+ return null;
227
+ }
228
+
229
+ const a = [];
230
+ if (nError === 1) {
231
+ a.push(T('1 erreur'));
232
+ }
233
+ if (nError > 1) {
234
+ a.push(T('{nError} erreurs', null, {nError}));
235
+ }
236
+ if (nWarning === 1) {
237
+ a.push(T('1 avertissement'));
238
+ }
239
+ if (nWarning > 1) {
240
+ a.push(T('{nWarning} avertissements', null, {nWarning}));
241
+ }
242
+ if (nInfo === 1) {
243
+ a.push(T('1 information'));
244
+ }
245
+ if (nInfo > 1) {
246
+ a.push(T('{nInfo} informations', null, {nInfo}));
247
+ }
248
+ const message = StringBuilder.joinSentences(a);
249
+
250
+ const type = nError > 0 ? 'error' : nWarning > 0 ? 'warning' : 'info';
251
+
252
+ const color = this.getColor(type);
253
+ const style = {
254
+ borderLeft: this.isRetro ? `30px solid ${color}` : `10px solid ${color}`,
255
+ backgroundColor: this.getColorBackground(type),
256
+ };
257
+
258
+ return (
259
+ <div className={this.styles.classNames.compacted} style={style}>
260
+ {this.renderGlyphs('error', nError)}
261
+ {this.renderGlyphs('warning', nWarning)}
262
+ {this.renderGlyphs('info', nInfo)}
263
+ <Label width="20px" />
264
+ <Label text={message} />
265
+ </div>
266
+ );
267
+ }
268
+
269
+ renderButton(total) {
270
+ if (total === 1) {
271
+ return null;
272
+ }
273
+
274
+ return (
275
+ <div className={this.styles.classNames.button}>
276
+ <Button
277
+ glyph={this.extended ? 'solid/caret-up' : 'solid/caret-down'}
278
+ border="none"
279
+ width="30px"
280
+ height="30px"
281
+ onClick={() => (this.extended = !this.extended)}
282
+ />
283
+ </div>
284
+ );
285
+ }
286
+
287
+ render() {
288
+ const {alerts} = this.props;
289
+ if (!alerts) {
290
+ return null;
291
+ }
292
+
293
+ const total = alerts.reduce((count, group) => {
294
+ count += group.get('alerts').size;
295
+ return count;
296
+ }, 0);
297
+
298
+ if (total === 0) {
299
+ return null;
300
+ }
301
+
302
+ return (
303
+ <div className={this.styles.classNames.entityAlerts}>
304
+ {this.extended || total === 1
305
+ ? alerts.map((group, index) => this.renderGroup(group, index))
306
+ : this.renderAlertCompacted()}
307
+ {this.renderButton(total)}
308
+ </div>
309
+ );
310
+ }
311
+ }
312
+
313
+ /******************************************************************************/
314
+
315
+ const ConnectedEntityAlerts = Widget.connect((state, props) => {
316
+ if (!props.entityId) {
317
+ return {};
318
+ }
319
+ const alerts = state.get(`backend.${props.entityId}.meta.alerts`);
320
+ if (!alerts) {
321
+ return {};
322
+ }
323
+ return {
324
+ alerts,
325
+ };
326
+ })(EntityAlerts);
327
+
328
+ export default ConnectedEntityAlerts;