hippo-fw 0.9.6 → 0.9.7
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.
- checksums.yaml +4 -4
- data/client/hippo/components/asset.jsx +22 -2
- data/client/hippo/components/asset.scss +1 -1
- data/client/hippo/components/data-list.jsx +38 -27
- data/client/hippo/components/data-list/data-list.scss +2 -0
- data/client/hippo/components/data-table.jsx +4 -2
- data/client/hippo/components/data-table/formatters.js +7 -0
- data/client/hippo/components/data-table/table-styles.scss +10 -0
- data/client/hippo/components/date-time.jsx +93 -133
- data/client/hippo/components/date-time.scss +1 -36
- data/client/hippo/components/form/api.js +4 -3
- data/client/hippo/components/form/fields.jsx +7 -1
- data/client/hippo/components/form/fields/date-wrapper.jsx +4 -4
- data/client/hippo/components/icon.jsx +10 -1
- data/client/hippo/components/query-builder.jsx +6 -1
- data/client/hippo/components/record-finder/query-layer.jsx +1 -1
- data/client/hippo/components/save-button.jsx +55 -0
- data/client/hippo/components/text-editor.jsx +10 -9
- data/client/hippo/components/text-editor/text-editor.scss +0 -1
- data/client/hippo/components/time-zone-select.jsx +60 -0
- data/client/hippo/models/asset.js +10 -5
- data/client/hippo/models/base.js +1 -1
- data/client/hippo/models/pub_sub.js +22 -67
- data/client/hippo/models/pub_sub/channel.js +28 -8
- data/client/hippo/models/pub_sub/map.js +57 -0
- data/client/hippo/models/query/array-result.js +5 -4
- data/client/hippo/models/query/field.js +19 -3
- data/client/hippo/models/system-setting.js +16 -1
- data/client/hippo/models/tenant.js +8 -7
- data/client/hippo/screens/system-settings.jsx +10 -12
- data/client/hippo/screens/user-management/edit-form.jsx +10 -11
- data/client/hippo/workspace/index.jsx +6 -3
- data/client/hippo/workspace/menu-option.jsx +2 -5
- data/client/hippo/workspace/menu.jsx +13 -1
- data/client/hippo/workspace/styles.scss +11 -26
- data/command-reference-files/initial/Gemfile +1 -1
- data/command-reference-files/model/client/appy-app/models/test_test.js +1 -1
- data/command-reference-files/model/spec/server/models/test_test_spec.rb +10 -0
- data/lib/hippo/api/cable.rb +0 -2
- data/lib/hippo/command/generate_model.rb +2 -3
- data/lib/hippo/spec_helper.rb +4 -2
- data/lib/hippo/tenant.rb +7 -1
- data/lib/hippo/version.rb +1 -1
- data/package-lock.json +60 -46
- data/package.json +5 -2
- data/spec/client/components/__snapshots__/record-finder.spec.jsx.snap +1 -0
- data/spec/client/components/__snapshots__/time-zone-select.spec.jsx.snap +48 -0
- data/spec/client/components/form.spec.jsx +7 -0
- data/spec/client/components/time-zone-select.spec.jsx +11 -0
- data/spec/client/models/pub_sub.spec.js +1 -3
- data/spec/client/models/pub_sub/channel.spec.js +45 -0
- data/spec/client/models/system-setting.spec.js +14 -0
- data/spec/client/workspace/__snapshots__/menu.spec.jsx.snap +9 -9
- data/spec/server/api/tenant_change_spec.rb +1 -1
- data/templates/client/models/model.js +1 -1
- data/templates/spec/factories/model.rb +6 -0
- data/templates/spec/server/model_spec.rb +4 -4
- data/views/hippo_root_view.erb +4 -0
- metadata +11 -10
- data/client/hippo/components/date-time/calendar.jsx +0 -113
- data/client/hippo/components/date-time/date-time-drop.jsx +0 -75
- data/client/hippo/components/date-time/date-time.scss +0 -157
- data/client/hippo/components/date-time/time.jsx +0 -119
- data/client/hippo/workspace/foo.js +0 -0
- data/command-reference-files/model/spec/fixtures/appy-app/test_test.yml +0 -11
- data/command-reference-files/model/spec/server/test_test_spec.rb +0 -10
- data/spec/client/components/date-time.spec.jsx +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf25cc10af49e41c6a3b48817f8bc1b50853484e
|
4
|
+
data.tar.gz: 7afc125a95df6077aa39e6f6acec0d42c3d926a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98ee0dc3e62a19bf1d3aa0503781a0b374061a0490c06a73039cb8f3040b455cfb9a18b157ae54c1940ecb27f9cb19f054656e9bd185a5276058809deaf6edad
|
7
|
+
data.tar.gz: 3217e075db4cac207c3b5cad67a8cb269114ca7f59a8396b8112472ce2acef5e347d808ee888baa4f61257d3e5ceaa5d61ba029689ec0505cbef6b6aa1d9aacf
|
@@ -18,6 +18,7 @@ export default class Asset extends React.PureComponent {
|
|
18
18
|
static defaultProps = {
|
19
19
|
label: '',
|
20
20
|
className: '',
|
21
|
+
tabIndex: 0,
|
21
22
|
}
|
22
23
|
|
23
24
|
static propTypes = {
|
@@ -25,6 +26,7 @@ export default class Asset extends React.PureComponent {
|
|
25
26
|
name: PropTypes.string.isRequired,
|
26
27
|
label: PropTypes.string,
|
27
28
|
className: PropTypes.string,
|
29
|
+
tabIndex: PropTypes.number,
|
28
30
|
}
|
29
31
|
|
30
32
|
@action.bound
|
@@ -43,6 +45,18 @@ export default class Asset extends React.PureComponent {
|
|
43
45
|
return this.props.label || titleize(this.props.name);
|
44
46
|
}
|
45
47
|
|
48
|
+
@action.bound
|
49
|
+
setDZRef(dz) {
|
50
|
+
this.dropZone = dz;
|
51
|
+
}
|
52
|
+
|
53
|
+
@action.bound
|
54
|
+
onKey(ev) {
|
55
|
+
if ('Enter' === ev.key) {
|
56
|
+
this.dropZone.open();
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
46
60
|
preview() {
|
47
61
|
if (this.asset && this.asset.exists) {
|
48
62
|
return this.asset.isImage ?
|
@@ -56,20 +70,26 @@ export default class Asset extends React.PureComponent {
|
|
56
70
|
);
|
57
71
|
}
|
58
72
|
|
73
|
+
|
59
74
|
render() {
|
60
|
-
const { model: _, label: __, name: ___, className, ...col } = this.props;
|
75
|
+
const { model: _, label: __, name: ___, className, tabIndex, ...col } = this.props;
|
61
76
|
|
62
77
|
return (
|
63
78
|
<Col
|
64
79
|
{...col}
|
65
80
|
className={classnames(className, 'asset', 'form-field')}
|
66
81
|
>
|
67
|
-
<Field
|
82
|
+
<Field
|
83
|
+
label={this.label}
|
84
|
+
tabIndex={tabIndex}
|
85
|
+
onKeyPress={this.onKey}
|
86
|
+
>
|
68
87
|
<Dropzone
|
69
88
|
className="drop-zone"
|
70
89
|
activeClassName="drop-zone-active"
|
71
90
|
onDrop={this.onDrop}
|
72
91
|
multiple={false}
|
92
|
+
ref={this.setDZRef}
|
73
93
|
>
|
74
94
|
{this.preview()}
|
75
95
|
</Dropzone>
|
@@ -69,37 +69,48 @@ export default class DataList extends React.Component {
|
|
69
69
|
render() {
|
70
70
|
const { query } = this;
|
71
71
|
const { rowHeight, rowRenderer, ...listProps } = this.props;
|
72
|
+
|
72
73
|
return (
|
73
74
|
<Box
|
74
75
|
className={cn('data-list', { selectable: this.props.onRowClick })}
|
75
|
-
align='stretch'
|
76
|
+
align='stretch' flex
|
76
77
|
>
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
78
|
+
|
79
|
+
{this.props.header}
|
80
|
+
|
81
|
+
<Box className="body" align="stretch" flex>
|
82
|
+
<InfiniteLoader
|
83
|
+
keyChange={query.results.updateKey}
|
84
|
+
minimumBatchSize={query.pageSize}
|
85
|
+
isRowLoaded={this.isRowLoaded}
|
86
|
+
loadMoreRows={this.loadMoreRows}
|
87
|
+
rowCount={query.results.totalCount}
|
88
|
+
keyChange={query.results.fingerprint}
|
89
|
+
>
|
90
|
+
{({ onRowsRendered, registerChild }) =>
|
91
|
+
<AutoSizer
|
92
|
+
keyChange={query.results.fingerprint}
|
93
|
+
updateKey={query.results.updateKey}
|
94
|
+
>
|
95
|
+
{({ height, width }) =>
|
96
|
+
<List
|
97
|
+
{...listProps}
|
98
|
+
height={height}
|
99
|
+
width={width}
|
100
|
+
ref={(list) => {
|
101
|
+
registerChild(list);
|
102
|
+
this.listRef = list;
|
103
|
+
}}
|
104
|
+
rowHeight={rowHeight}
|
105
|
+
headerHeight={50}
|
106
|
+
onRowsRendered={onRowsRendered}
|
107
|
+
rowRenderer={rowRenderer || this.rowRenderer}
|
108
|
+
rowCount={query.results.rows.length}
|
109
|
+
keyChange={query.results.fingerprint}
|
110
|
+
/>}
|
111
|
+
</AutoSizer>}
|
112
|
+
</InfiniteLoader>
|
113
|
+
</Box>
|
103
114
|
</Box>
|
104
115
|
);
|
105
116
|
}
|
@@ -119,7 +119,7 @@ export default class DataTable extends React.Component {
|
|
119
119
|
}
|
120
120
|
|
121
121
|
@computed get gridRenderKey() {
|
122
|
-
return `${this.query.results.
|
122
|
+
return `${this.query.results.fingerprint}-${this.editIndex}`;
|
123
123
|
}
|
124
124
|
|
125
125
|
@computed get columnDefinitions() {
|
@@ -129,7 +129,9 @@ export default class DataTable extends React.Component {
|
|
129
129
|
columnData: f,
|
130
130
|
dataKey: f.dataIndex || f.id,
|
131
131
|
headerRenderer: this.headerRenderer,
|
132
|
-
}, pick(f, 'width', 'label', 'flexGrow', 'flexShrink',
|
132
|
+
}, pick(f, 'width', 'label', 'flexGrow', 'flexShrink',
|
133
|
+
'cellRenderer', 'className', 'headerClassName'),
|
134
|
+
),
|
133
135
|
);
|
134
136
|
if (this.props.editor) {
|
135
137
|
definitions.unshift({
|
@@ -37,5 +37,15 @@
|
|
37
37
|
}
|
38
38
|
}
|
39
39
|
|
40
|
+
.ReactVirtualized__Table__rowColumn {
|
41
|
+
&.l { text-align: left; }
|
42
|
+
&.r { text-align: right; }
|
43
|
+
&.c { text-align: center; }
|
44
|
+
}
|
45
|
+
.ReactVirtualized__Table__headerColumn {
|
46
|
+
&.l { text-align: left; }
|
47
|
+
&.r { text-align: right; }
|
48
|
+
&.c { text-align: center; }
|
49
|
+
}
|
40
50
|
}
|
41
51
|
}
|
@@ -1,172 +1,132 @@
|
|
1
1
|
import React from 'react';
|
2
|
-
import PropTypes
|
3
|
-
import {
|
4
|
-
import {
|
5
|
-
import
|
6
|
-
import
|
7
|
-
import
|
8
|
-
import
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { observer } from 'mobx-react';
|
4
|
+
import { autobind } from 'core-decorators';
|
5
|
+
import Flatpickr from 'flatpickr';
|
6
|
+
import { defaults, has, omit } from 'lodash';
|
7
|
+
import { observable, action } from 'mobx';
|
8
|
+
import './date-time.scss';
|
9
|
+
|
10
|
+
const hooks = [
|
11
|
+
'onOpen',
|
12
|
+
'onMonthChange',
|
13
|
+
'onYearChange',
|
14
|
+
'onReady',
|
15
|
+
'onValueUpdate',
|
16
|
+
'onDayCreate',
|
17
|
+
'onBlur',
|
18
|
+
'onChange',
|
19
|
+
];
|
20
|
+
|
21
|
+
const defaultOptions = {
|
22
|
+
enableTime: true,
|
23
|
+
format: 'M d Y h:iK',
|
24
|
+
};
|
20
25
|
|
21
26
|
@observer
|
22
|
-
export default class
|
27
|
+
export default class DateTimePicker extends React.PureComponent {
|
23
28
|
static propTypes = {
|
24
|
-
|
25
|
-
|
26
|
-
|
29
|
+
defaultValue: PropTypes.string,
|
30
|
+
options: PropTypes.object,
|
31
|
+
onChange: PropTypes.func,
|
32
|
+
onOpen: PropTypes.func,
|
33
|
+
onClose: PropTypes.func,
|
34
|
+
onMonthChange: PropTypes.func,
|
35
|
+
onYearChange: PropTypes.func,
|
36
|
+
onReady: PropTypes.func,
|
37
|
+
onValueUpdate: PropTypes.func,
|
38
|
+
onDayCreate: PropTypes.func,
|
39
|
+
value: PropTypes.oneOfType([
|
40
|
+
PropTypes.string,
|
41
|
+
PropTypes.array,
|
42
|
+
PropTypes.object,
|
43
|
+
PropTypes.number,
|
44
|
+
]),
|
45
|
+
children: PropTypes.node,
|
27
46
|
}
|
28
47
|
|
29
48
|
static defaultProps = {
|
30
|
-
|
31
|
-
onDropChange: () => {},
|
49
|
+
options: {},
|
32
50
|
}
|
33
51
|
|
34
|
-
|
35
|
-
onDropChange: PropTypes.func,
|
36
|
-
}
|
37
|
-
|
38
|
-
@observable drop;
|
39
|
-
@observable dateValue;
|
52
|
+
@observable node;
|
40
53
|
|
41
|
-
|
54
|
+
componentWillReceiveProps(props) {
|
55
|
+
const options = this.getOptions(props);
|
42
56
|
|
43
|
-
|
44
|
-
|
45
|
-
const dropElement = document.querySelector(`.${DateTimeDrop.className}`);
|
46
|
-
if (!isDescendant(this.containerRef, ev.target) &&
|
47
|
-
(!dropElement || !isDescendant(dropElement, ev.target))) {
|
48
|
-
this.setDropActivation(false);
|
57
|
+
if (has(props, 'value')) {
|
58
|
+
this.flatpickr.setDate(props.value, false);
|
49
59
|
}
|
50
|
-
}
|
51
60
|
|
52
|
-
|
53
|
-
onForceClose() {
|
54
|
-
this.setDropActivation(false);
|
55
|
-
}
|
61
|
+
const optionsKeys = Object.getOwnPropertyNames(options);
|
56
62
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
const listeners = {
|
62
|
-
esc: this.onForceClose,
|
63
|
-
};
|
64
|
-
|
65
|
-
if (dropActive && !this.dropActive) {
|
66
|
-
document.addEventListener('click', this.onClose);
|
67
|
-
KeyboardAccelerators.startListeningToKeyboard(this, listeners);
|
68
|
-
// If this is inside a FormField, place the drop in reference to it.
|
69
|
-
const control = findAncestor(this.containerRef, `.${FORM_FIELD}`) || this.containerRef;
|
70
|
-
this.drop = new Drop(control, this.renderDrop(), {
|
71
|
-
align: { top: 'bottom', left: 'left' },
|
72
|
-
focusControl: true,
|
73
|
-
context: this.context,
|
74
|
-
});
|
75
|
-
this.dropActive = true;
|
76
|
-
this.props.onDropChange();
|
77
|
-
} else if (!dropActive && this.dropActive) {
|
78
|
-
document.removeEventListener('click', this.onClose);
|
79
|
-
KeyboardAccelerators.stopListeningToKeyboard(this, listeners);
|
80
|
-
|
81
|
-
if (this.drop) {
|
82
|
-
this.drop.remove();
|
83
|
-
this.drop = undefined;
|
84
|
-
}
|
85
|
-
this.dropActive = false;
|
86
|
-
this.props.onDropChange();
|
87
|
-
}
|
63
|
+
for (let index = optionsKeys.length - 1; index >= 0; index--) {
|
64
|
+
const key = optionsKeys[index];
|
65
|
+
let value = options[key];
|
88
66
|
|
89
|
-
|
90
|
-
|
67
|
+
// Hook handlers must be set as an array
|
68
|
+
if (hooks.indexOf(key) !== -1 && !Array.isArray(value)) {
|
69
|
+
value = [value];
|
70
|
+
}
|
71
|
+
this.flatpickr.set(key, value);
|
91
72
|
}
|
92
73
|
}
|
93
74
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
@action.bound
|
99
|
-
onInputChange(ev) {
|
100
|
-
this.editingValue = ev.target.value;
|
101
|
-
}
|
75
|
+
componentDidMount() {
|
76
|
+
const options = this.getOptions(this.props);
|
77
|
+
this.flatpickr = new Flatpickr(this.node, options);
|
102
78
|
|
103
|
-
|
104
|
-
|
105
|
-
if (!this.editingValue) { return; }
|
106
|
-
const value = moment(this.editingValue, this.props.format);
|
107
|
-
this.editingValue = '';
|
108
|
-
this.onForceClose();
|
109
|
-
if (value.isValid()) {
|
110
|
-
this.props.onChange(value);
|
111
|
-
this.dateValue = value;
|
79
|
+
if (has(this.props, 'value')) {
|
80
|
+
this.flatpickr.setDate(this.props.value, false);
|
112
81
|
}
|
113
82
|
}
|
114
83
|
|
115
84
|
componentWillUnmount() {
|
116
|
-
this.
|
85
|
+
this.flatpickr.destroy();
|
117
86
|
}
|
118
87
|
|
119
|
-
|
120
|
-
|
121
|
-
this.
|
88
|
+
|
89
|
+
@autobind onClose() {
|
90
|
+
if (this.node.blur) { this.node.blur(); }
|
122
91
|
}
|
123
92
|
|
124
|
-
@
|
125
|
-
|
126
|
-
const value = moment(date);
|
127
|
-
this.props.onChange(value.toDate());
|
128
|
-
this.dateValue = value;
|
93
|
+
@autobind onChange(dates) {
|
94
|
+
this.props.onChange({ target: { value: dates[0] } });
|
129
95
|
}
|
130
96
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
97
|
+
getOptions(props) {
|
98
|
+
const options = defaults({
|
99
|
+
...this.props.options,
|
100
|
+
onClose: this.onClose,
|
101
|
+
onChange: this.onChange,
|
102
|
+
dateFormat: props.format,
|
103
|
+
}, defaultOptions);
|
104
|
+
// Add prop hooks to options
|
105
|
+
hooks.forEach((hook) => {
|
106
|
+
if (this[hook]) {
|
107
|
+
options[hook] = this[hook];
|
108
|
+
} else if (this.props[hook]) {
|
109
|
+
options[hook] = this.props[hook];
|
110
|
+
}
|
111
|
+
});
|
112
|
+
return options;
|
139
113
|
}
|
140
114
|
|
141
|
-
@
|
142
|
-
|
143
|
-
|
144
|
-
return '';
|
115
|
+
@action.bound
|
116
|
+
setNode(node) {
|
117
|
+
this.node = node;
|
145
118
|
}
|
146
119
|
|
147
120
|
render() {
|
148
|
-
|
149
|
-
const
|
121
|
+
// eslint-disable-next-line no-unused-vars
|
122
|
+
const { options, defaultValue, value, children, ...props } = omit(this.props, hooks);
|
150
123
|
|
151
124
|
return (
|
152
|
-
<
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
placeholder={format}
|
158
|
-
className={`${INPUT} ${CLASS_ROOT}__input`}
|
159
|
-
onClick={this.onControlClick}
|
160
|
-
onChange={this.onInputChange}
|
161
|
-
onBlur={this.onInputBlur}
|
162
|
-
value={inputValue || ''}
|
163
|
-
/>
|
164
|
-
<Button
|
165
|
-
icon={<Icon />}
|
166
|
-
onClick={this.onControlClick}
|
167
|
-
className={`${CLASS_ROOT}__control`}
|
168
|
-
/>
|
169
|
-
</div>
|
125
|
+
<input
|
126
|
+
{...props}
|
127
|
+
defaultValue={defaultValue}
|
128
|
+
ref={this.setNode}
|
129
|
+
/>
|
170
130
|
);
|
171
131
|
}
|
172
132
|
}
|