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
@@ -1,4 +1,4 @@
1
- /* Noramlize.css */
1
+ /* Normalize.css */
2
2
  .rw-btn,
3
3
  .rw-input {
4
4
  color: inherit;
@@ -305,7 +305,7 @@ ul.rw-list.rw-list-grouped > li.rw-list-option,
305
305
  border-bottom-left-radius: 4px;
306
306
  border-top-left-radius: 4px;
307
307
  }
308
- .rw-rtl.rw-widget .rw-input {
308
+ .rw-rtl .rw-widget .rw-input {
309
309
  border-bottom-left-radius: 0;
310
310
  border-top-left-radius: 0;
311
311
  border-bottom-right-radius: 4px;
@@ -314,7 +314,7 @@ ul.rw-list.rw-list-grouped > li.rw-list-option,
314
314
  .rw-widget > .rw-select {
315
315
  border-left: #ccc 1px solid;
316
316
  }
317
- .rw-rtl.rw-widget > .rw-select {
317
+ .rw-widget.rw-rtl > .rw-select {
318
318
  border-right: #ccc 1px solid;
319
319
  border-left: none;
320
320
  }
@@ -401,8 +401,8 @@ ul.rw-list.rw-list-grouped > li.rw-list-option,
401
401
  .rw-combobox input.rw-input,
402
402
  .rw-datetimepicker input.rw-input,
403
403
  .rw-numberpicker input.rw-input {
404
- -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
405
- box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
404
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
405
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
406
406
  }
407
407
  .rw-combobox:active,
408
408
  .rw-datetimepicker:active,
@@ -1,6 +1,6 @@
1
1
  class Lanes.Workspace.Layout extends Lanes.React.Component
2
2
 
3
- dataObjects:
3
+ modelBindings:
4
4
  uistate: -> Lanes.Workspace.Extension.uistate
5
5
  viewport: -> @context.viewport
6
6
 
@@ -17,15 +17,6 @@ class Lanes.Workspace.Layout extends Lanes.React.Component
17
17
 
18
18
  componentWillMount: ->
19
19
  @uistate.set(@props)
20
- useBasename = Lanes.Vendor.BrowserHistory.useBasename
21
- history = useBasename(Lanes.Vendor.BrowserHistory.createHistory)({
22
- basename: Lanes.config.root_path
23
- })
24
- @historyStopListening = history.listen (location) ->
25
- Lanes.Screens.Definitions.setBrowserLocation(location)
26
- @setState({history})
27
-
28
- componentWillUnmount: -> @historyStopListening()
29
20
 
30
21
  render: ->
31
22
  <div className="layout">
@@ -1,16 +1,12 @@
1
1
  class Lanes.Workspace.Navbar extends Lanes.React.Component
2
- dataObjects:
2
+ modelBindings:
3
3
  settings: -> Lanes.config.system_settings
4
4
 
5
- propTypes:
6
- history: React.PropTypes.shape(
7
- push: React.PropTypes.func
8
- ).isRequired
9
-
10
5
  contextTypes:
11
6
  uistate: React.PropTypes.object.isRequired
12
7
 
13
- switchMenu: ->
8
+ switchMenu: (ev) ->
9
+ ev.preventDefault()
14
10
  @context.uistate.nextSidebarState()
15
11
 
16
12
  classNames: ->
@@ -18,12 +14,11 @@ class Lanes.Workspace.Navbar extends Lanes.React.Component
18
14
  "menu-hidden": !@model.screen_menu_shown
19
15
 
20
16
  Logo: ->
21
- if @settings.logo?.url
22
- <img src={@settings.logo.thumbnail_url} />
17
+ if @settings.logo?.thumbnail_url
18
+ url = "//#{Lanes.config.api_host}#{@settings.logo.thumbnail_url}"
19
+ <img src={url} />
23
20
  else
24
- <span>
25
- {Lanes.Extensions.controlling().title()}
26
- </span>
21
+ <span>{Lanes.Extensions.controlling().title()}</span>
27
22
 
28
23
  render: ->
29
24
 
@@ -37,5 +32,5 @@ class Lanes.Workspace.Navbar extends Lanes.React.Component
37
32
  <i className="icon"></i>
38
33
  </button>
39
34
  </div>
40
- <Lanes.Workspace.Tabs history={@props.history} />
35
+ <Lanes.Workspace.Tabs />
41
36
  </div>
@@ -10,12 +10,12 @@ class Lanes.Workspace.ScreenView extends Lanes.React.Component
10
10
  contextTypes:
11
11
  uistate: React.PropTypes.object.isRequired
12
12
 
13
- dataObjects:
13
+ modelBindings:
14
14
  displaying: -> Lanes.Screens.Definitions.displaying
15
15
  allScreens: -> Lanes.Screens.Definitions.all
16
16
 
17
- bindDataEvents:
18
- displaying: 'change:active remove add'
17
+ bindEvents:
18
+ displaying: 'add remove reset change:active'
19
19
  allScreens: 'change:loading'
20
20
 
21
21
  renderScreen: (screen) ->
@@ -34,7 +34,6 @@ class Lanes.Workspace.ScreenView extends Lanes.React.Component
34
34
  </div>
35
35
 
36
36
  render: ->
37
-
38
37
  child = if @displaying.isEmpty() then <@BaseView /> else @displaying.map(@renderScreen)
39
38
  <div className={"page-content #{@context.uistate.layout_size}"}>
40
39
  {@renderLoading() if Lanes.Screens.Definitions.all.isLoading()}
@@ -1,12 +1,9 @@
1
1
  class ScreenList extends Lanes.React.Component
2
- propTypes:
3
- history: React.PropTypes.shape(
4
- push: React.PropTypes.func
5
- ).isRequired
6
2
 
7
- activateScreen: ->
3
+ activateScreen: (ev) ->
4
+ ev.preventDefault()
8
5
  @model.display().then (screen) =>
9
- @props.history.push(screen.historyUrl())
6
+ @context.viewport.history.push(screen.historyUrl())
10
7
 
11
8
  render: ->
12
9
  <li>
@@ -18,12 +15,8 @@ class ScreenList extends Lanes.React.Component
18
15
 
19
16
  class ScreenGroup extends Lanes.React.Component
20
17
 
21
- propTypes:
22
- history: React.PropTypes.shape(
23
- push: React.PropTypes.func
24
- ).isRequired
25
-
26
- toggleActive: ->
18
+ toggleActive: (ev) ->
19
+ ev.preventDefault()
27
20
  @model.active = !@model.active
28
21
  undefined
29
22
 
@@ -41,18 +34,14 @@ class ScreenGroup extends Lanes.React.Component
41
34
 
42
35
  class Lanes.Workspace.ScreensMenu extends Lanes.React.Component
43
36
 
44
- propTypes:
45
- history: React.PropTypes.shape(
46
- push: React.PropTypes.func
47
- ).isRequired
48
-
49
- dataObjects:
37
+ modelBindings:
50
38
  user: -> Lanes.current_user
51
39
 
52
40
  renderGroup: (group) ->
53
41
  <ScreenGroup {...@props} model=group key=group.id />
54
42
 
55
- logOut: ->
43
+ logOut: (ev) ->
44
+ ev.preventDefault()
56
45
  Lanes.current_user.logout()
57
46
 
58
47
  render: ->
@@ -1,20 +1,16 @@
1
1
  class TabView extends Lanes.React.Component
2
2
 
3
- setDataState: (nextState) ->
3
+ setModelState: (nextState) ->
4
4
  if @model.active
5
5
  _.dom(document.head).qs('title').text = @model.title()
6
- @props.history.replace(@model.historyUrl())
6
+ @context.viewport.history.replace(@model.historyUrl())
7
7
  if Lanes.Screens.Definitions.displaying.length is 0
8
- @props.history.push('/')
8
+ @context.viewport.history.push('/')
9
9
  @setState(nextState)
10
10
 
11
- propTypes:
12
- history: React.PropTypes.shape(
13
- push: React.PropTypes.func
14
- ).isRequired
15
-
16
11
  activate: ->
17
- @props.history.push(@model.historyUrl())
12
+ @model.active = true
13
+ @context.viewport.history.push(@model.historyUrl())
18
14
  null
19
15
 
20
16
  close: -> @model.remove()
@@ -28,12 +24,8 @@ class TabView extends Lanes.React.Component
28
24
 
29
25
 
30
26
  class Lanes.Workspace.Tabs extends Lanes.React.Component
31
- propTypes:
32
- history: React.PropTypes.shape(
33
- push: React.PropTypes.func
34
- ).isRequired
35
27
 
36
- dataObjects:
28
+ modelBindings:
37
29
  collection: -> Lanes.Screens.Definitions.displaying
38
30
 
39
31
  render: ->
@@ -2,11 +2,9 @@ class CreateAssets < ActiveRecord::Migration
2
2
  def change
3
3
 
4
4
  create_table "assets" do |t|
5
- t.string :file, null: false
6
-
7
5
  t.references :owner, polymorphic: true, null: false
8
6
  t.integer :order
9
- t.jsonb :metadata, null: false, default: {}
7
+ t.jsonb :file_data, null: false, default: {}
10
8
  end
11
9
 
12
10
  add_index :assets, [:owner_id, :owner_type]
data/lanes.gemspec CHANGED
@@ -24,37 +24,42 @@ Gem::Specification.new do |spec|
24
24
 
25
25
  spec.required_ruby_version = ">= 2.0"
26
26
 
27
- spec.add_dependency "activejob", "~> 4.2"
28
- spec.add_dependency "activerecord", "~> 4.2"
27
+ spec.add_dependency "activejob", "~> 5.0"
28
+ spec.add_dependency "activerecord", "~> 5.0"
29
+ spec.add_dependency "actioncable", "~> 5.0"
30
+
31
+ spec.add_dependency "sinatra", "~> 2.0.0.beta2"
32
+ spec.add_dependency "rack", "~> 2.0"
33
+ spec.add_dependency "rack-protection", "~> 2.0.0.beta2"
34
+
35
+ spec.add_dependency "rack-cors", "~> 0.4"
36
+ spec.add_dependency "rack-test", "~> 0.6"
37
+
29
38
  spec.add_dependency "bcrypt", "~> 3.1"
30
- spec.add_dependency "carrierwave", "~> 0.10.0"
39
+ spec.add_dependency "shrine", "~> 2.4"
40
+ spec.add_dependency "image_processing", "~> 0.4"
31
41
  spec.add_dependency "coffee-react", "~> 4.0"
32
42
  spec.add_dependency "coffee-script", "~> 2.4"
33
43
  spec.add_dependency "compass-import-once", "~> 1.0"
34
44
  spec.add_dependency "execjs", "~> 2.6"
35
45
  spec.add_dependency "fastimage", "~> 1.8.1"
36
46
  spec.add_dependency "guard", "~> 2.13"
37
- spec.add_dependency "guard-jasmine", "~> 2.0"
47
+ spec.add_dependency "guard-jasmine", "~> 2.1"
38
48
  spec.add_dependency "guard-minitest", "~> 2.3"
39
49
  spec.add_dependency "hashie", "~> 3.3"
40
50
  spec.add_dependency "jasmine-core", "~> 2.0"
41
51
  spec.add_dependency "jobba", "~> 1.4"
42
- spec.add_dependency "message_bus", "2.0.0.beta.6"
43
52
  spec.add_dependency "mini_magick", "~> 4.3.6"
44
53
  spec.add_dependency "minitest-around", "~> 0.2"
45
54
  spec.add_dependency "mocha", "~> 1.1"
46
55
  spec.add_dependency "oj", "~> 2.1"
47
56
  spec.add_dependency "pg", "~> 0.8"
48
- spec.add_dependency "rack-cors", "~> 0.4"
49
- spec.add_dependency "rack-protection", "~> 1.5"
50
- spec.add_dependency "rack-test", "~> 0.6"
51
57
  spec.add_dependency "rake", "~> 10.0"
52
58
  spec.add_dependency "require_all", "~> 1.3"
53
59
  spec.add_dependency "resque", "~> 1.25"
54
60
  spec.add_dependency "sanitize", "~> 3.0"
55
61
  spec.add_dependency "sass", "~> 3.4"
56
- spec.add_dependency "sinatra", "~> 1.4"
57
- spec.add_dependency "sprockets", "~> 3.6"
62
+ spec.add_dependency "sprockets", "3.6.3"
58
63
  spec.add_dependency "sprockets-helpers", "~> 1.2"
59
64
  spec.add_dependency "thor", "~> 0.19"
60
65
  spec.add_dependency "uglifier", "~> 2.7"
@@ -62,5 +67,5 @@ Gem::Specification.new do |spec|
62
67
  spec.add_development_dependency "bundler", "~> 1.5"
63
68
  spec.add_development_dependency "diffy", "~> 3.0"
64
69
  spec.add_development_dependency "growl", "~> 1.0"
65
-
70
+ spec.add_development_dependency "shrine-memory", ">= 0.2.2"
66
71
  end
@@ -1,20 +1,16 @@
1
1
  module AccessFixtureTestPatches
2
- extend ActiveSupport::Concern
3
2
 
4
- included do
5
- alias_method_chain :table_rows, :custom_autoset_user_fields
6
- end
7
-
8
- def table_rows_with_custom_autoset_user_fields
9
- results = table_rows_without_custom_autoset_user_fields
3
+ def table_rows
4
+ results = super
10
5
  if model_class && model_class < ActiveRecord::Base && model_class.record_modifications
11
6
  results[ table_name ].each do | row |
12
- row['created_by_id'] = 593363170 if model_class.column_names.include?('created_by_id')
13
- row['updated_by_id'] = 593363170 if model_class.column_names.include?('updated_by_id')
7
+ # 135138680 is the 'admin' user
8
+ row['created_by_id'] ||= 135138680 if model_class.column_names.include?('created_by_id')
9
+ row['updated_by_id'] ||= 135138680 if model_class.column_names.include?('updated_by_id')
14
10
  end
15
11
  end
16
12
  results
17
13
  end
18
14
  end
19
15
 
20
- ActiveRecord::FixtureSet.send :include, AccessFixtureTestPatches
16
+ ActiveRecord::FixtureSet.prepend AccessFixtureTestPatches
@@ -16,6 +16,30 @@ module Lanes::Concerns
16
16
  self.blacklist_attributes :created_at, :updated_at, :created_by_id, :updated_by_id
17
17
  before_update :record_update_modifications
18
18
  before_create :record_create_modifications
19
+
20
+ self.export_scope :with_user_logins
21
+ end
22
+
23
+ module ClassMethods
24
+
25
+ def with_user_logins
26
+ q = self; t = table_name
27
+ if current_scope.nil? || current_scope.select_values.exclude?("#{t}.*")
28
+ q = q.select("#{t}.*")
29
+ end
30
+ if self.column_names.include?('created_by_id')
31
+ q = q.select("created_by_user.login as created_by_login")
32
+ .joins("left join lanes_users as created_by_user on " \
33
+ "created_by_user.id = #{t}.created_by_id")
34
+ end
35
+ if self.column_names.include?('updated_by_id')
36
+ q = q.select("updated_by_user.login as updated_by_login")
37
+ .joins("left join lanes_users as updated_by_user on " \
38
+ "updated_by_user.id = #{t}.updated_by_id")
39
+ end
40
+ q
41
+ end
42
+
19
43
  end
20
44
 
21
45
  private
@@ -0,0 +1,49 @@
1
+ require 'action_cable'
2
+ # require 'action_cable/subscription_adapter/postgresql'
3
+
4
+ module Lanes
5
+ module API
6
+ module Cable
7
+ mattr_reader :server
8
+ mattr_reader :config
9
+
10
+
11
+ class Channel < ActionCable::Channel::Base
12
+ end
13
+
14
+ class Connection < ActionCable::Connection::Base
15
+ identified_by :current_user
16
+
17
+ def connect
18
+ reject_unauthorized_connection unless
19
+ cookies['user_id'] &&
20
+ self.current_user = Lanes::User.where(id: cookies['user_id']).first
21
+ end
22
+
23
+ protected
24
+
25
+ def cookies
26
+ request.session
27
+ end
28
+ end
29
+
30
+ def self.configure
31
+ require_relative 'updates'
32
+ @@config = ActionCable::Server::Configuration.new
33
+ config.logger = Lanes.logger
34
+ config.cable = Lanes.config.cable
35
+ config.connection_class = -> { Connection }
36
+ config.allowed_request_origins = -> (host) {
37
+ host
38
+ }
39
+
40
+ ActionCable::Server::Base.config = config
41
+ @@server = ActionCable.server
42
+ Updates.relay!
43
+ end
44
+
45
+ end
46
+
47
+
48
+ end
49
+ end
@@ -33,39 +33,64 @@ module Lanes
33
33
 
34
34
  protected
35
35
 
36
+ def perform_retrieval
37
+ query = build_query
38
+ query = add_scopes_to_query(query)
39
+ query = add_access_limits_to_query(query)
40
+ options = build_reply_options
41
+ if should_include_total_count?
42
+ options[:total_count] = count_query_records(query)
43
+ end
44
+ query = add_modifiers_to_query(query)
45
+ if params[:id]
46
+ query = query.first!
47
+ end
48
+ std_api_reply(:retrieve, query, options)
49
+ end
50
+
36
51
  def perform_single_destroy
37
- record = model.find(params[:id])
52
+ query = model.where(id: params[:id])
53
+ query = add_access_limits_to_query(query)
54
+ record = query.first!
38
55
  record.destroy
39
56
  std_api_reply(:destroy, record, {})
40
57
  end
41
58
 
42
59
  def perform_multiple_destroy
43
- records = model.find( data.map{|rec|rec['id']} )
60
+ query = model.where( id: data.map{|rec|rec['id']} )
61
+ query = add_access_limits_to_query(query)
44
62
  success = true
45
- records.each do | record |
63
+ query.each do | record |
46
64
  if user.can_delete?(record, record.id)
47
65
  success = false unless record.destroy
48
66
  end
49
67
  end
50
68
  options = build_reply_options.merge(success: success)
51
- std_api_reply(:destroy, records, options)
69
+ std_api_reply(:destroy, query, options)
52
70
  end
53
71
 
54
72
  def perform_multiple_updates
55
- records = model.find( data.map{|rec|rec['id']} )
73
+
74
+ query = model.where( id: data.map{|rec|rec['id']} )
75
+ query = add_access_limits_to_query(query)
76
+
56
77
  success = true
57
- records.each do | record |
78
+ query.each do | record |
58
79
  record_data = data.detect{ |rd| rd['id'] == record.id }
80
+ next unless record_data
59
81
  if user.can_write?(record, record.id)
60
82
  record.set_attribute_data(record_data, user)
61
83
  success = false unless record.save
62
84
  end
63
85
  end
64
86
  options = build_reply_options.merge(success: success)
65
- std_api_reply(:update, records, options)
87
+ std_api_reply(:update, query, options)
66
88
  end
67
89
 
68
- def perform_single_update(record)
90
+ def perform_single_update
91
+ query = build_query
92
+ query = add_access_limits_to_query(query)
93
+ record = query.first!
69
94
  record.set_attribute_data(data, user)
70
95
  options = build_reply_options.merge(success: record.save)
71
96
  std_api_reply(:update, record, options)
@@ -149,6 +174,14 @@ module Lanes
149
174
 
150
175
  # query options
151
176
 
177
+ def add_access_limits_to_query(query)
178
+ if model.respond_to?(:access_limits_for_query)
179
+ query = model.access_limits_for_query(query, user, params)
180
+ else
181
+ query
182
+ end
183
+ end
184
+
152
185
  def build_query(query = model.all)
153
186
  if params[:id]
154
187
  query = query.where(id: params[:id])
@@ -156,16 +189,26 @@ module Lanes
156
189
  if params[:nested_attribute]
157
190
  query = query.where(params[:nested_attribute])
158
191
  end
192
+ query = add_access_limits_to_query(query)
193
+
159
194
  if query_params.present?
160
195
  query = add_params_to_query(query)
161
196
  end
162
197
  query
163
198
  end
164
199
 
165
- def add_modifiers_to_query(query)
200
+ def count_query_records(query)
201
+ model.from('('+query.to_sql+') q').count
202
+ end
203
+
204
+ def add_scopes_to_query(query)
166
205
  if query_scopes.present?
167
206
  query = add_scope_to_query(query)
168
207
  end
208
+ query
209
+ end
210
+
211
+ def add_modifiers_to_query(query)
169
212
  query = query.limit(query_limit_size)
170
213
  query = query.offset(query_offset.to_i) if query_offset.present?
171
214
  if include_associations.any?
@@ -10,6 +10,15 @@ module Lanes
10
10
  get Lanes.config.api_path + '/asset/*',
11
11
  &API::Handlers::Asset.getter
12
12
 
13
+ get Lanes.config.api_path + '/ws' do
14
+ API::Cable.server.call(env)
15
+ end
16
+
17
+ post Lanes.config.api_path + '/dev-file-change.json' do
18
+ API::PubSub.publish("file-change", data)
19
+ "OK"
20
+ end
21
+
13
22
  Extensions.each(reversed: true) do | ext |
14
23
  ext.route(self)
15
24
  end
@@ -5,14 +5,7 @@ module Lanes
5
5
  class GenericController < ControllerBase
6
6
 
7
7
  def show
8
- query = build_query
9
- options = build_reply_options
10
- options[:total_count] = query.dup.unscope(:select).count if should_include_total_count?
11
- query = add_modifiers_to_query(query)
12
- if params[:id]
13
- query = query.first!
14
- end
15
- std_api_reply(:retrieve, query, options)
8
+ perform_retrieval
16
9
  end
17
10
 
18
11
  def create
@@ -23,7 +16,7 @@ module Lanes
23
16
 
24
17
  def update
25
18
  if params[:id]
26
- perform_single_update( build_query.first! )
19
+ perform_single_update
27
20
  elsif data.is_a?(Array)
28
21
  perform_multiple_updates
29
22
  end
@@ -4,8 +4,6 @@ module Lanes::API::Handlers
4
4
 
5
5
  def self.saver
6
6
  lambda do
7
- Lanes.logger.debug "Saving File. Root=#{CarrierWave.root}"
8
-
9
7
  path = "#{params['extension_id']}/#{params['owner_type']}"
10
8
  model = path.underscore.camelize.constantize
11
9
 
@@ -17,7 +15,8 @@ module Lanes::API::Handlers
17
15
  else
18
16
  owner.send("build_#{params['owner_association']}")
19
17
  end
20
- asset.store_uploaded_file(params['file'])
18
+
19
+ asset.update(file: params['file'])
21
20
 
22
21
  json_reply std_api_reply asset.new_record? ? :update : :create,
23
22
  asset,
@@ -27,10 +26,10 @@ module Lanes::API::Handlers
27
26
  end
28
27
 
29
28
  def self.getter
29
+ root = Lanes::Extensions.controlling
30
+ .root_path.join('public', 'files')
30
31
  lambda do
31
- # files are stored using a random string, therefore we assume that anyone who
32
- # knows the filename has access and don't empose any further restrictions
33
- send_file CarrierWave::Uploader::Base.root.call + '/' + params['splat'].first
32
+ - send_file(root.join( params['splat'].first ).to_s)
34
33
  end
35
34
  end
36
35
  end
@@ -15,8 +15,9 @@ module Lanes
15
15
  stylesheet_tag('lanes')
16
16
  end
17
17
 
18
- def client_bootstrap_data
19
- Oj.dump(Extensions.client_bootstrap_data(self), mode: :compat)
18
+ def client_bootstrap_data(mergedWith: {})
19
+ Oj.dump(Extensions.client_bootstrap_data(self)
20
+ .merge(mergedWith), mode: :compat)
20
21
  end
21
22
 
22
23
  def csrf_token
@@ -21,7 +21,7 @@ module Lanes
21
21
 
22
22
  def get_js_aliases(ns)
23
23
  ext = Extensions.for_identifier(ns)
24
- aliases = ext ? ext.client_js_aliases : {}
24
+ aliases = ext ? ext.client_js_aliases || {} : {}
25
25
  aliases.merge!({
26
26
  'LC' => 'window.Lanes.Components',
27
27
  'React' => 'window.Lanes.Vendor.React',
@@ -58,10 +58,11 @@ module Lanes
58
58
  (aliases, definitions) = get_js_aliases(identifier)
59
59
  ns, ns_file_ref, ns_ref, ns_name = get_wrapping_vars(identifier)
60
60
  file="{namespace:#{ns_file_ref},extension:{name:'#{ns}',identifier:'#{identifier}'},path:#{path}}"
61
- "(function(Lanes,#{ns_name}_,#{aliases},FILE,window,undefined)"\
62
- "{\n#{js}\n})"\
63
- "(window.Lanes,#{ns_ref}window.Lanes.Vendor.ld,"\
64
- "#{definitions},#{file},window);"
61
+ "(function(Lanes,#{ns_name}_,#{aliases},FILE,window,undefined)" \
62
+ "{\n#{js}\n})" \
63
+ "((window.Lanes = (window.Lanes || {})),#{ns_ref}" \
64
+ "(window.Lanes.Vendor = (window.Lanes.Vendor || {})).ld," \
65
+ "#{definitions},#{file},window);"
65
66
  end
66
67
 
67
68
  end