lanes 0.1.2 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -0
- data/client/lanes/access/Extension.coffee +19 -0
- data/client/lanes/access/LoginDialog.coffee +47 -0
- data/client/lanes/access/Roles.coffee +88 -0
- data/client/lanes/access/User.coffee +72 -0
- data/client/lanes/access/index.js +5 -0
- data/client/lanes/access/login-dialog.html +16 -0
- data/client/lanes/access/screens/user-management/GridUserEditor.coffee +25 -0
- data/client/lanes/access/screens/user-management/UserManagement.coffee +24 -0
- data/client/lanes/access/screens/user-management/grid-popover-editor.html +33 -0
- data/client/lanes/access/screens/user-management/index.js +3 -0
- data/client/lanes/access/screens/user-management/index.scss +7 -0
- data/client/lanes/access/screens/user-management/screen.html +7 -0
- data/client/lanes/{components/enabled.scss.erb → access/styles.scss} +0 -0
- data/{lib/lanes/command/templates/client/components → client/lanes/access/views}/.gitkeep +0 -0
- data/client/lanes/components/Base.coffee +3 -4
- data/client/lanes/components/enabled.js.erb +2 -0
- data/client/lanes/components/grid/Editor.coffee +1 -1
- data/client/lanes/components/grid/Grid.coffee +26 -27
- data/client/lanes/components/grid/{_index.scss → styles.scss} +0 -0
- data/client/lanes/components/grid/template.html +1 -1
- data/client/lanes/components/grid/vendor/dataTables.scroller.js +119 -42
- data/client/lanes/components/grid/vendor/jquery.dataTables.js +984 -526
- data/client/lanes/components/modal/ModalDialog.coffee +25 -4
- data/client/lanes/components/modal/styles.scss +19 -0
- data/client/lanes/components/modal/template.html +2 -2
- data/client/lanes/components/multi-select/MultiSelect.coffee +46 -0
- data/client/lanes/components/popover/PopOver.coffee +1 -1
- data/client/lanes/components/popover/styles.scss +2 -0
- data/client/lanes/components/{radio_group → radio-group}/RadioGroup.coffee +12 -23
- data/client/lanes/components/radio-group/index.js +1 -0
- data/client/lanes/components/radio-group/styles.scss +1 -0
- data/client/lanes/components/record-finder/Clause.coffee +38 -0
- data/client/lanes/components/record-finder/Dialog.coffee +45 -0
- data/client/lanes/components/record-finder/RecordFinder.coffee +55 -0
- data/client/lanes/components/{record_finder/clause.skr → record-finder/clause.html} +7 -5
- data/client/lanes/components/record-finder/config.json +3 -0
- data/client/lanes/components/{record_finder/dialog.skr → record-finder/dialog.html} +0 -0
- data/client/lanes/components/{record_finder/field.skr → record-finder/field.html} +1 -1
- data/client/lanes/components/record-finder/index.js +4 -0
- data/client/lanes/{styles/components/record-finder.scss → components/record-finder/styles.scss} +22 -20
- data/client/lanes/components/select-field/SelectField.coffee +62 -0
- data/client/lanes/components/{select_field → select-field}/index.js +0 -0
- data/client/lanes/components/{select_field/_index.scss → select-field/styles.scss} +0 -0
- data/client/lanes/extension/EarlyExtensions.js.erb +3 -3
- data/client/lanes/extension/Extensions.coffee +4 -1
- data/client/lanes/extension/LateLoaded.js.erb +3 -3
- data/client/lanes/index.js +2 -2
- data/client/lanes/index.scss.erb +30 -0
- data/client/lanes/lib/MakeBaseClass.coffee +20 -19
- data/client/lanes/lib/ModuleSupport.coffee +1 -1
- data/client/lanes/lib/results.coffee +1 -9
- data/client/lanes/lib/utilFunctions.coffee +56 -10
- data/client/lanes/models/Base.coffee +57 -116
- data/client/lanes/models/ChangeMonitor.coffee +29 -0
- data/client/lanes/models/ChangeSet.coffee +3 -3
- data/client/lanes/models/Collection.coffee +36 -4
- data/client/lanes/models/ModelAssociations.coffee +118 -0
- data/client/lanes/models/PubSub.coffee +5 -5
- data/client/lanes/models/Query.coffee +37 -27
- data/client/lanes/models/Sync.coffee +1 -1
- data/client/lanes/models/index.js +1 -0
- data/client/lanes/screens/Base.coffee +5 -8
- data/client/lanes/screens/ChangeListener.coffee +6 -3
- data/client/lanes/{models/Screens.coffee → screens/Definitions.coffee} +22 -9
- data/client/lanes/screens/Instance.coffee +22 -22
- data/client/lanes/screens/Router.coffee +1 -3
- data/client/lanes/screens/all.js.erb +3 -0
- data/client/lanes/screens/index.js +6 -1
- data/client/lanes/screens/{screen-definitions.js.erb → register.js.erb} +3 -3
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_alerts.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_badges.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_breadcrumbs.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_button-groups.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_buttons.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_carousel.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_close.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_code.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_component-animations.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_dropdowns.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_forms.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_glyphicons.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_grid.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_input-groups.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_jumbotron.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_labels.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_list-group.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_media.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_mixins.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_modals.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_navbar.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_navs.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_normalize.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_pager.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_pagination.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_panels.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_popovers.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_print.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_progress-bars.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_responsive-embed.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_responsive-utilities.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_scaffolding.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_tables.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_theme.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_thumbnails.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_tooltip.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_type.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_utilities.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_variables.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/_wells.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_alerts.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_background-variant.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_border-radius.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_buttons.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_center-block.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_clearfix.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_forms.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_gradients.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_grid-framework.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_grid.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_hide-text.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_image.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_labels.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_list-group.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_nav-divider.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_nav-vertical-align.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_opacity.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_pagination.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_panels.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_progress-bar.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_reset-filter.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_resize.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_responsive-visibility.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_size.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_tab-focus.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_table-row.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_text-emphasis.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_text-overflow.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/mixins/_vendor-prefixes.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_alerts.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_badges.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_breadcrumbs.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_button-groups.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_buttons.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_carousel.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_close.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_code.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_component-animations.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_dropdowns.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_forms.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_glyphicons.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_grid.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_input-groups.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_jumbotron.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_labels.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_list-group.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_media.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_mixins.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_modals.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_navbar.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_navs.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_normalize.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_pager.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_pagination.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_panels.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_popovers.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_print.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_progress-bars.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_responsive-embed.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_responsive-utilities.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_scaffolding.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_tables.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_theme.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_thumbnails.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_tooltip.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_type.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_utilities.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_variables.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/_wells.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/bootstrap.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_alerts.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_background-variant.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_border-radius.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_buttons.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_center-block.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_clearfix.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_forms.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_gradients.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_grid-framework.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_grid.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_hide-text.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_image.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_labels.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_list-group.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_nav-divider.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_nav-vertical-align.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_opacity.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_pagination.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_panels.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_progress-bar.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_reset-filter.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_resize.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_responsive-visibility.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_size.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_tab-focus.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_table-row.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_text-emphasis.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_text-overflow.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap → bootstrap}/old/mixins/_vendor-prefixes.scss +0 -0
- data/client/lanes/styles/{vendor/bootstrap-custom-grid.scss → bootstrap-custom-grid.scss} +0 -0
- data/client/lanes/styles/{vendor/bootstrap-custom-modals.scss → bootstrap-custom-modals.scss} +0 -0
- data/client/lanes/styles/bootstrap.scss +71 -0
- data/client/lanes/styles/{vendor/dataTables.scss → dataTables.scss} +0 -0
- data/client/lanes/styles/fonts.scss +9 -20
- data/client/lanes/vendor/packaged.js +27 -25
- data/client/lanes/views/Base.coffee +47 -34
- data/client/lanes/views/FormBindings.coffee +10 -9
- data/client/lanes/views/Helpers.coffee +14 -16
- data/client/lanes/views/ModelObserver.coffee +4 -4
- data/client/lanes/views/ModelUpdate.coffee +5 -2
- data/client/lanes/views/PubSub.coffee +1 -1
- data/client/lanes/views/Viewport.coffee +8 -78
- data/client/lanes/views/_button.html +1 -1
- data/client/lanes/views/_toolbar.html +21 -25
- data/client/lanes/views/model-update.html +7 -5
- data/client/lanes/workspace/ActiveScreensSwitcher.coffee +6 -12
- data/client/lanes/workspace/Extension.coffee +3 -0
- data/client/lanes/workspace/Layout.coffee +13 -9
- data/client/lanes/workspace/Navbar.coffee +2 -18
- data/client/lanes/workspace/Pages.coffee +13 -14
- data/client/lanes/workspace/ScreensMenu.coffee +9 -18
- data/client/lanes/workspace/UIState.coffee +78 -0
- data/client/lanes/workspace/WorkspaceView.coffee +4 -1
- data/client/lanes/workspace/index.js +0 -3
- data/client/lanes/workspace/navbar.html +0 -4
- data/client/lanes/workspace/pages.html +1 -1
- data/client/lanes/workspace/styles/changes-notification.scss +57 -0
- data/client/lanes/{styles → workspace/styles}/forms.scss +0 -0
- data/client/lanes/workspace/styles/header.scss +42 -0
- data/client/lanes/{styles → workspace/styles}/keybindings.scss +0 -0
- data/client/lanes/workspace/styles/layout.scss +209 -0
- data/client/lanes/workspace/styles/screens.scss +67 -0
- data/client/lanes/workspace/styles/tabs.scss +147 -0
- data/client/lanes/workspace/styles/toolbar.scss +4 -0
- data/client/lanes/workspace/styles.scss +20 -0
- data/docs/model.md +39 -7
- data/docs/todo-example-part-1.md +7 -7
- data/docs/view.md +57 -40
- data/lib/lanes/access/authentication_provider.rb +59 -0
- data/lib/lanes/access/config/routes.rb +26 -0
- data/lib/lanes/access/config/screens.rb +16 -0
- data/lib/lanes/access/db/migrate/20140615031600_create_lanes_users.rb +12 -0
- data/lib/lanes/access/extension.rb +40 -0
- data/lib/lanes/access/locked_fields.rb +43 -0
- data/lib/lanes/access/role.rb +60 -0
- data/lib/lanes/access/role_collection.rb +76 -0
- data/lib/lanes/access/roles/administrator.rb +39 -0
- data/lib/lanes/access/roles/support.rb +15 -0
- data/lib/lanes/access/track_modifications.rb +48 -0
- data/lib/lanes/access/user.rb +128 -0
- data/lib/lanes/access/version.rb +5 -0
- data/lib/lanes/access.rb +51 -0
- data/lib/lanes/api/helper_methods.rb +2 -2
- data/lib/lanes/api/javascript_processor.rb +3 -3
- data/lib/lanes/api/null_authentication_provider.rb +1 -1
- data/lib/lanes/api/pub_sub.rb +3 -3
- data/lib/lanes/api/request_wrapper.rb +1 -1
- data/lib/lanes/api/root.rb +1 -2
- data/lib/lanes/api/sprockets_extension.rb +6 -4
- data/lib/lanes/api/test_specs.rb +2 -8
- data/lib/lanes/command/app.rb +30 -12
- data/lib/lanes/command/db.rb +3 -0
- data/lib/lanes/command/generate_model.rb +4 -4
- data/lib/lanes/command/generate_screen.rb +12 -10
- data/lib/lanes/command/generate_view.rb +12 -9
- data/lib/lanes/command/named_command.rb +7 -5
- data/lib/lanes/command/server.rb +1 -1
- data/lib/lanes/command.rb +2 -5
- data/lib/lanes/components.rb +1 -1
- data/lib/lanes/concerns/queries.rb +1 -1
- data/lib/lanes/concerns/set_attribute_data.rb +5 -7
- data/lib/lanes/db.rb +5 -4
- data/lib/lanes/extension/definition.rb +95 -0
- data/lib/lanes/extension.rb +34 -69
- data/lib/lanes/guard_tasks.rb +2 -2
- data/lib/lanes/screen.rb +8 -0
- data/lib/lanes/spec_helper.rb +1 -37
- data/lib/lanes/version.rb +1 -1
- data/lib/lanes/workspace/extension.rb +28 -0
- data/lib/lanes/workspace.rb +7 -0
- data/npm-build/package.json +2 -2
- data/spec/api/javascript_processor_spec.rb +1 -1
- data/spec/lanes/components/grid/GridSpec.coffee +31 -0
- data/{lib/lanes/command/templates/client/views → spec/lanes/helpers}/.gitkeep +0 -0
- data/spec/{helpers → lanes/helpers}/jasmine-matchers.js +0 -0
- data/spec/{helpers → lanes/helpers}/lanes-helpers.coffee +2 -4
- data/spec/lanes/helpers/mock-ajax.js +576 -0
- data/spec/lanes/models/BaseSpec.coffee +24 -37
- data/spec/lanes/models/CollectionSpec.coffee +15 -2
- data/spec/lanes/models/ModelAssociationsSpec.coffee +51 -0
- data/spec/lanes/views/BaseSpec.coffee +14 -14
- data/spec/server/command_spec.rb +39 -0
- data/spec/{concerns → server/concerns}/api_path_spec.rb +1 -1
- data/spec/{concerns → server/concerns}/association_extensions_spec.rb +1 -2
- data/spec/{concerns → server/concerns}/attr_accessor_with_default_spec.rb +0 -0
- data/spec/{concerns → server/concerns}/export_associations_spec.rb +1 -2
- data/spec/{concerns → server/concerns}/export_methods_spec.rb +1 -3
- data/spec/{concerns → server/concerns}/export_scope_spec.rb +2 -2
- data/spec/{concerns → server/concerns}/exported_limits_spec.rb +1 -2
- data/spec/{concerns → server/concerns}/pub_sub_spec.rb +1 -1
- data/spec/{concerns → server/concerns}/set_attribute_data_spec.rb +1 -1
- data/spec/{configuration_spec.rb → server/configuration_spec.rb} +1 -1
- data/spec/{helpers → server}/minitest_assertions.rb +1 -1
- data/spec/{numbers_spec.rb → server/numbers_spec.rb} +1 -2
- data/{lib/lanes/testing_models.rb → spec/server/spec_helper.rb} +17 -3
- data/spec/{strings_spec.rb → server/strings_spec.rb} +1 -1
- data/templates/Gemfile +6 -0
- data/{lib/lanes/command/templates → templates}/Guardfile +0 -0
- data/templates/Rakefile +2 -0
- data/templates/client/Extension.coffee +7 -0
- data/templates/client/Router.coffee +4 -0
- data/{lib/lanes/command/templates/public → templates/client/components}/.gitkeep +0 -0
- data/templates/client/components/Component.coffee +1 -0
- data/{lib/lanes/command/templates → templates}/client/index.js +1 -0
- data/templates/client/models/BaseModel.coffee +5 -0
- data/{lib/lanes/command/templates → templates}/client/models/Model.coffee +2 -3
- data/{lib/lanes/command/templates → templates}/client/screens/Screen.coffee +6 -1
- data/{lib/lanes/command/templates → templates}/client/screens/index.js +0 -0
- data/{lib/lanes/command/templates → templates}/client/screens/layout.html +0 -0
- data/{lib/lanes/command/templates → templates}/client/screens/styles.scss +1 -2
- data/{lib/lanes/command/templates → templates}/client/styles.scss +0 -0
- data/{spec/helpers → templates/client/views}/.gitkeep +0 -0
- data/templates/client/views/BaseView.coffee +5 -0
- data/templates/client/views/View.coffee +10 -0
- data/{lib/lanes/command/templates → templates}/client/views/template.html +0 -0
- data/{lib/lanes/command/templates → templates}/config/database.yml +0 -0
- data/{lib/lanes/command/templates → templates}/config/lanes.rb +0 -0
- data/{lib/lanes/command/templates → templates}/config/routes.rb +0 -0
- data/templates/config/screen.rb +12 -0
- data/{lib/lanes/command/templates → templates}/config.ru +1 -1
- data/{lib/lanes/command/templates → templates}/db/create_table_migration.rb +1 -1
- data/{lib/lanes/command/templates → templates}/gitignore +1 -0
- data/templates/lib/namespace/base_model.rb +11 -0
- data/{lib/lanes/command/templates → templates}/lib/namespace/extension.rb +3 -3
- data/{lib/lanes/command/templates → templates}/lib/namespace/model.rb +1 -1
- data/templates/lib/namespace/version.rb +3 -0
- data/templates/lib/namespace.rb +14 -0
- data/templates/public/.gitkeep +0 -0
- data/templates/spec/client/Screen.coffee +5 -0
- data/templates/spec/client/helpers/ClientHelpers.coffee +5 -0
- data/templates/spec/client/models/ModelSpec.coffee +5 -0
- data/templates/spec/client/views/ViewSpec.coffee +5 -0
- data/{lib/lanes/command/templates → templates}/spec/fixtures/namespace/model.yml +0 -0
- data/{lib/lanes/command/templates/spec/namespace → templates/spec/server}/model_spec.rb +2 -2
- data/{lib/lanes/command/templates/spec/spec_helper.rb → templates/spec/server/spec_helpers.rb} +3 -2
- data/views/index.erb +5 -4
- data/views/specs.erb +2 -1
- metadata +273 -238
- data/client/lanes/components/grid/vendor/dataTables.bootstrap.js +0 -156
- data/client/lanes/components/grid/vendor/datatables.responsive.js +0 -666
- data/client/lanes/components/modal/_index.scss +0 -20
- data/client/lanes/components/popover/_index.scss +0 -1
- data/client/lanes/components/record_finder/RecordFinder.coffee +0 -143
- data/client/lanes/components/select_field/SelectField.coffee +0 -87
- data/client/lanes/extension/GlAccounts.coffee +0 -9
- data/client/lanes/minimal.js +0 -11
- data/client/lanes/minimal.scss.erb +0 -12
- data/client/lanes/styles/components/all.scss +0 -6
- data/client/lanes/styles/components/changes-notification.scss +0 -44
- data/client/lanes/styles/components/suggest.scss +0 -266
- data/client/lanes/styles/index.css +0 -4
- data/client/lanes/styles/layout.scss +0 -272
- data/client/lanes/styles/screens.scss +0 -66
- data/client/lanes/styles/tabs.scss +0 -148
- data/client/lanes/styles/vendor/bootstrap.scss +0 -74
- data/client/lanes/workspace.scss.erb +0 -29
- data/client/lanes-complete.js +0 -3
- data/client/lanes-workspace.scss.erb +0 -21
- data/db/migrate/20140615031600_create_hip_users.rb +0 -17
- data/lib/lanes/command/templates/Gemfile +0 -9
- data/lib/lanes/command/templates/Rakefile +0 -2
- data/lib/lanes/command/templates/client/Extension.coffee +0 -5
- data/lib/lanes/command/templates/client/components/Component.coffee +0 -1
- data/lib/lanes/command/templates/client/models/BaseModel.coffee +0 -5
- data/lib/lanes/command/templates/client/views/BaseView.coffee +0 -5
- data/lib/lanes/command/templates/client/views/View.coffee +0 -7
- data/lib/lanes/command/templates/config/screen.rb +0 -8
- data/lib/lanes/command/templates/lib/namespace/base_model.rb +0 -9
- data/lib/lanes/command/templates/lib/namespace/version.rb +0 -3
- data/lib/lanes/command/templates/lib/namespace.rb +0 -12
- data/lib/lanes/command/templates/spec/client/Screen.coffee +0 -7
- data/lib/lanes/command/templates/spec/client/models/ModelSpec.coffee +0 -5
- data/lib/lanes/command/templates/spec/client/views/ViewSpec.coffee +0 -5
- data/lib/lanes/db/migration_helpers.rb +0 -178
- data/public/javascripts/jasmine_examples/Player.js +0 -22
- data/public/javascripts/jasmine_examples/Song.js +0 -7
- data/spec/command_spec.rb +0 -49
- data/spec/helpers/jasmine-jquery.js +0 -813
@@ -0,0 +1,147 @@
|
|
1
|
+
.active-screens .nav a {
|
2
|
+
background-color: $gray-dark;
|
3
|
+
}
|
4
|
+
|
5
|
+
.header-top {
|
6
|
+
|
7
|
+
|
8
|
+
.menu-container {
|
9
|
+
position:absolute;
|
10
|
+
left: 0;
|
11
|
+
position: absolute;
|
12
|
+
overflow-x: visible;
|
13
|
+
overflow-y: auto;
|
14
|
+
border: 0;
|
15
|
+
top: 5px;
|
16
|
+
transition: all 0.15s ease-in-out 0s;
|
17
|
+
overflow-x: visible;
|
18
|
+
overflow-y: auto;
|
19
|
+
left: 200px;
|
20
|
+
right: 35px;
|
21
|
+
}
|
22
|
+
|
23
|
+
/* &.with-screen-menu { */
|
24
|
+
/* .menu-container { */
|
25
|
+
/* left: 0px; */
|
26
|
+
/* } */
|
27
|
+
/* } */
|
28
|
+
|
29
|
+
|
30
|
+
.active-screens {
|
31
|
+
display: inline-block;
|
32
|
+
}
|
33
|
+
|
34
|
+
.menu-container {
|
35
|
+
.active-screens {
|
36
|
+
width: 100%;
|
37
|
+
.wrapper{
|
38
|
+
position:relative;
|
39
|
+
margin:0 auto;
|
40
|
+
overflow:hidden;
|
41
|
+
padding:5px;
|
42
|
+
height:45px;
|
43
|
+
|
44
|
+
}
|
45
|
+
.nav {
|
46
|
+
position:absolute;
|
47
|
+
left:0px;
|
48
|
+
top: 1px;
|
49
|
+
min-width:3000px;
|
50
|
+
/* margin-left:12px; */
|
51
|
+
margin-top:0px;
|
52
|
+
|
53
|
+
li {
|
54
|
+
display:table-cell;
|
55
|
+
position:relative;
|
56
|
+
text-align:center;
|
57
|
+
cursor:grab;
|
58
|
+
cursor:-webkit-grab;
|
59
|
+
color:#efefef;
|
60
|
+
vertical-align:middle;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
|
64
|
+
.scroller {
|
65
|
+
text-align:center;
|
66
|
+
cursor:pointer;
|
67
|
+
visibility: hidden;
|
68
|
+
padding:7px;
|
69
|
+
padding-top:11px;
|
70
|
+
white-space:no-wrap;
|
71
|
+
vertical-align:middle;
|
72
|
+
color: $link-color;
|
73
|
+
&:hover{
|
74
|
+
color: $link-hover-color;
|
75
|
+
}
|
76
|
+
&.enabled {
|
77
|
+
visibility: visible;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
|
81
|
+
.scroller-right{
|
82
|
+
float:right;
|
83
|
+
&:before {
|
84
|
+
@extend .font-icon-display;
|
85
|
+
@extend .icon-arrow-right:before;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
.scroller-left {
|
90
|
+
float:left;
|
91
|
+
&:before {
|
92
|
+
@extend .font-icon-display;
|
93
|
+
@extend .icon-arrow-left:before;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
|
100
|
+
&.screen-menu-hidden {
|
101
|
+
.menu-container {
|
102
|
+
max-height: 45px;
|
103
|
+
overflow: hidden;
|
104
|
+
}
|
105
|
+
.screens-menu {
|
106
|
+
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
&.screen-menu-visible {
|
111
|
+
.menu-container {
|
112
|
+
top: 50px;
|
113
|
+
left: 0px;
|
114
|
+
right: 0px;
|
115
|
+
/* bottom: unset; */
|
116
|
+
max-height: 300px;
|
117
|
+
}
|
118
|
+
.active-screens {
|
119
|
+
display: none;
|
120
|
+
}
|
121
|
+
}
|
122
|
+
|
123
|
+
.active-screens {
|
124
|
+
|
125
|
+
height: 45px;
|
126
|
+
padding: 0 5px;
|
127
|
+
|
128
|
+
.nav-tabs {
|
129
|
+
border-bottom: 0;
|
130
|
+
position: absolute;
|
131
|
+
bottom: 0px;
|
132
|
+
}
|
133
|
+
|
134
|
+
.close {
|
135
|
+
position: absolute;
|
136
|
+
right: 7px;
|
137
|
+
top: 0px;
|
138
|
+
}
|
139
|
+
|
140
|
+
/* a { */
|
141
|
+
/* white-space: nowrap; */
|
142
|
+
/* } */
|
143
|
+
|
144
|
+
}
|
145
|
+
|
146
|
+
|
147
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
@import "lanes/styles/bootstrap";
|
2
|
+
@import "lanes/styles/fonts";
|
3
|
+
// extensions are rooted at .lanes
|
4
|
+
&{
|
5
|
+
padding: 0px;
|
6
|
+
margin: 0px;
|
7
|
+
background-color: $body-bg;
|
8
|
+
position: relative;
|
9
|
+
min-height: 10px; // needs height for resizing sensor to function
|
10
|
+
}
|
11
|
+
|
12
|
+
@import "styles/layout";
|
13
|
+
@import "styles/header";
|
14
|
+
@import "styles/tabs";
|
15
|
+
@import "styles/screens";
|
16
|
+
@import "styles/toolbar";
|
17
|
+
@import "styles/forms";
|
18
|
+
@import "styles/changes-notification";
|
19
|
+
@import "styles/keybindings";
|
20
|
+
|
data/docs/model.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
---
|
2
2
|
title: Model
|
3
|
-
heading: Lanes.
|
3
|
+
heading: Lanes.Models.Base
|
4
4
|
position_after: view
|
5
5
|
---
|
6
6
|
|
7
|
-
Lanes provides a Lanes.
|
7
|
+
Lanes provides a Lanes.Models.Base class that all other models extend from.
|
8
8
|
|
9
9
|
A Model is an extension of [Ampersand State](http://ampersandjs.com/docs#ampersand-state), and supports all the features that AmpersandState does.
|
10
10
|
|
@@ -22,6 +22,38 @@ Model methods that make requests to the server can specify options to control wh
|
|
22
22
|
|
23
23
|
### API Reference
|
24
24
|
|
25
|
+
# @where
|
26
|
+
|
27
|
+
Load models from server that match the query. Returns [Collection](#@query)
|
28
|
+
|
29
|
+
``` coffee
|
30
|
+
class Person extends Lanes.Models.Base
|
31
|
+
props:
|
32
|
+
id: 'integer'
|
33
|
+
name: 'string'
|
34
|
+
|
35
|
+
|
36
|
+
collection = Person.where( last_name: "smith" )
|
37
|
+
````
|
38
|
+
|
39
|
+
|
40
|
+
# @Collection
|
41
|
+
|
42
|
+
A collection definition is provided for each model.
|
43
|
+
|
44
|
+
Read more about [Request Options](#request-options)
|
45
|
+
|
46
|
+
``` coffee
|
47
|
+
class Person extends Lanes.Models.Base
|
48
|
+
props:
|
49
|
+
id: 'integer'
|
50
|
+
name: 'string'
|
51
|
+
|
52
|
+
|
53
|
+
collection = Person.Collection.fetch(query:{ name: "John" }, limit: 10, with: [ 'address','photo' ] )
|
54
|
+
````
|
55
|
+
|
56
|
+
|
25
57
|
# initialize
|
26
58
|
|
27
59
|
`new Model({options})`
|
@@ -35,7 +67,7 @@ If a collection reference is provided to initalize, it will be copied onto the m
|
|
35
67
|
Fetches and instantiates a record. Is useful for when you all you know is the record's ID. The identity map is consulted, and if the record is present there the existing copy is returned.
|
36
68
|
|
37
69
|
``` coffee
|
38
|
-
class Balance extends Lanes.
|
70
|
+
class Balance extends Lanes.Models.Base
|
39
71
|
props:
|
40
72
|
id: 'integer'
|
41
73
|
amount: 'bigdec'
|
@@ -59,7 +91,7 @@ Saves record state to server. If options.saveAll is true, then the entire data
|
|
59
91
|
Save also saves it's associations along with itself.
|
60
92
|
|
61
93
|
``` coffee
|
62
|
-
class Car extends Lanes.
|
94
|
+
class Car extends Lanes.Models.Base
|
63
95
|
associations:
|
64
96
|
driver: { model: Person }
|
65
97
|
props:
|
@@ -85,7 +117,7 @@ Sets field and values. Marks the fields as unsaved and the record as "dirty".
|
|
85
117
|
returns the field and values that have been modified and the unsavedData from associations as well.
|
86
118
|
|
87
119
|
``` coffee
|
88
|
-
class Car extends Lanes.
|
120
|
+
class Car extends Lanes.Models.Base
|
89
121
|
associations:
|
90
122
|
driver: { model: Person }
|
91
123
|
props:
|
@@ -113,7 +145,7 @@ Returns a string with an appropriate error message for setting the field to valu
|
|
113
145
|
|
114
146
|
If the change is considered valid, an empty string is returned.
|
115
147
|
|
116
|
-
The default implementation only checks the 'required' status of the field. Models inheriting from `Lanes.
|
148
|
+
The default implementation only checks the 'required' status of the field. Models inheriting from `Lanes.Models.Base` may provide an alternative implementation.
|
117
149
|
|
118
150
|
# withAssociations(list...)
|
119
151
|
|
@@ -153,7 +185,7 @@ end
|
|
153
185
|
It can be queried by the client:
|
154
186
|
|
155
187
|
``` coffee
|
156
|
-
class Invoice extends Lanes.
|
188
|
+
class Invoice extends Lanes.Models.Base
|
157
189
|
props:
|
158
190
|
id: 'integer'
|
159
191
|
total: 'bigdec'
|
data/docs/todo-example-part-1.md
CHANGED
@@ -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/
|
18
|
+
[Our example app at this point](https://github.com/argosity/lanes-todo-demo/tree/a0909c52d63d3c8e577bdb4338c91ba74e4b1dfa)
|
19
19
|
|
20
20
|
# Setup
|
21
21
|
|
@@ -25,24 +25,24 @@ Fire up the lanes testing server: `lanes serve`. The test server will start the
|
|
25
25
|
|
26
26
|
We'll copy the styles from the [TodoMVC template](https://github.com/tastejs/todomvc/tree/master/template).
|
27
27
|
|
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/
|
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)
|
29
29
|
|
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/
|
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)
|
31
31
|
|
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/
|
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)
|
33
33
|
|
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/
|
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)
|
35
35
|
|
36
36
|
Run migration: `lanes db migrate`
|
37
37
|
|
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/
|
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)
|
39
39
|
|
40
40
|
# Data and events
|
41
41
|
|
42
42
|
## Header View
|
43
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
44
|
|
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
|
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).
|
46
46
|
|
47
47
|
## Listing View
|
48
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)
|
data/docs/view.md
CHANGED
@@ -56,8 +56,7 @@ All views have a single DOM element. If a view does is not provided an el when
|
|
56
56
|
|
57
57
|
# template
|
58
58
|
|
59
|
-
|
60
|
-
|
59
|
+
Templates are specified either as inline strings on the "template" property, or as an external file with the same name as the view, but with the HTML extension. If an external file is used, embedded CoffeeScript can be used inside it. The name of the external template file can be changed by specifying a `templateName`
|
61
60
|
|
62
61
|
``` coffee
|
63
62
|
class MyView extends Lanes.Views.Base
|
@@ -69,43 +68,41 @@ view.render()
|
|
69
68
|
# view.el.innerHTML => <div><p>Hello World</p></div>
|
70
69
|
```
|
71
70
|
|
72
|
-
|
73
|
-
|
74
|
-
```
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
71
|
+
Given a template file located in `myapp/views/file-list`
|
72
|
+
|
73
|
+
```text
|
74
|
+
<% if @files.length: %>
|
75
|
+
<h1>My Files:</h1>
|
76
|
+
<% for file in @files: %>
|
77
|
+
<p><%= file.name %></p>
|
78
|
+
<% end %>
|
79
|
+
<% else: %>
|
80
|
+
No files
|
81
|
+
<% end %>
|
81
82
|
```
|
82
83
|
|
83
|
-
|
84
84
|
``` coffee
|
85
|
-
# Contained in file
|
86
|
-
|
85
|
+
# Contained in file FileList.coffee
|
87
86
|
class MyApp.Views.MyView extends Lanes.Views.Base
|
88
87
|
source: FILE
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
88
|
+
templateData: ->
|
89
|
+
{
|
90
|
+
files: [
|
91
|
+
{ name: "Gifts" }, { name: "Secrets" }, { name: "Games" }
|
92
|
+
]
|
93
|
+
{
|
94
|
+
|
95
|
+
view = new FileList
|
96
|
+
# will use the "FILE" information to render
|
97
|
+
# template above from "myapp/views/file-list"
|
93
98
|
view.render()
|
94
99
|
```
|
95
100
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
class MyApp.Views.MyView extends Lanes.Views.Base
|
102
|
-
source: FILE
|
103
|
-
templateName: "contents"
|
104
|
-
|
105
|
-
view = new MyView
|
106
|
-
# will use the "source" information to render
|
107
|
-
# a template from "myapp/views/contents"
|
108
|
-
view.render()
|
101
|
+
```html
|
102
|
+
<h1>My Files:</h1>
|
103
|
+
<p>Gifts</p>
|
104
|
+
<p></p>
|
105
|
+
<p>Gifts</p>
|
109
106
|
```
|
110
107
|
|
111
108
|
# subviews
|
@@ -146,7 +143,7 @@ class MyApp.Views.MyView extends Lanes.Views.Base
|
|
146
143
|
<div class='grid'></div>
|
147
144
|
<div class='names'></div>
|
148
145
|
</div>"
|
149
|
-
```
|
146
|
+
```
|
150
147
|
|
151
148
|
Notes:
|
152
149
|
|
@@ -162,9 +159,9 @@ Notes:
|
|
162
159
|
* **names**
|
163
160
|
* Since the "view" is given as a simple string, Lanes will search for it in the MyApp namespace, and will expect `MyApp.Views.NamesItem` to be defined
|
164
161
|
* A collection is specified. A collectionView will be created and the NamesItem class given as the child view to the collectionView. The collectionView will then handle rendering the collection whenever it has items added/removed.
|
165
|
-
|
166
162
|
|
167
|
-
|
163
|
+
|
164
|
+
# subviewOptions
|
168
165
|
|
169
166
|
When subviews are created, they are initialized with an options object containing the parent view, and any other options that are returned by the `subviewOptions` method.
|
170
167
|
|
@@ -183,14 +180,12 @@ class MyApp.Views.MyView extends Lanes.Views.Base
|
|
183
180
|
view: 'Heading'
|
184
181
|
footer:
|
185
182
|
view: 'Footer'
|
186
|
-
subviewOptions: ->
|
183
|
+
subviewOptions: (name,definition)->
|
187
184
|
{model: @model, status: "red"}
|
188
185
|
|
189
186
|
```
|
190
187
|
|
191
|
-
|
192
|
-
|
193
|
-
# events
|
188
|
+
# domEvents
|
194
189
|
|
195
190
|
Listens for DOM events that occur within the view _(under it's el)_. Events are specified as a
|
196
191
|
hash containing "event selector" for the key and either a name of a method or function for the value.
|
@@ -201,13 +196,35 @@ If the selector is ommited, the event will be bound to the root element.
|
|
201
196
|
``` coffee
|
202
197
|
class MyApp.Views.MyView extends Lanes.Views.Base
|
203
198
|
template: "<div><a class='title'>click me!</a></div>"
|
204
|
-
|
199
|
+
domEvents:
|
205
200
|
"click .title": "onTitleClick"
|
206
201
|
"click": -> console.log("I feel like I was clicked somewhere")
|
207
202
|
onTitleClick: ->
|
208
203
|
console.log "Title Was Clicked!"
|
209
204
|
```
|
210
205
|
|
206
|
+
# modelEvents
|
207
|
+
|
208
|
+
### and collectionEvents
|
209
|
+
|
210
|
+
Listens for events fired by the model and calls the given function when they occur.
|
211
|
+
|
212
|
+
The function may be specified as either an inline function, or as a method reference.
|
213
|
+
|
214
|
+
**Note**: The model and collection events are usually not needed. If the only action taken is to update the DOM, it's almost always better to use bindings.
|
215
|
+
|
216
|
+
``` coffee
|
217
|
+
class MyApp.Views.MyView extends Lanes.Views.Base
|
218
|
+
modelEvents:
|
219
|
+
"read", "render"
|
220
|
+
"change:birthday_now", -> alert("Happy Birthday!")
|
221
|
+
collectionEvents:
|
222
|
+
"change:length", "recalcAll"
|
223
|
+
|
224
|
+
recalcAll: (ev)->
|
225
|
+
doStuff()
|
226
|
+
```
|
227
|
+
|
211
228
|
# ui
|
212
229
|
|
213
230
|
A View will often need to access a given DOM element repeatedly. By specifying a the elements as part of the UI property, they will be cached when the view is rendered for speedy access.
|
@@ -220,7 +237,7 @@ class MyApp.Views.MyView extends Lanes.Views.Base
|
|
220
237
|
ui:
|
221
238
|
title: "a.title"
|
222
239
|
template: "<div><a class='title'>click me!</a></div>"
|
223
|
-
|
240
|
+
domEvents:
|
224
241
|
"click @ui.title": "onTitleClick"
|
225
242
|
onTitleClick: ->
|
226
243
|
console.log "Title Was Clicked!"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Lanes
|
2
|
+
module API
|
3
|
+
class AuthenticationProvider
|
4
|
+
|
5
|
+
def initialize(session:nil, params:nil, request_type: type)
|
6
|
+
@session = session
|
7
|
+
@params = params
|
8
|
+
@request_type = request_type
|
9
|
+
end
|
10
|
+
|
11
|
+
def current_user
|
12
|
+
@current_user ||= Lanes::User.where(id: @session['user_id']).first
|
13
|
+
end
|
14
|
+
|
15
|
+
def error_message
|
16
|
+
current_user ? "User not found" : error_message_for_access
|
17
|
+
end
|
18
|
+
|
19
|
+
def error_message_for_access
|
20
|
+
return "Unable to " + case @request_type
|
21
|
+
when 'GET' then "read"
|
22
|
+
when 'POST','PATCH','PUT' then "write"
|
23
|
+
when 'DELETE' then "delete"
|
24
|
+
else
|
25
|
+
"perform action"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def allowed_access_to?(klass)
|
30
|
+
return false if current_user.nil?
|
31
|
+
case @request_type
|
32
|
+
when 'GET'
|
33
|
+
klass.can_read_attributes?(@params,current_user)
|
34
|
+
when 'POST','PATCH','PUT'
|
35
|
+
klass.can_write_attributes?(@params,current_user)
|
36
|
+
when 'DELETE'
|
37
|
+
klass.can_delete_attributes?(@params,current_user)
|
38
|
+
else
|
39
|
+
false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def wrap_request(model, req)
|
44
|
+
if allowed_access_to?(model)
|
45
|
+
::Lanes::User.scoped_to(current_user) do | user |
|
46
|
+
Lanes.logger.debug "User : #{user.id} (#{user.login})"
|
47
|
+
Lanes.logger.debug "Params : #{@params}"
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
else
|
51
|
+
req.halt( 401, Oj.dump({
|
52
|
+
success:false, errors: {user: "Access Denied"}, message: "Access Denied"
|
53
|
+
}))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Lanes
|
2
|
+
API.routes.draw do
|
3
|
+
|
4
|
+
post "/user-session.json" do
|
5
|
+
wrap_json_reply do
|
6
|
+
user = User.where(login: data['login']).first
|
7
|
+
if user && user.authenticate(data['password'])
|
8
|
+
session[:user_id] = user.id
|
9
|
+
{ success: true, message: "Login succeeded", data: user.workspace_data }
|
10
|
+
else
|
11
|
+
{ success: false, message: "Login failed", errors: { login: 'failed' }, data: {} }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
delete "/user-session/:id.json" do
|
17
|
+
session.destroy
|
18
|
+
wrap_json_reply do
|
19
|
+
{ success: true, message: "Logout succeeded", data: {} }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
resources User
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
Lanes::Screen.define "user-management" do | screen |
|
2
|
+
screen.title = "User Management"
|
3
|
+
screen.description = "Add/Remove/Modify User Accounts"
|
4
|
+
screen.icon = "icon-group"
|
5
|
+
screen.group_id = "system-settings"
|
6
|
+
screen.model_class = "User"
|
7
|
+
screen.view_class = "Lanes.Access.Screens.UserManagement"
|
8
|
+
screen.js = 'lanes/access/screens/user-management.js'
|
9
|
+
screen.css = 'lanes/access/screens/user-management.css'
|
10
|
+
end
|
11
|
+
|
12
|
+
Lanes::Screen.define_group "system-settings" do | group |
|
13
|
+
group.title = "System Settings"
|
14
|
+
group.description = "Modify system settings"
|
15
|
+
group.icon = "icon-wrench"
|
16
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class CreateLanesUsers < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table "lanes_users" do | t |
|
4
|
+
t.string :login, :name, :email, null: false
|
5
|
+
t.string :password_digest, null: false
|
6
|
+
t.string "role_names", array: true, null:false, default: []
|
7
|
+
t.hstore "options", null: false, default: {}
|
8
|
+
t.timestamps null:false
|
9
|
+
end
|
10
|
+
add_index :lanes_users, :role_names, using: 'gin'
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative '../workspace/extension'
|
2
|
+
|
3
|
+
module Lanes
|
4
|
+
module Access
|
5
|
+
class Extension < Lanes::Extensions::Definition
|
6
|
+
|
7
|
+
identifier "lanes-access"
|
8
|
+
|
9
|
+
components 'modal', 'grid', 'select-field'
|
10
|
+
|
11
|
+
root_path Pathname.new(__FILE__).dirname.expand_path
|
12
|
+
|
13
|
+
def stylesheet_include
|
14
|
+
'lanes/access/styles'
|
15
|
+
end
|
16
|
+
|
17
|
+
def javascript_include
|
18
|
+
'lanes/access'
|
19
|
+
end
|
20
|
+
|
21
|
+
def client_namespace
|
22
|
+
'Access'
|
23
|
+
end
|
24
|
+
|
25
|
+
def client_paths
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
|
29
|
+
def client_bootstrap_data(view)
|
30
|
+
data = {}
|
31
|
+
if (user_id = view.session['user_id']) && (user = Lanes::User.where( id: user_id ).first)
|
32
|
+
data.merge!(user.workspace_data)
|
33
|
+
end
|
34
|
+
data
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Lanes
|
2
|
+
module Access
|
3
|
+
|
4
|
+
class LockedFields
|
5
|
+
|
6
|
+
@definitions = Hash.new{ |fields,klass|
|
7
|
+
fields[klass] = Hash.new{ |grants,field| grants[field] = [] }
|
8
|
+
}
|
9
|
+
class << self
|
10
|
+
|
11
|
+
# @param klass [Lanes::Model]
|
12
|
+
# @param field [Symbol]
|
13
|
+
# @param access_type [:read, :write]
|
14
|
+
# @return [Array<Role>] Roles that are allowed to access the field.
|
15
|
+
# An empty array indicates that the field is not locked and the Model
|
16
|
+
# should be used for determining access
|
17
|
+
def roles_needed_for(klass, attribute, access_type)
|
18
|
+
if @definitions.has_key?(klass) && @definitions[klass].has_key?(attribute)
|
19
|
+
@definitions[klass][attribute].each_with_object([]) do | grant, result |
|
20
|
+
result.push(grant[:role]) if grant[:only].nil? || grant[:only] == access_type
|
21
|
+
end
|
22
|
+
else
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Lock a given class and attribute to a given role
|
28
|
+
# @param klass [Lanes::Model]
|
29
|
+
# @param field [Symbol]
|
30
|
+
# @param only [:read, :write]
|
31
|
+
def lock(klass, field, role, only=nil)
|
32
|
+
@definitions[klass][field] << { role: role, only: only }
|
33
|
+
end
|
34
|
+
|
35
|
+
def definitions
|
36
|
+
@definitions
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|