redmine_crm 0.0.37 → 0.0.38

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4b0ba370b2cc56fc7a7573ba6e7fa65f63a739a9
4
- data.tar.gz: 2e257839a165ba3ac9a35f1735d25721dd7ab4a6
3
+ metadata.gz: 5ade85cd3ada9dbdf2283e26488fc7a8ae0eeb93
4
+ data.tar.gz: 1c872961e53a3f1186ee4283cb08a15b264b3fe2
5
5
  SHA512:
6
- metadata.gz: 8166cb752f502d9b172c30bf781ea30313f2a2fc5b2d37b9eb2a7585f8bd5e169509e6ceeee2703def216331ce00ad391ffc2ddf1571773dd0ba6adea658a45c
7
- data.tar.gz: b2763d0e87a531654ce8fb73937becf3ddb1fb53a5702452c8ce83bcdfc7172a95a16e429e26192d8e2fff00cb97dd3ac8fdd95ec68c5752418090e7064e67ed
6
+ metadata.gz: 07c4211ffc5be1a3322a8eec1dc7ccfdaabe77b8edc8cade7a486b0a51852a728b78144c31c3f5c998c18ef11d954a24000f646f58f23bb98e57723dda3dca4d
7
+ data.tar.gz: 6527ee07dbcc1e52cd240e03c70dbf6ac00d32ef43b0af638940572896eb239e8cc7bb444927a74570845ca3501d474615a584fb126860fa52401499c9ef24bd
@@ -20,7 +20,7 @@ pipelines:
20
20
  definitions:
21
21
  services:
22
22
  mysql:
23
- image: mysql
23
+ image: mysql:5.7
24
24
  environment:
25
25
  MYSQL_DATABASE: redmine_crm_test
26
26
  MYSQL_ROOT_PASSWORD: password
data/lib/redmine_crm.rb CHANGED
@@ -32,6 +32,10 @@ require 'redmine_crm/helpers/external_assets_helper'
32
32
  require 'redmine_crm/helpers/form_tag_helper'
33
33
  require 'redmine_crm/assets_manager'
34
34
 
35
+ module RedmineCrm
36
+ GEM_NAME = 'redmine_crm'.freeze
37
+ end
38
+
35
39
  if defined?(ActiveRecord::Base)
36
40
  ActiveRecord::Base.send :include, RedmineCrm::ActsAsList::List
37
41
  ActiveRecord::Base.extend(RedmineCrm::ActsAsVotable::Voter)
@@ -87,8 +87,8 @@ module RedmineCrm
87
87
  unless Object.const_defined?(viewing_class)
88
88
  Object.class_eval <<-EOV
89
89
  class #{viewing_class} < ActiveRecord::Base
90
- belongs_to :viewed, :polymorphic => true
91
- belongs_to :viewer, :class_name => #{viewer_class}, :foreign_key => :viewer_id
90
+ belongs_to :viewed, polymorphic: true
91
+ belongs_to :viewer, class_name: '#{viewer_class}', foreign_key: :viewer_id
92
92
  end
93
93
  EOV
94
94
  end
@@ -114,7 +114,7 @@ module RedmineCrm
114
114
  viewer_as_class = viewer_class.constantize
115
115
  return if viewer_as_class.instance_methods.include?('find_in_viewings')
116
116
  viewer_as_class.class_eval <<-EOS
117
- has_many :viewings, :foreign_key => :viewer_id, :class_name => #{viewing_class.to_s}
117
+ has_many :viewings, foreign_key: :viewer_id, class_name: '#{viewing_class.to_s}', dependent: :delete_all
118
118
  EOS
119
119
  end
120
120
  end
@@ -1,9 +1,9 @@
1
1
  module RedmineCrm
2
2
  class AssetsManager
3
3
  def self.install_assets
4
- return unless Gem.loaded_specs['redmine_crm']
5
- source = File.join(Gem.loaded_specs['redmine_crm'].full_gem_path, 'vendor', 'assets')
6
- destination = File.join(Dir.pwd, 'public', 'plugin_assets', 'redmine_crm')
4
+ return unless Gem.loaded_specs[GEM_NAME]
5
+ source = File.join(Gem.loaded_specs[GEM_NAME].full_gem_path, 'vendor', 'assets')
6
+ destination = File.join(Dir.pwd, 'public', 'plugin_assets', GEM_NAME)
7
7
  return unless File.directory?(source)
8
8
 
9
9
  source_files = Dir[source + '/**/*']
@@ -5,13 +5,15 @@ module RedmineCrm
5
5
  def select2_assets
6
6
  return if @select2_tag_included
7
7
  @select2_tag_included = true
8
- javascript_include_tag('select2', :plugin => 'redmine_crm') + stylesheet_link_tag('select2', :plugin => 'redmine_crm')
8
+ javascript_include_tag('select2', plugin: GEM_NAME) +
9
+ stylesheet_link_tag('select2', plugin: GEM_NAME) +
10
+ javascript_include_tag('select2_helpers', plugin: GEM_NAME)
9
11
  end
10
12
 
11
13
  def chartjs_assets
12
14
  return if @chartjs_tag_included
13
15
  @chartjs_tag_included = true
14
- javascript_include_tag('Chart.bundle.min', :plugin => 'redmine_crm')
16
+ javascript_include_tag('Chart.bundle.min', plugin: GEM_NAME)
15
17
  end
16
18
  end
17
19
  end
@@ -15,6 +15,10 @@ module RedmineCrm
15
15
  # * <tt>:data</tt> Load dropdown options from a local array if +url+ option not set.
16
16
  # * <tt>:placeholder</tt> Supports displaying a placeholder value.
17
17
  # * <tt>:include_hidden</tt> Adds hidden field after select when +multiple+ option true. Default value true.
18
+ # * <tt>:allow_clear</tt> Provides support for clearable selections. Default value false.
19
+ # * <tt>:min_input_length</tt> Minimum number of characters required to start a search. Default value 0.
20
+ # * <tt>:format_state</tt> Defines template of search results in the drop-down.
21
+ # * <tt>:tags</tt> Used to enable tagging feature.
18
22
  #
19
23
  # <b>Note:</b> The HTML specification says when +multiple+ parameter passed to select and all options got deselected
20
24
  # web browsers do not send any value to server.
@@ -22,102 +26,51 @@ module RedmineCrm
22
26
  # In case if you don't want the helper to generate this hidden field you can specify
23
27
  # <tt>include_hidden: false</tt> option.
24
28
  #
29
+ # <b>Note:</b> Select2 assets must be available on a page.
30
+ # To include select2 assets to a page, you need to use the helper select2_assets.
31
+ # For example:
32
+ # <% content_for :header_tags do %>
33
+ # <%= select2_assets %>
34
+ # <% end %>
35
+ #
25
36
  # Also aliased as: select2
26
37
  #
27
38
  # select2 'city_id', options_for_select(...)
28
39
  #
29
40
  def select2_tag(name, option_tags = nil, options = {})
30
- id = sanitize_to_id(name)
31
- placeholder = options[:placeholder] || 'Select ...'
41
+ s = select_tag(name, option_tags, options)
32
42
 
33
- content_for(:header_tags) { select2_assets }
34
- result = select_tag(name, option_tags, options)
35
43
  if options[:multiple] && options.fetch(:include_hidden, true)
36
- result << hidden_field_tag("#{name}[]", '')
44
+ s << hidden_field_tag("#{name}[]", '')
37
45
  end
38
46
 
39
- result << javascript_tag(<<-JS)
40
- $(function () {
41
- $('select#' + '#{id}').select2({
42
- #{select2_data_source_options(options)},
43
- #{select2_tags_options(options)},
44
- placeholder: '#{placeholder}'
45
- });
46
- });
47
- JS
47
+ s + javascript_tag("select2Tag('#{sanitize_to_id(name)}', #{options.to_json});")
48
48
  end
49
49
 
50
50
  alias select2 select2_tag
51
51
 
52
- # Transforms select filter field into select2
52
+ # Transforms select filters of +type+ fields into select2
53
53
  #
54
54
  # ==== Examples
55
- # transform_to_select2 'issue_tags', url: auto_complete_tags_url
56
- # transform_to_select2 'manager_id', format_state: 'formatStateWithAvatar', min_input_length: 1, url: '/managers'
55
+ # transform_to_select2 'tags', url: auto_complete_tags_url
56
+ # transform_to_select2 'people', format_state: 'formatStateWithAvatar', min_input_length: 1, url: '/managers'
57
57
  #
58
58
  # ==== Options
59
59
  # * <tt>:url</tt> Defines URL to search remote data using the ajax.
60
60
  # * <tt>:format_state</tt> Defines template of search results in the drop-down.
61
61
  # * <tt>:min_input_length</tt> Minimum number of characters required to start a search. Default value 0.
62
62
  # * <tt>:width</tt> Sets the width of the control. Default value '60%'.
63
+ # * <tt>:multiple</tt> Supports multi-value select box. If set to false the selection will not allow multiple choices. Default value true.
63
64
  #
64
- def transform_to_select2(field, options = {})
65
- return if field.empty?
66
-
67
- result = ''.html_safe
68
- unless @transform_to_select2_included
69
- result << javascript_include_tag('select2_helpers', plugin: 'redmine_crm')
70
- @transform_to_select2_included = true
71
- end
72
-
73
- result << javascript_tag(<<-JS)
74
- select2Filters['#{field}'] = {
75
- url: '#{options[:url].to_s}',
76
- formatState: #{options.fetch(:format_state, 'undefined')},
77
- minimumInputLength: #{options.fetch(:min_input_length, 0)},
78
- width: '#{options.fetch(:with, '60%')}'
79
- };
80
- JS
81
- end
82
-
83
- private
84
-
85
- def select2_data_source_options(options = {})
86
- if options[:url].to_s.empty?
87
- "data: #{options.fetch(:data, []).to_json}"
88
- else
89
- "ajax: {
90
- url: '#{options[:url]}',
91
- dataType: 'json',
92
- delay: 250,
93
- data: function (params) {
94
- return { q: params.term };
95
- },
96
- processResults: function (data, params) {
97
- return { results: data };
98
- },
99
- cache: true
100
- }"
101
- end
102
- end
103
-
104
- def select2_tags_options(options = {})
105
- if options.fetch(:tags, false)
106
- "tags: true,
107
- tokenSeparators: [','],
108
- createTag: function (params) {
109
- var term = $.trim(params.term);
110
- if (term === '' || term.indexOf(',') > -1) {
111
- return null; // Return null to disable tag creation
112
- }
113
- return {
114
- id: term,
115
- text: term
116
- }
117
- }"
118
- else
119
- 'tags: false'
120
- end
65
+ # <b>Note:</b> Select2 assets must be available on a page.
66
+ # To include select2 assets to a page, you need to use the helper select2_assets.
67
+ # For example:
68
+ # <% content_for :header_tags do %>
69
+ # <%= select2_assets %>
70
+ # <% end %>
71
+ #
72
+ def transform_to_select2(type, options = {})
73
+ javascript_tag("setSelect2Filter('#{type}', #{options.to_json});") unless type.empty?
121
74
  end
122
75
  end
123
76
  end
@@ -1,3 +1,3 @@
1
1
  module RedmineCrm
2
- VERSION = "0.0.37"
2
+ VERSION = '0.0.38'
3
3
  end
@@ -1,39 +1,168 @@
1
- var oldToggleFilter = window.toggleFilter;
1
+ var SELECT2_DELAY = 250;
2
2
 
3
- window.toggleFilter = function (field) {
4
- oldToggleFilter(field);
5
- return transform_to_select2(field);
3
+ var select2Filters = {};
4
+
5
+ function setSelect2Filter(type, options) {
6
+ if (typeof operatorByType === 'undefined') { return }
7
+
8
+ operatorByType[type] = operatorByType[type] || operatorByType['list_optional'];
9
+ select2Filters[type] = options;
6
10
  };
7
11
 
8
- function formatStateWithAvatar(opt) {
9
- return $('<span>' + opt.avatar + '&nbsp;' + opt.text + '</span>');
12
+
13
+ var originBuildFilterRow = buildFilterRow;
14
+ buildFilterRow = function (field, operator, values) {
15
+ originBuildFilterRow(field, operator, values);
16
+
17
+ var options = select2Options(field);
18
+ if (options) {
19
+ setSelect2FilterValues(field, options, values);
20
+ transformToSelect2(field, options);
21
+ }
10
22
  };
11
23
 
12
- var select2Filters = {};
13
24
 
14
- function transform_to_select2(field) {
15
- field = field.replace('.', '_');
16
- var filter = select2Filters[field];
17
- if (filter !== undefined && $('#tr_' + field + ' .values .select2').size() == 0) {
18
- $('#tr_' + field + ' .toggle-multiselect').hide();
19
- $('#tr_' + field + ' .values .value').attr('multiple', 'multiple');
20
- $('#tr_' + field + ' .values .value').select2({
21
- ajax: {
22
- url: filter['url'],
23
- dataType: 'json',
24
- delay: 250,
25
- data: function (params) {
26
- return {q: params.term};
27
- },
28
- processResults: function (data, params) {
29
- return {results: data};
30
- },
31
- cache: true
32
- },
33
- placeholder: ' ',
34
- minimumInputLength: filter['minimumInputLength'],
35
- width: filter['width'],
36
- templateResult: filter['formatState']
37
- });
25
+ function select2Options(field) {
26
+ var filter = availableFilters[field];
27
+ var options = select2Filters[filter['type']];
28
+
29
+ if (!options && filter['field_format']) {
30
+ options = select2Filters[field]
31
+ }
32
+
33
+ return options;
34
+ };
35
+
36
+
37
+ function setSelect2FilterValues(field, options, values) {
38
+ var needAddValues = !rowHasSelectTag(field);
39
+ if (needAddValues) { addSelectTag(field) }
40
+
41
+ var $select = findSelectTagInRowBy(field);
42
+ if (options['multiple'] !== false) { $select.attr('multiple', true) }
43
+
44
+ if (needAddValues) { addOptionTags($select, field, values); }
45
+ };
46
+
47
+
48
+ function addSelectTag(field) {
49
+ var fieldId = sanitizeToId(field);
50
+ $('#tr_' + fieldId).find('td.values').append(
51
+ '<span style="display:none;"><select class="value" id="values_'+fieldId+'_1" name="v['+field+'][]"></select></span>'
52
+ );
53
+ };
54
+
55
+
56
+ function addOptionTags($select, field, values) {
57
+ var filterValues = availableFilters[field]['values'];
58
+
59
+ for (var i = 0; i < filterValues.length; i++) {
60
+ var filterValue = filterValues[i];
61
+ var option = $('<option>');
62
+
63
+ if ($.isArray(filterValue)) {
64
+ option.val(filterValue[1]).text(filterValue[0]);
65
+ if ($.inArray(filterValue[1], values) > -1) { option.attr('selected', true); }
66
+ } else {
67
+ option.val(filterValue).text(filterValue);
68
+ if ($.inArray(filterValue, values) > -1) { option.attr('selected', true); }
38
69
  }
39
- };
70
+
71
+ $select.append(option);
72
+ }
73
+ };
74
+
75
+
76
+ function sanitizeToId(field) { return field.replace('.', '_') };
77
+
78
+ function findSelectTagInRowBy(field) {
79
+ return findInRowBy(field, '.values select.value');
80
+ };
81
+
82
+ function rowHasSelectTag(field) {
83
+ return findInRowBy(field, '.values select.value').size() > 0;
84
+ };
85
+
86
+ function rowHasSelect2(field) {
87
+ return findInRowBy(field, '.values .select2').size() > 0;
88
+ };
89
+
90
+ function findInRowBy(field, selector) {
91
+ return $('#tr_' + sanitizeToId(field) + ' ' + selector);
92
+ };
93
+
94
+ function formatStateWithAvatar(opt) {
95
+ return $('<span>' + opt.avatar + '&nbsp;' + opt.text + '</span>');
96
+ };
97
+
98
+
99
+ function transformToSelect2(field, options) {
100
+ if (rowHasSelect2(field)) { return }
101
+
102
+ findInRowBy(field, '.toggle-multiselect').hide();
103
+ findSelectTagInRowBy(field).select2(buildSelect2Options(options));
104
+ };
105
+
106
+
107
+ function select2Tag(id, options) {
108
+ $(function () {
109
+ $('select#' + id).select2(buildSelect2Options(options));
110
+ });
111
+ };
112
+
113
+
114
+ function buildSelect2Options(options) {
115
+ result = {
116
+ placeholder: options['placeholder'] || '',
117
+ allowClear: !!options['allow_clear'],
118
+ minimumInputLength: options['min_input_length'] || 0,
119
+ templateResult: window[options['format_state']],
120
+ width: options['width'] || '60%'
121
+ };
122
+
123
+ addDataSourceOptions(result, options);
124
+ addTagsOptions(result, options);
125
+
126
+ return result;
127
+ };
128
+
129
+
130
+ function addDataSourceOptions(target, options) {
131
+ if (options['url']) {
132
+ target['ajax'] = {
133
+ url: options['url'],
134
+ dataType: 'json',
135
+ delay: SELECT2_DELAY,
136
+ data: function (params) {
137
+ return { q: params.term };
138
+ },
139
+ processResults: function (data, params) {
140
+ return { results: data };
141
+ },
142
+ cache: true
143
+ };
144
+ } else {
145
+ target['data'] = options['data'] || [];
146
+ }
147
+ };
148
+
149
+
150
+ function addTagsOptions(target, options) {
151
+ if (options['tags']) {
152
+ target['tags'] = true;
153
+ target['tokenSeparators'] = [','];
154
+ target['createTag'] = createTag;
155
+ } else {
156
+ target['tags'] = false;
157
+ }
158
+ };
159
+
160
+
161
+ function createTag(params) {
162
+ var term = $.trim(params.term);
163
+ if (term === '' || term.indexOf(',') > -1) {
164
+ return null; // Return null to disable tag creation
165
+ }
166
+
167
+ return { id: term, text: term };
168
+ };
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redmine_crm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.37
4
+ version: 0.0.38
5
5
  platform: ruby
6
6
  authors:
7
7
  - RedmineUP
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-28 00:00:00.000000000 Z
11
+ date: 2018-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails