lanes 0.1.9.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (304) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Rakefile +1 -1
  4. data/client/lanes/Boot.cjsx +3 -3
  5. data/client/lanes/Config.coffee +38 -3
  6. data/client/lanes/access/Extension.coffee +1 -1
  7. data/client/lanes/access/LoginDialog.cjsx +57 -47
  8. data/client/lanes/access/Roles.coffee +2 -2
  9. data/client/lanes/access/User.coffee +4 -3
  10. data/client/lanes/access/screens/user-management/UserManagement.cjsx +12 -11
  11. data/client/lanes/components/calendar/Calendar.cjsx +16 -0
  12. data/client/lanes/components/calendar/index.js +3 -0
  13. data/client/lanes/components/calendar/styles.scss +3 -0
  14. data/client/lanes/components/grid/Body.cjsx +86 -0
  15. data/client/lanes/components/grid/CellStyles.coffee +20 -0
  16. data/client/lanes/components/grid/EditingMixin.cjsx +84 -24
  17. data/client/lanes/components/grid/Editor.cjsx +45 -0
  18. data/client/lanes/components/grid/Grid.cjsx +62 -104
  19. data/client/lanes/components/grid/Header.cjsx +35 -0
  20. data/client/lanes/components/grid/PopOverMixin.cjsx +19 -9
  21. data/client/lanes/components/grid/PopoverEditor.cjsx +7 -1
  22. data/client/lanes/components/grid/RowEditor.cjsx +1 -1
  23. data/client/lanes/components/grid/Selections.cjsx +39 -0
  24. data/client/lanes/components/grid/Toolbar.cjsx +24 -5
  25. data/client/lanes/components/grid/editors.scss +22 -50
  26. data/client/lanes/components/grid/index.js +0 -1
  27. data/client/lanes/components/grid/row-editor.scss +68 -0
  28. data/client/lanes/components/grid/styles.scss +79 -3
  29. data/client/lanes/components/modal/Modal.cjsx +64 -24
  30. data/client/lanes/components/modal/styles.scss +12 -0
  31. data/client/lanes/components/record-finder/Clause.cjsx +11 -4
  32. data/client/lanes/components/record-finder/Dialog.cjsx +23 -24
  33. data/client/lanes/components/record-finder/RecordFinder.cjsx +45 -14
  34. data/client/lanes/components/record-finder/styles.scss +9 -6
  35. data/client/lanes/components/select-field/SelectField.cjsx +108 -53
  36. data/client/lanes/components/select-field/styles.scss +19 -0
  37. data/client/lanes/components/shared/ControlLabel.cjsx +45 -0
  38. data/client/lanes/components/shared/DateTime.cjsx +48 -0
  39. data/client/lanes/components/shared/DisplayValue.cjsx +16 -0
  40. data/client/lanes/components/shared/FieldMixin.cjsx +54 -23
  41. data/client/lanes/components/shared/FieldSet.cjsx +12 -35
  42. data/client/lanes/components/shared/FieldWrapper.cjsx +13 -0
  43. data/client/lanes/components/shared/FormGroup.cjsx +37 -0
  44. data/client/lanes/components/shared/Icon.cjsx +20 -0
  45. data/client/lanes/components/shared/ImageSaver.cjsx +33 -0
  46. data/client/lanes/components/shared/Input.cjsx +19 -0
  47. data/client/lanes/components/shared/InputFieldMixin.cjsx +48 -0
  48. data/client/lanes/components/shared/JobProgress.cjsx +27 -0
  49. data/client/lanes/components/shared/NetworkActivityOverlay.cjsx +58 -0
  50. data/client/lanes/components/shared/NumberInput.cjsx +29 -0
  51. data/client/lanes/components/shared/ResizeSensor.cjsx +11 -0
  52. data/client/lanes/components/shared/ScreenWrapper.cjsx +13 -0
  53. data/client/lanes/components/shared/Throbber.cjsx +3 -0
  54. data/client/lanes/components/shared/ToggleField.cjsx +33 -0
  55. data/client/lanes/components/shared/Tooltip.cjsx +2 -2
  56. data/client/lanes/components/shared/fields.scss +75 -13
  57. data/client/lanes/components/shared/fieldset.scss +3 -5
  58. data/client/lanes/components/shared/image-saver.scss +38 -0
  59. data/client/lanes/components/shared/index.js +2 -0
  60. data/client/lanes/{styles/plugins → components/shared}/overlay.scss +17 -4
  61. data/client/lanes/components/shared/resize-sensor.scss +30 -0
  62. data/client/lanes/components/shared/styles.scss +13 -0
  63. data/client/lanes/components/shared/throbber.scss +53 -0
  64. data/client/lanes/components/toolbar/RemoteChangeSets.cjsx +21 -48
  65. data/client/lanes/components/toolbar/SaveButton.cjsx +24 -0
  66. data/client/lanes/components/toolbar/Toolbar.cjsx +24 -37
  67. data/client/lanes/components/toolbar/changes-notification.scss +10 -6
  68. data/client/lanes/components/toolbar/styles.scss +29 -9
  69. data/client/lanes/extension/Base.coffee +4 -5
  70. data/client/lanes/index.js +0 -1
  71. data/client/lanes/index.scss.erb +10 -1
  72. data/client/lanes/lib/HotReload.coffee +13 -15
  73. data/client/lanes/lib/MakeBaseClass.coffee +6 -1
  74. data/client/lanes/lib/development.coffee +2 -0
  75. data/client/lanes/lib/dom-polyfills.coffee +5 -0
  76. data/client/lanes/lib/dom.coffee +38 -9
  77. data/client/lanes/lib/format.coffee +11 -0
  78. data/client/lanes/lib/index.js.erb +2 -0
  79. data/client/lanes/lib/production.coffee +6 -0
  80. data/client/lanes/lib/utilFunctions.coffee +50 -15
  81. data/client/lanes/models/AssociationMap.coffee +122 -46
  82. data/client/lanes/models/AssociationProxy.coffee +147 -0
  83. data/client/lanes/models/Base.coffee +97 -85
  84. data/client/lanes/models/ChangeMonitor.coffee +7 -3
  85. data/client/lanes/models/ChangeSet.coffee +2 -2
  86. data/client/lanes/models/Collection.coffee +49 -6
  87. data/client/lanes/models/JobStatus.coffee +32 -0
  88. data/client/lanes/models/PubSub.coffee +7 -5
  89. data/client/lanes/models/Query.coffee +115 -34
  90. data/client/lanes/models/ServerCache.coffee +67 -52
  91. data/client/lanes/models/State.coffee +97 -0
  92. data/client/lanes/models/Sync.coffee +18 -13
  93. data/client/lanes/models/SystemSettings.coffee +0 -0
  94. data/client/lanes/models/index.js +1 -0
  95. data/client/lanes/models/mixins/FileSupport.coffee +60 -0
  96. data/client/lanes/models/mixins/HasCodeField.coffee +13 -6
  97. data/client/lanes/models/query/ArrayResult.coffee +188 -0
  98. data/client/lanes/models/query/CollectionResult.coffee +71 -0
  99. data/client/lanes/models/query/Result.coffee +9 -0
  100. data/client/lanes/react/Component.coffee +7 -3
  101. data/client/lanes/react/PubSub.coffee +7 -7
  102. data/client/lanes/react/Root.cjsx +1 -4
  103. data/client/lanes/react/Screen.coffee +1 -0
  104. data/client/lanes/react/TypeValidators.coffee +3 -3
  105. data/client/lanes/react/Viewport.coffee +41 -7
  106. data/client/lanes/react/index.js +0 -1
  107. data/client/lanes/react/mixins/Access.coffee +4 -1
  108. data/client/lanes/react/mixins/Data.coffee +40 -25
  109. data/client/lanes/react/mixins/FieldErrors.coffee +27 -0
  110. data/client/lanes/react/mixins/RelayEditingState.coffee +4 -0
  111. data/client/lanes/react/mixins/Screen.coffee +14 -0
  112. data/client/lanes/react/mixins/Viewport.coffee +9 -3
  113. data/client/lanes/screens/ChangeListener.coffee +3 -3
  114. data/client/lanes/screens/Commands.coffee +14 -7
  115. data/client/lanes/screens/CommonComponents.cjsx +20 -0
  116. data/client/lanes/screens/Definitions.coffee +64 -20
  117. data/client/lanes/screens/SystemSettings.cjsx +56 -0
  118. data/client/lanes/screens/UserPreferences.cjsx +38 -0
  119. data/client/lanes/screens/index.js +3 -0
  120. data/client/lanes/screens/styles.scss +2 -1
  121. data/client/lanes/styles/fonts.scss +1 -0
  122. data/client/lanes/styles/global.scss +2 -1
  123. data/client/lanes/styles/global/flexbox.scss +16 -0
  124. data/client/lanes/styles/global/styles.scss +1 -0
  125. data/client/lanes/styles/mixins/_dropdown.scss +21 -0
  126. data/client/lanes/styles/mixins/_flexbox.scss +394 -0
  127. data/client/lanes/styles/mixins/all.scss +2 -0
  128. data/client/lanes/styles/variables.scss +28 -0
  129. data/client/lanes/testing/BeforeEach.coffee +15 -14
  130. data/client/lanes/testing/Helpers.coffee +14 -5
  131. data/client/lanes/testing/TestObjects.coffee +10 -2
  132. data/client/lanes/testing/index.js +1 -0
  133. data/client/lanes/testing/jasmine-react.js +125 -0
  134. data/client/lanes/vendor/base.js +56049 -74987
  135. data/client/lanes/vendor/calendar.js +17301 -0
  136. data/client/lanes/vendor/calendar.scss +303 -0
  137. data/client/lanes/vendor/commons.js +14990 -15847
  138. data/client/lanes/vendor/development.js +4912 -1952
  139. data/client/lanes/vendor/grid.js +14246 -5551
  140. data/client/lanes/vendor/grid.scss +876 -335
  141. data/client/lanes/vendor/index.js +1 -0
  142. data/client/lanes/vendor/message-bus-ajax.js +44 -0
  143. data/client/lanes/vendor/message-bus.js +414 -0
  144. data/client/lanes/vendor/rw-widgets.eot +0 -0
  145. data/client/lanes/vendor/rw-widgets.svg +18 -0
  146. data/client/lanes/vendor/rw-widgets.ttf +0 -0
  147. data/client/lanes/vendor/rw-widgets.woff +0 -0
  148. data/client/lanes/vendor/toggle.js +345 -0
  149. data/client/lanes/vendor/toggle.scss +138 -0
  150. data/client/lanes/vendor/widgets.js +21245 -6839
  151. data/client/lanes/vendor/widgets.scss +83 -67
  152. data/client/lanes/workspace/Layout.cjsx +18 -8
  153. data/client/lanes/workspace/Modal.cjsx +47 -0
  154. data/client/lanes/workspace/Navbar.cjsx +16 -2
  155. data/client/lanes/workspace/ScreenView.cjsx +10 -3
  156. data/client/lanes/workspace/ScreensMenu.cjsx +23 -7
  157. data/client/lanes/workspace/Tabs.cjsx +55 -0
  158. data/client/lanes/workspace/UIState.coffee +7 -8
  159. data/client/lanes/workspace/index.js +2 -1
  160. data/client/lanes/workspace/mixin.coffee +11 -0
  161. data/client/lanes/workspace/mixins/UIState.coffee +8 -0
  162. data/client/lanes/workspace/mixins/index.js +3 -0
  163. data/client/lanes/workspace/styles.scss +2 -1
  164. data/client/lanes/workspace/styles/header.scss +23 -1
  165. data/client/lanes/workspace/styles/layout.scss +26 -24
  166. data/client/lanes/workspace/styles/screens.scss +0 -4
  167. data/client/lanes/workspace/styles/tabs.scss +3 -10
  168. data/config/routes.rb +10 -4
  169. data/config/screens.rb +25 -0
  170. data/db/migrate/01_create_system_settings.rb +10 -0
  171. data/docs/todo-example-part-1.md +18 -20
  172. data/lanes.gemspec +15 -6
  173. data/lib/lanes.rb +4 -2
  174. data/lib/lanes/access/config/routes.rb +5 -3
  175. data/lib/lanes/access/config/screens.rb +1 -0
  176. data/lib/lanes/access/db/migrate/20140615031600_create_lanes_users.rb +1 -1
  177. data/lib/lanes/access/user.rb +1 -1
  178. data/lib/lanes/api.rb +2 -1
  179. data/lib/lanes/api/controller.rb +32 -71
  180. data/lib/lanes/api/default_routes.rb +10 -8
  181. data/lib/lanes/api/formatted_reply.rb +53 -0
  182. data/lib/lanes/api/handlers/file.rb +26 -0
  183. data/lib/lanes/api/helper_methods.rb +29 -5
  184. data/lib/lanes/api/javascript_processor.rb +36 -17
  185. data/lib/lanes/api/pub_sub.rb +6 -9
  186. data/lib/lanes/api/request_wrapper.rb +1 -2
  187. data/lib/lanes/api/root.rb +11 -43
  188. data/lib/lanes/api/routing.rb +63 -0
  189. data/lib/lanes/api/sprockets_extension.rb +15 -7
  190. data/lib/lanes/api/updates.rb +1 -2
  191. data/lib/lanes/command.rb +0 -1
  192. data/lib/lanes/command/app.rb +6 -5
  193. data/lib/lanes/command/console.rb +1 -0
  194. data/lib/lanes/command/generate.rb +3 -0
  195. data/lib/lanes/command/generate_migration.rb +33 -0
  196. data/lib/lanes/command/generate_model.rb +4 -26
  197. data/lib/lanes/command/migration_support.rb +29 -0
  198. data/lib/lanes/command/update_model.rb +14 -5
  199. data/lib/lanes/concerns/all.rb +2 -0
  200. data/lib/lanes/concerns/api_path.rb +4 -2
  201. data/lib/lanes/concerns/association_extensions.rb +1 -1
  202. data/lib/lanes/concerns/attr_accessor_with_default.rb +3 -1
  203. data/lib/lanes/concerns/code_identifier.rb +1 -1
  204. data/lib/lanes/concerns/image_uploader.rb +42 -0
  205. data/lib/lanes/concerns/pub_sub.rb +0 -1
  206. data/lib/lanes/concerns/queries.rb +2 -2
  207. data/lib/lanes/concerns/set_attribute_data.rb +4 -13
  208. data/lib/lanes/concerns/sorting_expressions.rb +34 -0
  209. data/lib/lanes/configuration.rb +48 -9
  210. data/lib/lanes/extension.rb +16 -7
  211. data/lib/lanes/extension/definition.rb +8 -2
  212. data/lib/lanes/job.rb +78 -0
  213. data/lib/lanes/job/failure_logger.rb +33 -0
  214. data/lib/lanes/model.rb +4 -0
  215. data/lib/lanes/rake_tasks.rb +6 -0
  216. data/lib/lanes/redis.rb +13 -0
  217. data/lib/lanes/screen.rb +34 -18
  218. data/lib/lanes/system_settings.rb +66 -0
  219. data/lib/lanes/version.rb +1 -1
  220. data/lib/lanes/workspace/extension.rb +1 -1
  221. data/npm-build/base.js +10 -3
  222. data/npm-build/calendar.js +6 -0
  223. data/npm-build/development.js +4 -5
  224. data/npm-build/grid.js +3 -5
  225. data/npm-build/package.json +40 -29
  226. data/npm-build/react-toggle.js +5 -0
  227. data/npm-build/react-widgets.js +6 -0
  228. data/npm-build/update-dayz +14 -0
  229. data/npm-build/webpack.config.js +5 -2
  230. data/spec/command-reference-files/initial/Gemfile +1 -1
  231. data/spec/command-reference-files/initial/config/routes.rb +2 -0
  232. data/spec/command-reference-files/initial/lib/appy-app.rb +4 -0
  233. data/spec/command-reference-files/initial/lib/appy-app/extension.rb +2 -0
  234. data/spec/command-reference-files/initial/spec/server/{spec_helpers.rb → spec_helper.rb} +0 -0
  235. data/spec/command-reference-files/model/config/routes.rb +2 -0
  236. data/spec/command-reference-files/model/spec/server/test_test_spec.rb +1 -1
  237. data/spec/command-reference-files/screen/client/appy-app/screens/ready-set-go/ReadySetGo.cjsx +6 -4
  238. data/spec/command-reference-files/screen/client/appy-app/screens/ready-set-go/index.scss +4 -3
  239. data/spec/command-reference-files/screen/config/screens.rb +4 -2
  240. data/spec/command-reference-files/screen/spec/appy-app/screens/ready-set-go/ReadySetGoSpec.coffee +1 -1
  241. data/spec/fixtures/system_settings.yml +1 -0
  242. data/spec/lanes/components/grid/GridSpec.coffee +56 -31
  243. data/spec/lanes/components/grid/RowEditorSpec.coffee +96 -0
  244. data/spec/lanes/components/select-field/SelectFieldSpec.coffee +99 -0
  245. data/spec/lanes/components/shared/NetworkActivityOverlaySpec.coffee +34 -0
  246. data/spec/lanes/models/AssociationMapSpec.coffee +36 -2
  247. data/spec/lanes/models/AssociationProxySpec.coffee +77 -0
  248. data/spec/lanes/models/BaseSpec.coffee +37 -4
  249. data/spec/lanes/models/CollectionSpec.coffee +11 -17
  250. data/spec/lanes/models/PubSubSpec.coffee +1 -1
  251. data/spec/lanes/models/ServerCacheSpec.coffee +65 -0
  252. data/spec/server/api/coffeescript_processor_spec.rb +1 -1
  253. data/spec/server/concerns/pub_sub_spec.rb +9 -10
  254. data/spec/server/concerns/sorting_expressions_spec.rb +34 -0
  255. data/spec/server/configuration_spec.rb +3 -3
  256. data/spec/server/job_spec.rb +54 -0
  257. data/spec/server/spec_helper.rb +0 -5
  258. data/spec/server/system_settings_spec.rb +23 -0
  259. data/templates/client/screens/Screen.cjsx +6 -4
  260. data/templates/client/screens/styles.scss +4 -3
  261. data/templates/config/routes.rb +2 -0
  262. data/templates/config/screen.rb +4 -2
  263. data/templates/lib/namespace.rb +4 -0
  264. data/templates/lib/namespace/extension.rb +2 -0
  265. data/templates/spec/client/Screen.coffee +1 -1
  266. data/templates/spec/server/model_spec.rb +1 -1
  267. data/templates/spec/server/{spec_helpers.rb → spec_helper.rb} +0 -0
  268. data/views/lanes_root_view.erb +70 -0
  269. data/views/specs.erb +2 -2
  270. metadata +207 -68
  271. data/client/images/lanes/dataTables/Sorting icons.psd +0 -0
  272. data/client/images/lanes/dataTables/back_disabled.png +0 -0
  273. data/client/images/lanes/dataTables/back_enabled.png +0 -0
  274. data/client/images/lanes/dataTables/back_enabled_hover.png +0 -0
  275. data/client/images/lanes/dataTables/favicon.ico +0 -0
  276. data/client/images/lanes/dataTables/forward_disabled.png +0 -0
  277. data/client/images/lanes/dataTables/forward_enabled.png +0 -0
  278. data/client/images/lanes/dataTables/forward_enabled_hover.png +0 -0
  279. data/client/images/lanes/dataTables/loading-background.png +0 -0
  280. data/client/images/lanes/dataTables/sort_asc.png +0 -0
  281. data/client/images/lanes/dataTables/sort_asc_disabled.png +0 -0
  282. data/client/images/lanes/dataTables/sort_both.png +0 -0
  283. data/client/images/lanes/dataTables/sort_desc.png +0 -0
  284. data/client/images/lanes/dataTables/sort_desc_disabled.png +0 -0
  285. data/client/lanes/components/shared/Resize.cjsx +0 -152
  286. data/client/lanes/components/shared/TextArea.cjsx +0 -19
  287. data/client/lanes/components/shared/TextField.cjsx +0 -25
  288. data/client/lanes/models/Bootstrap.coffee +0 -5
  289. data/client/lanes/models/QueryResults.coffee +0 -93
  290. data/client/lanes/react/FormBindings.coffee +0 -103
  291. data/client/lanes/react/Router.cjsx +0 -18
  292. data/client/lanes/styles/dataTables.scss +0 -4
  293. data/client/lanes/styles/plugins/all.scss +0 -2
  294. data/client/lanes/styles/plugins/resize-sensor.scss +0 -24
  295. data/client/lanes/vendor/jquery-2.js +0 -9190
  296. data/client/lanes/vendor/jquery.tap.js +0 -401
  297. data/client/lanes/vendor/magicsuggest.js +0 -1565
  298. data/client/lanes/vendor/message-bus.coffee +0 -264
  299. data/client/lanes/workspace/ActiveScreenSwitcher.cjsx +0 -38
  300. data/client/lanes/workspace/styles/toolbar.scss +0 -4
  301. data/lib/lanes/api/eco.js +0 -516
  302. data/lib/lanes/api/sprockets_compressor.rb +0 -39
  303. data/spec/command-reference-files/model/lib/appy-app.rb +0 -11
  304. data/views/index.erb +0 -19
data/config/routes.rb CHANGED
@@ -1,7 +1,13 @@
1
- require 'lanes/access/user'
1
+ Lanes::API.routes.for_extension 'lanes' do
2
2
 
3
- module Lanes
4
- API.routes.draw do
5
- resources User
3
+ root_view :lanes_root_view
4
+
5
+ get 'job-statuses/:id.json' do
6
+ wrap_reply do
7
+ status = Lanes::Job.status_for_id(params[:id])
8
+ raise ActiveRecord::RecordNotFound unless status
9
+ std_api_reply :update, status, success: true
10
+ end
6
11
  end
12
+
7
13
  end
data/config/screens.rb ADDED
@@ -0,0 +1,25 @@
1
+ Lanes::Screen.for_extension 'lanes' do | screens |
2
+
3
+ screens.define "user-preferences" do | screen |
4
+ screen.title = "User Preferences"
5
+ screen.description = "Modify User Profile"
6
+ screen.icon = "user-secret"
7
+ screen.group_id = "system-settings"
8
+ screen.model_class = "User"
9
+ screen.view_class = "UserPreferences"
10
+ screen.js = ''
11
+ screen.css = ''
12
+ end
13
+
14
+ screens.define "system-settings" do | screen |
15
+ screen.title = "System Settings"
16
+ screen.description = "Update System Settings"
17
+ screen.icon = "cogs"
18
+ screen.group_id = "system-settings"
19
+ screen.model_class = "User"
20
+ screen.view_class = "SystemSettings"
21
+ screen.js = ''
22
+ screen.css = ''
23
+ end
24
+
25
+ end
@@ -0,0 +1,10 @@
1
+ class CreateSystemSettings < ActiveRecord::Migration
2
+ def change
3
+
4
+ create_table "system_settings" do |t|
5
+ t.string "logo"
6
+ t.jsonb "settings", null: false, default: {}
7
+ end
8
+
9
+ end
10
+ end
@@ -15,7 +15,7 @@ lanes new todo
15
15
 
16
16
  This will create a new directory with a skeleton Lanes application. Read more about the directories and what their purposes are at {% doc_link command heading:'lanes new' %}.
17
17
 
18
- [Our example app at this point](https://github.com/argosity/lanes-todo-demo/tree/a0909c52d63d3c8e577bdb4338c91ba74e4b1dfa)
18
+ [Our example app at this point](https://github.com/argosity/lanes-todo-demo/tree/c5ee64a5e932055470bf2d13d417f118b89114d6)
19
19
 
20
20
  # Setup
21
21
 
@@ -23,40 +23,40 @@ A sample database configuration file is located in `config/database.yml` which w
23
23
 
24
24
  Fire up the lanes testing server: `lanes serve`. The test server will start the app and you can view it at: `http://localhost:8888/`. You should see a simple "Todo" message. You can also view the Jasmine specs at `http://localhost:8888/spec`
25
25
 
26
- We'll copy the styles from the [TodoMVC template](https://github.com/tastejs/todomvc/tree/master/template).
26
+ Next we'll create a data model `lanes generate model task title:string{80} completed:boolean` [commit](https://github.com/argosity/lanes-todo-demo/commit/e22d058d49c482f9be0167068adab1e37be868bc)
27
+
28
+ Since a task should default to being non-completed, we'll edit the migration to default that field to `false` and add a validation to the model [commit](https://github.com/argosity/lanes-todo-demo/commit/4fda061c13d399062850173eff7bb616563a82bf)
27
29
 
28
- Looking at the Todo app, it has four distinct areas. A `sidebar`, `header`, `footer` and `listing` views. We can create views for them by executing `lanes generate view <name>`, where '< name >' is the view to create. [commit](https://github.com/argosity/lanes-todo-demo/commit/6d34c981637f75a182bf708290a146fdc72c77f2)
30
+ Lanes uses the concept of **Screens** to dynamically load a React component and all it's dependencies. In this case, the Todo app will have only one screen which we can create by running: `lanes generate screen main` [commit](https://github.com/argosity/lanes-todo-demo/commit/f8614fd7d2e29987639ed7c6141e35c5e51e035f)
29
31
 
30
- First we take the TodoMVC html template and break it apart into sections and copy them to each view. We're then able to plug each view's reference into the Screen as subviews. [commit](https://github.com/argosity/lanes-todo-demo/commit/33d3d56b7a03e403276e894cc9233d4d2aa353e8)
32
+ Looking at the Todo app, it has four distinct areas. A `sidebar`, `header`, `footer` and `listing` components. We can create views for them by executing `lanes generate component <name>`, where '< name >' is the view to create. [commit](https://github.com/argosity/lanes-todo-demo/commit/cdd63af42efada9d3c9a05658337e44141a0500a)
31
33
 
32
- Next we'll create a data model `lanes generate model task title:string{80} completed:boolean` [commit](https://github.com/argosity/lanes-todo-demo/commit/c157f43fbf13a431e9ea08c67d65026c1b96e6dd)
34
+ We'll copy the styles from the [TodoMVC template](https://github.com/tastejs/todomvc/tree/master/template).
33
35
 
34
- Since a task should default to being non-completed, we'll edit the migration to default that field to `false` and add a validation to the model [commit](https://github.com/argosity/lanes-todo-demo/commit/6ab50c30eee4b11a4406eacc53b1f5e63de76b45)
36
+ First we take the TodoMVC html template and break it apart into sections and copy them to each view. We're then able to plug each component's into the Screen. [commit](https://github.com/argosity/lanes-todo-demo/commit/cb2651fc3c7bfc0d2f093023056241b93c9b0597)
35
37
 
36
38
  Run migration: `lanes db migrate`
37
39
 
38
- We'll also create a TaskSummary model that is in charge of summarizing the state of the tasks. It will listen to the tasks collection and perform calculations when events occur. [commit](https://github.com/argosity/lanes-todo-demo/commit/c3372a0d76b5aafb4921b98c10f91d34c86ab86f)
40
+ We'll also create a TaskSummary model that is in charge of summarizing the state of the tasks. It will listen to the tasks collection and perform calculations when events occur. [commit](https://github.com/argosity/lanes-todo-demo/commit/61a9cb6a6101816becf7f0aa556dd6506f9ffed4)
39
41
 
40
42
  # Data and events
41
43
 
42
- ## Header View
43
- It's responsible for interaction with the "What needs to be done?" input. When text is present and the "enter" key is pressed, it should save a record and add it to the collection. We're able to do so in [just a few lines of code](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Header.coffee#L22-L25)
44
+ ## Header
45
+ It's responsible for interaction with the "What needs to be done?" input. When text is present and the "enter" key is pressed, it should save a record and add it to the collection. We're able to do so in [just a few lines of code](https://github.com/argosity/lanes-todo-demo/commit/bbdf8c8a95ddea8285615d4a7898d9054b22c4b4)
44
46
 
45
- We can easily test that it performs as it should by [adding a few specs](https://github.com/argosity/lanes-todo-demo/blob/master/spec/todo/views/HeaderSpec.coffee).
47
+ ## Listing
48
+ This component is a bit more complex. It's split into two components, a parent which handles toggling all todo's between being complete and pending, and a collection of task components that model each individual task. [Listing](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/components/Listing.cjsx)
46
49
 
47
- ## Listing View
48
- This view is a bit more complex. It has a parent view which handles toggling all todo's between being complete and pending, and a collection of subviews that model each individual task. [ListingView](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Listing.coffee)
50
+ Each Task component is responsible for handling it's own editing state and saving value to it's model. [TaskComponent](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/components/Task.cjsx)
49
51
 
50
- Each TaskView is responsible for handling it's own editing state and saving value to it's model.
52
+ ## Footer
53
+ The only action this component takes is to delete any tasks that are marked as complete when the "Clear Completed" button is clicked. It also displays quite a few values from our TasksSummary. Lane's data-bindings make these easy to wire up. [Footer](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/components/Footer.cjsx)
51
54
 
52
- ## Footer View
53
- The only action this view takes is to delete any tasks that are marked as complete when the "Clear Completed" button is clicked. It also displays quite a few values from our TasksSummary. Lane's declarative bindings make these easy to wire up. [FooterView](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Footer.coffee)
54
-
55
- You might notice that Lanes makes it super easy to batch update or delete a collection. The footer simply calls destroyAll on the "completed" sub-collection provided by the TaskSummary. Since that sub-collection filters the main collection to only contain "completed" tasks, it's safe to just destroy all the model's in one go. It's so easy in fact that the FooterView demonstrates an alternative use of events. The function is directly given to the "events" property, rather than a method reference. [Save Call](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/views/Footer.coffee#L27)
55
+ You might notice that Lanes makes it super easy to batch update or delete a collection. The footer simply calls destroyAll on the "completed" sub-collection provided by the TaskSummary. Since that sub-collection filters the main collection to only contain "completed" tasks, it's safe to just destroy all the model's in one go.
56
56
 
57
57
  # Routing
58
58
 
59
- For a simple app like the this one, it's easiest to just allow the URL change to trigger what the filtered collection is displaying. We set that up when the screen is initialized. [Routing](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/Router.coffee)
59
+ For a simple app like the this one, it's easiest to just allow the URL change to trigger what the filtered collection is displaying. [Routing](https://github.com/argosity/lanes-todo-demo/blob/master/client/todo/Routes.cjsx)
60
60
 
61
61
  # Deploying
62
62
 
@@ -67,5 +67,3 @@ Simply commit the source and add a remote per Heroku's instructions: [https://de
67
67
  When you `git push heroku`, Heroku will notice that Lanes uses sprockets and will automatically run `rake assets:precompile`, and then run the application using the puma webserver.
68
68
 
69
69
  On first deploy and when your db schema has changed, you will have to provision and migrate the database on Heroku by running: `heroku run rake db:migrate`
70
-
71
-
data/lanes.gemspec CHANGED
@@ -25,19 +25,23 @@ Gem::Specification.new do |spec|
25
25
  spec.required_ruby_version = ">= 2.0"
26
26
 
27
27
  spec.add_dependency "activerecord", "~> 4.2"
28
+ spec.add_dependency "activejob", "~> 4.2"
29
+ spec.add_dependency "jobba", "~> 1.4"
30
+
31
+ spec.add_dependency "resque", "~> 1.25"
28
32
  spec.add_dependency "pg", "~> 0.17"
29
33
  spec.add_dependency "sinatra", "~> 1.4"
30
34
  spec.add_dependency "bcrypt", "~> 3.1"
31
35
  spec.add_dependency "oj", "~> 2.1"
32
- spec.add_dependency "message_bus", "~> 1.0"
33
- spec.add_dependency "rack_csrf", "~> 2.5"
34
- spec.add_dependency "sprockets", "~> 2.0"
36
+ spec.add_dependency "message_bus", "2.0.0.beta.6"
37
+ spec.add_dependency "rack-protection", "~> 1.5"
38
+ spec.add_dependency "sprockets", "~> 3.0"
35
39
  spec.add_dependency "coffee-script", "~> 2.3"
36
40
  spec.add_dependency "coffee-react", "~> 3.0"
37
41
  spec.add_dependency "execjs", "~> 2.2"
38
42
  spec.add_dependency "thor", "~> 0.19"
39
43
  spec.add_dependency "sass", "~> 3.4"
40
- spec.add_dependency "sprockets-helpers", "~> 1.1"
44
+ spec.add_dependency "sprockets-helpers", "~> 1.2"
41
45
  spec.add_dependency "compass-import-once", "~> 1.0"
42
46
  spec.add_dependency "guard", "~> 2.0"
43
47
  spec.add_dependency "hashie", "~> 3.3"
@@ -45,13 +49,18 @@ Gem::Specification.new do |spec|
45
49
  spec.add_dependency "minitest-around", "~> 0.2"
46
50
  spec.add_dependency "mocha", "~> 1.1"
47
51
  spec.add_dependency "guard-minitest", "~> 2.3"
48
- spec.add_dependency "yui-compressor", "~> 0.12"
49
- spec.add_dependency "closure-compiler", "~> 1.1"
52
+
53
+ spec.add_dependency "uglifier", "~> 2.7"
50
54
  spec.add_dependency "guard-jasmine", "~> 2.0"
51
55
  spec.add_dependency "rake", "~> 10.0"
52
56
  spec.add_dependency "jasmine-core", "~> 2.0"
53
57
  spec.add_dependency "require_all", "~> 1.3"
54
58
  spec.add_dependency "sanitize", "~> 3.0"
59
+ spec.add_dependency "carrierwave", "~> 0.10.0"
60
+ spec.add_dependency "fog", "~> 1.37.0"
61
+ spec.add_dependency "mini_magick", "~> 4.3.6"
62
+ spec.add_dependency "fastimage", "~> 1.8.1"
63
+
55
64
  spec.add_development_dependency "bundler", "~> 1.5"
56
65
  spec.add_development_dependency "growl", "~> 1.0"
57
66
  spec.add_development_dependency "diffy", "~> 3.0"
data/lib/lanes.rb CHANGED
@@ -3,18 +3,20 @@ require 'active_record'
3
3
  require_relative "lanes/version"
4
4
  require_relative "lanes/environment"
5
5
  require_relative "lanes/configuration"
6
+ require_relative "lanes/redis"
6
7
  require_relative "lanes/logger"
7
8
  if defined?(::Rails)
8
9
  require_relative "lanes/rails_engine"
9
10
  end
10
11
  require_relative "lanes/db"
11
-
12
12
  require_relative "lanes/strings"
13
13
  require_relative "lanes/numbers"
14
14
  require_relative "lanes/concerns/all"
15
15
  require_relative "lanes/validators/all"
16
16
  require_relative "lanes/model"
17
-
17
+ require_relative "lanes/system_settings"
18
18
  require_relative "lanes/components"
19
19
  require_relative "lanes/extension"
20
20
  require_relative "lanes/screen"
21
+ require_relative "lanes/job"
22
+ require_relative "lanes/job/failure_logger"
@@ -1,7 +1,9 @@
1
1
  module Lanes
2
- API.routes.draw do
2
+ Lanes::API.routes.for_extension 'lanes-access' do
3
3
 
4
- post "/user-session.json" do
4
+ resources User
5
+
6
+ post "user-session.json" do
5
7
  wrap_reply do
6
8
  user = User.where(login: data['login']).first
7
9
  Lanes.logger.warn "Found User: #{user}"
@@ -15,7 +17,7 @@ module Lanes
15
17
  end
16
18
  end
17
19
 
18
- delete "/user-session/:id.json" do
20
+ delete "user-session/:id.json" do
19
21
  session.destroy
20
22
  wrap_reply do
21
23
  { success: true, message: "Logout succeeded", data: {} }
@@ -5,6 +5,7 @@ Lanes::Screen.define_group "system-settings" do | group |
5
5
  end
6
6
 
7
7
  Lanes::Screen.for_extension 'access' do | screens |
8
+
8
9
  screens.define "user-management" do | screen |
9
10
  screen.title = "User Management"
10
11
  screen.description = "Add/Remove/Modify User Accounts"
@@ -4,7 +4,7 @@ class CreateLanesUsers < ActiveRecord::Migration
4
4
  t.string :login, :name, :email, null: false
5
5
  t.string :password_digest, null: false
6
6
  t.string "role_names", array: true, null:false, default: []
7
- t.hstore "options", null: false, default: {}
7
+ t.jsonb "options", null: false, default: {}
8
8
  t.timestamps null:false
9
9
  end
10
10
  add_index :lanes_users, :role_names, using: 'gin'
@@ -16,7 +16,7 @@ module Lanes
16
16
 
17
17
  def workspace_data
18
18
  my_data = attributes.slice('id','login','name','email','created_at',
19
- 'created_by','updated_at','updated_by','role_names')
19
+ 'created_by','updated_at','updated_by','role_names', 'options')
20
20
  { user: my_data, access: Access.for_user(self) }
21
21
  end
22
22
 
data/lib/lanes/api.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require_relative '../lanes'
2
2
  require_relative 'api/request_wrapper'
3
3
  require_relative 'api/error_formatter'
4
+ require_relative 'api/formatted_reply'
4
5
  require_relative 'api/controller'
5
6
  require_relative 'api/root'
6
7
 
@@ -8,5 +9,5 @@ Lanes.config.get(:environment) do
8
9
  require_relative("api/test_specs") unless Lanes.env.production?
9
10
  end
10
11
 
11
-
12
+ require_relative "api/handlers/file.rb"
12
13
  require_relative 'api/default_routes'
@@ -22,6 +22,7 @@ module Lanes
22
22
  class Controller
23
23
 
24
24
  attr_reader :model, :user, :params, :data
25
+ include FormattedReply
25
26
 
26
27
  def initialize(model, authentication, params, data={})
27
28
  @user = authentication.current_user
@@ -33,19 +34,18 @@ module Lanes
33
34
  def perform_retrieval
34
35
  query = build_query
35
36
  options = build_reply_options
36
- options[:total_count] = query.dup.count if should_include_total_count?
37
37
  query = add_modifiers_to_query(query)
38
- Lanes.logger.warn "ID: #{params[:id]}"
38
+ options[:total_count] = query.dup.unscope(:select).count if should_include_total_count?
39
39
  if params[:id]
40
40
  query = query.first!
41
41
  end
42
- build_reply(query, :retrieve, options)
42
+ std_api_reply(:retrieve, query, options)
43
43
  end
44
44
 
45
45
  def perform_creation
46
46
  record = model.from_attribute_data(data, user)
47
47
  options = build_reply_options.merge(success: record.save)
48
- build_reply(record, :create, options)
48
+ std_api_reply(:create, record, options)
49
49
  end
50
50
 
51
51
  def perform_update
@@ -64,12 +64,12 @@ module Lanes
64
64
  end
65
65
  end
66
66
 
67
- protected
67
+ protected
68
68
 
69
69
  def perform_single_destroy
70
70
  record = model.find(params[:id])
71
71
  record.destroy
72
- build_reply(record, :destroy, {})
72
+ std_api_reply(:destroy, record, {})
73
73
  end
74
74
 
75
75
  def perform_multiple_destroy
@@ -81,7 +81,7 @@ module Lanes
81
81
  end
82
82
  end
83
83
  options = build_reply_options.merge(success: success)
84
- build_reply(records, :destroy, options)
84
+ std_api_reply(:destroy, records, options)
85
85
  end
86
86
 
87
87
  def perform_multiple_updates
@@ -95,13 +95,13 @@ module Lanes
95
95
  end
96
96
  end
97
97
  options = build_reply_options.merge(success: success)
98
- build_reply(records, :update, options)
98
+ std_api_reply(:update, records, options)
99
99
  end
100
100
 
101
101
  def perform_single_update(record)
102
102
  record.set_attribute_data(data, user)
103
103
  options = build_reply_options.merge(success: record.save)
104
- build_reply(record, :update, options)
104
+ std_api_reply(:update, record, options)
105
105
  end
106
106
 
107
107
  # @return [Array<String>] The fields to include in query. May represent either an attribute or a method
@@ -112,7 +112,7 @@ module Lanes
112
112
  params[:df] == 'array'
113
113
  end
114
114
  def query_scopes
115
- params[:w]
115
+ [*params[:w]]
116
116
  end
117
117
  def query_params
118
118
  params[:q]
@@ -131,51 +131,6 @@ module Lanes
131
131
  params[:s]
132
132
  end
133
133
 
134
- # json methods
135
- # constructs a Hash with success, messages, and data keys and
136
- # populates them appropriately
137
-
138
- def build_reply(query, type, options)
139
- success = options[:success].nil? ? true : options[:success]
140
- json = {}
141
- if query.is_a?(ActiveRecord::Base) && query.errors.any?
142
- json[:errors] = {}
143
- success = false
144
- query.errors.each{ | attr, message |
145
- json[:errors][attr] = message
146
- }
147
- end
148
- if options[:total_count]
149
- json[:total] = options.delete(:total_count)
150
- end
151
- json.merge(
152
- success: success,
153
- message: options[:messsage] || json_status_str(query, type.to_s.capitalize, success),
154
- data: success ? records_for_reply(query, type, options) : []
155
- )
156
- end
157
-
158
-
159
- # @return Array<Array> returns either an array of fields
160
- def records_for_reply(query, type, options)
161
- return [] if :destroy == type
162
- if reply_with_array?
163
- query.pluck( *requested_fields )
164
- else
165
- query.as_json(options)
166
- end
167
- end
168
-
169
- def json_status_str(record, type, success)
170
- if success
171
- return type + " succeeded"
172
- elsif record
173
- return type + " failed: " + record.errors.full_messages.join("; ")
174
- else
175
- return "Record not found"
176
- end
177
- end
178
-
179
134
  # reply options
180
135
 
181
136
  # Should the result include the total number of available records
@@ -195,6 +150,7 @@ module Lanes
195
150
  if requested_fields.any?
196
151
  options[:methods] = requested_fields.select{|f| model.has_exported_method?(f,user) }
197
152
  end
153
+ options[:format] = reply_with_array? ? 'array' : 'object'
198
154
  options
199
155
  end
200
156
 
@@ -233,9 +189,6 @@ module Lanes
233
189
  if params[:nested_attribute]
234
190
  query = query.where(params[:nested_attribute])
235
191
  end
236
- if query_scopes.present?
237
- query = add_scope_to_query(query)
238
- end
239
192
  if query_params.present?
240
193
  query = add_params_to_query(query)
241
194
  end
@@ -243,9 +196,11 @@ module Lanes
243
196
  end
244
197
 
245
198
  def add_modifiers_to_query(query)
199
+ if query_scopes.present?
200
+ query = add_scope_to_query(query)
201
+ end
246
202
  query = query.limit(query_limit_size)
247
203
  query = query.offset(query_offset.to_i) if query_offset.present?
248
-
249
204
  if include_associations.any?
250
205
  allowed_includes = include_associations.each_with_object([]) do |desired, results|
251
206
  if desired.is_a?(Hash)
@@ -262,11 +217,12 @@ module Lanes
262
217
  end
263
218
  if sort_order.present?
264
219
  sort_order.each do | fld, dir |
265
- query = query.order( fld.gsub(/[^\w|^\.]/,'') + ' ' + ( ( 'asc' == dir.downcase ) ? 'ASC' : 'DESC' ) )
220
+ query = model.append_sort_to_query(
221
+ query, fld, dir.downcase.to_sym
222
+ )
266
223
  end
267
224
  end
268
225
  query
269
-
270
226
  end
271
227
 
272
228
 
@@ -288,12 +244,13 @@ module Lanes
288
244
  def add_params_to_query(query)
289
245
  query_params.each do | field, value |
290
246
  next unless ( field = convert_field_to_arel(field) )
291
- condition = if value.is_a?(Hash) && value.has_key?('value')
292
- api_op_string_to_arel_predicate(field, value['op'], value['value'])
293
- else
294
- api_op_string_to_arel_predicate(field, nil, value)
295
- end
296
- query = query.where(condition)
247
+ if value.is_a?(Hash) && value.has_key?('value')
248
+ op = value['op']
249
+ value = value['value']
250
+ end
251
+ query = query.where(
252
+ field_to_predicate(field, value, op)
253
+ )
297
254
  end
298
255
  query
299
256
  end
@@ -306,20 +263,24 @@ module Lanes
306
263
  else
307
264
  nil
308
265
  end
309
- else
266
+ elsif model.attribute_method?(field)
310
267
  model.arel_table[field]
268
+ else
269
+ Arel::Nodes::SqlLiteral.new(
270
+ model.connection.quote_column_name(field)
271
+ )
311
272
  end
312
273
  end
313
274
 
314
275
  # complete list: https://github.com/rails/arel/blob/master/lib/arel/predications.rb
315
- def api_op_string_to_arel_predicate( field, op, value )
276
+ def field_to_predicate( field, value, op = nil )
316
277
  case op
317
- when 'eq' then field.eq(value)
278
+ when nil, 'eq' then field.eq(value)
279
+ when 'like' then field.matches( value )
318
280
  when 'ne' then field.not_eq(value)
319
281
  when 'lt' then field.lt(value)
320
282
  when ( op=='in' && value=~/.*:.*/ ) then field.in( Range.new( *value.split(':') ) )
321
283
  when 'gt' then field.gt(value)
322
- when 'like' then field.matches( value )
323
284
  else
324
285
  value =~ /%/ ? field.matches( value ) : field.eq( value )
325
286
  end