fat_free_crm 0.19.2 → 0.20.0
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 +4 -4
- data/.github/workflows/brakeman-analysis.yml +46 -0
- data/.github/workflows/rubocop-analysis.yml +40 -0
- data/.github/workflows/ruby.yml +52 -0
- data/.rubocop_todo.yml +49 -43
- data/.travis.yml +1 -20
- data/CHANGELOG.md +13 -0
- data/Gemfile +9 -5
- data/Gemfile.lock +163 -119
- data/README.md +4 -3
- data/SECURITY.md +11 -0
- data/app/assets/javascripts/application.js.erb +3 -0
- data/app/assets/stylesheets/application.css.erb +1 -0
- data/app/assets/stylesheets/base.scss +9 -2
- data/app/assets/stylesheets/bootstrap-custom.scss +206 -0
- data/app/assets/stylesheets/common.scss +87 -67
- data/app/assets/stylesheets/header.scss +0 -8
- data/app/controllers/admin/field_groups_controller.rb +1 -1
- data/app/controllers/admin/fields_controller.rb +1 -1
- data/app/controllers/admin/groups_controller.rb +1 -1
- data/app/controllers/admin/tags_controller.rb +2 -2
- data/app/controllers/admin/users_controller.rb +2 -1
- data/app/controllers/application_controller.rb +10 -0
- data/app/controllers/comments_controller.rb +1 -1
- data/app/controllers/entities/accounts_controller.rb +1 -1
- data/app/controllers/entities/campaigns_controller.rb +1 -1
- data/app/controllers/home_controller.rb +3 -1
- data/app/controllers/lists_controller.rb +1 -1
- data/app/controllers/tasks_controller.rb +3 -3
- data/app/controllers/users_controller.rb +3 -1
- data/app/helpers/accounts_helper.rb +12 -0
- data/app/helpers/application_helper.rb +3 -5
- data/app/helpers/tasks_helper.rb +2 -2
- data/app/models/entities/account.rb +1 -1
- data/app/models/entities/account_contact.rb +1 -1
- data/app/models/entities/account_opportunity.rb +1 -1
- data/app/models/entities/campaign.rb +1 -1
- data/app/models/entities/contact.rb +1 -1
- data/app/models/entities/lead.rb +1 -1
- data/app/models/entities/opportunity.rb +1 -1
- data/app/models/fields/custom_field_pair.rb +2 -2
- data/app/models/observers/opportunity_observer.rb +1 -1
- data/app/models/polymorphic/address.rb +1 -1
- data/app/models/polymorphic/comment.rb +1 -1
- data/app/models/polymorphic/email.rb +1 -1
- data/app/models/polymorphic/task.rb +1 -1
- data/app/models/setting.rb +4 -2
- data/app/models/users/preference.rb +2 -2
- data/app/models/users/user.rb +2 -2
- data/app/views/accounts/_edit.html.haml +2 -2
- data/app/views/accounts/_new.html.haml +2 -2
- data/app/views/accounts/_sidebar_index.html.haml +2 -2
- data/app/views/accounts/_sidebar_show.html.haml +19 -19
- data/app/views/accounts/create.js.haml +1 -2
- data/app/views/accounts/destroy.js.haml +1 -1
- data/app/views/accounts/show.html.haml +1 -0
- data/app/views/accounts/update.js.haml +2 -3
- data/app/views/admin/field_groups/create.js.haml +0 -1
- data/app/views/admin/field_groups/destroy.js.haml +0 -1
- data/app/views/admin/field_groups/update.js.haml +0 -1
- data/app/views/admin/fields/create.js.haml +0 -1
- data/app/views/admin/fields/destroy.js.haml +0 -1
- data/app/views/admin/fields/update.js.haml +0 -1
- data/app/views/admin/groups/create.js.haml +0 -1
- data/app/views/admin/groups/destroy.js.haml +0 -1
- data/app/views/admin/groups/update.js.haml +0 -1
- data/app/views/admin/tags/create.js.haml +0 -1
- data/app/views/admin/tags/destroy.js.haml +0 -1
- data/app/views/admin/tags/update.js.haml +0 -1
- data/app/views/admin/users/create.js.haml +0 -1
- data/app/views/admin/users/destroy.js.haml +0 -1
- data/app/views/admin/users/update.js.haml +0 -1
- data/app/views/campaigns/_edit.html.haml +1 -1
- data/app/views/campaigns/_new.html.haml +1 -1
- data/app/views/campaigns/_sidebar_index.html.haml +2 -2
- data/app/views/campaigns/_sidebar_show.html.haml +68 -67
- data/app/views/campaigns/create.js.haml +1 -2
- data/app/views/campaigns/destroy.js.haml +1 -1
- data/app/views/campaigns/show.html.haml +1 -0
- data/app/views/campaigns/update.js.haml +3 -4
- data/app/views/comments/_edit.html.haml +1 -1
- data/app/views/comments/_new.html.haml +1 -1
- data/app/views/comments/update.js.haml +0 -1
- data/app/views/contacts/_edit.html.haml +1 -1
- data/app/views/contacts/_new.html.haml +1 -1
- data/app/views/contacts/_sidebar_show.html.haml +18 -18
- data/app/views/contacts/create.js.haml +0 -1
- data/app/views/contacts/destroy.js.haml +1 -1
- data/app/views/contacts/show.html.haml +1 -0
- data/app/views/contacts/update.js.haml +2 -3
- data/app/views/entities/_title_bar.html.haml +1 -1
- data/app/views/entities/attach.js.haml +2 -2
- data/app/views/entities/discard.js.haml +2 -2
- data/app/views/home/_opportunity.html.haml +1 -1
- data/app/views/home/_task.html.haml +1 -1
- data/app/views/home/index.xls.builder +51 -0
- data/app/views/layouts/_sidebar.html.haml +2 -2
- data/app/views/layouts/_tabbed.html.haml +14 -11
- data/app/views/layouts/application.html.haml +2 -2
- data/app/views/leads/_edit.html.haml +2 -2
- data/app/views/leads/_new.html.haml +2 -2
- data/app/views/leads/_sidebar_index.html.haml +2 -2
- data/app/views/leads/_sidebar_show.html.haml +30 -30
- data/app/views/leads/create.js.haml +2 -3
- data/app/views/leads/destroy.js.haml +2 -2
- data/app/views/leads/promote.js.haml +3 -4
- data/app/views/leads/reject.js.haml +3 -3
- data/app/views/leads/show.html.haml +1 -1
- data/app/views/leads/update.js.haml +4 -5
- data/app/views/lists/create.js.haml +0 -1
- data/app/views/opportunities/_edit.html.haml +1 -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 +1 -1
- data/app/views/opportunities/_sidebar_index.html.haml +2 -2
- data/app/views/opportunities/_sidebar_show.html.haml +47 -46
- data/app/views/opportunities/create.js.haml +3 -4
- data/app/views/opportunities/destroy.js.haml +3 -3
- data/app/views/opportunities/show.html.haml +1 -0
- data/app/views/opportunities/update.js.haml +5 -6
- data/app/views/shared/_inline_styles.html.haml +0 -26
- data/app/views/tasks/_assigned.html.haml +1 -1
- data/app/views/tasks/_completed.html.haml +1 -1
- data/app/views/tasks/_edit.html.haml +1 -1
- data/app/views/tasks/_new.html.haml +1 -1
- data/app/views/tasks/_pending.html.haml +1 -1
- data/app/views/tasks/_related.html.haml +1 -1
- data/app/views/tasks/_selector.html.haml +7 -8
- data/app/views/tasks/_sidebar_index.html.haml +2 -2
- data/app/views/tasks/_title.html.haml +1 -1
- data/app/views/tasks/complete.js.haml +1 -1
- data/app/views/tasks/create.js.haml +1 -2
- data/app/views/tasks/destroy.js.haml +1 -1
- data/app/views/tasks/uncomplete.js.haml +1 -2
- data/app/views/tasks/update.js.haml +0 -1
- data/app/views/users/change_password.js.haml +0 -1
- data/app/views/users/update.js.haml +0 -1
- data/app/views/users/upload_avatar.js.haml +0 -1
- data/app/views/versions/_version_item.html.haml +1 -1
- data/bin/setup +6 -6
- data/config/application.rb +1 -1
- data/config/environment.rb +1 -1
- data/config/initializers/content_security_policy.rb +5 -0
- data/config/initializers/new_framework_defaults_6_0.rb +46 -0
- data/config/initializers/simple_form.rb +135 -55
- data/config/initializers/simple_form_bootstrap.rb +433 -0
- data/config/locales/fat_free_crm.cs.yml +86 -47
- data/config/locales/fat_free_crm.ru.yml +1 -0
- data/config/settings.default.yml +0 -41
- data/db/migrate/20200806004152_add_pattern_to_fields.rb +7 -0
- data/db/migrate/20200806004459_add_html5_to_fields.rb +10 -0
- data/db/schema.rb +11 -6
- data/fat_free_crm.gemspec +4 -4
- data/lib/fat_free_crm/core_ext.rb +1 -1
- data/lib/fat_free_crm/gem_ext.rb +0 -1
- data/lib/fat_free_crm/tabs.rb +2 -2
- data/lib/fat_free_crm/version.rb +2 -2
- data/lib/gravatar_image_tag.rb +1 -1
- data/lib/tasks/ffcrm/preference_update.rake +19 -0
- data/lib/tasks/ffcrm/setup.rake +1 -1
- data/lib/templates/erb/scaffold/_form.html.erb +4 -2
- data/spec/controllers/comments_controller_spec.rb +6 -6
- data/spec/controllers/home_controller_spec.rb +3 -3
- data/spec/controllers/users_controller_spec.rb +13 -1
- data/spec/factories/user_factories.rb +5 -2
- data/spec/features/acceptance_helper.rb +1 -1
- data/spec/features/accounts_spec.rb +2 -2
- data/spec/features/admin/groups_spec.rb +1 -1
- data/spec/features/admin/users_spec.rb +1 -1
- data/spec/features/campaigns_spec.rb +2 -2
- data/spec/features/contacts_spec.rb +2 -5
- data/spec/features/leads_spec.rb +11 -7
- data/spec/features/opportunities_spec.rb +4 -4
- data/spec/features/support/browser.rb +6 -2
- data/spec/features/support/selector_helpers.rb +10 -1
- data/spec/features/tasks_spec.rb +6 -6
- data/spec/helpers/accounts_helper_spec.rb +57 -0
- data/spec/models/entities/opportunity_spec.rb +2 -2
- data/spec/models/fields/custom_field_pair_spec.rb +2 -2
- data/spec/models/observers/entity_observer_spec.rb +3 -3
- data/spec/models/polymorphic/task_spec.rb +11 -11
- data/spec/models/polymorphic/version_spec.rb +2 -2
- data/spec/models/users/preference_spec.rb +1 -1
- data/spec/views/accounts/_edit.haml_spec.rb +1 -1
- data/spec/views/accounts/_new.haml_spec.rb +1 -1
- data/spec/views/accounts/create.js.haml_spec.rb +0 -1
- data/spec/views/accounts/update.js.haml_spec.rb +2 -5
- data/spec/views/admin/field_groups/create.js.haml_spec.rb +0 -1
- data/spec/views/admin/field_groups/update.js.haml_spec.rb +0 -1
- data/spec/views/admin/users/create.js.haml_spec.rb +0 -1
- data/spec/views/admin/users/destroy.js.haml_spec.rb +0 -6
- data/spec/views/admin/users/update.js.haml_spec.rb +1 -2
- data/spec/views/campaigns/_edit.haml_spec.rb +1 -1
- data/spec/views/campaigns/_new.haml_spec.rb +1 -1
- data/spec/views/campaigns/create.js.haml_spec.rb +0 -1
- data/spec/views/campaigns/destroy.js.haml_spec.rb +0 -1
- data/spec/views/campaigns/update.js.haml_spec.rb +2 -6
- data/spec/views/contacts/_edit.haml_spec.rb +1 -1
- data/spec/views/contacts/_new.haml_spec.rb +1 -1
- data/spec/views/contacts/create.js.haml_spec.rb +0 -1
- data/spec/views/contacts/update.js.haml_spec.rb +3 -7
- data/spec/views/home/index.haml_spec.rb +2 -2
- data/spec/views/leads/_edit.haml_spec.rb +1 -1
- data/spec/views/leads/_new.haml_spec.rb +1 -1
- data/spec/views/leads/create.js.haml_spec.rb +0 -3
- data/spec/views/leads/destroy.js.haml_spec.rb +0 -2
- data/spec/views/leads/promote.js.haml_spec.rb +3 -11
- data/spec/views/leads/reject.js.haml_spec.rb +0 -3
- data/spec/views/leads/update.js.haml_spec.rb +3 -11
- data/spec/views/opportunities/_edit.haml_spec.rb +1 -1
- data/spec/views/opportunities/_new.haml_spec.rb +1 -1
- data/spec/views/opportunities/create.js.haml_spec.rb +0 -2
- data/spec/views/opportunities/destroy.js.haml_spec.rb +0 -3
- data/spec/views/opportunities/update.js.haml_spec.rb +3 -11
- data/spec/views/tasks/_edit.haml_spec.rb +1 -1
- data/spec/views/tasks/complete.js.haml_spec.rb +0 -1
- data/spec/views/tasks/create.js.haml_spec.rb +0 -2
- data/spec/views/tasks/destroy.js.haml_spec.rb +0 -1
- data/spec/views/tasks/uncomplete.js.haml_spec.rb +0 -1
- data/spec/views/tasks/update.js.haml_spec.rb +1 -4
- data/spec/views/users/change_password.js.haml_spec.rb +1 -2
- data/spec/views/users/update.js.haml_spec.rb +1 -2
- data/spec/views/users/upload_avatar.js.haml_spec.rb +1 -2
- metadata +23 -14
- data/config/initializers/new_framework_defaults_5_2.rb +0 -40
- data/lib/fat_free_crm/gem_ext/simple_form/action_view_extensions/form_helper.rb +0 -24
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
$('##{dom_id(@entity)}').css('background-color', '#ffe4e1').slideUp(250);
|
5
5
|
- if called_from_index_page?
|
6
|
-
= refresh_sidebar(:index
|
6
|
+
= refresh_sidebar(:index)
|
7
7
|
$('#paginate').replaceWith('#{ j render(partial: "shared/paginate_with_per_page") }');
|
8
8
|
- elsif called_from_landing_page?("campaigns")
|
9
|
-
= refresh_sidebar_for(:campaigns, :show
|
9
|
+
= refresh_sidebar_for(:campaigns, :show)
|
@@ -6,14 +6,14 @@
|
|
6
6
|
- if called_from_landing_page?
|
7
7
|
crm.flip_form('convert_#{entity_name}');
|
8
8
|
crm.set_title('convert_#{entity_name}', '#{h @entity.full_name}');
|
9
|
-
= refresh_sidebar(:show
|
9
|
+
= refresh_sidebar(:show)
|
10
10
|
- else
|
11
11
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
12
12
|
$('##{id}').effect("highlight", { duration:1500 });
|
13
13
|
- if called_from_index_page?
|
14
|
-
= refresh_sidebar(:index
|
14
|
+
= refresh_sidebar(:index)
|
15
15
|
- elsif called_from_landing_page?("campaigns")
|
16
|
-
= refresh_sidebar_for(:campaigns, :show
|
16
|
+
= refresh_sidebar_for(:campaigns, :show)
|
17
17
|
- if @opportunity.id # Make sure the opportunity has been saved.
|
18
18
|
$('#opportunities').prepend('#{ j render(partial: "opportunities/opportunity", collection: [ @opportunity ]) }');
|
19
19
|
- else
|
@@ -22,5 +22,4 @@
|
|
22
22
|
- else
|
23
23
|
$('##{id}').html('#{ j render(partial: "convert") }');
|
24
24
|
crm.create_or_select_account(#{ request.referer =~ /\/accounts\// || @account.id.blank? });
|
25
|
-
$('##{id}').effect("shake", { duration:250, distance: 6 });
|
26
25
|
$('##{dom_id(@entity, :edit)} input[type!=hidden]').first().focus();
|
@@ -5,8 +5,8 @@
|
|
5
5
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
6
6
|
$('##{id}').effect("highlight", { duration:1500 });
|
7
7
|
- if called_from_index_page?
|
8
|
-
= refresh_sidebar(:index
|
8
|
+
= refresh_sidebar(:index)
|
9
9
|
- elsif called_from_landing_page?("campaigns")
|
10
|
-
= refresh_sidebar_for(:campaigns, :show
|
10
|
+
= refresh_sidebar_for(:campaigns, :show)
|
11
11
|
- else
|
12
|
-
= refresh_sidebar(:show
|
12
|
+
= refresh_sidebar(:show)
|
@@ -6,23 +6,22 @@
|
|
6
6
|
- if called_from_landing_page?
|
7
7
|
crm.flip_form('edit_#{entity_name}');
|
8
8
|
crm.set_title('edit_#{entity_name}', '#{h @entity.full_name}');
|
9
|
-
= refresh_sidebar(:show
|
9
|
+
= refresh_sidebar(:show)
|
10
10
|
- else
|
11
11
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
12
12
|
$('##{id}').effect("highlight", { duration:1500 });
|
13
13
|
- if called_from_index_page?
|
14
|
-
= refresh_sidebar(:index
|
14
|
+
= refresh_sidebar(:index)
|
15
15
|
- elsif called_from_landing_page?("campaigns")
|
16
|
-
= refresh_sidebar_for(:campaigns, :show
|
16
|
+
= refresh_sidebar_for(:campaigns, :show)
|
17
17
|
- else
|
18
18
|
$('#recently').replaceWith('#{ j render(partial: "shared/recently") }');
|
19
19
|
|
20
20
|
- else
|
21
21
|
$('##{id}').html('#{ j render(partial: "edit") }');
|
22
|
-
$('##{id}').effect("shake", { duration:250, distance: 6 });
|
23
22
|
- if @entity.errors[:first_name].blank? and entity.errors[:last_name].present?
|
24
23
|
$('#lead_last_name').focus();
|
25
24
|
- else
|
26
25
|
$('##{dom_id(@entity, :edit)} input[type!=hidden]').first().focus();
|
27
26
|
|
28
|
-
= hook(:entity_update, self, {entity: @entity})
|
27
|
+
= hook(:entity_update, self, {entity: @entity})
|
@@ -13,6 +13,6 @@
|
|
13
13
|
= hook(:entity_form, self, {f: f, entity: @opportunity})
|
14
14
|
|
15
15
|
.buttonbar
|
16
|
-
= f.submit t(:save_opportunity), onclick: %/$("#account_assigned_to").val($("#opportunity_assigned_to").val())
|
16
|
+
= f.submit t(:save_opportunity), onclick: %/$("#account_assigned_to").val($("#opportunity_assigned_to").val());/, class: 'btn btn-primary'
|
17
17
|
#{t :or}
|
18
18
|
= link_to_cancel edit_opportunity_path(@opportunity)
|
@@ -13,6 +13,6 @@
|
|
13
13
|
= hook(:entity_form, self, {f: f, entity: @opportunity})
|
14
14
|
|
15
15
|
.buttonbar
|
16
|
-
= f.submit t(:create_opportunity), onclick: %/$("#account_assigned_to").val($("#opportunity_assigned_to").val()); if ($("#account_id").css('display') != 'none') { $("#account_id").enable(); }
|
16
|
+
= f.submit t(:create_opportunity), onclick: %/$("#account_assigned_to").val($("#opportunity_assigned_to").val()); if ($("#account_id").css('display') != 'none') { $("#account_id").enable(); }/, class: 'btn btn-primary'
|
17
17
|
#{t :or}
|
18
18
|
= link_to_cancel new_opportunity_path
|
@@ -1,13 +1,13 @@
|
|
1
1
|
.filters#filters
|
2
2
|
.caption= t :opportunity_stages
|
3
3
|
- @stage.each do |value, key|
|
4
|
-
.check_box
|
4
|
+
.check_box
|
5
5
|
%div{style: "float:right;"}
|
6
6
|
= @opportunity_stage_total[key]
|
7
7
|
= opportunity_stage_checkbox(key, @opportunity_stage_total[key])
|
8
8
|
= label_tag(key, value)
|
9
9
|
|
10
|
-
.check_box
|
10
|
+
.check_box
|
11
11
|
%div{style: "float:right;"}
|
12
12
|
= @opportunity_stage_total[:other]
|
13
13
|
= opportunity_stage_checkbox("other", @opportunity_stage_total[:other])
|
@@ -1,52 +1,53 @@
|
|
1
1
|
.panel#summary
|
2
2
|
.caption #{t :opportunity_summary}
|
3
|
-
%
|
4
|
-
%
|
5
|
-
|
6
|
-
|
7
|
-
%
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
%
|
20
|
-
|
21
|
-
|
22
|
-
%
|
23
|
-
|
24
|
-
|
25
|
-
%
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
%tt #{t :discount}:
|
30
|
-
%li
|
31
|
-
%dt= @opportunity.amount ? number_to_currency(@opportunity.weighted_amount.to_f, precision: 0) : t(:n_a)
|
32
|
-
%tt #{t :weighted_amount}:
|
33
|
-
%li
|
34
|
-
%dt= @opportunity.assigned_to ? truncate(@opportunity.assignee.full_name, length: 16) : nil
|
35
|
-
%tt #{t :assigned_to}:
|
36
|
-
%li
|
37
|
-
%dt
|
38
|
-
- if @opportunity.account
|
39
|
-
= link_to(truncate(@opportunity.account.name, length: 16), @opportunity.account, title: @opportunity.account.name)
|
40
|
-
- else
|
41
|
-
#{t :n_a}
|
42
|
-
%tt #{t :account}:
|
43
|
-
%li.last
|
44
|
-
%dt
|
45
|
-
- if @opportunity.campaign
|
46
|
-
= link_to(truncate(@opportunity.campaign.name, length: 16), @opportunity.campaign, title: @opportunity.campaign.name)
|
3
|
+
%dl
|
4
|
+
%li
|
5
|
+
%dt= @opportunity.stage ? t(@opportunity.stage) : t(:other)
|
6
|
+
%tt #{t :stage}:
|
7
|
+
%li
|
8
|
+
%dt= @opportunity.closes_on ? l(@opportunity.closes_on, format: :mmdd) : t(:n_a)
|
9
|
+
%tt #{t :close_date}:
|
10
|
+
- if @opportunity.closes_on && @opportunity.stage !~ /lost|won/
|
11
|
+
%li
|
12
|
+
- days_left = (@opportunity.closes_on - Date.today).to_i
|
13
|
+
- if days_left >= 0
|
14
|
+
%dt= days_left
|
15
|
+
%tt #{t :days_left}:
|
16
|
+
- else
|
17
|
+
%dt.warn= t('pluralize.day', count: (days_left * -1))
|
18
|
+
%tt #{t :days_late}:
|
19
|
+
%li
|
20
|
+
%dt= @opportunity.probability ? @opportunity.probability.to_s + "%" : t(:n_a)
|
21
|
+
%tt #{t :probability}:
|
22
|
+
%li
|
23
|
+
%dt= @opportunity.amount ? number_to_currency(@opportunity.amount.to_f, precision: 0) : t(:n_a)
|
24
|
+
%tt #{t :amount}:
|
25
|
+
%li
|
26
|
+
%dt= @opportunity.discount ? number_to_currency(@opportunity.discount.to_f, precision: 0) : t(:n_a)
|
27
|
+
- if @opportunity.amount && @opportunity.discount
|
28
|
+
%tt== Discount (#{number_to_percentage(@opportunity.discount / @opportunity.amount * 100, precision: 1)}):
|
47
29
|
- else
|
48
|
-
#{t :
|
49
|
-
%
|
30
|
+
%tt #{t :discount}:
|
31
|
+
%li
|
32
|
+
%dt= @opportunity.amount ? number_to_currency(@opportunity.weighted_amount.to_f, precision: 0) : t(:n_a)
|
33
|
+
%tt #{t :weighted_amount}:
|
34
|
+
%li
|
35
|
+
%dt= @opportunity.assigned_to ? truncate(@opportunity.assignee.full_name, length: 16) : nil
|
36
|
+
%tt #{t :assigned_to}:
|
37
|
+
%li
|
38
|
+
%dt
|
39
|
+
- if @opportunity.account
|
40
|
+
= link_to(truncate(@opportunity.account.name, length: 16), @opportunity.account, title: @opportunity.account.name)
|
41
|
+
- else
|
42
|
+
#{t :n_a}
|
43
|
+
%tt #{t :account}:
|
44
|
+
%li.last
|
45
|
+
%dt
|
46
|
+
- if @opportunity.campaign
|
47
|
+
= link_to(truncate(@opportunity.campaign.name, length: 16), @opportunity.campaign, title: @opportunity.campaign.name)
|
48
|
+
- else
|
49
|
+
#{t :n_a}
|
50
|
+
%tt #{t :campaign}:
|
50
51
|
|
51
52
|
- unless @opportunity.background_info.blank?
|
52
53
|
.caption #{t :background_info}
|
@@ -10,14 +10,14 @@
|
|
10
10
|
$('##{dom_id(@entity)}').effect("highlight", { duration:1500 });
|
11
11
|
|
12
12
|
- if called_from_index_page?
|
13
|
-
= refresh_sidebar(:index
|
13
|
+
= refresh_sidebar(:index)
|
14
14
|
$('#paginate').html('#{ j render(partial: "shared/paginate_with_per_page") }');
|
15
15
|
- elsif called_from_landing_page?("accounts") # Opportunity created on Account landing page: refresh Account summary.
|
16
16
|
- @account.reload
|
17
|
-
= refresh_sidebar_for(:accounts, :show
|
17
|
+
= refresh_sidebar_for(:accounts, :show)
|
18
18
|
- elsif called_from_landing_page?("campaigns") # Opportunity created on Campaign landing page: refresh Campaign summary.
|
19
19
|
- @campaign.reload
|
20
|
-
= refresh_sidebar_for(:campaigns, :show
|
20
|
+
= refresh_sidebar_for(:campaigns, :show)
|
21
21
|
- else # Opportunity created on Contact landing page: refresh recent items list.
|
22
22
|
$('#recently').replaceWith('#{ j render(partial: "shared/recently") }');
|
23
23
|
crm.flick('empty', 'remove');
|
@@ -25,5 +25,4 @@
|
|
25
25
|
- else
|
26
26
|
$('##{create_id}').html('#{ j render(partial: "new") }');
|
27
27
|
crm.create_or_select_account(#{ request.referer =~ /\/accounts\// || @account.id.blank? });
|
28
|
-
$('##{create_id}').effect("shake", { duration:250, distance: 6 });
|
29
28
|
$('#new_#{entity_name} input[type!=hidden]').first().focus();
|
@@ -3,11 +3,11 @@
|
|
3
3
|
|
4
4
|
$('##{dom_id(@entity)}').css('background-color', '#ffe4e1').slideUp(250);
|
5
5
|
- if called_from_index_page?
|
6
|
-
= refresh_sidebar(:index
|
6
|
+
= refresh_sidebar(:index)
|
7
7
|
$('#paginate').html('#{ j render(partial: "shared/paginate_with_per_page") }');
|
8
8
|
- elsif called_from_landing_page?("accounts")
|
9
|
-
= refresh_sidebar_for(:accounts, :show
|
9
|
+
= refresh_sidebar_for(:accounts, :show)
|
10
10
|
- elsif called_from_landing_page?("campaigns")
|
11
|
-
= refresh_sidebar_for(:campaigns, :show
|
11
|
+
= refresh_sidebar_for(:campaigns, :show)
|
12
12
|
- else
|
13
13
|
$('#recently').replaceWith('#{ j render(partial: "shared/recently") }');
|
@@ -7,6 +7,7 @@
|
|
7
7
|
= styles_for :task, :contact
|
8
8
|
|
9
9
|
= render 'opportunities/title_bar', opportunity: @opportunity
|
10
|
+
= render 'opportunities/sidebar_show', opportunity: @opportunity
|
10
11
|
|
11
12
|
= render "comments/new", commentable: @opportunity
|
12
13
|
= render partial: "shared/timeline", collection: @timeline
|
@@ -6,22 +6,21 @@
|
|
6
6
|
- if called_from_landing_page?
|
7
7
|
crm.flip_form('edit_#{entity_name}');
|
8
8
|
crm.set_title('edit_#{entity_name}', '#{h @entity.name}');
|
9
|
-
= refresh_sidebar(:show
|
9
|
+
= refresh_sidebar(:show)
|
10
10
|
- else
|
11
11
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
12
12
|
$('##{id}').effect("highlight", { duration:1500 });
|
13
13
|
- if called_from_index_page?
|
14
|
-
= refresh_sidebar(:index
|
14
|
+
= refresh_sidebar(:index)
|
15
15
|
- elsif called_from_landing_page?(:accounts)
|
16
|
-
= refresh_sidebar_for(:accounts, :show
|
16
|
+
= refresh_sidebar_for(:accounts, :show)
|
17
17
|
- elsif called_from_landing_page?(:campaigns)
|
18
|
-
= refresh_sidebar_for(:campaigns, :show
|
18
|
+
= refresh_sidebar_for(:campaigns, :show)
|
19
19
|
- else
|
20
20
|
$('#recently').replaceWith('#{ j render(partial: "shared/recently") }');
|
21
21
|
- else
|
22
22
|
$('##{id}').html('#{ j render(partial: "edit") }');
|
23
23
|
crm.create_or_select_account(#{ request.referer =~ /\/accounts\// || @account.id.blank? });
|
24
|
-
$('##{id}').effect("shake", { duration:250, distance: 6 });
|
25
24
|
$('##{dom_id(@entity, :edit)} input[type!=hidden]').first().focus();
|
26
25
|
|
27
|
-
= hook(:entity_update, self, {entity: @entity})
|
26
|
+
= hook(:entity_update, self, {entity: @entity})
|
@@ -1,31 +1,5 @@
|
|
1
1
|
-# Generate dynamic styles that get embedded on the page.
|
2
2
|
- content_for :styles do
|
3
3
|
|
4
|
-
- if models.include?(:account)
|
5
|
-
- Setting.account_category_color.each do |key, value|
|
6
|
-
li.account .#{key} { background:#{value}; }
|
7
|
-
|
8
|
-
- if models.include?(:campaign)
|
9
|
-
- Setting.campaign_status_color.each do |key, value|
|
10
|
-
li.campaign .#{key} { background:#{value}; }
|
11
|
-
|
12
|
-
- if models.include?(:lead)
|
13
|
-
- Setting.lead_status_color.each do |key, value|
|
14
|
-
li.lead .#{key} { background:#{value}; }
|
15
|
-
|
16
|
-
- if models.include?(:opportunity)
|
17
|
-
- Setting.opportunity_stage_color.each do |key, value|
|
18
|
-
li.opportunity .#{key} { background:#{value}; }
|
19
|
-
|
20
|
-
- if models.include?(:task)
|
21
|
-
- Setting.task_category_color.each do |key, value|
|
22
|
-
li.task .#{key} { background:#{value}; }
|
23
|
-
|
24
|
-
- if models.include?(:user)
|
25
|
-
li.user .admin { background: lightblue; }
|
26
|
-
li.user .suspended { background: gainsboro; }
|
27
|
-
li.user .active { background: lightgreen; }
|
28
|
-
li.user .signed_up { background: lightsalmon; }
|
29
|
-
|
30
4
|
= hook(:inline_styles, self, local_assigns)
|
31
5
|
|
@@ -2,7 +2,7 @@
|
|
2
2
|
- unless related.category.blank?
|
3
3
|
.strip{class: related.category}= t(related.category)
|
4
4
|
- else
|
5
|
-
.strip
|
5
|
+
.strip.other #{t :other}
|
6
6
|
%div
|
7
7
|
- if related.assigned_to
|
8
8
|
= link_to(related.assignee.full_name, user_path(related.assignee))
|
@@ -1,8 +1,7 @@
|
|
1
|
-
%
|
2
|
-
%
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
= t :completed_tab
|
1
|
+
%nav{ class: "nav nav-pills nav-sm" }
|
2
|
+
%a{ class: "nav-link " + (@view == "pending" ? "active" : "off"), href: tasks_path }
|
3
|
+
= t :pending_tab
|
4
|
+
%a{ class: "nav-link " + (@view == "assigned" ? "active" : "off"), href: url_for(action: :index, view: "assigned") }
|
5
|
+
= t :assigned_tab
|
6
|
+
%a{ class: "nav-link " + (@view == "completed" ? "active" : "off"), href: url_for(action: :index, view: "completed") }
|
7
|
+
= t :completed_tab
|
@@ -2,13 +2,13 @@
|
|
2
2
|
= render "selector"
|
3
3
|
- if @view == "pending" || @view == "assigned"
|
4
4
|
- Setting.unroll(:task_bucket).each do |value, key|
|
5
|
-
.check_box
|
5
|
+
.check_box
|
6
6
|
%div{style: "float:right;"}
|
7
7
|
= @task_total[key]
|
8
8
|
= task_filter_checkbox(@view, key, @task_total[key]) + " " + t(value)
|
9
9
|
- else # @view == "completed"
|
10
10
|
- Setting.unroll(:task_completed).each do |value, key|
|
11
|
-
.check_box
|
11
|
+
.check_box
|
12
12
|
%div{style: "float:right;"}
|
13
13
|
= @task_total[key]
|
14
14
|
= task_filter_checkbox(@view, key, @task_total[key]) + " " + t(value)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
.title_tools
|
2
|
-
= link_to_inline(:create_task, url_for(action: :new, view: @view), text: t(:create_task))
|
2
|
+
= link_to_inline(:create_task, url_for(action: :new, view: @view), text: t(:create_task), class: 'btn-sm btn-primary')
|
3
3
|
.title#title
|
4
4
|
= (@view == "assigned" ? t(:assigned_tasks) : t(:tasks))
|
5
5
|
= image_tag("loading.gif", size: :thumb, id: "loading", style: "display: none;")
|
@@ -4,7 +4,7 @@
|
|
4
4
|
$('##{dom_id(@task)}').fadeOut({ duration:500 });
|
5
5
|
- if @empty_bucket
|
6
6
|
$('#list_#{@empty_bucket}').fadeOut({ duration:500 });
|
7
|
-
= refresh_sidebar(:index
|
7
|
+
= refresh_sidebar(:index)
|
8
8
|
|
9
9
|
- else # Completing from the Asset page -- replace task partial with completed one.
|
10
10
|
|
@@ -22,7 +22,7 @@
|
|
22
22
|
$('#list_#{bucket}').show();
|
23
23
|
$('##{bucket}').before('#{ j render(partial: @view, collection: [ @task ], locals: { bucket: bucket }) }');
|
24
24
|
$('##{dom_id(@task)}').effect("highlight", { duration:1500 });
|
25
|
-
= refresh_sidebar(:index
|
25
|
+
= refresh_sidebar(:index)
|
26
26
|
|
27
27
|
crm.flick('empty', 'remove');
|
28
28
|
|
@@ -34,6 +34,5 @@
|
|
34
34
|
$('#recently').replaceWith('#{ j render(partial: "shared/recently") }');
|
35
35
|
|
36
36
|
- else # Couldn't create the task -- validation failed.
|
37
|
-
$('#create_task').effect("shake", { duration:250, distance: 6 });
|
38
37
|
$('#task_name').focus();
|
39
38
|
$('#new_task input[type=submit]').enable();
|
@@ -5,8 +5,7 @@
|
|
5
5
|
$('#list_#{@empty_bucket}').fadeOut({ duration:500 });
|
6
6
|
|
7
7
|
- if called_from_index_page?
|
8
|
-
= refresh_sidebar(:index
|
8
|
+
= refresh_sidebar(:index)
|
9
9
|
- else # Errors
|
10
|
-
$('##{dom_id(@task)}').effect("shake", { duration:250, distance: 6 });
|
11
10
|
$('#task_name').focus();
|
12
11
|
$('#task_submit').enable();
|
@@ -1,6 +1,6 @@
|
|
1
1
|
- if [first, second].any?(&:present?)
|
2
2
|
%br
|
3
|
-
- if first.blank? and second.present?
|
3
|
+
- if first.blank? and second.present? && !second.is_a?(Time)
|
4
4
|
= t('version.set_html', attr: label, to: second)
|
5
5
|
- elsif first.present? and second.present?
|
6
6
|
= t('version.change_html', attr: label, from: first, to: second)
|
data/bin/setup
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require 'fileutils'
|
5
|
-
include FileUtils
|
6
5
|
|
7
6
|
# path to your application root.
|
8
7
|
APP_ROOT = File.expand_path('..', __dir__)
|
@@ -11,24 +10,25 @@ def system!(*args)
|
|
11
10
|
system(*args) || abort("\n== Command #{args} failed ==")
|
12
11
|
end
|
13
12
|
|
14
|
-
chdir APP_ROOT do
|
15
|
-
# This script is a
|
13
|
+
FileUtils.chdir APP_ROOT do
|
14
|
+
# This script is a way to setup or update your development environment automatically.
|
15
|
+
# This script is idempotent, so that you can run it at anytime and get an expectable outcome.
|
16
16
|
# Add necessary setup steps to this file.
|
17
17
|
|
18
18
|
puts '== Installing dependencies =='
|
19
19
|
system! 'gem install bundler --conservative'
|
20
20
|
system('bundle check') || system!('bundle install')
|
21
21
|
|
22
|
-
# Install JavaScript dependencies
|
22
|
+
# Install JavaScript dependencies
|
23
23
|
# system('bin/yarn')
|
24
24
|
|
25
25
|
# puts "\n== Copying sample files =="
|
26
26
|
# unless File.exist?('config/database.yml')
|
27
|
-
# cp 'config/database.yml.sample', 'config/database.yml'
|
27
|
+
# FileUtils.cp 'config/database.yml.sample', 'config/database.yml'
|
28
28
|
# end
|
29
29
|
|
30
30
|
puts "\n== Preparing database =="
|
31
|
-
system! 'bin/rails db:
|
31
|
+
system! 'bin/rails db:prepare'
|
32
32
|
|
33
33
|
puts "\n== Removing old logs and tempfiles =="
|
34
34
|
system! 'bin/rails log:clear tmp:clear'
|
data/config/application.rb
CHANGED
@@ -29,7 +29,7 @@ require 'fat_free_crm/gem_ext/rails/engine'
|
|
29
29
|
module FatFreeCRM
|
30
30
|
class Application < Rails::Application
|
31
31
|
# Initialize configuration defaults for originally generated Rails version.
|
32
|
-
config.load_defaults
|
32
|
+
config.load_defaults 6.0
|
33
33
|
|
34
34
|
# Settings in config/environments/* take precedence over those specified here.
|
35
35
|
# Application configuration should go into files in config/initializers
|
data/config/environment.rb
CHANGED
@@ -12,6 +12,8 @@
|
|
12
12
|
# policy.object_src :none
|
13
13
|
# policy.script_src :self, :https
|
14
14
|
# policy.style_src :self, :https
|
15
|
+
# # If you are using webpack-dev-server then specify webpack-dev-server host
|
16
|
+
# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development?
|
15
17
|
|
16
18
|
# # Specify URI for violation reports
|
17
19
|
# # policy.report_uri "/csp-violation-report-endpoint"
|
@@ -20,6 +22,9 @@
|
|
20
22
|
# If you are using UJS then enable automatic nonce generation
|
21
23
|
# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) }
|
22
24
|
|
25
|
+
# Set the nonce only to specific directives
|
26
|
+
# Rails.application.config.content_security_policy_nonce_directives = %w(script-src)
|
27
|
+
|
23
28
|
# Report CSP violations to a specified URI
|
24
29
|
# For further information see the following documentation:
|
25
30
|
# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only
|