lanes 0.0.1

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 (391) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.jshintrc +3 -0
  4. data/Gemfile +9 -0
  5. data/Guardfile +15 -0
  6. data/LICENSE-MIT.txt +21 -0
  7. data/README.md +15 -0
  8. data/Rakefile +74 -0
  9. data/bin/lanes +5 -0
  10. data/client/images/ajax-loader.gif +0 -0
  11. data/client/images/dataTables/Sorting icons.psd +0 -0
  12. data/client/images/dataTables/back_disabled.png +0 -0
  13. data/client/images/dataTables/back_enabled.png +0 -0
  14. data/client/images/dataTables/back_enabled_hover.png +0 -0
  15. data/client/images/dataTables/favicon.ico +0 -0
  16. data/client/images/dataTables/forward_disabled.png +0 -0
  17. data/client/images/dataTables/forward_enabled.png +0 -0
  18. data/client/images/dataTables/forward_enabled_hover.png +0 -0
  19. data/client/images/dataTables/loading-background.png +0 -0
  20. data/client/images/dataTables/sort_asc.png +0 -0
  21. data/client/images/dataTables/sort_asc_disabled.png +0 -0
  22. data/client/images/dataTables/sort_both.png +0 -0
  23. data/client/images/dataTables/sort_desc.png +0 -0
  24. data/client/images/dataTables/sort_desc_disabled.png +0 -0
  25. data/client/images/logo-sm.png +0 -0
  26. data/client/javascripts/component/Base.coffee +39 -0
  27. data/client/javascripts/component/ChoicesInput.coffee +47 -0
  28. data/client/javascripts/component/Grid.coffee +199 -0
  29. data/client/javascripts/component/ModalDialog.coffee +44 -0
  30. data/client/javascripts/component/PopOver.coffee +52 -0
  31. data/client/javascripts/component/RadioGroup.coffee +59 -0
  32. data/client/javascripts/component/RecordFinder.coffee +143 -0
  33. data/client/javascripts/component/SelectField.coffee +43 -0
  34. data/client/javascripts/component/TaggedField.coffee +27 -0
  35. data/client/javascripts/component/grid/Editor.coffee +65 -0
  36. data/client/javascripts/component/grid/PopOverEditor.coffee +29 -0
  37. data/client/javascripts/component/grid/RowEditor.coffee +31 -0
  38. data/client/javascripts/component/grid/popover-editor.html +18 -0
  39. data/client/javascripts/component/grid/row-editor.html +16 -0
  40. data/client/javascripts/component/grid.html +4 -0
  41. data/client/javascripts/component/index.js +5 -0
  42. data/client/javascripts/component/modal.html +17 -0
  43. data/client/javascripts/component/popover.html +5 -0
  44. data/client/javascripts/component/record-finder/clause.skr +35 -0
  45. data/client/javascripts/component/record-finder/dialog.skr +4 -0
  46. data/client/javascripts/component/record-finder/field.skr +8 -0
  47. data/client/javascripts/data/Bootstrap.coffee +8 -0
  48. data/client/javascripts/data/ChangeSet.coffee +50 -0
  49. data/client/javascripts/data/Collection.coffee +111 -0
  50. data/client/javascripts/data/Config.coffee +15 -0
  51. data/client/javascripts/data/Model.coffee +269 -0
  52. data/client/javascripts/data/PubSub.coffee +68 -0
  53. data/client/javascripts/data/Query.coffee +184 -0
  54. data/client/javascripts/data/Roles.coffee +91 -0
  55. data/client/javascripts/data/Screens.coffee +157 -0
  56. data/client/javascripts/data/Sync.coffee +62 -0
  57. data/client/javascripts/data/User.coffee +70 -0
  58. data/client/javascripts/data/index.js +7 -0
  59. data/client/javascripts/data/mixins/HasCodeField.coffee +13 -0
  60. data/client/javascripts/extension/Base.coffee +9 -0
  61. data/client/javascripts/extension/Extensions.coffee +17 -0
  62. data/client/javascripts/extension/GlAccounts.coffee +9 -0
  63. data/client/javascripts/extension/index.js +6 -0
  64. data/client/javascripts/extension/load.js.erb +3 -0
  65. data/client/javascripts/lanes-complete.js +3 -0
  66. data/client/javascripts/lanes-workspace.js +1 -0
  67. data/client/javascripts/lib/MakeBaseClass.coffee +55 -0
  68. data/client/javascripts/lib/ModuleSupport.coffee +22 -0
  69. data/client/javascripts/lib/Templates.coffee +47 -0
  70. data/client/javascripts/lib/create-namespace.js +0 -0
  71. data/client/javascripts/lib/debounce.coffee +15 -0
  72. data/client/javascripts/lib/defer.coffee +7 -0
  73. data/client/javascripts/lib/el.js +115 -0
  74. data/client/javascripts/lib/index.js +9 -0
  75. data/client/javascripts/lib/loader.coffee +95 -0
  76. data/client/javascripts/lib/namespace.coffee +9 -0
  77. data/client/javascripts/lib/noConflict.coffee +14 -0
  78. data/client/javascripts/lib/promise_helpers.coffee +4 -0
  79. data/client/javascripts/lib/results.coffee +15 -0
  80. data/client/javascripts/lib/underscore.inflection.js +210 -0
  81. data/client/javascripts/lib/utilFunctions.coffee +51 -0
  82. data/client/javascripts/plugins/ResizeSensor.js +144 -0
  83. data/client/javascripts/plugins/index.js +4 -0
  84. data/client/javascripts/plugins/overlay.coffee +41 -0
  85. data/client/javascripts/plugins/trigger.coffee +15 -0
  86. data/client/javascripts/vendor/bootstrap/affix.js +142 -0
  87. data/client/javascripts/vendor/bootstrap/alert.js +92 -0
  88. data/client/javascripts/vendor/bootstrap/button.js +110 -0
  89. data/client/javascripts/vendor/bootstrap/carousel.js +223 -0
  90. data/client/javascripts/vendor/bootstrap/collapse.js +170 -0
  91. data/client/javascripts/vendor/bootstrap/dropdown.js +151 -0
  92. data/client/javascripts/vendor/bootstrap/modal.js +280 -0
  93. data/client/javascripts/vendor/bootstrap/popover.js +113 -0
  94. data/client/javascripts/vendor/bootstrap/scrollspy.js +170 -0
  95. data/client/javascripts/vendor/bootstrap/tab.js +128 -0
  96. data/client/javascripts/vendor/bootstrap/tooltip.js +457 -0
  97. data/client/javascripts/vendor/bootstrap/transition.js +59 -0
  98. data/client/javascripts/vendor/dataTables/dataTables.bootstrap.js +156 -0
  99. data/client/javascripts/vendor/dataTables/dataTables.scroller.js +1185 -0
  100. data/client/javascripts/vendor/dataTables/datatables.responsive.js +666 -0
  101. data/client/javascripts/vendor/dataTables/index.js +2 -0
  102. data/client/javascripts/vendor/dataTables/jquery.dataTables.js +14380 -0
  103. data/client/javascripts/vendor/jquery-2.js +9190 -0
  104. data/client/javascripts/vendor/jquery.tap.js +401 -0
  105. data/client/javascripts/vendor/magicsuggest.js +1565 -0
  106. data/client/javascripts/vendor/message-bus.js +285 -0
  107. data/client/javascripts/vendor/modern-stack.js +14 -0
  108. data/client/javascripts/vendor/packaged.js +13769 -0
  109. data/client/javascripts/view/Assets.coffee +9 -0
  110. data/client/javascripts/view/Base.coffee +231 -0
  111. data/client/javascripts/view/FormBindings.coffee +98 -0
  112. data/client/javascripts/view/Functions.coffee +13 -0
  113. data/client/javascripts/view/Helpers.coffee +77 -0
  114. data/client/javascripts/view/InterfaceState.coffee +88 -0
  115. data/client/javascripts/view/Keys.coffee +59 -0
  116. data/client/javascripts/view/ModelObserver.coffee +31 -0
  117. data/client/javascripts/view/ModelUpdate.coffee +8 -0
  118. data/client/javascripts/view/PubSub.coffee +29 -0
  119. data/client/javascripts/view/RenderContext.coffee +32 -0
  120. data/client/javascripts/view/SaveNotify.coffee +30 -0
  121. data/client/javascripts/view/Screen.coffee +30 -0
  122. data/client/javascripts/view/TimedHighlight.coffee +38 -0
  123. data/client/javascripts/view/TimedMask.coffee +65 -0
  124. data/client/javascripts/view/_button.html +3 -0
  125. data/client/javascripts/view/_toolbar.html +27 -0
  126. data/client/javascripts/view/index.js +10 -0
  127. data/client/javascripts/view/mixins/ScreenChangeListener.coffee +43 -0
  128. data/client/javascripts/view/model-update.html +13 -0
  129. data/client/javascripts/view/screen-definitions.js.erb +7 -0
  130. data/client/javascripts/workspace/ActiveScreensSwitcher.coffee +117 -0
  131. data/client/javascripts/workspace/Instance.es6 +60 -0
  132. data/client/javascripts/workspace/Layout.coffee +18 -0
  133. data/client/javascripts/workspace/LoginDialog.coffee +33 -0
  134. data/client/javascripts/workspace/Navbar.coffee +44 -0
  135. data/client/javascripts/workspace/Pages.coffee +46 -0
  136. data/client/javascripts/workspace/ScreensMenu.coffee +126 -0
  137. data/client/javascripts/workspace/index.js +12 -0
  138. data/client/javascripts/workspace/layout.html +4 -0
  139. data/client/javascripts/workspace/login-dialog.html +16 -0
  140. data/client/javascripts/workspace/menu.html +356 -0
  141. data/client/javascripts/workspace/menu_toggle.html +9 -0
  142. data/client/javascripts/workspace/navbar.html +19 -0
  143. data/client/javascripts/workspace/pages.html +6 -0
  144. data/client/javascripts/workspace/screens-menu.html +11 -0
  145. data/client/javascripts/workspace/screens-switcher.html +7 -0
  146. data/client/javascripts/workspace/tab.html +0 -0
  147. data/client/screens/user-management/UserEditScreen.coffee +21 -0
  148. data/client/screens/user-management/UserManagement.coffee +24 -0
  149. data/client/screens/user-management/grid-popover-editor.html +33 -0
  150. data/client/screens/user-management/index.css +4 -0
  151. data/client/screens/user-management/index.js +2 -0
  152. data/client/screens/user-management/user-management-styles.scss +7 -0
  153. data/client/screens/user-management/user-management.html +8 -0
  154. data/client/stylesheets/compoonents/all.scss +6 -0
  155. data/client/stylesheets/compoonents/changes-notification.scss +44 -0
  156. data/client/stylesheets/compoonents/grid-editors.scss +65 -0
  157. data/client/stylesheets/compoonents/grid.scss +301 -0
  158. data/client/stylesheets/compoonents/modal-dialog.scss +23 -0
  159. data/client/stylesheets/compoonents/record-finder.scss +71 -0
  160. data/client/stylesheets/compoonents/suggest.scss +266 -0
  161. data/client/stylesheets/fonts/icomoon.eot +0 -0
  162. data/client/stylesheets/fonts/icomoon.svg +160 -0
  163. data/client/stylesheets/fonts/icomoon.ttf +0 -0
  164. data/client/stylesheets/fonts/icomoon.woff +0 -0
  165. data/client/stylesheets/fonts/selection.json +3565 -0
  166. data/client/stylesheets/fonts/style.css +451 -0
  167. data/client/stylesheets/fonts.scss +38 -0
  168. data/client/stylesheets/forms.scss +75 -0
  169. data/client/stylesheets/index.css +4 -0
  170. data/client/stylesheets/keybindings.scss +6 -0
  171. data/client/stylesheets/lanes-workspace.scss +17 -0
  172. data/client/stylesheets/layout.scss +272 -0
  173. data/client/stylesheets/plugins/all.scss +2 -0
  174. data/client/stylesheets/plugins/overlay.scss +63 -0
  175. data/client/stylesheets/plugins/resize-sensor.scss +24 -0
  176. data/client/stylesheets/screens.scss +66 -0
  177. data/client/stylesheets/tabs.scss +148 -0
  178. data/client/stylesheets/vendor/bootstrap/_alerts.scss +68 -0
  179. data/client/stylesheets/vendor/bootstrap/_badges.scss +57 -0
  180. data/client/stylesheets/vendor/bootstrap/_breadcrumbs.scss +26 -0
  181. data/client/stylesheets/vendor/bootstrap/_button-groups.scss +240 -0
  182. data/client/stylesheets/vendor/bootstrap/_buttons.scss +157 -0
  183. data/client/stylesheets/vendor/bootstrap/_carousel.scss +243 -0
  184. data/client/stylesheets/vendor/bootstrap/_close.scss +35 -0
  185. data/client/stylesheets/vendor/bootstrap/_code.scss +68 -0
  186. data/client/stylesheets/vendor/bootstrap/_component-animations.scss +35 -0
  187. data/client/stylesheets/vendor/bootstrap/_dropdowns.scss +215 -0
  188. data/client/stylesheets/vendor/bootstrap/_forms.scss +538 -0
  189. data/client/stylesheets/vendor/bootstrap/_glyphicons.scss +237 -0
  190. data/client/stylesheets/vendor/bootstrap/_grid.scss +84 -0
  191. data/client/stylesheets/vendor/bootstrap/_input-groups.scss +166 -0
  192. data/client/stylesheets/vendor/bootstrap/_jumbotron.scss +48 -0
  193. data/client/stylesheets/vendor/bootstrap/_labels.scss +66 -0
  194. data/client/stylesheets/vendor/bootstrap/_list-group.scss +132 -0
  195. data/client/stylesheets/vendor/bootstrap/_media.scss +56 -0
  196. data/client/stylesheets/vendor/bootstrap/_mixins.scss +39 -0
  197. data/client/stylesheets/vendor/bootstrap/_modals.scss +150 -0
  198. data/client/stylesheets/vendor/bootstrap/_navbar.scss +659 -0
  199. data/client/stylesheets/vendor/bootstrap/_navs.scss +242 -0
  200. data/client/stylesheets/vendor/bootstrap/_normalize.scss +425 -0
  201. data/client/stylesheets/vendor/bootstrap/_pager.scss +55 -0
  202. data/client/stylesheets/vendor/bootstrap/_pagination.scss +88 -0
  203. data/client/stylesheets/vendor/bootstrap/_panels.scss +243 -0
  204. data/client/stylesheets/vendor/bootstrap/_popovers.scss +133 -0
  205. data/client/stylesheets/vendor/bootstrap/_print.scss +101 -0
  206. data/client/stylesheets/vendor/bootstrap/_progress-bars.scss +105 -0
  207. data/client/stylesheets/vendor/bootstrap/_responsive-embed.scss +34 -0
  208. data/client/stylesheets/vendor/bootstrap/_responsive-utilities.scss +174 -0
  209. data/client/stylesheets/vendor/bootstrap/_scaffolding.scss +150 -0
  210. data/client/stylesheets/vendor/bootstrap/_tables.scss +233 -0
  211. data/client/stylesheets/vendor/bootstrap/_theme.scss +258 -0
  212. data/client/stylesheets/vendor/bootstrap/_thumbnails.scss +38 -0
  213. data/client/stylesheets/vendor/bootstrap/_tooltip.scss +95 -0
  214. data/client/stylesheets/vendor/bootstrap/_type.scss +304 -0
  215. data/client/stylesheets/vendor/bootstrap/_utilities.scss +57 -0
  216. data/client/stylesheets/vendor/bootstrap/_variables.scss +850 -0
  217. data/client/stylesheets/vendor/bootstrap/_wells.scss +29 -0
  218. data/client/stylesheets/vendor/bootstrap/bootstrap.scss +50 -0
  219. data/client/stylesheets/vendor/bootstrap/mixins/_alerts.scss +14 -0
  220. data/client/stylesheets/vendor/bootstrap/mixins/_background-variant.scss +11 -0
  221. data/client/stylesheets/vendor/bootstrap/mixins/_border-radius.scss +18 -0
  222. data/client/stylesheets/vendor/bootstrap/mixins/_buttons.scss +50 -0
  223. data/client/stylesheets/vendor/bootstrap/mixins/_center-block.scss +7 -0
  224. data/client/stylesheets/vendor/bootstrap/mixins/_clearfix.scss +22 -0
  225. data/client/stylesheets/vendor/bootstrap/mixins/_forms.scss +84 -0
  226. data/client/stylesheets/vendor/bootstrap/mixins/_gradients.scss +58 -0
  227. data/client/stylesheets/vendor/bootstrap/mixins/_grid-framework.scss +81 -0
  228. data/client/stylesheets/vendor/bootstrap/mixins/_grid.scss +122 -0
  229. data/client/stylesheets/vendor/bootstrap/mixins/_hide-text.scss +21 -0
  230. data/client/stylesheets/vendor/bootstrap/mixins/_image.scss +34 -0
  231. data/client/stylesheets/vendor/bootstrap/mixins/_labels.scss +12 -0
  232. data/client/stylesheets/vendor/bootstrap/mixins/_list-group.scss +31 -0
  233. data/client/stylesheets/vendor/bootstrap/mixins/_nav-divider.scss +10 -0
  234. data/client/stylesheets/vendor/bootstrap/mixins/_nav-vertical-align.scss +9 -0
  235. data/client/stylesheets/vendor/bootstrap/mixins/_opacity.scss +8 -0
  236. data/client/stylesheets/vendor/bootstrap/mixins/_pagination.scss +23 -0
  237. data/client/stylesheets/vendor/bootstrap/mixins/_panels.scss +24 -0
  238. data/client/stylesheets/vendor/bootstrap/mixins/_progress-bar.scss +10 -0
  239. data/client/stylesheets/vendor/bootstrap/mixins/_reset-filter.scss +8 -0
  240. data/client/stylesheets/vendor/bootstrap/mixins/_resize.scss +6 -0
  241. data/client/stylesheets/vendor/bootstrap/mixins/_responsive-visibility.scss +21 -0
  242. data/client/stylesheets/vendor/bootstrap/mixins/_size.scss +10 -0
  243. data/client/stylesheets/vendor/bootstrap/mixins/_tab-focus.scss +9 -0
  244. data/client/stylesheets/vendor/bootstrap/mixins/_table-row.scss +28 -0
  245. data/client/stylesheets/vendor/bootstrap/mixins/_text-emphasis.scss +11 -0
  246. data/client/stylesheets/vendor/bootstrap/mixins/_text-overflow.scss +8 -0
  247. data/client/stylesheets/vendor/bootstrap/mixins/_vendor-prefixes.scss +219 -0
  248. data/client/stylesheets/vendor/bootstrap-custom-grid.scss +85 -0
  249. data/client/stylesheets/vendor/bootstrap-custom-modals.scss +150 -0
  250. data/client/stylesheets/vendor/bootstrap.scss +69 -0
  251. data/client/stylesheets/vendor/dataTables.scss +4 -0
  252. data/config/database.yml +9 -0
  253. data/config/puma.rb +7 -0
  254. data/config.ru +4 -0
  255. data/db/migrate/20140615031600_create_hip_users.rb +17 -0
  256. data/db/seed.rb +37 -0
  257. data/foo/Gemfile +5 -0
  258. data/foo/Guardfile +13 -0
  259. data/foo/foo/Gemfile +5 -0
  260. data/foo/foo/lib/foo.rb +7 -0
  261. data/foo/lib/foo/version.rb +3 -0
  262. data/foo/lib/foo.rb +8 -0
  263. data/lanes.gemspec +54 -0
  264. data/lib/generators/lanes/migrations/install_generator.rb +42 -0
  265. data/lib/lanes/access/locked_fields.rb +43 -0
  266. data/lib/lanes/access/role.rb +58 -0
  267. data/lib/lanes/access/role_collection.rb +75 -0
  268. data/lib/lanes/access/roles/administrator.rb +25 -0
  269. data/lib/lanes/access/roles/support.rb +13 -0
  270. data/lib/lanes/access/user_maint_screen.rb +32 -0
  271. data/lib/lanes/access.rb +50 -0
  272. data/lib/lanes/api/asset_pipeline.rb +59 -0
  273. data/lib/lanes/api/authentication_helper.rb +21 -0
  274. data/lib/lanes/api/authentication_provider.rb +45 -0
  275. data/lib/lanes/api/controller.rb +290 -0
  276. data/lib/lanes/api/default_routes.rb +35 -0
  277. data/lib/lanes/api/eco.js +516 -0
  278. data/lib/lanes/api/error_formatter.rb +37 -0
  279. data/lib/lanes/api/helper_methods.rb +32 -0
  280. data/lib/lanes/api/javascript_processor.rb +116 -0
  281. data/lib/lanes/api/pub_sub.rb +33 -0
  282. data/lib/lanes/api/request_wrapper.rb +42 -0
  283. data/lib/lanes/api/root.rb +103 -0
  284. data/lib/lanes/api/skr_templates.rb +60 -0
  285. data/lib/lanes/api/test_specs.rb +59 -0
  286. data/lib/lanes/api/updates.rb +38 -0
  287. data/lib/lanes/api.rb +27 -0
  288. data/lib/lanes/cli.rb +13 -0
  289. data/lib/lanes/concerns/all.rb +16 -0
  290. data/lib/lanes/concerns/api_path.rb +21 -0
  291. data/lib/lanes/concerns/association_extensions.rb +85 -0
  292. data/lib/lanes/concerns/attr_accessor_with_default.rb +62 -0
  293. data/lib/lanes/concerns/code_identifier.rb +43 -0
  294. data/lib/lanes/concerns/export_associations.rb +52 -0
  295. data/lib/lanes/concerns/export_join_tables.rb +39 -0
  296. data/lib/lanes/concerns/export_methods.rb +104 -0
  297. data/lib/lanes/concerns/export_scope.rb +66 -0
  298. data/lib/lanes/concerns/exported_limit_evaluator.rb +17 -0
  299. data/lib/lanes/concerns/immutable_model.rb +32 -0
  300. data/lib/lanes/concerns/locked_fields.rb +84 -0
  301. data/lib/lanes/concerns/pub_sub.rb +105 -0
  302. data/lib/lanes/concerns/queries.rb +20 -0
  303. data/lib/lanes/concerns/random_hash_code.rb +40 -0
  304. data/lib/lanes/concerns/sanitize_api_data.rb +15 -0
  305. data/lib/lanes/concerns/set_attribute_data.rb +154 -0
  306. data/lib/lanes/concerns/track_modifications.rb +51 -0
  307. data/lib/lanes/concerns/visible_id_identifier.rb +53 -0
  308. data/lib/lanes/configuration.rb +85 -0
  309. data/lib/lanes/db/migration_helpers.rb +178 -0
  310. data/lib/lanes/db/migrations.rb +13 -0
  311. data/lib/lanes/db/seed.rb +27 -0
  312. data/lib/lanes/db.rb +86 -0
  313. data/lib/lanes/environment.rb +19 -0
  314. data/lib/lanes/extension.rb +72 -0
  315. data/lib/lanes/generators/app/Gemfile +5 -0
  316. data/lib/lanes/generators/app/Guardfile +13 -0
  317. data/lib/lanes/generators/app/Rakefile +9 -0
  318. data/lib/lanes/generators/app/config/database.yml +9 -0
  319. data/lib/lanes/generators/app/config.ru +4 -0
  320. data/lib/lanes/generators/app/lib/main_class/version.rb +3 -0
  321. data/lib/lanes/generators/app/lib/main_class.rb +8 -0
  322. data/lib/lanes/generators/app.rb +36 -0
  323. data/lib/lanes/guard_tasks.rb +44 -0
  324. data/lib/lanes/logger.rb +37 -0
  325. data/lib/lanes/model.rb +26 -0
  326. data/lib/lanes/numbers.rb +72 -0
  327. data/lib/lanes/rails_engine.rb +5 -0
  328. data/lib/lanes/screens.rb +126 -0
  329. data/lib/lanes/spec_asset_expander.rb +43 -0
  330. data/lib/lanes/strings.rb +56 -0
  331. data/lib/lanes/user.rb +127 -0
  332. data/lib/lanes/validators/all.rb +2 -0
  333. data/lib/lanes/validators/email.rb +17 -0
  334. data/lib/lanes/validators/set.rb +18 -0
  335. data/lib/lanes/version.rb +5 -0
  336. data/lib/lanes.rb +22 -0
  337. data/npm-build/README +1 -0
  338. data/npm-build/compile.coffee +15 -0
  339. data/npm-build/package.json +59 -0
  340. data/npm-build/shims/underscore.js +1416 -0
  341. data/npm-build/template.js +33 -0
  342. data/public/javascripts/jasmine_examples/Player.js +22 -0
  343. data/public/javascripts/jasmine_examples/Song.js +7 -0
  344. data/spec/api/javascript_processor_spec.rb +107 -0
  345. data/spec/api/user_spec.rb +52 -0
  346. data/spec/client/component/ChoicesInputSpec.coffee +12 -0
  347. data/spec/client/component/foo_spec.coffee +4 -0
  348. data/spec/client/foo_spec.js +0 -0
  349. data/spec/client/jasmine_examples/PlayerSpec.js +0 -0
  350. data/spec/client/support/jasmine.yml +128 -0
  351. data/spec/client/support/jasmine_helper.rb +15 -0
  352. data/spec/concerns/api_path_spec.rb +14 -0
  353. data/spec/concerns/association_extensions_spec.rb +30 -0
  354. data/spec/concerns/attr_accessor_with_default_spec.rb +57 -0
  355. data/spec/concerns/code_identifier_spec.rb +45 -0
  356. data/spec/concerns/export_associations_spec.rb +7 -0
  357. data/spec/concerns/export_methods_spec.rb +43 -0
  358. data/spec/concerns/export_scope_spec.rb +15 -0
  359. data/spec/concerns/exported_limits_spec.rb +47 -0
  360. data/spec/concerns/pub_sub_spec.rb +83 -0
  361. data/spec/concerns/set_attribute_data_spec.rb +66 -0
  362. data/spec/configuration_spec.rb +26 -0
  363. data/spec/fixtures/lanes/users.yml +13 -0
  364. data/spec/helpers/.gitkeep +0 -0
  365. data/spec/helpers/SpecHelper.js +18 -0
  366. data/spec/locked_fields_spec.rb +27 -0
  367. data/spec/numbers_spec.rb +26 -0
  368. data/spec/role_collection_spec.rb +19 -0
  369. data/spec/spec_helper.rb +163 -0
  370. data/spec/strings_spec.rb +41 -0
  371. data/spec/testing_models.rb +54 -0
  372. data/spec/user_role_spec.rb +7 -0
  373. data/spec/user_spec.rb +53 -0
  374. data/tasks/migrations.rake +22 -0
  375. data/tasks/publish.rake +8 -0
  376. data/views/index.erb +29 -0
  377. data/views/specs.erb +25 -0
  378. data/yard_ext/all.rb +9 -0
  379. data/yard_ext/code_identifier_handler.rb +33 -0
  380. data/yard_ext/concern_meta_methods.rb +60 -0
  381. data/yard_ext/config_options.rb +27 -0
  382. data/yard_ext/exported_scope.rb +4 -0
  383. data/yard_ext/immutable_handler.rb +17 -0
  384. data/yard_ext/json_attr_accessor.rb +22 -0
  385. data/yard_ext/locked_fields_handler.rb +21 -0
  386. data/yard_ext/templates/default/layout/html/layout.erb +20 -0
  387. data/yard_ext/templates/default/method_details/html/github_link.erb +1 -0
  388. data/yard_ext/templates/default/method_details/setup.rb +3 -0
  389. data/yard_ext/validators.rb +1 -0
  390. data/yard_ext/visible_id_handler.rb +38 -0
  391. metadata +772 -0
@@ -0,0 +1,33 @@
1
+ require "oj"
2
+
3
+ require_relative "updates"
4
+
5
+ require 'message_bus'
6
+
7
+ module Lanes
8
+ module API
9
+
10
+ class PubSub
11
+
12
+ def self.publish(channel, data)
13
+ MessageBus.publish channel, data #Oj.dump(data, mode: :compat)
14
+ end
15
+
16
+ def self.initialize
17
+ # Use OJ - it encodes dates properly as ISO 8601
18
+ # https://github.com/moment/moment/issues/1407
19
+ Oj.mimic_JSON()
20
+ # # Requiring json here seems to stop conflicts when requiring json in other files.
21
+ begin
22
+ require 'json'
23
+ rescue Exception
24
+ # ignore
25
+ end
26
+ ::MessageBus.redis_config = Lanes.config.redis
27
+ Updates.relay!
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,42 @@
1
+ module Sinatra
2
+
3
+ module RequestWrapper
4
+
5
+ def wrap_request(model, params, parent_attribute)
6
+
7
+ authentication = Lanes::API::AuthenticationProvider.new(
8
+ request_type: request.request_method,
9
+ session: session,
10
+ params: params
11
+ )
12
+
13
+ unless authentication.allowed_access_to?(model)
14
+ halt( 401, Oj.dump({
15
+ success:false, errors: {user: "Access Denied"}, message: authentication.error_message
16
+ }))
17
+ end
18
+ ::Lanes::User.scoped_to(authentication.current_user) do | user |
19
+ Lanes.logger.debug "User : #{user.id} (#{user.login})"
20
+ Lanes.logger.debug "Params : #{request.params}"
21
+
22
+ params[:nested_attribute] = Hash[ parent_attribute, params[parent_attribute] ] if parent_attribute
23
+
24
+ wrap_json_reply do
25
+ yield authentication
26
+ end
27
+
28
+ end
29
+ end
30
+
31
+ def wrap_json_reply
32
+ response = yield
33
+ if false == response[:success]
34
+ status(406)
35
+ end
36
+ Oj.dump(response, mode: :compat)
37
+ end
38
+
39
+ end
40
+
41
+
42
+ end
@@ -0,0 +1,103 @@
1
+ require 'sinatra'
2
+ require 'oj'
3
+ require 'rack/csrf'
4
+ require 'sprockets-helpers'
5
+ require 'message_bus'
6
+ require_relative 'asset_pipeline'
7
+ require_relative 'helper_methods'
8
+ require_relative 'pub_sub'
9
+
10
+ module Lanes
11
+ module API
12
+ class Root < Sinatra::Application
13
+ set :environment, Lanes.config.environment
14
+ Lanes.config.get(:environment) do | env |
15
+ set :environment, env
16
+ end
17
+ register AssetPipeline
18
+ helpers Sinatra::RequestWrapper
19
+ helpers HelperMethods
20
+ not_found do
21
+ Oj.dump({ message: "endpoint not found", success: false })
22
+ end
23
+ before do
24
+ content_type 'application/json'
25
+ end
26
+
27
+ use Rack::Session::Cookie, :key => 'lanes.session', :secret => Lanes.config.session_secret_key_base
28
+ use ActiveRecord::ConnectionAdapters::ConnectionManagement
29
+ use MessageBus::Rack::Middleware
30
+ error do
31
+ Lanes.logger.warn request.env['sinatra.error']#.backtrace
32
+ Oj.dump({
33
+ success: false,
34
+ errors: { exception: request.env['sinatra.error'].message },
35
+ message: request.env['sinatra.error'].message
36
+ })
37
+ end
38
+
39
+ configure do
40
+ set :views, Pathname.new(__FILE__).dirname.join("../../../views")
41
+ set :show_exceptions, false
42
+ DB.establish_connection
43
+ PubSub.initialize
44
+ # use Rack::Csrf, :skip=>['GET:/'], :raise => true
45
+ end
46
+
47
+ def self.build_route(model, options = {})
48
+
49
+ path = options[:path] || model.api_path
50
+ controller = options[:controller] || Lanes::API::Controller
51
+
52
+ parent_attribute = false
53
+ prefix = if options[:under]
54
+ parent_attribute = options[:parent_attribute] || options[:under].underscore.singularize+'_id'
55
+ else
56
+ ''
57
+ end
58
+
59
+
60
+ # index
61
+ get "#{prefix}/#{path}/?:id?.json" do
62
+ wrap_request(model, params, parent_attribute) do |authentication|
63
+ controller.new(model, authentication, params).perform_retrieval
64
+ end
65
+ end
66
+
67
+ # create
68
+ post "#{prefix}/#{path}.json" do
69
+ wrap_request(model, params, parent_attribute) do |authentication|
70
+ controller.new(model, authentication, params, data).perform_creation
71
+ end
72
+ end
73
+
74
+ unless options[:immutable]
75
+ patch "#{prefix}/#{path}/:id.json" do
76
+ perform_request(model, params, parent_attribute) do |authentication|
77
+ controller.new(model, authentication, params, data).perform_update
78
+ end
79
+ end
80
+
81
+ # update
82
+ put "#{prefix}/#{path}/:id.json" do
83
+ wrap_request(model, params, parent_attribute) do |authentication|
84
+ controller.new(model, authentication, params, data).perform_update
85
+ end
86
+ end
87
+
88
+ unless options[:indestructible]
89
+ # destroy
90
+ delete "#{prefix}/#{path}/:id.json" do
91
+ wrap_request(model, params, parent_attribute) do |authentication|
92
+ controller.new(model, authentication, params).perform_destroy
93
+ end
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,60 @@
1
+ # Stockor templates compiler
2
+ #
3
+ # This is a hacked together version of Sam Stephenson's Eco
4
+ # project for embedded coffeescript templates.
5
+ #
6
+ # Our version has the various helper functions pre-loaded
7
+ # so the templates themselves are smaller in size.
8
+ # and also includes a "h" helper namespace
9
+
10
+ require 'pathname'
11
+ require 'tilt'
12
+ module Skr
13
+ module Workspace
14
+
15
+ module EJSSource
16
+ class << self
17
+ def path
18
+ @path ||= Pathname.new(__FILE__).dirname.join('eco.js')
19
+ end
20
+
21
+ def contents
22
+ @contents ||= path.read
23
+ end
24
+
25
+ def combined_contents
26
+ [CoffeeScript::Source.contents, contents].join(";\n")
27
+ end
28
+
29
+ def context
30
+ @context ||= ExecJS.compile(combined_contents)
31
+ end
32
+
33
+ def compile(template)
34
+ template = template.read if template.respond_to?(:read)
35
+ context.call("eco.precompile", template, 'Skr.TemplateWrapper','Skr.View.Helpers')
36
+ end
37
+
38
+ end
39
+ end
40
+
41
+
42
+ class SkrTemplates < Tilt::Template
43
+
44
+ self.default_mime_type = 'application/javascript'
45
+
46
+ def evaluate(scope, locals, &block)
47
+ "Skr.Templates['#{scope.logical_path}']=" + EJSSource.compile(data)
48
+ end
49
+
50
+ def prepare;
51
+ # NOOP
52
+ end
53
+
54
+ def self.register(app)
55
+ app.assets.register_engine(".skr", self )
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,59 @@
1
+ require 'jasmine-core'
2
+
3
+ module Lanes
4
+ module API
5
+
6
+ class TestSpecs
7
+ cattr_accessor :current
8
+
9
+ def initialize(root)
10
+ @root = root
11
+ end
12
+
13
+ def css_files
14
+ urlpath Jasmine::Core.css_files
15
+ end
16
+
17
+ def js_files
18
+ urlpath(Jasmine::Core.js_files) +
19
+ urlpath(Jasmine::Core.boot_files) +
20
+ urlpath(spec_files("helpers")) +
21
+ urlpath(spec_files("client"))
22
+ end
23
+
24
+ private
25
+
26
+ def spec_files(path)
27
+ dir = @root.join("spec")
28
+ regex = /^#{dir}\//
29
+ Dir.glob( dir.join(path,"**/*.{coffee,js}") ).map do |file|
30
+ file.sub(regex,'').sub(/coffee$/,'js')
31
+ end
32
+ end
33
+
34
+ def urlpath(files)
35
+ files.map{ |file| "/spec/"+file }
36
+ end
37
+ end
38
+
39
+ Lanes.config.get(:specs_root) do | root |
40
+ TestSpecs.current = TestSpecs.new(root)
41
+ Root.sprockets.append_path(root.join("spec"))
42
+ end
43
+
44
+ Root.sprockets.append_path(Jasmine::Core.path)
45
+
46
+ Root.get '/spec' do
47
+ content_type 'text/html'
48
+ erb :specs, locals: { specs: TestSpecs.current }
49
+ end
50
+
51
+ Root.get "/spec/*" do |path|
52
+ env_sprockets = request.env.dup
53
+ env_sprockets['PATH_INFO'] = path
54
+ settings.sprockets.call env_sprockets
55
+ end
56
+
57
+
58
+ end
59
+ end
@@ -0,0 +1,38 @@
1
+ module Lanes
2
+
3
+ module API
4
+
5
+ module Updates
6
+ @relaying_messages = false
7
+
8
+ def self.user_info_for_change(model)
9
+ if model.has_attribute?(:updated_by_id)
10
+ model.updated_by.as_json(only:[:id,:name,:email])
11
+ else
12
+ {}
13
+ end
14
+ end
15
+
16
+ def self.relay!
17
+ if @relaying_messages
18
+ raise "Already relaying messages, calling relay! twice will lead to message duplication"
19
+ end
20
+ @relaying_messages = true
21
+ Lanes::Model.observe(:save) do |model|
22
+ if model.changes.any?
23
+ path = "/#{model.class.api_path}/#{model.id}"
24
+
25
+ Lanes::API::PubSub.publish(path, {
26
+ by: self.user_info_for_change(model),
27
+ update: model.changes
28
+ })
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+
37
+ end
38
+ end
data/lib/lanes/api.rb ADDED
@@ -0,0 +1,27 @@
1
+ require_relative 'api/authentication_helper'
2
+ require_relative 'api/authentication_provider'
3
+
4
+ require_relative 'api/request_wrapper'
5
+ require_relative 'api/error_formatter'
6
+ require_relative 'api/controller'
7
+ require_relative 'api/root'
8
+ require_relative 'api/default_routes'
9
+ # require_relative 'api/login_sessions_controller'
10
+ # require_relative 'api/users_controller'
11
+
12
+ require_relative "api/pub_sub"
13
+
14
+
15
+ Lanes.config.get(:environment) do
16
+ require_relative("api/test_specs") if Lanes.env.test?
17
+ end
18
+
19
+ # Lanes::API::Root.routes['GET'].each do |route|
20
+ # puts route[0]
21
+ # end
22
+
23
+ # require_relative "api/skr_templates"
24
+ # if defined?(::Rails)
25
+ # require_relative "api/engine"
26
+ # require_relative "api/route_helper"
27
+ # end
data/lib/lanes/cli.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'thor'
2
+ require_relative '../lanes'
3
+ require_relative 'generators/app'
4
+
5
+ module Lanes
6
+
7
+ class CLI < Thor
8
+
9
+ register Generators::App, 'new', 'new [NAME]', 'Creates a new Lanes based application'
10
+
11
+ end
12
+
13
+ end
@@ -0,0 +1,16 @@
1
+ require_relative "api_path"
2
+ require_relative "association_extensions"
3
+ require_relative "attr_accessor_with_default"
4
+ require_relative "code_identifier"
5
+ require_relative "export_associations"
6
+ require_relative "export_join_tables"
7
+ require_relative "export_methods"
8
+ require_relative "export_scope"
9
+ require_relative "immutable_model"
10
+ require_relative "set_attribute_data"
11
+ require_relative "locked_fields"
12
+ require_relative "pub_sub"
13
+ require_relative "queries"
14
+ require_relative "random_hash_code"
15
+ require_relative "sanitize_api_data"
16
+ require_relative "visible_id_identifier"
@@ -0,0 +1,21 @@
1
+ module Lanes::Concerns
2
+
3
+ # @see ClassMethods
4
+ module ApiPath
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+
9
+ def api_path
10
+ self.to_s.demodulize.pluralize.underscore.dasherize
11
+ end
12
+
13
+ def from_api_path(path)
14
+ name = path.underscore.camelize.singularize
15
+ name = "Lanes::#{name}" unless name=~/^Lanes/
16
+ name.safe_constantize
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,85 @@
1
+ module Lanes::Concerns
2
+
3
+
4
+ # Custom implentation of has_many and belongs_to
5
+ #
6
+ module AssociationExtensions
7
+
8
+ extend ActiveSupport::Concern
9
+
10
+ module ClassMethods
11
+
12
+ def has_one(name, scope = nil, options = {})
13
+ opts = extract_private_options( scope, options )
14
+ associations = super
15
+ handle_private_options( name, opts ) unless opts.empty?
16
+ associations
17
+ end
18
+
19
+ def belongs_to(name, scope = nil, options = {} )
20
+ opts = extract_private_options( scope, options )
21
+ associations = super
22
+ handle_private_options( name, opts ) unless opts.empty?
23
+ associations
24
+ end
25
+
26
+ def has_many(name, scope=nil,options={}, &extension )
27
+ opts = extract_private_options( scope, options )
28
+ associations = super
29
+ handle_private_options( name, opts ) unless opts.empty?
30
+ associations
31
+ end
32
+
33
+ private
34
+
35
+ def handle_private_options( name, opts )
36
+ association = reflect_on_association( name.to_sym )
37
+ setup_listeners( association, opts[:listen] ) if opts[:listen]
38
+ setup_association_export( association, opts[:export] ) if opts[:export]
39
+ end
40
+
41
+ def extract_private_options( scope, options )
42
+ if scope.is_a?(Hash)
43
+ scope.extract!( :export, :listen )
44
+ else
45
+ options.extract!( :export, :listen )
46
+ end
47
+ end
48
+
49
+ # This gets complex; We
50
+ # First setup proc's for each listener,
51
+ # then attempt to load the associations's class
52
+ # If that succeds, we're done, otherwise we add it
53
+ # to PubSub's pending queue
54
+ def setup_listeners( association, listeners )
55
+ targets = {}
56
+ if listeners.any? && association.options[:inverse_of].nil?
57
+ raise ArgumentError.new "Setting listener on #{name}##{association.name} " +
58
+ "but the association does not have " +
59
+ "an inverse_of specified."
60
+ end
61
+ listeners.each do | name, target |
62
+ targets[ name ] = Proc.new{ | record, *args |
63
+ record = record.send( association.inverse_of.name )
64
+ record.send( target, *( [record] + args ) ) if record
65
+ }
66
+ end
67
+ begin
68
+ klass = association.klass # This will throw if the class hasn't been loaded yet
69
+ targets.each{ | name, proc | klass._add_event_listener( name, proc ) }
70
+ rescue NameError
71
+ pending = PendingEventListeners.all[association.class_name.demodulize]
72
+ targets.each do | name, proc |
73
+ pending[name] << proc
74
+ end
75
+ end
76
+ end
77
+
78
+ def setup_association_export( association, options )
79
+ export_associations( association.name, options == true ? {} : options )
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ end
@@ -0,0 +1,62 @@
1
+ module Lanes::Concerns
2
+
3
+ # @see ClassMethods
4
+ module AttrAccessorWithDefault
5
+ extend ActiveSupport::Concern
6
+
7
+ module ClassMethods
8
+
9
+ # defines a attr_accessor with a default value
10
+ # @param name [ Symbol ] name of the attribute
11
+ # @param default [ Object, lambda, Proc ] if a value is given, be aware that it will be shared between instances
12
+ # @example
13
+ #
14
+ # Shared = Struct.new(:str)
15
+ # class AttrTestClass
16
+ # include AttrAccessorWithDefault
17
+ # attr_accessor_with_default :non_copying, ->{ Shared.new("a default string") }
18
+ # attr_accessor_with_default :shared, Shared.new("a default string")
19
+ # end
20
+ # a = AttrTestClass.new
21
+ # b = AttrTestClass.new
22
+ # a.non_copying.str #=> "a default string"
23
+ # a.non_copying.str = "new_string" #=> "new string"
24
+ # b.non_copying.str #=> "a default string"
25
+ #
26
+ # a.shared.str #=> "a default string"
27
+ # b.shared.str #=> "a default string"
28
+ # a.shared.str = "new string" #=> "new string"
29
+ # b.shared.str #=> "new string"
30
+
31
+ def attr_accessor_with_default( name, default=nil )
32
+ attr_writer name
33
+ attr_add_default_setting_method(name)
34
+ attr_reader_with_default( name, default )
35
+ end
36
+
37
+ def attr_add_default_setting_method(name)
38
+ module_eval do
39
+ define_singleton_method(name) do | value |
40
+ attr_reader_with_default( name, value )
41
+ end
42
+ end
43
+ end
44
+ def attr_reader_with_default( name, default )
45
+ module_eval do
46
+ define_method( name ) do
47
+ class << self; self; end.class_eval do
48
+ attr_reader( name )
49
+ end
50
+ if instance_variables.include? "@#{name}"
51
+ instance_variable_get( "@#{name}" )
52
+ else
53
+ instance_variable_set( "@#{name}", default.is_a?(Proc) ? default.call : default )
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+
62
+ end
@@ -0,0 +1,43 @@
1
+ module Lanes
2
+ module Concerns
3
+
4
+ # @see ClassMethods
5
+ module CodeIdentifier
6
+
7
+ extend ActiveSupport::Concern
8
+
9
+ # ### Code Identifier Concern
10
+ # This adds the {#has_code_identifier} class method
11
+ module ClassMethods
12
+
13
+ # A 2-10 character string that identifies an entity, such as a Customer, Vendor, or SKU.
14
+ # The code is often assigned by the user, but may also
15
+ # be auto-generated by {Lanes::Strings.code_identifier}
16
+ #
17
+ # @param max_length [Integer] how long the code is allowed to be
18
+ # @param from [Symbol], method to call for a string to base the code upon
19
+ def has_code_identifier( from: nil, max_length: 10 )
20
+
21
+ validates :code, :length=>2..max_length, :presence=>true, :uniqueness=>true
22
+
23
+ alias_attribute :record_identifier, :code
24
+
25
+ if from
26
+ before_validation(:on=>:create) do
27
+ source = self[from]
28
+ unless source.blank?
29
+ self.code ||= Lanes::Strings.code_identifier( source, length:max_length )
30
+ end
31
+ end
32
+ end
33
+
34
+ before_validation do
35
+ self.code = self.code.upcase unless self.code.blank?
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,52 @@
1
+ module Lanes::Concerns
2
+
3
+ # @see ClassMethods
4
+ module ExportAssociations
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :exported_associations
9
+ end
10
+
11
+ module ClassMethods
12
+ # Mark associations as exported, meaning they can be quered against and optionally written to
13
+ # @param associations [list of Symbols]
14
+ # @option options [Boolean] :writable should the associations accept nested attributes
15
+ # @option options [Boolean] :mandatory should the association be included with it's parent at all times?
16
+ # @option options [Symbol referring to a method, lambda] :limit restrict to Users for whom true is returned
17
+ def export_associations( *associations )
18
+ self.exported_associations ||= {}
19
+ associations.flatten!
20
+ options = associations.extract_options!
21
+ associations.each do | assoc_name |
22
+ self.exported_associations[ assoc_name.to_sym ] = options
23
+ if options[:writable]
24
+ accepts_nested_attributes_for( assoc_name, options.except(:writable, :optional) )
25
+ end
26
+ if false == options[:optional]
27
+ self.export_methods( *assoc_name, { :optional=>false })
28
+ end
29
+ end
30
+ end
31
+
32
+ # If the association is exported it may be queried against and it's data included
33
+ # along with the parent record. It may not be written to unless the :writable flag
34
+ # was set, in which case it'll be allowed by has_exported_association?
35
+ def has_exported_association?( association, user )
36
+ self.exported_associations &&
37
+ ( options = self.exported_associations[ association.to_sym ] ) &&
38
+ evaluate_export_limit( user, :association, association, options[:limit] )
39
+ end
40
+
41
+ # Does the association allow writes? True if the association has been exported
42
+ # and it accepts nested attributes
43
+ def has_exported_nested_attribute?( association, user )
44
+ self.nested_attributes_options[ association.to_sym ] &&
45
+ self.has_exported_association?( association, user )
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ end