lanes 0.5.6 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (162) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -2
  3. data/client/lanes/Config.coffee +6 -5
  4. data/client/lanes/access/LoginDialog.cjsx +4 -2
  5. data/client/lanes/access/Roles.coffee +3 -0
  6. data/client/lanes/access/screens/user-management/Editor.cjsx +1 -1
  7. data/client/lanes/components/grid/Body.cjsx +4 -3
  8. data/client/lanes/components/grid/Grid.cjsx +4 -3
  9. data/client/lanes/components/grid/Header.cjsx +1 -1
  10. data/client/lanes/components/grid/PopOverMixin.cjsx +6 -6
  11. data/client/lanes/components/grid/Selections.cjsx +16 -6
  12. data/client/lanes/components/grid/Toolbar.cjsx +1 -1
  13. data/client/lanes/components/grid/styles.scss +21 -5
  14. data/client/lanes/components/modal/Modal.cjsx +18 -9
  15. data/client/lanes/components/record-finder/Clause.cjsx +1 -2
  16. data/client/lanes/components/record-finder/Dialog.cjsx +11 -3
  17. data/client/lanes/components/record-finder/RecordFinder.cjsx +14 -7
  18. data/client/lanes/components/record-finder/styles.scss +1 -0
  19. data/client/lanes/components/select-field/SelectField.cjsx +36 -10
  20. data/client/lanes/components/select-field/styles.scss +7 -0
  21. data/client/lanes/components/shared/Checkbox.cjsx +34 -0
  22. data/client/lanes/components/shared/DateTime.cjsx +3 -2
  23. data/client/lanes/components/shared/ErrorDisplay.cjsx +1 -1
  24. data/client/lanes/components/shared/FieldMixin.cjsx +26 -15
  25. data/client/lanes/components/shared/FieldSet.cjsx +1 -1
  26. data/client/lanes/components/shared/FieldWrapper.cjsx +2 -2
  27. data/client/lanes/components/shared/FormGroup.cjsx +2 -2
  28. data/client/lanes/components/shared/Icon.cjsx +31 -4
  29. data/client/lanes/components/shared/IconButton.cjsx +8 -0
  30. data/client/lanes/components/shared/ImageAsset.cjsx +8 -5
  31. data/client/lanes/components/shared/IndeterminateCheckbox.cjsx +19 -0
  32. data/client/lanes/components/shared/InputFieldMixin.cjsx +6 -0
  33. data/client/lanes/components/shared/JobProgress.cjsx +4 -3
  34. data/client/lanes/components/shared/NetworkActivityOverlay.cjsx +1 -1
  35. data/client/lanes/components/shared/ScreenWrapper.cjsx +1 -1
  36. data/client/lanes/components/shared/ToggleField.cjsx +2 -1
  37. data/client/lanes/components/shared/Tooltip.cjsx +10 -2
  38. data/client/lanes/components/shared/fields.scss +7 -2
  39. data/client/lanes/components/toolbar/RemoteChangeSets.cjsx +10 -7
  40. data/client/lanes/components/toolbar/SaveButton.cjsx +5 -4
  41. data/client/lanes/components/toolbar/Toolbar.cjsx +18 -19
  42. data/client/lanes/components/toolbar/changes-notification.scss +3 -1
  43. data/client/lanes/components/toolbar/styles.scss +6 -3
  44. data/client/lanes/lib/HotReload.coffee +1 -1
  45. data/client/lanes/lib/all.js +1 -1
  46. data/client/lanes/lib/dom.coffee +14 -1
  47. data/client/lanes/lib/format.coffee +3 -0
  48. data/client/lanes/lib/loader.coffee +0 -2
  49. data/client/lanes/lib/{dom-polyfills.coffee → polyfills.coffee} +3 -0
  50. data/client/lanes/lib/utilFunctions.coffee +5 -7
  51. data/client/lanes/models/Asset.coffee +33 -20
  52. data/client/lanes/models/AssociationMap.coffee +5 -6
  53. data/client/lanes/models/Base.coffee +5 -2
  54. data/client/lanes/models/Collection.coffee +23 -2
  55. data/client/lanes/models/PubSub.coffee +51 -13
  56. data/client/lanes/models/Query.coffee +53 -42
  57. data/client/lanes/models/State.coffee +5 -4
  58. data/client/lanes/models/Sync.coffee +5 -3
  59. data/client/lanes/models/index.js +1 -1
  60. data/client/lanes/models/mixins/TrackCollectionRemovals.coffee +17 -0
  61. data/client/lanes/models/query/ArrayResult.coffee +16 -17
  62. data/client/lanes/models/query/CollectionResult.coffee +4 -4
  63. data/client/lanes/react/Component.coffee +14 -13
  64. data/client/lanes/react/Root.cjsx +1 -1
  65. data/client/lanes/react/Screen.coffee +1 -0
  66. data/client/lanes/react/Viewport.coffee +52 -16
  67. data/client/lanes/react/mixins/Access.coffee +5 -0
  68. data/client/lanes/react/mixins/Data.coffee +52 -144
  69. data/client/lanes/react/mixins/MonitorSize.coffee +1 -1
  70. data/client/lanes/react/mixins/ReadEditingState.coffee +3 -0
  71. data/client/lanes/screens/Commands.coffee +1 -1
  72. data/client/lanes/screens/CommonComponents.cjsx +2 -2
  73. data/client/lanes/screens/Definitions.coffee +3 -1
  74. data/client/lanes/screens/SystemSettings.cjsx +13 -18
  75. data/client/lanes/screens/UserPreferences.cjsx +1 -1
  76. data/client/lanes/styles/fonts.scss +2 -3
  77. data/client/lanes/styles/global/styles.scss +2 -1
  78. data/client/lanes/testing/TestObjects.coffee +6 -2
  79. data/client/lanes/vendor/action_cable.js +590 -0
  80. data/client/lanes/vendor/development/calendar.js +56 -56
  81. data/client/lanes/vendor/development/commons.js +7819 -6690
  82. data/client/lanes/vendor/development/data.js +1877 -1455
  83. data/client/lanes/vendor/development/helpers.js +39 -82
  84. data/client/lanes/vendor/development/toggle.js +20 -20
  85. data/client/lanes/vendor/development/ui.js +14629 -14261
  86. data/client/lanes/vendor/development/widgets.js +3146 -2173
  87. data/client/lanes/vendor/index.js +1 -2
  88. data/client/lanes/vendor/production/calendar.js +56 -56
  89. data/client/lanes/vendor/production/commons.js +6352 -6185
  90. data/client/lanes/vendor/production/data.js +1871 -1456
  91. data/client/lanes/vendor/production/toggle.js +20 -20
  92. data/client/lanes/vendor/production/ui.js +14694 -14286
  93. data/client/lanes/vendor/production/widgets.js +3139 -2166
  94. data/client/lanes/vendor/standalone/index.js +5666 -4586
  95. data/client/lanes/vendor/styles/widgets.scss +5 -5
  96. data/client/lanes/workspace/Layout.cjsx +1 -10
  97. data/client/lanes/workspace/Navbar.cjsx +8 -13
  98. data/client/lanes/workspace/ScreenView.cjsx +3 -4
  99. data/client/lanes/workspace/ScreensMenu.cjsx +8 -19
  100. data/client/lanes/workspace/Tabs.cjsx +6 -14
  101. data/db/migrate/02_create_assets.rb +1 -3
  102. data/lanes.gemspec +16 -11
  103. data/lib/lanes/access/test_fixture_extensions.rb +6 -10
  104. data/lib/lanes/access/track_modifications.rb +24 -0
  105. data/lib/lanes/api/cable.rb +49 -0
  106. data/lib/lanes/api/controller_base.rb +52 -9
  107. data/lib/lanes/api/default_routes.rb +9 -0
  108. data/lib/lanes/api/generic_controller.rb +2 -9
  109. data/lib/lanes/api/handlers/asset.rb +5 -6
  110. data/lib/lanes/api/helper_methods.rb +3 -2
  111. data/lib/lanes/api/javascript_processor.rb +6 -5
  112. data/lib/lanes/api/pub_sub.rb +14 -32
  113. data/lib/lanes/api/request_wrapper.rb +1 -1
  114. data/lib/lanes/api/root.rb +4 -7
  115. data/lib/lanes/api/routing.rb +3 -3
  116. data/lib/lanes/api/sprockets_extension.rb +1 -1
  117. data/lib/lanes/api.rb +4 -0
  118. data/lib/lanes/asset.rb +25 -25
  119. data/lib/lanes/concerns/asset_uploader.rb +25 -47
  120. data/lib/lanes/concerns/export_scope.rb +5 -7
  121. data/lib/lanes/concerns/queries.rb +7 -3
  122. data/lib/lanes/concerns/set_attribute_data.rb +12 -6
  123. data/lib/lanes/configuration.rb +4 -7
  124. data/lib/lanes/db.rb +3 -1
  125. data/lib/lanes/guard_tasks.rb +2 -1
  126. data/lib/lanes/hot_reload_plugin.rb +2 -1
  127. data/lib/lanes/job.rb +0 -1
  128. data/lib/lanes/logger.rb +3 -3
  129. data/lib/lanes/model.rb +0 -3
  130. data/lib/lanes/spec_helper.rb +1 -1
  131. data/lib/lanes/system_settings.rb +8 -14
  132. data/lib/lanes/version.rb +1 -1
  133. data/npm-build/data.js +1 -0
  134. data/npm-build/package.json +21 -19
  135. data/npm-build/ui.js +3 -0
  136. data/npm-build/update-dayz +2 -2
  137. data/npm-build/update-model-bindings.js +5 -0
  138. data/spec/command-reference-files/initial/Gemfile +1 -1
  139. data/spec/command-reference-files/initial/config/database.yml +1 -0
  140. data/spec/command-reference-files/initial/config/lanes.rb +3 -3
  141. data/spec/command-reference-files/screen/spec/appy-app/screens/ready-set-go/ReadySetGoSpec.coffee +1 -1
  142. data/spec/lanes/components/grid/GridSpec.coffee +2 -2
  143. data/spec/lanes/components/grid/PopoverEditorSpec.coffee +11 -12
  144. data/spec/lanes/components/select-field/SelectFieldSpec.coffee +6 -4
  145. data/spec/lanes/components/shared/NetworkActivityOverlaySpec.coffee +1 -1
  146. data/spec/lanes/models/PubSubSpec.coffee +6 -8
  147. data/spec/lanes/models/QuerySpec.coffee +19 -0
  148. data/spec/lanes/react/mixins/DataSpec.coffee +18 -16
  149. data/spec/server/api/coffeescript_processor_spec.rb +1 -1
  150. data/spec/server/api/controller_base_spec.rb +77 -0
  151. data/spec/server/api/pub_sub_spec.rb +9 -0
  152. data/spec/server/asset_spec.rb +23 -18
  153. data/spec/server/concerns/export_scope_spec.rb +2 -1
  154. data/spec/server/concerns/exported_limits_spec.rb +14 -9
  155. data/spec/server/concerns/set_attribute_data_spec.rb +17 -0
  156. data/spec/server/spec_helper.rb +29 -11
  157. data/templates/config/database.yml +1 -0
  158. data/templates/spec/client/Screen.coffee +1 -1
  159. data/views/specs.erb +4 -1
  160. metadata +138 -89
  161. data/client/lanes/vendor/message-bus-ajax.js +0 -44
  162. data/client/lanes/vendor/message-bus.js +0 -414
@@ -3,17 +3,17 @@ Lanes.Components.Form || = {}
3
3
 
4
4
  Lanes.Components.Form.FieldMixin = {
5
5
 
6
- bindDataEvents: ->
6
+ registerForPubSub: false
7
+
8
+ bindEvents: ->
7
9
  model: "change:#{@props.name} remote-update:#{@props.name} invalid-fields invalid-field:#{@getInvalidFieldName()}"
8
10
 
9
11
  mixins: [
10
12
  Lanes.React.Mixins.Access
11
13
  Lanes.React.Mixins.ReadEditingState
12
-
13
14
  Lanes.React.Mixins.FieldErrors
14
15
  ]
15
16
 
16
- pubsub: false
17
17
  propTypes:
18
18
  model: Lanes.PropTypes.State.isRequired
19
19
  name: React.PropTypes.string.isRequired
@@ -42,11 +42,11 @@ Lanes.Components.Form.FieldMixin = {
42
42
  _unsetChangeSet: ->
43
43
  @setState(displayChangeset: false, pendingChangeSetDelay: null)
44
44
 
45
- setDataState: (state, evname) ->
45
+ setModelState: ->
46
46
  displayChangeset = @model.updatingFromChangeset and @model.changedAttributes()[@props.name]
47
47
  if displayChangeset and not @state.pendingChangeSetDelay
48
48
  pendingChangeSetDelay = _.delay(@_unsetChangeSet, 2000)
49
- @setState(_.extend( state, {pendingChangeSetDelay, displayChangeset}))
49
+ @setState({pendingChangeSetDelay, displayChangeset})
50
50
 
51
51
  _fieldMixinGetLabelValue: ->
52
52
  @getLabelValue?() ||
@@ -69,7 +69,11 @@ Lanes.Components.Form.FieldMixin = {
69
69
 
70
70
  _fieldMixinRenderFormGroup: (child, props, options) ->
71
71
  if (invalidMsg = @fieldInvalidValueMessage())
72
- msg = <BS.HelpBlock>{invalidMsg}</BS.HelpBlock>
72
+ feedback = [
73
+ <BS.FormControl.Feedback key="feedback" />
74
+ <BS.HelpBlock key="help">{invalidMsg}</BS.HelpBlock>
75
+ ]
76
+
73
77
  unless @props.unlabeled
74
78
  label =
75
79
  <BS.ControlLabel>
@@ -80,8 +84,7 @@ Lanes.Components.Form.FieldMixin = {
80
84
  <BS.FormGroup validationState={options.validationState}>
81
85
  {label}
82
86
  {child}
83
- <BS.FormControl.Feedback />
84
- {msg}
87
+ {feedback}
85
88
  </BS.FormGroup>
86
89
  </BS.Col>
87
90
 
@@ -95,13 +98,14 @@ Lanes.Components.Form.FieldMixin = {
95
98
  _fieldMixinRenderDisplay: (props) ->
96
99
  value = @fieldMixinGetValue()
97
100
  value = value.toString() if _.isObject(value)
98
-
99
- <BS.FormControl.Static {...props}>
101
+ <BS.FormControl.Static>
100
102
  {value}
101
103
  </BS.FormControl.Static>
102
104
 
105
+
103
106
  _fieldMixinRenderNone: (props) ->
104
- <span {...props} />
107
+ clean = LC.Form.FieldMixin.statics.cleanSizeProps(props)
108
+ <span {...clean} />
105
109
 
106
110
  renderType: ->
107
111
  if @isEditingRecord()
@@ -117,11 +121,18 @@ Lanes.Components.Form.FieldMixin = {
117
121
  else
118
122
  ['none', 'None']
119
123
  statics:
120
- cleanColumnProps: (props) ->
121
- _.omit props, 'model', 'label', 'name', 'unlabeled', 'fieldOnly', 'placeholder', 'type'
124
+ cleanSizeProps: (props, comp = {}) ->
125
+ Lanes.u.cleanBsSizes( LC.Form.FieldMixin.statics.cleanColumnProps(props, comp) )
126
+
127
+ cleanColumnProps: (props, comp, xtra...) ->
128
+ _.omit( props, _.keys(comp.constructor.propTypes).concat([
129
+ 'model', 'label', 'name', 'unlabeled', 'fieldOnly', 'placeholder',
130
+ 'commands', 'query', 'editOnly', 'syncOptions', 'labelField', 'type',
131
+ 'selectField', 'idField', 'queryModel', 'choices', 'align'
132
+ ], xtra))
122
133
 
123
134
  renderEmptyColumn: (props = @props) ->
124
- props = @cleanColumnProps(props)
135
+ props = @cleanColumnProps(props, @)
125
136
  <BS.Col {...props} />
126
137
 
127
138
  render: ->
@@ -130,7 +141,7 @@ Lanes.Components.Form.FieldMixin = {
130
141
 
131
142
  hasError = @isFieldValueInvalid()
132
143
  options.validationState = 'warning' if hasError
133
- props = LC.Form.FieldMixin.statics.cleanColumnProps(@props)
144
+ props = LC.Form.FieldMixin.statics.cleanColumnProps(@props, @)
134
145
 
135
146
  props.className = _.classnames(
136
147
  _.result(this, 'fieldClassName'),
@@ -17,7 +17,7 @@ class Lanes.Components.FieldSet extends Lanes.React.Component
17
17
  @setState(expanded: not @state.expanded)
18
18
 
19
19
  render: ->
20
- colProps = _.omit(@props, 'name')
20
+ colProps = _.omit(@props, 'name', 'expanded')
21
21
  <BS.Col {...colProps}>
22
22
  <fieldset className={
23
23
  _.classnames("collapsible", @props.className, @state.icon
@@ -20,7 +20,6 @@ class Lanes.Components.FieldWrapper extends Lanes.React.BaseComponent
20
20
  {@props.label}
21
21
  </BS.ControlLabel>
22
22
 
23
-
24
23
  renderType: ->
25
24
  if @isEditingRecord()
26
25
  if @hasWriteAccess()
@@ -37,8 +36,9 @@ class Lanes.Components.FieldWrapper extends Lanes.React.BaseComponent
37
36
 
38
37
  render: ->
39
38
  [type, child] = @renderType()
39
+
40
40
  props = _.omit(@props,
41
- 'value', 'model', 'value', 'label', 'name'
41
+ 'value', 'model', 'value', 'label', 'name', 'displayComponent'
42
42
  )
43
43
  unless child
44
44
  Comp = @props.displayComponent
@@ -10,11 +10,11 @@ class Lanes.Components.FormGroup extends Lanes.React.Component
10
10
  'right', 'left', 'center'
11
11
  ])
12
12
 
13
- bindDataEvents: ->
13
+ bindEvents: ->
14
14
  model: "invalid-fields invalid-field:#{@getInvalidFieldName()}"
15
15
 
16
16
  render: ->
17
- className = _.classnames(className, @props.className, "field"
17
+ className = _.classnames(className, @props.className, "lanes-field"
18
18
  editing: @props.editing
19
19
  "align-#{@props.align}": @props.align
20
20
  display: false == @props.editing
@@ -1,21 +1,48 @@
1
+ DEFAULT_TOOLTIP_PROPS = { placement: 'top', trigger: 'click' }
2
+
1
3
  class Lanes.Components.Icon extends Lanes.React.BaseComponent
2
4
 
3
5
  propTypes:
4
- type: React.PropTypes.string.isRequired
5
- animated: React.PropTypes.bool
6
+ type: React.PropTypes.string.isRequired
7
+ animated: React.PropTypes.bool
8
+ spinner: React.PropTypes.bool
9
+ className: React.PropTypes.string
10
+ tooltip: React.PropTypes.oneOfType([
11
+ React.PropTypes.string, React.PropTypes.element
12
+ ])
13
+ tooltipProps: React.PropTypes.object
6
14
 
7
- render: ->
15
+ getInitialState: ->
16
+ uniqueId: _.uniqueId('icon-tooltip-')
17
+
18
+ getDefaultProps: ->
19
+ tooltipProps: DEFAULT_TOOLTIP_PROPS
8
20
 
21
+ render: ->
9
22
  classes = _.classnames 'icon', "icon-#{@props.type}", @props.className,
10
23
  'non-printable': @props.noPrint,
11
24
  'with-action' : @props.onClick,
12
25
  "icon-#{@props.size}" : @props.size,
13
26
  'icon-pulse' : @props.animated
27
+ 'icon-spin' : @props.spin or @props.type is 'spinner'
14
28
  'flush' : @props.flush
15
29
  'icon-lg' : @props['lg']
16
30
  'icon-2x' : @props['2x']
17
31
  'icon-3x' : @props['3x']
18
32
  'icon-4x' : @props['4x']
19
33
  'icon-5x' : @props['5x']
34
+ 'clickable' : @props.clickable or (@props.tooltip and @props.tooltipProps.trigger is 'click')
35
+
36
+ icon =
37
+ <i style={@props.style} className={classes} />
20
38
 
21
- <i {...@props} style={@props.style} className={classes} />
39
+ if @props.tooltip
40
+ props = _.extend({}, DEFAULT_TOOLTIP_PROPS, @props.tooltipProps)
41
+ <LC.Tooltip id={@state.uniqueId}
42
+ content={@props.tooltip}
43
+ {...props}
44
+ >
45
+ {icon}
46
+ </LC.Tooltip>
47
+ else
48
+ icon
@@ -0,0 +1,8 @@
1
+ class Lanes.Components.IconButton extends Lanes.React.BaseComponent
2
+
3
+ render: ->
4
+ buttonProps = _.omit(@props, 'icon', 'iconProps')
5
+ buttonProps.className = _.classnames(buttonProps.className, 'flush')
6
+ <BS.Button {...buttonProps}>
7
+ <LC.Icon type={@props.icon} lg {...@props.iconProps} />
8
+ </BS.Button>
@@ -7,12 +7,12 @@ class Lanes.Components.ImageAsset extends Lanes.React.Component
7
7
  'thumb', 'medium', 'original'
8
8
  ]).isRequired
9
9
 
10
- dataObjects:
10
+ modelBindings:
11
11
  asset: -> @props.model[@props.name]
12
12
 
13
13
  listenNetworkEvents: true
14
14
 
15
- bindDataEvents: ->
15
+ bindEvents: ->
16
16
  model: "change:#{@props.name} change:#{@props.name}_data"
17
17
 
18
18
  handleImageChange: (ev) ->
@@ -30,7 +30,7 @@ class Lanes.Components.ImageAsset extends Lanes.React.Component
30
30
  className = _.classnames('image-asset', @props.className, {
31
31
  'with-image': @asset.hasImage
32
32
  })
33
-
33
+ console.log @asset.file_data
34
34
  <LC.FieldWrapper
35
35
  {...@props}
36
36
  className={className}
@@ -39,8 +39,11 @@ class Lanes.Components.ImageAsset extends Lanes.React.Component
39
39
  <Component />
40
40
  <form>
41
41
  <label className="selector">
42
- <span>{if @asset.hasImage then 'Update' else 'Choose'}</span>
43
- <input id='file' className="file" type="file" onChange={@handleImageChange} />
42
+ <span>
43
+ {if @asset.hasImage then 'Update' else 'Choose'}
44
+ </span>
45
+ <input id='file' className="file" type="file"
46
+ onChange={@handleImageChange} />
44
47
  </label>
45
48
  </form>
46
49
  </LC.FieldWrapper>
@@ -0,0 +1,19 @@
1
+ class Lanes.Components.IndeterminateCheckbox extends Lanes.React.Component
2
+
3
+ componentDidMount: -> @updateIndeterminate()
4
+ componentDidUpdate: -> @updateIndeterminate()
5
+
6
+ updateIndeterminate: ->
7
+ _.dom(@).el.indeterminate =
8
+ @props.checked isnt true and @props.checked isnt false
9
+
10
+ handleCheckboxChange: (ev) ->
11
+ if ev.target.checked
12
+ @fieldMixinSetValue( new FakeInputEvent(@props.value) )
13
+
14
+ render: ->
15
+ <input type="checkbox"
16
+ {...@props}
17
+ checked={@props.checked}
18
+ onChange={@props.onChange}
19
+ />
@@ -7,6 +7,10 @@ Lanes.Components.Form.InputFieldMixin =
7
7
  propTypes:
8
8
  onlyNumeric: React.PropTypes.bool
9
9
  selctOnFocus: React.PropTypes.bool
10
+ onEnter: React.PropTypes.func
11
+
12
+ focus: ->
13
+ _.dom(@, 'input').el.focus()
10
14
 
11
15
  getDefaultProps: ->
12
16
  type: 'text'
@@ -33,4 +37,6 @@ Lanes.Components.Form.InputFieldMixin =
33
37
  if @props.onEnter then handlers.onKeyDown = @handleKeyDown
34
38
  if @props.selectOnFocus then handlers.onFocus = @selectOnFocus
35
39
 
40
+ props = Lanes.u.cleanBsSizes(props)
41
+
36
42
  @renderInputField(props, handlers)
@@ -1,13 +1,14 @@
1
1
  class Lanes.Components.JobStatus extends Lanes.React.Component
2
2
 
3
+ registerForPubSub: true
4
+ listenNetworkEvents: true
5
+
3
6
  propTypes:
4
7
  job: Lanes.PropTypes.State
5
8
  onlyExecuting: React.PropTypes.bool
6
9
  message: React.PropTypes.string
7
10
 
8
- pubsub: true
9
- listenNetworkEvents: true
10
- dataObjects: { job: 'props' }
11
+ modelBindings: { job: 'props' }
11
12
  statusMessage: ->
12
13
  if _.isEmpty(@job.stepsCompleted) then '' else
13
14
  'Completed: ' + _.toSentence(@job.stepsCompleted)
@@ -25,7 +25,7 @@ class Lanes.Components.NetworkActivityOverlay extends Lanes.React.Component
25
25
 
26
26
  listenNetworkEvents: true
27
27
 
28
- setDataState: (state) ->
28
+ setNetworkActivity: (state) ->
29
29
  if state.hasError or state.isRequesting
30
30
  @installRemoval(state)
31
31
  else if not @state.hasError
@@ -5,7 +5,7 @@ class Lanes.Components.ScreenWrapper extends Lanes.React.Component
5
5
 
6
6
  render: ->
7
7
  classes = _.classnames(
8
- 'screen-wrapper', @props.identifier,
8
+ 'screen-wrapper', @props.identifier, @props.className
9
9
  'flex-vertically': @props.flexVertical
10
10
  )
11
11
  <div className={classes} style={@props.style}>
@@ -8,6 +8,7 @@ class Lanes.Components.ToggleField extends Lanes.React.Component
8
8
  null
9
9
 
10
10
  renderDisplay: (props) ->
11
+ props = Lanes.u.cleanBsSizes(props)
11
12
  <Lanes.Vendor.ReactToggle
12
13
  {...props}
13
14
  checked={!!@props.model[@props.name]}
@@ -15,7 +16,7 @@ class Lanes.Components.ToggleField extends Lanes.React.Component
15
16
  />
16
17
 
17
18
  renderEdit: (props) ->
18
-
19
+ props = Lanes.u.cleanBsSizes(props)
19
20
  <Lanes.Vendor.ReactToggle
20
21
  {...props}
21
22
  onChange={@handleToggleChange}
@@ -1,10 +1,18 @@
1
1
  class Lanes.Components.Tooltip extends Lanes.React.Component
2
2
 
3
- TTProps: ['id', 'placement', 'positionLeft', 'positionTop', 'arrowOffsetLeft', 'arrowOffsetTop']
3
+ TTProps: [
4
+ 'id', 'placement', 'positionLeft', 'positionTop',
5
+ 'arrowOffsetLeft', 'arrowOffsetTop'
6
+ ]
4
7
 
5
8
  render: ->
6
9
  ttprops = _.pick(@props, @TTProps...)
7
10
  tooltip = <BS.Tooltip {...ttprops}>{@props.content}</BS.Tooltip>
8
- <BS.OverlayTrigger overlay={tooltip} placement='left' container={@context.viewport.lanes}>
11
+ <BS.OverlayTrigger
12
+ overlay={tooltip}
13
+ placement='left'
14
+ container={@context.viewport.lanes}
15
+ {...@props}
16
+ >
9
17
  {@props.children}
10
18
  </BS.OverlayTrigger>
@@ -6,8 +6,13 @@ $lanes-field-margin: 6px;
6
6
 
7
7
 
8
8
  .lanes-field {
9
-
10
- .control-label {display: block;}
9
+ .form-control {
10
+ height: inherit;
11
+ }
12
+ .control-label {
13
+ display: block;
14
+ min-height: 18px;
15
+ }
11
16
 
12
17
  &.display {
13
18
  .form-group {
@@ -42,10 +42,13 @@ class Lanes.Components.Toolbar.RemoteChangeSets extends Lanes.React.Component
42
42
  <i className="icon icon-cloud-download icon-lg" />
43
43
  <LC.CountBadge superScript count={@model.changes.length} />
44
44
  </span>
45
- <BS.Nav navbar pullRight className="changes-notification">
46
- <BS.DropdownButton id="record-changes" title={title}>
47
- <div className="scroller">
48
- {@model.changes.map (ch) -> <Change key={ch.cid} model={ch} />}
49
- </div>
50
- </BS.DropdownButton>
51
- </BS.Nav>
45
+
46
+ <div className="changes-notification">
47
+ <BS.DropdownButton id="record-changes"
48
+ title={title}
49
+ >
50
+ <div className="scroller">
51
+ {@model.changes.map (ch) -> <Change key={ch.cid} model={ch} />}
52
+ </div>
53
+ </BS.DropdownButton>
54
+ </div>
@@ -20,8 +20,9 @@ class Lanes.Components.Toolbar.SaveButton extends Lanes.React.Component
20
20
  return null unless @props.commands.canEditModel()
21
21
  model = @props.commands.getModel()
22
22
  text = if model.isNew() then 'Create' else 'Save'
23
- classNames = _.classnames('save', 'navbar-btn', 'control', {disabled: !@isSavable(model)})
24
- <BS.Button navItem componentClass="button"
25
- onClick={@onSave} className={classNames} >
23
+ classNames = _.classnames('save', 'navbar-btn', 'control',
24
+ {disabled: !@isSavable(model)}
25
+ )
26
+ <BS.NavItem onClick={@onSave} className={classNames}>
26
27
  <LC.Icon type="cloud-upload" />{text}
27
- </BS.Button>
28
+ </BS.NavItem>
@@ -7,27 +7,21 @@ class Lanes.Components.Toolbar extends Lanes.React.Component
7
7
  toggleEdit: Lanes.PropTypes.Model
8
8
  commands: React.PropTypes.object.isRequired
9
9
 
10
- dataObjects:
11
- changedModel: -> @props.commands.getModel()
10
+ modelBindings:
11
+ model: 'props'
12
12
 
13
- bindDataEvents:
13
+ bindEvents:
14
14
  changedModel: 'remote-update isSavable'
15
15
 
16
- renderResetButton: ->
17
- <BS.Button navItem componentClass="button"
18
- onClick={@props.commands.resetModel} className="reset navbar-btn control">
19
- <LC.Icon type="undo" />Reset
20
- </BS.Button>
21
-
22
16
  EditToggle: ->
23
17
  return null unless @props.commands.canEditModel()
24
- <li navItem className="toggle control">
25
- <label>
26
- <Lanes.Vendor.ReactToggle
27
- aria-labelledby="Editing"
28
- onChange={@props.commands.toggleEdit}
29
- checked={@props.commands.isEditing()} />
30
- <span>Edit</span>
18
+ <li className="toggle control">
19
+ <label>
20
+ <Lanes.Vendor.ReactToggle
21
+ aria-labelledby="Editing"
22
+ onChange={@props.commands.toggleEdit}
23
+ checked={@props.commands.isEditing()} />
24
+ <span>Edit</span>
31
25
  </label>
32
26
  </li>
33
27
 
@@ -37,9 +31,14 @@ class Lanes.Components.Toolbar extends Lanes.React.Component
37
31
  render: ->
38
32
  <BS.Nav bsStyle="pills" className="lanes-toolbar">
39
33
  <Lanes.Components.Toolbar.SaveButton commands={@props.commands} />
40
- {@renderResetButton()}
34
+ <BS.NavItem
35
+ onClick={@props.commands.resetModel}
36
+ className="reset navbar-btn control">
37
+ <LC.Icon type="undo" />Reset
38
+ </BS.NavItem>
41
39
  {@props.children}
42
- <div className="spacer"/>
40
+ <BS.NavItem className="spacer" />
41
+
43
42
  <@EditToggle />
44
- <LC.Toolbar.RemoteChangeSets model=@changedModel />
43
+ <LC.Toolbar.RemoteChangeSets model=@model />
45
44
  </BS.Nav>
@@ -22,6 +22,9 @@
22
22
  }
23
23
 
24
24
  .dropdown-menu {
25
+ width: 300px;
26
+ right: 0;
27
+ left: -200px;
25
28
  .update {
26
29
  border-bottom: 1px solid $table-border-color;
27
30
  margin-bottom: 5px;
@@ -45,7 +48,6 @@
45
48
  margin-left: 0.5rem;
46
49
  white-space: nowrap;
47
50
  text-overflow: ellipsis;
48
- max-width: 180px;
49
51
  overflow: hidden;
50
52
  }
51
53
  }
@@ -15,8 +15,11 @@
15
15
  align-items: center;
16
16
  flex-wrap: wrap;
17
17
 
18
- .btn {
19
- &.save {
18
+
19
+ .navbar-btn {
20
+ &.save > a {
21
+ width: 100%;
22
+ @extend .btn;
20
23
  @extend .btn-primary;
21
24
  // the save button needs to be clicable even if disabled
22
25
  &.disabled {
@@ -29,7 +32,7 @@
29
32
  flex: 1;
30
33
  }
31
34
  .control {
32
- width: 100px;
35
+ width: 120px;
33
36
  margin-right: 10px;
34
37
  }
35
38
  .arrow {
@@ -3,7 +3,7 @@ REACT_CACHE = Object.create(null)
3
3
  Lanes.lib.HotReload =
4
4
 
5
5
  remember: (klass) ->
6
- return klass # unless klass::FILE
6
+ return unless klass::FILE
7
7
  path = klass::FILE.path.join("/") + ".js"
8
8
  if REACT_CACHE[path]
9
9
  return klass
@@ -5,7 +5,7 @@
5
5
  //= require ./loader
6
6
  //= require ./MakeBaseClass
7
7
  //= require ./el
8
- //= require ./dom-polyfills
8
+ //= require ./polyfills
9
9
  //= require ./dom
10
10
  //= require ./format
11
11
  //= require ./promise_helpers
@@ -15,10 +15,23 @@ class Lanes.lib.Dom
15
15
  remove: ->
16
16
  @el.parentElement.removeChild(@el)
17
17
 
18
+ focus: ->
19
+ @el.focus?()
20
+
18
21
  focusAndSelect: ->
19
22
  @el.select?()
20
23
  @el.focus?()
21
24
 
25
+ setStyle: (style) ->
26
+ _.extend(@el.style, style)
27
+
28
+ on: (evname, fn, useCapture = false) ->
29
+ if @el.addEventListener
30
+ @el.addEventListener(evname, fn, useCapture)
31
+ else if @el.attachEvent
32
+ @el.attachEvent('on' + evname, fn)
33
+
34
+
22
35
  closest: (selector) ->
23
36
  # Traverse the DOM up with a while loop
24
37
  el = @el
@@ -39,7 +52,7 @@ chain = (fn) ->
39
52
 
40
53
  for name, func of Lanes.Vendor.dom
41
54
  Lanes.lib.Dom::[name] = if name.match(/^has/)
42
- wrapArg
55
+ wrapArg(func)
43
56
  else
44
57
  chain(func)
45
58
 
@@ -6,6 +6,9 @@ Lanes.u.format.shortDate = (d) ->
6
6
  Lanes.u.format.shortDateTime = (d) ->
7
7
  _.moment(d).format('lll')
8
8
 
9
+ Lanes.u.format.dateTime = (d) ->
10
+ _.moment(d).format('YYYY-MM-DD hh:mm')
11
+
9
12
  Lanes.u.format.currency = (v) ->
10
13
  v ||= '0'
11
14
  _.sprintf('%0.2f', parseFloat(v)).replace(/\B(?=(\d{3})+\b)/g, ",")
@@ -88,8 +88,6 @@ class Lanes.lib.AssetLoader
88
88
 
89
89
  Lanes.lib.RequestAssets = (urls...) ->
90
90
  urls = urls[0] if urls.length == 1 && _.isArray(urls[0])
91
- for url, i in urls
92
- urls[i] = Lanes.config.assets_path_prefix.concat( '/', urls[i] )
93
91
  new _.Promise( (resolve, reject) ->
94
92
  new Lanes.lib.AssetLoader(urls, (completed) ->
95
93
  failures = _.pick(completed, (status, url) -> !status.success )
@@ -3,3 +3,6 @@ if Element && !Element.prototype.matches
3
3
  proto.matches = proto.matchesSelector ||
4
4
  proto.mozMatchesSelector || proto.msMatchesSelector ||
5
5
  proto.oMatchesSelector || proto.webkitMatchesSelector
6
+
7
+ unless _.isFunction(Object.assign)
8
+ Object.assign = _.extend
@@ -15,13 +15,11 @@ distillTypes = (type, ns) ->
15
15
  _.reduce( type.split( '.' ), ( ( memo, val ) -> return if memo then memo[ val ] else null ), ns )
16
16
 
17
17
  Lanes.u = {
18
-
19
- withReactContext: (newContext, fn) ->
20
- previousContext = Lanes.Vendor.ReactContext.current
21
- Lanes.Vendor.ReactContext.current = _.clone newContext
22
- ret = fn()
23
- Lanes.Vendor.ReactContext.current = previousContext
24
- ret
18
+ cleanBsSizes: (props) ->
19
+ _.omit(props,
20
+ 'xs', 'sm', 'md', 'lg',
21
+ 'xsOffset', 'smOffset', 'mdOffset', 'lgOffset'
22
+ )
25
23
 
26
24
  makeComparatorUsing: (method) ->
27
25
  (a, b) -> Lanes.u.comparator(a[method], b[method])