hippo-fw 0.9.4 → 0.9.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +2 -3
- data/Gemfile +1 -1
- data/client/hippo/__mocks__/config.js +4 -4
- data/client/hippo/boot.jsx +1 -0
- data/client/hippo/components/asset.jsx +4 -4
- data/client/hippo/components/date-time.jsx +169 -0
- data/client/hippo/components/date-time.scss +38 -0
- data/client/hippo/components/date-time/calendar.jsx +115 -0
- data/client/hippo/components/date-time/date-time-drop.jsx +77 -0
- data/client/hippo/components/date-time/date-time.scss +157 -0
- data/client/hippo/components/date-time/time.jsx +120 -0
- data/client/hippo/components/form/fields/date-wrapper.jsx +4 -3
- data/client/hippo/components/form/model.js +0 -2
- data/client/hippo/components/text-editor.jsx +85 -0
- data/client/hippo/components/text-editor/display-modes/Button.jsx +17 -0
- data/client/hippo/components/text-editor/display-modes/SaveState.jsx +17 -0
- data/client/hippo/components/text-editor/display-modes/ToggleEdit.jsx +22 -0
- data/client/hippo/components/text-editor/display-modes/ToggleInsert.jsx +21 -0
- data/client/hippo/components/text-editor/display-modes/ToggleLayout.jsx +21 -0
- data/client/hippo/components/text-editor/display-modes/TogglePreview.jsx +21 -0
- data/client/hippo/components/text-editor/display-modes/ToggleResize.jsx +21 -0
- data/client/hippo/components/text-editor/display-modes/index.css +0 -0
- data/client/hippo/components/text-editor/display-modes/index.js +30 -0
- data/client/hippo/components/text-editor/image-plugin/Component/Display/index.js +80 -0
- data/client/hippo/components/text-editor/image-plugin/Component/Form/index.js +40 -0
- data/client/hippo/components/text-editor/image-plugin/Component/index.js +16 -0
- data/client/hippo/components/text-editor/image-plugin/Component/index.scss +0 -0
- data/client/hippo/components/text-editor/image-plugin/index.js +32 -0
- data/client/hippo/components/text-editor/image-plugin/index.scss +25 -0
- data/client/hippo/components/text-editor/plugins.js +22 -0
- data/client/hippo/components/text-editor/renderer.jsx +37 -0
- data/client/hippo/components/text-editor/text-editor.scss +49 -0
- data/client/hippo/extensions/base.js +5 -2
- data/client/hippo/extensions/hippo.js +5 -2
- data/client/hippo/extensions/index.js +9 -3
- data/client/hippo/lib/__mocks__/request-assets.js +2 -2
- data/client/hippo/lib/bootstrap.js +0 -1
- data/client/hippo/lib/smooth-scroll.js +0 -1
- data/client/hippo/lib/util.js +4 -4
- data/client/hippo/models/asset.js +43 -23
- data/client/hippo/models/base.js +1 -2
- data/client/hippo/models/config.js +0 -1
- data/client/hippo/models/decorators.js +3 -3
- data/client/hippo/models/pub_sub.js +2 -5
- data/client/hippo/models/pub_sub/channel.js +0 -1
- data/client/hippo/models/query.js +0 -1
- data/client/hippo/models/query/array-result.js +0 -1
- data/client/hippo/models/query/clause.js +0 -1
- data/client/hippo/models/query/field.js +0 -1
- data/client/hippo/models/query/info.js +0 -3
- data/client/hippo/models/query/operator.js +0 -2
- data/client/hippo/models/query/result.js +0 -1
- data/client/hippo/models/sync.js +1 -1
- data/client/hippo/models/system-setting.js +0 -2
- data/client/hippo/models/tenant.js +0 -1
- data/client/hippo/screens/definition.js +0 -2
- data/client/hippo/screens/group.js +0 -2
- data/client/hippo/screens/instance.js +0 -3
- data/client/hippo/screens/system-settings/mailer-config.jsx +0 -3
- data/client/hippo/styles/global.scss +3 -0
- data/client/hippo/testing/mocks/fetch.js +6 -6
- data/client/hippo/user.js +4 -4
- data/client/hippo/workspace/index.jsx +12 -5
- data/client/hippo/workspace/root-view.jsx +10 -0
- data/command-reference-files/initial/.gitignore +1 -0
- data/command-reference-files/initial/Gemfile +1 -1
- data/command-reference-files/initial/client/appy-app/extension.js +4 -0
- data/command-reference-files/initial/config/webpack.config.js +25 -23
- data/config/routes.rb +4 -1
- data/config/webpack.config.js +1 -2
- data/hippo-fw.gemspec +4 -2
- data/lib/hippo.rb +0 -1
- data/lib/hippo/api/handlers/asset.rb +9 -0
- data/lib/hippo/api/updates.rb +2 -2
- data/lib/hippo/configuration.rb +0 -4
- data/lib/hippo/db.rb +2 -2
- data/lib/hippo/{rails.rb → db/fake_rails.rb} +0 -0
- data/lib/hippo/extension.rb +1 -2
- data/lib/hippo/mailer.rb +1 -0
- data/lib/hippo/spec_helper.rb +1 -0
- data/lib/hippo/version.rb +1 -1
- data/package-lock.json +626 -68
- data/package.json +14 -13
- data/spec/client/access/login-dialog.spec.jsx +1 -0
- data/spec/client/components/asset.spec.jsx +1 -2
- data/spec/client/components/date-time.spec.jsx +20 -0
- data/spec/client/extension/base.spec.js +0 -2
- data/spec/client/models/base.spec.js +4 -4
- data/spec/client/models/query.spec.js +2 -2
- data/spec/client/models/sync.spec.js +1 -1
- data/spec/client/screens/system-settings.spec.jsx +2 -1
- data/spec/client/setup.js +3 -0
- data/spec/client/test-models.js +0 -2
- data/spec/server/api/tenant_change_spec.rb +1 -1
- data/spec/server/api/tenant_isolation_spec.rb +6 -3
- data/spec/server/concerns/api_path_spec.rb +2 -2
- data/templates/.gitignore +1 -0
- data/templates/client/extension.js +4 -0
- data/templates/config/webpack.config.js +25 -23
- metadata +48 -12
- data/client/hippo/lib/pub_sub.js +0 -34
- data/client/hippo/react/viewport-root.jsx +0 -44
- data/spec/client/components/__snapshots__/asset.spec.jsx.snap +0 -48
- data/spec/client/screens/__snapshots__/system-settings.spec.jsx.snap +0 -443
- data/templates/gitignore +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a86a77e5eb0041425dcc05d9b6d8efb2c304a99
|
4
|
+
data.tar.gz: df658e7e5eb832884c88606575617b4247aa4e89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3df81f86cd6613d3ad71237534c7c997bac329470697ab6a83af8182e155059d1ee99d0e54298d45352a81ebfc137793560116af7271537c87cc2b62dba3e388
|
7
|
+
data.tar.gz: 566662660f26bf8cbb0dd4c31a4afdab9d1da1b53ca380bdeff349a9e7e7f16dab0cc18455f07f85a24c9e7c190c5b773a8a1f8b2f956d3bce701a174d9060ba
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -17,8 +17,7 @@ env:
|
|
17
17
|
global:
|
18
18
|
- DATABASE_URL=postgres://travis@127.0.0.1:5432/travis
|
19
19
|
- REDIS_URL=redis://localhost:6379
|
20
|
-
- TRAVIS_NODE_VERSION="
|
20
|
+
- TRAVIS_NODE_VERSION="7"
|
21
21
|
before_install:
|
22
22
|
- nvm install $TRAVIS_NODE_VERSION
|
23
|
-
- npm install
|
24
|
-
- yarn install
|
23
|
+
- npm install
|
data/Gemfile
CHANGED
@@ -2,7 +2,7 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
gem "activerecord-multi-tenant", git: 'https://github.com/citusdata/activerecord-multi-tenant.git', branch: 'release-0.5.1'
|
5
|
+
# gem "activerecord-multi-tenant", git: 'https://github.com/citusdata/activerecord-multi-tenant.git', branch: 'release-0.5.1'
|
6
6
|
|
7
7
|
# gem "activerecord-multi-tenant", git: "https://github.com/nathanstitt/activerecord-multi-tenant", branch: 'query_rewriter'
|
8
8
|
|
@@ -5,10 +5,10 @@ window.localStorage = {
|
|
5
5
|
},
|
6
6
|
};
|
7
7
|
|
8
|
-
const
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
const Config = jest.genMockFromModule('../models/config');
|
9
|
+
const { default: DefaultConfig } = Config;
|
10
|
+
const config = new DefaultConfig();
|
11
|
+
|
12
12
|
Object.defineProperty(config, 'api_path', {
|
13
13
|
value: '/api',
|
14
14
|
});
|
data/client/hippo/boot.jsx
CHANGED
@@ -22,9 +22,9 @@ export default class Asset extends React.PureComponent {
|
|
22
22
|
}
|
23
23
|
|
24
24
|
static propTypes = {
|
25
|
-
model:
|
26
|
-
name:
|
27
|
-
label:
|
25
|
+
model: PropTypes.instanceOf(BaseModel).isRequired,
|
26
|
+
name: PropTypes.string.isRequired,
|
27
|
+
label: PropTypes.string,
|
28
28
|
className: PropTypes.string,
|
29
29
|
}
|
30
30
|
|
@@ -33,7 +33,7 @@ export default class Asset extends React.PureComponent {
|
|
33
33
|
if (!this.asset) {
|
34
34
|
this.props.model[this.props.name] = {};
|
35
35
|
}
|
36
|
-
this.asset.
|
36
|
+
this.asset.setFile(files[0]);
|
37
37
|
}
|
38
38
|
|
39
39
|
get asset() {
|
@@ -0,0 +1,169 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { action, observable, computed } from 'mobx';
|
4
|
+
import { observer } from 'mobx-react';
|
5
|
+
import CalendarIcon from 'grommet/components/icons/base/Calendar';
|
6
|
+
import ClockIcon from 'grommet/components/icons/base/Clock';
|
7
|
+
import Button from 'grommet/components/Button';
|
8
|
+
import CSSClassnames from 'grommet/utils/CSSClassnames';
|
9
|
+
import { findAncestor, isDescendant } from 'grommet/utils/DOM';
|
10
|
+
import KeyboardAccelerators from 'grommet/utils/KeyboardAccelerators';
|
11
|
+
import Drop from 'grommet/utils/Drop';
|
12
|
+
import moment from 'moment';
|
13
|
+
|
14
|
+
import DateTimeDrop from './date-time/date-time-drop';
|
15
|
+
import './date-time/date-time.scss';
|
16
|
+
|
17
|
+
const INPUT = CSSClassnames.INPUT;
|
18
|
+
const FORM_FIELD = CSSClassnames.FORM_FIELD;
|
19
|
+
const CLASS_ROOT = CSSClassnames.DATE_TIME;
|
20
|
+
|
21
|
+
@observer
|
22
|
+
export default class DateTime extends React.Component {
|
23
|
+
|
24
|
+
static propTypes = {
|
25
|
+
value: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
|
26
|
+
onChange: PropTypes.func.isRequired,
|
27
|
+
format: PropTypes.string,
|
28
|
+
}
|
29
|
+
|
30
|
+
static defaultProps = {
|
31
|
+
format: 'M/D/YYYY',
|
32
|
+
onDropChange: () => {},
|
33
|
+
}
|
34
|
+
|
35
|
+
static contextTypes = {
|
36
|
+
onDropChange: PropTypes.func,
|
37
|
+
}
|
38
|
+
|
39
|
+
@observable drop;
|
40
|
+
@observable dateValue;
|
41
|
+
@observable editingValue
|
42
|
+
|
43
|
+
@action.bound
|
44
|
+
onClose(ev) {
|
45
|
+
const dropElement = document.querySelector(`.${DateTimeDrop.className}`);
|
46
|
+
if (!isDescendant(this.containerRef, ev.target) &&
|
47
|
+
(!dropElement || !isDescendant(dropElement, ev.target))) {
|
48
|
+
this.setDropActivation(false);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
@action.bound
|
53
|
+
onForceClose() {
|
54
|
+
this.setDropActivation(false);
|
55
|
+
}
|
56
|
+
|
57
|
+
@action.bound
|
58
|
+
setDropActivation(dropActive) {
|
59
|
+
const { onDropChange } = this.context;
|
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
|
+
}
|
88
|
+
|
89
|
+
if (onDropChange) {
|
90
|
+
onDropChange(dropActive);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
@computed get value() {
|
95
|
+
return this.dateValue || moment(this.props.value || new Date());
|
96
|
+
}
|
97
|
+
|
98
|
+
set value(value) {
|
99
|
+
this.dateValue = value;
|
100
|
+
}
|
101
|
+
|
102
|
+
@action.bound
|
103
|
+
onInputChange(ev) {
|
104
|
+
this.editingValue = ev.target.value;
|
105
|
+
}
|
106
|
+
|
107
|
+
@action.bound
|
108
|
+
onInputBlur() {
|
109
|
+
if (this.editingValue) {
|
110
|
+
this.value = moment(this.editingValue, this.props.format);
|
111
|
+
delete this.editingValue;
|
112
|
+
this.onForceClose();
|
113
|
+
this.props.onChange(this.value);
|
114
|
+
}
|
115
|
+
}
|
116
|
+
|
117
|
+
componentWillUnmount() {
|
118
|
+
this.setDropActivation(false);
|
119
|
+
}
|
120
|
+
|
121
|
+
@action.bound
|
122
|
+
onControlClick() {
|
123
|
+
this.setDropActivation(true);
|
124
|
+
}
|
125
|
+
|
126
|
+
@action.bound
|
127
|
+
onDateChange(date) {
|
128
|
+
this.value = moment(date);
|
129
|
+
this.props.onChange(this.value.toDate());
|
130
|
+
}
|
131
|
+
|
132
|
+
renderDrop() {
|
133
|
+
return (
|
134
|
+
<DateTimeDrop
|
135
|
+
{...this.props}
|
136
|
+
onChange={this.onDateChange}
|
137
|
+
value={this.value}
|
138
|
+
/>
|
139
|
+
);
|
140
|
+
}
|
141
|
+
|
142
|
+
render() {
|
143
|
+
const { props: { format, dateOnly } } = this;
|
144
|
+
const inputValue = this.editingValue || this.value.format(format);
|
145
|
+
const Icon = dateOnly ? CalendarIcon : ClockIcon;
|
146
|
+
|
147
|
+
return (
|
148
|
+
<div
|
149
|
+
ref={r => (this.containerRef = r)}
|
150
|
+
className={CLASS_ROOT}
|
151
|
+
>
|
152
|
+
<input
|
153
|
+
placeholder={format}
|
154
|
+
className={`${INPUT} ${CLASS_ROOT}__input`}
|
155
|
+
onClick={this.onControlClick}
|
156
|
+
onChange={this.onInputChange}
|
157
|
+
onBlur={this.onInputBlur}
|
158
|
+
value={inputValue || ''}
|
159
|
+
/>
|
160
|
+
<Button
|
161
|
+
icon={<Icon />}
|
162
|
+
onClick={this.onControlClick}
|
163
|
+
className={`${CLASS_ROOT}__control`}
|
164
|
+
/>
|
165
|
+
</div>
|
166
|
+
);
|
167
|
+
}
|
168
|
+
|
169
|
+
}
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#hippo-root {
|
2
|
+
@import '~input-moment/dist/input-moment.css';
|
3
|
+
.date-time.component {
|
4
|
+
|
5
|
+
.tab {
|
6
|
+
display: none;
|
7
|
+
&.active { display: block; }
|
8
|
+
}
|
9
|
+
|
10
|
+
.tabs {
|
11
|
+
> * { padding: 0.23rem; }
|
12
|
+
margin-bottom: 10px;
|
13
|
+
.grommetux-control-icon { margin-right: 0.5rem; }
|
14
|
+
}
|
15
|
+
|
16
|
+
.toolbar {
|
17
|
+
display: flex;
|
18
|
+
justify-content: space-between;
|
19
|
+
button {
|
20
|
+
min-width: 30px;
|
21
|
+
padding: 0;
|
22
|
+
&.next-month {
|
23
|
+
&:before {
|
24
|
+
content: ">";
|
25
|
+
display: block;
|
26
|
+
}
|
27
|
+
}
|
28
|
+
&.prev-month {
|
29
|
+
&:before {
|
30
|
+
content: "<";
|
31
|
+
display: block;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
|
38
|
+
}
|
@@ -0,0 +1,115 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { observer } from 'mobx-react';
|
4
|
+
import { action } from 'mobx';
|
5
|
+
import cx from 'classnames';
|
6
|
+
import range from 'lodash/range';
|
7
|
+
import chunk from 'lodash/chunk';
|
8
|
+
import Header from 'grommet/components/Header';
|
9
|
+
import Button from 'grommet/components/Button';
|
10
|
+
import Title from 'grommet/components/Title';
|
11
|
+
import LinkPreviousIcon from 'grommet/components/icons/base/LinkPrevious';
|
12
|
+
import LinkNextIcon from 'grommet/components/icons/base/LinkNext';
|
13
|
+
|
14
|
+
const Day = ({ i, w, d, className, ...props }) => {
|
15
|
+
const prevMonth = w === 0 && i > 7;
|
16
|
+
const nextMonth = w >= 4 && i <= 14;
|
17
|
+
const cls = cx(className, {
|
18
|
+
'prev-month': prevMonth,
|
19
|
+
'next-month': nextMonth,
|
20
|
+
'current-day': !prevMonth && !nextMonth && i === d
|
21
|
+
});
|
22
|
+
|
23
|
+
return <td className={cls} {...props}>{i}</td>;
|
24
|
+
};
|
25
|
+
|
26
|
+
|
27
|
+
@observer
|
28
|
+
export default class Calendar extends React.PureComponent {
|
29
|
+
|
30
|
+
static propTypes = {
|
31
|
+
moment: PropTypes.object.isRequired,
|
32
|
+
onChange: PropTypes.func.isRequired,
|
33
|
+
}
|
34
|
+
|
35
|
+
@action.bound
|
36
|
+
selectDate(i, w) {
|
37
|
+
const prevMonth = w === 0 && i > 7;
|
38
|
+
const nextMonth = w >= 4 && i <= 14;
|
39
|
+
const m = this.props.moment;
|
40
|
+
|
41
|
+
m.date(i);
|
42
|
+
if (prevMonth) m.subtract(1, 'month');
|
43
|
+
if (nextMonth) m.add(1, 'month');
|
44
|
+
|
45
|
+
this.props.onChange(m);
|
46
|
+
this.forceUpdate();
|
47
|
+
}
|
48
|
+
|
49
|
+
@action.bound
|
50
|
+
prevMonth(e) {
|
51
|
+
e.preventDefault();
|
52
|
+
this.props.onChange(this.props.moment.subtract(1, 'month'));
|
53
|
+
this.forceUpdate();
|
54
|
+
}
|
55
|
+
|
56
|
+
@action.bound
|
57
|
+
nextMonth(e) {
|
58
|
+
e.preventDefault();
|
59
|
+
this.props.onChange(this.props.moment.add(1, 'month'));
|
60
|
+
this.forceUpdate();
|
61
|
+
}
|
62
|
+
|
63
|
+
render() {
|
64
|
+
const m = this.props.moment;
|
65
|
+
const d = m.date();
|
66
|
+
const d1 = m.clone().subtract(1, 'month').endOf('month').date();
|
67
|
+
const d2 = m.clone().date(1).day();
|
68
|
+
const d3 = m.clone().endOf('month').date();
|
69
|
+
const days = [].concat(
|
70
|
+
range(d1 - d2 + 1, d1 + 1),
|
71
|
+
range(1, d3 + 1),
|
72
|
+
range(1, 42 - d3 - d2 + 1),
|
73
|
+
);
|
74
|
+
const weeks = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
75
|
+
|
76
|
+
return (
|
77
|
+
<div className={cx('calendar', this.props.className)}>
|
78
|
+
|
79
|
+
<Header key='header' justify='between'>
|
80
|
+
<Button className="previous" icon={<LinkPreviousIcon />} onClick={this.prevMonth} />
|
81
|
+
<Title className="title" responsive={false}>
|
82
|
+
{m.format('MMMM YYYY')}
|
83
|
+
</Title>
|
84
|
+
<Button className="next" icon={<LinkNextIcon />} onClick={this.nextMonth} />
|
85
|
+
</Header>
|
86
|
+
|
87
|
+
<div className="grid">
|
88
|
+
<table>
|
89
|
+
<thead>
|
90
|
+
<tr>
|
91
|
+
{weeks.map((w, i) => <td key={i}>{w}</td>)}
|
92
|
+
</tr>
|
93
|
+
</thead>
|
94
|
+
|
95
|
+
<tbody>
|
96
|
+
{chunk(days, 7).map((row, w) =>
|
97
|
+
<tr key={w}>
|
98
|
+
{row.map(i =>
|
99
|
+
<Day
|
100
|
+
key={i}
|
101
|
+
i={i}
|
102
|
+
d={d}
|
103
|
+
w={w}
|
104
|
+
onClick={() => this.selectDate(i, w)}
|
105
|
+
/>,
|
106
|
+
)}
|
107
|
+
</tr>,
|
108
|
+
)}
|
109
|
+
</tbody>
|
110
|
+
</table>
|
111
|
+
</div>
|
112
|
+
</div>
|
113
|
+
);
|
114
|
+
}
|
115
|
+
}
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import PropTypes from 'prop-types';
|
3
|
+
import { action, observable } from 'mobx';
|
4
|
+
import { observer } from 'mobx-react';
|
5
|
+
import CSSClassnames from 'grommet/utils/CSSClassnames';
|
6
|
+
import CalendarIcon from 'grommet/components/icons/base/Calendar';
|
7
|
+
import ClockIcon from 'grommet/components/icons/base/Clock';
|
8
|
+
import Box from 'grommet/components/Box';
|
9
|
+
import cn from 'classnames';
|
10
|
+
|
11
|
+
import Calendar from './calendar';
|
12
|
+
import Time from './time';
|
13
|
+
|
14
|
+
const FORM_FIELD = CSSClassnames.FORM_FIELD;
|
15
|
+
const CLASS_ROOT = 'date-time';
|
16
|
+
|
17
|
+
@observer
|
18
|
+
export default class DateTimeDrop extends React.Component {
|
19
|
+
|
20
|
+
static propTypes = {
|
21
|
+
value: PropTypes.object.isRequired,
|
22
|
+
onChange: PropTypes.func.isRequired,
|
23
|
+
minuteStep: PropTypes.number,
|
24
|
+
}
|
25
|
+
|
26
|
+
static className = 'date-time-drop';
|
27
|
+
|
28
|
+
@observable isShowingTime = false;
|
29
|
+
|
30
|
+
@action.bound
|
31
|
+
toggleTabs() {
|
32
|
+
this.isShowingTime = !this.isShowingTime;
|
33
|
+
}
|
34
|
+
|
35
|
+
render() {
|
36
|
+
return (
|
37
|
+
<Box
|
38
|
+
className={`${this.constructor.className} component date-time-drop`}
|
39
|
+
>
|
40
|
+
<Box
|
41
|
+
direction='row'
|
42
|
+
className="tabs"
|
43
|
+
>
|
44
|
+
<Box
|
45
|
+
onClick={this.isShowingTime ? this.toggleTabs : null}
|
46
|
+
colorIndex={this.isShowingTime ? '' : 'neutral-1'}
|
47
|
+
align="center" justify="center" flex direction='row' className="calendar"
|
48
|
+
>
|
49
|
+
<CalendarIcon />
|
50
|
+
Day
|
51
|
+
</Box>
|
52
|
+
<Box
|
53
|
+
onClick={this.isShowingTime ? null : this.toggleTabs}
|
54
|
+
colorIndex={this.isShowingTime ? 'neutral-1' : ''}
|
55
|
+
align="center" justify="center" flex direction='row' className="time"
|
56
|
+
>
|
57
|
+
<ClockIcon />
|
58
|
+
Time
|
59
|
+
</Box>
|
60
|
+
</Box>
|
61
|
+
<div className={cn('tab', { active: !this.isShowingTime })}>
|
62
|
+
<Calendar
|
63
|
+
moment={this.props.value}
|
64
|
+
onChange={this.props.onChange}
|
65
|
+
/>
|
66
|
+
</div>
|
67
|
+
<div className={cn('tab', { active: this.isShowingTime })}>
|
68
|
+
<Time
|
69
|
+
moment={this.props.value}
|
70
|
+
onChange={this.props.onChange}
|
71
|
+
/>
|
72
|
+
</div>
|
73
|
+
</Box>
|
74
|
+
);
|
75
|
+
}
|
76
|
+
|
77
|
+
}
|