hippo-fw 0.9.8 → 0.9.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/client/hippo/access/subscription-choice-layer.jsx +170 -0
  3. data/client/hippo/access/subscription-choice-layer/cancel-subscription.jsx +111 -0
  4. data/client/hippo/access/subscription-choice-layer/payment-form.jsx +154 -0
  5. data/client/hippo/access/subscription-choice-layer/subscription-choice.scss +29 -0
  6. data/client/hippo/boot.jsx +1 -1
  7. data/client/hippo/components/asset.jsx +1 -1
  8. data/client/hippo/components/asset.scss +1 -0
  9. data/client/hippo/components/data-table.jsx +36 -38
  10. data/client/hippo/components/date-time.jsx +25 -9
  11. data/client/hippo/components/form/api.js +1 -0
  12. data/client/hippo/components/form/fields.jsx +3 -2
  13. data/client/hippo/components/form/fields/checkbox-wrapper.jsx +1 -1
  14. data/client/hippo/components/form/fields/date-wrapper.jsx +1 -1
  15. data/client/hippo/components/form/fields/email-wrapper.jsx +31 -0
  16. data/client/hippo/components/form/fields/form-field.scss +8 -0
  17. data/client/hippo/components/form/fields/label.jsx +5 -7
  18. data/client/hippo/components/form/fields/select-wrapper.jsx +1 -1
  19. data/client/hippo/components/form/fields/tags-wrapper.jsx +1 -1
  20. data/client/hippo/components/form/fields/text-wrapper.jsx +1 -1
  21. data/client/hippo/components/form/fields/textarea-wrapper.jsx +1 -1
  22. data/client/hippo/components/form/wrapper.jsx +1 -1
  23. data/client/hippo/components/grid.js +1 -0
  24. data/client/hippo/components/master-detail.jsx +1 -1
  25. data/client/hippo/components/network-activity-overlay.jsx +6 -6
  26. data/client/hippo/components/payments/field.jsx +64 -0
  27. data/client/hippo/components/payments/field.scss +18 -0
  28. data/client/hippo/components/popout-window.jsx +1 -1
  29. data/client/hippo/components/query-builder.jsx +1 -1
  30. data/client/hippo/components/query-builder/boolean-picker.jsx +1 -1
  31. data/client/hippo/components/query-builder/clause-filter.jsx +2 -2
  32. data/client/hippo/components/query-builder/clause.jsx +16 -10
  33. data/client/hippo/components/query-builder/date-picker.jsx +1 -1
  34. data/client/hippo/components/query-builder/query-builder.scss +23 -2
  35. data/client/hippo/components/record-finder.jsx +5 -2
  36. data/client/hippo/components/record-finder/query-layer.jsx +1 -1
  37. data/client/hippo/components/save-button.jsx +1 -1
  38. data/client/hippo/components/screen.jsx +1 -1
  39. data/client/hippo/components/text-editor.jsx +82 -40
  40. data/client/hippo/components/text-editor/renderer.jsx +15 -35
  41. data/client/hippo/components/text-editor/renderer.scss +15 -0
  42. data/client/hippo/components/text-editor/text-editor.scss +2 -15
  43. data/client/hippo/components/text-editor/upload-adapter.js +66 -0
  44. data/client/hippo/components/time-zone-select.jsx +1 -1
  45. data/client/hippo/components/tool-tip.jsx +9 -14
  46. data/client/hippo/components/toolbar.jsx +16 -0
  47. data/client/hippo/components/warning-notification.jsx +1 -1
  48. data/client/hippo/extensions/base.js +3 -2
  49. data/client/hippo/extensions/index.js +1 -1
  50. data/client/hippo/lib/action_cable.js +8 -0
  51. data/client/hippo/lib/action_cable/cable.js +47 -0
  52. data/client/hippo/lib/action_cable/connection.js +192 -0
  53. data/client/hippo/lib/action_cable/connection_monitor.js +135 -0
  54. data/client/hippo/lib/action_cable/consumer.js +56 -0
  55. data/client/hippo/lib/action_cable/subscription.js +98 -0
  56. data/client/hippo/lib/action_cable/subscriptions.js +129 -0
  57. data/client/hippo/lib/date-range.js +22 -5
  58. data/client/hippo/lib/lazy-getter.js +31 -0
  59. data/client/hippo/lib/util.js +6 -1
  60. data/client/hippo/models/base.js +8 -3
  61. data/client/hippo/models/config.js +7 -2
  62. data/client/hippo/models/date-type.js +14 -0
  63. data/client/hippo/models/decorators.js +5 -5
  64. data/client/hippo/models/pub_sub.js +1 -1
  65. data/client/hippo/models/query/array-result.js +4 -1
  66. data/client/hippo/models/subscription.js +35 -0
  67. data/client/hippo/models/sync.js +1 -1
  68. data/client/hippo/models/tenant.js +14 -1
  69. data/client/hippo/react/component-not-found.jsx +14 -18
  70. data/client/hippo/screens/async-loading.jsx +46 -0
  71. data/client/hippo/screens/definition.js +2 -1
  72. data/client/hippo/screens/preferences.jsx +57 -0
  73. data/client/hippo/screens/system-settings.jsx +4 -6
  74. data/client/hippo/screens/system-settings/mailer-config.jsx +1 -1
  75. data/client/hippo/screens/system-settings/tenant.jsx +57 -4
  76. data/client/hippo/screens/user-management.jsx +2 -2
  77. data/client/hippo/screens/user-management/edit-form.jsx +1 -1
  78. data/client/hippo/styles/global/fancy-header.scss +2 -1
  79. data/client/hippo/styles/global/mixins.scss +14 -1
  80. data/client/hippo/testing/index.js +7 -0
  81. data/client/hippo/user.js +9 -2
  82. data/client/hippo/workspace/index.jsx +29 -8
  83. data/client/hippo/workspace/menu-group.jsx +1 -1
  84. data/client/hippo/workspace/menu-option.jsx +2 -0
  85. data/client/hippo/workspace/menu.jsx +30 -6
  86. data/client/hippo/workspace/screen.jsx +5 -1
  87. data/client/hippo/workspace/styles.scss +22 -3
  88. data/command-reference-files/initial/Gemfile +1 -1
  89. data/config/routes.rb +6 -0
  90. data/config/screens.rb +9 -17
  91. data/db/migrate/20171129024737_create_subscriptions.rb +12 -0
  92. data/fixtures/vcr_cassettes/Tenant_changes/sends_email_when_tenant_identifier_changes.yml +72 -0
  93. data/fixtures/vcr_cassettes/Tenant_isoloation/disallows_using_a_user_s_token_on_incorrect_domain.yml +141 -0
  94. data/fixtures/vcr_cassettes/Tenant_isoloation/isolates_bar_s_tenant_data_from_foo.yml +141 -0
  95. data/fixtures/vcr_cassettes/Tenant_isoloation/isolates_foo_s_tenant_data_from_bar.yml +141 -0
  96. data/hippo-fw.gemspec +4 -3
  97. data/lib/hippo.rb +1 -0
  98. data/lib/hippo/access/roles/basic_user.rb +1 -0
  99. data/lib/hippo/api/authentication_provider.rb +4 -5
  100. data/lib/hippo/api/handlers/asset.rb +9 -4
  101. data/lib/hippo/api/handlers/subscription.rb +39 -0
  102. data/lib/hippo/api/handlers/user_session.rb +0 -1
  103. data/lib/hippo/api/helper_methods.rb +8 -4
  104. data/lib/hippo/api/request_wrapper.rb +12 -1
  105. data/lib/hippo/command/console.rb +3 -3
  106. data/lib/hippo/concerns/asset_uploader.rb +8 -2
  107. data/lib/hippo/concerns/pub_sub.rb +8 -8
  108. data/lib/hippo/configuration.rb +6 -4
  109. data/lib/hippo/extension.rb +3 -2
  110. data/lib/hippo/model.rb +1 -0
  111. data/lib/hippo/models/subscription.rb +7 -0
  112. data/lib/hippo/payments.rb +129 -0
  113. data/lib/hippo/screen.rb +4 -2
  114. data/lib/hippo/screen/definition.rb +4 -0
  115. data/lib/hippo/spec_helper.rb +4 -4
  116. data/lib/hippo/templates/liquid/precision.rb +9 -0
  117. data/lib/hippo/tenant.rb +4 -5
  118. data/lib/hippo/user.rb +5 -5
  119. data/lib/hippo/version.rb +1 -1
  120. data/lib/hippo/webpack.rb +5 -1
  121. data/package-lock.json +437 -881
  122. data/package.json +19 -5
  123. data/spec/client/components/__snapshots__/query-builder.spec.jsx.snap +34 -1
  124. data/spec/client/components/__snapshots__/record-finder.spec.jsx.snap +1 -0
  125. data/spec/client/models/base.spec.js +7 -0
  126. data/spec/client/models/subscription.spec.js +8 -0
  127. data/spec/client/screens/__snapshots__/preferences.spec.jsx.snap +223 -0
  128. data/spec/client/screens/preferences.spec.jsx +10 -0
  129. data/spec/client/test-models.js +1 -1
  130. data/spec/client/workspace/__snapshots__/menu.spec.jsx.snap +12 -0
  131. data/spec/factories/subscription.rb +6 -0
  132. data/spec/factories/tenant.rb +1 -1
  133. data/spec/factories/user.rb +1 -1
  134. data/spec/server/api/tenant_change_spec.rb +11 -8
  135. data/spec/server/api/tenant_isolation_spec.rb +11 -8
  136. data/spec/server/api/user_sessions_spec.rb +10 -7
  137. data/spec/server/api/user_spec.rb +45 -0
  138. data/spec/server/models/subscription_spec.rb +10 -0
  139. data/spec/server/payment_helpers.rb +13 -0
  140. data/spec/server/print/form_spec.rb +1 -1
  141. data/spec/server/spec_helper.rb +3 -11
  142. data/templates/js/screen-definitions.js +4 -1
  143. data/templates/spec/factories/model.rb +1 -1
  144. data/views/hippo_root_view.erb +5 -5
  145. metadata +84 -25
  146. data/client/hippo/components/grid/config.json +0 -3
  147. data/client/hippo/components/grid/editors.scss +0 -78
  148. data/client/hippo/components/grid/index.js +0 -2
  149. data/client/hippo/components/grid/row-editor.scss +0 -74
  150. data/client/hippo/components/grid/styles.scss +0 -118
  151. data/client/hippo/components/text-editor/display-modes/Button.jsx +0 -20
  152. data/client/hippo/components/text-editor/display-modes/ToggleEdit.jsx +0 -23
  153. data/client/hippo/components/text-editor/display-modes/ToggleInsert.jsx +0 -22
  154. data/client/hippo/components/text-editor/display-modes/ToggleLayout.jsx +0 -22
  155. data/client/hippo/components/text-editor/display-modes/TogglePreview.jsx +0 -22
  156. data/client/hippo/components/text-editor/display-modes/ToggleResize.jsx +0 -22
  157. data/client/hippo/components/text-editor/display-modes/index.css +0 -0
  158. data/client/hippo/components/text-editor/display-modes/index.js +0 -30
  159. data/client/hippo/components/text-editor/image-plugin/Component/Display/index.js +0 -82
  160. data/client/hippo/components/text-editor/image-plugin/Component/Form/index.js +0 -42
  161. data/client/hippo/components/text-editor/image-plugin/Component/index.js +0 -16
  162. data/client/hippo/components/text-editor/image-plugin/Component/index.scss +0 -0
  163. data/client/hippo/components/text-editor/image-plugin/index.js +0 -32
  164. data/client/hippo/components/text-editor/image-plugin/index.scss +0 -25
  165. data/client/hippo/components/toolbar/changes-notification.scss +0 -63
  166. data/client/hippo/components/toolbar/index.js +0 -3
  167. data/client/hippo/components/toolbar/styles.scss +0 -74
@@ -41,7 +41,7 @@ whenDomReady().then(() => {
41
41
  console.warn(`The model for ${model.identifiedBy}(${property}) cannot be found`);
42
42
  });
43
43
 
44
- const loading = document.querySelector('.loading');
44
+ const loading = document.querySelector('.hippo-app-loading');
45
45
  if (loading) {
46
46
  loading.classList.add('complete');
47
47
  delay(() => {
@@ -14,7 +14,7 @@ import { BaseModel } from '../models/base';
14
14
  import './asset.scss';
15
15
 
16
16
  @observer
17
- export default class Asset extends React.PureComponent {
17
+ export default class Asset extends React.Component {
18
18
 
19
19
  static defaultProps = {
20
20
  label: '',
@@ -8,6 +8,7 @@
8
8
  padding: 0.5rem;
9
9
  cursor: pointer;
10
10
  overflow: auto;
11
+ -webkit-overflow-scrolling: touch;
11
12
  &-active {
12
13
  background-color: $selected-background-color;
13
14
  }
@@ -1,15 +1,15 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { pick, extend, defaults, map, bindAll, partial, toInteger, isNumber } from 'lodash';
3
+ import { pick, extend, defaults, map, partial, toInteger, isNumber } from 'lodash';
4
4
  import { defaultTableRowRenderer, Table, InfiniteLoader, AutoSizer, Column } from 'react-virtualized';
5
5
  import { action, computed, observable, autorun } from 'mobx';
6
6
  import { observer } from 'mobx-react';
7
+ import { autobind } from 'core-decorators';
7
8
  import cn from 'classnames';
8
-
9
+ import 'react-virtualized/styles.css';
9
10
  import NextIcon from 'grommet/components/icons/base/CaretNext';
10
11
  import Button from 'grommet/components/Button';
11
-
12
- import 'react-virtualized/styles.css';
12
+ import ActivityOverlay from './network-activity-overlay';
13
13
  import './data-table/table-styles.scss';
14
14
 
15
15
  import Query from '../models/query';
@@ -42,33 +42,29 @@ export default class DataTable extends React.Component {
42
42
  editRowIndex: PropTypes.number,
43
43
  }
44
44
 
45
- @observable editIndex;
46
- @observable query;
47
-
48
- constructor(props) {
49
- super(props);
50
- this.query = props.query;
51
- bindAll(this,
52
- 'rowRenderer',
53
- 'rowAtIndex',
54
- 'calculateRowHeight',
55
- 'isRowLoaded',
56
- 'loadMoreRows',
57
- 'headerRenderer');
58
- this.editIndex = props.editRowIndex;
59
- autorun(() => {
45
+ @observable editIndex = this.props.editRowIndex;
46
+
47
+ componentWillReceiveProps(nextProps) {
48
+ this.editIndex = nextProps.editRowIndex;
49
+ }
50
+
51
+ componentWillMount() {
52
+ this.query.open();
53
+ this.disposeRowHeightCalculator = autorun(() => {
60
54
  if (isNumber(this.editIndex) && this.tableRef) {
61
55
  this.tableRef.recomputeRowHeights(this.editIndex);
62
56
  }
63
57
  });
64
58
  }
65
59
 
66
- componentWillReceiveProps(nextProps) {
67
- this.editIndex = nextProps.editRowIndex;
60
+ componentWillUnmount() {
61
+ this.disposeRowHeightCalculator();
62
+ this.query.close();
68
63
  }
69
64
 
70
- componentWillMount() { this.query.open(); }
71
- componentWillUnmount() { this.query.close(); }
65
+ get query() {
66
+ return this.props.query;
67
+ }
72
68
 
73
69
  get rowProps() {
74
70
  const props = {};
@@ -123,14 +119,14 @@ export default class DataTable extends React.Component {
123
119
  }
124
120
 
125
121
  @computed get columnDefinitions() {
126
- const definitions = map(this.query.info.visibleFields, f =>
127
- extend({
128
- key: f.id,
129
- columnData: f,
130
- dataKey: f.dataIndex || f.id,
131
- headerRenderer: this.headerRenderer,
132
- }, pick(f, 'width', 'label', 'flexGrow', 'flexShrink',
133
- 'cellRenderer', 'className', 'headerClassName')));
122
+ const definitions = map(this.query.info.visibleFields, f => extend({
123
+ key: f.id,
124
+ columnData: f,
125
+ dataKey: f.dataIndex || f.id,
126
+ headerRenderer: this.headerRenderer,
127
+ }, pick(f, 'width', 'label', 'flexGrow', 'flexShrink',
128
+ 'cellRenderer', 'className', 'headerClassName')));
129
+
134
130
  if (this.props.editor) {
135
131
  definitions.unshift({
136
132
  key: 'edit-toggle',
@@ -151,15 +147,15 @@ export default class DataTable extends React.Component {
151
147
  }, this.props.styles);
152
148
  }
153
149
 
154
- rowAtIndex({ index }) {
150
+ @autobind rowAtIndex({ index }) {
155
151
  return this.props.query.results.rows[index];
156
152
  }
157
153
 
158
- calculateRowHeight({ index }) {
154
+ @autobind calculateRowHeight({ index }) {
159
155
  return (this.editIndex === index) ? this.props.editor.desiredHeight || 40 : 40;
160
156
  }
161
157
 
162
- rowRenderer(props) {
158
+ @autobind rowRenderer(props) {
163
159
  const {
164
160
  index, className, key, style,
165
161
  } = props;
@@ -184,18 +180,18 @@ export default class DataTable extends React.Component {
184
180
  return defaultTableRowRenderer(props);
185
181
  }
186
182
 
187
- headerRenderer({ columnData: field }) {
183
+ @autobind headerRenderer({ columnData: field }) {
188
184
  return <HeaderCell field={field} onAdd={this.props.canCreate ? this.onRowAdd : null} />;
189
185
  }
190
186
 
191
- isRowLoaded({ index }) {
187
+ @autobind isRowLoaded({ index }) {
192
188
  return (
193
189
  (this.query.results.rows.length > index) &&
194
- (this.query.results.isRowLoading(index) || this.query.results.rows[index])
190
+ (this.query.results.isRowLoading(index) || this.query.results.rows[index])
195
191
  );
196
192
  }
197
193
 
198
- loadMoreRows({ startIndex: start, stopIndex }) {
194
+ @action.bound loadMoreRows({ startIndex: start, stopIndex }) {
199
195
  const limit = (stopIndex + 1) - start;
200
196
  return this.query.results.fetch({ start, limit });
201
197
  }
@@ -207,6 +203,8 @@ export default class DataTable extends React.Component {
207
203
  className={cn('data-table', { selectable: this.props.onRowClick })}
208
204
  style={this.wrapperStyles}
209
205
  >
206
+ <ActivityOverlay model={query.results} message="Loading…" />
207
+
210
208
  <InfiniteLoader
211
209
  keyChange={this.gridRenderKey}
212
210
  minimumBatchSize={this.query.pageSize}
@@ -1,11 +1,14 @@
1
1
  import React from 'react';
2
+ import { defaults, has, omit } from 'lodash';
3
+ import { observable, action } from 'mobx';
4
+ import moment from 'moment-timezone';
2
5
  import PropTypes from 'prop-types';
3
6
  import { observer } from 'mobx-react';
4
7
  import { autobind } from 'core-decorators';
5
8
  import Flatpickr from 'flatpickr';
6
- import { defaults, has, omit } from 'lodash';
7
- import { observable, action } from 'mobx';
8
9
  import './date-time.scss';
10
+ import { isArrayLike } from '../lib/util';
11
+ import DateRange from '../lib/date-range';
9
12
 
10
13
  const hooks = [
11
14
  'onOpen',
@@ -24,7 +27,7 @@ const defaultOptions = {
24
27
  };
25
28
 
26
29
  @observer
27
- export default class DateTimePicker extends React.PureComponent {
30
+ export default class DateTimePicker extends React.Component {
28
31
 
29
32
  static propTypes = {
30
33
  defaultValue: PropTypes.string,
@@ -55,9 +58,7 @@ export default class DateTimePicker extends React.PureComponent {
55
58
  componentWillReceiveProps(props) {
56
59
  const options = this.getOptions(props);
57
60
 
58
- if (has(props, 'value')) {
59
- this.flatpickr.setDate(props.value, false);
60
- }
61
+ this.setValueFromProps(props);
61
62
 
62
63
  const optionsKeys = Object.getOwnPropertyNames(options);
63
64
 
@@ -76,10 +77,18 @@ export default class DateTimePicker extends React.PureComponent {
76
77
  componentDidMount() {
77
78
  const options = this.getOptions(this.props);
78
79
  this.flatpickr = new Flatpickr(this.node, options);
80
+ this.setValueFromProps(this.props);
81
+ }
79
82
 
80
- if (has(this.props, 'value')) {
81
- this.flatpickr.setDate(this.props.value, false);
83
+ setValueFromProps(props) {
84
+ if (!has(props, 'value')) { return; }
85
+ let { value } = props;
86
+ if (value instanceof DateRange) { value = value.asArray; }
87
+ if (moment.isMoment(value)) { value = value.toDate(); }
88
+ if (isArrayLike(value)) {
89
+ value = value.map(v => (moment.isMoment(v) ? v.toDate() : v));
82
90
  }
91
+ this.flatpickr.setDate(value, false);
83
92
  }
84
93
 
85
94
  componentWillUnmount() {
@@ -94,7 +103,14 @@ export default class DateTimePicker extends React.PureComponent {
94
103
  @autobind onChange(dates) {
95
104
  if ('range' === this.props.options.mode) {
96
105
  if (2 === dates.length) {
97
- this.props.onChange({ target: { value: dates } });
106
+ this.props.onChange({
107
+ target: {
108
+ value: [
109
+ moment(dates[0]).startOf('day'),
110
+ moment(dates[1]).endOf('day'),
111
+ ],
112
+ },
113
+ });
98
114
  }
99
115
  } else {
100
116
  this.props.onChange({ target: { value: dates[0] } });
@@ -159,6 +159,7 @@ export class FormState {
159
159
  } else {
160
160
  this.set(model);
161
161
  }
162
+ return model;
162
163
  }
163
164
 
164
165
  persistTo(model) {
@@ -11,16 +11,17 @@ import { titleize } from '../../lib/util';
11
11
  import DateWrapper from './fields/date-wrapper';
12
12
  import SelectWrapper from './fields/select-wrapper';
13
13
  import TextWrapper from './fields/text-wrapper';
14
+ import EmailWrapper from './fields/email-wrapper';
14
15
  import CheckBoxWrapper from './fields/checkbox-wrapper';
15
16
  import TagsWrapper from './fields/tags-wrapper';
16
17
  import TextAreaWrapper from './fields/textarea-wrapper';
17
18
  import Label from './fields/label';
18
19
  import TimeZoneSelect from '../../components/time-zone-select';
19
20
 
20
-
21
21
  import './fields/form-field.scss';
22
22
 
23
23
  const TypesMapping = {
24
+ email: EmailWrapper,
24
25
  text: TextWrapper,
25
26
  date: DateWrapper,
26
27
  tags: TagsWrapper,
@@ -34,7 +35,7 @@ const TypesMapping = {
34
35
 
35
36
  @inject('formState')
36
37
  @observer
37
- export default class FormField extends React.PureComponent {
38
+ export default class FormField extends React.Component {
38
39
 
39
40
  static propTypes = Object.assign({
40
41
  label: PropTypes.string,
@@ -4,7 +4,7 @@ import { action } from 'mobx';
4
4
  import CheckBox from 'grommet/components/CheckBox';
5
5
 
6
6
  @observer
7
- export default class CheckBoxWrapper extends React.PureComponent {
7
+ export default class CheckBoxWrapper extends React.Component {
8
8
 
9
9
  @action.bound onBlur(ev) {
10
10
  this.props.onBlur({ target: { value: ev.target.checked } });
@@ -6,7 +6,7 @@ import moment from 'moment';
6
6
  import DateTime from '../../date-time';
7
7
 
8
8
  @observer
9
- export default class DateWrapper extends React.PureComponent {
9
+ export default class DateWrapper extends React.Component {
10
10
 
11
11
  static defaultProps = {
12
12
  format: 'M/d/Y h:iK',
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { observer } from 'mobx-react';
3
+ import { action } from 'mobx';
4
+ import TextInput from 'grommet/components/TextInput';
5
+
6
+
7
+ @observer
8
+ export default class EmailWrapper extends React.Component {
9
+
10
+ @action.bound focus() {
11
+ this.inputRef.componentRef.focus();
12
+ }
13
+
14
+ @action.bound onChange(ev) {
15
+ if (ev.target && ev.target.value) {
16
+ ev.target.value = ev.target.value.replace(' ', '');
17
+ }
18
+ return this.props.onChange(ev);
19
+ }
20
+
21
+ render() {
22
+ return (
23
+ <TextInput
24
+ ref={(f) => { this.inputRef = f; }}
25
+ {...this.props}
26
+ onDOMChange={this.onChange}
27
+ />
28
+ );
29
+ }
30
+
31
+ }
@@ -11,4 +11,12 @@
11
11
  }
12
12
  }
13
13
 
14
+
15
+ .grommetux-form-field__contents {
16
+ label {
17
+ padding: 0 24px;
18
+ }
19
+ }
20
+
21
+
14
22
  @import './react-tags';
@@ -1,16 +1,14 @@
1
1
  import React from 'react';
2
+ import { isString } from 'lodash';
2
3
  import { observer } from 'mobx-react';
3
- import Value from 'grommet/components/Value';
4
+ import Label from 'grommet/components/Label';
4
5
 
5
6
  @observer
6
- export default class LabelWrapper extends React.PureComponent {
7
+ export default class LabelWrapper extends React.Component {
7
8
 
8
9
  render() {
9
- const { value } = this.props;
10
-
11
- return (
12
- <Value value={value} />
13
- );
10
+ const { value, ...props } = this.props;
11
+ return isString(value) ? <Label {...props}>{value}</Label> : value;
14
12
  }
15
13
 
16
14
  }
@@ -5,7 +5,7 @@ import Select from 'grommet/components/Select';
5
5
  import { get, find } from 'lodash';
6
6
 
7
7
  @observer
8
- export default class SelectFieldWrapper extends React.PureComponent {
8
+ export default class SelectFieldWrapper extends React.Component {
9
9
 
10
10
  @action.bound
11
11
  onSelectChange({ value: { id } }) {
@@ -5,7 +5,7 @@ import { action, isObservableArray } from 'mobx';
5
5
  import Tags from 'react-tag-autocomplete';
6
6
 
7
7
  @observer
8
- export default class CheckBoxWrapper extends React.PureComponent {
8
+ export default class CheckBoxWrapper extends React.Component {
9
9
 
10
10
  get tags() {
11
11
  if (isEmpty(this.props.value)) {
@@ -5,7 +5,7 @@ import TextInput from 'grommet/components/TextInput';
5
5
 
6
6
 
7
7
  @observer
8
- export default class TextWrapper extends React.PureComponent {
8
+ export default class TextWrapper extends React.Component {
9
9
 
10
10
  @action.bound focus() {
11
11
  this.inputRef.componentRef.focus();
@@ -2,7 +2,7 @@ import React from 'react';
2
2
  import { observer } from 'mobx-react';
3
3
 
4
4
  @observer
5
- export default class TextAreaWrapper extends React.PureComponent {
5
+ export default class TextAreaWrapper extends React.Component {
6
6
 
7
7
  render() {
8
8
  return (
@@ -6,7 +6,7 @@ import { FormState } from './api';
6
6
  import Screen from '../screen';
7
7
 
8
8
  @observer
9
- export default class FormWrapper extends React.PureComponent {
9
+ export default class FormWrapper extends React.Component {
10
10
 
11
11
  static propTypes = {
12
12
  tag: PropTypes.string,
@@ -0,0 +1 @@
1
+ export { Row, Col } from 'react-flexa';
@@ -10,7 +10,7 @@ import './master-detail.scss';
10
10
  const DELAY_TIME = 500;
11
11
 
12
12
  @observer
13
- export default class MasterDetail extends React.PureComponent {
13
+ export default class MasterDetail extends React.Component {
14
14
 
15
15
  static propTypes = {
16
16
  master: PropTypes.element.isRequired,
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { observer, PropTypes as MobxPropTypes } from 'mobx-react';
3
+ import { observer } from 'mobx-react';
4
4
  import { autorun, action, observable, computed } from 'mobx';
5
5
  import Spinning from 'grommet/components/icons/Spinning';
6
6
  import CircleInformationIcon from 'grommet/components/icons/base/CircleInformation';
@@ -13,7 +13,7 @@ function Indicator({ error }) {
13
13
  }
14
14
 
15
15
  @observer
16
- export default class NetworkActivityOverlay extends React.PureComponent {
16
+ export default class NetworkActivityOverlay extends React.Component {
17
17
 
18
18
  static defaultProps = {
19
19
  timeout: 30000,
@@ -21,7 +21,7 @@ export default class NetworkActivityOverlay extends React.PureComponent {
21
21
  }
22
22
 
23
23
  static propTypes = {
24
- model: MobxPropTypes.observableObject,
24
+ model: PropTypes.object,
25
25
  message: PropTypes.string,
26
26
  timeout: PropTypes.number,
27
27
  visible: PropTypes.bool,
@@ -30,7 +30,7 @@ export default class NetworkActivityOverlay extends React.PureComponent {
30
30
  }
31
31
 
32
32
  @computed get isRequesting() {
33
- const { syncInProgress } = this.props.model;
33
+ const { syncInProgress } = this.props.model || {};
34
34
  if (this.props.method) {
35
35
  return !!(syncInProgress && syncInProgress.method === this.props.method);
36
36
  }
@@ -38,7 +38,7 @@ export default class NetworkActivityOverlay extends React.PureComponent {
38
38
  }
39
39
 
40
40
  @computed get hasError() {
41
- return !isEmpty(this.props.model.errors);
41
+ return this.props.model && !isEmpty(this.props.model.errors);
42
42
  }
43
43
 
44
44
  @computed get isVisible() {
@@ -89,7 +89,7 @@ export default class NetworkActivityOverlay extends React.PureComponent {
89
89
  let { message } = this.props;
90
90
  if (!message) {
91
91
  if (this.hasError) {
92
- message = model.errorMessage || 'Error';
92
+ message = get(model, 'errorMessage', 'Error');
93
93
  } else {
94
94
  const method = get(model, 'syncInProgress.method');
95
95
  if ('GET' === method) {