lanes 0.1.2 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (399) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -0
  3. data/client/lanes/access/Extension.coffee +19 -0
  4. data/client/lanes/access/LoginDialog.coffee +47 -0
  5. data/client/lanes/access/Roles.coffee +88 -0
  6. data/client/lanes/access/User.coffee +72 -0
  7. data/client/lanes/access/index.js +5 -0
  8. data/client/lanes/access/login-dialog.html +16 -0
  9. data/client/lanes/access/screens/user-management/GridUserEditor.coffee +25 -0
  10. data/client/lanes/access/screens/user-management/UserManagement.coffee +24 -0
  11. data/client/lanes/access/screens/user-management/grid-popover-editor.html +33 -0
  12. data/client/lanes/access/screens/user-management/index.js +3 -0
  13. data/client/lanes/access/screens/user-management/index.scss +7 -0
  14. data/client/lanes/access/screens/user-management/screen.html +7 -0
  15. data/client/lanes/{components/enabled.scss.erb → access/styles.scss} +0 -0
  16. data/{lib/lanes/command/templates/client/components → client/lanes/access/views}/.gitkeep +0 -0
  17. data/client/lanes/components/Base.coffee +3 -4
  18. data/client/lanes/components/enabled.js.erb +2 -0
  19. data/client/lanes/components/grid/Editor.coffee +1 -1
  20. data/client/lanes/components/grid/Grid.coffee +26 -27
  21. data/client/lanes/components/grid/{_index.scss → styles.scss} +0 -0
  22. data/client/lanes/components/grid/template.html +1 -1
  23. data/client/lanes/components/grid/vendor/dataTables.scroller.js +119 -42
  24. data/client/lanes/components/grid/vendor/jquery.dataTables.js +984 -526
  25. data/client/lanes/components/modal/ModalDialog.coffee +25 -4
  26. data/client/lanes/components/modal/styles.scss +19 -0
  27. data/client/lanes/components/modal/template.html +2 -2
  28. data/client/lanes/components/multi-select/MultiSelect.coffee +46 -0
  29. data/client/lanes/components/popover/PopOver.coffee +1 -1
  30. data/client/lanes/components/popover/styles.scss +2 -0
  31. data/client/lanes/components/{radio_group → radio-group}/RadioGroup.coffee +12 -23
  32. data/client/lanes/components/radio-group/index.js +1 -0
  33. data/client/lanes/components/radio-group/styles.scss +1 -0
  34. data/client/lanes/components/record-finder/Clause.coffee +38 -0
  35. data/client/lanes/components/record-finder/Dialog.coffee +45 -0
  36. data/client/lanes/components/record-finder/RecordFinder.coffee +55 -0
  37. data/client/lanes/components/{record_finder/clause.skr → record-finder/clause.html} +7 -5
  38. data/client/lanes/components/record-finder/config.json +3 -0
  39. data/client/lanes/components/{record_finder/dialog.skr → record-finder/dialog.html} +0 -0
  40. data/client/lanes/components/{record_finder/field.skr → record-finder/field.html} +1 -1
  41. data/client/lanes/components/record-finder/index.js +4 -0
  42. data/client/lanes/{styles/components/record-finder.scss → components/record-finder/styles.scss} +22 -20
  43. data/client/lanes/components/select-field/SelectField.coffee +62 -0
  44. data/client/lanes/components/{select_field → select-field}/index.js +0 -0
  45. data/client/lanes/components/{select_field/_index.scss → select-field/styles.scss} +0 -0
  46. data/client/lanes/extension/EarlyExtensions.js.erb +3 -3
  47. data/client/lanes/extension/Extensions.coffee +4 -1
  48. data/client/lanes/extension/LateLoaded.js.erb +3 -3
  49. data/client/lanes/index.js +2 -2
  50. data/client/lanes/index.scss.erb +30 -0
  51. data/client/lanes/lib/MakeBaseClass.coffee +20 -19
  52. data/client/lanes/lib/ModuleSupport.coffee +1 -1
  53. data/client/lanes/lib/results.coffee +1 -9
  54. data/client/lanes/lib/utilFunctions.coffee +56 -10
  55. data/client/lanes/models/Base.coffee +57 -116
  56. data/client/lanes/models/ChangeMonitor.coffee +29 -0
  57. data/client/lanes/models/ChangeSet.coffee +3 -3
  58. data/client/lanes/models/Collection.coffee +36 -4
  59. data/client/lanes/models/ModelAssociations.coffee +118 -0
  60. data/client/lanes/models/PubSub.coffee +5 -5
  61. data/client/lanes/models/Query.coffee +37 -27
  62. data/client/lanes/models/Sync.coffee +1 -1
  63. data/client/lanes/models/index.js +1 -0
  64. data/client/lanes/screens/Base.coffee +5 -8
  65. data/client/lanes/screens/ChangeListener.coffee +6 -3
  66. data/client/lanes/{models/Screens.coffee → screens/Definitions.coffee} +22 -9
  67. data/client/lanes/screens/Instance.coffee +22 -22
  68. data/client/lanes/screens/Router.coffee +1 -3
  69. data/client/lanes/screens/all.js.erb +3 -0
  70. data/client/lanes/screens/index.js +6 -1
  71. data/client/lanes/screens/{screen-definitions.js.erb → register.js.erb} +3 -3
  72. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_alerts.scss +0 -0
  73. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_badges.scss +0 -0
  74. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_breadcrumbs.scss +0 -0
  75. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_button-groups.scss +0 -0
  76. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_buttons.scss +0 -0
  77. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_carousel.scss +0 -0
  78. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_close.scss +0 -0
  79. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_code.scss +0 -0
  80. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_component-animations.scss +0 -0
  81. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_dropdowns.scss +0 -0
  82. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_forms.scss +0 -0
  83. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_glyphicons.scss +0 -0
  84. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_grid.scss +0 -0
  85. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_input-groups.scss +0 -0
  86. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_jumbotron.scss +0 -0
  87. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_labels.scss +0 -0
  88. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_list-group.scss +0 -0
  89. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_media.scss +0 -0
  90. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_mixins.scss +0 -0
  91. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_modals.scss +0 -0
  92. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_navbar.scss +0 -0
  93. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_navs.scss +0 -0
  94. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_normalize.scss +0 -0
  95. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_pager.scss +0 -0
  96. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_pagination.scss +0 -0
  97. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_panels.scss +0 -0
  98. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_popovers.scss +0 -0
  99. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_print.scss +0 -0
  100. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_progress-bars.scss +0 -0
  101. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_responsive-embed.scss +0 -0
  102. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_responsive-utilities.scss +0 -0
  103. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_scaffolding.scss +0 -0
  104. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_tables.scss +0 -0
  105. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_theme.scss +0 -0
  106. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_thumbnails.scss +0 -0
  107. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_tooltip.scss +0 -0
  108. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_type.scss +0 -0
  109. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_utilities.scss +0 -0
  110. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_variables.scss +0 -0
  111. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_wells.scss +0 -0
  112. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_alerts.scss +0 -0
  113. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_background-variant.scss +0 -0
  114. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_border-radius.scss +0 -0
  115. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_buttons.scss +0 -0
  116. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_center-block.scss +0 -0
  117. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_clearfix.scss +0 -0
  118. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_forms.scss +0 -0
  119. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_gradients.scss +0 -0
  120. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_grid-framework.scss +0 -0
  121. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_grid.scss +0 -0
  122. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_hide-text.scss +0 -0
  123. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_image.scss +0 -0
  124. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_labels.scss +0 -0
  125. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_list-group.scss +0 -0
  126. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_nav-divider.scss +0 -0
  127. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_nav-vertical-align.scss +0 -0
  128. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_opacity.scss +0 -0
  129. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_pagination.scss +0 -0
  130. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_panels.scss +0 -0
  131. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_progress-bar.scss +0 -0
  132. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_reset-filter.scss +0 -0
  133. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_resize.scss +0 -0
  134. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_responsive-visibility.scss +0 -0
  135. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_size.scss +0 -0
  136. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_tab-focus.scss +0 -0
  137. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_table-row.scss +0 -0
  138. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_text-emphasis.scss +0 -0
  139. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_text-overflow.scss +0 -0
  140. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_vendor-prefixes.scss +0 -0
  141. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_alerts.scss +0 -0
  142. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_badges.scss +0 -0
  143. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_breadcrumbs.scss +0 -0
  144. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_button-groups.scss +0 -0
  145. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_buttons.scss +0 -0
  146. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_carousel.scss +0 -0
  147. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_close.scss +0 -0
  148. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_code.scss +0 -0
  149. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_component-animations.scss +0 -0
  150. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_dropdowns.scss +0 -0
  151. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_forms.scss +0 -0
  152. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_glyphicons.scss +0 -0
  153. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_grid.scss +0 -0
  154. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_input-groups.scss +0 -0
  155. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_jumbotron.scss +0 -0
  156. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_labels.scss +0 -0
  157. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_list-group.scss +0 -0
  158. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_media.scss +0 -0
  159. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_mixins.scss +0 -0
  160. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_modals.scss +0 -0
  161. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_navbar.scss +0 -0
  162. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_navs.scss +0 -0
  163. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_normalize.scss +0 -0
  164. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_pager.scss +0 -0
  165. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_pagination.scss +0 -0
  166. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_panels.scss +0 -0
  167. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_popovers.scss +0 -0
  168. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_print.scss +0 -0
  169. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_progress-bars.scss +0 -0
  170. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_responsive-embed.scss +0 -0
  171. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_responsive-utilities.scss +0 -0
  172. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_scaffolding.scss +0 -0
  173. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_tables.scss +0 -0
  174. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_theme.scss +0 -0
  175. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_thumbnails.scss +0 -0
  176. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_tooltip.scss +0 -0
  177. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_type.scss +0 -0
  178. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_utilities.scss +0 -0
  179. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_variables.scss +0 -0
  180. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_wells.scss +0 -0
  181. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/bootstrap.scss +0 -0
  182. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_alerts.scss +0 -0
  183. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_background-variant.scss +0 -0
  184. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_border-radius.scss +0 -0
  185. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_buttons.scss +0 -0
  186. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_center-block.scss +0 -0
  187. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_clearfix.scss +0 -0
  188. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_forms.scss +0 -0
  189. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_gradients.scss +0 -0
  190. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_grid-framework.scss +0 -0
  191. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_grid.scss +0 -0
  192. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_hide-text.scss +0 -0
  193. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_image.scss +0 -0
  194. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_labels.scss +0 -0
  195. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_list-group.scss +0 -0
  196. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_nav-divider.scss +0 -0
  197. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_nav-vertical-align.scss +0 -0
  198. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_opacity.scss +0 -0
  199. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_pagination.scss +0 -0
  200. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_panels.scss +0 -0
  201. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_progress-bar.scss +0 -0
  202. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_reset-filter.scss +0 -0
  203. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_resize.scss +0 -0
  204. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_responsive-visibility.scss +0 -0
  205. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_size.scss +0 -0
  206. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_tab-focus.scss +0 -0
  207. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_table-row.scss +0 -0
  208. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_text-emphasis.scss +0 -0
  209. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_text-overflow.scss +0 -0
  210. data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_vendor-prefixes.scss +0 -0
  211. data/client/lanes/styles/{vendor/bootstrap-custom-grid.scss → bootstrap-custom-grid.scss} +0 -0
  212. data/client/lanes/styles/{vendor/bootstrap-custom-modals.scss → bootstrap-custom-modals.scss} +0 -0
  213. data/client/lanes/styles/bootstrap.scss +71 -0
  214. data/client/lanes/styles/{vendor/dataTables.scss → dataTables.scss} +0 -0
  215. data/client/lanes/styles/fonts.scss +9 -20
  216. data/client/lanes/vendor/packaged.js +27 -25
  217. data/client/lanes/views/Base.coffee +47 -34
  218. data/client/lanes/views/FormBindings.coffee +10 -9
  219. data/client/lanes/views/Helpers.coffee +14 -16
  220. data/client/lanes/views/ModelObserver.coffee +4 -4
  221. data/client/lanes/views/ModelUpdate.coffee +5 -2
  222. data/client/lanes/views/PubSub.coffee +1 -1
  223. data/client/lanes/views/Viewport.coffee +8 -78
  224. data/client/lanes/views/_button.html +1 -1
  225. data/client/lanes/views/_toolbar.html +21 -25
  226. data/client/lanes/views/model-update.html +7 -5
  227. data/client/lanes/workspace/ActiveScreensSwitcher.coffee +6 -12
  228. data/client/lanes/workspace/Extension.coffee +3 -0
  229. data/client/lanes/workspace/Layout.coffee +13 -9
  230. data/client/lanes/workspace/Navbar.coffee +2 -18
  231. data/client/lanes/workspace/Pages.coffee +13 -14
  232. data/client/lanes/workspace/ScreensMenu.coffee +9 -18
  233. data/client/lanes/workspace/UIState.coffee +78 -0
  234. data/client/lanes/workspace/WorkspaceView.coffee +4 -1
  235. data/client/lanes/workspace/index.js +0 -3
  236. data/client/lanes/workspace/navbar.html +0 -4
  237. data/client/lanes/workspace/pages.html +1 -1
  238. data/client/lanes/workspace/styles/changes-notification.scss +57 -0
  239. data/client/lanes/{styles → workspace/styles}/forms.scss +0 -0
  240. data/client/lanes/workspace/styles/header.scss +42 -0
  241. data/client/lanes/{styles → workspace/styles}/keybindings.scss +0 -0
  242. data/client/lanes/workspace/styles/layout.scss +209 -0
  243. data/client/lanes/workspace/styles/screens.scss +67 -0
  244. data/client/lanes/workspace/styles/tabs.scss +147 -0
  245. data/client/lanes/workspace/styles/toolbar.scss +4 -0
  246. data/client/lanes/workspace/styles.scss +20 -0
  247. data/docs/model.md +39 -7
  248. data/docs/todo-example-part-1.md +7 -7
  249. data/docs/view.md +57 -40
  250. data/lib/lanes/access/authentication_provider.rb +59 -0
  251. data/lib/lanes/access/config/routes.rb +26 -0
  252. data/lib/lanes/access/config/screens.rb +16 -0
  253. data/lib/lanes/access/db/migrate/20140615031600_create_lanes_users.rb +12 -0
  254. data/lib/lanes/access/extension.rb +40 -0
  255. data/lib/lanes/access/locked_fields.rb +43 -0
  256. data/lib/lanes/access/role.rb +60 -0
  257. data/lib/lanes/access/role_collection.rb +76 -0
  258. data/lib/lanes/access/roles/administrator.rb +39 -0
  259. data/lib/lanes/access/roles/support.rb +15 -0
  260. data/lib/lanes/access/track_modifications.rb +48 -0
  261. data/lib/lanes/access/user.rb +128 -0
  262. data/lib/lanes/access/version.rb +5 -0
  263. data/lib/lanes/access.rb +51 -0
  264. data/lib/lanes/api/helper_methods.rb +2 -2
  265. data/lib/lanes/api/javascript_processor.rb +3 -3
  266. data/lib/lanes/api/null_authentication_provider.rb +1 -1
  267. data/lib/lanes/api/pub_sub.rb +3 -3
  268. data/lib/lanes/api/request_wrapper.rb +1 -1
  269. data/lib/lanes/api/root.rb +1 -2
  270. data/lib/lanes/api/sprockets_extension.rb +6 -4
  271. data/lib/lanes/api/test_specs.rb +2 -8
  272. data/lib/lanes/command/app.rb +30 -12
  273. data/lib/lanes/command/db.rb +3 -0
  274. data/lib/lanes/command/generate_model.rb +4 -4
  275. data/lib/lanes/command/generate_screen.rb +12 -10
  276. data/lib/lanes/command/generate_view.rb +12 -9
  277. data/lib/lanes/command/named_command.rb +7 -5
  278. data/lib/lanes/command/server.rb +1 -1
  279. data/lib/lanes/command.rb +2 -5
  280. data/lib/lanes/components.rb +1 -1
  281. data/lib/lanes/concerns/queries.rb +1 -1
  282. data/lib/lanes/concerns/set_attribute_data.rb +5 -7
  283. data/lib/lanes/db.rb +5 -4
  284. data/lib/lanes/extension/definition.rb +95 -0
  285. data/lib/lanes/extension.rb +34 -69
  286. data/lib/lanes/guard_tasks.rb +2 -2
  287. data/lib/lanes/screen.rb +8 -0
  288. data/lib/lanes/spec_helper.rb +1 -37
  289. data/lib/lanes/version.rb +1 -1
  290. data/lib/lanes/workspace/extension.rb +28 -0
  291. data/lib/lanes/workspace.rb +7 -0
  292. data/npm-build/package.json +2 -2
  293. data/spec/api/javascript_processor_spec.rb +1 -1
  294. data/spec/lanes/components/grid/GridSpec.coffee +31 -0
  295. data/{lib/lanes/command/templates/client/views → spec/lanes/helpers}/.gitkeep +0 -0
  296. data/spec/{helpers → lanes/helpers}/jasmine-matchers.js +0 -0
  297. data/spec/{helpers → lanes/helpers}/lanes-helpers.coffee +2 -4
  298. data/spec/lanes/helpers/mock-ajax.js +576 -0
  299. data/spec/lanes/models/BaseSpec.coffee +24 -37
  300. data/spec/lanes/models/CollectionSpec.coffee +15 -2
  301. data/spec/lanes/models/ModelAssociationsSpec.coffee +51 -0
  302. data/spec/lanes/views/BaseSpec.coffee +14 -14
  303. data/spec/server/command_spec.rb +39 -0
  304. data/spec/{concerns → server/concerns}/api_path_spec.rb +1 -1
  305. data/spec/{concerns → server/concerns}/association_extensions_spec.rb +1 -2
  306. data/spec/{concerns → server/concerns}/attr_accessor_with_default_spec.rb +0 -0
  307. data/spec/{concerns → server/concerns}/export_associations_spec.rb +1 -2
  308. data/spec/{concerns → server/concerns}/export_methods_spec.rb +1 -3
  309. data/spec/{concerns → server/concerns}/export_scope_spec.rb +2 -2
  310. data/spec/{concerns → server/concerns}/exported_limits_spec.rb +1 -2
  311. data/spec/{concerns → server/concerns}/pub_sub_spec.rb +1 -1
  312. data/spec/{concerns → server/concerns}/set_attribute_data_spec.rb +1 -1
  313. data/spec/{configuration_spec.rb → server/configuration_spec.rb} +1 -1
  314. data/spec/{helpers → server}/minitest_assertions.rb +1 -1
  315. data/spec/{numbers_spec.rb → server/numbers_spec.rb} +1 -2
  316. data/{lib/lanes/testing_models.rb → spec/server/spec_helper.rb} +17 -3
  317. data/spec/{strings_spec.rb → server/strings_spec.rb} +1 -1
  318. data/templates/Gemfile +6 -0
  319. data/{lib/lanes/command/templates → templates}/Guardfile +0 -0
  320. data/templates/Rakefile +2 -0
  321. data/templates/client/Extension.coffee +7 -0
  322. data/templates/client/Router.coffee +4 -0
  323. data/{lib/lanes/command/templates/public → templates/client/components}/.gitkeep +0 -0
  324. data/templates/client/components/Component.coffee +1 -0
  325. data/{lib/lanes/command/templates → templates}/client/index.js +1 -0
  326. data/templates/client/models/BaseModel.coffee +5 -0
  327. data/{lib/lanes/command/templates → templates}/client/models/Model.coffee +2 -3
  328. data/{lib/lanes/command/templates → templates}/client/screens/Screen.coffee +6 -1
  329. data/{lib/lanes/command/templates → templates}/client/screens/index.js +0 -0
  330. data/{lib/lanes/command/templates → templates}/client/screens/layout.html +0 -0
  331. data/{lib/lanes/command/templates → templates}/client/screens/styles.scss +1 -2
  332. data/{lib/lanes/command/templates → templates}/client/styles.scss +0 -0
  333. data/{spec/helpers → templates/client/views}/.gitkeep +0 -0
  334. data/templates/client/views/BaseView.coffee +5 -0
  335. data/templates/client/views/View.coffee +10 -0
  336. data/{lib/lanes/command/templates → templates}/client/views/template.html +0 -0
  337. data/{lib/lanes/command/templates → templates}/config/database.yml +0 -0
  338. data/{lib/lanes/command/templates → templates}/config/lanes.rb +0 -0
  339. data/{lib/lanes/command/templates → templates}/config/routes.rb +0 -0
  340. data/templates/config/screen.rb +12 -0
  341. data/{lib/lanes/command/templates → templates}/config.ru +1 -1
  342. data/{lib/lanes/command/templates → templates}/db/create_table_migration.rb +1 -1
  343. data/{lib/lanes/command/templates → templates}/gitignore +1 -0
  344. data/templates/lib/namespace/base_model.rb +11 -0
  345. data/{lib/lanes/command/templates → templates}/lib/namespace/extension.rb +3 -3
  346. data/{lib/lanes/command/templates → templates}/lib/namespace/model.rb +1 -1
  347. data/templates/lib/namespace/version.rb +3 -0
  348. data/templates/lib/namespace.rb +14 -0
  349. data/templates/public/.gitkeep +0 -0
  350. data/templates/spec/client/Screen.coffee +5 -0
  351. data/templates/spec/client/helpers/ClientHelpers.coffee +5 -0
  352. data/templates/spec/client/models/ModelSpec.coffee +5 -0
  353. data/templates/spec/client/views/ViewSpec.coffee +5 -0
  354. data/{lib/lanes/command/templates → templates}/spec/fixtures/namespace/model.yml +0 -0
  355. data/{lib/lanes/command/templates/spec/namespace → templates/spec/server}/model_spec.rb +2 -2
  356. data/{lib/lanes/command/templates/spec/spec_helper.rb → templates/spec/server/spec_helpers.rb} +3 -2
  357. data/views/index.erb +5 -4
  358. data/views/specs.erb +2 -1
  359. metadata +273 -238
  360. data/client/lanes/components/grid/vendor/dataTables.bootstrap.js +0 -156
  361. data/client/lanes/components/grid/vendor/datatables.responsive.js +0 -666
  362. data/client/lanes/components/modal/_index.scss +0 -20
  363. data/client/lanes/components/popover/_index.scss +0 -1
  364. data/client/lanes/components/record_finder/RecordFinder.coffee +0 -143
  365. data/client/lanes/components/select_field/SelectField.coffee +0 -87
  366. data/client/lanes/extension/GlAccounts.coffee +0 -9
  367. data/client/lanes/minimal.js +0 -11
  368. data/client/lanes/minimal.scss.erb +0 -12
  369. data/client/lanes/styles/components/all.scss +0 -6
  370. data/client/lanes/styles/components/changes-notification.scss +0 -44
  371. data/client/lanes/styles/components/suggest.scss +0 -266
  372. data/client/lanes/styles/index.css +0 -4
  373. data/client/lanes/styles/layout.scss +0 -272
  374. data/client/lanes/styles/screens.scss +0 -66
  375. data/client/lanes/styles/tabs.scss +0 -148
  376. data/client/lanes/styles/vendor/bootstrap.scss +0 -74
  377. data/client/lanes/workspace.scss.erb +0 -29
  378. data/client/lanes-complete.js +0 -3
  379. data/client/lanes-workspace.scss.erb +0 -21
  380. data/db/migrate/20140615031600_create_hip_users.rb +0 -17
  381. data/lib/lanes/command/templates/Gemfile +0 -9
  382. data/lib/lanes/command/templates/Rakefile +0 -2
  383. data/lib/lanes/command/templates/client/Extension.coffee +0 -5
  384. data/lib/lanes/command/templates/client/components/Component.coffee +0 -1
  385. data/lib/lanes/command/templates/client/models/BaseModel.coffee +0 -5
  386. data/lib/lanes/command/templates/client/views/BaseView.coffee +0 -5
  387. data/lib/lanes/command/templates/client/views/View.coffee +0 -7
  388. data/lib/lanes/command/templates/config/screen.rb +0 -8
  389. data/lib/lanes/command/templates/lib/namespace/base_model.rb +0 -9
  390. data/lib/lanes/command/templates/lib/namespace/version.rb +0 -3
  391. data/lib/lanes/command/templates/lib/namespace.rb +0 -12
  392. data/lib/lanes/command/templates/spec/client/Screen.coffee +0 -7
  393. data/lib/lanes/command/templates/spec/client/models/ModelSpec.coffee +0 -5
  394. data/lib/lanes/command/templates/spec/client/views/ViewSpec.coffee +0 -5
  395. data/lib/lanes/db/migration_helpers.rb +0 -178
  396. data/public/javascripts/jasmine_examples/Player.js +0 -22
  397. data/public/javascripts/jasmine_examples/Song.js +0 -7
  398. data/spec/command_spec.rb +0 -49
  399. data/spec/helpers/jasmine-jquery.js +0 -813
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c48fe1ac2eaf85a9771acba612806120af0168b
4
- data.tar.gz: 815755b8f6e731e8a85f6a02ed443a1ef676e9cf
3
+ metadata.gz: bc96c5119c604258c8b8f4c2ceb3c8c3028519bc
4
+ data.tar.gz: 4f4f8fd4254620611174e393070c68c257b13790
5
5
  SHA512:
6
- metadata.gz: 7d868609cfbac56dbd4e6ed6e4ca02284acd12c7e0cbea3145748b1a0726dd7e9bb8267eaa0c5ac436844297acc15a612fa6a07cb03e800f5e50d0a6f68c0e93
7
- data.tar.gz: 844e24f045c8896fb405e20570edc981a7dcc04a3167316b9741090b42f2bc33767837b49a4d6589c60e747937d4f2410d989ce4c8891676ee757f3264ed53cd
6
+ metadata.gz: f54221e4207bc547a4aaf6015f28c41991c4347fe2bcf328a8bc5b335c480a2c1b48837a63b55993368ee4529cac2165e966cda612d06a0d52dee1aa28592742
7
+ data.tar.gz: f7fcb100561a1345cb2280853531b5e12a44ed52a96656e4328581a798bf1b5b54ad4355e54e037f2e26e7d0fa7f90a1c071c990c0f479b34731fb65c4cce43f
data/README.md CHANGED
@@ -6,6 +6,25 @@ Read more at [lanesframework.org](http://lanesframework.org/)
6
6
 
7
7
  It's extracted from the Stockor ERP application and is still very much a work in progress.
8
8
 
9
+ Some of it's features are:
10
+
11
+ * **Integrated web server**: Sinatra is used internally with RESTful routes auto-created for each model. This frees the developer from the hassel of integrating disparate systems and allows Lanes to provide tools that are guaranteed to work together.
12
+
13
+ * **Rich JSON requests**: Clients can perform ad-hoc querys against server-side data and the the reply format can be extensively customized. Operators are provided for specifying which fields and associations are included in the result set, as well as ordering and pagination support. It's also easy to write custom query operators. ActiveRecord is used internally to eager-load associations in order to prevent N+1 queries.
14
+
15
+ * **Real-Time data updates**: Whenever a CRUD operation is performed on a model, the web-server will relay the event to client observers that have registered for updates. By default a model is registered for updates whenever it's bound to a view, which works to prevent unwanted updates and allows records to be garbage collected. Updates are performed by long-pulling via the message-bus gem. A client-side identity map is also used so that only one copy of the model for a given id exists and is updated.
16
+
17
+ * **Next-Gen web-framework**: Derived from ampersand state, the web framework completely written in CoffeeScript and uses defined properties to implement data getter and setters. This means that it's IE 9+ only. It's heavily influenced by Backbone, Ampersand and a bit of Marrionette.
18
+
19
+ * **Integrated continual testing environment**: When ran in development mode, Lanes watches for file changes and runs the appropriate spec for both your client and server code automatically. Minispec is utilized for the Ruby models, and client code tested via Jasmine.
20
+
21
+ * **Role-driven security**: Models can be marked as readable, writeable, or deletable for roles. Additionally, fields can be marked as read-only or invisible to prevent unauthorized access.
22
+
23
+ * **Extendible**: Extensions can be registered with the framework and will be automatically compiled and included in builds. Components are loaded on-demand and are not included unless an extension requires them. Lanes also dynamically loads the Javascript and CSS for screens on-demand immediatly before they are displayed.
24
+
25
+ * **Embeddable and Responsive**: Designed from the ground up to be embeddable in hostile environments. All code is non-conflicting and wrapped in closures. Sass is auto-namespaced. Detect changes in it's container's size and relay them to clasess for responsive layouts. A modified Bootstrap based css layout can optionally be loaded which will provide a responsive grid that's bound to the container's size, not the documents.
26
+
27
+
9
28
  ## Contributing
10
29
 
11
30
  The standard instructions are always good:
@@ -0,0 +1,19 @@
1
+ class Lanes.Access.Extension extends Lanes.Extensions.Base
2
+
3
+ identifier: "lanes-access"
4
+
5
+ setBootstrapData: (data)->
6
+ Lanes.current_user = new Lanes.Models.User
7
+
8
+ Lanes.Models.Roles.all = new Lanes.Models.Roles(
9
+ _.map( data.roles, (role)->
10
+ { id: role.toLowerCase(), name: role }
11
+ )
12
+ )
13
+ if data.user
14
+ Lanes.current_user.set(data.user)
15
+ if data.access
16
+ Lanes.current_user.access_data = data.access
17
+
18
+ onAvailable: (view)->
19
+ Lanes.Access.createLoginDialog(view)
@@ -0,0 +1,47 @@
1
+ class Lanes.Access.LoginDialog extends Lanes.Components.ModalDialog
2
+
3
+ bodyTemplateName: 'login-dialog'
4
+ templatePrefix: 'lanes/access'
5
+ hideOnBackdropClick: false
6
+ showHideButton: false
7
+ hideOnEsc: false
8
+
9
+ size: 'md'
10
+ title: 'Please sign in …'
11
+ FILE: FILE
12
+
13
+ domEvents:
14
+ 'click .btn-primary': 'onLogin'
15
+
16
+ buttons:
17
+ login: { label: 'Login', type: 'primary' }
18
+
19
+ ui:
20
+ l: '#LoginField',
21
+ pw: '#PasswordField'
22
+ alert: '.alert'
23
+
24
+ initialize: (options)->
25
+ super
26
+ this.listenToAndRun(Lanes.current_user, 'change:isLoggedIn', this.onUserChange)
27
+
28
+ onUserChange: ->
29
+ this.toggleShown(!Lanes.current_user.isLoggedIn)
30
+
31
+ onLogin: (ev)->
32
+ msg = this.ui.alert.hide()
33
+ mask = new Lanes.Views.TimedMask(this.$el, "Attempting Login …")
34
+ session = Lanes.Models.User.attemptLogin( @ui.l.val(), @ui.pw.val(), {
35
+ scope: this
36
+ success: ->
37
+ mask.displaySuccess("Login Success!")
38
+ error: ->
39
+ msg.show().text(session.lastServerMessage )
40
+ mask.displayFailure(session.lastServerMessage)
41
+ })
42
+
43
+ onShown: -> @ui.l.focus()
44
+
45
+
46
+ Lanes.Access.createLoginDialog = (view)->
47
+ new Lanes.Access.LoginDialog( parent: view )
@@ -0,0 +1,88 @@
1
+ class Role extends Lanes.Models.BasicModel
2
+ props:
3
+ id: 'string'
4
+ name: 'string'
5
+ member: { type: 'boolean', default: false }
6
+
7
+
8
+ class Lanes.Models.Roles extends Lanes.Models.BasicCollection
9
+ model: Role
10
+ comparator: 'name'
11
+
12
+
13
+ class UserRole
14
+ constructor: (config={})->
15
+ @type = config.type
16
+ for method in RWD
17
+ this[method] = _.map(config[method],klassFor)
18
+
19
+ can: (type,model)->
20
+ -1 != this[type].indexOf(model)
21
+
22
+ decodeLockedFields: (fields, previous={})->
23
+ decoded = _.extend({}, previous)
24
+ for lock in fields
25
+ if klass = klassFor(lock.type)
26
+ decoded[ klass ] = locks = {}
27
+ locks[field] = grants for field, grants of lock.locks
28
+ decoded
29
+
30
+ RWD = ['read','write','delete']
31
+
32
+
33
+ # The admin is special and can do anything
34
+ class Administrator
35
+ constructor: ->
36
+ UserRole.prototype.constructor.apply(this,arguments)
37
+ can: -> true
38
+
39
+ decodeLockedFields: ->
40
+ {}
41
+
42
+ RoleMap = {
43
+ "administrator": Administrator
44
+ }
45
+
46
+
47
+ class Lanes.Models.UserRoleSet
48
+
49
+ constructor: (access={})->
50
+ _.defaults(access, { roles: [], locked_fields: [] })
51
+ @roles = []
52
+ @locked_fields = {}
53
+ for role in access.roles
54
+ klass = RoleMap[role.type] || UserRole
55
+ role = new klass(role)
56
+ @roles.push( role )
57
+ @locked_fields = role.decodeLockedFields(access.locked_fields, @locked_fields)
58
+
59
+ can:(method,model,field)->
60
+ if model instanceof Lanes.Models.Base
61
+ model = model.constructor
62
+
63
+ if field && ( locks = @locked_fields[model] ) && ( grants = locks[field] )
64
+ for grant in grants
65
+ if grant.only && grant.only != method
66
+ return this.testModelAccess(method,model)
67
+ else
68
+ for role in @roles
69
+ return true if role.type == grant.role
70
+ return false
71
+ else
72
+ return this.testModelAccess(method,model)
73
+
74
+ testModelAccess:(method,model)->
75
+ !!_.detect( @roles, (role)->role.can(method,model) )
76
+
77
+ canRead:(model,field)->
78
+ this.can('read',model,field)
79
+
80
+ canWrite:(model,field)->
81
+ this.can('write',model,field)
82
+
83
+ canDelete:(model)->
84
+ this.can('delete',model)
85
+
86
+ klassFor = (identifier)->
87
+ Lanes.u.getPath(identifier) ||
88
+ Lanes.warn("Model #{identifier} not found for role")
@@ -0,0 +1,72 @@
1
+ class Lanes.Models.User extends Lanes.Models.Base
2
+
3
+ constructor: (attributes,access)->
4
+ super
5
+ this.access_data = access
6
+
7
+ api_path: 'users'
8
+ derived:
9
+ roles:
10
+ deps: ['role_names', 'access_data']
11
+ fn: -> new Lanes.Models.UserRoleSet( @access_data )
12
+ isLoggedIn:
13
+ deps:['id'], fn: -> !!this.id
14
+ allRoles:
15
+ deps: ['role_names', 'access_data']
16
+ fn: ->
17
+ role_data = Lanes.Models.Roles.all?.toJSON() || []
18
+ roles = new Lanes.Models.Roles( role_data )
19
+ _.each( this.role_names, (name)->
20
+ roles.get(name)?.member = true
21
+ )
22
+ roles
23
+
24
+ session:
25
+ access_data: 'object'
26
+
27
+ props:
28
+ id: { type: "integer", required:true }
29
+ login: 'string'
30
+ name: 'string'
31
+ email: 'string'
32
+ role_names: { type: 'array', default: -> [] }
33
+ options: 'object'
34
+ password: 'string'
35
+
36
+ canRead: (model,field) -> this.roles.canRead(model,field)
37
+ canWrite: (model,field) -> this.roles.canWrite(model,field)
38
+ canDelete: (model) -> this.roles.canDelete(model)
39
+
40
+ logout: ->
41
+ session = new Session( id: this.id )
42
+ session
43
+ .destroy()
44
+ .then =>
45
+ _.each(@attributes, (value,key)=> @set(key, null) )
46
+
47
+ setLoginData: (attrs, access)->
48
+ this.access_data = access
49
+ this.set(attrs)
50
+
51
+ @attemptLogin: (login, password, options)->
52
+ session = new Session( login: login, password: password )
53
+ success = options.success
54
+ session.save(_.extend(options,{
55
+ success: (reply)->
56
+ Lanes.current_user.setLoginData(session.user, session.access)
57
+ success.apply(options.scope, arguments)
58
+ }))
59
+ session
60
+
61
+ class Lanes.Models.UserCollection extends Lanes.Models.Collection
62
+ model: Lanes.Models.User
63
+
64
+
65
+ class Session extends Lanes.Models.Base
66
+ api_path: 'user-session'
67
+ props:
68
+ id: 'integer'
69
+ login: 'string'
70
+ password: 'string'
71
+ access: 'object'
72
+ user: 'object'
@@ -0,0 +1,5 @@
1
+ //=require ./User
2
+ //=require ./Roles
3
+ //=require ./LoginDialog
4
+ //=require ./login-dialog
5
+ //=require ./Extension
@@ -0,0 +1,16 @@
1
+ <div class="row">
2
+ <div style="display:none" class="alert alert-danger" role="alert"></div>
3
+ <div class="<%= h.grid_offsets(0,2) %> <%= h.grid_widths 12, 8%>">
4
+ <form role="form">
5
+ <div class="form-group">
6
+ <label for="LoginField">Login</label>
7
+ <input type="email" id="LoginField" value="admin" class="form-control login" placeholder="Enter Login">
8
+ </div>
9
+ <div class="form-group">
10
+ <label for="PasswordField">Password <a href="/sessions/forgot_password">(forgot password)</a></label>
11
+ <input type="password" id="PasswordField" value="password" class="form-control password" placeholder="Password">
12
+ </div>
13
+
14
+ </form>
15
+ </div>
16
+ </div>
@@ -0,0 +1,25 @@
1
+ class Lanes.Access.Screens.UserManagement.GridUserEditor extends Lanes.Components.Grid.PopOverEditor
2
+
3
+ writeTemplateName: 'user-management/grid-popover-editor'
4
+ templatePrefix: 'lanes/access/screens'
5
+
6
+ writeTemplateData: ->
7
+ { columns: _.reject(this.grid.columnDefinitions,(f)-> f.field=='role_names') }
8
+
9
+ subviews:
10
+ roles:
11
+ component: 'SelectField'
12
+ model: 'model'
13
+ options: 'roleOptions'
14
+
15
+ roleOptions: ->
16
+ { multiple: true, data: this.model.allRoles, mappings:{ title: 'name', selected: 'member' } }
17
+
18
+ constructor: (options={})->
19
+ super( _.extend(options,{formBindings: true}) )
20
+
21
+ persistFields: ->
22
+ @model.set({
23
+ role_names: _.pluck(this.$('select option:selected'), 'value'),
24
+ password: this.$('input[name=password]').val()
25
+ })
@@ -0,0 +1,24 @@
1
+ class Lanes.Access.Screens.UserManagement extends Lanes.Screens.Base
2
+
3
+ templateName: 'user-management/screen'
4
+ templatePrefix: 'lanes/access/screens'
5
+ FILE: FILE
6
+
7
+ subviews:
8
+ grid:
9
+ component: 'Grid'
10
+ options: 'gridOptions'
11
+
12
+ gridOptions: ->
13
+ {
14
+ recordQuery: new Lanes.Models.Query({
15
+ modelClass: Lanes.Models.User,
16
+ fields: [ 'login', 'name', 'email', 'role_names' ]
17
+ }),
18
+ editorConfig: {}
19
+ editRecords: true
20
+ editingController: Lanes.Access.Screens.UserManagement.GridUserEditor
21
+ selectionMode: 'single',
22
+ addRecords: true
23
+ deleteRecords: true
24
+ }
@@ -0,0 +1,33 @@
1
+ <form class="user-edit form-horizontal" role="form">
2
+ <% for field in @columns: %>
3
+ <div class="form-group">
4
+ <label for="field-<%= field.field %>" class="col-sm-3 control-label"><%= field.title %></label>
5
+ <div class="col-sm-9">
6
+ <input type="text" name="<%= field.field %>" class="form-control" id="field-<%= field.field %>" placeholder="">
7
+ </div>
8
+ </div>
9
+ <% end %>
10
+
11
+ <div class="form-group">
12
+ <label for="field-password" class="col-sm-3 control-label">Roles</label>
13
+ <div class="col-sm-9">
14
+ <div data-hook="roles"></div>
15
+ </div>
16
+ </div>
17
+
18
+ <div class="form-group">
19
+ <label for="field-password" class="col-sm-3 control-label">Password</label>
20
+ <div class="col-sm-9">
21
+ <input type="password" name="password" class="form-control" id="field-password" placeholder="">
22
+ </div>
23
+ </div>
24
+
25
+ <div class="buttons">
26
+ <button type="button" class="btn btn-default cancel">
27
+ <i class="icon-cancel-circle"> Cancel</i>
28
+ </button>
29
+ <button type="button" class="btn btn-primary save">
30
+ <i class="icon-save"> Save</i>
31
+ </button>
32
+ </div>
33
+ </form>
@@ -0,0 +1,3 @@
1
+ //= require ./UserManagement
2
+ //= require ./GridUserEditor
3
+ //= require_tree .
@@ -0,0 +1,7 @@
1
+ .lanes {
2
+
3
+ .grid-popover-editor {
4
+ width: 350px;
5
+ }
6
+
7
+ }
@@ -0,0 +1,7 @@
1
+ <div class="users">
2
+ <h3>Manage User Accounts</h3>
3
+
4
+ <div class="grid" data-hook="grid">
5
+ </div>
6
+
7
+ </div>
@@ -1,10 +1,12 @@
1
1
  class BaseComponent
2
+ abstractClass: true
2
3
 
3
4
  constructor: (options={})->
4
5
  super
5
6
  @access ||= this.calculate_access()
6
7
 
7
8
  session:
9
+ field_name: { 'string', setOnce: true }
8
10
  access:
9
11
  type: 'string',
10
12
  values: ['read','write','none']
@@ -15,7 +17,7 @@ class BaseComponent
15
17
 
16
18
  emptyTemplateName: -> this.writeTemplate()
17
19
  readTemplateName: -> this.writeTemplate()
18
- writeTemplateName: -> 'lanes/views/empty-span'
20
+ writeTemplateName: -> 'empty-span'
19
21
 
20
22
  renderContextFree: ->
21
23
  tmpl = if this.writeAble
@@ -24,11 +26,8 @@ class BaseComponent
24
26
  'readTemplate'
25
27
  else
26
28
  'emptyTemplate'
27
-
28
29
  this.replaceEl( this.renderTemplateMethod(tmpl) );
29
30
 
30
- templatePrefix: -> this.FILE.extensionName.toLowerCase() + "/components/"
31
-
32
31
  calculate_access:->
33
32
  if ! @field_name || Lanes.Views.RenderContext.canWrite(@field_name)
34
33
  'write'
@@ -1,3 +1,5 @@
1
1
  <% Lanes::Components.enabled_with_dependencies(self) do | component |
2
2
  require_asset "lanes/components/#{component}"
3
3
  end %>
4
+
5
+ <% Lanes::Screen.uncache_file_on_update(self) %>
@@ -3,7 +3,7 @@ class Lanes.Components.Grid.Editor extends Lanes.Components.Base
3
3
  session:
4
4
  grid: 'object' # n.b. - not 'state'. Doing so causes stack overflow since grid also has a 'editor' session var
5
5
 
6
- events:
6
+ domEvents:
7
7
  'click .save': 'saveChanges'
8
8
  'click .cancel': 'cancelEditing'
9
9
 
@@ -8,8 +8,9 @@ _.extend( Lanes.$.fn.dataTableExt.oStdClasses,{
8
8
 
9
9
 
10
10
  class Lanes.Components.Grid extends Lanes.Components.Base
11
+ FILE: FILE
11
12
 
12
- events:
13
+ domEvents:
13
14
  'click button.refresh': 'reload'
14
15
  'click button.delete': 'deleteRow'
15
16
  'click button.create': 'addRow'
@@ -17,7 +18,7 @@ class Lanes.Components.Grid extends Lanes.Components.Base
17
18
  'cancel-edit': 'onCancelEdit'
18
19
  'order.dt table': 'onSort'
19
20
 
20
- writeTemplateName: 'grid/template'
21
+ writeTemplateName: 'template'
21
22
 
22
23
  writeTemplateData: ->
23
24
  data = { grid: this, buttons: ['refresh'] }
@@ -31,7 +32,8 @@ class Lanes.Components.Grid extends Lanes.Components.Base
31
32
  @recordQuery.fields.map(this._makeField, this)
32
33
 
33
34
  modelClass:
34
- deps:['recordQuery'], fn:-> @recordQuery.model_class
35
+ deps:['recordQuery'], fn:->
36
+ @recordQuery?.modelClass
35
37
 
36
38
  singleSelectMode:
37
39
  deps:['selectionMode'], fn:-> @selectionMode == 'single'
@@ -48,7 +50,8 @@ class Lanes.Components.Grid extends Lanes.Components.Base
48
50
  editingController: 'any' # either string or constructor fn
49
51
 
50
52
  initialize: ->
51
- this.listenTo(this.viewport,'change:screen_enu_size', this.delayedWidthReset)
53
+ if this.viewport
54
+ this.listenTo(this.viewport,'change:screen_enu_size', this.adjustColumnWidth)
52
55
  unless Lanes.current_user.canWrite(this.modelClass)
53
56
  this.editRecords = false
54
57
  this.addRecords = false
@@ -76,7 +79,7 @@ class Lanes.Components.Grid extends Lanes.Components.Base
76
79
 
77
80
  unselect: (row)->
78
81
  this.$el.trigger('unselect-row', [@modelForRow(row), {row:row}])
79
- row.removeClass('active')
82
+ Lanes.dom.removeClass(row,'active')
80
83
 
81
84
  beginEdit: (row,ev)->
82
85
  return false unless model = this.modelForRow(row)
@@ -116,14 +119,14 @@ class Lanes.Components.Grid extends Lanes.Components.Base
116
119
  row = this.$(ev.target).closest('tr')
117
120
  if this.editRecords
118
121
  this.beginEdit(row,ev)
119
- else if @singleSelectMode
120
- this.unselect(row) for row in this.$('tr .active')
122
+ if @singleSelectMode
123
+ this.unselect(selected) for selected in this.$('tr.active')
124
+
125
+ if row.hasClass('active')
126
+ this.unselect(row)
121
127
  else
122
- if row.hasClass('active')
123
- this.unselect(row)
124
- else
125
- row.addClass('active')
126
- this.$el.trigger('select-row', {model:model, row:row} ) if model = this.modelForRow(row)
128
+ row.addClass('active')
129
+ this.$el.trigger('select-row', model, row ) if model = this.modelForRow(row)
127
130
 
128
131
  updateRow: (row, model)->
129
132
  row.attr('id', model.id)
@@ -135,17 +138,14 @@ class Lanes.Components.Grid extends Lanes.Components.Base
135
138
  return data.model if data.model?.isModel
136
139
  attrs = if row.attr('id') then { id: parseInt(row.attr('id')) } else {}
137
140
  for field,i in @columnDefinitions
138
- attrs[field.field] = data[i]
141
+ attrs[field.id] = data[i]
139
142
  data.model = new @modelClass(attrs,ignoreUnsaved:true)
140
143
 
141
- delayedGridConfiguration: ->
142
- _.delay( =>
143
- @dt_api.columns.adjust()
144
- ,500 )
144
+ adjustColumnWidth: ->
145
+ @dt_api.columns.adjust()
146
+
145
147
 
146
- render: ->
147
- super
148
- responsiveHelper = undefined;
148
+ onRender: ->
149
149
  breakpointDefinition = {
150
150
  tablet: 1024,
151
151
  phone : 480
@@ -161,7 +161,7 @@ class Lanes.Components.Grid extends Lanes.Components.Base
161
161
  oScroller: { loadingIndicator: true }
162
162
  ajax:
163
163
  url: @recordQuery.url + ".json"
164
- data: (d)=>@buildModels(d)
164
+ data: (d)=>@buildQuery(d)
165
165
  dataSrc: (d)->
166
166
  d.recordsFiltered = d.recordsTotal = d.total
167
167
  row.DT_RowId = row.shift() for row in d.data
@@ -172,19 +172,18 @@ class Lanes.Components.Grid extends Lanes.Components.Base
172
172
  columns: @columnDefinitions
173
173
  )
174
174
  this.dt_api = this.dataTable.api()
175
- this.delayedGridConfiguration()
176
175
  this
177
176
 
178
- buildModels: (d)->
177
+ buildQuery: (d)->
179
178
  params = {
180
179
  o: {}, s: d.start, l: d.length||100, df:'array',
181
- f: ['id'].concat(_.pluck(@columnDefinitions, 'field'))
180
+ f: ['id'].concat(_.pluck(@columnDefinitions, 'id'))
182
181
  }
183
182
  if ! _.isEmpty( query = @recordQuery.asParams() )
184
183
  params['q']=query
185
184
  for order in d.order
186
185
  column = @recordQuery.fields.at(order.column)
187
- params['o'][column.field] = order.dir
186
+ params['o'][column.id] = order.dir
188
187
  params
189
188
 
190
189
 
@@ -192,10 +191,10 @@ class Lanes.Components.Grid extends Lanes.Components.Base
192
191
  align = switch query_field.type
193
192
  when 'integer','bigdec' then 'r'
194
193
  else 'l'
195
- { title: query_field.title, field: query_field.field, className: align, "targets": [ index ] }
194
+ { title: query_field.title, id: query_field.id, className: align, "targets": [ index ] }
196
195
 
197
196
  _dataFromModel: (model)->
198
197
  data = []
199
198
  for field,i in @columnDefinitions
200
- data.push( model.get(field.field) || '' )
199
+ data.push( model.get(field.id) || '' )
201
200
  data
@@ -1,4 +1,4 @@
1
- <div class="lanes-grid">
1
+ <div class="lanes-grid grid">
2
2
  <% if @grid.editRecords: %><%= h.toolbar( buttons: @buttons ) %><% end %>
3
3
  <table cellspacing="0" width="100%"></table>
4
4
  </div>