lanes 0.0.5 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/Gemfile +0 -1
  4. data/README.md +2 -0
  5. data/client/lanes/data/Bootstrap.coffee +2 -2
  6. data/client/lanes/data/Collection.coffee +4 -0
  7. data/client/lanes/data/Config.coffee +0 -5
  8. data/client/lanes/data/Model.coffee +236 -150
  9. data/client/lanes/data/PubSub.coffee +6 -12
  10. data/client/lanes/data/Sync.coffee +1 -0
  11. data/client/lanes/extension/Extensions.coffee +4 -2
  12. data/client/lanes/lib/MakeBaseClass.coffee +1 -1
  13. data/client/lanes/minimal.js +11 -0
  14. data/client/lanes/minimal.scss.erb +12 -0
  15. data/client/lanes/screens/Base.coffee +1 -2
  16. data/client/lanes/screens/Instance.coffee +52 -0
  17. data/client/lanes/vendor/packaged.js +1 -2
  18. data/client/lanes/views/Base.coffee +12 -10
  19. data/client/lanes/workspace.scss.erb +3 -0
  20. data/client/lanes/workspace/index.js +2 -12
  21. data/docs/command.md +111 -0
  22. data/docs/model.md +188 -0
  23. data/docs/todo-example-part-1.md +71 -0
  24. data/docs/view.md +275 -0
  25. data/{spec/client/jasmine_examples/PlayerSpec.js → docs/welcome.md} +0 -0
  26. data/lanes.gemspec +3 -1
  27. data/lib/lanes/api/helper_methods.rb +8 -0
  28. data/lib/lanes/api/javascript_processor.rb +14 -10
  29. data/lib/lanes/api/pub_sub.rb +7 -7
  30. data/lib/lanes/api/request_wrapper.rb +1 -0
  31. data/lib/lanes/api/root.rb +2 -7
  32. data/lib/lanes/api/sprockets_compressor.rb +6 -2
  33. data/lib/lanes/api/sprockets_extension.rb +25 -9
  34. data/lib/lanes/api/test_specs.rb +13 -9
  35. data/lib/lanes/command.rb +16 -6
  36. data/lib/lanes/command/app.rb +11 -5
  37. data/lib/lanes/command/generate_model.rb +4 -3
  38. data/lib/lanes/command/generate_screen.rb +2 -1
  39. data/lib/lanes/command/generate_view.rb +1 -1
  40. data/lib/lanes/command/named_command.rb +5 -4
  41. data/lib/lanes/command/templates/Gemfile +1 -2
  42. data/lib/lanes/command/templates/client/data/Model.coffee +3 -3
  43. data/lib/lanes/command/templates/client/{namespace-extension.js → index.js} +0 -0
  44. data/lib/lanes/command/templates/client/screens/Screen.coffee +1 -3
  45. data/lib/lanes/command/templates/client/{styles/styles.scss → styles.scss} +0 -0
  46. data/lib/lanes/command/templates/client/views/View.coffee +1 -3
  47. data/lib/lanes/command/templates/config/lanes.rb +1 -1
  48. data/lib/lanes/command/templates/gitignore +1 -0
  49. data/lib/lanes/command/templates/lib/namespace/screen.rb +1 -1
  50. data/lib/lanes/command/templates/public/.gitkeep +0 -0
  51. data/lib/lanes/command/templates/spec/client/Screen.coffee +7 -0
  52. data/lib/lanes/command/templates/spec/client/views/ViewSpec.coffee +2 -2
  53. data/lib/lanes/concerns/all.rb +1 -1
  54. data/lib/lanes/concerns/sanitize_fields.rb +32 -0
  55. data/lib/lanes/concerns/set_attribute_data.rb +4 -4
  56. data/lib/lanes/db.rb +7 -8
  57. data/lib/lanes/extension.rb +37 -3
  58. data/lib/lanes/guard_tasks.rb +2 -2
  59. data/lib/lanes/model.rb +2 -2
  60. data/lib/lanes/screens.rb +1 -0
  61. data/lib/lanes/spec_helper.rb +17 -6
  62. data/{spec → lib/lanes}/testing_models.rb +1 -1
  63. data/lib/lanes/version.rb +1 -1
  64. data/npm-build/compile.coffee +1 -6
  65. data/public/javascripts/jasmine_examples/Player.js +22 -0
  66. data/public/javascripts/jasmine_examples/Song.js +7 -0
  67. data/spec/api/javascript_processor_spec.rb +6 -3
  68. data/spec/concerns/api_path_spec.rb +1 -1
  69. data/spec/concerns/association_extensions_spec.rb +7 -3
  70. data/spec/concerns/attr_accessor_with_default_spec.rb +1 -1
  71. data/spec/concerns/code_identifier_spec.rb +1 -1
  72. data/spec/concerns/export_associations_spec.rb +1 -1
  73. data/spec/concerns/export_methods_spec.rb +1 -14
  74. data/spec/concerns/export_scope_spec.rb +7 -9
  75. data/spec/concerns/exported_limits_spec.rb +1 -1
  76. data/spec/concerns/pub_sub_spec.rb +1 -1
  77. data/spec/concerns/set_attribute_data_spec.rb +16 -24
  78. data/spec/configuration_spec.rb +1 -1
  79. data/spec/helpers/lanes-helpers.coffee +61 -0
  80. data/spec/lanes/data/ModelSpec.coffee +152 -0
  81. data/spec/lanes/data/PubSubSpec.coffee +21 -0
  82. data/spec/{client/view → lanes/views}/BaseSpec.coffee +6 -26
  83. data/spec/numbers_spec.rb +1 -1
  84. data/spec/strings_spec.rb +1 -1
  85. data/views/index.erb +3 -10
  86. data/views/specs.erb +4 -1
  87. metadata +62 -16
  88. data/client/lanes/plugins/trigger.coffee +0 -15
  89. data/client/lanes/workspace/Instance.es6 +0 -64
  90. data/lib/lanes/concerns/sanitize_api_data.rb +0 -15
  91. data/spec/api/user_spec.rb +0 -52
  92. data/spec/fixtures/lanes/users.yml +0 -13
  93. data/spec/locked_fields_spec.rb +0 -27
  94. data/spec/role_collection_spec.rb +0 -19
  95. data/spec/user_role_spec.rb +0 -7
  96. data/spec/user_spec.rb +0 -53
@@ -1,4 +1,4 @@
1
- require_relative '../spec_helper'
1
+ require "lanes/spec_helper"
2
2
 
3
3
 
4
4
  class ExportedLimitsTest < Lanes::TestCase
@@ -1,4 +1,4 @@
1
- require_relative '../spec_helper'
1
+ require "lanes/spec_helper"
2
2
 
3
3
  class PubSubTest < Lanes::TestCase
4
4
 
@@ -1,45 +1,37 @@
1
- require_relative '../spec_helper'
1
+ require "lanes/spec_helper"
2
2
 
3
3
  class SetAttributeDataTest < Lanes::TestCase
4
4
 
5
5
  include TestingModels
6
+ def setup
7
+ @user = DummyUser.new
8
+ end
6
9
 
7
10
  def test_attribute_access
8
11
  tm = TestModel.new
9
- assert tm.setting_attribute_is_allowed?(:name, lanes_users(:admin)), "can't access :name"
10
- assert tm.can_write_attributes?({}, admin), "Can't write to TestModel"
12
+ assert tm.setting_attribute_is_allowed?(:name, @user), "can't access :name"
13
+ assert tm.can_write_attributes?({}, @user), "Can't write to TestModel"
11
14
  data = { name: 'CASH', number: '1200' }
12
- assert_equal( data, TestModel.new.set_attribute_data(data) )
15
+ assert_equal( data, TestModel.new.set_attribute_data(data,@user) )
13
16
  end
14
17
 
15
18
  def test_blacklisting
16
- assert TestModel.new.setting_attribute_is_allowed?(:number,Lanes::User.current)
19
+ assert TestModel.new.setting_attribute_is_allowed?(:number,@user)
17
20
  TestModel.send :blacklist_attributes, :number
18
21
  assert_includes TestModel.blacklisted_attributes, :number
19
- refute TestModel.new.setting_attribute_is_allowed?(:number, Lanes::User.current), "Allowed setting blacklisted attribute"
20
- record = TestModel.from_attribute_data({ name: 'CASH', number: '1234'})
22
+ refute TestModel.new.setting_attribute_is_allowed?(:number, @user), "Allowed setting blacklisted attribute"
23
+ record = TestModel.from_attribute_data({ name: 'CASH', number: '1234'}, @user)
21
24
  assert_nil record.number
22
25
  end
23
26
 
24
27
  def test_whitelisting
25
- refute TestModel.new.setting_attribute_is_allowed?('updated_at',Lanes::User.current)
28
+ refute TestModel.new.setting_attribute_is_allowed?('updated_at', @user)
26
29
  TestModel.send :whitelist_attributes, :updated_at
27
- assert TestModel.new.setting_attribute_is_allowed?('updated_at',Lanes::User.current)
28
- end
29
-
30
- def test_recursive_cleaning_belongs_to
31
- assert TestModel.has_exported_association?( :bt, admin )
32
- data = { name: 'testing', bt: { description: 'childish', secret_field: 'dr evil' } }
33
- record = TestModel.new
34
- cleaned = record.set_attribute_data(data)
35
- assert_equal( { name: 'testing', bt:{ description: 'childish' } }, cleaned)
36
- assert record.bt
37
- assert_equal 'childish', record.bt.description
38
- assert_nil record.bt.secret_field
30
+ assert TestModel.new.setting_attribute_is_allowed?('updated_at', @user)
39
31
  end
40
32
 
41
33
  def test_recursive_cleaning_has_many
42
- assert TestModel.has_exported_association?( :hm, admin )
34
+ assert TestModel.has_exported_association?( :hm, @user )
43
35
  data = {
44
36
  name: 'testing',
45
37
  hm: [
@@ -47,7 +39,7 @@ class SetAttributeDataTest < Lanes::TestCase
47
39
  { description: 'childish-2', secret_field: 'dr evil' }
48
40
  ]}
49
41
  record = TestModel.new
50
- cleaned_data = record.set_attribute_data(data)
42
+ cleaned_data = record.set_attribute_data(data,@user)
51
43
  assert_equal 2, record.hm.length
52
44
  assert_equal cleaned_data, {:name=>"testing", :hm=>[{:description=>"childish-1"}, {:description=>"childish-2"}]}
53
45
  assert_saves record
@@ -56,10 +48,10 @@ class SetAttributeDataTest < Lanes::TestCase
56
48
  def test_sending_to_method
57
49
  tm = TestModel.new
58
50
  def tm.meaning_of_life=(var); @setting = var end
59
- tm.set_attribute_data({ meaning_of_life: 42 })
51
+ tm.set_attribute_data({ meaning_of_life: 42 }, @user)
60
52
  assert_nil tm.instance_variable_get(:@setting)
61
53
  TestModel.send :whitelist_attributes, :meaning_of_life
62
- tm.set_attribute_data({ meaning_of_life: 42 })
54
+ tm.set_attribute_data({ meaning_of_life: 42 }, @user)
63
55
  assert_equal 42, tm.instance_variable_get(:@setting)
64
56
  end
65
57
 
@@ -1,4 +1,4 @@
1
- require_relative 'spec_helper'
1
+ require "lanes/spec_helper"
2
2
 
3
3
  describe Lanes::Configuration do
4
4
 
@@ -0,0 +1,61 @@
1
+ Lanes.namespace 'Testing'
2
+
3
+ class Lanes.Testing.View extends Lanes.Views.Base
4
+ template: "<p>hi</p"
5
+ events: { "click #mylink": 'onClick' }
6
+ onClick: Lanes.emptyFn
7
+
8
+ Lanes.Vendor.MessageBus = {
9
+ subscribe: jasmine.createSpy('subscribe')
10
+ unsubscribe: jasmine.createSpy('unsubscribe')
11
+ start: Lanes.emptyFn
12
+ }
13
+
14
+ class Lanes.Testing.Model extends Lanes.Data.Model
15
+ api_path: "test"
16
+ props:
17
+ id: 'number',
18
+ name: ['string', true],
19
+ html: 'string',
20
+ url: 'string',
21
+ something: 'string',
22
+ fireDanger: 'string'
23
+
24
+ session:
25
+ active: 'boolean'
26
+
27
+ derived:
28
+ classes:
29
+ deps: ['something', 'fireDanger', 'active'],
30
+ fn: -> this.something + this.active;
31
+
32
+ class Lanes.Testing.Collection extends Lanes.Data.Collection
33
+ model: Lanes.Testing.Model
34
+
35
+ syncResponse = (method,model,options)->
36
+ if options.success && syncReply.success
37
+ options.success(model, syncReply, {})
38
+ if options.failure && !syncReply.success
39
+ options.failure(model, syncReply, {})
40
+
41
+ syncReply = {}
42
+
43
+ window.syncSucceedWith = (data)->
44
+ syncReply.success = true
45
+ syncReply.data = data
46
+
47
+ beforeEach ->
48
+
49
+ syncReply = {
50
+ success: true
51
+ message: ''
52
+ data: {}
53
+ }
54
+
55
+ Lanes.Testing.syncSpy = jasmine.createSpy('sync').and.callFake(syncResponse)
56
+ Lanes.Testing.syncSpy.lastOptions = ->
57
+ this.calls.mostRecent().args[2]
58
+ Lanes.Data.Model::sync = Lanes.Testing.syncSpy
59
+ Lanes.Data.Collection::sync = Lanes.Testing.syncSpy
60
+
61
+
@@ -0,0 +1,152 @@
1
+
2
+ describe "Model Suite", ->
3
+ Model = undefined
4
+ Collection = undefined
5
+ class Color
6
+ constructor: -> super
7
+ props: { id: 'integer', rgb: 'string' }
8
+ Lanes.Data.Model.extend(Color)
9
+
10
+ makeModel = (props,args={})->
11
+ _.extend(Model.prototype, props)
12
+ Lanes.Data.Model.extend(Model)
13
+ Collection::model = Model
14
+ Lanes.Data.Collection.extend(Collection)
15
+ collection = new Collection
16
+ return collection.add(new Model(args))
17
+
18
+ beforeEach ->
19
+ class TestModel
20
+ constructor: -> super
21
+ Model = TestModel
22
+ class TestCollection
23
+ constructor: -> super
24
+ Collection = TestCollection
25
+
26
+
27
+ it "tracks unsaved attributes", ->
28
+ model = makeModel({
29
+ session:
30
+ foo: 'string'
31
+ bar: 'integer'
32
+ props:
33
+ saved: 'string'
34
+ }, {bar: 'baz'})
35
+ expect(model.isDirty()).toBeFalse()
36
+ model.foo = 'baz' # session prop
37
+ expect(model.isDirty()).toBeFalse()
38
+ expect(model.unsavedData()).toBeEmptyObject()
39
+ model.set( saved: 'true' )
40
+ expect(model.isDirty()).toBeTrue()
41
+
42
+
43
+ it "can tell if it has attributes", ->
44
+ model = makeModel({
45
+ session:
46
+ foo: 'string'
47
+ props:
48
+ bar: 'string'
49
+ })
50
+ expect(model.hasAttribute('missing')).toBeFalse()
51
+ expect(model.hasAttribute('foo')).toBeTrue()
52
+ expect(model.hasAttribute('bar')).toBeTrue()
53
+
54
+ it "provides data for saving", ->
55
+ # model with other types of data, but should only save "props"
56
+ model = makeModel({
57
+ associations:
58
+ color:{ model: Color }
59
+ session:
60
+ unsaved: 'string'
61
+ props:
62
+ id: 'integer'
63
+ foo: 'string'
64
+ bar: 'string'
65
+ derived:
66
+ atest:
67
+ fn: -> 'blarg'
68
+
69
+ })
70
+ model.set( id: 10, unsaved: 'falsify', color: { rgb: '99FFFF' } )
71
+
72
+ expect( model.dataForSave() ).toEqual( id: 10, color: { rgb: '99FFFF' } )
73
+ model.foo = 'a value'
74
+ a=model.changeMonitor.changedAttributes()
75
+ expect( model.dataForSave() ).toEqual( id: 10, foo: 'a value', color: { rgb: '99FFFF' } )
76
+
77
+ it "can be saved", ->
78
+ model = makeModel({
79
+ props:
80
+ id: 'integer'
81
+ foo: 'string'
82
+ bar: 'string'
83
+
84
+ }, { foo: 'one, two, three'} )
85
+ expect(model.isDirty()).toBeTrue()
86
+ expect(model.unsavedData()).toEqual( foo: 'one, two, three' )
87
+ model.save()
88
+ expect(model.sync).toHaveBeenCalledWith('create', model, jasmine.any(Object))
89
+ model.id=11
90
+ expect(model.isNew()).toBeFalse()
91
+ model.sync.calls.reset()
92
+ syncSucceedWith({
93
+ foo: 'a new foo value'
94
+ })
95
+ model.save()
96
+ expect(model.sync).toHaveBeenCalledWith('patch', model, jasmine.any(Object))
97
+ expect(model.foo).toEqual('a new foo value')
98
+
99
+ it "can be fetched",->
100
+ model = makeModel({
101
+ props:
102
+ { id: 'integer', foo: 'string' }
103
+ })
104
+ syncSucceedWith({
105
+ foo: 'foo value'
106
+ })
107
+ model.fetch()
108
+ expect(model.sync).toHaveBeenCalledWith('read', model, jasmine.any(Object))
109
+ expect(model.foo).toEqual('foo value')
110
+ options = model.sync.lastOptions()
111
+ expect(options).toHaveTrue('ignoreUnsaved')
112
+ expect(options).toHaveNumberWithinRange('limit',1,1)
113
+
114
+
115
+ it "can be destroyed", ->
116
+ model = makeModel({
117
+ props: { id: 'integer' }
118
+ },{ id: 1 })
119
+ collection = model.collection
120
+ expect(collection.length).toEqual(1)
121
+ model.destroy()
122
+ expect(model.sync)
123
+ .toHaveBeenCalledWith('delete', model, jasmine.any(Object))
124
+ expect(collection.length).toEqual(0)
125
+
126
+ it "sets associations", ->
127
+ model = makeModel({
128
+ associations:
129
+ color:{ model: Color }
130
+ props: { id: 'integer', foo: 'string' }
131
+ },{ id: 1 })
132
+ expect(model.color).toBeObject()
133
+ model.set(color: { rgb: '99FFFF' })
134
+ expect(model.color.rgb).toEqual('99FFFF')
135
+ model.setFromResponse(color:{ rgb: 'FFA500' })
136
+ expect(model.color.rgb).toEqual('FFA500')
137
+
138
+ it "can fetch associations", ->
139
+ model = makeModel({
140
+ associations:
141
+ color:{ model: Color }
142
+ props: { id: 'integer', foo: 'string' }
143
+ },{ id: 1 })
144
+ model.withAssociations('color')
145
+ expect(model.sync).toHaveBeenCalledWith('read', model, jasmine.any(Object))
146
+ options = model.sync.lastOptions()
147
+ expect(options.include).toEqual(['color'])
148
+
149
+ it "assigns an inverse collection property", ->
150
+ model = makeModel({})
151
+ expect(Model::Collection).toEqual(Collection)
152
+
@@ -0,0 +1,21 @@
1
+
2
+ describe "PubSub Suite", ->
3
+
4
+ it "checks in/out a model when it binds to a view", ->
5
+ view = new Lanes.Testing.View
6
+ model = new Lanes.Testing.Model(id:1)
7
+ spyOn(Lanes.Data.PubSub,'add').and.callThrough()
8
+ spyOn(Lanes.Data.PubSub,'remove')
9
+ view.model = model
10
+ expect(Lanes.Data.PubSub.add).toHaveBeenCalledWith(model)
11
+ expect(Lanes.Vendor.MessageBus.subscribe)
12
+ .toHaveBeenCalledWith("/test/1", jasmine.any(Function))
13
+ view.unset('model')
14
+ expect(Lanes.Data.PubSub.remove).toHaveBeenCalledWith(model)
15
+
16
+ it "can retrieve a model after checkin", ->
17
+ model = new Lanes.Testing.Model(id: 11, name:'bar')
18
+ Lanes.Data.PubSub.add(model)
19
+ checkin = Lanes.Data.PubSub.instanceFor(Lanes.Testing.Model, 11)
20
+ expect(checkin).toEqual(model)
21
+
@@ -1,23 +1,4 @@
1
1
 
2
- class Model extends Lanes.Data.Model
3
- props:
4
- id: 'number',
5
- name: ['string', true],
6
- html: 'string',
7
- url: 'string',
8
- something: 'string',
9
- fireDanger: 'string'
10
-
11
- session:
12
- active: 'boolean'
13
-
14
- derived:
15
- classes:
16
- deps: ['something', 'fireDanger', 'active'],
17
- fn: -> this.something + this.active;
18
-
19
- class Collection extends Lanes.Data.Collection
20
- model: Model
21
2
 
22
3
  describe "BaseView Suite", ->
23
4
  View = undefined
@@ -40,7 +21,6 @@ describe "BaseView Suite", ->
40
21
  view.render()
41
22
  expect(spy).toHaveBeenCalled()
42
23
 
43
-
44
24
  it "renders a template string", ->
45
25
  view = makeView({
46
26
  template: "<p>hi</p"
@@ -64,7 +44,7 @@ describe "BaseView Suite", ->
64
44
  expect(spy).toHaveBeenCalledWith(jasmine.any(Object),22)
65
45
 
66
46
  it "updates from bindings", ->
67
- model = new Model({ name: "Bob" })
47
+ model = new Lanes.Testing.Model({ name: "Bob" })
68
48
  view = makeView({
69
49
  bindings: {
70
50
  "model.name": { hook: 'link' }
@@ -85,7 +65,7 @@ describe "BaseView Suite", ->
85
65
  constructor: -> super
86
66
  session: { answer: 'string' }
87
67
  Lanes.Views.Base.extend(LowerView)
88
- model = new Model
68
+ model = new Lanes.Testing.Model
89
69
  view = makeView({
90
70
  subviews:
91
71
  lower:
@@ -108,7 +88,7 @@ describe "BaseView Suite", ->
108
88
  constructor: -> super
109
89
  bindings: { "model.name": { type: "text" } }
110
90
  Lanes.Views.Base.extend(LowerView)
111
- collection = new Collection
91
+ collection = new Lanes.Testing.Collection
112
92
  view = makeView({
113
93
  subviews:
114
94
  lower:
@@ -141,7 +121,7 @@ describe "BaseView Suite", ->
141
121
  it "invokes model events", ->
142
122
  nameSpy = jasmine.createSpy()
143
123
  urlSpy = jasmine.createSpy()
144
- model = new Model
124
+ model = new Lanes.Testing.Model
145
125
  view = makeView({
146
126
  modelEvents:
147
127
  'change:name': nameSpy
@@ -159,8 +139,8 @@ describe "BaseView Suite", ->
159
139
  collectionEvents:
160
140
  all: 'onEvent'
161
141
  onEvent: eventSpy
162
- initialize: -> this.collection = new Collection
142
+ initialize: -> this.collection = new Lanes.Testing.Collection
163
143
  })
164
144
  expect(eventSpy).not.toHaveBeenCalled()
165
- view.collection.add(new Model)
145
+ view.collection.add(new Lanes.Testing.Model)
166
146
  expect(eventSpy).toHaveBeenCalled()
data/spec/numbers_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require_relative 'spec_helper'
1
+ require "lanes/spec_helper"
2
2
 
3
3
  describe Lanes::Numbers do
4
4
 
data/spec/strings_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require_relative 'spec_helper'
1
+ require "lanes/spec_helper"
2
2
 
3
3
  describe Lanes::Strings do
4
4
 
data/views/index.erb CHANGED
@@ -5,21 +5,14 @@
5
5
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui"/>
7
7
  <title><%= Lanes.config.app_title %></title>
8
- <%= javascript_tag 'lanes/workspace' %>
9
- <%= stylesheet_tag 'lanes/workspace' %>
8
+ <%= lanes_javascript_tag %>
9
+ <%= lanes_stylesheet_tag %>
10
10
  <script type="text/javascript">
11
- Lanes.Workspace.create('.lanes-root', {
12
- csrf_token: "<%= csrf_token %>",
13
- view: "<%= Lanes.config.root_view %>",
14
- root_path: "<%= lanes_api_url %>"
15
- }, <%= client_bootstrap_data %> );
11
+ Lanes.renderScreenTo('body', <%= client_bootstrap_data %> );
16
12
  </script>
17
13
  </head>
18
14
 
19
15
  <body>
20
16
 
21
- <div class="lanes-root">
22
- </div>
23
-
24
17
  </body>
25
18
  </html>