lanes 0.5.6 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -2
- data/client/lanes/Config.coffee +6 -5
- data/client/lanes/access/LoginDialog.cjsx +4 -2
- data/client/lanes/access/Roles.coffee +3 -0
- data/client/lanes/access/screens/user-management/Editor.cjsx +1 -1
- data/client/lanes/components/grid/Body.cjsx +4 -3
- data/client/lanes/components/grid/Grid.cjsx +4 -3
- data/client/lanes/components/grid/Header.cjsx +1 -1
- data/client/lanes/components/grid/PopOverMixin.cjsx +6 -6
- data/client/lanes/components/grid/Selections.cjsx +16 -6
- data/client/lanes/components/grid/Toolbar.cjsx +1 -1
- data/client/lanes/components/grid/styles.scss +21 -5
- data/client/lanes/components/modal/Modal.cjsx +18 -9
- data/client/lanes/components/record-finder/Clause.cjsx +1 -2
- data/client/lanes/components/record-finder/Dialog.cjsx +11 -3
- data/client/lanes/components/record-finder/RecordFinder.cjsx +14 -7
- data/client/lanes/components/record-finder/styles.scss +1 -0
- data/client/lanes/components/select-field/SelectField.cjsx +36 -10
- data/client/lanes/components/select-field/styles.scss +7 -0
- data/client/lanes/components/shared/Checkbox.cjsx +34 -0
- data/client/lanes/components/shared/DateTime.cjsx +3 -2
- data/client/lanes/components/shared/ErrorDisplay.cjsx +1 -1
- data/client/lanes/components/shared/FieldMixin.cjsx +26 -15
- data/client/lanes/components/shared/FieldSet.cjsx +1 -1
- data/client/lanes/components/shared/FieldWrapper.cjsx +2 -2
- data/client/lanes/components/shared/FormGroup.cjsx +2 -2
- data/client/lanes/components/shared/Icon.cjsx +31 -4
- data/client/lanes/components/shared/IconButton.cjsx +8 -0
- data/client/lanes/components/shared/ImageAsset.cjsx +8 -5
- data/client/lanes/components/shared/IndeterminateCheckbox.cjsx +19 -0
- data/client/lanes/components/shared/InputFieldMixin.cjsx +6 -0
- data/client/lanes/components/shared/JobProgress.cjsx +4 -3
- data/client/lanes/components/shared/NetworkActivityOverlay.cjsx +1 -1
- data/client/lanes/components/shared/ScreenWrapper.cjsx +1 -1
- data/client/lanes/components/shared/ToggleField.cjsx +2 -1
- data/client/lanes/components/shared/Tooltip.cjsx +10 -2
- data/client/lanes/components/shared/fields.scss +7 -2
- data/client/lanes/components/toolbar/RemoteChangeSets.cjsx +10 -7
- data/client/lanes/components/toolbar/SaveButton.cjsx +5 -4
- data/client/lanes/components/toolbar/Toolbar.cjsx +18 -19
- data/client/lanes/components/toolbar/changes-notification.scss +3 -1
- data/client/lanes/components/toolbar/styles.scss +6 -3
- data/client/lanes/lib/HotReload.coffee +1 -1
- data/client/lanes/lib/all.js +1 -1
- data/client/lanes/lib/dom.coffee +14 -1
- data/client/lanes/lib/format.coffee +3 -0
- data/client/lanes/lib/loader.coffee +0 -2
- data/client/lanes/lib/{dom-polyfills.coffee → polyfills.coffee} +3 -0
- data/client/lanes/lib/utilFunctions.coffee +5 -7
- data/client/lanes/models/Asset.coffee +33 -20
- data/client/lanes/models/AssociationMap.coffee +5 -6
- data/client/lanes/models/Base.coffee +5 -2
- data/client/lanes/models/Collection.coffee +23 -2
- data/client/lanes/models/PubSub.coffee +51 -13
- data/client/lanes/models/Query.coffee +53 -42
- data/client/lanes/models/State.coffee +5 -4
- data/client/lanes/models/Sync.coffee +5 -3
- data/client/lanes/models/index.js +1 -1
- data/client/lanes/models/mixins/TrackCollectionRemovals.coffee +17 -0
- data/client/lanes/models/query/ArrayResult.coffee +16 -17
- data/client/lanes/models/query/CollectionResult.coffee +4 -4
- data/client/lanes/react/Component.coffee +14 -13
- data/client/lanes/react/Root.cjsx +1 -1
- data/client/lanes/react/Screen.coffee +1 -0
- data/client/lanes/react/Viewport.coffee +52 -16
- data/client/lanes/react/mixins/Access.coffee +5 -0
- data/client/lanes/react/mixins/Data.coffee +52 -144
- data/client/lanes/react/mixins/MonitorSize.coffee +1 -1
- data/client/lanes/react/mixins/ReadEditingState.coffee +3 -0
- data/client/lanes/screens/Commands.coffee +1 -1
- data/client/lanes/screens/CommonComponents.cjsx +2 -2
- data/client/lanes/screens/Definitions.coffee +3 -1
- data/client/lanes/screens/SystemSettings.cjsx +13 -18
- data/client/lanes/screens/UserPreferences.cjsx +1 -1
- data/client/lanes/styles/fonts.scss +2 -3
- data/client/lanes/styles/global/styles.scss +2 -1
- data/client/lanes/testing/TestObjects.coffee +6 -2
- data/client/lanes/vendor/action_cable.js +590 -0
- data/client/lanes/vendor/development/calendar.js +56 -56
- data/client/lanes/vendor/development/commons.js +7819 -6690
- data/client/lanes/vendor/development/data.js +1877 -1455
- data/client/lanes/vendor/development/helpers.js +39 -82
- data/client/lanes/vendor/development/toggle.js +20 -20
- data/client/lanes/vendor/development/ui.js +14629 -14261
- data/client/lanes/vendor/development/widgets.js +3146 -2173
- data/client/lanes/vendor/index.js +1 -2
- data/client/lanes/vendor/production/calendar.js +56 -56
- data/client/lanes/vendor/production/commons.js +6352 -6185
- data/client/lanes/vendor/production/data.js +1871 -1456
- data/client/lanes/vendor/production/toggle.js +20 -20
- data/client/lanes/vendor/production/ui.js +14694 -14286
- data/client/lanes/vendor/production/widgets.js +3139 -2166
- data/client/lanes/vendor/standalone/index.js +5666 -4586
- data/client/lanes/vendor/styles/widgets.scss +5 -5
- data/client/lanes/workspace/Layout.cjsx +1 -10
- data/client/lanes/workspace/Navbar.cjsx +8 -13
- data/client/lanes/workspace/ScreenView.cjsx +3 -4
- data/client/lanes/workspace/ScreensMenu.cjsx +8 -19
- data/client/lanes/workspace/Tabs.cjsx +6 -14
- data/db/migrate/02_create_assets.rb +1 -3
- data/lanes.gemspec +16 -11
- data/lib/lanes/access/test_fixture_extensions.rb +6 -10
- data/lib/lanes/access/track_modifications.rb +24 -0
- data/lib/lanes/api/cable.rb +49 -0
- data/lib/lanes/api/controller_base.rb +52 -9
- data/lib/lanes/api/default_routes.rb +9 -0
- data/lib/lanes/api/generic_controller.rb +2 -9
- data/lib/lanes/api/handlers/asset.rb +5 -6
- data/lib/lanes/api/helper_methods.rb +3 -2
- data/lib/lanes/api/javascript_processor.rb +6 -5
- data/lib/lanes/api/pub_sub.rb +14 -32
- data/lib/lanes/api/request_wrapper.rb +1 -1
- data/lib/lanes/api/root.rb +4 -7
- data/lib/lanes/api/routing.rb +3 -3
- data/lib/lanes/api/sprockets_extension.rb +1 -1
- data/lib/lanes/api.rb +4 -0
- data/lib/lanes/asset.rb +25 -25
- data/lib/lanes/concerns/asset_uploader.rb +25 -47
- data/lib/lanes/concerns/export_scope.rb +5 -7
- data/lib/lanes/concerns/queries.rb +7 -3
- data/lib/lanes/concerns/set_attribute_data.rb +12 -6
- data/lib/lanes/configuration.rb +4 -7
- data/lib/lanes/db.rb +3 -1
- data/lib/lanes/guard_tasks.rb +2 -1
- data/lib/lanes/hot_reload_plugin.rb +2 -1
- data/lib/lanes/job.rb +0 -1
- data/lib/lanes/logger.rb +3 -3
- data/lib/lanes/model.rb +0 -3
- data/lib/lanes/spec_helper.rb +1 -1
- data/lib/lanes/system_settings.rb +8 -14
- data/lib/lanes/version.rb +1 -1
- data/npm-build/data.js +1 -0
- data/npm-build/package.json +21 -19
- data/npm-build/ui.js +3 -0
- data/npm-build/update-dayz +2 -2
- data/npm-build/update-model-bindings.js +5 -0
- data/spec/command-reference-files/initial/Gemfile +1 -1
- data/spec/command-reference-files/initial/config/database.yml +1 -0
- data/spec/command-reference-files/initial/config/lanes.rb +3 -3
- data/spec/command-reference-files/screen/spec/appy-app/screens/ready-set-go/ReadySetGoSpec.coffee +1 -1
- data/spec/lanes/components/grid/GridSpec.coffee +2 -2
- data/spec/lanes/components/grid/PopoverEditorSpec.coffee +11 -12
- data/spec/lanes/components/select-field/SelectFieldSpec.coffee +6 -4
- data/spec/lanes/components/shared/NetworkActivityOverlaySpec.coffee +1 -1
- data/spec/lanes/models/PubSubSpec.coffee +6 -8
- data/spec/lanes/models/QuerySpec.coffee +19 -0
- data/spec/lanes/react/mixins/DataSpec.coffee +18 -16
- data/spec/server/api/coffeescript_processor_spec.rb +1 -1
- data/spec/server/api/controller_base_spec.rb +77 -0
- data/spec/server/api/pub_sub_spec.rb +9 -0
- data/spec/server/asset_spec.rb +23 -18
- data/spec/server/concerns/export_scope_spec.rb +2 -1
- data/spec/server/concerns/exported_limits_spec.rb +14 -9
- data/spec/server/concerns/set_attribute_data_spec.rb +17 -0
- data/spec/server/spec_helper.rb +29 -11
- data/templates/config/database.yml +1 -0
- data/templates/spec/client/Screen.coffee +1 -1
- data/views/specs.erb +4 -1
- metadata +138 -89
- data/client/lanes/vendor/message-bus-ajax.js +0 -44
- 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
|
-
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
121
|
-
|
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
|
-
|
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:
|
5
|
-
animated:
|
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
|
-
|
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
|
-
|
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
|
-
|
10
|
+
modelBindings:
|
11
11
|
asset: -> @props.model[@props.name]
|
12
12
|
|
13
13
|
listenNetworkEvents: true
|
14
14
|
|
15
|
-
|
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>
|
43
|
-
|
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
|
-
|
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
|
-
|
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: [
|
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
|
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>
|
@@ -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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
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',
|
24
|
-
|
25
|
-
|
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.
|
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
|
-
|
11
|
-
|
10
|
+
modelBindings:
|
11
|
+
model: 'props'
|
12
12
|
|
13
|
-
|
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
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
-
|
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
|
-
<
|
40
|
+
<BS.NavItem className="spacer" />
|
41
|
+
|
43
42
|
<@EditToggle />
|
44
|
-
<LC.Toolbar.RemoteChangeSets model=@
|
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
|
-
|
19
|
-
|
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:
|
35
|
+
width: 120px;
|
33
36
|
margin-right: 10px;
|
34
37
|
}
|
35
38
|
.arrow {
|
data/client/lanes/lib/all.js
CHANGED
data/client/lanes/lib/dom.coffee
CHANGED
@@ -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 )
|
@@ -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
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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])
|