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.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +2 -3
  4. data/Gemfile +1 -1
  5. data/client/hippo/__mocks__/config.js +4 -4
  6. data/client/hippo/boot.jsx +1 -0
  7. data/client/hippo/components/asset.jsx +4 -4
  8. data/client/hippo/components/date-time.jsx +169 -0
  9. data/client/hippo/components/date-time.scss +38 -0
  10. data/client/hippo/components/date-time/calendar.jsx +115 -0
  11. data/client/hippo/components/date-time/date-time-drop.jsx +77 -0
  12. data/client/hippo/components/date-time/date-time.scss +157 -0
  13. data/client/hippo/components/date-time/time.jsx +120 -0
  14. data/client/hippo/components/form/fields/date-wrapper.jsx +4 -3
  15. data/client/hippo/components/form/model.js +0 -2
  16. data/client/hippo/components/text-editor.jsx +85 -0
  17. data/client/hippo/components/text-editor/display-modes/Button.jsx +17 -0
  18. data/client/hippo/components/text-editor/display-modes/SaveState.jsx +17 -0
  19. data/client/hippo/components/text-editor/display-modes/ToggleEdit.jsx +22 -0
  20. data/client/hippo/components/text-editor/display-modes/ToggleInsert.jsx +21 -0
  21. data/client/hippo/components/text-editor/display-modes/ToggleLayout.jsx +21 -0
  22. data/client/hippo/components/text-editor/display-modes/TogglePreview.jsx +21 -0
  23. data/client/hippo/components/text-editor/display-modes/ToggleResize.jsx +21 -0
  24. data/client/hippo/components/text-editor/display-modes/index.css +0 -0
  25. data/client/hippo/components/text-editor/display-modes/index.js +30 -0
  26. data/client/hippo/components/text-editor/image-plugin/Component/Display/index.js +80 -0
  27. data/client/hippo/components/text-editor/image-plugin/Component/Form/index.js +40 -0
  28. data/client/hippo/components/text-editor/image-plugin/Component/index.js +16 -0
  29. data/client/hippo/components/text-editor/image-plugin/Component/index.scss +0 -0
  30. data/client/hippo/components/text-editor/image-plugin/index.js +32 -0
  31. data/client/hippo/components/text-editor/image-plugin/index.scss +25 -0
  32. data/client/hippo/components/text-editor/plugins.js +22 -0
  33. data/client/hippo/components/text-editor/renderer.jsx +37 -0
  34. data/client/hippo/components/text-editor/text-editor.scss +49 -0
  35. data/client/hippo/extensions/base.js +5 -2
  36. data/client/hippo/extensions/hippo.js +5 -2
  37. data/client/hippo/extensions/index.js +9 -3
  38. data/client/hippo/lib/__mocks__/request-assets.js +2 -2
  39. data/client/hippo/lib/bootstrap.js +0 -1
  40. data/client/hippo/lib/smooth-scroll.js +0 -1
  41. data/client/hippo/lib/util.js +4 -4
  42. data/client/hippo/models/asset.js +43 -23
  43. data/client/hippo/models/base.js +1 -2
  44. data/client/hippo/models/config.js +0 -1
  45. data/client/hippo/models/decorators.js +3 -3
  46. data/client/hippo/models/pub_sub.js +2 -5
  47. data/client/hippo/models/pub_sub/channel.js +0 -1
  48. data/client/hippo/models/query.js +0 -1
  49. data/client/hippo/models/query/array-result.js +0 -1
  50. data/client/hippo/models/query/clause.js +0 -1
  51. data/client/hippo/models/query/field.js +0 -1
  52. data/client/hippo/models/query/info.js +0 -3
  53. data/client/hippo/models/query/operator.js +0 -2
  54. data/client/hippo/models/query/result.js +0 -1
  55. data/client/hippo/models/sync.js +1 -1
  56. data/client/hippo/models/system-setting.js +0 -2
  57. data/client/hippo/models/tenant.js +0 -1
  58. data/client/hippo/screens/definition.js +0 -2
  59. data/client/hippo/screens/group.js +0 -2
  60. data/client/hippo/screens/instance.js +0 -3
  61. data/client/hippo/screens/system-settings/mailer-config.jsx +0 -3
  62. data/client/hippo/styles/global.scss +3 -0
  63. data/client/hippo/testing/mocks/fetch.js +6 -6
  64. data/client/hippo/user.js +4 -4
  65. data/client/hippo/workspace/index.jsx +12 -5
  66. data/client/hippo/workspace/root-view.jsx +10 -0
  67. data/command-reference-files/initial/.gitignore +1 -0
  68. data/command-reference-files/initial/Gemfile +1 -1
  69. data/command-reference-files/initial/client/appy-app/extension.js +4 -0
  70. data/command-reference-files/initial/config/webpack.config.js +25 -23
  71. data/config/routes.rb +4 -1
  72. data/config/webpack.config.js +1 -2
  73. data/hippo-fw.gemspec +4 -2
  74. data/lib/hippo.rb +0 -1
  75. data/lib/hippo/api/handlers/asset.rb +9 -0
  76. data/lib/hippo/api/updates.rb +2 -2
  77. data/lib/hippo/configuration.rb +0 -4
  78. data/lib/hippo/db.rb +2 -2
  79. data/lib/hippo/{rails.rb → db/fake_rails.rb} +0 -0
  80. data/lib/hippo/extension.rb +1 -2
  81. data/lib/hippo/mailer.rb +1 -0
  82. data/lib/hippo/spec_helper.rb +1 -0
  83. data/lib/hippo/version.rb +1 -1
  84. data/package-lock.json +626 -68
  85. data/package.json +14 -13
  86. data/spec/client/access/login-dialog.spec.jsx +1 -0
  87. data/spec/client/components/asset.spec.jsx +1 -2
  88. data/spec/client/components/date-time.spec.jsx +20 -0
  89. data/spec/client/extension/base.spec.js +0 -2
  90. data/spec/client/models/base.spec.js +4 -4
  91. data/spec/client/models/query.spec.js +2 -2
  92. data/spec/client/models/sync.spec.js +1 -1
  93. data/spec/client/screens/system-settings.spec.jsx +2 -1
  94. data/spec/client/setup.js +3 -0
  95. data/spec/client/test-models.js +0 -2
  96. data/spec/server/api/tenant_change_spec.rb +1 -1
  97. data/spec/server/api/tenant_isolation_spec.rb +6 -3
  98. data/spec/server/concerns/api_path_spec.rb +2 -2
  99. data/templates/.gitignore +1 -0
  100. data/templates/client/extension.js +4 -0
  101. data/templates/config/webpack.config.js +25 -23
  102. metadata +48 -12
  103. data/client/hippo/lib/pub_sub.js +0 -34
  104. data/client/hippo/react/viewport-root.jsx +0 -44
  105. data/spec/client/components/__snapshots__/asset.spec.jsx.snap +0 -48
  106. data/spec/client/screens/__snapshots__/system-settings.spec.jsx.snap +0 -443
  107. data/templates/gitignore +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 66252f602687cd15c345fe869696110e2b106c45
4
- data.tar.gz: 6e63cb8121ff3b3a7b5d4186306755648397342f
3
+ metadata.gz: 8a86a77e5eb0041425dcc05d9b6d8efb2c304a99
4
+ data.tar.gz: df658e7e5eb832884c88606575617b4247aa4e89
5
5
  SHA512:
6
- metadata.gz: 166aadffc4273278372aad7b702ddb0baac76f106afa7482be135aef026c5c0f3071ae6fa7dbffa5b3ff9667b81620b43356b64615a393d9d328156ae22e2a8a
7
- data.tar.gz: f9b71478268619454b76bd254e45c5947274f70228b355fc39f8f66cf752fb86c19e3eb3501ea63ac7fa5bc74e0d4c803ae6e76cfdf236d8ac7ceab4c4ceb957
6
+ metadata.gz: 3df81f86cd6613d3ad71237534c7c997bac329470697ab6a83af8182e155059d1ee99d0e54298d45352a81ebfc137793560116af7271537c87cc2b62dba3e388
7
+ data.tar.gz: 566662660f26bf8cbb0dd4c31a4afdab9d1da1b53ca380bdeff349a9e7e7f16dab0cc18455f07f85a24c9e7c190c5b773a8a1f8b2f956d3bce701a174d9060ba
data/.gitignore CHANGED
@@ -7,6 +7,7 @@
7
7
  .yardoc
8
8
  Gemfile.lock
9
9
  InstalledFiles
10
+ config/secrets.yml
10
11
  coverage
11
12
  doc/
12
13
  log/
@@ -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="6.9.2"
20
+ - TRAVIS_NODE_VERSION="7"
21
21
  before_install:
22
22
  - nvm install $TRAVIS_NODE_VERSION
23
- - npm install yarn
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 config = jest.genMockFromModule('../models/config');
9
- //
10
- // config.bootstrapUserData = jest.fn();
11
- // config.reset = jest.fn();
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
  });
@@ -4,6 +4,7 @@ import whenDomReady from 'when-dom-ready';
4
4
  import { delay } from 'lodash';
5
5
  import { AppContainer } from 'react-hot-loader';
6
6
  import { onBoot } from './models/pub_sub';
7
+ import './extensions/hippo';
7
8
 
8
9
  const Workspace = require('hippo/workspace').default;
9
10
 
@@ -22,9 +22,9 @@ export default class Asset extends React.PureComponent {
22
22
  }
23
23
 
24
24
  static propTypes = {
25
- model: PropTypes.instanceOf(BaseModel).isRequired,
26
- name: PropTypes.string.isRequired,
27
- label: PropTypes.string,
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.file = files[0];
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
+ }