fat_free_crm 0.21.0 → 0.22.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of fat_free_crm might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/app/assets/config/fat_free_crm.js +3 -0
- data/app/assets/config/manifest.js +1 -3
- data/app/assets/javascripts/application.js.erb +1 -0
- data/app/assets/javascripts/crm.js.coffee +6 -3
- data/app/assets/javascripts/crm_select2.js.coffee +4 -1
- data/app/assets/javascripts/crm_tags.js.coffee +4 -4
- data/app/assets/javascripts/crm_validations.js.coffee +12 -0
- data/app/assets/stylesheets/bootstrap-custom.scss +3 -3
- data/app/assets/stylesheets/common.scss +9 -0
- data/app/assets/stylesheets/rails.scss +1 -1
- data/app/controllers/admin/field_groups_controller.rb +0 -2
- data/app/controllers/admin/fields_controller.rb +16 -13
- data/app/controllers/admin/tags_controller.rb +1 -1
- data/app/controllers/admin/users_controller.rb +1 -1
- data/app/controllers/application_controller.rb +11 -0
- data/app/controllers/comments_controller.rb +2 -0
- data/app/controllers/emails_controller.rb +2 -0
- data/app/controllers/entities/accounts_controller.rb +3 -1
- data/app/controllers/entities/campaigns_controller.rb +3 -1
- data/app/controllers/entities/contacts_controller.rb +3 -1
- data/app/controllers/entities/leads_controller.rb +4 -2
- data/app/controllers/entities/opportunities_controller.rb +3 -1
- data/app/controllers/entities_controller.rb +3 -1
- data/app/controllers/home_controller.rb +2 -0
- data/app/controllers/lists_controller.rb +7 -4
- data/app/controllers/tasks_controller.rb +3 -1
- data/app/controllers/users_controller.rb +2 -0
- data/app/helpers/application_helper.rb +4 -4
- data/app/helpers/opportunities_helper.rb +4 -2
- data/app/helpers/users_helper.rb +1 -1
- data/app/models/entities/campaign.rb +2 -2
- data/app/models/fields/custom_field.rb +2 -2
- data/app/models/fields/custom_field_pair.rb +6 -7
- data/app/models/fields/field.rb +1 -3
- data/app/models/list.rb +1 -1
- data/app/models/observers/entity_observer.rb +1 -1
- data/app/models/polymorphic/comment.rb +1 -1
- data/app/models/setting.rb +4 -5
- data/app/models/users/user.rb +1 -1
- data/app/views/accounts/_contact_info.html.haml +1 -1
- data/app/views/accounts/_top_section.html.haml +3 -3
- data/app/views/accounts/show.js.haml +1 -1
- data/app/views/accounts/update.js.haml +1 -0
- data/app/views/admin/custom_fields/_check_boxes_field.html.haml +4 -1
- data/app/views/admin/custom_fields/_date_pair_field.html.haml +1 -1
- data/app/views/campaigns/_top_section.html.haml +2 -2
- data/app/views/campaigns/show.js.haml +1 -1
- data/app/views/campaigns/update.js.haml +1 -0
- data/app/views/contacts/_top_section.html.haml +5 -5
- data/app/views/contacts/show.js.haml +2 -3
- data/app/views/contacts/update.js.haml +1 -0
- data/app/views/devise/sessions/new.html.haml +4 -5
- data/app/views/fields/_group.html.haml +5 -2
- data/app/views/fields/_group_table.html.haml +4 -5
- data/app/views/fields/_group_view.html.haml +4 -1
- data/app/views/fields/_sidebar_show.html.haml +5 -8
- data/app/views/fields/group.js.erb +3 -1
- data/app/views/layouts/application.html.haml +1 -1
- data/app/views/leads/_top_section.html.haml +4 -4
- data/app/views/leads/show.js.haml +1 -1
- data/app/views/leads/update.js.haml +1 -0
- data/app/views/opportunities/_top_section.html.haml +2 -2
- data/app/views/opportunities/show.js.haml +1 -1
- data/app/views/opportunities/update.js.haml +1 -0
- data/app/views/shared/_add_comment.html.haml +1 -1
- data/app/views/shared/_address.html.haml +1 -1
- data/app/views/tasks/_top_section.html.haml +4 -4
- data/bin/bundle +108 -2
- data/bin/rails +3 -3
- data/bin/rake +2 -2
- data/bin/setup +12 -15
- data/config/application.rb +9 -4
- data/config/boot.rb +3 -5
- data/config/cable.yml +10 -0
- data/config/database.yml +25 -0
- data/config/environment.rb +4 -3
- data/config/environments/development.rb +47 -14
- data/config/environments/production.rb +17 -15
- data/config/environments/test.rb +19 -9
- data/config/initializers/action_mailer.rb +1 -0
- data/config/initializers/content_security_policy.rb +21 -26
- data/config/initializers/custom_field_ransack_translations.rb +2 -1
- data/config/initializers/filter_parameter_logging.rb +6 -2
- data/config/initializers/inflections.rb +4 -4
- data/config/initializers/permissions_policy.rb +12 -0
- data/config/settings.default.yml +2 -1
- data/config/storage.yml +5 -5
- data/db/demo/field_groups.yml +2 -1
- data/db/migrate/20230526212613_convert_to_active_storage.rb +27 -11
- data/db/schema.rb +107 -105
- data/lib/fat_free_crm/callback.rb +2 -3
- data/lib/fat_free_crm/custom_fields.rb +1 -0
- data/lib/fat_free_crm/mail_processor/dropbox.rb +1 -1
- data/lib/fat_free_crm/version.rb +2 -2
- metadata +43 -19
- data/config/initializers/new_framework_defaults_6_0.rb +0 -46
@@ -19,7 +19,7 @@ class EntityObserver < ActiveRecord::Observer
|
|
19
19
|
private
|
20
20
|
|
21
21
|
def send_notification_to_assignee(item)
|
22
|
-
UserMailer.assigned_entity_notification(item, current_user).
|
22
|
+
UserMailer.assigned_entity_notification(item, current_user).deliver_later if item.assignee.present? && current_user.present? && can_send_email?
|
23
23
|
end
|
24
24
|
|
25
25
|
# Need to have a host set before email can be sent
|
@@ -54,7 +54,7 @@ class Comment < ActiveRecord::Base
|
|
54
54
|
def notify_subscribers
|
55
55
|
commentable.subscribed_users.reject { |user_id| user_id == user.id }.each do |subscriber_id|
|
56
56
|
if subscriber = User.find_by_id(subscriber_id)
|
57
|
-
SubscriptionMailer.comment_notification(subscriber, self).
|
57
|
+
SubscriptionMailer.comment_notification(subscriber, self).deliver_later
|
58
58
|
end
|
59
59
|
end
|
60
60
|
end
|
data/app/models/setting.rb
CHANGED
@@ -58,13 +58,11 @@ class Setting < ActiveRecord::Base
|
|
58
58
|
return cache[name] if cache.key?(name)
|
59
59
|
|
60
60
|
# Check database
|
61
|
-
if database_and_table_exists?
|
62
|
-
|
63
|
-
return cache[name] = setting.value unless setting.value.nil?
|
64
|
-
end
|
61
|
+
if database_and_table_exists? && (setting = find_by_name(name.to_s))&.value.present?
|
62
|
+
return cache[name] = setting.value
|
65
63
|
end
|
66
64
|
# Check YAML settings
|
67
|
-
|
65
|
+
cache[name] = yaml_settings[name] if yaml_settings.key?(name)
|
68
66
|
end
|
69
67
|
|
70
68
|
# Set setting value
|
@@ -73,6 +71,7 @@ class Setting < ActiveRecord::Base
|
|
73
71
|
raise ArgumentError, "name cannot be blank" if name.blank?
|
74
72
|
|
75
73
|
return nil unless database_and_table_exists?
|
74
|
+
|
76
75
|
setting = find_by_name(name.to_s) || new(name: name.to_s)
|
77
76
|
setting.value = value
|
78
77
|
setting.save
|
data/app/models/users/user.rb
CHANGED
@@ -61,7 +61,7 @@ class User < ActiveRecord::Base
|
|
61
61
|
has_many :opportunities
|
62
62
|
has_many :assigned_opportunities, class_name: 'Opportunity', foreign_key: 'assigned_to'
|
63
63
|
has_many :permissions, dependent: :destroy
|
64
|
-
has_many :preferences, dependent: :destroy
|
64
|
+
has_many :preferences, class_name: 'Preference', dependent: :destroy
|
65
65
|
has_many :lists
|
66
66
|
has_and_belongs_to_many :groups
|
67
67
|
|
@@ -2,9 +2,9 @@
|
|
2
2
|
.section
|
3
3
|
%table
|
4
4
|
%tr
|
5
|
-
%td(colspan="5")
|
5
|
+
%td{class: (@account.errors['name'].present? ? 'fieldWithErrors' : nil)}(colspan="5")
|
6
6
|
.label.top.req #{t :name}:
|
7
|
-
= f.text_field :name, autofocus: true, style: "width:500px"
|
7
|
+
= f.text_field :name, autofocus: true, style: "width:500px", required: "required"
|
8
8
|
%tr
|
9
9
|
%td
|
10
10
|
.label #{t :assigned_to}:
|
@@ -12,7 +12,7 @@
|
|
12
12
|
%td= spacer
|
13
13
|
%td
|
14
14
|
.label #{t :category}:
|
15
|
-
= f.select :category, Setting.unroll(:account_category), { selected: (@account.category || "other").to_sym, include_blank: t(:other) }, { style: "width:160px", class: 'select2' }
|
15
|
+
= f.select :category, Setting.unroll(:account_category), { selected: (@account.category || "other").to_sym, include_blank: t(:other) }, { style: "width:160px", class: 'select2', placeholder: t(:other) }
|
16
16
|
%td= spacer
|
17
17
|
%td
|
18
18
|
.label #{t :rating}:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
- entity_name = controller.controller_name.singularize.underscore #account
|
2
2
|
- @entity = instance_variable_get("@#{entity_name}")
|
3
3
|
|
4
|
-
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show
|
4
|
+
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show", formats: [:html], entity_name => @entity) }');
|
5
5
|
= raw generate_js_for_popups(@entity, :tasks, :contacts, :opportunities)
|
@@ -7,6 +7,7 @@
|
|
7
7
|
crm.flip_form('edit_#{entity_name}');
|
8
8
|
crm.set_title('edit_#{entity_name}', '#{j @entity.name}');
|
9
9
|
= refresh_sidebar(:show)
|
10
|
+
$('#summary').html('#{ j (render partial: "#{entity_name.pluralize}/sidebar_show", entity_name => @entity) }');
|
10
11
|
- else
|
11
12
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
12
13
|
$('##{id}').effect("highlight", { duration:1500 });
|
@@ -1,6 +1,9 @@
|
|
1
1
|
%div
|
2
2
|
.label.top.req
|
3
3
|
= "Select Options (pipe separated):"
|
4
|
-
= f.text_field :collection_string, class: 'field_collection_string', size: 78
|
4
|
+
= f.text_field :collection_string, class: 'field_collection_string', size: 78, placeholder: "Option 1|Option 2|Option 3"
|
5
5
|
|
6
6
|
= render partial: 'admin/custom_fields/base_field', locals: {f: f}
|
7
|
+
|
8
|
+
- if f.object.new_record?
|
9
|
+
.info2 After saving, you must restart all instances of the Rails server to apply column serialization.
|
@@ -2,9 +2,9 @@
|
|
2
2
|
.section
|
3
3
|
%table
|
4
4
|
%tr
|
5
|
-
%td(colspan="5")
|
5
|
+
%td{class: (@campaign.errors['name'].present? ? 'fieldWithErrors' : nil)}(colspan="5")
|
6
6
|
.label.top.req #{t :name}:
|
7
|
-
= f.text_field :name, autofocus: true, style: "width:500px"
|
7
|
+
= f.text_field :name, autofocus: true, style: "width:500px", required: "required"
|
8
8
|
%tr
|
9
9
|
%td
|
10
10
|
.label #{t :start_date}:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
- entity_name = controller.controller_name.singularize.underscore #account
|
2
2
|
- @entity = instance_variable_get("@#{entity_name}")
|
3
3
|
|
4
|
-
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show
|
4
|
+
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show", formats: [:html], entity_name => @entity) }');
|
5
5
|
= raw generate_js_for_popups(@entity, :tasks, :leads, :opportunities)
|
@@ -7,6 +7,7 @@
|
|
7
7
|
crm.flip_form('edit_#{entity_name}');
|
8
8
|
crm.set_title('edit_#{entity_name}', '#{h @entity.name}');
|
9
9
|
= refresh_sidebar(:show)
|
10
|
+
$('#summary').html('#{ j (render partial: "#{entity_name.pluralize}/sidebar_show", entity_name => @entity) }');
|
10
11
|
- else
|
11
12
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
12
13
|
$('##{id}').effect("highlight", { duration:1500 });
|
@@ -3,13 +3,13 @@
|
|
3
3
|
.section
|
4
4
|
%table
|
5
5
|
%tr
|
6
|
-
%td
|
7
|
-
.label.top
|
8
|
-
= f.text_field :first_name, autofocus: true
|
6
|
+
%td{class: (@contact.errors['first_name'].present? ? 'fieldWithErrors' : nil)}
|
7
|
+
.label.top{ class: "#{Setting.require_first_names ? 'req' : nil}" } #{t :first_name}:
|
8
|
+
= f.text_field :first_name, autofocus: true, required: (Setting.require_first_names ? "required" : nil)
|
9
9
|
%td= spacer
|
10
|
-
%td
|
10
|
+
%td{class: (@contact.errors['last_name'].present? ? 'fieldWithErrors' : nil)}
|
11
11
|
.label.top{ class: "#{Setting.require_last_names ? 'req' : nil}" } #{t :last_name}:
|
12
|
-
= f.text_field :last_name
|
12
|
+
= f.text_field :last_name, required: (Setting.require_last_names ? "required" : nil)
|
13
13
|
%tr
|
14
14
|
%td
|
15
15
|
.label #{t :email}:
|
@@ -1,5 +1,4 @@
|
|
1
|
-
- entity_name = controller.controller_name.singularize.underscore
|
1
|
+
- entity_name = controller.controller_name.singularize.underscore
|
2
2
|
- @entity = instance_variable_get("@#{entity_name}")
|
3
|
-
|
4
|
-
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show.html", entity_name => @entity) }');
|
3
|
+
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show", formats: [:html], entity_name => @entity) }');
|
5
4
|
= raw generate_js_for_popups(@entity, :tasks, :opportunities)
|
@@ -8,6 +8,7 @@
|
|
8
8
|
crm.flip_form('edit_#{entity_name}');
|
9
9
|
crm.set_title('edit_#{entity_name}', '#{h @entity.full_name}');
|
10
10
|
= refresh_sidebar(:show)
|
11
|
+
$('#summary').html('#{ j (render partial: "#{entity_name.pluralize}/sidebar_show", entity_name => @entity) }');
|
11
12
|
- else
|
12
13
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
13
14
|
$('##{id}').effect("highlight", { duration:1500 });
|
@@ -23,10 +23,9 @@
|
|
23
23
|
.label= t(:password)
|
24
24
|
= f.input_field :password
|
25
25
|
|
26
|
-
|
26
|
+
.section
|
27
27
|
= f.input :remember_me, as: :boolean, inline_label: t('remember_me')
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
= t(:or)
|
28
|
+
= f.submit t(:login), class: 'btn btn-primary'
|
29
|
+
|
30
|
+
.section
|
32
31
|
= link_to t(:forgot_password) + '?', new_password_path(resource_name)
|
@@ -1,6 +1,9 @@
|
|
1
1
|
- if field_group.name != 'custom_fields'
|
2
|
-
|
3
|
-
-
|
2
|
+
- # Ensure field groups containing validation errors are expanded
|
3
|
+
- required_field_names = field_group.fields.select(&:required?).map(&:name)
|
4
|
+
- fields_with_errors = f.object.errors.map{|e| e.attribute.to_s}
|
5
|
+
- force_open = (required_field_names & fields_with_errors).any?
|
6
|
+
- collapsed = session[field_group.key].nil? && !force_open
|
4
7
|
%div{ id: "#{field_group.key}_container", :"data-tag" => field_group.tag.try(:name) }
|
5
8
|
= subtitle field_group.key, collapsed, t(field_group.name, default: field_group.label)
|
6
9
|
.section
|
@@ -2,12 +2,11 @@
|
|
2
2
|
- field_group.fields.without_pairs.in_groups_of(2, false) do |group|
|
3
3
|
%tr
|
4
4
|
- group.each_with_index do |field, i|
|
5
|
-
%td
|
5
|
+
%td{class: (f.object.errors[field.name].present? ? 'fieldWithErrors' : nil)}
|
6
6
|
- if field.hint.present?
|
7
7
|
= image_tag "info_tiny.png", title: field.hint, class: "tooltip-icon"
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
= f.input field.name, field.input_options.merge(checked: checked)
|
8
|
+
.label.top{class: (field.required? ? 'req': nil)}
|
9
|
+
= "#{field.label}:"
|
10
|
+
= f.input_field field.name, field.input_options
|
12
11
|
- if i == 0
|
13
12
|
%td= spacer
|
@@ -4,7 +4,10 @@
|
|
4
4
|
%tr
|
5
5
|
- group.each do |field|
|
6
6
|
= col(field.label, (i == groups.size - 1) ? :last : nil) do
|
7
|
-
|
7
|
+
- if field.as == "text"
|
8
|
+
= simple_format(field.render_value(entity))
|
9
|
+
- else
|
10
|
+
= field.render_value(entity)
|
8
11
|
- if group.size == 1
|
9
12
|
%th.last
|
10
13
|
%td.last
|
@@ -1,9 +1,6 @@
|
|
1
1
|
- asset.field_groups.each do |field_group|
|
2
|
-
-
|
3
|
-
- if
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
- fg.each do |field|
|
8
|
-
- if (value = field.render_value(asset)).present?
|
9
|
-
== #{field.label}:<br /> <b>#{truncate(value, length: 35)}</b><br />
|
2
|
+
- fields = field_group.fields.without_pairs
|
3
|
+
- if fields.select{|f| asset.send(f.name).present? }.any?
|
4
|
+
- unless field_group.name == 'custom_fields'
|
5
|
+
.caption #{field_group.label_i18n}
|
6
|
+
= render("fields/group_view", fields: fields, entity: asset) unless fields.nil?
|
@@ -1,3 +1,5 @@
|
|
1
1
|
<%= simple_fields_for(@asset) do |f| %>
|
2
|
-
|
2
|
+
<% @field_groups.each do |field_group| %>
|
3
|
+
$('#field_groups').append('<%= j render(partial: 'fields/group', locals: {f: f, field_group: field_group, fields: field_group.fields}) %>')
|
4
|
+
<% end %>
|
3
5
|
<% end %>
|
@@ -42,7 +42,7 @@
|
|
42
42
|
= render "layouts/footer"
|
43
43
|
|
44
44
|
%script{type: "text/javascript"}
|
45
|
-
= "crm.base_url = '#{Setting.base_url}';" unless Setting.base_url.blank?
|
45
|
+
= "crm.base_url = '#{h Setting.base_url}';".html_safe unless Setting.base_url.blank?
|
46
46
|
= get_browser_timezone_offset
|
47
47
|
= content_for :javascript_epilogue
|
48
48
|
= hook(:javascript_epilogue, self)
|
@@ -3,13 +3,13 @@
|
|
3
3
|
.section
|
4
4
|
%table
|
5
5
|
%tr
|
6
|
-
%td
|
6
|
+
%td{ class: (@lead.errors['first_name'].present? ? 'fieldWithErrors' : nil)}
|
7
7
|
.label.top{ class: "#{Setting.require_first_names ? 'req' : nil}" } #{t :first_name}:
|
8
|
-
= f.text_field :first_name, autofocus: true
|
8
|
+
= f.text_field :first_name, autofocus: true, required: (Setting.require_first_names ? "required" : nil)
|
9
9
|
%td= spacer
|
10
|
-
%td
|
10
|
+
%td{ class: (@lead.errors['last_name'].present? ? 'fieldWithErrors' : nil)}
|
11
11
|
.label.top{ class: "#{Setting.require_last_names ? 'req' : nil}" } #{t :last_name}:
|
12
|
-
= f.text_field :last_name
|
12
|
+
= f.text_field :last_name, required: (Setting.require_last_names ? "required" : nil)
|
13
13
|
%tr
|
14
14
|
%td
|
15
15
|
.label #{t :email}:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
- entity_name = controller.controller_name.singularize.underscore #account
|
2
2
|
- @entity = instance_variable_get("@#{entity_name}")
|
3
3
|
|
4
|
-
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show
|
4
|
+
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show", formats: [:html], entity_name => @entity) }');
|
5
5
|
= raw generate_js_for_popups(@entity, :tasks)
|
@@ -7,6 +7,7 @@
|
|
7
7
|
crm.flip_form('edit_#{entity_name}');
|
8
8
|
crm.set_title('edit_#{entity_name}', '#{h @entity.full_name}');
|
9
9
|
= refresh_sidebar(:show)
|
10
|
+
$('#summary').html('#{ j (render partial: "#{entity_name.pluralize}/sidebar_show", entity_name => @entity) }');
|
10
11
|
- else
|
11
12
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
12
13
|
$('##{id}').effect("highlight", { duration:1500 });
|
@@ -2,9 +2,9 @@
|
|
2
2
|
.section
|
3
3
|
%table
|
4
4
|
%tr
|
5
|
-
%td
|
5
|
+
%td{class: (@opportunity.errors['name'].present? ? 'fieldWithErrors' : nil)}
|
6
6
|
.label.req.top #{t :name}:
|
7
|
-
= f.text_field :name, autofocus: true, style: "width:325px"
|
7
|
+
= f.text_field :name, autofocus: true, style: "width:325px", required: "required"
|
8
8
|
%td= spacer
|
9
9
|
%td
|
10
10
|
.label.req.top #{t :stage}:
|
@@ -1,5 +1,5 @@
|
|
1
1
|
- entity_name = controller.controller_name.singularize.underscore #account
|
2
2
|
- @entity = instance_variable_get("@#{entity_name}")
|
3
3
|
|
4
|
-
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show
|
4
|
+
$('#main').html('#{ j (render template: "#{entity_name.pluralize}/show", formats: [:html], entity_name => @entity) }');
|
5
5
|
= raw generate_js_for_popups(@entity, :tasks, :contacts)
|
@@ -7,6 +7,7 @@
|
|
7
7
|
crm.flip_form('edit_#{entity_name}');
|
8
8
|
crm.set_title('edit_#{entity_name}', '#{h @entity.name}');
|
9
9
|
= refresh_sidebar(:show)
|
10
|
+
$('#summary').html('#{ j (render partial: "#{entity_name.pluralize}/sidebar_show", entity_name => @entity) }');
|
10
11
|
- else
|
11
12
|
$('##{id}').replaceWith('#{ j render(partial: entity_name, collection: [ @entity ]) }');
|
12
13
|
$('##{id}').effect("highlight", { duration:1500 });
|
@@ -41,4 +41,4 @@
|
|
41
41
|
= address_field(a, :zipcode, "width:80px;")
|
42
42
|
%td= spacer
|
43
43
|
%td
|
44
|
-
= a.country_select(:country, priority_countries: priority_countries, include_blank:
|
44
|
+
= a.country_select(:country, {priority_countries: priority_countries, include_blank: true}, {data: { placeholder: t(:select_a_country)}, class: 'select2'})
|
@@ -3,10 +3,10 @@
|
|
3
3
|
%tr
|
4
4
|
%td(colspan="5")
|
5
5
|
.label.top.req #{t :name}:
|
6
|
-
= f.text_field :name, autofocus: true, style: "width:500px"
|
6
|
+
= f.text_field :name, autofocus: true, style: "width:500px", required: "required"
|
7
7
|
%tr
|
8
8
|
%td
|
9
|
-
.label
|
9
|
+
.label #{t :due}:
|
10
10
|
- bucket = (params[:bucket].blank? ? @task.bucket : params[:bucket]) || "due_asap"
|
11
11
|
- with_time = Setting.task_calendar_with_time
|
12
12
|
- if @task.bucket != "specific_time"
|
@@ -18,11 +18,11 @@
|
|
18
18
|
= f.text_field :calendar, value: f.object.due_at.strftime(fmt), style: "width:160px;", autocomplete: :off, class: (with_time ? 'datetime' : 'date')
|
19
19
|
%td= spacer
|
20
20
|
%td
|
21
|
-
.label
|
21
|
+
.label #{t :assign_to}:
|
22
22
|
= user_select(:task, all_users, current_user)
|
23
23
|
%td= spacer
|
24
24
|
%td
|
25
|
-
.label
|
25
|
+
.label #{t :category}:
|
26
26
|
= f.select :category, @category, { selected: @task.category.blank? ? nil : @task.category.to_sym, include_blank: t(:select_blank) }, { style: "width:160px", class: 'select2' }
|
27
27
|
|
28
28
|
- if Setting.background_info && Setting.background_info.include?(:task)
|
data/bin/bundle
CHANGED
@@ -1,5 +1,111 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($PROGRAM_NAME) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
|
28
|
+
bundler_version = nil
|
29
|
+
update_index = nil
|
30
|
+
ARGV.each_with_index do |a, i|
|
31
|
+
bundler_version = a if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
32
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
33
|
+
|
34
|
+
bundler_version = Regexp.last_match(1)
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../Gemfile", __dir__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, ".locked")
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
|
59
|
+
lockfile_contents = File.read(lockfile)
|
60
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
61
|
+
|
62
|
+
Regexp.last_match(1)
|
63
|
+
end
|
64
|
+
|
65
|
+
def bundler_requirement
|
66
|
+
@bundler_requirement ||=
|
67
|
+
env_var_version ||
|
68
|
+
cli_arg_version ||
|
69
|
+
bundler_requirement_for(lockfile_version)
|
70
|
+
end
|
71
|
+
|
72
|
+
def bundler_requirement_for(version)
|
73
|
+
return "#{Gem::Requirement.default}.a" unless version
|
74
|
+
|
75
|
+
bundler_gem_version = Gem::Version.new(version)
|
76
|
+
|
77
|
+
bundler_gem_version.approximate_recommendation
|
78
|
+
end
|
79
|
+
|
80
|
+
def load_bundler!
|
81
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
82
|
+
|
83
|
+
activate_bundler
|
84
|
+
end
|
85
|
+
|
86
|
+
def activate_bundler
|
87
|
+
gem_error = activation_error_handling do
|
88
|
+
gem "bundler", bundler_requirement
|
89
|
+
end
|
90
|
+
return if gem_error.nil?
|
91
|
+
|
92
|
+
require_error = activation_error_handling do
|
93
|
+
require "bundler/version"
|
94
|
+
end
|
95
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
96
|
+
|
97
|
+
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
98
|
+
exit 42
|
99
|
+
end
|
100
|
+
|
101
|
+
def activation_error_handling
|
102
|
+
yield
|
103
|
+
nil
|
104
|
+
rescue StandardError, LoadError => e
|
105
|
+
e
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
m.load_bundler!
|
110
|
+
|
111
|
+
load Gem.bin_path("bundler", "bundle") if m.invoked_as_script?
|
data/bin/rails
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
APP_PATH = File.expand_path(
|
5
|
-
require_relative
|
6
|
-
require
|
4
|
+
APP_PATH = File.expand_path("../config/application", __dir__)
|
5
|
+
require_relative "../config/boot"
|
6
|
+
require "rails/commands"
|
data/bin/rake
CHANGED
data/bin/setup
CHANGED
@@ -1,38 +1,35 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require
|
4
|
+
require "fileutils"
|
5
5
|
|
6
6
|
# path to your application root.
|
7
|
-
APP_ROOT = File.expand_path(
|
7
|
+
APP_ROOT = File.expand_path("..", __dir__)
|
8
8
|
|
9
9
|
def system!(*args)
|
10
10
|
system(*args) || abort("\n== Command #{args} failed ==")
|
11
11
|
end
|
12
12
|
|
13
13
|
FileUtils.chdir APP_ROOT do
|
14
|
-
# This script is a way to
|
15
|
-
# This script is idempotent, so that you can run it at
|
14
|
+
# This script is a way to set up or update your development environment automatically.
|
15
|
+
# This script is idempotent, so that you can run it at any time and get an expectable outcome.
|
16
16
|
# Add necessary setup steps to this file.
|
17
17
|
|
18
|
-
puts
|
19
|
-
system!
|
20
|
-
system(
|
21
|
-
|
22
|
-
# Install JavaScript dependencies
|
23
|
-
# system('bin/yarn')
|
18
|
+
puts "== Installing dependencies =="
|
19
|
+
system! "gem install bundler --conservative"
|
20
|
+
system("bundle check") || system!("bundle install")
|
24
21
|
|
25
22
|
# puts "\n== Copying sample files =="
|
26
|
-
# unless File.exist?(
|
27
|
-
# FileUtils.cp
|
23
|
+
# unless File.exist?("config/database.yml")
|
24
|
+
# FileUtils.cp "config/database.yml.sample", "config/database.yml"
|
28
25
|
# end
|
29
26
|
|
30
27
|
puts "\n== Preparing database =="
|
31
|
-
system!
|
28
|
+
system! "bin/rails db:prepare"
|
32
29
|
|
33
30
|
puts "\n== Removing old logs and tempfiles =="
|
34
|
-
system!
|
31
|
+
system! "bin/rails log:clear tmp:clear"
|
35
32
|
|
36
33
|
puts "\n== Restarting application server =="
|
37
|
-
system!
|
34
|
+
system! "bin/rails restart"
|
38
35
|
end
|
data/config/application.rb
CHANGED
@@ -30,11 +30,15 @@ require 'fat_free_crm/gem_ext/rails/engine'
|
|
30
30
|
module FatFreeCRM
|
31
31
|
class Application < Rails::Application
|
32
32
|
# Initialize configuration defaults for originally generated Rails version.
|
33
|
-
config.load_defaults
|
33
|
+
config.load_defaults 7.0
|
34
34
|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
35
|
+
# Configuration for the application, engines, and railties goes here.
|
36
|
+
#
|
37
|
+
# These settings can be overridden in specific environments using the files
|
38
|
+
# in config/environments, which are processed later.
|
39
|
+
#
|
40
|
+
# config.time_zone = "Central Time (US & Canada)"
|
41
|
+
# config.eager_load_paths << Rails.root.join("extras")
|
38
42
|
|
39
43
|
# Models are organized in sub-directories
|
40
44
|
config.autoload_paths += Dir[Rails.root.join("app/models/**")] +
|
@@ -78,6 +82,7 @@ module FatFreeCRM
|
|
78
82
|
config.active_record.use_yaml_unsafe_load = false
|
79
83
|
config.active_record.yaml_column_permitted_classes = [
|
80
84
|
::ActiveRecord::Type::Time::Value,
|
85
|
+
::ActiveSupport::HashWithIndifferentAccess, # for Field#settings serialization see app/models/fields/field.rb
|
81
86
|
::ActiveSupport::TimeWithZone,
|
82
87
|
::ActiveSupport::TimeZone,
|
83
88
|
::BigDecimal,
|
data/config/boot.rb
CHANGED
@@ -6,9 +6,7 @@
|
|
6
6
|
# See MIT-LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
7
7
|
#------------------------------------------------------------------------------
|
8
8
|
|
9
|
-
|
10
|
-
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
|
9
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
11
10
|
|
12
|
-
require
|
13
|
-
|
14
|
-
require 'bootsnap/setup'
|
11
|
+
require "bundler/setup" # Set up gems listed in the Gemfile.
|
12
|
+
require "bootsnap/setup" # Speed up boot time by caching expensive operations.
|