fat_free_crm 0.22.0 → 0.23.0
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/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_textarea_autocomplete.js.coffee +6 -9
- 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/fields_controller.rb +16 -13
- data/app/controllers/application_controller.rb +1 -1
- data/app/controllers/emails_controller.rb +1 -1
- data/app/controllers/entities/contacts_controller.rb +1 -1
- data/app/controllers/entities_controller.rb +1 -1
- data/app/controllers/lists_controller.rb +5 -4
- data/app/controllers/users_controller.rb +15 -3
- data/app/helpers/application_helper.rb +5 -5
- data/app/helpers/leads_helper.rb +1 -1
- data/app/helpers/opportunities_helper.rb +5 -3
- data/app/helpers/users_helper.rb +1 -1
- data/app/models/entities/campaign.rb +3 -3
- 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/lead_observer.rb +2 -1
- data/app/models/observers/task_observer.rb +2 -1
- data/app/models/polymorphic/address.rb +2 -1
- data/app/models/polymorphic/comment.rb +3 -4
- data/app/models/polymorphic/task.rb +1 -1
- data/app/models/users/user.rb +7 -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 +2 -4
- 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/config/application.rb +2 -0
- data/config/database.yml +9 -12
- data/config/environments/development.rb +15 -0
- data/config/initializers/action_mailer.rb +1 -1
- data/config/initializers/application_controller_renderer.rb +1 -0
- data/config/initializers/backtrace_silencers.rb +1 -0
- data/config/initializers/content_security_policy.rb +1 -0
- data/config/initializers/custom_field_ransack_translations.rb +2 -2
- data/config/initializers/devise.rb +1 -0
- data/config/initializers/inflections.rb +1 -0
- data/config/initializers/permissions_policy.rb +1 -0
- data/config/routes.rb +1 -3
- data/config/settings.default.yml +2 -1
- data/db/fat_free_crm_development.sqlite3 +0 -0
- data/db/fat_free_crm_test.sqlite3 +0 -0
- data/db/migrate/20230422234321_optionally_create_action_text_tables.action_text.rb +29 -0
- data/db/migrate/20230526211831_create_active_storage_tables.active_storage.rb +3 -3
- data/db/migrate/20230526212613_convert_to_active_storage.rb +11 -14
- data/db/schema.rb +16 -9
- data/db/seeds.rb +1 -0
- data/lib/fat_free_crm/callback.rb +0 -1
- data/lib/fat_free_crm/core_ext/string.rb +1 -1
- data/lib/fat_free_crm/custom_fields.rb +1 -0
- data/lib/fat_free_crm/mail_processor/base.rb +6 -10
- data/lib/fat_free_crm/version.rb +1 -1
- metadata +7 -31
- data/public/avatars/User/2/large_rails.png +0 -0
- data/public/avatars/User/2/medium_rails.png +0 -0
- data/public/avatars/User/2/original_rails.png +0 -0
- data/public/avatars/User/2/small_rails.png +0 -0
- data/public/avatars/User/2/thumb_rails.png +0 -0
- data/public/avatars/User/3/large_rails.png +0 -0
- data/public/avatars/User/3/medium_rails.png +0 -0
- data/public/avatars/User/3/original_rails.png +0 -0
- data/public/avatars/User/3/small_rails.png +0 -0
- data/public/avatars/User/3/thumb_rails.png +0 -0
- data/public/avatars/User/4/large_rails.png +0 -0
- data/public/avatars/User/4/medium_rails.png +0 -0
- data/public/avatars/User/4/original_rails.png +0 -0
- data/public/avatars/User/4/small_rails.png +0 -0
- data/public/avatars/User/4/thumb_rails.png +0 -0
- data/public/avatars/User/6/large_rails.png +0 -0
- data/public/avatars/User/6/medium_rails.png +0 -0
- data/public/avatars/User/6/original_rails.png +0 -0
- data/public/avatars/User/6/small_rails.png +0 -0
- data/public/avatars/User/6/thumb_rails.png +0 -0
- data/public/avatars/User/7/large_rails.png +0 -0
- data/public/avatars/User/7/medium_rails.png +0 -0
- data/public/avatars/User/7/original_rails.png +0 -0
- data/public/avatars/User/7/small_rails.png +0 -0
- data/public/avatars/User/7/thumb_rails.png +0 -0
@@ -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 %>
|
@@ -26,9 +26,7 @@
|
|
26
26
|
- if current_user.present?
|
27
27
|
:javascript
|
28
28
|
#{yield :javascript}
|
29
|
-
|
30
|
-
#{raw User.all.map{|u| "'#{j u.full_name} (@#{j u.username})'" }.join(",\n")}
|
31
|
-
];
|
29
|
+
|
32
30
|
|
33
31
|
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
|
34
32
|
<link rel="icon" href="/favicon.ico" type="image/x-icon">
|
@@ -42,7 +40,7 @@
|
|
42
40
|
= render "layouts/footer"
|
43
41
|
|
44
42
|
%script{type: "text/javascript"}
|
45
|
-
= "crm.base_url = '#{Setting.base_url}';" unless Setting.base_url.blank?
|
43
|
+
= "crm.base_url = '#{h Setting.base_url}';".html_safe unless Setting.base_url.blank?
|
46
44
|
= get_browser_timezone_offset
|
47
45
|
= content_for :javascript_epilogue
|
48
46
|
= 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/config/application.rb
CHANGED
@@ -85,6 +85,8 @@ module FatFreeCRM
|
|
85
85
|
::ActiveSupport::HashWithIndifferentAccess, # for Field#settings serialization see app/models/fields/field.rb
|
86
86
|
::ActiveSupport::TimeWithZone,
|
87
87
|
::ActiveSupport::TimeZone,
|
88
|
+
::ActsAsTaggableOn::TagList,
|
89
|
+
::ActsAsTaggableOn::DefaultParser,
|
88
90
|
::BigDecimal,
|
89
91
|
::Date,
|
90
92
|
::Symbol,
|
data/config/database.yml
CHANGED
@@ -1,26 +1,23 @@
|
|
1
|
+
# SQLite version 3.x
|
2
|
+
# gem install sqlite3-ruby (not necessary on OS X Leopard)
|
1
3
|
---
|
2
4
|
development: &development
|
3
|
-
adapter:
|
4
|
-
database: fat_free_crm_development
|
5
|
-
|
6
|
-
|
7
|
-
host: localhost
|
8
|
-
port: 5432
|
9
|
-
schema_search_path: public
|
10
|
-
min_messages: warning
|
5
|
+
adapter: sqlite3
|
6
|
+
database: db/fat_free_crm_development.sqlite3
|
7
|
+
pool: 5
|
8
|
+
timeout: 5000
|
11
9
|
|
12
10
|
# Warning: The database defined as "test" will be erased and
|
13
11
|
# re-generated from your development database when you run "rake".
|
14
12
|
# Do not set this db to the same as development or production.
|
15
13
|
test:
|
16
14
|
<<: *development
|
17
|
-
database: fat_free_crm_test
|
15
|
+
database: db/fat_free_crm_test.sqlite3
|
18
16
|
|
19
17
|
production:
|
20
18
|
<<: *development
|
21
|
-
database: fat_free_crm_production
|
19
|
+
database: db/fat_free_crm_production.sqlite3
|
22
20
|
|
23
21
|
staging:
|
24
22
|
<<: *development
|
25
|
-
database: fat_free_crm_staging
|
26
|
-
|
23
|
+
database: db/fat_free_crm_staging.sqlite3
|
@@ -83,5 +83,20 @@ if defined?(FatFreeCRM::Application)
|
|
83
83
|
# Checks for improperly declared sprockets dependencies.
|
84
84
|
# Raises helpful error messages.
|
85
85
|
config.assets.raise_runtime_errors = true
|
86
|
+
|
87
|
+
# Are we running in a GitHub Codespace?
|
88
|
+
if ENV.fetch('CODESPACE_NAME', nil)
|
89
|
+
config.host = "#{ENV.fetch('CODESPACE_NAME', nil)}-3000.app.github.dev:443"
|
90
|
+
config.hosts << ".preview.app.github.dev"
|
91
|
+
config.hosts << ".app.github.dev"
|
92
|
+
|
93
|
+
config.force_ssl = true
|
94
|
+
config.action_dispatch.cookies_same_site_protection = :lax
|
95
|
+
|
96
|
+
config.action_dispatch.trusted_proxies = [
|
97
|
+
# Trust all IPs (safe in dev only)
|
98
|
+
IPAddr.new("0.0.0.0/0"), IPAddr.new("::/0")
|
99
|
+
]
|
100
|
+
end
|
86
101
|
end
|
87
102
|
end
|
@@ -6,8 +6,8 @@
|
|
6
6
|
# See MIT-LICENSE file or http://www.opensource.org/licenses/mit-license.php
|
7
7
|
#------------------------------------------------------------------------------
|
8
8
|
# Load field names for custom fields, for Ransack search
|
9
|
-
require '
|
10
|
-
if Setting.database_and_table_exists?
|
9
|
+
require 'setting'
|
10
|
+
if Setting.database_and_table_exists? && ActiveRecord::Base.connection.table_exists?(:custom_fields)
|
11
11
|
Rails.application.config.after_initialize do
|
12
12
|
I18n.backend.load_translations
|
13
13
|
|
@@ -16,6 +16,7 @@ Devise.setup do |config|
|
|
16
16
|
# Devise will use the `secret_key_base` as its `secret_key`
|
17
17
|
# by default. You can change it below and use your own secret key.
|
18
18
|
# config.secret_key = SecureRandom.hex(64)
|
19
|
+
config.secret_key = Rails.application.secret_key_base
|
19
20
|
|
20
21
|
# ==> Mailer Configuration
|
21
22
|
# Configure the e-mail address which will be shown in Devise::Mailer,
|
data/config/routes.rb
CHANGED
@@ -23,6 +23,7 @@ Rails.application.routes.draw do
|
|
23
23
|
resources :users, only: %i[index show] do
|
24
24
|
collection do
|
25
25
|
get :opportunities_overview
|
26
|
+
match :auto_complete, via: %i[get post]
|
26
27
|
end
|
27
28
|
end
|
28
29
|
end
|
@@ -159,9 +160,6 @@ Rails.application.routes.draw do
|
|
159
160
|
patch :change_password
|
160
161
|
post :redraw
|
161
162
|
end
|
162
|
-
collection do
|
163
|
-
match :auto_complete, via: %i[get post]
|
164
|
-
end
|
165
163
|
end
|
166
164
|
|
167
165
|
namespace :admin do
|
data/config/settings.default.yml
CHANGED
@@ -192,7 +192,8 @@
|
|
192
192
|
#------------------------------------------------------------------------------
|
193
193
|
# Specify which countries (if any) should appear at the top of country pickers
|
194
194
|
# priority_countries:
|
195
|
-
# -
|
195
|
+
# - AU
|
196
|
+
# - BF
|
196
197
|
|
197
198
|
# Main and Admin Tabs
|
198
199
|
#------------------------------------------------------------------------------
|
Binary file
|
File without changes
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This migration comes from action_text (originally 20180528164100)
|
4
|
+
class OptionallyCreateActionTextTables < ActiveRecord::Migration[6.0]
|
5
|
+
def change
|
6
|
+
# Use Active Record's configured type for primary and foreign keys
|
7
|
+
primary_key_type, foreign_key_type = primary_and_foreign_key_types
|
8
|
+
|
9
|
+
create_table :action_text_rich_texts, id: primary_key_type, if_not_exists: true do |t|
|
10
|
+
t.string :name, null: false
|
11
|
+
t.text :body, size: :long
|
12
|
+
t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
|
13
|
+
|
14
|
+
t.timestamps
|
15
|
+
|
16
|
+
t.index %i[record_type record_id name], name: "index_action_text_rich_texts_uniqueness", unique: true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def primary_and_foreign_key_types
|
23
|
+
config = Rails.configuration.generators
|
24
|
+
setting = config.options[config.orm][:primary_key_type]
|
25
|
+
primary_key_type = setting || :primary_key
|
26
|
+
foreign_key_type = setting || :bigint
|
27
|
+
[primary_key_type, foreign_key_type]
|
28
|
+
end
|
29
|
+
end
|
@@ -6,7 +6,7 @@ class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
|
|
6
6
|
# Use Active Record's configured type for primary and foreign keys
|
7
7
|
primary_key_type, foreign_key_type = primary_and_foreign_key_types
|
8
8
|
|
9
|
-
create_table :active_storage_blobs, id: primary_key_type do |t|
|
9
|
+
create_table :active_storage_blobs, id: primary_key_type, if_not_exists: true do |t|
|
10
10
|
t.string :key, null: false
|
11
11
|
t.string :filename, null: false
|
12
12
|
t.string :content_type
|
@@ -19,7 +19,7 @@ class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
|
|
19
19
|
t.index [:key], unique: true
|
20
20
|
end
|
21
21
|
|
22
|
-
create_table :active_storage_attachments, id: primary_key_type do |t|
|
22
|
+
create_table :active_storage_attachments, id: primary_key_type, if_not_exists: true do |t|
|
23
23
|
t.string :name, null: false
|
24
24
|
t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type
|
25
25
|
t.references :blob, null: false, type: foreign_key_type
|
@@ -30,7 +30,7 @@ class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
|
|
30
30
|
t.foreign_key :active_storage_blobs, column: :blob_id
|
31
31
|
end
|
32
32
|
|
33
|
-
create_table :active_storage_variant_records, id: primary_key_type do |t|
|
33
|
+
create_table :active_storage_variant_records, id: primary_key_type, if_not_exists: true do |t|
|
34
34
|
t.belongs_to :blob, null: false, index: false, type: foreign_key_type
|
35
35
|
t.string :variation_digest, null: false
|
36
36
|
|
@@ -4,19 +4,16 @@ class ConvertToActiveStorage < ActiveRecord::Migration[5.2]
|
|
4
4
|
require 'open-uri'
|
5
5
|
|
6
6
|
def up
|
7
|
-
get_blob_id = case ENV['CI'] && ENV['DB']
|
8
|
-
when 'sqlite'
|
9
|
-
'LAST_INSERT_ROWID()'
|
10
|
-
when 'mysql'
|
11
|
-
'LAST_INSERT_ID()'
|
12
|
-
when 'postgres'
|
13
|
-
'LASTVAL()'
|
14
|
-
else
|
15
|
-
'LASTVAL()'
|
16
|
-
end
|
17
|
-
|
18
7
|
ActiveRecord::Base.connection.raw_connection.then do |conn|
|
19
|
-
|
8
|
+
get_blob_id = case ENV['CI'] && ENV['DB']
|
9
|
+
when 'mysql'
|
10
|
+
'LAST_INSERT_ID()'
|
11
|
+
else
|
12
|
+
'LASTVAL()'
|
13
|
+
end
|
14
|
+
get_blob_id = 'LAST_INSERT_ROWID()' if conn.is_a?(SQLite3::Database)
|
15
|
+
if conn.is_a?(::PG::Connection)
|
16
|
+
get_blob_id = 'LASTVAL()'
|
20
17
|
conn.prepare('active_storage_blobs', <<-SQL)
|
21
18
|
INSERT INTO active_storage_blobs (
|
22
19
|
key, filename, content_type, metadata, byte_size, checksum, created_at
|
@@ -29,13 +26,13 @@ class ConvertToActiveStorage < ActiveRecord::Migration[5.2]
|
|
29
26
|
) VALUES ($1, $2, $3, #{get_blob_id}, $4)
|
30
27
|
SQL
|
31
28
|
else
|
32
|
-
conn.
|
29
|
+
conn.prepare(<<-SQL)
|
33
30
|
INSERT INTO active_storage_blobs (
|
34
31
|
`key`, filename, content_type, metadata, byte_size, checksum, created_at
|
35
32
|
) VALUES (?, ?, ?, '{}', ?, ?, ?)
|
36
33
|
SQL
|
37
34
|
|
38
|
-
conn.
|
35
|
+
conn.prepare(<<-SQL)
|
39
36
|
INSERT INTO active_storage_attachments (
|
40
37
|
name, record_type, record_id, blob_id, created_at
|
41
38
|
) VALUES (?, ?, ?, #{get_blob_id}, ?)
|