goblin-gadgets 2.0.5 → 2.0.9

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.
@@ -2,7 +2,6 @@
2
2
  //T:2019-02-27
3
3
 
4
4
  const Goblin = require('xcraft-core-goblin');
5
- const common = require('goblin-workshop').common;
6
5
 
7
6
  module.exports = (config) => {
8
7
  const {name, initialState, actions, events, gadgets} = config;
@@ -30,6 +29,7 @@ module.exports = (config) => {
30
29
  ) {
31
30
  const childrenGadgets = {};
32
31
  if (gadgets) {
32
+ const {common} = require('goblin-workshop');
33
33
  yield common.createGadgets(quest, goblinName, gadgets, childrenGadgets);
34
34
  }
35
35
 
@@ -66,13 +66,13 @@ module.exports = (config) => {
66
66
  //Register gagdet quest handlers
67
67
  if (gadgets[key].onActions) {
68
68
  for (const handler of Object.keys(gadgets[key].onActions)) {
69
- logicHandlers[`${key}-${handler}`] = gadgets[key].onActions[handler];
69
+ const {jsify} = require('xcraft-core-utils/lib/string.js');
70
+ const questName = jsify(`${key}-${handler}`);
71
+ logicHandlers[questName] = gadgets[key].onActions[handler];
70
72
 
71
- Goblin.registerQuest(goblinName, `${key}-${handler}`, function (
72
- quest
73
- ) {
73
+ Goblin.registerQuest(goblinName, questName, function* (quest) {
74
74
  quest.do();
75
- quest.me.update();
75
+ yield quest.me.update();
76
76
  });
77
77
  }
78
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goblin-gadgets",
3
- "version": "2.0.5",
3
+ "version": "2.0.9",
4
4
  "description": "Gadgets library",
5
5
  "main": "./builders/builders.js",
6
6
  "scripts": {
package/table-gadget.js CHANGED
@@ -73,6 +73,26 @@ exports.xcraftCommands = function () {
73
73
  }
74
74
  }
75
75
  },
76
+ deselect: (state, action) => {
77
+ const id = action.rowId;
78
+ const selectedIds = state.get('selectedIds', []);
79
+ if (selectedIds.includes(id)) {
80
+ state = state.unpush('selectedIds', id);
81
+ }
82
+
83
+ return state;
84
+ },
85
+ deselectAll: (state) => {
86
+ return state.set('selectedIds', []);
87
+ },
88
+ selectAll: (state) => {
89
+ const rowIds = state
90
+ .get('sortedRows')
91
+ .map((row) => row.get('row').get('id'))
92
+ .valueSeq()
93
+ .toArray();
94
+ return state.set('selectedIds', rowIds);
95
+ },
76
96
  doubleClick: (state) => {
77
97
  // NOP, see doubleClick in events ---^
78
98
  return state;
@@ -545,6 +545,7 @@ export default function styles(theme, props) {
545
545
  const w = Unit.multiply(to(theme.shapes.lineHeight, cssUnit), 0.8);
546
546
  boxWidth = w;
547
547
  boxMinWidth = w;
548
+ boxSizing = 'content-box';
548
549
  activeColor = theme.palette.comboActiveBackground;
549
550
  borderActiveColor = theme.palette.comboActiveBackground;
550
551
  if (disabled) {
@@ -1070,7 +1071,7 @@ export default function styles(theme, props) {
1070
1071
  };
1071
1072
 
1072
1073
  return {
1073
- box: boxStyle,
1074
+ button: boxStyle,
1074
1075
  triangle: triangleStyle,
1075
1076
  busyBox: busyBoxStyle,
1076
1077
  busyGlyph: busyGlyphStyle,
@@ -258,7 +258,7 @@ export default class Button extends Widget {
258
258
  return null;
259
259
  }
260
260
  const result = [];
261
- const boxStyle = Object.assign({}, this.styles.props.box);
261
+ const boxStyle = Object.assign({}, this.styles.props.button);
262
262
  result.push(this.renderLabel(boxStyle));
263
263
  result.push(this.renderShortcut(boxStyle));
264
264
  result.push(this.renderFocusedForeground());
@@ -342,7 +342,7 @@ export default class Button extends Widget {
342
342
  propsTabIndex.tabIndex = 0;
343
343
  }
344
344
 
345
- const boxClass = this.styles.classNames.box;
345
+ const boxClass = this.styles.classNames.button;
346
346
 
347
347
  if (this.props.kind === 'container' || this.props.kind === 'box') {
348
348
  return (
@@ -1,5 +1,4 @@
1
1
  import * as SpacingHelpers from 'goblin-gadgets/widgets/helpers/spacing-helpers';
2
- import {Unit} from 'goblin-theme';
3
2
 
4
3
  /******************************************************************************/
5
4
 
@@ -9,18 +8,10 @@ export const propNames = [
9
8
  'horizontalSpacing',
10
9
  'shape',
11
10
  'width',
12
- 'comboDirection',
13
11
  ];
14
12
 
15
13
  export default function styles(theme, props) {
16
- const {
17
- grow,
18
- visibility,
19
- horizontalSpacing,
20
- shape,
21
- width,
22
- comboDirection,
23
- } = props;
14
+ const {grow, visibility, horizontalSpacing, shape, width} = props;
24
15
 
25
16
  let flexGrow = grow;
26
17
  let flexShrink = null;
@@ -43,7 +34,7 @@ export default function styles(theme, props) {
43
34
  borderRadius = theme.shapes.actionRadius;
44
35
  }
45
36
 
46
- const box = {
37
+ const buttonCombo = {
47
38
  display: 'flex',
48
39
  flexDirection: 'row',
49
40
  justifyContent: 'flex-start',
@@ -61,36 +52,21 @@ export default function styles(theme, props) {
61
52
  opacity: opacity,
62
53
  };
63
54
 
64
- const shadowBox = {...box};
65
- shadowBox.boxShadow = theme.shapes.comboShadow;
66
- shadowBox.borderRadius = borderRadius;
55
+ const buttonComboShadow = {...buttonCombo};
56
+ buttonComboShadow.boxShadow = theme.shapes.comboShadow;
57
+ buttonComboShadow.borderRadius = borderRadius;
67
58
 
68
- const focusedBox = {...box};
69
- focusedBox.boxShadow = theme.shapes.focusedShadow + theme.palette.focused;
70
- focusedBox.borderRadius = borderRadius;
59
+ const buttonComboFocused = {...buttonCombo};
60
+ buttonComboFocused.boxShadow =
61
+ theme.shapes.focusedShadow + theme.palette.focused;
62
+ buttonComboFocused.borderRadius = borderRadius;
71
63
 
72
- const comboBox = {
73
- position: 'absolute',
74
- right: comboDirection === 'right' ? null : '0px',
75
- left: comboDirection === 'right' ? '0px' : null,
76
- top: Unit.add(theme.shapes.lineHeight, '1px'),
77
- marginTop: theme.shapes.lineSpacing,
78
- zIndex: 1,
79
- display: 'flex',
80
- flexDirection: 'column',
81
- boxShadow: theme.shapes.calendarShadow,
82
- };
83
-
84
- const emptyCombo = {
85
- margin: theme.shapes.containerMargin,
86
- };
64
+ /******************************************************************************/
87
65
 
88
66
  return {
89
- box,
90
- shadowBox,
91
- focusedBox,
92
- comboBox,
93
- emptyCombo,
67
+ buttonCombo,
68
+ buttonComboShadow,
69
+ buttonComboFocused,
94
70
  };
95
71
  }
96
72
 
@@ -262,10 +262,10 @@ export default class ButtonCombo extends Widget {
262
262
  }
263
263
 
264
264
  const boxClass = this.state.showCombo
265
- ? this.styles.classNames.shadowBox
265
+ ? this.styles.classNames.buttonComboShadow
266
266
  : this.props.focus
267
- ? this.styles.classNames.focusedBox
268
- : this.styles.classNames.box;
267
+ ? this.styles.classNames.buttonComboFocused
268
+ : this.styles.classNames.buttonCombo;
269
269
 
270
270
  return (
271
271
  <span
@@ -258,6 +258,7 @@ class ColorPicker extends Widget {
258
258
  onBlur={this.onTextChanged}
259
259
  />
260
260
  <Button
261
+ kind="combo"
261
262
  glyph="solid/eye-dropper"
262
263
  tooltip={T('Colle la couleur contenue dans le bloc-notes')}
263
264
  onClick={this.onPaste}
@@ -31,7 +31,6 @@ import FileInput from 'goblin-gadgets/widgets/file-input/widget';
31
31
  import DirectoryInput from 'goblin-gadgets/widgets/directory-input/widget';
32
32
  import StateBrowser from 'goblin-gadgets/widgets/state-browser/widget';
33
33
 
34
- import Plugin from 'goblin-desktop/widgets/plugin/widget';
35
34
  import SchemaHelpers from 'goblin-toolbox/lib/schema-helpers';
36
35
 
37
36
  import importer from 'goblin_importer';
@@ -604,7 +603,7 @@ class Field extends Form {
604
603
  );
605
604
  FinalPlugin = this.mapWidget(WiredPlugin, 'entityIds', this.fullPath);
606
605
  } else {
607
- FinalPlugin = Plugin;
606
+ FinalPlugin = widgetImporter('plugin');
608
607
  }
609
608
 
610
609
  const FinalContainer = this.mapWidget(
@@ -1238,7 +1237,7 @@ class Field extends Form {
1238
1237
  WiredPlugin = Widget.Wired(CustomPlugin)(pluginId);
1239
1238
  FinalPlugin = this.mapWidget(WiredPlugin, 'entityIds', this.fullPath);
1240
1239
  } else {
1241
- FinalPlugin = Plugin;
1240
+ FinalPlugin = widgetImporter('plugin');
1242
1241
  }
1243
1242
 
1244
1243
  return (
@@ -38,7 +38,7 @@ function getLogoInitials(initials, pseudo, firstName, lastName) {
38
38
  }
39
39
 
40
40
  // The content of the logo is always in capitals.
41
- return text.toUpperCase();
41
+ return text.substring(0, 3).toUpperCase();
42
42
  }
43
43
 
44
44
  //-----------------------------------------------------------------------------
@@ -4,11 +4,35 @@ import GuildHelpers from '../guild-user-logo/guild-helpers';
4
4
 
5
5
  /******************************************************************************/
6
6
 
7
- export const propNames = ['size', 'color', 'shape', 'initials', 'onClick'];
7
+ export const propNames = [
8
+ 'size',
9
+ 'color',
10
+ 'shape',
11
+ 'initials',
12
+ 'pseudo',
13
+ 'firstName',
14
+ 'lastName',
15
+ 'onClick',
16
+ ];
8
17
 
9
18
  export default function styles(theme, props) {
10
- let {size = '50px', color, shape, initials = '?', onClick} = props;
19
+ let {
20
+ size = '50px',
21
+ color,
22
+ shape,
23
+ initials,
24
+ pseudo,
25
+ firstName,
26
+ lastName,
27
+ onClick,
28
+ } = props;
11
29
 
30
+ initials = GuildHelpers.getLogoInitials(
31
+ initials,
32
+ pseudo,
33
+ firstName,
34
+ lastName
35
+ );
12
36
  color = GuildHelpers.getLogoColor(color);
13
37
  shape = GuildHelpers.getLogoShape(shape);
14
38
 
@@ -20,6 +44,7 @@ export default function styles(theme, props) {
20
44
  'flexDirection': 'column',
21
45
  'justifyContent': 'center',
22
46
  'alignItems': 'center',
47
+ 'cursor': onClick ? 'pointer' : null,
23
48
  'transition': theme.transitions.hover,
24
49
  ':hover': {
25
50
  transform: onClick ? 'scale(1.1)' : null,
@@ -26,11 +26,14 @@ export default class GuildUserLogo extends Widget {
26
26
  }
27
27
 
28
28
  renderInitials() {
29
- const text = this.props.initials
30
- ? this.props.initials.substring(0, 3)
31
- : '?';
29
+ const i = GuildHelpers.getLogoInitials(
30
+ this.props.initials,
31
+ this.props.pseudo,
32
+ this.props.firstName,
33
+ this.props.lastName
34
+ );
32
35
 
33
- return <div className={this.styles.classNames.text}>{text}</div>;
36
+ return <div className={this.styles.classNames.text}>{i}</div>;
34
37
  }
35
38
 
36
39
  renderLogo() {
@@ -132,7 +132,7 @@ export default class GuildUserProfile extends Widget {
132
132
  {id: 'triangle', glyph: 'solid/triangle', text: T('Triangle')},
133
133
  {id: 'certificate', glyph: 'solid/certificate', text: T('Fleur')},
134
134
  {id: 'star', glyph: 'solid/star', text: T('Etoile')},
135
- {id: 'heart', glyph: 'solid/heart', text: T('Coeur')},
135
+ {id: 'heart', glyph: 'solid/heart', text: T('Cœur')},
136
136
  ];
137
137
 
138
138
  return (
@@ -8,6 +8,9 @@ import throttle from 'lodash/throttle';
8
8
  * @param {Component} Component - The raw input to wrap
9
9
  * @param {string} valueName - (optional) Can be used to rename the 'value' prop
10
10
  * @returns {Component} A new component
11
+ *
12
+ * To make the wrapper work, the raw input must accept the following props:
13
+ * onChange, onFocus, onBlur and optionally onValidate
11
14
  */
12
15
  export default function wrapRawInput(Component, valueName = 'value') {
13
16
  /**
@@ -78,13 +78,14 @@ const initialState = new Shredder({
78
78
  export default (state = initialState, action = {}) => {
79
79
  switch (action.type) {
80
80
  case 'INITIALISE': {
81
- let {data, selectedIds} = action;
81
+ let {data, selectedIds, id} = action;
82
82
 
83
83
  if (!Shredder.isShredder(data)) {
84
84
  data = new Shredder(data);
85
85
  }
86
86
 
87
87
  state = state.set('data', data);
88
+ state = state.set('id', id);
88
89
 
89
90
  const defaultSortingColumns = data.get('defaultSortingColumns');
90
91
  if (defaultSortingColumns) {
@@ -150,6 +151,11 @@ export default (state = initialState, action = {}) => {
150
151
  }
151
152
 
152
153
  case 'MOVE_SELECTION': {
154
+ const mode = action.mode;
155
+ if (mode === 'multi') {
156
+ return state;
157
+ }
158
+
153
159
  const {direction} = action;
154
160
 
155
161
  const sortedRows = state.get('sortedRows');
@@ -170,6 +176,17 @@ export default (state = initialState, action = {}) => {
170
176
  state = updateAfterChangingSelection(state);
171
177
  return state;
172
178
  }
179
+
180
+ case 'DESELECT': {
181
+ const id = action.rowId;
182
+ const selectedIds = state.get('selectedIds', []);
183
+ if (selectedIds.includes(id)) {
184
+ state = state.unpush('selectedIds', id);
185
+ }
186
+
187
+ state = updateAfterChangingSelection(state);
188
+ return state;
189
+ }
173
190
  }
174
191
  return state;
175
192
  };
@@ -72,6 +72,7 @@ class Table extends Widget {
72
72
  data: this.props.data,
73
73
  sortingColumns: this.props.selectedIds,
74
74
  selectedIds,
75
+ id: this.props.id,
75
76
  });
76
77
  }
77
78
  }
@@ -120,6 +121,7 @@ class Table extends Widget {
120
121
  this.dispatch({
121
122
  type: 'MOVE_SELECTION',
122
123
  direction,
124
+ mode: this.props.selectionMode,
123
125
  });
124
126
  }
125
127
 
@@ -366,6 +366,9 @@ export default class TextFieldTypedNC extends Widget {
366
366
 
367
367
  handleDateClicked(date) {
368
368
  if (this.props.onChange) {
369
+ if (this.props.shift) {
370
+ date = DateConverters.addDays(date, -this.props.shift);
371
+ }
369
372
  this.props.onChange(date);
370
373
  }
371
374
  }
@@ -62,8 +62,8 @@ class WellDone extends Widget {
62
62
 
63
63
  return {
64
64
  position: 'absolute',
65
- left: '40%',
66
- top: '50%',
65
+ left: 'calc(50% - 150px)',
66
+ bottom: '160px',
67
67
  transform,
68
68
  animation,
69
69
  animationDelay,
@@ -114,8 +114,8 @@ class WellDone extends Widget {
114
114
  renderBoxBack(hidden) {
115
115
  const style = {
116
116
  position: 'absolute',
117
- left: '40%',
118
- top: '50%',
117
+ bottom: '0px',
118
+ left: 'calc(50% - 150px)',
119
119
  width: '300px',
120
120
  visibility: hidden ? 'hidden' : 'visible',
121
121
  };
@@ -126,8 +126,8 @@ class WellDone extends Widget {
126
126
  renderBoxFront(hidden) {
127
127
  const style = {
128
128
  position: 'absolute',
129
- left: '40%',
130
- top: '50%',
129
+ bottom: '0px',
130
+ left: 'calc(50% - 150px)',
131
131
  width: '300px',
132
132
  visibility: hidden ? 'hidden' : 'visible',
133
133
  };