fat_free_crm 0.13.2 → 0.13.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fat_free_crm might be problematic. Click here for more details.
- checksums.yaml +5 -13
- data/.travis.yml +3 -3
- data/Gemfile +5 -2
- data/Gemfile.lock +137 -119
- data/MIT-LICENSE +1 -1
- data/README.md +5 -3
- data/app/assets/javascripts/admin/fields.js.coffee +31 -8
- data/app/assets/javascripts/application.js.erb +6 -10
- data/app/assets/javascripts/crm.js.coffee +426 -0
- data/app/assets/javascripts/crm_chosen.js.coffee +19 -38
- data/app/assets/javascripts/crm_classes.js.coffee +215 -0
- data/app/assets/javascripts/crm_comments.js.coffee +20 -58
- data/app/assets/javascripts/crm_loginout.js.coffee +27 -0
- data/app/assets/javascripts/crm_select2.js.coffee +29 -0
- data/app/assets/javascripts/crm_sortable.js.coffee +32 -0
- data/app/assets/javascripts/crm_tags.js.coffee +22 -0
- data/app/assets/javascripts/crm_textarea_autocomplete.js.coffee +33 -0
- data/app/assets/javascripts/datepicker.js.coffee +2 -2
- data/app/assets/javascripts/format_buttons.js.coffee +23 -24
- data/app/assets/javascripts/lists.js.coffee +45 -76
- data/app/assets/javascripts/pagination.js.coffee +16 -0
- data/app/assets/javascripts/search.js.coffee +6 -22
- data/app/assets/javascripts/timeago.js.coffee +21 -0
- data/app/assets/stylesheets/application.css.erb +0 -1
- data/app/assets/stylesheets/common.scss +36 -29
- data/app/assets/stylesheets/lists.css.scss +17 -3
- data/app/controllers/admin/groups_controller.rb +2 -1
- data/app/controllers/application_controller.rb +5 -5
- data/app/controllers/entities/accounts_controller.rb +1 -1
- data/app/controllers/entities/campaigns_controller.rb +1 -1
- data/app/controllers/entities/contacts_controller.rb +1 -1
- data/app/controllers/entities/leads_controller.rb +1 -1
- data/app/controllers/entities/opportunities_controller.rb +1 -1
- data/app/controllers/home_controller.rb +10 -7
- data/app/controllers/tasks_controller.rb +15 -0
- data/app/controllers/users_controller.rb +6 -4
- data/app/helpers/accounts_helper.rb +8 -5
- data/app/helpers/application_helper.rb +53 -39
- data/app/helpers/campaigns_helper.rb +1 -0
- data/app/helpers/leads_helper.rb +3 -3
- data/app/helpers/opportunities_helper.rb +15 -0
- data/app/helpers/remote_link_pagination_helper.rb +8 -0
- data/app/helpers/tags_helper.rb +2 -2
- data/app/helpers/tasks_helper.rb +22 -15
- data/app/helpers/users_helper.rb +3 -2
- data/app/mailers/user_mailer.rb +9 -3
- data/app/models/entities/account_contact.rb +1 -1
- data/app/models/fields/custom_field.rb +1 -1
- data/app/models/list.rb +1 -0
- data/app/models/observers/entity_observer.rb +10 -1
- data/app/models/observers/lead_observer.rb +2 -0
- data/app/models/observers/opportunity_observer.rb +2 -0
- data/app/models/observers/task_observer.rb +2 -0
- data/app/models/polymorphic/avatar.rb +2 -0
- data/app/models/polymorphic/comment.rb +0 -1
- data/app/models/polymorphic/task.rb +41 -9
- data/app/models/users/ability.rb +1 -0
- data/app/models/users/group.rb +0 -5
- data/app/models/users/user.rb +0 -7
- data/app/views/accounts/_edit.html.haml +1 -0
- data/app/views/accounts/_index_brief.html.haml +2 -2
- data/app/views/accounts/_index_long.html.haml +2 -2
- data/app/views/accounts/_new.html.haml +1 -0
- data/app/views/accounts/_sidebar_index.html.haml +1 -1
- data/app/views/accounts/_sidebar_show.html.haml +1 -1
- data/app/views/accounts/_top_section.html.haml +1 -1
- data/app/views/accounts/create.js.haml +9 -9
- data/app/views/accounts/destroy.js.haml +2 -2
- data/app/views/accounts/edit.js.haml +5 -5
- data/app/views/accounts/index.js.haml +5 -5
- data/app/views/accounts/new.js.haml +1 -1
- data/app/views/accounts/show.html.haml +1 -1
- data/app/views/accounts/show.js.haml +1 -1
- data/app/views/accounts/update.js.haml +7 -5
- data/app/views/admin/field_groups/_field_group.html.haml +4 -5
- data/app/views/admin/field_groups/confirm.js.haml +2 -2
- data/app/views/admin/field_groups/create.js.haml +6 -12
- data/app/views/admin/field_groups/destroy.js.haml +3 -3
- data/app/views/admin/field_groups/edit.js.haml +1 -1
- data/app/views/admin/field_groups/new.js.haml +1 -1
- data/app/views/admin/field_groups/update.js.haml +2 -2
- data/app/views/admin/fields/_field.html.haml +1 -1
- data/app/views/admin/fields/_sort_by.html.haml +3 -3
- data/app/views/admin/fields/create.js.haml +9 -9
- data/app/views/admin/fields/destroy.js.haml +4 -4
- data/app/views/admin/fields/edit.js.haml +2 -2
- data/app/views/admin/fields/index.html.haml +1 -8
- data/app/views/admin/fields/show.html.haml +1 -1
- data/app/views/admin/fields/update.js.haml +8 -8
- data/app/views/admin/groups/_form.html.haml +1 -3
- data/app/views/admin/groups/create.js.haml +8 -8
- data/app/views/admin/groups/destroy.js.haml +3 -3
- data/app/views/admin/groups/edit.js.haml +3 -3
- data/app/views/admin/groups/index.js.haml +2 -2
- data/app/views/admin/groups/new.js.haml +2 -2
- data/app/views/admin/groups/update.js.haml +5 -5
- data/app/views/admin/tags/confirm.js.haml +2 -2
- data/app/views/admin/tags/create.js.haml +8 -8
- data/app/views/admin/tags/destroy.js.haml +3 -3
- data/app/views/admin/tags/edit.js.haml +4 -4
- data/app/views/admin/tags/new.js.haml +1 -1
- data/app/views/admin/tags/update.js.haml +5 -5
- data/app/views/admin/users/_profile.html.haml +3 -4
- data/app/views/admin/users/confirm.js.haml +2 -2
- data/app/views/admin/users/create.js.haml +8 -8
- data/app/views/admin/users/destroy.js.haml +3 -3
- data/app/views/admin/users/edit.js.haml +4 -4
- data/app/views/admin/users/index.js.haml +2 -2
- data/app/views/admin/users/new.js.haml +2 -2
- data/app/views/admin/users/reactivate.js.haml +2 -2
- data/app/views/admin/users/suspend.js.haml +2 -2
- data/app/views/admin/users/update.js.haml +5 -5
- data/app/views/campaigns/_edit.html.haml +1 -0
- data/app/views/campaigns/_index_brief.html.haml +1 -1
- data/app/views/campaigns/_index_long.html.haml +1 -1
- data/app/views/campaigns/_new.html.haml +1 -0
- data/app/views/campaigns/_sidebar_index.html.haml +1 -1
- data/app/views/campaigns/_sidebar_show.html.haml +1 -1
- data/app/views/campaigns/_status.html.haml +1 -1
- data/app/views/campaigns/_top_section.html.haml +1 -1
- data/app/views/campaigns/create.js.haml +10 -10
- data/app/views/campaigns/destroy.js.haml +2 -2
- data/app/views/campaigns/edit.js.haml +6 -6
- data/app/views/campaigns/index.js.haml +5 -5
- data/app/views/campaigns/new.js.haml +1 -1
- data/app/views/campaigns/show.html.haml +1 -1
- data/app/views/campaigns/show.js.haml +1 -1
- data/app/views/campaigns/update.js.haml +8 -6
- data/app/views/comments/_edit.html.haml +1 -1
- data/app/views/comments/_new.html.haml +1 -1
- data/app/views/comments/create.js.haml +9 -9
- data/app/views/comments/destroy.js.haml +2 -2
- data/app/views/comments/edit.js.haml +3 -3
- data/app/views/comments/update.js.haml +5 -5
- data/app/views/contacts/_contacts.html.haml +1 -1
- data/app/views/contacts/_edit.html.haml +1 -0
- data/app/views/contacts/_index_brief.html.haml +2 -2
- data/app/views/contacts/_index_full.html.haml +2 -2
- data/app/views/contacts/_index_long.html.haml +2 -2
- data/app/views/contacts/_new.html.haml +1 -0
- data/app/views/contacts/_section_general.html.haml +4 -3
- data/app/views/contacts/_sidebar_show.html.haml +1 -1
- data/app/views/contacts/_top_section.html.haml +1 -1
- data/app/views/contacts/create.js.haml +10 -10
- data/app/views/contacts/destroy.js.haml +3 -3
- data/app/views/contacts/edit.js.haml +5 -5
- data/app/views/contacts/index.js.haml +5 -5
- data/app/views/contacts/new.js.haml +1 -1
- data/app/views/contacts/show.html.haml +1 -1
- data/app/views/contacts/show.js.haml +1 -1
- data/app/views/contacts/update.js.haml +8 -6
- data/app/views/emails/destroy.js.haml +2 -2
- data/app/views/entities/_basic_search.html.haml +15 -12
- data/app/views/entities/_permissions.html.haml +6 -11
- data/app/views/entities/attach.js.haml +3 -3
- data/app/views/entities/contacts.js.haml +2 -2
- data/app/views/entities/discard.js.haml +1 -1
- data/app/views/entities/leads.js.haml +2 -2
- data/app/views/entities/opportunities.js.haml +2 -2
- data/app/views/entities/subscription_update.js.haml +1 -1
- data/app/views/entities/versions.js.haml +2 -2
- data/app/views/fields/group.js.erb +1 -1
- data/app/views/home/_account.html.haml +2 -2
- data/app/views/home/_assets_menu.html.haml +3 -3
- data/app/views/home/_duration_menu.html.haml +3 -3
- data/app/views/home/_events_menu.html.haml +3 -3
- data/app/views/home/_opportunity.html.haml +2 -2
- data/app/views/home/_options.html.haml +0 -1
- data/app/views/home/_users_menu.html.haml +3 -3
- data/app/views/home/index.js.haml +4 -4
- data/app/views/home/options.js.haml +1 -1
- data/app/views/layouts/_about.html.haml +3 -3
- data/app/views/layouts/_footer.html.haml +1 -1
- data/app/views/layouts/_header.html.haml +1 -1
- data/app/views/layouts/_jumpbox.html.haml +23 -21
- data/app/views/layouts/_sidebar.html.haml +1 -2
- data/app/views/layouts/admin/application.html.haml +1 -1
- data/app/views/layouts/application.html.haml +3 -3
- data/app/views/leads/_convert.html.haml +1 -11
- data/app/views/leads/_convert_permissions.html.haml +4 -9
- data/app/views/leads/_edit.html.haml +1 -0
- data/app/views/leads/_index_brief.html.haml +1 -1
- data/app/views/leads/_index_long.html.haml +1 -1
- data/app/views/leads/_leads.html.haml +1 -1
- data/app/views/leads/_new.html.haml +1 -0
- data/app/views/leads/_sidebar_index.html.haml +1 -1
- data/app/views/leads/_sidebar_show.html.haml +1 -1
- data/app/views/leads/_top_section.html.haml +1 -1
- data/app/views/leads/convert.js.haml +5 -5
- data/app/views/leads/create.js.haml +9 -9
- data/app/views/leads/destroy.js.haml +2 -2
- data/app/views/leads/edit.js.haml +5 -5
- data/app/views/leads/index.js.haml +5 -5
- data/app/views/leads/new.js.haml +1 -1
- data/app/views/leads/promote.js.haml +7 -7
- data/app/views/leads/reject.js.haml +2 -2
- data/app/views/leads/show.html.haml +1 -1
- data/app/views/leads/show.js.haml +1 -1
- data/app/views/leads/update.js.haml +9 -7
- data/app/views/lists/_lists.html.haml +6 -0
- data/app/views/lists/_sidebar.html.haml +18 -17
- data/app/views/lists/create.js.haml +6 -7
- data/app/views/lists/destroy.js.haml +1 -1
- data/app/views/opportunities/_edit.html.haml +2 -1
- data/app/views/opportunities/_index_brief.html.haml +1 -1
- data/app/views/opportunities/_index_long.html.haml +1 -1
- data/app/views/opportunities/_new.html.haml +2 -1
- data/app/views/opportunities/_opportunities.html.haml +1 -1
- data/app/views/opportunities/_sidebar_index.html.haml +1 -1
- data/app/views/opportunities/_sidebar_show.html.haml +1 -1
- data/app/views/opportunities/_top_section.html.haml +2 -2
- data/app/views/opportunities/contacts.js.haml +2 -2
- data/app/views/opportunities/create.js.haml +10 -10
- data/app/views/opportunities/destroy.js.haml +3 -3
- data/app/views/opportunities/edit.js.haml +5 -5
- data/app/views/opportunities/index.html.haml +1 -1
- data/app/views/opportunities/index.js.haml +5 -5
- data/app/views/opportunities/new.js.haml +1 -1
- data/app/views/opportunities/show.html.haml +1 -1
- data/app/views/opportunities/show.js.haml +1 -1
- data/app/views/opportunities/update.js.haml +8 -6
- data/app/views/shared/_address.html.haml +1 -1
- data/app/views/shared/_inline_styles.html.haml +1 -1
- data/app/views/shared/_naming.html.haml +3 -3
- data/app/views/shared/_paginate.haml +2 -1
- data/app/views/shared/_paginate_with_per_page.html.haml +10 -12
- data/app/views/shared/_search.html.haml +7 -3
- data/app/views/shared/_select_popup.html.haml +9 -11
- data/app/views/shared/_tags.html.haml +5 -4
- data/app/views/tasks/_completed.html.haml +3 -1
- data/app/views/tasks/_selector.html.haml +1 -1
- data/app/views/tasks/_top_section.html.haml +1 -1
- data/app/views/tasks/complete.js.haml +7 -7
- data/app/views/tasks/create.js.haml +17 -17
- data/app/views/tasks/destroy.js.haml +2 -2
- data/app/views/tasks/discard.js.haml +1 -1
- data/app/views/tasks/edit.js.haml +4 -4
- data/app/views/tasks/filter.js.haml +2 -2
- data/app/views/tasks/new.js.haml +1 -1
- data/app/views/tasks/uncomplete.js.haml +12 -0
- data/app/views/tasks/update.js.haml +4 -4
- data/app/views/users/_avatar.html.haml +1 -1
- data/app/views/users/_languages.html.haml +3 -3
- data/app/views/users/_profile.html.haml +1 -1
- data/app/views/users/avatar.js.haml +1 -1
- data/app/views/users/change_password.js.haml +5 -5
- data/app/views/users/edit.js.haml +1 -1
- data/app/views/users/password.js.haml +2 -2
- data/app/views/users/show.html.haml +1 -1
- data/app/views/users/update.js.haml +5 -5
- data/app/views/users/upload_avatar.js.haml +3 -3
- data/app/views/versions/_versions.html.haml +1 -1
- data/config/application.rb +3 -0
- data/config/environments/production.rb +1 -1
- data/config/environments/staging.rb +58 -13
- data/config/initializers/locale.rb +2 -0
- data/config/locales/cz_fat_free_crm.yml +1 -0
- data/config/locales/de_fat_free_crm.yml +1 -0
- data/config/locales/en-GB_fat_free_crm.yml +1 -0
- data/config/locales/en-US_fat_free_crm.yml +2 -0
- data/config/locales/es_fat_free_crm.yml +1 -0
- data/config/locales/fr-CA_fat_free_crm.yml +1 -0
- data/config/locales/fr_fat_free_crm.yml +1 -0
- data/config/locales/it_fat_free_crm.yml +1 -0
- data/config/locales/ja_fat_free_crm.yml +1 -0
- data/config/locales/pl_fat_free_crm.yml +1 -0
- data/config/locales/pt-BR_fat_free_crm.yml +1 -0
- data/config/locales/ru_fat_free_crm.yml +444 -61
- data/config/locales/sv-SE_fat_free_crm.yml +1 -0
- data/config/locales/th_fat_free_crm.yml +1 -0
- data/config/locales/zh-CN_fat_free_crm.yml +1 -0
- data/config/routes.rb +20 -19
- data/config/settings.default.yml +11 -10
- data/fat_free_crm.gemspec +5 -4
- data/lib/{plugins/country_select/lib/country_select.rb → country_select.rb} +0 -0
- data/lib/fat_free_crm.rb +3 -1
- data/lib/fat_free_crm/engine.rb +2 -4
- data/lib/fat_free_crm/gem_dependencies.rb +1 -1
- data/lib/fat_free_crm/gem_ext.rb +0 -2
- data/lib/fat_free_crm/permissions.rb +2 -3
- data/lib/fat_free_crm/version.rb +1 -1
- data/lib/{plugins/gravatar_image_tag/lib/gravatar_image_tag.rb → gravatar_image_tag.rb} +0 -0
- data/lib/tasks/ffcrm/settings.rake +4 -16
- data/public/favicon.ico +0 -0
- data/spec/controllers/entities/accounts_controller_spec.rb +5 -5
- data/spec/controllers/entities/campaigns_controller_spec.rb +5 -5
- data/spec/controllers/entities/contacts_controller_spec.rb +42 -5
- data/spec/controllers/entities/leads_controller_spec.rb +7 -7
- data/spec/controllers/entities/opportunities_controller_spec.rb +5 -5
- data/spec/controllers/home_controller_spec.rb +3 -3
- data/spec/controllers/tasks_controller_spec.rb +29 -0
- data/spec/factories/shared_factories.rb +1 -3
- data/spec/features/support/selector_helpers.rb +4 -4
- data/spec/helpers/tasks_helper_spec.rb +10 -5
- data/spec/lib/permissions_spec.rb +10 -22
- data/spec/mailers/user_mailer_spec.rb +5 -4
- data/spec/models/observers/entity_observer_spec.rb +13 -8
- data/spec/models/polymorphic/task_spec.rb +111 -32
- data/spec/routing/accounts_routing_spec.rb +1 -1
- data/spec/routing/campaigns_routing_spec.rb +1 -1
- data/spec/routing/contacts_routing_spec.rb +1 -1
- data/spec/routing/leads_routing_spec.rb +1 -1
- data/spec/routing/opportunities_routing_spec.rb +1 -1
- data/spec/shared/controllers.rb +2 -2
- data/spec/spec_helper.rb +1 -0
- data/spec/views/accounts/create.js.haml_spec.rb +3 -3
- data/spec/views/accounts/index.js.haml_spec.rb +4 -4
- data/spec/views/accounts/update.js.haml_spec.rb +5 -5
- data/spec/views/admin/field_groups/create.js.haml_spec.rb +2 -2
- data/spec/views/admin/field_groups/edit.js.haml_spec.rb +1 -1
- data/spec/views/admin/field_groups/new.js.haml_spec.rb +1 -1
- data/spec/views/admin/field_groups/update.js.haml_spec.rb +1 -1
- data/spec/views/admin/users/create.js.haml_spec.rb +2 -2
- data/spec/views/admin/users/destroy.js.haml_spec.rb +1 -1
- data/spec/views/admin/users/edit.js.haml_spec.rb +1 -1
- data/spec/views/admin/users/index.js.haml_spec.rb +1 -1
- data/spec/views/admin/users/new.js.haml_spec.rb +1 -1
- data/spec/views/admin/users/reactivate.js.haml_spec.rb +1 -1
- data/spec/views/admin/users/suspend.js.haml_spec.rb +1 -1
- data/spec/views/admin/users/update.js.haml_spec.rb +3 -3
- data/spec/views/campaigns/create.js.haml_spec.rb +4 -4
- data/spec/views/campaigns/destroy.js.haml_spec.rb +1 -1
- data/spec/views/campaigns/edit.js.haml_spec.rb +4 -4
- data/spec/views/campaigns/index.js.haml_spec.rb +2 -2
- data/spec/views/campaigns/new.js.haml_spec.rb +1 -1
- data/spec/views/campaigns/update.js.haml_spec.rb +7 -7
- data/spec/views/contacts/create.js.haml_spec.rb +4 -4
- data/spec/views/contacts/edit.js.haml_spec.rb +4 -4
- data/spec/views/contacts/index.js.html_spec.rb +2 -2
- data/spec/views/contacts/new.js.haml_spec.rb +2 -2
- data/spec/views/contacts/update.js.haml_spec.rb +11 -11
- data/spec/views/home/index.js.haml_spec.rb +1 -1
- data/spec/views/home/options.js.haml_spec.rb +3 -3
- data/spec/views/leads/convert.js.haml_spec.rb +3 -3
- data/spec/views/leads/create.js.haml_spec.rb +5 -5
- data/spec/views/leads/destroy.js.haml_spec.rb +1 -1
- data/spec/views/leads/edit.js.haml_spec.rb +4 -4
- data/spec/views/leads/index.js.haml_spec.rb +2 -2
- data/spec/views/leads/new.js.haml_spec.rb +1 -1
- data/spec/views/leads/promote.js.haml_spec.rb +13 -13
- data/spec/views/leads/reject.js.haml_spec.rb +6 -6
- data/spec/views/leads/update.js.haml_spec.rb +11 -11
- data/spec/views/opportunities/create.js.haml_spec.rb +4 -4
- data/spec/views/opportunities/destroy.js.haml_spec.rb +1 -1
- data/spec/views/opportunities/edit.js.haml_spec.rb +4 -4
- data/spec/views/opportunities/index.js.haml_spec.rb +2 -2
- data/spec/views/opportunities/update.js.haml_spec.rb +11 -11
- data/spec/views/tasks/complete.js.haml_spec.rb +5 -5
- data/spec/views/tasks/create.js.haml_spec.rb +13 -13
- data/spec/views/tasks/destroy.js.haml_spec.rb +3 -3
- data/spec/views/tasks/edit.js.haml_spec.rb +4 -4
- data/spec/views/tasks/new.js.haml_spec.rb +2 -2
- data/spec/views/tasks/uncomplete.js.haml_spec.rb +44 -0
- data/spec/views/tasks/update.js.haml_spec.rb +17 -17
- data/spec/views/users/avatar.js.haml_spec.rb +1 -1
- data/spec/views/users/change_password.js.haml_spec.rb +4 -4
- data/spec/views/users/edit.js.haml_spec.rb +1 -1
- data/spec/views/users/password.js.haml_spec.rb +2 -2
- data/spec/views/users/update.js.haml_spec.rb +5 -5
- data/spec/views/users/upload_avatar.js.haml_spec.rb +2 -2
- data/vendor/assets/javascripts/ajax-chosen.jquery.coffee +166 -76
- data/vendor/assets/javascripts/chosen.jquery.coffee +2 -2
- data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-pt-BR.js +22 -0
- data/vendor/assets/javascripts/jquery_ui_datepicker/{jquery-ui-timepicker-sv.js → jquery-ui-timepicker-sv-SE.js} +0 -0
- data/vendor/assets/javascripts/jquery_ui_datepicker/jquery-ui-timepicker-th.js +19 -0
- data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-fr-CA.js +21 -0
- data/vendor/assets/javascripts/jquery_ui_datepicker/jquery.ui.datepicker-pt.js +21 -0
- data/vendor/assets/javascripts/rating.js +2 -2
- metadata +101 -122
- data/app/assets/images/facebook-close.gif +0 -0
- data/app/assets/javascripts/crm.js +0 -495
- data/app/assets/javascripts/crm_classes.js +0 -218
- data/app/assets/javascripts/crm_fields.js +0 -34
- data/app/assets/javascripts/crm_loginout.js +0 -29
- data/app/assets/javascripts/crm_textarea_autocomplete.js +0 -32
- data/app/assets/javascripts/groups.js.coffee +0 -8
- data/app/assets/javascripts/jquery-noconflict.js +0 -6
- data/app/assets/javascripts/timeago.js +0 -17
- data/app/views/lists/_personal_sidebar.html.haml +0 -28
- data/lib/fat_free_crm/gem_ext/active_model/serializers/xml/serializer/attribute.rb +0 -17
- data/lib/fat_free_crm/gem_ext/authlogic/session/cookies.rb +0 -16
- data/lib/fat_free_crm/plugin_dependencies.rb +0 -12
- data/lib/plugins/country_select/MIT-LICENSE +0 -20
- data/lib/plugins/country_select/README +0 -14
- data/lib/plugins/country_select/init.rb +0 -1
- data/lib/plugins/country_select/install.rb +0 -2
- data/lib/plugins/country_select/uninstall.rb +0 -2
- data/lib/plugins/gravatar_image_tag/Gemfile +0 -8
- data/lib/plugins/gravatar_image_tag/README.textile +0 -108
- data/lib/plugins/gravatar_image_tag/ROADMAP.textile +0 -33
- data/lib/plugins/gravatar_image_tag/Rakefile +0 -50
- data/lib/plugins/gravatar_image_tag/VERSION +0 -1
- data/lib/plugins/gravatar_image_tag/gravatar_image_tag.gemspec +0 -45
- data/lib/plugins/gravatar_image_tag/init.rb +0 -2
- data/lib/plugins/gravatar_image_tag/spec/gravatar_image_tag_spec.rb +0 -83
- data/lib/plugins/gravatar_image_tag/spec/test_helper.rb +0 -12
- data/lib/tasks/db/migrate.rake +0 -66
- data/lib/tasks/db/schema.rake +0 -20
- data/vendor/assets/javascripts/ajax-chosen-prototype.js +0 -2
- data/vendor/assets/javascripts/ajax-chosen.proto.coffee +0 -98
- data/vendor/assets/javascripts/chosen-prototype.js +0 -3
- data/vendor/assets/javascripts/chosen.proto.coffee +0 -580
- data/vendor/assets/javascripts/event.simulate.js +0 -64
- data/vendor/assets/javascripts/facebooklist.js +0 -548
- data/vendor/assets/javascripts/facebooklist.simulate.js +0 -28
- data/vendor/assets/javascripts/modalbox.js +0 -506
- data/vendor/assets/stylesheets/facebooklist.css +0 -47
@@ -6,7 +6,21 @@
|
|
6
6
|
// Place all the styles related to the Lists controller here.
|
7
7
|
// They will automatically be included in application.css.
|
8
8
|
// You can use Sass (SCSS) here: http://sass-lang.com/
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
|
10
|
+
.lists {
|
11
|
+
i.fa { font-size: 130% }
|
12
|
+
a:hover { background:none; color:#0033cc }
|
13
|
+
.list_icon { opacity: 0.5; }
|
14
|
+
img.input_info { vertical-align: middle; }
|
15
|
+
.list_save {
|
16
|
+
text-align: right;
|
17
|
+
margin: 10px 0 0;
|
18
|
+
}
|
19
|
+
.list_form {
|
20
|
+
margin: 10px 0 0;
|
21
|
+
input[type=submit] {
|
22
|
+
margin-top: 10px;
|
23
|
+
vertical-align: baseline;
|
24
|
+
}
|
25
|
+
}
|
12
26
|
}
|
@@ -35,7 +35,8 @@ class Admin::GroupsController < Admin::ApplicationController
|
|
35
35
|
# POST /groups
|
36
36
|
#----------------------------------------------------------------------------
|
37
37
|
def create
|
38
|
-
@group.
|
38
|
+
@group.attributes = params[:group]
|
39
|
+
@group.save
|
39
40
|
|
40
41
|
respond_with(@group)
|
41
42
|
end
|
@@ -42,7 +42,7 @@ class ApplicationController < ActionController::Base
|
|
42
42
|
respond_to do |format|
|
43
43
|
format.any(:js, :html) { render :partial => 'auto_complete' }
|
44
44
|
format.json { render :json => @auto_complete.inject({}){|h,a|
|
45
|
-
h[a.id] = a.respond_to?(:full_name) ?
|
45
|
+
h[a.id] = a.respond_to?(:full_name) ? h(a.full_name) : h(a.name); h
|
46
46
|
}}
|
47
47
|
end
|
48
48
|
end
|
@@ -120,7 +120,7 @@ private
|
|
120
120
|
flash[:notice] = t(:msg_login_needed) if request.fullpath != "/"
|
121
121
|
respond_to do |format|
|
122
122
|
format.html { redirect_to login_url }
|
123
|
-
format.js { render
|
123
|
+
format.js { render :text => "window.location = '#{login_url}';" }
|
124
124
|
end
|
125
125
|
end
|
126
126
|
end
|
@@ -202,7 +202,7 @@ private
|
|
202
202
|
|
203
203
|
respond_to do |format|
|
204
204
|
format.html { redirect_to(redirection_url) }
|
205
|
-
format.js { render
|
205
|
+
format.js { render :text => 'window.location.reload();' }
|
206
206
|
format.json { render :text => flash[:warning], :status => :not_found }
|
207
207
|
format.xml { render :xml => [flash[:warning]], :status => :not_found }
|
208
208
|
end
|
@@ -216,7 +216,7 @@ private
|
|
216
216
|
url = send("#{related.pluralize}_path")
|
217
217
|
respond_to do |format|
|
218
218
|
format.html { redirect_to(url) }
|
219
|
-
format.js { render
|
219
|
+
format.js { render :text => %Q{window.location.href = "#{url}";} }
|
220
220
|
format.json { render :text => flash[:warning], :status => :not_found }
|
221
221
|
format.xml { render :xml => [flash[:warning]], :status => :not_found }
|
222
222
|
end
|
@@ -227,7 +227,7 @@ private
|
|
227
227
|
flash[:warning] = t(:msg_not_authorized, default: 'You are not authorized to take this action.')
|
228
228
|
respond_to do |format|
|
229
229
|
format.html { redirect_to(redirection_url) }
|
230
|
-
format.js { render
|
230
|
+
format.js { render :text => 'window.location.reload();' }
|
231
231
|
format.json { render :text => flash[:warning], :status => :unauthorized }
|
232
232
|
format.xml { render :xml => [flash[:warning]], :status => :unauthorized }
|
233
233
|
end
|
@@ -98,7 +98,7 @@ class AccountsController < EntitiesController
|
|
98
98
|
#----------------------------------------------------------------------------
|
99
99
|
# Handled by ApplicationController :auto_complete
|
100
100
|
|
101
|
-
#
|
101
|
+
# GET /accounts/redraw AJAX
|
102
102
|
#----------------------------------------------------------------------------
|
103
103
|
def redraw
|
104
104
|
current_user.pref[:accounts_per_page] = params[:per_page] if params[:per_page]
|
@@ -136,7 +136,7 @@ class CampaignsController < EntitiesController
|
|
136
136
|
#----------------------------------------------------------------------------
|
137
137
|
# Handled by ApplicationController :auto_complete
|
138
138
|
|
139
|
-
#
|
139
|
+
# GET /campaigns/redraw AJAX
|
140
140
|
#----------------------------------------------------------------------------
|
141
141
|
def redraw
|
142
142
|
current_user.pref[:campaigns_per_page] = params[:per_page] if params[:per_page]
|
@@ -116,7 +116,7 @@ class ContactsController < EntitiesController
|
|
116
116
|
#----------------------------------------------------------------------------
|
117
117
|
# Handled by ApplicationController :auto_complete
|
118
118
|
|
119
|
-
#
|
119
|
+
# GET /contacts/redraw AJAX
|
120
120
|
#----------------------------------------------------------------------------
|
121
121
|
def redraw
|
122
122
|
current_user.pref[:contacts_per_page] = params[:per_page] if params[:per_page]
|
@@ -157,7 +157,7 @@ class LeadsController < EntitiesController
|
|
157
157
|
# Handled by ApplicationController :auto_complete
|
158
158
|
|
159
159
|
|
160
|
-
#
|
160
|
+
# GET /leads/redraw AJAX
|
161
161
|
#----------------------------------------------------------------------------
|
162
162
|
def redraw
|
163
163
|
current_user.pref[:leads_per_page] = params[:per_page] if params[:per_page]
|
@@ -145,7 +145,7 @@ class OpportunitiesController < EntitiesController
|
|
145
145
|
#----------------------------------------------------------------------------
|
146
146
|
# Handled by ApplicationController :auto_complete
|
147
147
|
|
148
|
-
#
|
148
|
+
# GET /opportunities/redraw AJAX
|
149
149
|
#----------------------------------------------------------------------------
|
150
150
|
def redraw
|
151
151
|
@opportunities = get_opportunities(:page => 1, :per_page => params[:per_page])
|
@@ -10,9 +10,9 @@ class HomeController < ApplicationController
|
|
10
10
|
#----------------------------------------------------------------------------
|
11
11
|
def index
|
12
12
|
@activities = get_activities
|
13
|
-
@my_tasks = Task.visible_on_dashboard(current_user).by_due_at
|
14
|
-
@my_opportunities = Opportunity.visible_on_dashboard(current_user).by_closes_on.by_amount
|
15
|
-
@my_accounts = Account.visible_on_dashboard(current_user).by_name
|
13
|
+
@my_tasks = Task.visible_on_dashboard(current_user).includes(:user, :asset).by_due_at
|
14
|
+
@my_opportunities = Opportunity.visible_on_dashboard(current_user).includes(:account, :user, :tags).by_closes_on.by_amount
|
15
|
+
@my_accounts = Account.visible_on_dashboard(current_user).includes(:user, :tags).by_name
|
16
16
|
respond_with(@activities)
|
17
17
|
end
|
18
18
|
|
@@ -28,15 +28,18 @@ class HomeController < ApplicationController
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
#
|
31
|
+
# GET /home/redraw AJAX
|
32
32
|
#----------------------------------------------------------------------------
|
33
33
|
def redraw
|
34
34
|
current_user.pref[:activity_asset] = params[:asset] if params[:asset]
|
35
35
|
current_user.pref[:activity_event] = params[:event] if params[:event]
|
36
36
|
current_user.pref[:activity_user] = params[:user] if params[:user]
|
37
37
|
current_user.pref[:activity_duration] = params[:duration] if params[:duration]
|
38
|
+
@activities = get_activities
|
38
39
|
|
39
|
-
|
40
|
+
respond_with(@activities) do |format|
|
41
|
+
format.js { render :index }
|
42
|
+
end
|
40
43
|
end
|
41
44
|
|
42
45
|
# GET /home/toggle AJAX
|
@@ -94,7 +97,7 @@ class HomeController < ApplicationController
|
|
94
97
|
options[:duration] ||= activity_duration
|
95
98
|
options[:max] ||= 500
|
96
99
|
|
97
|
-
Version.latest(options).visible_to(current_user)
|
100
|
+
Version.includes(user: [:avatar]).latest(options).visible_to(current_user)
|
98
101
|
end
|
99
102
|
|
100
103
|
#----------------------------------------------------------------------------
|
@@ -144,7 +147,7 @@ class HomeController < ApplicationController
|
|
144
147
|
duration = current_user.pref[:activity_duration]
|
145
148
|
if duration
|
146
149
|
words = duration.split("_") # "two_weeks" => 2.weeks
|
147
|
-
if %w(one two).include?(words.first)
|
150
|
+
if %w(one two).include?(words.first) and %w(hour day days week weeks month).include?(words.last)
|
148
151
|
%w(zero one two).index(words.first).send(words.last)
|
149
152
|
end
|
150
153
|
end
|
@@ -134,6 +134,21 @@ class TasksController < ApplicationController
|
|
134
134
|
respond_with(@task)
|
135
135
|
end
|
136
136
|
|
137
|
+
# PUT /tasks/1/uncomplete
|
138
|
+
#----------------------------------------------------------------------------
|
139
|
+
def uncomplete
|
140
|
+
@task = Task.tracked_by(current_user).find(params[:id])
|
141
|
+
@task.update_attributes(:completed_at => nil, :completed_by => nil) if @task
|
142
|
+
|
143
|
+
# Make sure bucket's div gets hidden if we're deleting last task in the bucket.
|
144
|
+
if Task.bucket_empty?(params[:bucket], current_user, @view)
|
145
|
+
@empty_bucket = params[:bucket]
|
146
|
+
end
|
147
|
+
|
148
|
+
update_sidebar
|
149
|
+
respond_with(@task)
|
150
|
+
end
|
151
|
+
|
137
152
|
# POST /tasks/auto_complete/query AJAX
|
138
153
|
#----------------------------------------------------------------------------
|
139
154
|
# Handled by ApplicationController :auto_complete
|
@@ -75,8 +75,10 @@ class UsersController < ApplicationController
|
|
75
75
|
render
|
76
76
|
else
|
77
77
|
if params[:avatar]
|
78
|
-
|
79
|
-
|
78
|
+
avatar = Avatar.create(params[:avatar].merge(:entity => @user))
|
79
|
+
if avatar.valid?
|
80
|
+
@user.avatar = avatar
|
81
|
+
else
|
80
82
|
@user.avatar.errors.clear
|
81
83
|
@user.avatar.errors.add(:image, t(:msg_bad_image_file))
|
82
84
|
end
|
@@ -116,11 +118,11 @@ class UsersController < ApplicationController
|
|
116
118
|
respond_with(@user)
|
117
119
|
end
|
118
120
|
|
119
|
-
#
|
121
|
+
# GET /users/1/redraw
|
120
122
|
#----------------------------------------------------------------------------
|
121
123
|
def redraw
|
122
124
|
current_user.preference[:locale] = params[:locale]
|
123
|
-
render
|
125
|
+
render :js => %Q{window.location.href = "#{user_path(current_user)}";}
|
124
126
|
end
|
125
127
|
|
126
128
|
# GET /users/opportunities_overview
|
@@ -22,14 +22,17 @@ module AccountsHelper
|
|
22
22
|
].join(', ')
|
23
23
|
end
|
24
24
|
|
25
|
+
# Generates a select list with the first 25 accounts
|
26
|
+
# and prepends the currently selected account, if any.
|
27
|
+
#----------------------------------------------------------------------------
|
25
28
|
def account_select(options = {})
|
26
|
-
# Generates a select list with the first 25 accounts,
|
27
|
-
# and prepends the currently selected account, if available
|
28
29
|
options[:selected] = (@account && @account.id) || 0
|
29
30
|
accounts = ([@account] + Account.my.order(:name).limit(25)).compact.uniq
|
30
31
|
collection_select :account, :id, accounts, :id, :name, options,
|
31
32
|
{:"data-placeholder" => t(:select_an_account),
|
32
|
-
:
|
33
|
+
:"data-url" => auto_complete_accounts_path(format: 'json'),
|
34
|
+
:style => "width:330px; display:none;",
|
35
|
+
:class => 'ajax_chosen' }
|
33
36
|
end
|
34
37
|
|
35
38
|
# Select an existing account or create a new one.
|
@@ -42,11 +45,11 @@ module AccountsHelper
|
|
42
45
|
t(:account).html_safe +
|
43
46
|
|
44
47
|
content_tag(:span, :id => 'account_create_title') do
|
45
|
-
"(#{t :create_new} #{t :or} <a href='#' onclick='crm.select_account(
|
48
|
+
"(#{t :create_new} #{t :or} <a href='#' onclick='crm.select_account(); return false;'>#{t :select_existing}</a>):".html_safe
|
46
49
|
end.html_safe +
|
47
50
|
|
48
51
|
content_tag(:span, :id => 'account_select_title') do
|
49
|
-
"(<a href='#' onclick='crm.create_account(
|
52
|
+
"(<a href='#' onclick='crm.create_account(); return false;'>#{t :create_new}</a> #{t :or} #{t :select_existing}):".html_safe
|
50
53
|
end.html_safe +
|
51
54
|
|
52
55
|
content_tag(:span, ':', :id => 'account_disabled_title').html_safe
|
@@ -63,7 +63,7 @@ module ApplicationHelper
|
|
63
63
|
def load_select_popups_for(related, *assets)
|
64
64
|
js = generate_js_for_popups(related, *assets)
|
65
65
|
content_for(:javascript_epilogue) do
|
66
|
-
raw "
|
66
|
+
raw "$(function() { #{js} });"
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -91,7 +91,7 @@ module ApplicationHelper
|
|
91
91
|
link_to(text,
|
92
92
|
url + "#{url.include?('?') ? '&' : '?'}cancel=false" + related,
|
93
93
|
:remote => true,
|
94
|
-
:onclick => "this.href = this.href.replace(/cancel=(true|false)/,'cancel='+
|
94
|
+
:onclick => "this.href = this.href.replace(/cancel=(true|false)/,'cancel='+ ($('##{id}').css('display') != 'none'));",
|
95
95
|
:class => options[:class]
|
96
96
|
)
|
97
97
|
end
|
@@ -179,7 +179,7 @@ module ApplicationHelper
|
|
179
179
|
tabs = [ :campaigns, :accounts, :leads, :contacts, :opportunities ]
|
180
180
|
current = tabs.first unless tabs.include?(current)
|
181
181
|
tabs.map do |tab|
|
182
|
-
link_to_function(t("tab_#{tab}"), "crm.jumper('#{tab}')", :class => (tab == current ? 'selected' : ''))
|
182
|
+
link_to_function(t("tab_#{tab}"), "crm.jumper('#{tab}')", "html-data" => tab, :class => (tab == current ? 'selected' : ''))
|
183
183
|
end.join(" | ").html_safe
|
184
184
|
end
|
185
185
|
|
@@ -196,7 +196,7 @@ module ApplicationHelper
|
|
196
196
|
|
197
197
|
#----------------------------------------------------------------------------
|
198
198
|
def one_submit_only(form='')
|
199
|
-
{ :onsubmit => "
|
199
|
+
{ :onsubmit => "$('#'+this.id+' input[type=submit]').prop('disabled', true)".html_safe }
|
200
200
|
end
|
201
201
|
|
202
202
|
#----------------------------------------------------------------------------
|
@@ -213,9 +213,9 @@ module ApplicationHelper
|
|
213
213
|
def confirm_delete(model, params = {})
|
214
214
|
question = %(<span class="warn">#{t(:confirm_delete, model.class.to_s.downcase)}</span>).html_safe
|
215
215
|
yes = link_to(t(:yes_button), params[:url] || model, :method => :delete)
|
216
|
-
no = link_to_function(t(:no_button), "
|
217
|
-
text = "
|
218
|
-
text << "
|
216
|
+
no = link_to_function(t(:no_button), "$('#menu').html($('#confirm').html());")
|
217
|
+
text = "$('#confirm').html( $('#menu').html() );\n"
|
218
|
+
text << "$('#menu').html('#{question} #{yes} : #{no}');"
|
219
219
|
text.html_safe
|
220
220
|
end
|
221
221
|
|
@@ -234,8 +234,8 @@ module ApplicationHelper
|
|
234
234
|
#----------------------------------------------------------------------------
|
235
235
|
def refresh_sidebar_for(view, action = nil, shake = nil)
|
236
236
|
text = ""
|
237
|
-
text << "
|
238
|
-
text << "
|
237
|
+
text << "$('#sidebar').html('#{ j render(:partial => "layouts/sidebar", :locals => { :view => view, :action => action }) }');"
|
238
|
+
text << "$('##{j shake.to_s}').effect('shake', { duration:200, distance: 3 });" if shake
|
239
239
|
text.html_safe
|
240
240
|
end
|
241
241
|
|
@@ -257,40 +257,41 @@ module ApplicationHelper
|
|
257
257
|
|
258
258
|
# Ajax helper to refresh current index page once the user selects an option.
|
259
259
|
#----------------------------------------------------------------------------
|
260
|
-
def redraw(option, value, url =
|
260
|
+
def redraw(option, value, url = send("redraw_#{controller.controller_name}_path"))
|
261
261
|
if value.is_a?(Array)
|
262
262
|
param, value = value.first, value.last
|
263
263
|
end
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
264
|
+
%Q{
|
265
|
+
if ($('##{option}').html() != '#{value}') {
|
266
|
+
$('##{option}').html('#{value}');
|
267
|
+
$('#loading').show();
|
268
|
+
$.post('#{url}', {#{option}: '#{param || value}'}, function () {
|
269
|
+
$('#loading').hide();
|
270
|
+
});
|
271
|
+
}
|
272
|
+
}
|
271
273
|
end
|
272
274
|
|
273
275
|
#----------------------------------------------------------------------------
|
274
|
-
def options_menu_item(option, key, url =
|
276
|
+
def options_menu_item(option, key, url = send("redraw_#{controller.controller_name}_path"))
|
275
277
|
name = t("option_#{key}")
|
276
278
|
"{ name: \"#{name.titleize}\", on_select: function() {" +
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
279
|
+
%Q{
|
280
|
+
if ($('##{option}').html() != '#{name}') {
|
281
|
+
$('##{option}').html('#{name}');
|
282
|
+
$('#loading').show();
|
283
|
+
$.get('#{url}', {#{option}: '#{key}', query: $('#query').val()}, function () {
|
284
|
+
$('#loading').hide();
|
285
|
+
});
|
286
|
+
}
|
287
|
+
} + "}}"
|
284
288
|
end
|
285
289
|
|
286
290
|
# Ajax helper to pass browser timezone offset to the server.
|
287
291
|
#----------------------------------------------------------------------------
|
288
292
|
def get_browser_timezone_offset
|
289
293
|
unless session[:timezone_offset]
|
290
|
-
|
291
|
-
:url => timezone_path,
|
292
|
-
:with => "'offset='+(new Date()).getTimezoneOffset()"
|
293
|
-
)
|
294
|
+
"$.get('#{timezone_path}', {offset: (new Date()).getTimezoneOffset()});"
|
294
295
|
end
|
295
296
|
end
|
296
297
|
|
@@ -387,15 +388,18 @@ module ApplicationHelper
|
|
387
388
|
|
388
389
|
def entity_filter_checkbox(name, value, count)
|
389
390
|
checked = (session["#{controller_name}_filter"].present? ? session["#{controller_name}_filter"].split(",").include?(value.to_s) : count.to_i > 0)
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
391
|
+
url = url_for(:action => :filter)
|
392
|
+
onclick = %Q{
|
393
|
+
var query = $('#query').val(),
|
394
|
+
values = [];
|
395
|
+
$('input[name="#{name}[]"]').filter(':checked').each(function () {
|
396
|
+
values.push(this.value);
|
397
|
+
});
|
398
|
+
$('#loading').show();
|
399
|
+
$.post('#{url}', {#{name}: values.join(','), query: query}, function () {
|
400
|
+
$('#loading').hide();
|
401
|
+
});
|
402
|
+
}.html_safe
|
399
403
|
check_box_tag("#{name}[]", value, checked, :id => value, :onclick => onclick)
|
400
404
|
end
|
401
405
|
|
@@ -470,7 +474,7 @@ module ApplicationHelper
|
|
470
474
|
end
|
471
475
|
|
472
476
|
#----------------------------------------------------------------------------
|
473
|
-
# Generate the html for
|
477
|
+
# Generate the html for $.timeago function
|
474
478
|
# <span class="timeago" datetime="2008-07-17T09:24:17Z">July 17, 2008</span>
|
475
479
|
def timeago(time, options = {})
|
476
480
|
options[:class] ||= "timeago"
|
@@ -491,4 +495,14 @@ module ApplicationHelper
|
|
491
495
|
end
|
492
496
|
end
|
493
497
|
|
498
|
+
#----------------------------------------------------------------------------
|
499
|
+
# Ajaxification FTW!
|
500
|
+
# e.g. collection = Opportunity.my.scope
|
501
|
+
# options = { renderer: {...} , params: {...}
|
502
|
+
def paginate(options = {})
|
503
|
+
collection = options.delete(:collection)
|
504
|
+
options = { renderer: RemoteLinkPaginationHelper::LinkRenderer }.merge(options)
|
505
|
+
will_paginate(collection, options)
|
506
|
+
end
|
507
|
+
|
494
508
|
end
|
data/app/helpers/leads_helper.rb
CHANGED
@@ -31,9 +31,9 @@ module LeadsHelper
|
|
31
31
|
def confirm_reject(lead)
|
32
32
|
question = %(<span class="warn">#{t(:reject_lead_confirm)}</span>)
|
33
33
|
yes = link_to(t(:yes_button), reject_lead_path(lead), :method => :put)
|
34
|
-
no = link_to_function(t(:no_button), "
|
35
|
-
text = "
|
36
|
-
text << "
|
34
|
+
no = link_to_function(t(:no_button), "$('#menu').html($('#confirm').html());")
|
35
|
+
text = "$('#confirm').html( $('#menu').html() );\n"
|
36
|
+
text << "$('#menu').html('#{question} #{yes} : #{no}');"
|
37
37
|
text.html_safe
|
38
38
|
end
|
39
39
|
|