hippo-fw 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|