underworld 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/LICENSE +339 -0
- data/Rakefile +48 -0
- data/app/assets/fonts/DroidNaskh-Bold.ttf +0 -0
- data/app/assets/fonts/DroidNaskh-Regular.ttf +0 -0
- data/app/assets/fonts/OpenSans-Bold.ttf +0 -0
- data/app/assets/fonts/OpenSans-BoldItalic.ttf +0 -0
- data/app/assets/fonts/OpenSans-ExtraBold.ttf +0 -0
- data/app/assets/fonts/OpenSans-ExtraBoldItalic.ttf +0 -0
- data/app/assets/fonts/OpenSans-Italic.ttf +0 -0
- data/app/assets/fonts/OpenSans-Light.ttf +0 -0
- data/app/assets/fonts/OpenSans-LightItalic.ttf +0 -0
- data/app/assets/fonts/OpenSans-Regular.ttf +0 -0
- data/app/assets/fonts/OpenSans-Semibold.ttf +0 -0
- data/app/assets/fonts/OpenSans-SemiboldItalic.ttf +0 -0
- data/app/assets/images/underworld/select2-spinner.gif +0 -0
- data/app/assets/images/underworld/select2.png +0 -0
- data/app/assets/images/underworld/select2x2.png +0 -0
- data/app/assets/javascripts/underworld/application.js +16 -0
- data/app/assets/javascripts/underworld/dashboard/application.js.erb +30 -0
- data/app/assets/javascripts/underworld/dashboard/functions.js.erb +50 -0
- data/app/assets/javascripts/underworld/dashboard/init.js.coffee +33 -0
- data/app/assets/javascripts/underworld/dashboard/lib/actions.js +7 -0
- data/app/assets/javascripts/underworld/dashboard/lib/amd.js.coffee.erb +0 -0
- data/app/assets/javascripts/underworld/dashboard/lib/flash_message.js +71 -0
- data/app/assets/javascripts/underworld/dashboard/lib/locale.js +14 -0
- data/app/assets/javascripts/underworld/dashboard/lib/misc.js +5 -0
- data/app/assets/javascripts/underworld/dashboard/lib/string.js +3 -0
- data/app/assets/javascripts/underworld/dashboard/lib/ujs_patches.js.coffee +28 -0
- data/app/assets/javascripts/underworld/dashboard/manifest.js +5 -0
- data/app/assets/javascripts/underworld/dashboard/variables.js.erb +6 -0
- data/app/assets/javascripts/underworld/groups.js +2 -0
- data/app/assets/javascripts/underworld/home.js +2 -0
- data/app/assets/javascripts/underworld/i18n.js +13 -0
- data/app/assets/javascripts/underworld/simple.js +20 -0
- data/app/assets/javascripts/underworld/users.js +2 -0
- data/app/assets/stylesheets/underworld/dashboard/loadindicator.scss +17 -0
- data/app/assets/stylesheets/underworld/dashboard/ltr/application.css +38 -0
- data/app/assets/stylesheets/underworld/dashboard/ltr/base.css.scss +0 -0
- data/app/assets/stylesheets/underworld/dashboard/rtl/application.css +11 -0
- data/app/assets/stylesheets/underworld/dashboard/rtl/base.css.scss +0 -0
- data/app/assets/stylesheets/underworld/dashboard/share.scss +62 -0
- data/app/assets/stylesheets/underworld/dashboard/variables.scss +9 -0
- data/app/assets/stylesheets/underworld/ltr/application.css +0 -0
- data/app/assets/stylesheets/underworld/rtl/application.css +0 -0
- data/app/assets/stylesheets/underworld/simple/ltr/application.css +2 -0
- data/app/assets/stylesheets/underworld/simple/rtl/application.css +2 -0
- data/app/assets/stylesheets/underworld/simple/rtl/rtl.scss +16 -0
- data/app/assets/stylesheets/underworld/simple/share.scss +11 -0
- data/app/controllers/underworld/api_controller.rb +133 -0
- data/app/controllers/underworld/application_controller.rb +16 -0
- data/app/controllers/underworld/assets_controller.rb +6 -0
- data/app/controllers/underworld/dashboard/application_controller.rb +43 -0
- data/app/controllers/underworld/dashboard/groups_controller.rb +85 -0
- data/app/controllers/underworld/dashboard/profile_controller.rb +49 -0
- data/app/controllers/underworld/dashboard/user_messages_controller.rb +27 -0
- data/app/controllers/underworld/dashboard/users_controller.rb +116 -0
- data/app/controllers/underworld/dashboard_controller.rb +16 -0
- data/app/controllers/underworld/omniauth/callbacks_controller.rb +24 -0
- data/app/helpers/underworld/application_helper.rb +4 -0
- data/app/helpers/underworld/dashboard_helper.rb +107 -0
- data/app/helpers/underworld/groups_helper.rb +4 -0
- data/app/helpers/underworld/home_helper.rb +4 -0
- data/app/helpers/underworld/users_helper.rb +8 -0
- data/app/models/application_record.rb +3 -0
- data/app/models/underworld/concerns/assignment.rb +16 -0
- data/app/models/underworld/concerns/user/auth_definitions.rb +87 -0
- data/app/models/underworld/concerns/user/gravatar.rb +11 -0
- data/app/models/underworld/concerns/user/mongoid_fields.rb +81 -0
- data/app/models/underworld/concerns/user/permission.rb +47 -0
- data/app/models/underworld/concerns/user/user_roles.rb +24 -0
- data/app/models/underworld/group.rb +57 -0
- data/app/models/underworld/permission.rb +43 -0
- data/app/models/underworld/user.rb +81 -0
- data/app/models/underworld/user_message.rb +6 -0
- data/app/policies/underworld/admin_only_policy.rb +66 -0
- data/app/policies/underworld/application_policy.rb +55 -0
- data/app/policies/underworld/group_policy.rb +8 -0
- data/app/policies/underworld/user_message_policy.rb +9 -0
- data/app/policies/underworld/user_policy.rb +9 -0
- data/app/views/angular/auth/groups/details.html +2 -0
- data/app/views/angular/auth/groups/index.html +2 -0
- data/app/views/angular/auth/groups/new.html +2 -0
- data/app/views/angular/auth/index.html +30 -0
- data/app/views/angular/auth/profile/edit.html +54 -0
- data/app/views/angular/auth/users/details.html +28 -0
- data/app/views/angular/auth/users/index.html +6 -0
- data/app/views/angular/auth/users/new.html +57 -0
- data/app/views/angular/conversations/details.html +19 -0
- data/app/views/angular/conversations/index.html +13 -0
- data/app/views/angular/conversations/new.html +39 -0
- data/app/views/angular/conversations/show.html +6 -0
- data/app/views/angular/conversations/show_details.html +15 -0
- data/app/views/angular/fields/boolean/boolean.html +4 -0
- data/app/views/angular/fields/control-combo/control-list.html +19 -0
- data/app/views/angular/fields/datetime/datetime.html +10 -0
- data/app/views/angular/fields/datetime/time.html +25 -0
- data/app/views/angular/fields/file/file.html.slim +0 -0
- data/app/views/angular/fields/float/float.html +4 -0
- data/app/views/angular/fields/image/image.html +1 -0
- data/app/views/angular/fields/integer/integer.html +4 -0
- data/app/views/angular/fields/relation/relation.html +44 -0
- data/app/views/angular/fields/string/string.html +22 -0
- data/app/views/angular/fields/tag/tag.html +1 -0
- data/app/views/angular/fields/text/text.html +4 -0
- data/app/views/angular/filter/index.html +15 -0
- data/app/views/angular/index.html +3 -0
- data/app/views/angular/locale/fa.po +25 -0
- data/app/views/angular/locale/templates.pot +24 -0
- data/app/views/angular/logs/index.html +6 -0
- data/app/views/angular/modules.html +0 -0
- data/app/views/angular/nav.html.erb +39 -0
- data/app/views/angular/underworld/views/generic_add_view.html.slim +5 -0
- data/app/views/devise/registrations/edit.html.erb +29 -0
- data/app/views/devise/registrations/new.html.erb +38 -0
- data/app/views/devise/sessions/new.html.erb +37 -0
- data/app/views/devise/shared/_links.erb +19 -0
- data/app/views/devise/shared/_omni_link.erb +33 -0
- data/app/views/kaminari/_first_page.html.slim +3 -0
- data/app/views/kaminari/_gap.html.slim +2 -0
- data/app/views/kaminari/_last_page.html.slim +3 -0
- data/app/views/kaminari/_next_page.html.slim +3 -0
- data/app/views/kaminari/_page.html.slim +3 -0
- data/app/views/kaminari/_paginator.html.slim +13 -0
- data/app/views/kaminari/_prev_page.html.slim +3 -0
- data/app/views/layouts/underworld/application.html.erb +79 -0
- data/app/views/layouts/underworld/dashboard.html.erb +52 -0
- data/app/views/layouts/underworld/simple.html.erb +27 -0
- data/app/views/underworld/api/v1/conversations/create.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/conversations/destroy.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/conversations/index.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/conversations/reply.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/conversations/show.json.jbuilder +14 -0
- data/app/views/underworld/api/v1/conversations/trash.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/groups/create.json.jbuilder +4 -0
- data/app/views/underworld/api/v1/groups/destroy.html.erb +2 -0
- data/app/views/underworld/api/v1/groups/destroy.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/groups/edit.html.erb +2 -0
- data/app/views/underworld/api/v1/groups/index.html.erb +2 -0
- data/app/views/underworld/api/v1/groups/index.json.jbuilder +6 -0
- data/app/views/underworld/api/v1/groups/new.html.erb +2 -0
- data/app/views/underworld/api/v1/groups/show.html.erb +2 -0
- data/app/views/underworld/api/v1/groups/show.json.jbuilder +5 -0
- data/app/views/underworld/api/v1/groups/update.json.jbuilder +4 -0
- data/app/views/underworld/api/v1/logs/index.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/permissions/index.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/permissions/user_permissions.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/users/create.html.erb +2 -0
- data/app/views/underworld/api/v1/users/create.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/users/destroy.json.jbuilder +1 -0
- data/app/views/underworld/api/v1/users/distroy.html.erb +2 -0
- data/app/views/underworld/api/v1/users/edit.html.erb +2 -0
- data/app/views/underworld/api/v1/users/index.html.erb +2 -0
- data/app/views/underworld/api/v1/users/index.json.jbuilder +4 -0
- data/app/views/underworld/api/v1/users/show.html.erb +2 -0
- data/app/views/underworld/api/v1/users/show.json.jbuilder +2 -0
- data/app/views/underworld/api/v1/users/update.json.jbuilder +1 -0
- data/app/views/underworld/dashboard/groups/_form.html.slim +68 -0
- data/app/views/underworld/dashboard/groups/create.js.erb +3 -0
- data/app/views/underworld/dashboard/groups/edit.html.slim +3 -0
- data/app/views/underworld/dashboard/groups/errors.js.erb +3 -0
- data/app/views/underworld/dashboard/groups/index.html.slim +47 -0
- data/app/views/underworld/dashboard/groups/new.html.slim +2 -0
- data/app/views/underworld/dashboard/groups/update.js.erb +3 -0
- data/app/views/underworld/dashboard/index.html.erb +0 -0
- data/app/views/underworld/dashboard/login_required_page.html.erb +5 -0
- data/app/views/underworld/dashboard/not_found.html.slim +9 -0
- data/app/views/underworld/dashboard/not_found.js.erb +1 -0
- data/app/views/underworld/dashboard/profile/_form.html.erb +33 -0
- data/app/views/underworld/dashboard/profile/_profile_form.html.erb +33 -0
- data/app/views/underworld/dashboard/profile/create.js.erb +3 -0
- data/app/views/underworld/dashboard/profile/edit.html.erb +2 -0
- data/app/views/underworld/dashboard/profile/edit_password.html.erb +2 -0
- data/app/views/underworld/dashboard/profile/errors.js.erb +3 -0
- data/app/views/underworld/dashboard/resource/_form.html.slim +33 -0
- data/app/views/underworld/dashboard/resource/_input.html.slim +3 -0
- data/app/views/underworld/dashboard/resource/create.js.erb +3 -0
- data/app/views/underworld/dashboard/resource/destroy.js.erb +2 -0
- data/app/views/underworld/dashboard/resource/edit.html.slim +3 -0
- data/app/views/underworld/dashboard/resource/index.html.slim +60 -0
- data/app/views/underworld/dashboard/resource/new.html.slim +2 -0
- data/app/views/underworld/dashboard/resource/show.html.slim +22 -0
- data/app/views/underworld/dashboard/resource/update.js.erb +3 -0
- data/app/views/underworld/dashboard/shared/_content_header.html.slim +15 -0
- data/app/views/underworld/dashboard/shared/_control_sidebar.html.slim +50 -0
- data/app/views/underworld/dashboard/shared/_footer.html.slim +7 -0
- data/app/views/underworld/dashboard/shared/_header.html.erb +98 -0
- data/app/views/underworld/dashboard/shared/_sidebar.html.erb +69 -0
- data/app/views/underworld/dashboard/shared/_toolbar.html.slim +0 -0
- data/app/views/underworld/dashboard/shared/errors.js.erb +3 -0
- data/app/views/underworld/dashboard/user_messages/_form.html.slim +0 -0
- data/app/views/underworld/dashboard/user_messages/create.js.erb +0 -0
- data/app/views/underworld/dashboard/user_messages/destroy.js.erb +0 -0
- data/app/views/underworld/dashboard/user_messages/new.html.slim +72 -0
- data/app/views/underworld/dashboard/users/_form.html.slim +73 -0
- data/app/views/underworld/dashboard/users/_password_form.html.slim +37 -0
- data/app/views/underworld/dashboard/users/create.js.erb +3 -0
- data/app/views/underworld/dashboard/users/destroy.js.erb +2 -0
- data/app/views/underworld/dashboard/users/edit.html.slim +3 -0
- data/app/views/underworld/dashboard/users/edit_password.html.slim +1 -0
- data/app/views/underworld/dashboard/users/errors.js.erb +3 -0
- data/app/views/underworld/dashboard/users/index.html.slim +66 -0
- data/app/views/underworld/dashboard/users/new.html.slim +2 -0
- data/app/views/underworld/dashboard/users/show.html.slim +6 -0
- data/app/views/underworld/dashboard/users/update.js.erb +3 -0
- data/app/views/underworld/dashboard/users/update_password.js.erb +3 -0
- data/app/views/underworld/relations/_belongs_to.json.jbuilder +11 -0
- data/config/initializers/devise.rb +24 -0
- data/config/locales/devise.en.yml +59 -0
- data/config/locales/devise.fa.yml +58 -0
- data/config/locales/underworld.en.yml +96 -0
- data/config/locales/underworld.fa.yml +108 -0
- data/config/routes.rb +43 -0
- data/config/spring.rb +1 -0
- data/db/migrate/20131013091000_devise_create_underworld_users.rb +65 -0
- data/db/migrate/20131020124701_create_underworld_groups.rb +15 -0
- data/db/migrate/20131021170923_create_underworld_permissions.rb +15 -0
- data/db/migrate/20131123120422_add_permissions_groups_table.rb +16 -0
- data/db/migrate/20140613120923_add_users_groups_table.rb +13 -0
- data/db/migrate/20151122115129_add_uniqueness_index_to_users_groups.rb +11 -0
- data/db/migrate/20160310105736_create_underworld_user_messages.rb +25 -0
- data/db/seeds.rb +49 -0
- data/lib/generators/underworld/install_generator.rb +108 -0
- data/lib/generators/underworld/resource_generator.rb +70 -0
- data/lib/generators/underworld/resources_generator.rb +20 -0
- data/lib/generators/underworld/templates/README +21 -0
- data/lib/generators/underworld/templates/SPECS +13 -0
- data/lib/generators/underworld/templates/api/controller.rb.erb +60 -0
- data/lib/generators/underworld/templates/api_controller.rb +2 -0
- data/lib/generators/underworld/templates/dashboard/controller.rb.erb +2 -0
- data/lib/generators/underworld/templates/dashboard_controller.rb +18 -0
- data/lib/generators/underworld/templates/devise.rb +251 -0
- data/lib/generators/underworld/templates/features/api.feature +92 -0
- data/lib/generators/underworld/templates/features/api.step.rb +7 -0
- data/lib/generators/underworld/templates/features/step_definitions/email_steps.rb +206 -0
- data/lib/generators/underworld/templates/features/support/email_spec.rb +1 -0
- data/lib/generators/underworld/templates/features/support/env.rb +79 -0
- data/lib/generators/underworld/templates/javascripts/application.js +19 -0
- data/lib/generators/underworld/templates/policy/application_policy.rb +2 -0
- data/lib/generators/underworld/templates/policy/policy.rb.erb +2 -0
- data/lib/generators/underworld/templates/seeds.rb +1 -0
- data/lib/generators/underworld/templates/spec/factories/groups.rb +5 -0
- data/lib/generators/underworld/templates/spec/factories/users.rb +10 -0
- data/lib/generators/underworld/templates/spec/spec_helper.rb +69 -0
- data/lib/generators/underworld/templates/spec/support/devise.rb +3 -0
- data/lib/generators/underworld/templates/stylesheets/dashboard/ltr/application.css +3 -0
- data/lib/generators/underworld/templates/stylesheets/dashboard/rtl/application.css +3 -0
- data/lib/generators/underworld/templates/stylesheets/ltr/application.css +3 -0
- data/lib/generators/underworld/templates/stylesheets/rtl/application.css +3 -0
- data/lib/generators/underworld/templates/underworld.rb +12 -0
- data/lib/generators/underworld/templates/views/create.json.jbuilder.erb +3 -0
- data/lib/generators/underworld/templates/views/destroy.json.jbuilder.erb +1 -0
- data/lib/generators/underworld/templates/views/index.json.jbuilder.erb +13 -0
- data/lib/generators/underworld/templates/views/show.json.jbuilder.erb +6 -0
- data/lib/generators/underworld/templates/views/update.json.jbuilder.erb +6 -0
- data/lib/generators/underworld/views_generator.rb +57 -0
- data/lib/tasks/docs.rake +6 -0
- data/lib/tasks/sync.rake +9 -0
- data/lib/tasks/underworld_tasks.rake +38 -0
- data/lib/underworld.rb +35 -0
- data/lib/underworld/action_dispatch.rb +3 -0
- data/lib/underworld/api.rb +42 -0
- data/lib/underworld/api/groups_api.rb +41 -0
- data/lib/underworld/api/permissions_api.rb +24 -0
- data/lib/underworld/api/root.rb +15 -0
- data/lib/underworld/api/users_api.rb +20 -0
- data/lib/underworld/concerns.rb +7 -0
- data/lib/underworld/concerns/authorizable.rb +81 -0
- data/lib/underworld/configuration.rb +97 -0
- data/lib/underworld/dashboard.rb +11 -0
- data/lib/underworld/dashboard/dsl.rb +41 -0
- data/lib/underworld/dashboard/dsl/base.rb +133 -0
- data/lib/underworld/dashboard/dsl/create.rb +116 -0
- data/lib/underworld/dashboard/dsl/form_fields_properties.rb +62 -0
- data/lib/underworld/dashboard/dsl/index.rb +45 -0
- data/lib/underworld/dashboard/dsl/show.rb +6 -0
- data/lib/underworld/dashboard/dsl/update.rb +6 -0
- data/lib/underworld/dashboard/helpers/box_helpers.rb +129 -0
- data/lib/underworld/dashboard/models.rb +2 -0
- data/lib/underworld/dashboard/models/sidebar.rb +139 -0
- data/lib/underworld/dashboard/sections.rb +2 -0
- data/lib/underworld/dashboard/sections/resource.rb +229 -0
- data/lib/underworld/dashboard/sections/resource_create.rb +263 -0
- data/lib/underworld/dashboard/sections/resource_destroy.rb +27 -0
- data/lib/underworld/dashboard/sections/resource_show.rb +96 -0
- data/lib/underworld/dashboard/sections/resources_index.rb +113 -0
- data/lib/underworld/dashboard/sections/sidebar.rb +41 -0
- data/lib/underworld/discovery.rb +8 -0
- data/lib/underworld/discovery/permissions.rb +49 -0
- data/lib/underworld/engine.rb +53 -0
- data/lib/underworld/exceptions.rb +7 -0
- data/lib/underworld/extension.rb +18 -0
- data/lib/underworld/extension/base.rb +29 -0
- data/lib/underworld/fake_assets.rb +5 -0
- data/lib/underworld/i18n.rb +101 -0
- data/lib/underworld/initialize.rb +0 -0
- data/lib/underworld/liquid.rb +7 -0
- data/lib/underworld/liquid/block.rb +14 -0
- data/lib/underworld/liquid/render_tag.rb +50 -0
- data/lib/underworld/liquid/tag.rb +51 -0
- data/lib/underworld/middlewares.rb +1 -0
- data/lib/underworld/middlewares/locale.rb +29 -0
- data/lib/underworld/omniauth.rb +8 -0
- data/lib/underworld/omniauth/callbacks.rb +39 -0
- data/lib/underworld/orm.rb +30 -0
- data/lib/underworld/routes.rb +117 -0
- data/lib/underworld/version.rb +3 -0
- data/test/controllers/underworld/dashboard/resource_test.rb +118 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/javascripts/dashboard/application.js +19 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/assets/stylesheets/dashboard/ltr/application.css +3 -0
- data/test/dummy/app/assets/stylesheets/dashboard/rtl/application.css +3 -0
- data/test/dummy/app/assets/stylesheets/ltr/application.css +3 -0
- data/test/dummy/app/assets/stylesheets/rtl/application.css +3 -0
- data/test/dummy/app/controllers/api_controller.rb +2 -0
- data/test/dummy/app/controllers/application_controller.rb +6 -0
- data/test/dummy/app/controllers/dashboard/application_controller.rb +18 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/policies/application_policy.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +38 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/devise.rb +251 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/formstatic.rb +76 -0
- data/test/dummy/config/initializers/formtastic.rb +110 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/kaminari_config.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/underworld.rb +11 -0
- data/test/dummy/config/initializers/underworld_assets.rb +1 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +13 -0
- data/test/dummy/lib/templates/slim/scaffold/_form.html.slim +8 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/fabricators/underworld/groups.rb +27 -0
- data/test/fabricators/underworld/permissions.rb +14 -0
- data/test/fabricators/underworld/users.rb +17 -0
- data/test/generators/install_generator_test.rb +84 -0
- data/test/integration/underworld/authentication_test.rb +36 -0
- data/test/integration/underworld/dashboard_test.rb +64 -0
- data/test/test_helper.rb +72 -0
- metadata +1045 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
#require_dependency 'underworld/dashboard/dsl'
|
2
|
+
|
3
|
+
module Underworld::Dashboard
|
4
|
+
autoload :DSL, 'underworld/dashboard/dsl'
|
5
|
+
|
6
|
+
module Helpers
|
7
|
+
end
|
8
|
+
|
9
|
+
autoload :Models, 'underworld/dashboard/models'
|
10
|
+
autoload :Sections, 'underworld/dashboard/sections.rb'
|
11
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require_dependency 'underworld/dashboard/dsl/form_fields_properties'
|
2
|
+
require_dependency 'underworld/dashboard/sections/resource'
|
3
|
+
require_dependency 'underworld/dashboard/sections/resources_index'
|
4
|
+
require_dependency 'underworld/dashboard/sections/resource_create'
|
5
|
+
require_dependency 'underworld/dashboard/sections/resource_show'
|
6
|
+
require_dependency 'underworld/dashboard/sections/resource_destroy'
|
7
|
+
require_dependency 'underworld/dashboard/sections/sidebar'
|
8
|
+
|
9
|
+
module Underworld::Dashboard
|
10
|
+
module DSL
|
11
|
+
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
include Underworld::Dashboard::Sections::Resource
|
15
|
+
include Underworld::Dashboard::Sections::ResourcesIndex
|
16
|
+
include Underworld::Dashboard::Sections::ResourceCreate
|
17
|
+
include Underworld::Dashboard::Sections::ResourceShow
|
18
|
+
include Underworld::Dashboard::Sections::ResourceDestroy
|
19
|
+
include Underworld::Dashboard::Sections::Sidebar
|
20
|
+
|
21
|
+
attr_accessor :_override_views
|
22
|
+
|
23
|
+
def _override_views
|
24
|
+
@_override_views ||= []
|
25
|
+
end
|
26
|
+
|
27
|
+
module ClassMethods
|
28
|
+
# override the default view for given views or the result
|
29
|
+
# of the given block, by the one from the application
|
30
|
+
def override_views(*views, &block)
|
31
|
+
|
32
|
+
define_method(:_override_views) do
|
33
|
+
result = views || []
|
34
|
+
result.concat(block.call) if block_given?
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Underworld::Dashboard::DSL
|
4
|
+
class Base
|
5
|
+
attr_reader(:action_buttons, :fields, :model, :default_scope,
|
6
|
+
:action_buttons)
|
7
|
+
|
8
|
+
# Base class for all the DSL property classes to be
|
9
|
+
# used as the yielded object inside each section DSL
|
10
|
+
# scope.
|
11
|
+
#
|
12
|
+
# For example the below code will yield an instance of
|
13
|
+
# one of this class children.
|
14
|
+
#
|
15
|
+
# in_index do
|
16
|
+
# # This will yield an instance of this class child
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# The most important note in this class is that all the public
|
20
|
+
# methods that their name starts with an underscore (_) not meant to
|
21
|
+
# be used as DSL.
|
22
|
+
def initialize(model)
|
23
|
+
@action_buttons = []
|
24
|
+
@model = model
|
25
|
+
@fields = resolve_model_reflections
|
26
|
+
@fields_type = {}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Allow user to specify an array of model attributes to be used
|
30
|
+
# in respected section. For example attributes to show as header
|
31
|
+
# columns in index section
|
32
|
+
def attributes(*fields_name, **options, &block)
|
33
|
+
if options.include? :except
|
34
|
+
@fields = resolve_model_reflections.reject do |field|
|
35
|
+
options[:except].include? field.to_sym
|
36
|
+
end
|
37
|
+
elsif options.include? :append
|
38
|
+
|
39
|
+
@fields += options[:append]
|
40
|
+
else
|
41
|
+
|
42
|
+
# Check for valid field names
|
43
|
+
fields_name.each do |name|
|
44
|
+
unless @fields.include? name.to_s
|
45
|
+
raise ArgumentError, "can't find '#{name}' field for model '#{model}'."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
# set new value for fields
|
49
|
+
@fields = fields_name.map(&:to_s) unless fields_name.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
@fields.concat(block.call.map(&:to_s)) if block_given?
|
53
|
+
end
|
54
|
+
|
55
|
+
# Return the default scope for current properties object.
|
56
|
+
# scope will be used to fetch all the records for the given
|
57
|
+
# section. The Default implementation belongs to index section
|
58
|
+
# and return a page aware list of all the objects.
|
59
|
+
#
|
60
|
+
# You can easily change it via the corresponding section dsl.
|
61
|
+
# For example in case of `index` section:
|
62
|
+
#
|
63
|
+
# in_index do |index|
|
64
|
+
# index.scope do |params|
|
65
|
+
# YourModel.all
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# # or ...
|
69
|
+
#
|
70
|
+
# scope :my_scope
|
71
|
+
# end
|
72
|
+
#
|
73
|
+
# private
|
74
|
+
# def my_scope
|
75
|
+
# YourModel.where(...)
|
76
|
+
#
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# Arguments:
|
80
|
+
# * **params**: Is the same params passed to controller action.
|
81
|
+
def scope(name = nil, &block)
|
82
|
+
return @default_scope = block if block_given?
|
83
|
+
@default_scope = name.to_sym
|
84
|
+
end
|
85
|
+
|
86
|
+
# Define a new action on the `action` place of the current section
|
87
|
+
# **options**: Is a hash which contains the action button properties.
|
88
|
+
#
|
89
|
+
# `name`: Label to use with the button.
|
90
|
+
# `href`: The link href to use in the `a` tag
|
91
|
+
# `class`: classes of the button.
|
92
|
+
# `icon_class`: font awesome icon to use in button.
|
93
|
+
def action_button(**options)
|
94
|
+
@action_buttons ||= []
|
95
|
+
@action_buttons << options
|
96
|
+
@action_buttons.uniq!
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
# Replace foreign key names with their reflection names
|
102
|
+
# and create an array of model fields
|
103
|
+
def resolve_model_reflections
|
104
|
+
# TODO: cach the result using and instance_var or something
|
105
|
+
reflections = model.reflections
|
106
|
+
columns = Set.new model.column_names
|
107
|
+
new_fields = Set.new
|
108
|
+
fields_to_remove = Set.new
|
109
|
+
|
110
|
+
reflections.each do |name, column|
|
111
|
+
has_many = ActiveRecord::Reflection::HasManyReflection
|
112
|
+
has_and_belongs_to_many = ActiveRecord::Reflection::HasAndBelongsToManyReflection
|
113
|
+
|
114
|
+
if !column.is_a?(has_many) && !column.is_a?(has_and_belongs_to_many)
|
115
|
+
new_fields << name.to_s
|
116
|
+
fields_to_remove << column.foreign_key.to_s
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
if model.respond_to? :attachment_definitions
|
121
|
+
# Paperclip is installed and model contains attachments
|
122
|
+
model.attachment_definitions.each do |name, _|
|
123
|
+
new_fields << name.to_s
|
124
|
+
["file_name", "content_type", "file_size", "updated_at"].each do |x|
|
125
|
+
fields_to_remove << "#{name}_#{x}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
columns.union(new_fields) - fields_to_remove
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require_dependency 'underworld/dashboard/dsl/base'
|
2
|
+
|
3
|
+
module Underworld::Dashboard::DSL
|
4
|
+
class Create < Base
|
5
|
+
|
6
|
+
def initialize(model)
|
7
|
+
super
|
8
|
+
@field_details = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
# Specify attributes details, for example if you want to change a datetime
|
12
|
+
# field type to string you need to do like this:
|
13
|
+
#
|
14
|
+
# in_form do
|
15
|
+
# attributes_properties date: { as: :string }
|
16
|
+
# end
|
17
|
+
def attributes_properties(**options)
|
18
|
+
options_set = Set.new options.keys.map(&:to_s)
|
19
|
+
|
20
|
+
unless options_set.subset? Set.new(@fields)
|
21
|
+
fail "You have to provide correct attribute names in" +
|
22
|
+
"'attributes_properties' for '#{@model}'."
|
23
|
+
end
|
24
|
+
|
25
|
+
# TODO: Check for valid value for each key
|
26
|
+
@field_details = options || {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def _field_details
|
30
|
+
details = @field_details.dup
|
31
|
+
|
32
|
+
fields_for_form.each do |field|
|
33
|
+
if !details.include? field.to_sym
|
34
|
+
|
35
|
+
type = guess_field_type(field)
|
36
|
+
details[field.to_sym] = initialize_field(field.to_sym, type)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
details
|
41
|
+
end
|
42
|
+
|
43
|
+
def fields_for_form
|
44
|
+
fields_name = @fields.dup
|
45
|
+
|
46
|
+
fields_name.delete('id')
|
47
|
+
fields_name.delete('created_at')
|
48
|
+
fields_name.delete('updated_at')
|
49
|
+
|
50
|
+
fields_name
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def guess_field_type(field)
|
56
|
+
column = model.columns_hash[field.to_s]
|
57
|
+
return column.type.to_sym unless column.nil?
|
58
|
+
|
59
|
+
return :file if has_attachment? field.to_sym
|
60
|
+
|
61
|
+
has_many = ActiveRecord::Reflection::HasManyReflection
|
62
|
+
has_and_belongs_to_many = ActiveRecord::Reflection::HasAndBelongsToManyReflection
|
63
|
+
reflection = model.reflections[field.to_s]
|
64
|
+
|
65
|
+
unless reflection.nil?
|
66
|
+
return nil if reflection.is_a? has_many
|
67
|
+
return :multiple_select if reflection.is_a? has_and_belongs_to_many
|
68
|
+
:select
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_attachment?(name)
|
73
|
+
if model.respond_to? :attachment_definitions
|
74
|
+
return true if model.attachment_definitions.keys.include? name
|
75
|
+
end
|
76
|
+
|
77
|
+
false
|
78
|
+
end
|
79
|
+
|
80
|
+
def initialize_field(name, type)
|
81
|
+
if respond_to?("setup_#{type}".to_sym, true)
|
82
|
+
return send("setup_#{type}", name)
|
83
|
+
end
|
84
|
+
{ as: type.to_sym }
|
85
|
+
end
|
86
|
+
|
87
|
+
def setup_datetime(name)
|
88
|
+
{ as: :string,
|
89
|
+
input_html: { class: 'datetimepicker' }
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def setup_time(name)
|
94
|
+
{ as: :string,
|
95
|
+
input_html: { class: 'timepicker' }
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
def setup_date(name)
|
100
|
+
{ as: :string,
|
101
|
+
input_html: { class: 'datepicker1' }
|
102
|
+
}
|
103
|
+
end
|
104
|
+
|
105
|
+
def setup_multiple_select(name)
|
106
|
+
{ as: :select,
|
107
|
+
input_html: { class: 'multiple select' }
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
def setup_integer(name)
|
112
|
+
{ as: nil }
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Underworld::Dashboard
|
2
|
+
class FormFieldsProperties
|
3
|
+
|
4
|
+
def initializer
|
5
|
+
@fields = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def fields=(all_fields)
|
9
|
+
fields.each do |name, field|
|
10
|
+
unless all_fields.include? name.to_s
|
11
|
+
raise ArgumentError, "'#{name}' is not a valid field"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
all_fields.each do |name, field|
|
16
|
+
unless fields.include?(name.to_sym)
|
17
|
+
|
18
|
+
Rails.logger.debug("FIELD NAME: #{name}")
|
19
|
+
Rails.logger.debug("FIELD TYPE: #{field.type}")
|
20
|
+
|
21
|
+
if self.respond_to?("setup_#{field.type}".to_sym, true)
|
22
|
+
puts "sdasda" * 100
|
23
|
+
send("setup_#{field.type}", name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def fields
|
30
|
+
@fields || {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def []=(name, detail)
|
34
|
+
@fields ||= {}
|
35
|
+
@fields[name.to_sym] = detail
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](index)
|
39
|
+
unless @fields.nil?
|
40
|
+
return @fields[index] || {}
|
41
|
+
end
|
42
|
+
{}
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(m, *args, &block)
|
46
|
+
@fields ||= {}
|
47
|
+
if self.respond_to? m
|
48
|
+
return self.send(m, *args, &block)
|
49
|
+
else
|
50
|
+
# FIXME: This probably is a bad idea. We should get the whole
|
51
|
+
# args
|
52
|
+
@fields[m] = args[0]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_hash
|
57
|
+
fields
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_dependency 'underworld/dashboard/dsl/base'
|
2
|
+
|
3
|
+
module Underworld::Dashboard::DSL
|
4
|
+
class Index < Base
|
5
|
+
attr_reader :tool_buttons
|
6
|
+
|
7
|
+
# Allow user to specify an array of model attributes to be used
|
8
|
+
# in respected section. For example attributes to show as header
|
9
|
+
# columns in index section
|
10
|
+
def attributes(*fields_name, **options, &block)
|
11
|
+
if options.include? :except
|
12
|
+
@fields = resolve_model_reflections.reject do |field|
|
13
|
+
options[:except].include? field.to_sym
|
14
|
+
end
|
15
|
+
elsif options.include? :append
|
16
|
+
@fields += options[:append]
|
17
|
+
else
|
18
|
+
# set new value for fields
|
19
|
+
@fields = fields_name.map(&:to_s) unless fields_name.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
@fields.concat(block.call.map(&:to_s)) if block_given?
|
23
|
+
end
|
24
|
+
|
25
|
+
# Define a new tool on the `tool` place of the index section
|
26
|
+
# **options**: Is a hash which contains the tool button properties.
|
27
|
+
#
|
28
|
+
# `name`: name of the button. used as identifier
|
29
|
+
# `class`: classes of the button.
|
30
|
+
# `icon_class`: font awesome icon to use in button.
|
31
|
+
# `remote`: whether
|
32
|
+
#
|
33
|
+
# You have to provide a block for this method which returns
|
34
|
+
# a string to be used as the **href** for the link
|
35
|
+
def tool_button(**options, &block)
|
36
|
+
fail 'You have to provide a block for `tool_button`' if !block_given?
|
37
|
+
|
38
|
+
options[:block] = block
|
39
|
+
@tool_buttons ||= {}
|
40
|
+
@tool_buttons[options[:name]] = options
|
41
|
+
end
|
42
|
+
|
43
|
+
alias_method :table_fields, :attributes
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
module Underworld::Dashboard
|
2
|
+
module Helpers
|
3
|
+
module BoxHelpers
|
4
|
+
|
5
|
+
class Box
|
6
|
+
def footer(&block)
|
7
|
+
return @footer = nil unless block_given?
|
8
|
+
@footer = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def body(&block)
|
12
|
+
@body = block
|
13
|
+
end
|
14
|
+
|
15
|
+
def footer_content
|
16
|
+
@footer
|
17
|
+
end
|
18
|
+
|
19
|
+
def body_content
|
20
|
+
@body
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Tabs
|
25
|
+
|
26
|
+
class Tab
|
27
|
+
attr_reader :title, :title_icon
|
28
|
+
attr_accessor :content, :id
|
29
|
+
|
30
|
+
def initialize(title, **options)
|
31
|
+
@title = title
|
32
|
+
@active = false
|
33
|
+
@active = true if options[:active] == true
|
34
|
+
@title_icon = options[:title_icon]
|
35
|
+
end
|
36
|
+
|
37
|
+
def active?
|
38
|
+
@active
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :title_icon
|
43
|
+
|
44
|
+
def initialize(**options)
|
45
|
+
@tabs = []
|
46
|
+
@title_icon = options[:title_icon]
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def tab(title, **options, &block)
|
51
|
+
id = @tabs.length
|
52
|
+
tab = Tab.new(title, **options)
|
53
|
+
tab.content = block
|
54
|
+
tab.id = id
|
55
|
+
@tabs << tab
|
56
|
+
end
|
57
|
+
|
58
|
+
def tabs
|
59
|
+
@tabs
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def box(title = nil, **options)
|
64
|
+
content = Box.new
|
65
|
+
|
66
|
+
yield content
|
67
|
+
|
68
|
+
result = "<div class='box #{options[:box_class] || 'box-default'}'>" +
|
69
|
+
"<div class='box-header with-border'>" +
|
70
|
+
"<h3 class='box-title'>" +
|
71
|
+
title +
|
72
|
+
'</h3>'
|
73
|
+
|
74
|
+
unless options[:show_tools].nil?
|
75
|
+
result += "<div class='box-tools pull-right'>" +
|
76
|
+
"<button class='btn btn-box-tool' data-widget='collapse'>" +
|
77
|
+
"<i class='fa fa-minus'></i></button>" +
|
78
|
+
"</div><!-- /.box-tools -->"
|
79
|
+
end
|
80
|
+
|
81
|
+
result += "</div><!-- /.box-header -->" +
|
82
|
+
"<div class='box-body'>" +
|
83
|
+
capture(&content.body_content) +
|
84
|
+
"</div><!-- /.box-body -->"
|
85
|
+
|
86
|
+
unless content.footer_content.nil?
|
87
|
+
result += '<div class="box-footer">' +
|
88
|
+
content.footer_content +
|
89
|
+
"</div><!-- /.box-footer-->"
|
90
|
+
end
|
91
|
+
|
92
|
+
result += "</div><!-- /.box -->"
|
93
|
+
|
94
|
+
result.html_safe
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
def tabbed_box(title = nil, **options)
|
99
|
+
content = Tabs.new
|
100
|
+
|
101
|
+
yield content
|
102
|
+
|
103
|
+
result = "<div class='nav-tabs-custom'>" +
|
104
|
+
"<ul class='nav nav-tabs pull-right'>"
|
105
|
+
|
106
|
+
content.tabs.each do |tab|
|
107
|
+
active = nil
|
108
|
+
active = "class='active'" if tab.active?
|
109
|
+
|
110
|
+
result += "<li #{active}><a href='#tab_#{tab.id}-#{tab.id}' data-toggle='tab'>" +
|
111
|
+
"<i class='fa #{tab.title_icon}'></i> #{tab.title}</a></li>"
|
112
|
+
end
|
113
|
+
|
114
|
+
result += "<li class='pull-left header'><i class='fa #{options[:title_icon]}'></i>#{title}</li>" +
|
115
|
+
"</ul>" +
|
116
|
+
"<div class='tab-content'>"
|
117
|
+
|
118
|
+
content.tabs.each do |tab|
|
119
|
+
result += "<div class='tab-pane #{'active' if tab.active?}' id='tab_#{tab.id}-#{tab.id}'>" +
|
120
|
+
capture(&tab.content) +
|
121
|
+
"</div><!-- /.tab-pane -->"
|
122
|
+
end
|
123
|
+
|
124
|
+
result += "</div><!-- /.tab-content --></div>"
|
125
|
+
result.html_safe
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|