redmine_crm 0.0.36 → 0.0.37

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/README.md +160 -33
  4. data/Rakefile +3 -12
  5. data/bitbucket-pipelines.yml +20 -6
  6. data/doc/CHANGELOG +5 -0
  7. data/lib/redmine_crm.rb +5 -0
  8. data/lib/redmine_crm/acts_as_draftable/draft.rb +40 -0
  9. data/lib/redmine_crm/acts_as_draftable/rcrm_acts_as_draftable.rb +154 -0
  10. data/lib/redmine_crm/acts_as_taggable/rcrm_acts_as_taggable.rb +1 -1
  11. data/lib/redmine_crm/acts_as_viewed/rcrm_acts_as_viewed.rb +0 -1
  12. data/lib/redmine_crm/acts_as_votable/votable.rb +6 -10
  13. data/lib/redmine_crm/helpers/form_tag_helper.rb +31 -0
  14. data/lib/redmine_crm/money_helper.rb +0 -2
  15. data/lib/redmine_crm/version.rb +1 -1
  16. data/redmine_crm.gemspec +6 -1
  17. data/test/acts_as_draftable/draft_test.rb +29 -0
  18. data/test/acts_as_draftable/rcrm_acts_as_draftable_test.rb +185 -0
  19. data/test/acts_as_taggable/rcrm_acts_as_taggable_test.rb +9 -11
  20. data/test/acts_as_taggable/tag_list_test.rb +25 -29
  21. data/test/acts_as_taggable/tag_test.rb +58 -51
  22. data/test/acts_as_votable/rcrm_acts_as_votable_test.rb +6 -4
  23. data/test/acts_as_votable/rcrm_acts_as_voter_test.rb +7 -5
  24. data/test/acts_as_votable/votable_test.rb +1 -1
  25. data/test/database.yml +14 -18
  26. data/test/models/issue.rb +14 -0
  27. data/test/{fixtures → models}/news.rb +0 -0
  28. data/test/{fixtures → models}/project.rb +0 -0
  29. data/test/{fixtures → models}/user.rb +0 -0
  30. data/test/{fixtures → models}/vote_classes.rb +0 -20
  31. data/test/schema.rb +9 -1
  32. data/test/test_helper.rb +5 -57
  33. data/vendor/assets/javascripts/select2_helpers.js +39 -0
  34. metadata +75 -14
  35. data/test/fixtures/issue.rb +0 -22
  36. data/test/liquid/drops/liquid_test.rb +0 -52
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2ae8872b72b3265c1ae6e6993a8b3e0ca78f920
4
- data.tar.gz: c8364d112ed92618726af3ef54b16ffc23090abd
3
+ metadata.gz: 4b0ba370b2cc56fc7a7573ba6e7fa65f63a739a9
4
+ data.tar.gz: 2e257839a165ba3ac9a35f1735d25721dd7ab4a6
5
5
  SHA512:
6
- metadata.gz: 7a623433baaf7d77bf346e0a04e0a0052eeee082d063d13b073b20d487208bf1ac0183d03380b18e109d7ddfbc88405f5c8afde7d05c4b3a2c65241f50ff1b67
7
- data.tar.gz: 4004698fa8ee608d219a319142708253de3dc0770bba5d856715ffb9c49d7753c0c41320321bf8a9a6296b87a2767249727d215077487972088a58889b07389c
6
+ metadata.gz: 8166cb752f502d9b172c30bf781ea30313f2a2fc5b2d37b9eb2a7585f8bd5e169509e6ceeee2703def216331ce00ad391ffc2ddf1571773dd0ba6adea658a45c
7
+ data.tar.gz: b2763d0e87a531654ce8fb73937becf3ddb1fb53a5702452c8ce83bcdfc7172a95a16e429e26192d8e2fff00cb97dd3ac8fdd95ec68c5752418090e7064e67ed
data/.gitignore CHANGED
@@ -4,6 +4,8 @@
4
4
  /_yardoc/
5
5
  /coverage/
6
6
  /pkg/
7
+ /public/
8
+ /test/public/
7
9
  /spec/reports/
8
10
  /tmp/
9
11
  *.bundle
data/README.md CHANGED
@@ -1,71 +1,198 @@
1
1
  # RedmineCrm
2
2
 
3
- Gem include next functional for Redmine plugins:
4
- * rcrm_acts_as_taggable
5
- * rcrm_acts_as_votable
6
- * rcrm_acts_as_viewable
3
+ This gem is used at RedmineUP as a general place for shared functionality and
4
+ assets. It contains **Chart.js** and **select2** JS libraries, various mixins
5
+ for ActiveRecord models and other things you might find useful.
7
6
 
8
- ## Installation
7
+ Among mixins there are:
8
+
9
+ * rcrm_acts_as_draftable
10
+ * rcrm_acts_as_taggable
11
+ * rcrm_acts_as_viewable
12
+ * rcrm_acts_as_votable
9
13
 
10
- Add this line to your application's Gemfile:
11
14
 
15
+ ## Installation
16
+
17
+ Add it to your plugin's Gemfile:
12
18
  ```ruby
13
- gem "redmine_crm"
19
+ gem 'redmine_crm'
20
+ ```
21
+
22
+ Then invoke the following command in your plugin's or Redmine directory:
23
+ ```
24
+ $ bundle install
14
25
  ```
15
26
 
16
- And then execute:
27
+ And now you can start using it.
17
28
 
18
- $ bundle
19
29
 
20
- Or install it yourself as:
30
+ ## Usage
31
+ ### Drafts
32
+ This module allows saving and restoring drafts for different models. To be
33
+ saved as a draft, an instance does not need to pass the validations. Drafts
34
+ store not only model attributes, but also associations and virtual attributes.
35
+ A draft could be linked to a given user, so every user can manage his/her own
36
+ drafts independent of others. A draft might have a parent instance.
37
+
38
+ First of all, drafts need to be saved somewhere, so let's create a migration:
39
+ ```ruby
40
+ class CreateDrafts < Rails.version > '5' ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
41
+ def change
42
+ ActiveRecord::Base.create_drafts_table
43
+ end
44
+ end
45
+ ```
46
+
47
+ Then in the Redmine directory run:
48
+ ```
49
+ $ rake redmine:plugins:migrate
50
+ ```
21
51
 
22
- $ gem install redmine_crm
52
+ Next, add `rcrm_acts_as_draftable` to a model for which you want to save drafts:
53
+ ```ruby
54
+ class Message < ActiveRecord::Base
55
+ rcrm_acts_as_draftable
56
+ end
57
+ ```
23
58
 
24
- Create migration with next code:
59
+ And that's it for the preparation, now you're ready to make use of drafts:
25
60
  ```ruby
26
- require 'redmine_crm/rcrm_acts_as_taggable'
61
+ # You can save message as a draft.
62
+ Message.new(subject: 'foo').save_draft
63
+
64
+ # And later restore message from the draft.
65
+ draft = Message.drafts(nil).last
66
+ message = draft.restore
67
+ puts message.subject
68
+ # => foo
69
+
70
+ # Draft can be overwritten.
71
+ message.content = 'bar'
72
+ puts message.save_draft
73
+ # => true
74
+
75
+ # You can also save draft linked to a particular user.
76
+ Message.new(subject: 'baz').save_draft(current_user)
77
+
78
+ # And restore message from some user's draft.
79
+ user_draft = Message.drafts(current_user).last
80
+ user_message = user_draft.restore
81
+ puts user_message.subject
82
+ # => baz
83
+
84
+ # It's also possible to restore a bunch of messages at once.
85
+ messages = Message.drafts(current_user).restore_all
86
+ p messages.map(&:subject)
87
+ # => ["baz"]
88
+
89
+ # When a model instance is saved, corresponding draft is removed.
90
+ puts Message.drafts(current_user).count
91
+ # => 1
92
+ user_message.board_id = Board.first.id
93
+ user_message.save!
94
+ puts Message.drafts(current_user).count
95
+ # => 0
96
+
97
+ # Draft won't be saved for a persisted instance.
98
+ puts user_message.save_draft
99
+ # => false
100
+ ```
27
101
 
28
- def self.up
29
- ActiveRecord::Base.create_taggable_table
30
- end
102
+ ### Tags
103
+ This module makes it possible to tag objects.
31
104
 
32
- def self.down
33
- ActiveRecord::Base.drop_taggable_table
105
+ First, create a migration:
106
+ ```ruby
107
+ class CreateTags < Rails.version > '5' ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
108
+ def change
109
+ ActiveRecord::Base.create_taggable_table
34
110
  end
35
111
  end
36
112
  ```
37
- For rcrm_acts_as_viewed You may add column for your model
38
- with help:
39
113
 
114
+ Then in the Redmine directory run:
115
+ ```
116
+ $ rake redmine:plugins:migrate
117
+ ```
118
+
119
+ Next, add `rcrm_acts_as_taggable` to a model for which you want to provide tags:
40
120
  ```ruby
121
+ class Contact < ActiveRecord::Base
122
+ rcrm_acts_as_taggable
123
+ end
124
+ ```
41
125
 
42
- YourModel.add_viewings_columns
126
+ TODO: Add examples of usage.
43
127
 
44
- ```
45
- It will add two column to your table (views and total_views)
46
- and view_count will return two number: total view and unique views.
47
- Without this migration you will get only unique views.
128
+ ### Viewings
129
+ This module allows you to count views for some ActiveRecord model instances.
48
130
 
49
- Run migration for plugin:
131
+ To count views you'll need to create a migration:
132
+ ```ruby
133
+ class CreateViewings < Rails.version > '5' ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
134
+ def change
135
+ ActiveRecord::Base.create_viewings_table
136
+ end
137
+ end
138
+ ```
50
139
 
140
+ To apply it, run the following in the Redmine directory:
51
141
  ```
52
- rake redmine:plugins:migrate
142
+ $ rake redmine:plugins:migrate
53
143
  ```
54
144
 
55
- ## Usage
145
+ Then add `rcrm_acts_as_viewed` to a model for which you want to count views.
146
+ ```ruby
147
+ class Question < ActiveRecord::Base
148
+ rcrm_acts_as_viewed
149
+ end
150
+ ```
151
+
152
+ TODO: Provide some usage examples.
56
153
 
57
- Add to model
154
+ ### Votes
155
+ With this module you can make your models votable and allow users to vote.
58
156
 
157
+ As always, create a migration first:
59
158
  ```ruby
60
- rcrm_acts_as_taggable
159
+ class CreateVotes < Rails.version > '5' ? ActiveRecord::Migration[5.0] : ActiveRecord::Migration
160
+ def change
161
+ ActiveRecord::Base.create_votable_table
162
+ end
163
+ end
164
+ ```
165
+
166
+ Then apply it by running the following command in the Redmine directory:
167
+ ```
168
+ $ rake redmine:plugins:migrate
169
+ ```
170
+
171
+ To make a model votable, add `rcrm_acts_as_votable` to it:
172
+ ```ruby
173
+ class Question < ActiveRecord::Base
61
174
  rcrm_acts_as_votable
175
+ end
62
176
  ```
63
177
 
178
+ TODO: Write about `rcrm_acts_as_voter` and add usage examples.
64
179
 
65
- ## Run test
66
180
 
181
+ ## Development
182
+
183
+ If you're planning to extend this gem, you will need to install development
184
+ dependencies. To do this, execute the following command in the project's
185
+ directory:
186
+ ```
187
+ $ bundle install
188
+ ```
189
+
190
+ After that you'll be able to run tests:
67
191
  ```
68
- rake test
192
+ $ bundle exec rake test
69
193
  ```
70
194
 
71
- For test for mysql set enviroment variable DB to value 'mysql' and run test.
195
+ SQLite in-memory database will be used by default, which is the fastest way to run tests. To run them using different database adapters, set `DB` environment variable to one of the available values — `mysql`, `postgresql`, `sqlite`. For example, to use PostgreSQL, invoke tests like so:
196
+ ```
197
+ $ bundle exec rake test DB=postgresql
198
+ ```
data/Rakefile CHANGED
@@ -1,20 +1,11 @@
1
- require "bundler/gem_tasks"
2
-
3
- require 'rake'
1
+ require 'bundler/gem_tasks'
4
2
  require 'rake/testtask'
5
- # require 'rake/rdoctask'
6
3
 
7
- desc 'Default: run unit tests.'
8
- task :default => :test
4
+ task default: :test
9
5
 
10
- desc 'Test the acts_as_taggable_on_steroids plugin.'
6
+ desc 'Run tests'
11
7
  Rake::TestTask.new(:test) do |t|
12
8
  t.libs << 'test'
13
9
  t.pattern = 'test/**/*_test.rb'
14
10
  t.verbose = true
15
11
  end
16
-
17
- desc 'Copy migration file to db/migration of plugin'
18
- file 'copy_migration' do
19
- cp "generators/redmine_crm_migration/templates/migration.rb", "db/migrate/redmine_crm.rb"
20
- end
@@ -8,10 +8,24 @@ image: ruby:2.3.0
8
8
  pipelines:
9
9
  default:
10
10
  - step:
11
- script: # Modify the commands below to build your repository.
12
- - bundler --version
11
+ script:
13
12
  - bundle install
14
- - gem install byebug
15
- - gem install rails -v 5.1.2
16
- - gem install sqlite3
17
- - rake test
13
+ - bundle exec rake test DB=sqlite
14
+ - bundle exec rake test DB=postgresql
15
+ - bundle exec rake test DB=mysql
16
+ services:
17
+ - mysql
18
+ - postgres
19
+
20
+ definitions:
21
+ services:
22
+ mysql:
23
+ image: mysql
24
+ environment:
25
+ MYSQL_DATABASE: redmine_crm_test
26
+ MYSQL_ROOT_PASSWORD: password
27
+ postgres:
28
+ image: postgres
29
+ environment:
30
+ POSTGRES_DB: redmine_crm_test
31
+ POSTGRES_PASSWORD: password
data/doc/CHANGELOG CHANGED
@@ -4,6 +4,11 @@ Redmine crm gem - general functions for plugins (tags, vote, viewing, currency)
4
4
  Copyright (C) 2011-2018 RedmineUP
5
5
  https://www.redmineup.com/
6
6
 
7
+ == 2018-03-28 v0.0.37
8
+
9
+ * Added rcrm_acts_as_draftable
10
+ * Added transform_to_select2 helper
11
+
7
12
  == 2018-03-22 v0.0.36
8
13
 
9
14
  * select2_tag improvements
data/lib/redmine_crm.rb CHANGED
@@ -1,3 +1,6 @@
1
+ require 'active_record'
2
+ require 'action_view'
3
+
1
4
  require 'redmine_crm/version'
2
5
 
3
6
  require 'redmine_crm/acts_as_list/list'
@@ -10,6 +13,8 @@ require 'redmine_crm/acts_as_votable/rcrm_acts_as_votable'
10
13
  require 'redmine_crm/acts_as_votable/rcrm_acts_as_voter'
11
14
  require 'redmine_crm/acts_as_votable/vote'
12
15
  require 'redmine_crm/acts_as_votable/voter'
16
+ require 'redmine_crm/acts_as_draftable/rcrm_acts_as_draftable'
17
+ require 'redmine_crm/acts_as_draftable/draft'
13
18
 
14
19
  require 'redmine_crm/currency'
15
20
  require 'redmine_crm/helpers/tags_helper'
@@ -0,0 +1,40 @@
1
+ # The MIT License (MIT)
2
+
3
+ # Copyright (c) 2016-2018 Georg Ledermann
4
+
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module RedmineCrm
24
+ module ActsAsDraftable
25
+ class Draft < ActiveRecord::Base
26
+ belongs_to :user
27
+ belongs_to :parent, polymorphic: true
28
+
29
+ validates_presence_of :data, :target_type
30
+
31
+ def restore
32
+ target_type.constantize.from_draft(self)
33
+ end
34
+
35
+ def self.restore_all
36
+ find_each.map(&:restore)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,154 @@
1
+ # The MIT License (MIT)
2
+
3
+ # Copyright (c) 2016-2018 Georg Ledermann
4
+
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ # THE SOFTWARE.
22
+
23
+ module RedmineCrm
24
+ module ActsAsDraftable #:nodoc: all
25
+ module Base
26
+ ALLOWED_DRAFT_OPTIONS = [:parent]
27
+
28
+ def draftable?
29
+ false
30
+ end
31
+
32
+ def rcrm_acts_as_draftable(options = {})
33
+ raise ArgumentError unless options.is_a?(Hash)
34
+ raise ArgumentError unless options.keys.all? { |k| ALLOWED_DRAFT_OPTIONS.include?(k) }
35
+
36
+ class_attribute :draft_parent
37
+
38
+ if options[:parent]
39
+ parent_class = self.reflect_on_all_associations(:belongs_to).find { |a| a.name == options[:parent] }.try(:klass)
40
+ raise ArgumentError unless parent_class
41
+
42
+ unless parent_class.method_defined?(:drafts)
43
+ parent_class.class_eval do
44
+ def drafts(user)
45
+ Draft.where(user: user, parent: self)
46
+ end
47
+
48
+ def self.child_drafts(user)
49
+ Draft.where(user: user, parent_type: self.base_class.name)
50
+ end
51
+ end
52
+ end
53
+
54
+ self.draft_parent = options[:parent]
55
+ end
56
+
57
+ attr_accessor :draft_id
58
+ after_create :clear_draft
59
+
60
+ extend RedmineCrm::ActsAsDraftable::ClassMethods
61
+ include RedmineCrm::ActsAsDraftable::InstanceMethods
62
+ end
63
+ end # Base
64
+
65
+ module ClassMethods
66
+ def draftable?
67
+ true
68
+ end
69
+
70
+ def from_draft(draft_or_id)
71
+ draft = draft_or_id.is_a?(Draft) ? draft_or_id : Draft.find(draft_or_id)
72
+ raise ArgumentError unless draft.target_type == name
73
+
74
+ target = draft.target_type.constantize.new
75
+ target.load_from_draft(draft.data)
76
+
77
+ target.send("#{draft_parent}=", draft.parent) if draft_parent
78
+ target.draft_id = draft.id
79
+ target
80
+ end
81
+
82
+ def drafts(user)
83
+ Draft.where(user: user, target_type: name)
84
+ end
85
+ end # ClassMethods
86
+
87
+ module InstanceMethods
88
+ def save_draft(user = nil)
89
+ return false unless self.new_record?
90
+
91
+ draft = Draft.find_by_id(self.draft_id) || Draft.new
92
+
93
+ draft.data = dump_to_draft
94
+ draft.target_type = self.class.name
95
+ draft.user = user
96
+ draft.parent = self.send(self.class.draft_parent) if self.class.draft_parent
97
+
98
+ result = draft.save
99
+ self.draft_id = draft.id if result
100
+ result
101
+ end
102
+
103
+ def update_draft(user, attributes)
104
+ with_transaction_returning_status do
105
+ assign_attributes(attributes)
106
+ save_draft(user)
107
+ end
108
+ end
109
+
110
+ def dump_to_draft
111
+ Marshal.dump(instance_values)
112
+ end
113
+
114
+ def load_from_draft(string)
115
+ values = Marshal.load(string)
116
+
117
+ values.each do |name, value|
118
+ instance_variable_set("@#{name}", value)
119
+ end
120
+ end
121
+
122
+ private
123
+
124
+ def clear_draft
125
+ if draft = Draft.find_by_id(self.draft_id)
126
+ self.draft_id = nil if draft.destroy
127
+ end
128
+ end
129
+ end # InstanceMethods
130
+
131
+ module Migration
132
+ def create_drafts_table
133
+ return if connection.table_exists?(:drafts)
134
+
135
+ connection.create_table :drafts do |t|
136
+ t.string :target_type, limit: 150, null: false
137
+ t.references :user
138
+ t.references :parent, polymorphic: true, index: true
139
+ t.binary :data, limit: 16777215, null: false
140
+ t.datetime :updated_at, null: false
141
+ end
142
+
143
+ connection.add_index :drafts, [:user_id, :target_type]
144
+ end
145
+
146
+ def drop_drafts_table
147
+ connection.drop_table :drafts if connection.table_exists?(:drafts)
148
+ end
149
+ end # Migration
150
+ end
151
+ end
152
+
153
+ ActiveRecord::Base.extend RedmineCrm::ActsAsDraftable::Base
154
+ ActiveRecord::Base.extend RedmineCrm::ActsAsDraftable::Migration