goblin-desktop 2.0.0 → 2.0.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.
Files changed (130) hide show
  1. package/README.md +108 -108
  2. package/builders/wizard.js +478 -478
  3. package/contexts.js +13 -13
  4. package/desktop-manager.js +10 -10
  5. package/desktop-window.js +13 -13
  6. package/desktop.js +13 -13
  7. package/lib/service.js +135 -135
  8. package/package.json +36 -36
  9. package/password-wizard.js +13 -13
  10. package/quest-run-wizard.js +13 -13
  11. package/taskbar.js +13 -13
  12. package/widgets/audio/sfx.js +177 -177
  13. package/widgets/board/view.js +37 -37
  14. package/widgets/board/widget.js +65 -65
  15. package/widgets/contexts/logic-handlers.js +36 -36
  16. package/widgets/contexts/service.js +40 -40
  17. package/widgets/contexts/view.js +22 -22
  18. package/widgets/contexts/widget.js +147 -147
  19. package/widgets/datagrid/datagrid-entity.js +82 -82
  20. package/widgets/datagrid/datagrid-headers.js +272 -272
  21. package/widgets/datagrid/datagrid-item.js +82 -82
  22. package/widgets/datagrid/styles.js +13 -13
  23. package/widgets/datagrid/widget.js +191 -191
  24. package/widgets/datagrid-cell/styles.js +52 -52
  25. package/widgets/datagrid-cell/widget.js +41 -41
  26. package/widgets/default/view.js +91 -91
  27. package/widgets/desktop/compensator.js +9 -9
  28. package/widgets/desktop/logic-handlers.js +237 -237
  29. package/widgets/desktop/service.js +816 -816
  30. package/widgets/desktop/styles.js +28 -28
  31. package/widgets/desktop/widget.js +175 -175
  32. package/widgets/desktop-clock/styles.js +69 -69
  33. package/widgets/desktop-clock/widget.js +387 -387
  34. package/widgets/desktop-clock-clock/styles.js +56 -56
  35. package/widgets/desktop-clock-clock/widget.js +96 -96
  36. package/widgets/desktop-clock-menu/styles.js +129 -129
  37. package/widgets/desktop-clock-menu/widget.js +63 -63
  38. package/widgets/desktop-connection-status/reducer.js +15 -15
  39. package/widgets/desktop-connection-status/styles.js +44 -44
  40. package/widgets/desktop-connection-status/widget.js +129 -129
  41. package/widgets/desktop-content/widget.js +68 -68
  42. package/widgets/desktop-footer/reducer.js +31 -31
  43. package/widgets/desktop-footer/styles.js +36 -36
  44. package/widgets/desktop-footer/widget.js +52 -52
  45. package/widgets/desktop-monitors/styles.js +155 -155
  46. package/widgets/desktop-monitors/widget.js +273 -273
  47. package/widgets/desktop-notebook/styles.js +155 -155
  48. package/widgets/desktop-notebook/widget.js +253 -253
  49. package/widgets/desktop-notifications/styles.js +147 -147
  50. package/widgets/desktop-notifications/widget.js +231 -231
  51. package/widgets/desktop-scale/reducer.js +15 -15
  52. package/widgets/desktop-scale/styles.js +48 -48
  53. package/widgets/desktop-scale/widget.js +172 -172
  54. package/widgets/desktop-state-monitor/styles.js +72 -72
  55. package/widgets/desktop-state-monitor/widget.js +123 -123
  56. package/widgets/desktop-taskbar/widget.js +57 -57
  57. package/widgets/desktop-themes-menu/widget.js +121 -121
  58. package/widgets/desktop-topbar/widget.js +201 -201
  59. package/widgets/desktop-window/service.js +56 -56
  60. package/widgets/desktop-window/styles.js +22 -22
  61. package/widgets/desktop-window/widget.js +70 -70
  62. package/widgets/detail/view.js +40 -40
  63. package/widgets/detail/widget.js +125 -125
  64. package/widgets/editor/widget.js +80 -80
  65. package/widgets/entity-alerts/styles.js +77 -77
  66. package/widgets/entity-alerts/widget.js +328 -328
  67. package/widgets/entity-list/view.js +36 -36
  68. package/widgets/entity-list/widget.js +209 -209
  69. package/widgets/entity-list-item/widget.js +68 -68
  70. package/widgets/entity-row/styles.js +104 -104
  71. package/widgets/entity-row/widget.js +523 -523
  72. package/widgets/entity-row-button/styles.js +46 -46
  73. package/widgets/entity-row-button/widget.js +57 -57
  74. package/widgets/entity-view/reducer.js +20 -20
  75. package/widgets/entity-view/styles.js +90 -90
  76. package/widgets/entity-view/widget.js +516 -516
  77. package/widgets/facet-checkbox/styles.js +17 -17
  78. package/widgets/facet-checkbox/widget.js +43 -43
  79. package/widgets/facet-filter/widget.js +94 -94
  80. package/widgets/facet-filter-add/styles.js +30 -30
  81. package/widgets/facet-filter-add/widget.js +105 -105
  82. package/widgets/facet-filter-button/styles.js +74 -74
  83. package/widgets/facet-filter-button/widget.js +214 -214
  84. package/widgets/facet-filter-list-dialog/styles.js +59 -59
  85. package/widgets/facet-filter-list-dialog/widget.js +253 -253
  86. package/widgets/facet-filter-list-dialog-footer/styles.js +22 -22
  87. package/widgets/facet-filter-list-dialog-footer/widget.js +105 -105
  88. package/widgets/facet-filter-range-dialog/styles.js +82 -82
  89. package/widgets/facet-filter-range-dialog/widget.js +398 -398
  90. package/widgets/facet-filter-range-dialog-footer/styles.js +22 -22
  91. package/widgets/facet-filter-range-dialog-footer/widget.js +182 -182
  92. package/widgets/gamepad/widget.js +75 -75
  93. package/widgets/helpers/facet-helpers.js +105 -105
  94. package/widgets/hinter/reducer.js +35 -35
  95. package/widgets/hinter/styles.js +79 -79
  96. package/widgets/hinter/view.js +31 -31
  97. package/widgets/hinter/widget.js +292 -292
  98. package/widgets/junction/styles.js +22 -22
  99. package/widgets/junction/widget.js +50 -50
  100. package/widgets/main-tab-menu/widget.js +136 -136
  101. package/widgets/map/view.js +49 -49
  102. package/widgets/map/widget.js +65 -65
  103. package/widgets/monitor/widget.js +66 -66
  104. package/widgets/navigating-layer/widget.js +25 -25
  105. package/widgets/notifications-button/widget.js +44 -44
  106. package/widgets/password-wizard/service.js +53 -53
  107. package/widgets/password-wizard/ui.js +66 -66
  108. package/widgets/plugin/styles.js +294 -294
  109. package/widgets/plugin/widget.js +636 -636
  110. package/widgets/quest-run-wizard/service.js +49 -49
  111. package/widgets/quest-run-wizard/ui.js +25 -25
  112. package/widgets/search/styles.js +80 -80
  113. package/widgets/search/widget.js +286 -284
  114. package/widgets/simple/view.js +29 -29
  115. package/widgets/status-filters/widget.js +121 -121
  116. package/widgets/tab/styles.js +16 -16
  117. package/widgets/tab/widget.js +88 -88
  118. package/widgets/tab-content/widget.js +35 -35
  119. package/widgets/tabs/widget.js +48 -48
  120. package/widgets/taskbar/service.js +99 -99
  121. package/widgets/taskbar/view.js +24 -24
  122. package/widgets/taskbar/widget.js +169 -169
  123. package/widgets/widget-doc-caller/widget.js +55 -55
  124. package/widgets/wizard/widget.js +299 -299
  125. package/widgets/wizard-buttons/widget.js +107 -107
  126. package/widgets/workitem/styles.js +281 -281
  127. package/widgets/workitem/view.js +62 -62
  128. package/widgets/workitem/widget.js +967 -940
  129. package/widgets/workitem-dialog/widget.js +86 -86
  130. package/widgets/workitem-fields/widget.js +63 -63
@@ -1,523 +1,523 @@
1
- //T:2019-02-27
2
- import React from 'react';
3
- import Widget from 'goblin-laboratory/widgets/widget';
4
- import TableCell from 'goblin-gadgets/widgets/table-cell/widget';
5
- import Gauge from 'goblin-gadgets/widgets/gauge/widget';
6
- import Label from 'goblin-gadgets/widgets/label/widget';
7
- import ColoredContainer from 'goblin-gadgets/widgets/colored-container/widget';
8
- import EntityRowButton from 'goblin-desktop/widgets/entity-row-button/widget';
9
- import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
10
- import T from 't';
11
- import ListHelpers from 'goblin-workshop/lib/list-helpers.js';
12
- import RetroGear from 'goblin-gadgets/widgets/retro-gear/widget';
13
- import {ColorManipulator} from 'goblin-theme';
14
- import Shredder from 'xcraft-core-shredder';
15
- import {Unit} from 'goblin-theme';
16
-
17
- /******************************************************************************/
18
-
19
- class _Driller extends Widget {
20
- constructor() {
21
- super(...arguments);
22
- this.renewTTL = this.renewTTL.bind(this);
23
- this._loadRequested = false;
24
- this._renewInterval = null;
25
- }
26
-
27
- renewTTL(id) {
28
- if (this._renewInterval) {
29
- clearInterval(this._renewInterval);
30
- }
31
- this._renewInterval = setInterval(this.props.onDrillDown, 15000, id);
32
- }
33
-
34
- componentWillUnmount() {
35
- super.componentWillUnmount();
36
- clearInterval(this._renewInterval);
37
- }
38
-
39
- /******************************************************************************/
40
-
41
- renderSpinner() {
42
- if (this.context.theme.look.name === 'retro') {
43
- return (
44
- <div className={this.styles.classNames.busyBox}>
45
- <RetroGear
46
- color={ColorManipulator.darken(
47
- this.context.theme.palette.light,
48
- 0.2
49
- )}
50
- left="0px"
51
- top="0px"
52
- radius="20px"
53
- toothCount={12}
54
- toothThickness={6}
55
- rotationDuration="3s"
56
- rotationDirection="cw"
57
- shadow="no"
58
- />
59
- </div>
60
- );
61
- } else {
62
- return <FontAwesomeIcon icon={[`fas`, 'spinner']} size={'1x'} pulse />;
63
- }
64
- }
65
-
66
- render() {
67
- if (this._loadRequested === false && this.props.entityId) {
68
- setTimeout(this.props.onDrillDown, 0, this.props.entityId);
69
- this.renewTTL(this.props.entityId);
70
- this._loadRequested = true;
71
- }
72
-
73
- if (this.props.loaded) {
74
- return (
75
- <TableCell
76
- rowId={this.props.rowId}
77
- isLast={false}
78
- isHeader={false}
79
- text={this.props.text}
80
- {...ListHelpers.getColumnProps(
81
- this.props.column,
82
- this.props.settings
83
- )}
84
- />
85
- );
86
- } else {
87
- return (
88
- <TableCell
89
- rowId={this.props.rowId}
90
- isLast={false}
91
- isHeader={false}
92
- {...ListHelpers.getColumnProps(
93
- this.props.column,
94
- this.props.settings
95
- )}
96
- >
97
- {this.renderSpinner()}
98
- </TableCell>
99
- );
100
- }
101
- }
102
- }
103
-
104
- /******************************************************************************/
105
-
106
- const Driller = Widget.connect((state, props) => {
107
- const loaded = !!state.get(`backend.${props.entityId}.id`, null);
108
- const path = props.path || 'meta.summaries.info';
109
- return {
110
- column: props.column,
111
- entityId: props.entityId,
112
- loaded: loaded,
113
- text: loaded ? state.get(`backend.${props.entityId}.${path}`) : '',
114
- };
115
- })(_Driller);
116
-
117
- /******************************************************************************/
118
-
119
- const Score = Widget.connect((state, props) => {
120
- const highlights = state.get(`backend.${props.listId}.highlights`);
121
- let score;
122
- if (highlights.get(props.entityId, null) !== null) {
123
- score = highlights.get(`${props.entityId}.score`);
124
- }
125
- return {value: score * 100};
126
- })(Gauge);
127
-
128
- /******************************************************************************/
129
-
130
- const Colored = Widget.connect((state, props) => {
131
- const highlights = state.get(`backend.${props.listId}.highlights`);
132
- let score;
133
- if (highlights.get(props.entityId, null) !== null) {
134
- score = highlights.get(`${props.entityId}.score`);
135
- }
136
- return {value: score * 100};
137
- })(ColoredContainer);
138
-
139
- /******************************************************************************/
140
-
141
- const TableCellWithHighlight = Widget.connect((state, props) => {
142
- const highlights = state.get(`backend.${props.listId}.highlights`);
143
- let text = props.text;
144
- if (highlights.get(props.entityId, null) !== null) {
145
- const auto = highlights.get(`${props.entityId}.auto`);
146
- const phonetic = highlights.get(`${props.entityId}.phonetic`);
147
- if (auto && !phonetic) {
148
- text = auto;
149
- }
150
- if (!auto && phonetic) {
151
- text = phonetic;
152
- }
153
- if (auto && phonetic) {
154
- text = auto;
155
- }
156
- }
157
- return {text};
158
- })(TableCell);
159
-
160
- /******************************************************************************/
161
-
162
- class EntityRow extends Widget {
163
- constructor() {
164
- super(...arguments);
165
- this.renewTTL = this.renewTTL.bind(this);
166
- this.onEditInStash = this.onEditInStash.bind(this);
167
- this.onEditAndOpen = this.onEditAndOpen.bind(this);
168
- this._idRequested = null;
169
- this._renewInterval = null;
170
- }
171
-
172
- renewTTL(id) {
173
- if (this._renewInterval) {
174
- clearInterval(this._renewInterval);
175
- }
176
- this._renewInterval = setInterval(this.props.onDrillDown, 15000, id);
177
- }
178
-
179
- onEditInStash() {
180
- this.props.onEdit(this.props.rowIndex, false);
181
- }
182
-
183
- onEditAndOpen() {
184
- this.props.onEdit(this.props.rowIndex, true);
185
- }
186
-
187
- componentWillUnmount() {
188
- super.componentWillUnmount();
189
- clearInterval(this._renewInterval);
190
- }
191
-
192
- isFilterPath(path) {
193
- if (this.props.hasFilter && this.props.filterPaths) {
194
- return this.props.filterPaths.includes(path);
195
- }
196
- return false;
197
- }
198
-
199
- /******************************************************************************/
200
-
201
- renderButtons() {
202
- return (
203
- <div className={`buttons-hover ${this.styles.classNames.buttons}`}>
204
- <EntityRowButton
205
- place="left"
206
- glyph="solid/external-link"
207
- tooltip={T('Editer plus tard')}
208
- onClick={this.onEditInStash}
209
- />
210
- <EntityRowButton
211
- place="right"
212
- glyph="solid/pencil"
213
- tooltip={T('Editer immédiatement')}
214
- onClick={this.onEditAndOpen}
215
- />
216
- </div>
217
- );
218
- }
219
-
220
- renderCellTextBar(cell, text, isFilter, index) {
221
- const props = ListHelpers.getColumnProps(cell, this.props.settings);
222
- const {type, width, ...otherProps} = props;
223
-
224
- if (isFilter) {
225
- const w = Unit.sub(width, '15px');
226
- return (
227
- <div key={index} className={this.styles.classNames.filteredCellBarre}>
228
- <Colored
229
- entityId={this.props.id}
230
- listId={this.props.listId}
231
- gradient="red-yellow-green"
232
- width="5px"
233
- alpha={0.9}
234
- />
235
- <Label width="10px" />
236
- <TableCellWithHighlight
237
- entityId={this.props.id}
238
- listId={this.props.listId}
239
- rowId={this.props.rowIndex}
240
- index={index}
241
- isLast={false}
242
- isHeader={false}
243
- width={w}
244
- {...otherProps}
245
- maxHeight={this.props.maxHeight}
246
- cellFormat="original"
247
- text={text}
248
- />
249
- </div>
250
- );
251
- } else {
252
- return (
253
- <TableCell
254
- rowId={this.props.rowIndex}
255
- key={index}
256
- index={index}
257
- isLast={false}
258
- isHeader={false}
259
- width={width}
260
- {...otherProps}
261
- maxHeight={this.props.maxHeight}
262
- cellFormat="original"
263
- text={text}
264
- />
265
- );
266
- }
267
- }
268
-
269
- renderCellTextCarnaval(cell, text, isFilter, index) {
270
- const props = ListHelpers.getColumnProps(cell, this.props.settings);
271
- const {type, width, ...otherProps} = props;
272
-
273
- if (isFilter) {
274
- const w = Unit.sub(width, '15px');
275
- return (
276
- <Colored
277
- key={index}
278
- entityId={this.props.id}
279
- listId={this.props.listId}
280
- gradient="red-yellow-green"
281
- margin="-2px 5px -2px 0px"
282
- padding="0px 0px 0px 10px"
283
- radius="5px"
284
- alpha={this.context.theme.palette.isDarkTheme ? 0.3 : 0.8}
285
- >
286
- <TableCellWithHighlight
287
- entityId={this.props.id}
288
- listId={this.props.listId}
289
- rowId={this.props.rowIndex}
290
- index={index}
291
- isLast={false}
292
- isHeader={false}
293
- width={w}
294
- {...otherProps}
295
- maxHeight={this.props.maxHeight}
296
- cellFormat="original"
297
- text={text}
298
- />
299
- </Colored>
300
- );
301
- } else {
302
- return (
303
- <TableCell
304
- rowId={this.props.rowIndex}
305
- key={index}
306
- index={index}
307
- isLast={false}
308
- isHeader={false}
309
- width={width}
310
- {...otherProps}
311
- maxHeight={this.props.maxHeight}
312
- cellFormat="original"
313
- text={text}
314
- />
315
- );
316
- }
317
- }
318
-
319
- renderCellTextGauge(cell, text, isFilter, index) {
320
- const props = ListHelpers.getColumnProps(cell, this.props.settings);
321
- const {type, width, ...otherProps} = props;
322
-
323
- if (isFilter) {
324
- const w = Unit.sub(width, '12px');
325
- return (
326
- <div key={index} className={this.styles.classNames.filteredCellGauge}>
327
- <Score
328
- entityId={this.props.id}
329
- listId={this.props.listId}
330
- kind="simple"
331
- gradient="red-yellow-green"
332
- direction="vertical"
333
- width="6px"
334
- height="unset"
335
- />
336
- <Label width="6px" />
337
- <TableCellWithHighlight
338
- entityId={this.props.id}
339
- listId={this.props.listId}
340
- rowId={this.props.rowIndex}
341
- index={index}
342
- isLast={false}
343
- isHeader={false}
344
- width={w}
345
- {...otherProps}
346
- maxHeight={this.props.maxHeight}
347
- cellFormat="original"
348
- text={text}
349
- />
350
- </div>
351
- );
352
- } else {
353
- return (
354
- <TableCell
355
- rowId={this.props.rowIndex}
356
- key={index}
357
- index={index}
358
- isLast={false}
359
- isHeader={false}
360
- width={width}
361
- {...otherProps}
362
- maxHeight={this.props.maxHeight}
363
- cellFormat="original"
364
- text={text}
365
- />
366
- );
367
- }
368
- }
369
-
370
- renderCellText(cell, text, isFilter, index) {
371
- switch (this.props.variant) {
372
- default:
373
- case 'gauge':
374
- return this.renderCellTextGauge(cell, text, isFilter, index);
375
- case 'bar':
376
- return this.renderCellTextBar(cell, text, isFilter, index);
377
- case 'carnaval':
378
- return this.renderCellTextCarnaval(cell, text, isFilter, index);
379
- }
380
- }
381
-
382
- renderCell(cell, index) {
383
- if (!cell) {
384
- return null;
385
- }
386
- const targetPath = ListHelpers.getColumnTargetPath(cell);
387
- const columnSubPath = ListHelpers.getColumnSubPath(cell);
388
- let text = ListHelpers.getColumnDisplayText(cell, this.props.entity);
389
-
390
- const {schema} = this.props;
391
- if (schema) {
392
- const propSchema = schema.get(targetPath, null);
393
- if (propSchema) {
394
- const {type} = propSchema.pick('type');
395
- if (type === 'enum') {
396
- const valuesInfo = propSchema.get('valuesInfo');
397
- if (valuesInfo) {
398
- text = valuesInfo.get(`${text}.text`, text);
399
- }
400
- }
401
- }
402
- }
403
-
404
- if (
405
- ListHelpers.isTargetingValueOrRef(this.props.entity, targetPath) &&
406
- text !== null
407
- ) {
408
- return (
409
- <Driller
410
- entityId={text}
411
- schema={this.props.schema}
412
- rowId={this.props.rowIndex}
413
- key={index}
414
- column={cell}
415
- onDrillDown={this.props.onDrillDown}
416
- onSelect={this.props.onSelect}
417
- onEdit={this.props.onEdit}
418
- path={columnSubPath}
419
- />
420
- );
421
- } else {
422
- const isFilter = this.isFilterPath(targetPath);
423
- return this.renderCellText(cell, text, isFilter, index);
424
- }
425
- }
426
-
427
- renderSpinner() {
428
- if (this.context.theme.look.name === 'retro') {
429
- return (
430
- <div className={this.styles.classNames.spinner}>
431
- <div className={this.styles.classNames.busyBox}>
432
- <RetroGear
433
- color={ColorManipulator.darken(
434
- this.context.theme.palette.light,
435
- 0.2
436
- )}
437
- left="0px"
438
- top="0px"
439
- radius="20px"
440
- toothCount={12}
441
- toothThickness={6}
442
- rotationDuration="3s"
443
- rotationDirection="cw"
444
- shadow="no"
445
- />
446
- </div>
447
- </div>
448
- );
449
- } else {
450
- return (
451
- <div className={this.styles.classNames.spinner}>
452
- <FontAwesomeIcon icon={[`fas`, 'spinner']} size={'1x'} pulse />
453
- </div>
454
- );
455
- }
456
- }
457
-
458
- render() {
459
- const {id, rowIndex, entity, columns, onDrillDown} = this.props;
460
- const loaded = id && entity;
461
-
462
- if (onDrillDown && id && this._idRequested !== id) {
463
- setTimeout(onDrillDown, 0, id);
464
- this.renewTTL(id);
465
- this._idRequested = id;
466
- }
467
-
468
- if (!loaded) {
469
- return (
470
- <div className={this.styles.classNames.busyEntityRow}>
471
- <TableCell isLast={false} isHeader={false}>
472
- {this.renderSpinner()}
473
- </TableCell>
474
- </div>
475
- );
476
- }
477
-
478
- const n = new Shredder({
479
- text: rowIndex + 1,
480
- weight: 'bold',
481
- });
482
-
483
- const divProps = {};
484
- if (this.props.onSelect) {
485
- divProps.onClick = () => this.props.onSelect(rowIndex);
486
- }
487
-
488
- return (
489
- <div className={this.styles.classNames.entityRow} {...divProps}>
490
- <TableCell
491
- rowId={rowIndex}
492
- index={rowIndex}
493
- isLast={false}
494
- isHeader={false}
495
- width={this.props.firstColumnWidth || '50px'}
496
- wrap="no-end"
497
- text={n}
498
- />
499
- {columns.map((c, i) => this.renderCell(c, i))}
500
- {this.renderButtons()}
501
- </div>
502
- );
503
- }
504
- }
505
-
506
- /******************************************************************************/
507
-
508
- export default Widget.connect((state, props) => {
509
- const entityId = props.useView ? `entity-view@${props.id}` : props.id;
510
- const entity = state.get(`backend.${entityId}`);
511
- if (!entity) {
512
- // TODO: !!!
513
- //? console.warn(`>>> Entity ${entityId} not found <<<`);
514
- } else if (!entity.get('meta')) {
515
- // TODO: Why some entities don't have meta ???
516
- //? console.warn(`>>> Entity ${entityId} has no meta <<<`);
517
- }
518
-
519
- return {
520
- id: props.id,
521
- entity,
522
- };
523
- })(EntityRow);
1
+ //T:2019-02-27
2
+ import React from 'react';
3
+ import Widget from 'goblin-laboratory/widgets/widget';
4
+ import TableCell from 'goblin-gadgets/widgets/table-cell/widget';
5
+ import Gauge from 'goblin-gadgets/widgets/gauge/widget';
6
+ import Label from 'goblin-gadgets/widgets/label/widget';
7
+ import ColoredContainer from 'goblin-gadgets/widgets/colored-container/widget';
8
+ import EntityRowButton from 'goblin-desktop/widgets/entity-row-button/widget';
9
+ import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
10
+ import T from 't';
11
+ import ListHelpers from 'goblin-workshop/lib/list-helpers.js';
12
+ import RetroGear from 'goblin-gadgets/widgets/retro-gear/widget';
13
+ import {ColorManipulator} from 'goblin-theme';
14
+ import Shredder from 'xcraft-core-shredder';
15
+ import {Unit} from 'goblin-theme';
16
+
17
+ /******************************************************************************/
18
+
19
+ class _Driller extends Widget {
20
+ constructor() {
21
+ super(...arguments);
22
+ this.renewTTL = this.renewTTL.bind(this);
23
+ this._loadRequested = false;
24
+ this._renewInterval = null;
25
+ }
26
+
27
+ renewTTL(id) {
28
+ if (this._renewInterval) {
29
+ clearInterval(this._renewInterval);
30
+ }
31
+ this._renewInterval = setInterval(this.props.onDrillDown, 15000, id);
32
+ }
33
+
34
+ componentWillUnmount() {
35
+ super.componentWillUnmount();
36
+ clearInterval(this._renewInterval);
37
+ }
38
+
39
+ /******************************************************************************/
40
+
41
+ renderSpinner() {
42
+ if (this.context.theme.look.name === 'retro') {
43
+ return (
44
+ <div className={this.styles.classNames.busyBox}>
45
+ <RetroGear
46
+ color={ColorManipulator.darken(
47
+ this.context.theme.palette.light,
48
+ 0.2
49
+ )}
50
+ left="0px"
51
+ top="0px"
52
+ radius="20px"
53
+ toothCount={12}
54
+ toothThickness={6}
55
+ rotationDuration="3s"
56
+ rotationDirection="cw"
57
+ shadow="no"
58
+ />
59
+ </div>
60
+ );
61
+ } else {
62
+ return <FontAwesomeIcon icon={[`fas`, 'spinner']} size={'1x'} pulse />;
63
+ }
64
+ }
65
+
66
+ render() {
67
+ if (this._loadRequested === false && this.props.entityId) {
68
+ setTimeout(this.props.onDrillDown, 0, this.props.entityId);
69
+ this.renewTTL(this.props.entityId);
70
+ this._loadRequested = true;
71
+ }
72
+
73
+ if (this.props.loaded) {
74
+ return (
75
+ <TableCell
76
+ rowId={this.props.rowId}
77
+ isLast={false}
78
+ isHeader={false}
79
+ text={this.props.text}
80
+ {...ListHelpers.getColumnProps(
81
+ this.props.column,
82
+ this.props.settings
83
+ )}
84
+ />
85
+ );
86
+ } else {
87
+ return (
88
+ <TableCell
89
+ rowId={this.props.rowId}
90
+ isLast={false}
91
+ isHeader={false}
92
+ {...ListHelpers.getColumnProps(
93
+ this.props.column,
94
+ this.props.settings
95
+ )}
96
+ >
97
+ {this.renderSpinner()}
98
+ </TableCell>
99
+ );
100
+ }
101
+ }
102
+ }
103
+
104
+ /******************************************************************************/
105
+
106
+ const Driller = Widget.connect((state, props) => {
107
+ const loaded = !!state.get(`backend.${props.entityId}.id`, null);
108
+ const path = props.path || 'meta.summaries.info';
109
+ return {
110
+ column: props.column,
111
+ entityId: props.entityId,
112
+ loaded: loaded,
113
+ text: loaded ? state.get(`backend.${props.entityId}.${path}`) : '',
114
+ };
115
+ })(_Driller);
116
+
117
+ /******************************************************************************/
118
+
119
+ const Score = Widget.connect((state, props) => {
120
+ const highlights = state.get(`backend.${props.listId}.highlights`);
121
+ let score;
122
+ if (highlights.get(props.entityId, null) !== null) {
123
+ score = highlights.get(`${props.entityId}.score`);
124
+ }
125
+ return {value: score * 100};
126
+ })(Gauge);
127
+
128
+ /******************************************************************************/
129
+
130
+ const Colored = Widget.connect((state, props) => {
131
+ const highlights = state.get(`backend.${props.listId}.highlights`);
132
+ let score;
133
+ if (highlights.get(props.entityId, null) !== null) {
134
+ score = highlights.get(`${props.entityId}.score`);
135
+ }
136
+ return {value: score * 100};
137
+ })(ColoredContainer);
138
+
139
+ /******************************************************************************/
140
+
141
+ const TableCellWithHighlight = Widget.connect((state, props) => {
142
+ const highlights = state.get(`backend.${props.listId}.highlights`);
143
+ let text = props.text;
144
+ if (highlights.get(props.entityId, null) !== null) {
145
+ const auto = highlights.get(`${props.entityId}.auto`);
146
+ const phonetic = highlights.get(`${props.entityId}.phonetic`);
147
+ if (auto && !phonetic) {
148
+ text = auto;
149
+ }
150
+ if (!auto && phonetic) {
151
+ text = phonetic;
152
+ }
153
+ if (auto && phonetic) {
154
+ text = auto;
155
+ }
156
+ }
157
+ return {text};
158
+ })(TableCell);
159
+
160
+ /******************************************************************************/
161
+
162
+ class EntityRow extends Widget {
163
+ constructor() {
164
+ super(...arguments);
165
+ this.renewTTL = this.renewTTL.bind(this);
166
+ this.onEditInStash = this.onEditInStash.bind(this);
167
+ this.onEditAndOpen = this.onEditAndOpen.bind(this);
168
+ this._idRequested = null;
169
+ this._renewInterval = null;
170
+ }
171
+
172
+ renewTTL(id) {
173
+ if (this._renewInterval) {
174
+ clearInterval(this._renewInterval);
175
+ }
176
+ this._renewInterval = setInterval(this.props.onDrillDown, 15000, id);
177
+ }
178
+
179
+ onEditInStash() {
180
+ this.props.onEdit(this.props.rowIndex, false);
181
+ }
182
+
183
+ onEditAndOpen() {
184
+ this.props.onEdit(this.props.rowIndex, true);
185
+ }
186
+
187
+ componentWillUnmount() {
188
+ super.componentWillUnmount();
189
+ clearInterval(this._renewInterval);
190
+ }
191
+
192
+ isFilterPath(path) {
193
+ if (this.props.hasFilter && this.props.filterPaths) {
194
+ return this.props.filterPaths.includes(path);
195
+ }
196
+ return false;
197
+ }
198
+
199
+ /******************************************************************************/
200
+
201
+ renderButtons() {
202
+ return (
203
+ <div className={`buttons-hover ${this.styles.classNames.buttons}`}>
204
+ <EntityRowButton
205
+ place="left"
206
+ glyph="solid/external-link"
207
+ tooltip={T('Editer plus tard')}
208
+ onClick={this.onEditInStash}
209
+ />
210
+ <EntityRowButton
211
+ place="right"
212
+ glyph="solid/pencil"
213
+ tooltip={T('Editer immédiatement')}
214
+ onClick={this.onEditAndOpen}
215
+ />
216
+ </div>
217
+ );
218
+ }
219
+
220
+ renderCellTextBar(cell, text, isFilter, index) {
221
+ const props = ListHelpers.getColumnProps(cell, this.props.settings);
222
+ const {type, width, ...otherProps} = props;
223
+
224
+ if (isFilter) {
225
+ const w = Unit.sub(width, '15px');
226
+ return (
227
+ <div key={index} className={this.styles.classNames.filteredCellBarre}>
228
+ <Colored
229
+ entityId={this.props.id}
230
+ listId={this.props.listId}
231
+ gradient="red-yellow-green"
232
+ width="5px"
233
+ alpha={0.9}
234
+ />
235
+ <Label width="10px" />
236
+ <TableCellWithHighlight
237
+ entityId={this.props.id}
238
+ listId={this.props.listId}
239
+ rowId={this.props.rowIndex}
240
+ index={index}
241
+ isLast={false}
242
+ isHeader={false}
243
+ width={w}
244
+ {...otherProps}
245
+ maxHeight={this.props.maxHeight}
246
+ cellFormat="original"
247
+ text={text}
248
+ />
249
+ </div>
250
+ );
251
+ } else {
252
+ return (
253
+ <TableCell
254
+ rowId={this.props.rowIndex}
255
+ key={index}
256
+ index={index}
257
+ isLast={false}
258
+ isHeader={false}
259
+ width={width}
260
+ {...otherProps}
261
+ maxHeight={this.props.maxHeight}
262
+ cellFormat="original"
263
+ text={text}
264
+ />
265
+ );
266
+ }
267
+ }
268
+
269
+ renderCellTextCarnaval(cell, text, isFilter, index) {
270
+ const props = ListHelpers.getColumnProps(cell, this.props.settings);
271
+ const {type, width, ...otherProps} = props;
272
+
273
+ if (isFilter) {
274
+ const w = Unit.sub(width, '15px');
275
+ return (
276
+ <Colored
277
+ key={index}
278
+ entityId={this.props.id}
279
+ listId={this.props.listId}
280
+ gradient="red-yellow-green"
281
+ margin="-2px 5px -2px 0px"
282
+ padding="0px 0px 0px 10px"
283
+ radius="5px"
284
+ alpha={this.context.theme.palette.isDarkTheme ? 0.3 : 0.8}
285
+ >
286
+ <TableCellWithHighlight
287
+ entityId={this.props.id}
288
+ listId={this.props.listId}
289
+ rowId={this.props.rowIndex}
290
+ index={index}
291
+ isLast={false}
292
+ isHeader={false}
293
+ width={w}
294
+ {...otherProps}
295
+ maxHeight={this.props.maxHeight}
296
+ cellFormat="original"
297
+ text={text}
298
+ />
299
+ </Colored>
300
+ );
301
+ } else {
302
+ return (
303
+ <TableCell
304
+ rowId={this.props.rowIndex}
305
+ key={index}
306
+ index={index}
307
+ isLast={false}
308
+ isHeader={false}
309
+ width={width}
310
+ {...otherProps}
311
+ maxHeight={this.props.maxHeight}
312
+ cellFormat="original"
313
+ text={text}
314
+ />
315
+ );
316
+ }
317
+ }
318
+
319
+ renderCellTextGauge(cell, text, isFilter, index) {
320
+ const props = ListHelpers.getColumnProps(cell, this.props.settings);
321
+ const {type, width, ...otherProps} = props;
322
+
323
+ if (isFilter) {
324
+ const w = Unit.sub(width, '12px');
325
+ return (
326
+ <div key={index} className={this.styles.classNames.filteredCellGauge}>
327
+ <Score
328
+ entityId={this.props.id}
329
+ listId={this.props.listId}
330
+ kind="simple"
331
+ gradient="red-yellow-green"
332
+ direction="vertical"
333
+ width="6px"
334
+ height="unset"
335
+ />
336
+ <Label width="6px" />
337
+ <TableCellWithHighlight
338
+ entityId={this.props.id}
339
+ listId={this.props.listId}
340
+ rowId={this.props.rowIndex}
341
+ index={index}
342
+ isLast={false}
343
+ isHeader={false}
344
+ width={w}
345
+ {...otherProps}
346
+ maxHeight={this.props.maxHeight}
347
+ cellFormat="original"
348
+ text={text}
349
+ />
350
+ </div>
351
+ );
352
+ } else {
353
+ return (
354
+ <TableCell
355
+ rowId={this.props.rowIndex}
356
+ key={index}
357
+ index={index}
358
+ isLast={false}
359
+ isHeader={false}
360
+ width={width}
361
+ {...otherProps}
362
+ maxHeight={this.props.maxHeight}
363
+ cellFormat="original"
364
+ text={text}
365
+ />
366
+ );
367
+ }
368
+ }
369
+
370
+ renderCellText(cell, text, isFilter, index) {
371
+ switch (this.props.variant) {
372
+ default:
373
+ case 'gauge':
374
+ return this.renderCellTextGauge(cell, text, isFilter, index);
375
+ case 'bar':
376
+ return this.renderCellTextBar(cell, text, isFilter, index);
377
+ case 'carnaval':
378
+ return this.renderCellTextCarnaval(cell, text, isFilter, index);
379
+ }
380
+ }
381
+
382
+ renderCell(cell, index) {
383
+ if (!cell) {
384
+ return null;
385
+ }
386
+ const targetPath = ListHelpers.getColumnTargetPath(cell);
387
+ const columnSubPath = ListHelpers.getColumnSubPath(cell);
388
+ let text = ListHelpers.getColumnDisplayText(cell, this.props.entity);
389
+
390
+ const {schema} = this.props;
391
+ if (schema) {
392
+ const propSchema = schema.get(targetPath, null);
393
+ if (propSchema) {
394
+ const {type} = propSchema.pick('type');
395
+ if (type === 'enum') {
396
+ const valuesInfo = propSchema.get('valuesInfo');
397
+ if (valuesInfo) {
398
+ text = valuesInfo.get(`${text}.text`, text);
399
+ }
400
+ }
401
+ }
402
+ }
403
+
404
+ if (
405
+ ListHelpers.isTargetingValueOrRef(this.props.entity, targetPath) &&
406
+ text !== null
407
+ ) {
408
+ return (
409
+ <Driller
410
+ entityId={text}
411
+ schema={this.props.schema}
412
+ rowId={this.props.rowIndex}
413
+ key={index}
414
+ column={cell}
415
+ onDrillDown={this.props.onDrillDown}
416
+ onSelect={this.props.onSelect}
417
+ onEdit={this.props.onEdit}
418
+ path={columnSubPath}
419
+ />
420
+ );
421
+ } else {
422
+ const isFilter = this.isFilterPath(targetPath);
423
+ return this.renderCellText(cell, text, isFilter, index);
424
+ }
425
+ }
426
+
427
+ renderSpinner() {
428
+ if (this.context.theme.look.name === 'retro') {
429
+ return (
430
+ <div className={this.styles.classNames.spinner}>
431
+ <div className={this.styles.classNames.busyBox}>
432
+ <RetroGear
433
+ color={ColorManipulator.darken(
434
+ this.context.theme.palette.light,
435
+ 0.2
436
+ )}
437
+ left="0px"
438
+ top="0px"
439
+ radius="20px"
440
+ toothCount={12}
441
+ toothThickness={6}
442
+ rotationDuration="3s"
443
+ rotationDirection="cw"
444
+ shadow="no"
445
+ />
446
+ </div>
447
+ </div>
448
+ );
449
+ } else {
450
+ return (
451
+ <div className={this.styles.classNames.spinner}>
452
+ <FontAwesomeIcon icon={[`fas`, 'spinner']} size={'1x'} pulse />
453
+ </div>
454
+ );
455
+ }
456
+ }
457
+
458
+ render() {
459
+ const {id, rowIndex, entity, columns, onDrillDown} = this.props;
460
+ const loaded = id && entity;
461
+
462
+ if (onDrillDown && id && this._idRequested !== id) {
463
+ setTimeout(onDrillDown, 0, id);
464
+ this.renewTTL(id);
465
+ this._idRequested = id;
466
+ }
467
+
468
+ if (!loaded) {
469
+ return (
470
+ <div className={this.styles.classNames.busyEntityRow}>
471
+ <TableCell isLast={false} isHeader={false}>
472
+ {this.renderSpinner()}
473
+ </TableCell>
474
+ </div>
475
+ );
476
+ }
477
+
478
+ const n = new Shredder({
479
+ text: rowIndex + 1,
480
+ weight: 'bold',
481
+ });
482
+
483
+ const divProps = {};
484
+ if (this.props.onSelect) {
485
+ divProps.onClick = () => this.props.onSelect(rowIndex);
486
+ }
487
+
488
+ return (
489
+ <div className={this.styles.classNames.entityRow} {...divProps}>
490
+ <TableCell
491
+ rowId={rowIndex}
492
+ index={rowIndex}
493
+ isLast={false}
494
+ isHeader={false}
495
+ width={this.props.firstColumnWidth || '50px'}
496
+ wrap="no-end"
497
+ text={n}
498
+ />
499
+ {columns.map((c, i) => this.renderCell(c, i))}
500
+ {this.renderButtons()}
501
+ </div>
502
+ );
503
+ }
504
+ }
505
+
506
+ /******************************************************************************/
507
+
508
+ export default Widget.connect((state, props) => {
509
+ const entityId = props.useView ? `entity-view@${props.id}` : props.id;
510
+ const entity = state.get(`backend.${entityId}`);
511
+ if (!entity) {
512
+ // TODO: !!!
513
+ //? console.warn(`>>> Entity ${entityId} not found <<<`);
514
+ } else if (!entity.get('meta')) {
515
+ // TODO: Why some entities don't have meta ???
516
+ //? console.warn(`>>> Entity ${entityId} has no meta <<<`);
517
+ }
518
+
519
+ return {
520
+ id: props.id,
521
+ entity,
522
+ };
523
+ })(EntityRow);