hippo-fw 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/.nvmrc +2 -0
  3. data/.travis.yml +1 -1
  4. data/client/hippo/access/login-dialog.jsx +3 -5
  5. data/client/hippo/boot.jsx +2 -2
  6. data/client/hippo/components/asset.jsx +0 -1
  7. data/client/hippo/components/data-list.jsx +16 -15
  8. data/client/hippo/components/data-list/data-list.scss +10 -0
  9. data/client/hippo/components/data-table.jsx +14 -14
  10. data/client/hippo/components/data-table/header-cell.jsx +0 -1
  11. data/client/hippo/components/data-table/table-styles.scss +7 -0
  12. data/client/hippo/components/date-time.jsx +19 -16
  13. data/client/hippo/components/date-time/calendar.jsx +5 -7
  14. data/client/hippo/components/date-time/date-time-drop.jsx +0 -2
  15. data/client/hippo/components/date-time/time.jsx +0 -1
  16. data/client/hippo/components/form.jsx +1 -1
  17. data/client/hippo/components/form/{model.js → api.js} +25 -7
  18. data/client/hippo/components/form/fields.jsx +12 -11
  19. data/client/hippo/components/form/fields/date-wrapper.jsx +1 -1
  20. data/client/hippo/components/form/fields/form-field.scss +9 -1
  21. data/client/hippo/components/form/fields/label.jsx +14 -0
  22. data/client/hippo/components/form/fields/select-wrapper.jsx +2 -3
  23. data/client/hippo/components/form/wrapper.jsx +1 -3
  24. data/client/hippo/components/icon.jsx +2 -69
  25. data/client/hippo/components/master-detail.jsx +0 -2
  26. data/client/hippo/components/network-activity-overlay.jsx +1 -4
  27. data/client/hippo/components/query-builder.jsx +15 -16
  28. data/client/hippo/components/record-finder.jsx +2 -5
  29. data/client/hippo/components/record-finder/query-layer.jsx +1 -5
  30. data/client/hippo/components/screen.jsx +7 -3
  31. data/client/hippo/components/text-editor.jsx +2 -8
  32. data/client/hippo/components/tool-tip.jsx +2 -3
  33. data/client/hippo/components/warning-notification.jsx +3 -3
  34. data/client/hippo/lib/date-range.js +28 -0
  35. data/client/hippo/lib/util.js +6 -0
  36. data/client/hippo/models/asset.js +6 -3
  37. data/client/hippo/models/config.js +1 -1
  38. data/client/hippo/models/pub_sub.js +12 -7
  39. data/client/hippo/models/pub_sub/channel.js +6 -4
  40. data/client/hippo/models/query.js +19 -4
  41. data/client/hippo/models/query/array-result.js +9 -8
  42. data/client/hippo/models/query/clause.js +21 -13
  43. data/client/hippo/models/query/field.js +7 -2
  44. data/client/hippo/models/query/info.js +7 -3
  45. data/client/hippo/models/sync.js +11 -14
  46. data/client/hippo/react/Root.jsx +1 -2
  47. data/client/hippo/react/{DefaultComponentNotFound.jsx → component-not-found.jsx} +1 -3
  48. data/client/hippo/screens/index.js +6 -2
  49. data/client/hippo/screens/system-settings.jsx +10 -6
  50. data/client/hippo/screens/system-settings/mailer-config.jsx +0 -2
  51. data/client/hippo/screens/system-settings/tenant.jsx +1 -4
  52. data/client/hippo/screens/user-management.jsx +0 -1
  53. data/client/hippo/screens/user-management/edit-form.jsx +1 -2
  54. data/client/hippo/workspace/index.jsx +21 -12
  55. data/client/hippo/workspace/menu-group.jsx +4 -7
  56. data/client/hippo/workspace/menu-option.jsx +1 -3
  57. data/client/hippo/workspace/menu.jsx +29 -11
  58. data/client/hippo/workspace/navbar.jsx +1 -2
  59. data/client/hippo/workspace/root-view.jsx +5 -2
  60. data/client/hippo/workspace/screen.jsx +2 -3
  61. data/client/hippo/workspace/styles.scss +17 -0
  62. data/command-reference-files/screen/client/appy-app/screens/ready-set-go.jsx +2 -1
  63. data/db/migrate/20170530120004_create_users.rb +1 -1
  64. data/hippo-fw.gemspec +3 -2
  65. data/lib/hippo/api/cable.rb +13 -13
  66. data/lib/hippo/api/controller_base.rb +1 -0
  67. data/lib/hippo/api/handlers/tenant.rb +1 -1
  68. data/lib/hippo/api/handlers/user_session.rb +2 -1
  69. data/lib/hippo/api/helper_methods.rb +4 -1
  70. data/lib/hippo/api/pub_sub.rb +7 -6
  71. data/lib/hippo/api/to_json.rb +1 -1
  72. data/lib/hippo/api/updates.rb +2 -0
  73. data/lib/hippo/command/console.rb +11 -3
  74. data/lib/hippo/command/jest.rb +2 -0
  75. data/lib/hippo/configuration.rb +4 -7
  76. data/lib/hippo/rake_tasks.rb +1 -1
  77. data/lib/hippo/screen.rb +31 -93
  78. data/lib/hippo/screen/definition.rb +76 -0
  79. data/lib/hippo/screen/group.rb +26 -0
  80. data/lib/hippo/spec_helper.rb +3 -0
  81. data/lib/hippo/system_settings.rb +6 -0
  82. data/lib/hippo/user.rb +11 -3
  83. data/lib/hippo/version.rb +1 -1
  84. data/package-lock.json +419 -533
  85. data/package.json +32 -30
  86. data/spec/client/access/login-dialog.spec.jsx +4 -5
  87. data/spec/client/components/__snapshots__/query-builder.spec.jsx.snap +1 -1
  88. data/spec/client/components/__snapshots__/record-finder.spec.jsx.snap +72 -0
  89. data/spec/client/components/asset.spec.jsx +2 -6
  90. data/spec/client/components/data-list.spec.jsx +2 -6
  91. data/spec/client/components/data-table.spec.jsx +3 -5
  92. data/spec/client/components/date-time.spec.jsx +1 -1
  93. data/spec/client/components/form.spec.jsx +2 -2
  94. data/spec/client/components/master-detail.spec.jsx +1 -2
  95. data/spec/client/components/network-activity-overlay.spec.jsx +2 -3
  96. data/spec/client/components/query-builder.spec.jsx +3 -6
  97. data/spec/client/components/record-finder.spec.jsx +4 -4
  98. data/spec/client/models/pub_sub.spec.js +3 -1
  99. data/spec/client/models/query.spec.js +4 -9
  100. data/spec/client/screens/system-settings-tenants.spec.jsx +1 -1
  101. data/spec/client/screens/system-settings.spec.jsx +1 -4
  102. data/spec/client/workspace/__snapshots__/menu.spec.jsx.snap +15 -20
  103. data/spec/client/workspace/menu.spec.jsx +1 -2
  104. data/spec/server/api/user_sessions_spec.rb +15 -0
  105. data/templates/client/screens/screen.jsx +2 -1
  106. data/views/hippo_root_view.erb +1 -0
  107. metadata +30 -52
  108. data/client/hippo/components/calendar/Calendar.jsx +0 -25
  109. data/client/hippo/components/calendar/index.js +0 -3
  110. data/client/hippo/components/calendar/styles.scss +0 -3
  111. data/client/hippo/components/shared/AssetsListing.jsx +0 -23
  112. data/client/hippo/components/shared/Checkbox.jsx +0 -49
  113. data/client/hippo/components/shared/CountBadge.jsx +0 -13
  114. data/client/hippo/components/shared/DateTime.jsx +0 -58
  115. data/client/hippo/components/shared/DisplayValue.jsx +0 -15
  116. data/client/hippo/components/shared/ErrorDisplay.jsx +0 -37
  117. data/client/hippo/components/shared/FieldMixin.jsx +0 -254
  118. data/client/hippo/components/shared/FieldSet.jsx +0 -52
  119. data/client/hippo/components/shared/FieldWrapper.jsx +0 -94
  120. data/client/hippo/components/shared/FormGroup.jsx +0 -41
  121. data/client/hippo/components/shared/GenericField.jsx +0 -7
  122. data/client/hippo/components/shared/IconButton.jsx +0 -13
  123. data/client/hippo/components/shared/ImageAsset.jsx +0 -78
  124. data/client/hippo/components/shared/IndeterminateCheckbox.jsx +0 -31
  125. data/client/hippo/components/shared/Input.jsx +0 -16
  126. data/client/hippo/components/shared/InputFieldMixin.jsx +0 -78
  127. data/client/hippo/components/shared/JobProgress.jsx +0 -46
  128. data/client/hippo/components/shared/NumberInput.jsx +0 -37
  129. data/client/hippo/components/shared/PanelHeader.jsx +0 -15
  130. data/client/hippo/components/shared/RadioField.jsx +0 -33
  131. data/client/hippo/components/shared/ResizeSensor.jsx +0 -18
  132. data/client/hippo/components/shared/ScreenWrapper.jsx +0 -17
  133. data/client/hippo/components/shared/TextArea.jsx +0 -19
  134. data/client/hippo/components/shared/Throbber.jsx +0 -8
  135. data/client/hippo/components/shared/ToggleField.jsx +0 -2
  136. data/client/hippo/components/shared/Tooltip.jsx +0 -23
  137. data/client/hippo/components/shared/fields.scss +0 -58
  138. data/client/hippo/components/shared/fieldset.scss +0 -27
  139. data/client/hippo/components/shared/image-asset.scss +0 -53
  140. data/client/hippo/components/shared/index.js +0 -5
  141. data/client/hippo/components/shared/overlay.scss +0 -83
  142. data/client/hippo/components/shared/resize-sensor.scss +0 -30
  143. data/client/hippo/components/shared/styles.scss +0 -64
  144. data/client/hippo/components/shared/throbber.scss +0 -53
  145. data/client/hippo/fonts/fontawesome-webfont.woff +0 -0
  146. data/client/hippo/fonts/fontawesome-webfont.woff2 +0 -0
  147. data/client/hippo/workspace/content.jsx +0 -22
  148. data/client/hippo/workspace/tabs.jsx +0 -60
  149. data/client/hippo/workspace/viewport.jsx +0 -82
  150. data/spec/client/screens/__snapshots__/tabs.spec.jsx.snap +0 -127
  151. data/spec/client/screens/tabs.spec.jsx +0 -36
@@ -1,15 +0,0 @@
1
- import React from 'react';
2
-
3
- export default class DisplayValue extends React.Component {
4
- static mixins = [
5
- Hippo.Components.Form.FieldMixin
6
- ];
7
- static fieldClassName = 'display-value';
8
- renderEdit(props) {
9
- return (
10
- <BS.FormControl.Static {...props}>
11
- {this.fieldMixinGetValue()}
12
- </BS.FormControl.Static>
13
- );
14
- }
15
- }
@@ -1,37 +0,0 @@
1
- import React from 'react';
2
-
3
- export class ErrorDisplay extends React.Component {
4
- static propTypes =
5
- {model: Hippo.PropTypes.State.isRequired};
6
- bindEvents() {
7
- return (
8
- {model: "change:error"}
9
- );
10
- }
11
-
12
- clearErrors() {
13
- return (
14
- this.model.errors = null
15
- );
16
- }
17
-
18
- render() {
19
- if (!this.model.errors) { return null; }
20
- return (
21
- <div export className="alert alert-warning alert-dismissible" role="alert">
22
- <button
23
- onClick={this.clearErrors}
24
- type="button"
25
- export className="close"
26
- data-dismiss="alert"
27
- aria-label="Close">
28
- <span aria-hidden="true">
29
- ×
30
- </span>
31
- </button>
32
- <i export className="icon icon-exclamation-circle" />
33
- {this.model.errorMessage}
34
- </div>
35
- );
36
- }
37
- }
@@ -1,254 +0,0 @@
1
- import React from 'react';
2
-
3
- if (!Hippo.Components.Form) { Hippo.Components.Form = {}; }
4
-
5
-
6
- Hippo.Components.Form.FieldMixin = {
7
-
8
- registerForPubSub: false,
9
-
10
- bindEvents() {
11
- return (
12
- {model: `change:${this.props.name} remote-update:${this.props.name} invalid-fields invalid-field:${this.getInvalidFieldName()}`}
13
- );
14
- },
15
-
16
- mixins: [
17
- Hippo.React.Mixins.Access,
18
- Hippo.React.Mixins.ReadEditingState,
19
- Hippo.React.Mixins.FieldErrors
20
- ],
21
-
22
- propTypes: {
23
- model: Hippo.PropTypes.State.isRequired,
24
- name: React.PropTypes.string.isRequired,
25
- unlabeled: React.PropTypes.bool,
26
- fieldOnly: React.PropTypes.bool,
27
- onChange: React.PropTypes.func,
28
- unstyled: React.PropTypes.bool,
29
- getValue: React.PropTypes.func,
30
- setValue: React.PropTypes.func,
31
- align: React.PropTypes.oneOf([
32
- 'right', 'left', 'center'
33
- ]),
34
- label: React.PropTypes.oneOfType([
35
- React.PropTypes.string, React.PropTypes.element
36
- ])
37
- },
38
-
39
- fieldMixinSetValue(ev) {
40
- if (this.props.onChange) {
41
- this.props.onChange(ev);
42
- }
43
- if (true !== __guardMethod__(ev, 'isDefaultPrevented', o => o.isDefaultPrevented())) {
44
- return (
45
- this.model[this.props.name] = ev.target.value
46
- );
47
- }
48
- },
49
-
50
- componentWillUnmount() {
51
- if (this.state.pendingChangeSetDelay) { return clearTimeout(this.state.pendingChangeSetDelay); }
52
- },
53
-
54
- _unsetChangeSet() {
55
- return (
56
- this.setState({displayChangeset: false, pendingChangeSetDelay: null})
57
- );
58
- },
59
-
60
- setModelState() {
61
- let pendingChangeSetDelay;
62
- const displayChangeset = this.model.updatingFromChangeset && this.model.changedAttributes()[this.props.name];
63
- if (displayChangeset && !this.state.pendingChangeSetDelay) {
64
- pendingChangeSetDelay = _.delay(this._unsetChangeSet, 2000);
65
- }
66
- return (
67
- this.setState({pendingChangeSetDelay, displayChangeset})
68
- );
69
- },
70
-
71
- _fieldMixinGetLabelValue() {
72
- return (
73
- __guardMethod__(this, 'getLabelValue', o => o.getLabelValue()) ||
74
- this.props.label ||
75
- _.titleize(_.humanize(this.props.name))
76
- );
77
- },
78
-
79
- fieldMixinGetValue() {
80
- const value = this.props.getValue ?
81
- this.props.getValue.call(this.model, this.props)
82
- : (this.props.value != null) ?
83
- this.props.value
84
- : this.getValue ?
85
- this.getValue()
86
- :
87
- this.model[this.props.name];
88
- if (_.isBlank(value)) {
89
- return (
90
- ''
91
- );
92
- } else {
93
- return (
94
- value
95
- );
96
- }
97
- },
98
-
99
- _fieldMixinRenderFormGroup(child, props, options) {
100
- let feedback, invalidMsg, label;
101
- if (invalidMsg = this.fieldInvalidValueMessage()) {
102
- feedback = [
103
- React.createElement(BS.FormControl.Feedback, {"key": "feedback"}),
104
- React.createElement(BS.HelpBlock, {"key": "help"}, (invalidMsg))
105
- ];
106
- }
107
-
108
- if (!this.props.unlabeled) {
109
- label =
110
- React.createElement(BS.ControlLabel, null,
111
- (this._fieldMixinGetLabelValue())
112
- );
113
- }
114
-
115
- return (
116
-
117
- React.createElement(BS.Col, Object.assign({}, props),
118
- React.createElement(BS.FormGroup, {"validationState": (options.validationState)},
119
- (label),
120
- (child),
121
- (feedback)
122
- )
123
- )
124
-
125
- );
126
- },
127
-
128
- _fieldMixinRenderEdit(props) {
129
- return (
130
- React.createElement(BS.FormControl, Object.assign({
131
- "type": (this.props.type || "text"),
132
- "value": (this.fieldMixinGetValue())
133
- }, props
134
- ))
135
- );
136
- },
137
-
138
- _fieldMixinRenderDisplay(props) {
139
- let value = this.fieldMixinGetValue();
140
- if (_.isObject(value)) { value = value.toString(); }
141
- return (
142
- React.createElement(BS.FormControl.Static, null,
143
- (value)
144
- )
145
- );
146
- },
147
-
148
-
149
- _fieldMixinRenderNone(props) {
150
- const clean = LC.Form.FieldMixin.statics.cleanSizeProps(props);
151
- return (
152
- React.createElement("span", Object.assign({}, clean ))
153
- );
154
- },
155
-
156
- renderType() {
157
- if (this.isEditingRecord()) {
158
- if (this.hasWriteAccess()) {
159
- return (
160
- ['edit', 'Edit']
161
- );
162
- } else if (this.hasReadAccess()) {
163
- return (
164
- ['read-only', 'Display']
165
- );
166
- } else {
167
- return (
168
- ['none', 'None']
169
- );
170
- }
171
- } else {
172
- if (this.hasReadAccess()) {
173
- return (
174
- ['display', 'Display']
175
- );
176
- } else {
177
- return (
178
- ['none', 'None']
179
- );
180
- }
181
- }
182
- },
183
- statics: {
184
- cleanSizeProps(props, comp) {
185
- if (comp == null) { comp = {}; }
186
- return (
187
- Hippo.u.cleanBsSizes( LC.Form.FieldMixin.statics.cleanColumnProps(props, comp) )
188
- );
189
- },
190
-
191
- cleanColumnProps(props, comp, ...xtra) {
192
- return (
193
- _.omit( props, _.keys(comp.constructor.propTypes).concat([
194
- 'model', 'label', 'name', 'unlabeled', 'fieldOnly', 'placeholder',
195
- 'commands', 'query', 'editOnly', 'syncOptions', 'labelField', 'type',
196
- 'selectField', 'idField', 'queryModel', 'choices', 'align'
197
- ], xtra))
198
- );
199
- },
200
-
201
- renderEmptyColumn(props) {
202
- if (props == null) { ({ props } = this); }
203
- props = this.cleanColumnProps(props, this);
204
- return (
205
- React.createElement(BS.Col, Object.assign({}, props ))
206
- );
207
- }
208
- },
209
-
210
- render() {
211
- const [type, method] = Array.from(this.renderType());
212
- const options = {};
213
-
214
- const hasError = this.isFieldValueInvalid();
215
- if (hasError) { options.validationState = 'warning'; }
216
- const props = LC.Form.FieldMixin.statics.cleanColumnProps(this.props, this);
217
-
218
- props.export className = _.classnames(
219
- _.result(this, 'fieldClassName'),
220
- 'hippo-field', type, props.export className,
221
- ( this.props.align ? `align-${this.props.align}` : null),
222
- {
223
- changeset: this.state.displayChangeset,
224
- 'has-error': hasError
225
- }
226
- );
227
- const fieldProps = Hippo.u.cleanBsSizes(props);
228
- const field = (this[ `render${method}` ] || this[`_fieldMixinRender${method}`])(
229
- this.props.fieldOnly ? fieldProps : _.omit(fieldProps, 'export className')
230
- );
231
- if (this.props.fieldOnly) {
232
- return (
233
- field
234
- );
235
- } else {
236
- return (
237
- ( this['renderFormGroup'] || this['_fieldMixinRenderFormGroup'] )(field, props, options)
238
- );
239
- }
240
- }
241
-
242
- };
243
-
244
- function __guardMethod__(obj, methodName, transform) {
245
- if (typeof obj !== 'undefined' && obj !== null && typeof obj[methodName] === 'function') {
246
- return (
247
- transform(obj, methodName)
248
- );
249
- } else {
250
- return (
251
- undefined
252
- );
253
- }
254
- }
@@ -1,52 +0,0 @@
1
- import React from 'react';
2
-
3
- export class FieldSet extends React.Component {
4
- static propTypes = {
5
- title: React.PropTypes.string.isRequired,
6
- expanded: React.PropTypes.bool,
7
- containerClassName: React.PropTypes.string
8
- };
9
- getDefaultProps() {
10
- return (
11
- {expanded: true}
12
- );
13
- }
14
-
15
- getInitialState() {
16
- return (
17
- {expanded: this.props.expanded}
18
- );
19
- }
20
-
21
- componentWillReceiveProps(nextProps) {
22
- if (nextProps.expanded != null) { return this.setState({expanded: nextProps.expanded}); }
23
- }
24
-
25
- toggleExpanded() {
26
- return (
27
- this.setState({expanded: !this.state.expanded})
28
- );
29
- }
30
-
31
- render() {
32
- const colProps = _.omit(this.props, 'name', 'expanded', 'bodyClassName');
33
- const bodyClassName = _.export classnames("container", this.props.containerClassName);
34
- return (
35
- React.createElement(BS.Col, Object.assign({}, colProps),
36
- React.createElement("fieldset", {"export className": (
37
- _.export classnames("collapsible", this.props.className, this.state.icon,
38
- {expanded: this.state.expanded, collapsed: !this.state.expanded})
39
- )},
40
- React.createElement("legend", {"onClick": (this.toggleExpanded)},
41
- (this.props.title)
42
- ),
43
- React.createElement(BS.Collapse, {"in": (this.state.expanded)},
44
- React.createElement("div", {"ref": "body", "export className": (bodyClassName)},
45
- (this.props.children)
46
- )
47
- )
48
- )
49
- )
50
- );
51
- }
52
- }
@@ -1,94 +0,0 @@
1
- import React from 'react';
2
-
3
- export class FieldWrapper extends BaseComponent {
4
- static mixins = [
5
- Hippo.React.Mixins.Access,
6
- Hippo.React.Mixins.FieldErrors,
7
- Hippo.React.Mixins.ReadEditingState
8
- ];
9
- static blankElement = 'span';
10
- static propTypes = {
11
- model: Hippo.PropTypes.State.isRequired,
12
- unlabeled: React.PropTypes.bool,
13
- displayComponent: React.PropTypes.any.isRequired,
14
- label: React.PropTypes.oneOfType([
15
- React.PropTypes.string, React.PropTypes.element
16
- ])
17
- };
18
- renderLabel() {
19
- if (this.props.unlabeled) { return null; }
20
- return (
21
- React.createElement(BS.ControlLabel, null,
22
- (this.props.label)
23
- )
24
- );
25
- }
26
-
27
- renderType() {
28
- if (this.isEditingRecord()) {
29
- if (this.hasWriteAccess()) {
30
- return (
31
- ['edit', this.props.children]
32
- );
33
- } else if (this.hasReadAccess()) {
34
- return (
35
- ['display']
36
- );
37
- } else {
38
- return (
39
- ['none', this.blankElement]
40
- );
41
- }
42
- } else {
43
- if (this.hasReadAccess()) {
44
- return (
45
- ['display']
46
- );
47
- } else {
48
- return (
49
- ['none', this.blankElement]
50
- );
51
- }
52
- }
53
- }
54
-
55
- render() {
56
- let invalidMsg, msg, validationState;
57
- let [type, child] = Array.from(this.renderType());
58
-
59
- const props = _.omit(this.props,
60
- 'value', 'model', 'value', 'label', 'name', 'displayComponent'
61
- );
62
- if (!child) {
63
- const Comp = this.props.displayComponent;
64
- child = React.createElement(Comp, {"props": true});
65
- }
66
-
67
- if (this.isFieldValueInvalid()) {
68
- validationState = 'warning';
69
- }
70
-
71
- if (invalidMsg = this.fieldInvalidValueMessage()) {
72
- msg = React.createElement(BS.HelpBlock, null, (invalidMsg));
73
- }
74
-
75
- const export className = _.classnames( 'hippo-field', type, this.props.className,
76
- ( this.props.align ? `align-${this.props.align}` : null)
77
- );
78
-
79
- return (
80
-
81
- React.createElement(BS.Col, Object.assign({}, props, {"export className": (className)}),
82
- React.createElement(BS.FormGroup, {"validationState": (validationState)},
83
- React.createElement(BS.ControlLabel, null,
84
- (this.renderLabel())
85
- ),
86
- (child),
87
- React.createElement(BS.FormControl.Feedback, null),
88
- (msg)
89
- )
90
- )
91
-
92
- );
93
- }
94
- }