hippo-fw 0.9.7 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +0 -3
  3. data/.nvmrc +1 -2
  4. data/.ruby-version +1 -1
  5. data/Rakefile +1 -1
  6. data/client/hippo/access/login-dialog.jsx +2 -0
  7. data/client/hippo/boot.jsx +12 -0
  8. data/client/hippo/components/asset.jsx +5 -1
  9. data/client/hippo/components/asset.scss +1 -0
  10. data/client/hippo/components/data-list.jsx +6 -4
  11. data/client/hippo/components/data-table.jsx +7 -6
  12. data/client/hippo/components/data-table/header-cell.jsx +2 -0
  13. data/client/hippo/components/date-time.jsx +12 -2
  14. data/client/hippo/components/form/api.js +12 -0
  15. data/client/hippo/components/form/fields.jsx +8 -1
  16. data/client/hippo/components/form/fields/checkbox-wrapper.jsx +2 -0
  17. data/client/hippo/components/form/fields/date-wrapper.jsx +2 -0
  18. data/client/hippo/components/form/fields/form-field.scss +2 -0
  19. data/client/hippo/components/form/fields/label.jsx +2 -0
  20. data/client/hippo/components/form/fields/react-tags.scss +170 -0
  21. data/client/hippo/components/form/fields/select-wrapper.jsx +2 -0
  22. data/client/hippo/components/form/fields/tags-wrapper.jsx +46 -0
  23. data/client/hippo/components/form/fields/text-wrapper.jsx +9 -1
  24. data/client/hippo/components/form/fields/textarea-wrapper.jsx +15 -0
  25. data/client/hippo/components/form/wrapper.jsx +21 -1
  26. data/client/hippo/components/help.jsx +21 -0
  27. data/client/hippo/components/master-detail.jsx +2 -0
  28. data/client/hippo/components/network-activity-overlay.jsx +3 -1
  29. data/client/hippo/components/popout-window.jsx +126 -0
  30. data/client/hippo/components/query-builder.jsx +9 -117
  31. data/client/hippo/components/query-builder/boolean-picker.jsx +28 -0
  32. data/client/hippo/components/query-builder/clause-filter.jsx +58 -0
  33. data/client/hippo/components/query-builder/clause.jsx +98 -0
  34. data/client/hippo/components/query-builder/date-picker.jsx +23 -0
  35. data/client/hippo/components/query-builder/query-builder.scss +7 -0
  36. data/client/hippo/components/record-finder.jsx +2 -0
  37. data/client/hippo/components/record-finder/query-layer.jsx +5 -1
  38. data/client/hippo/components/save-button.jsx +7 -1
  39. data/client/hippo/components/screen.jsx +2 -0
  40. data/client/hippo/components/text-editor.jsx +4 -5
  41. data/client/hippo/components/text-editor/display-modes/Button.jsx +5 -2
  42. data/client/hippo/components/text-editor/display-modes/ToggleEdit.jsx +2 -1
  43. data/client/hippo/components/text-editor/display-modes/ToggleInsert.jsx +2 -1
  44. data/client/hippo/components/text-editor/display-modes/ToggleLayout.jsx +2 -1
  45. data/client/hippo/components/text-editor/display-modes/TogglePreview.jsx +2 -1
  46. data/client/hippo/components/text-editor/display-modes/ToggleResize.jsx +2 -1
  47. data/client/hippo/components/text-editor/display-modes/index.js +7 -7
  48. data/client/hippo/components/text-editor/image-plugin/Component/Display/index.js +4 -2
  49. data/client/hippo/components/text-editor/image-plugin/Component/Form/index.js +2 -0
  50. data/client/hippo/components/text-editor/renderer.jsx +2 -0
  51. data/client/hippo/components/text-editor/text-editor.scss +13 -4
  52. data/client/hippo/components/time-zone-select.jsx +2 -0
  53. data/client/hippo/components/tool-tip.jsx +2 -0
  54. data/client/hippo/extensions/base.js +2 -0
  55. data/client/hippo/extensions/hippo.js +2 -0
  56. data/client/hippo/lib/__mocks__/request-assets.js +1 -2
  57. data/client/hippo/lib/bootstrap.js +2 -0
  58. data/client/hippo/lib/computed-properties.js +24 -0
  59. data/client/hippo/lib/date-range.js +13 -2
  60. data/client/hippo/lib/request-assets.js +3 -2
  61. data/client/hippo/lib/smooth-scroll.js +2 -0
  62. data/client/hippo/lib/util.js +1 -2
  63. data/client/hippo/models/asset.js +2 -0
  64. data/client/hippo/models/base.js +5 -2
  65. data/client/hippo/models/collection.js +2 -0
  66. data/client/hippo/models/config.js +3 -1
  67. data/client/hippo/models/pub_sub.js +2 -0
  68. data/client/hippo/models/pub_sub/channel.js +2 -0
  69. data/client/hippo/models/pub_sub/map.js +2 -0
  70. data/client/hippo/models/query.js +21 -12
  71. data/client/hippo/models/query/array-result.js +52 -16
  72. data/client/hippo/models/query/clause.js +11 -4
  73. data/client/hippo/models/query/field.js +2 -1
  74. data/client/hippo/models/query/info.js +7 -1
  75. data/client/hippo/models/query/operator.js +2 -0
  76. data/client/hippo/models/query/result.js +2 -0
  77. data/client/hippo/models/query/types.js +4 -0
  78. data/client/hippo/models/sync.js +2 -0
  79. data/client/hippo/models/system-setting.js +1 -15
  80. data/client/hippo/models/tenant.js +23 -7
  81. data/client/hippo/react/Root.jsx +2 -0
  82. data/client/hippo/react/component-not-found.jsx +2 -0
  83. data/client/hippo/screens/definition.js +2 -0
  84. data/client/hippo/screens/group.js +2 -0
  85. data/client/hippo/screens/instance.js +5 -1
  86. data/client/hippo/screens/system-settings.jsx +19 -5
  87. data/client/hippo/screens/system-settings/mailer-config.jsx +4 -2
  88. data/client/hippo/screens/system-settings/system-settings.scss +1 -1
  89. data/client/hippo/screens/system-settings/tenant.jsx +4 -2
  90. data/client/hippo/screens/user-management.jsx +2 -0
  91. data/client/hippo/screens/user-management/edit-form.jsx +2 -0
  92. data/client/hippo/testing/screens.js +10 -2
  93. data/client/hippo/user.js +4 -0
  94. data/client/hippo/workspace/index.jsx +3 -1
  95. data/client/hippo/workspace/menu-group.jsx +2 -0
  96. data/client/hippo/workspace/menu-option.jsx +2 -0
  97. data/client/hippo/workspace/menu.jsx +6 -3
  98. data/client/hippo/workspace/navbar.jsx +2 -0
  99. data/client/hippo/workspace/screen.jsx +2 -0
  100. data/client/hippo/workspace/styles.scss +5 -1
  101. data/command-reference-files/initial/.eslintrc.js +0 -3
  102. data/command-reference-files/initial/Gemfile +1 -1
  103. data/config/routes.rb +3 -1
  104. data/db/seed.rb +1 -1
  105. data/hippo-fw.gemspec +2 -2
  106. data/lib/hippo/api/controller_base.rb +2 -1
  107. data/lib/hippo/api/handlers/asset.rb +3 -2
  108. data/lib/hippo/api/handlers/tenant.rb +4 -6
  109. data/lib/hippo/api/helper_methods.rb +5 -7
  110. data/lib/hippo/api/route_set.rb +3 -2
  111. data/lib/hippo/asset.rb +4 -0
  112. data/lib/hippo/command/console.rb +1 -1
  113. data/lib/hippo/concerns/asset_uploader.rb +9 -4
  114. data/lib/hippo/concerns/queries.rb +3 -3
  115. data/lib/hippo/extension.rb +14 -4
  116. data/lib/hippo/extension/definition.rb +5 -1
  117. data/lib/hippo/logger.rb +26 -27
  118. data/lib/hippo/mailer.rb +19 -7
  119. data/lib/hippo/system_settings.rb +10 -4
  120. data/lib/hippo/templates/liquid.rb +1 -0
  121. data/lib/hippo/templates/liquid/pluralize.rb +16 -0
  122. data/lib/hippo/tenant.rb +17 -1
  123. data/lib/hippo/user.rb +10 -9
  124. data/lib/hippo/version.rb +1 -1
  125. data/lib/hippo/webpack.rb +22 -2
  126. data/package-lock.json +5462 -883
  127. data/package.json +9 -11
  128. data/spec/client/access/login-dialog.spec.jsx +2 -2
  129. data/spec/client/components/__snapshots__/query-builder.spec.jsx.snap +1 -1
  130. data/spec/client/components/__snapshots__/record-finder.spec.jsx.snap +1 -1
  131. data/spec/client/components/master-detail.spec.jsx +2 -1
  132. data/spec/client/components/query-builder.spec.jsx +3 -3
  133. data/spec/client/extension/base.spec.js +2 -0
  134. data/spec/client/models/base.spec.js +5 -3
  135. data/spec/client/models/query.spec.js +18 -6
  136. data/spec/client/models/sync.spec.js +2 -1
  137. data/spec/client/models/system-setting.spec.js +0 -12
  138. data/spec/client/screens/user-management.spec.jsx +1 -2
  139. data/spec/client/test-models.js +10 -0
  140. data/spec/server/api/tenant_change_spec.rb +1 -2
  141. data/spec/server/asset_spec.rb +2 -2
  142. data/templates/js/config-data.js +1 -1
  143. data/templates/spec/factories/model.rb +1 -1
  144. data/views/hippo_root_view.erb +1 -3
  145. metadata +17 -6
  146. data/client/hippo/components/text-editor/display-modes/SaveState.jsx +0 -17
@@ -6,6 +6,7 @@ import { get, find } from 'lodash';
6
6
 
7
7
  @observer
8
8
  export default class SelectFieldWrapper extends React.PureComponent {
9
+
9
10
  @action.bound
10
11
  onSelectChange({ value: { id } }) {
11
12
  const ev = { target: { value: id } };
@@ -27,4 +28,5 @@ export default class SelectFieldWrapper extends React.PureComponent {
27
28
  />
28
29
  );
29
30
  }
31
+
30
32
  }
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { isEmpty, isArray } from 'lodash';
3
+ import { observer } from 'mobx-react';
4
+ import { action, isObservableArray } from 'mobx';
5
+ import Tags from 'react-tag-autocomplete';
6
+
7
+ @observer
8
+ export default class CheckBoxWrapper extends React.PureComponent {
9
+
10
+ get tags() {
11
+ if (isEmpty(this.props.value)) {
12
+ return [];
13
+ } else if (!isArray(this.props.value) &&
14
+ !isObservableArray(this.props.value)) {
15
+ return [this.props.value];
16
+ }
17
+ return this.props.value;
18
+ }
19
+
20
+ @action.bound
21
+ onTagDelete(tagIndex) {
22
+ const { tags } = this;
23
+ tags.splice(tagIndex, 1);
24
+ this.props.onChange({ target: { value: tags } });
25
+ }
26
+
27
+ @action.bound onTagAdd(tag) {
28
+ const { tags } = this;
29
+ tags.push(tag);
30
+ this.props.onChange({ target: { value: tags } });
31
+ }
32
+
33
+ render() {
34
+ const { value: _, ...otherProps } = this.props;
35
+
36
+ return (
37
+ <Tags
38
+ handleDelete={this.onTagDelete}
39
+ handleAddition={this.onTagAdd}
40
+ tags={isObservableArray(this.tags) ? this.tags.peek() : this.tags}
41
+ {...otherProps}
42
+ />
43
+ );
44
+ }
45
+
46
+ }
@@ -6,15 +6,23 @@ import TextInput from 'grommet/components/TextInput';
6
6
 
7
7
  @observer
8
8
  export default class TextWrapper extends React.PureComponent {
9
+
9
10
  @action.bound focus() {
10
11
  this.inputRef.componentRef.focus();
11
12
  }
13
+
14
+ @action.bound onSelect({ suggestion }) {
15
+ this.props.onChange({ target: { value: suggestion } });
16
+ }
17
+
12
18
  render() {
13
19
  return (
14
20
  <TextInput
15
- ref={f => (this.inputRef = f)}
21
+ ref={(f) => { this.inputRef = f; }}
22
+ onSelect={this.onSelect}
16
23
  {...this.props} onDOMChange={this.props.onChange}
17
24
  />
18
25
  );
19
26
  }
27
+
20
28
  }
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import { observer } from 'mobx-react';
3
+
4
+ @observer
5
+ export default class TextAreaWrapper extends React.PureComponent {
6
+
7
+ render() {
8
+ return (
9
+ <textarea
10
+ {...this.props}
11
+ />
12
+ );
13
+ }
14
+
15
+ }
@@ -3,15 +3,18 @@ import PropTypes from 'prop-types';
3
3
  import { PropTypes as MobxPropTypes, Provider, observer } from 'mobx-react';
4
4
  import { observePubSub } from '../../models/pub_sub';
5
5
  import { FormState } from './api';
6
+ import Screen from '../screen';
6
7
 
7
8
  @observer
8
9
  export default class FormWrapper extends React.PureComponent {
10
+
9
11
  static propTypes = {
10
12
  tag: PropTypes.string,
11
13
  className: PropTypes.string,
12
14
  children: PropTypes.node.isRequired,
13
15
  state: PropTypes.instanceOf(FormState),
14
16
  model: MobxPropTypes.observableObject,
17
+ screen: PropTypes.instanceOf(Screen.Instance),
15
18
  }
16
19
 
17
20
  static get defaultProps() {
@@ -39,7 +42,9 @@ export default class FormWrapper extends React.PureComponent {
39
42
  }
40
43
 
41
44
  renderTagged() {
42
- const { tag: Tag, state, children, model: _, ...otherProps } = this.props;
45
+ const {
46
+ tag: Tag, state, children, model: _, ...otherProps
47
+ } = this.props;
43
48
  return (
44
49
  <Provider formState={state}>
45
50
  <Tag {...otherProps}>
@@ -49,8 +54,23 @@ export default class FormWrapper extends React.PureComponent {
49
54
  );
50
55
  }
51
56
 
57
+ renderScreen() {
58
+ const {
59
+ tag: _, state, children, screen, model: __, ...otherProps
60
+ } = this.props;
61
+ return (
62
+ <Provider formState={state}>
63
+ <Screen screen={screen} {...otherProps}>
64
+ {children}
65
+ </Screen>
66
+ </Provider>
67
+ );
68
+ }
69
+
52
70
  render() {
53
71
  if (this.props.model) { observePubSub(this.props.model); }
72
+ if (this.props.screen) { return this.renderScreen(); }
54
73
  return this.props.tag ? this.renderTagged() : this.renderTagless();
55
74
  }
75
+
56
76
  }
@@ -0,0 +1,21 @@
1
+ import React from 'react'; // eslint-disable-line no-unused-vars
2
+ import PropTypes from 'prop-types';
3
+ import { Tooltip } from 'react-tippy';
4
+ import 'react-tippy/dist/tippy.css';
5
+ import CircleQuestionIcon from 'grommet/components/icons/base/CircleQuestion';
6
+
7
+ export default function Help({ message, ...ttProps }) {
8
+ return (
9
+ <Tooltip
10
+ arrow
11
+ title={message}
12
+ {...ttProps}
13
+ >
14
+ <CircleQuestionIcon colorIndex="brand" />
15
+ </Tooltip>
16
+ );
17
+ }
18
+
19
+ Help.propTypes = {
20
+ message: PropTypes.string.isRequired,
21
+ };
@@ -11,6 +11,7 @@ const DELAY_TIME = 500;
11
11
 
12
12
  @observer
13
13
  export default class MasterDetail extends React.PureComponent {
14
+
14
15
  static propTypes = {
15
16
  master: PropTypes.element.isRequired,
16
17
  detail: PropTypes.element,
@@ -61,4 +62,5 @@ export default class MasterDetail extends React.PureComponent {
61
62
  </div>
62
63
  );
63
64
  }
65
+
64
66
  }
@@ -14,6 +14,7 @@ function Indicator({ error }) {
14
14
 
15
15
  @observer
16
16
  export default class NetworkActivityOverlay extends React.PureComponent {
17
+
17
18
  static defaultProps = {
18
19
  timeout: 30000,
19
20
  errorTimeout: 2000,
@@ -85,7 +86,7 @@ export default class NetworkActivityOverlay extends React.PureComponent {
85
86
 
86
87
  get message() {
87
88
  const { props: { model } } = this;
88
- let message = this.props.message;
89
+ let { message } = this.props;
89
90
  if (!message) {
90
91
  if (this.hasError) {
91
92
  message = model.errorMessage || 'Error';
@@ -121,4 +122,5 @@ export default class NetworkActivityOverlay extends React.PureComponent {
121
122
  </div>
122
123
  );
123
124
  }
125
+
124
126
  }
@@ -0,0 +1,126 @@
1
+ // inspiration from https://github.com/JakeGinnivan/react-popout
2
+ // this version triggers popup directly and leaves it open
3
+ // after the parent component unmounts
4
+
5
+ import React from 'react';
6
+ import PropTypes from 'prop-types';
7
+ import ReactDOM from 'react-dom';
8
+ import { isFunction, invoke, defaults, map, uniqueId } from 'lodash';
9
+ import { autobind } from 'core-decorators';
10
+
11
+ export default class PopoutWindow extends React.PureComponent {
12
+
13
+ static propTypes = {
14
+ title: PropTypes.string.isRequired,
15
+ children: PropTypes.node.isRequired,
16
+ onClose: PropTypes.func.isRequired,
17
+ url: PropTypes.string,
18
+ options: PropTypes.object,
19
+ windowImpl: PropTypes.shape({
20
+ open: PropTypes.func,
21
+ }),
22
+ };
23
+
24
+ static defaultProps = {
25
+ windowImpl: window,
26
+ url: 'about:blank',
27
+ };
28
+
29
+ containerId = uniqueId('popout-container');
30
+
31
+ popup = false;
32
+
33
+ defaultOptions = {
34
+ toolbar: 'no',
35
+ location: 'no',
36
+ directories: 'no',
37
+ status: 'no',
38
+ menubar: 'no',
39
+ scrollbars: 'yes',
40
+ resizable: 'yes',
41
+ width: 500,
42
+ height: 400,
43
+ top: (o, w) => ((w.innerHeight - o.height) / 2) + w.screenY,
44
+ left: (o, w) => ((w.innerWidth - o.width) / 2) + w.screenX,
45
+ };
46
+
47
+
48
+ componentDidMount() {
49
+ // May not exist if server-side rendering
50
+ if (this.props.windowImpl) {
51
+ this.open();
52
+ }
53
+ }
54
+
55
+ componentWillReceiveProps(nextProps) {
56
+ // re-render
57
+ if (this.isOpen && nextProps.children !== this.props.children) {
58
+ this.reRender();
59
+ }
60
+ }
61
+
62
+ get isOpen() {
63
+ return !!(this.popup && this.containerEl);
64
+ }
65
+
66
+ get containerEl() {
67
+ return this.popup.document.getElementById(this.containerId);
68
+ }
69
+
70
+ reRender(children = this.props.children) {
71
+ ReactDOM.render(children, this.containerEl);
72
+ }
73
+
74
+ open() {
75
+ if (this.isOpen) {
76
+ this.reRender();
77
+ this.popup.focus();
78
+ return;
79
+ }
80
+ // eslint-disable-next-line
81
+ const options = map(
82
+ defaults({}, this.props.options, this.defaultOptions),
83
+ (v, key, o) => `${key}=${v = isFunction(v) ? v(o, this.props.windowImpl) : v}`, // eslint-disable-line
84
+ ).join(',');
85
+
86
+ this.popup = this.props.windowImpl.open(this.props.url, this.props.title, options);
87
+
88
+ this.popup.onbeforeunload = this.onWindowBeforeUnLoad;
89
+ this.popup.onload = this.onWindowLoad;
90
+
91
+ // just in case onload fails to fire
92
+ if ('complete' === this.popup.document.readyState) {
93
+ this.onWindowLoad();
94
+ }
95
+ }
96
+
97
+ @autobind
98
+ close() {
99
+ invoke(this.popup, 'close');
100
+ }
101
+
102
+ @autobind
103
+ onWindowBeforeUnLoad() {
104
+ invoke(this.props, 'onClose');
105
+ ReactDOM.unmountComponentAtNode(this.containerEl);
106
+ this.containerEl.parentNode.removeChild(this.containerEl);
107
+ }
108
+
109
+ @autobind
110
+ onWindowLoad() {
111
+ // called twice
112
+ if (this.containerEl) { return; }
113
+
114
+ this.popup.document.title = this.props.title;
115
+ const container = this.popup.document.createElement('div');
116
+ container.id = this.containerId;
117
+ this.popup.document.body.appendChild(container);
118
+
119
+ ReactDOM.render(this.props.children, container);
120
+ }
121
+
122
+ render() {
123
+ return null; // don't need to render anything directly
124
+ }
125
+
126
+ }
@@ -1,125 +1,14 @@
1
1
  import React from 'react';
2
-
3
2
  import PropTypes from 'prop-types';
4
3
  import { find } from 'lodash';
5
4
  import { observer } from 'mobx-react';
6
- import { action } from 'mobx';
7
- import Box from 'grommet/components/Box';
8
- import Menu from 'grommet/components/Menu';
9
- import RadioButton from 'grommet/components/RadioButton';
10
- import TextInput from 'grommet/components/TextInput';
11
- import DownIcon from 'grommet/components/icons/base/Down';
12
- import { BaseModel } from '../models/base';
13
- import Query from '../models/query';
14
- import ClauseModel from '../models/query/clause';
15
-
16
- @observer
17
- class Radio extends React.PureComponent {
18
- static propTypes = {
19
- name: PropTypes.string.isRequired,
20
- onSelect: PropTypes.func.isRequired,
21
- model: PropTypes.instanceOf(BaseModel).isRequired,
22
- clause: PropTypes.instanceOf(ClauseModel).isRequired,
23
- }
24
-
25
- @action.bound
26
- onChange() {
27
- this.props.clause[this.props.name] = this.props.model;
28
- this.props.onSelect();
29
- }
30
-
31
- render() {
32
- const { model } = this.props;
33
- return (
34
- <RadioButton
35
- id={model.id}
36
- name={model.id}
37
- label={model.label}
38
- onChange={this.onChange}
39
- checked={(this.props.clause[this.props.name] === model)}
40
- />
41
- );
42
- }
43
- }
44
-
45
- @observer
46
- class ClauseFilter extends React.PureComponent {
47
- static propTypes = {
48
- clause: PropTypes.instanceOf(ClauseModel).isRequired,
49
- }
50
-
51
- render() {
52
- const { clause } = this.props;
53
- return (
54
- <span>
55
- <DownIcon /> {clause.field.label} {clause.operator.label}
56
- </span>
57
- );
58
- }
59
- }
60
-
61
- @observer
62
- class Clause extends React.PureComponent {
63
- static propTypes = {
64
- clause: PropTypes.instanceOf(ClauseModel).isRequired,
65
- }
66
-
67
- @action.bound
68
- onSelect() {
69
- this.menuRef._onClose();
70
- }
71
-
72
- @action.bound
73
- onValueChange(ev) {
74
- this.props.clause.value = ev.target.value;
75
- }
76
-
77
- @action.bound
78
- setMenuRef(ref) {
79
- this.menuRef = ref;
80
- }
81
-
82
- render() {
83
- const { clause } = this.props;
84
- return (
85
- <Box direction='row' pad={{ between: 'small' }}>
86
- <Menu
87
- ref={this.setMenuRef}
88
- size='large'
89
- pad='small'
90
- closeOnClick={false} icon={<ClauseFilter clause={clause} />}
91
- >
92
- <Box direction='row' pad="small">
93
- <Box size="small" pad={{ between: 'small' }}>
94
- {clause.query.info.queryableFields.map(f =>
95
- <Radio
96
- key={f.id} model={f} clause={clause}
97
- onSelect={this.onSelect} name='field' />,
98
- )}
99
- </Box>
100
- <Box size="small" pad={{ between: 'small' }}>
101
- {clause.validOperators.map(o =>
102
- <Radio
103
- key={o.id} model={o} clause={clause}
104
- onSelect={this.onSelect} name='operator'
105
- />,
106
- )}
107
- </Box>
108
- </Box>
109
- </Menu>
110
- <TextInput
111
- autoFocus
112
- style={{ flex: 1 }}
113
- value={clause.value || ''}
114
- onDOMChange={this.onValueChange}
115
- />
116
- </Box>
117
- );
118
- }
119
- }
5
+ import Query from '../models/query';
6
+ import Clause from './query-builder/clause';
7
+ import './query-builder/query-builder.scss';
120
8
 
121
9
  @observer
122
10
  export default class QueryBuilder extends React.PureComponent {
11
+
123
12
  static defaultProps = {
124
13
  autoFetch: false,
125
14
  }
@@ -127,6 +16,7 @@ export default class QueryBuilder extends React.PureComponent {
127
16
  static propTypes = {
128
17
  autoFetch: PropTypes.bool,
129
18
  query: PropTypes.instanceOf(Query).isRequired,
19
+ typeHandlers: PropTypes.object,
130
20
  }
131
21
 
132
22
  constructor(props) {
@@ -151,11 +41,13 @@ export default class QueryBuilder extends React.PureComponent {
151
41
  }
152
42
 
153
43
  render() {
154
- const { query } = this.props;
44
+ const { query, typeHandlers } = this.props;
155
45
  return (
156
46
  <div className="query-builder">
157
- {query.info.visibleClauses.map(c => <Clause key={c.id} clause={c} />)}
47
+ {query.info.visibleClauses.map(c =>
48
+ <Clause key={c.id} clause={c} typeHandlers={typeHandlers} />)}
158
49
  </div>
159
50
  );
160
51
  }
52
+
161
53
  }