redmineup 1.1.3 → 1.1.11
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +7 -17
- data/README.md +74 -153
- data/app/assets/javascripts/consumer.js +37 -60
- data/app/assets/javascripts/consumer_worker.js +199 -0
- data/app/assets/javascripts/jquery.colorPicker.min.js +26 -0
- data/app/assets/javascripts/select2_helpers.js +10 -0
- data/app/assets/stylesheets/redmineup.css +509 -0
- data/app/views/redmineup/_additional_assets.html.erb +1 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/config/routes.rb +4 -0
- data/doc/CHANGELOG +72 -25
- data/doc/active-record-mixins.md +156 -0
- data/doc/assets-money-and-utilities.md +71 -0
- data/doc/tagging-and-select2.md +108 -0
- data/lib/action_cable/connection/rup_connection.rb +17 -0
- data/lib/action_cable/server/rup_server.rb +4 -0
- data/lib/redmineup/acts_as_taggable/tag.rb +13 -3
- data/lib/redmineup/acts_as_taggable/up_acts_as_taggable.rb +9 -6
- data/lib/redmineup/acts_as_viewed/up_acts_as_viewed.rb +1 -1
- data/lib/redmineup/engine.rb +12 -2
- data/lib/redmineup/helpers/datetime_helper.rb +23 -0
- data/lib/redmineup/helpers/external_assets_helper.rb +14 -6
- data/lib/redmineup/helpers/form_tag_helper.rb +43 -0
- data/lib/redmineup/helpers/tags_helper.rb +41 -0
- data/lib/redmineup/hooks/views_layouts_hook.rb +1 -5
- data/lib/redmineup/money_helper.rb +10 -2
- data/lib/redmineup/patches/action_cable_base_patch.rb +9 -2
- data/lib/redmineup/patches/action_cable_patch.rb +2 -4
- data/lib/redmineup/patches/auto_completes_controller_patch.rb +19 -0
- data/lib/redmineup/patches/compatibility/sprite_patch.rb +1 -1
- data/lib/redmineup/patches/compatibility/user_patch.rb +3 -3
- data/lib/redmineup/version.rb +1 -1
- data/lib/redmineup.rb +16 -35
- data/test/acts_as_taggable/tag_test.rb +12 -9
- data/test/schema.rb +1 -1
- data/test/tags_helper_view_test.rb +41 -0
- data/test/test_helper.rb +2 -1
- metadata +14 -2
data/doc/CHANGELOG
CHANGED
|
@@ -4,64 +4,111 @@ Redmine UP gem - general functions for plugins (tags, vote, viewing, currency)
|
|
|
4
4
|
Copyright (C) 2011-2026 Kirill Bezrukov (RedmineUP)
|
|
5
5
|
https://www.redmineup.com/
|
|
6
6
|
|
|
7
|
+
== 2026-06-26 v1.1.11
|
|
8
|
+
|
|
9
|
+
* Added shared workers for websocket connection
|
|
10
|
+
|
|
11
|
+
== 2026-06-04 v1.1.10
|
|
12
|
+
|
|
13
|
+
* Added colorpicker JS component to shared gem assets, loaded globally via `redmineup_assets`
|
|
14
|
+
* Fixed viewings table ip column limit to 45 characters for IPv6 address support
|
|
15
|
+
|
|
16
|
+
== 2026-05-30 v1.1.9
|
|
17
|
+
|
|
18
|
+
* Added `prices_formatted_collection` to `MoneyHelper` — returns plain text price strings from currency hash, used by query totals
|
|
19
|
+
|
|
20
|
+
== 2026-05-01 v1.1.8
|
|
21
|
+
|
|
22
|
+
* Added `on_select` callback and `select_icon` options for `select2tag` helper
|
|
23
|
+
* Updated `requires_redmineup` version guard to reduce boilerplate in plugin init
|
|
24
|
+
* Fixed `link_to` display compatibility issue in Redmine 5
|
|
25
|
+
|
|
26
|
+
== 2026-04-18 v1.1.7
|
|
27
|
+
|
|
28
|
+
* hot fix for atom/rss compatibility for redmine < 5
|
|
29
|
+
|
|
30
|
+
== 2026-04-17 v1.1.6
|
|
31
|
+
|
|
32
|
+
* Added helpers for timezone conversions
|
|
33
|
+
|
|
34
|
+
== 2026-04-17 v1.1.5
|
|
35
|
+
|
|
36
|
+
* Added tag cloud links helper with URL convention by key
|
|
37
|
+
* Added shared tag list fields for views and FormBuilder
|
|
38
|
+
* Added shared tag autocomplete route for taggable models
|
|
39
|
+
* Updated layout hook to load shared gem assets globally
|
|
40
|
+
* Updated tag helpers registration in ActionView context
|
|
41
|
+
* Fixed tag color fallback for backward compatibility
|
|
42
|
+
* Fixed helper behavior for Ruby 2.3 compatibility
|
|
43
|
+
|
|
44
|
+
== 2026-04-10 v1.1.4
|
|
45
|
+
|
|
46
|
+
* Fixed tag queries for MSSQL adapter
|
|
47
|
+
|
|
7
48
|
== 2026-03-10 v1.1.3
|
|
8
49
|
|
|
9
|
-
* Fixed ActionCable compatibility
|
|
10
50
|
* Added send method for ActionCable
|
|
51
|
+
* Fixed ActionCable compatibility with cable.yaml apply
|
|
11
52
|
|
|
12
53
|
== 2025-11-07 v1.1.2
|
|
13
54
|
|
|
14
|
-
* Fixed assets loading error
|
|
55
|
+
* Fixed shared assets loading error
|
|
15
56
|
|
|
16
|
-
== 2025-10-
|
|
57
|
+
== 2025-10-01 v1.1.1
|
|
17
58
|
|
|
18
|
-
*
|
|
59
|
+
* Updated sprite_icon patch activation logic
|
|
19
60
|
|
|
20
61
|
== 2025-07-24 v1.1.0
|
|
21
62
|
|
|
22
|
-
* Added ActionCable methods
|
|
23
|
-
*
|
|
24
|
-
* Fixed
|
|
63
|
+
* Added ActionCable methods for plugin integrations
|
|
64
|
+
* Added SVG icon support for context menu actions
|
|
65
|
+
* Fixed tag migration method for old Rails versions
|
|
25
66
|
|
|
26
67
|
== 2025-07-09 v1.0.13
|
|
27
68
|
|
|
28
|
-
* Added color
|
|
69
|
+
* Added tag color support in tag model behavior
|
|
70
|
+
|
|
71
|
+
== 2025-07-08 v1.0.12
|
|
29
72
|
|
|
30
|
-
|
|
73
|
+
* Added tag color selection functionality
|
|
31
74
|
|
|
32
|
-
|
|
75
|
+
== 2025-03-30 v1.0.11
|
|
76
|
+
|
|
77
|
+
* Fixed ApplicationRecord loading compatibility
|
|
78
|
+
|
|
79
|
+
== 2025-02-04 v1.0.10
|
|
80
|
+
|
|
81
|
+
* Fixed SVG icon compatibility for older Redmine code
|
|
33
82
|
|
|
34
83
|
== 2025-02-04 v1.0.9
|
|
35
84
|
|
|
36
85
|
* Added regex_replace Liquid filter
|
|
37
|
-
* Added
|
|
86
|
+
* Added SVG icons for Redmine 6
|
|
87
|
+
* Fixed Liquid internal error in filter execution
|
|
88
|
+
* Fixed parse_inline_attachments Liquid filter behavior
|
|
38
89
|
|
|
39
90
|
== 2025-01-31 v1.0.8
|
|
40
91
|
|
|
41
|
-
* Fixed compatibility patch for Redmine
|
|
92
|
+
* Fixed compatibility patch for Redmine versions below 5
|
|
42
93
|
|
|
43
94
|
== 2025-01-29 v1.0.7
|
|
44
95
|
|
|
45
|
-
*
|
|
46
|
-
*
|
|
96
|
+
* Added sprite_icon compatibility patch for Redmine 6
|
|
97
|
+
* Fixed parse_inline_attachments Liquid filter behavior
|
|
47
98
|
|
|
48
99
|
== 2024-05-07 v1.0.6
|
|
49
100
|
|
|
50
|
-
* Updated Chart.js to v3.9.1
|
|
51
|
-
* Fixed assets paths for Redmine 5.3+
|
|
52
101
|
* Added attachments to IssueDrop and JournalDrop
|
|
53
|
-
* Added filter
|
|
102
|
+
* Added parse_inline_attachments filter for image URL fix
|
|
103
|
+
* Updated Chart.js library to version 3.9.1
|
|
104
|
+
* Fixed asset paths for Redmine 5.3 and newer
|
|
54
105
|
|
|
55
106
|
== 2024-01-31 v1.0.5
|
|
56
107
|
|
|
57
|
-
* Added plugin_installed?
|
|
58
|
-
*
|
|
108
|
+
* Added plugin_installed? helper for plugin checks
|
|
109
|
+
* Fixed ApplicationRecord compatibility patch behavior
|
|
59
110
|
|
|
60
111
|
== 2023-10-12 v1.0.1
|
|
61
112
|
|
|
62
|
-
*
|
|
63
|
-
|
|
64
|
-
== 2023-09-27 v1.0.0
|
|
65
|
-
|
|
66
|
-
* Initial release
|
|
67
|
-
* Mirgated from redmineup gem
|
|
113
|
+
* Added initial public release
|
|
114
|
+
* Updated module name from RedmineUp to Redmineup
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
# ActiveRecord mixins
|
|
2
|
+
|
|
3
|
+
This page documents the model mixins provided by `redmineup`.
|
|
4
|
+
|
|
5
|
+
## `up_acts_as_taggable`
|
|
6
|
+
|
|
7
|
+
Adds polymorphic tagging support.
|
|
8
|
+
|
|
9
|
+
### Migration
|
|
10
|
+
|
|
11
|
+
```ruby
|
|
12
|
+
class CreateTags < ActiveRecord::Migration[6.1]
|
|
13
|
+
def change
|
|
14
|
+
ActiveRecord::Base.create_taggable_table
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Useful migration helpers:
|
|
20
|
+
|
|
21
|
+
- `ActiveRecord::Base.create_taggable_table`
|
|
22
|
+
- `ActiveRecord::Base.drop_taggable_table`
|
|
23
|
+
- `ActiveRecord::Base.add_tags_column(:tags, name: :color, type: :integer, default: nil)`
|
|
24
|
+
- `ActiveRecord::Base.remove_tags_columns(:tags, :color)`
|
|
25
|
+
|
|
26
|
+
### Model
|
|
27
|
+
|
|
28
|
+
```ruby
|
|
29
|
+
class Product < ApplicationRecord
|
|
30
|
+
up_acts_as_taggable
|
|
31
|
+
end
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Runtime API
|
|
35
|
+
|
|
36
|
+
- `record.tag_list` / `record.tag_list = 'a, b'`
|
|
37
|
+
- `record.save_tags` (called via callbacks)
|
|
38
|
+
- `Model.available_tags(project: @project, limit: 30)`
|
|
39
|
+
- `Model.tagged_with(['tag1', 'tag2'])`
|
|
40
|
+
- `Model.find_related_tags('tag1')`
|
|
41
|
+
|
|
42
|
+
## `up_acts_as_draftable`
|
|
43
|
+
|
|
44
|
+
Adds draft save/restore workflow for unsaved or changed records.
|
|
45
|
+
|
|
46
|
+
### Migration
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
class CreateDrafts < ActiveRecord::Migration[6.1]
|
|
50
|
+
def change
|
|
51
|
+
ActiveRecord::Base.create_drafts_table
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Helpers:
|
|
57
|
+
|
|
58
|
+
- `ActiveRecord::Base.create_drafts_table`
|
|
59
|
+
- `ActiveRecord::Base.drop_drafts_table`
|
|
60
|
+
|
|
61
|
+
### Model
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
class WikiPage < ApplicationRecord
|
|
65
|
+
up_acts_as_draftable parent: :wiki
|
|
66
|
+
end
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Runtime API
|
|
70
|
+
|
|
71
|
+
- `record.save_draft`
|
|
72
|
+
- `record.update_draft(attrs)`
|
|
73
|
+
- `Model.drafts(User.current)`
|
|
74
|
+
- `Model.from_draft(draft_or_id)`
|
|
75
|
+
|
|
76
|
+
## `up_acts_as_viewed`
|
|
77
|
+
|
|
78
|
+
Tracks unique views by user (or IP) and total views.
|
|
79
|
+
|
|
80
|
+
### Migration
|
|
81
|
+
|
|
82
|
+
```ruby
|
|
83
|
+
class CreateViewings < ActiveRecord::Migration[6.1]
|
|
84
|
+
def change
|
|
85
|
+
ActiveRecord::Base.create_viewings_table
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Optional helpers for models with embedded counters:
|
|
91
|
+
|
|
92
|
+
- `ActiveRecord::Base.generate_viewings_columns(table)`
|
|
93
|
+
- `Model.add_viewings_columns`
|
|
94
|
+
- `Model.remove_viewings_columns`
|
|
95
|
+
- `ActiveRecord::Base.drop_viewings_table`
|
|
96
|
+
|
|
97
|
+
### Model
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
class Question < ApplicationRecord
|
|
101
|
+
up_acts_as_viewed
|
|
102
|
+
end
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Runtime API
|
|
106
|
+
|
|
107
|
+
- `record.view(request.remote_ip, User.current)`
|
|
108
|
+
- `record.viewed?`
|
|
109
|
+
- `record.view_count`
|
|
110
|
+
- `record.viewed_by?(request.remote_ip, User.current)`
|
|
111
|
+
|
|
112
|
+
## `up_acts_as_votable` and `up_acts_as_voter`
|
|
113
|
+
|
|
114
|
+
Adds voting capabilities for content and users.
|
|
115
|
+
|
|
116
|
+
### Migration
|
|
117
|
+
|
|
118
|
+
```ruby
|
|
119
|
+
class CreateVotes < ActiveRecord::Migration[6.1]
|
|
120
|
+
def change
|
|
121
|
+
ActiveRecord::Base.create_votable_table
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Helpers:
|
|
127
|
+
|
|
128
|
+
- `ActiveRecord::Base.create_votable_table`
|
|
129
|
+
- `ActiveRecord::Base.drop_votable_table`
|
|
130
|
+
|
|
131
|
+
### Models
|
|
132
|
+
|
|
133
|
+
```ruby
|
|
134
|
+
class Question < ApplicationRecord
|
|
135
|
+
up_acts_as_votable
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
class User < ApplicationRecord
|
|
139
|
+
up_acts_as_voter
|
|
140
|
+
end
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## `up_acts_as_priceable`
|
|
144
|
+
|
|
145
|
+
Generates currency-aware `*_to_s` methods for price fields.
|
|
146
|
+
|
|
147
|
+
### Model
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
class Deal < ApplicationRecord
|
|
151
|
+
up_acts_as_priceable :amount, :tax_amount, :subtotal, :total
|
|
152
|
+
end
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
This creates methods like `amount_to_s`, `tax_amount_to_s`, etc., backed by
|
|
156
|
+
`Redmineup::MoneyHelper#object_price`.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Assets, money, and shared utilities
|
|
2
|
+
|
|
3
|
+
## Asset helpers
|
|
4
|
+
|
|
5
|
+
Provided by `Redmineup::ExternalAssetsHelper`:
|
|
6
|
+
|
|
7
|
+
- `redmineup_assets`
|
|
8
|
+
- `select2_assets` (alias for `redmineup_assets`)
|
|
9
|
+
- `chartjs_assets`
|
|
10
|
+
|
|
11
|
+
`redmineup_assets` includes:
|
|
12
|
+
|
|
13
|
+
- `consumer.js`
|
|
14
|
+
- `select2.js`
|
|
15
|
+
- `select2_helpers.js`
|
|
16
|
+
- `redmineup.css`
|
|
17
|
+
|
|
18
|
+
The gem also hooks `view_layouts_base_html_head` and renders
|
|
19
|
+
`redmineup/_additional_assets`, so shared assets can be included globally.
|
|
20
|
+
Helpers are idempotent and safe to call from plugin views.
|
|
21
|
+
|
|
22
|
+
## Money and currency
|
|
23
|
+
|
|
24
|
+
### Settings API
|
|
25
|
+
|
|
26
|
+
`Redmineup::Settings::Money` provides access to plugin-level money settings:
|
|
27
|
+
|
|
28
|
+
- `default_currency`
|
|
29
|
+
- `major_currencies`
|
|
30
|
+
- `default_tax`
|
|
31
|
+
- `tax_type`, `tax_exclusive?`
|
|
32
|
+
- `thousands_delimiter`
|
|
33
|
+
- `decimal_separator`
|
|
34
|
+
- `disable_taxes?`
|
|
35
|
+
|
|
36
|
+
### Formatting helpers
|
|
37
|
+
|
|
38
|
+
`Redmineup::MoneyHelper` provides:
|
|
39
|
+
|
|
40
|
+
- `price_to_currency(price, currency, options = {})`
|
|
41
|
+
- `object_price(record, :price)`
|
|
42
|
+
- `prices_collection_by_currency(hash, hide_zeros: true)`
|
|
43
|
+
- `collection_for_currencies_select`
|
|
44
|
+
- `all_currencies`
|
|
45
|
+
|
|
46
|
+
`up_acts_as_priceable` uses these helpers to generate `*_to_s` methods on
|
|
47
|
+
models.
|
|
48
|
+
|
|
49
|
+
### Admin UI
|
|
50
|
+
|
|
51
|
+
`Redmineup::Currency.add_admin_money_menu` registers a Redmine admin menu item
|
|
52
|
+
that points to:
|
|
53
|
+
|
|
54
|
+
- `redmineup_settings_path(:money)`
|
|
55
|
+
|
|
56
|
+
## Misc shared helpers and patches
|
|
57
|
+
|
|
58
|
+
- `Redmineup::CalendarsHelper#calendar_day_css_classes`
|
|
59
|
+
- Liquid patch for numeric conversion in `Liquid::StandardFilters`
|
|
60
|
+
- Liquid filters/drops under `lib/redmineup/liquid/**`
|
|
61
|
+
- Compatibility and ActionCable patches loaded at gem boot
|
|
62
|
+
|
|
63
|
+
## Version requirements in plugins
|
|
64
|
+
|
|
65
|
+
Plugins typically guard compatibility in `init.rb`:
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
requires_redmineup version_or_higher: '1.1.5'
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Use this to fail fast when a plugin depends on newer helper or API behavior.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# Tagging and Select2 helpers
|
|
2
|
+
|
|
3
|
+
This page covers view helpers used by RedmineUP plugins for tag rendering,
|
|
4
|
+
tag editing, and select2-backed filters.
|
|
5
|
+
|
|
6
|
+
## Tag rendering helpers
|
|
7
|
+
|
|
8
|
+
Provided by `Redmineup::TagsHelper`:
|
|
9
|
+
|
|
10
|
+
- `tag_link(url, tag_name, options = {})`
|
|
11
|
+
- `tag_links(tag_list, options = {}) { |tag| url }`
|
|
12
|
+
- `tag_cloud(tags, classes) { |tag, css_class| ... }`
|
|
13
|
+
- `tag_cloud_links(tags, key, options = {})`
|
|
14
|
+
- `tag_separator`
|
|
15
|
+
|
|
16
|
+
### Recommended pattern
|
|
17
|
+
|
|
18
|
+
Define `*_tag_url` per plugin context:
|
|
19
|
+
|
|
20
|
+
```ruby
|
|
21
|
+
def contact_tag_url(tag_name, options = {})
|
|
22
|
+
{
|
|
23
|
+
controller: 'contacts',
|
|
24
|
+
action: 'index',
|
|
25
|
+
set_filter: 1,
|
|
26
|
+
fields: [:tags],
|
|
27
|
+
values: { tags: [tag_name] },
|
|
28
|
+
operators: { tags: '=' }
|
|
29
|
+
}.merge(options)
|
|
30
|
+
end
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Then render the cloud via convention:
|
|
34
|
+
|
|
35
|
+
```erb
|
|
36
|
+
<%= tag_cloud_links(Contact.available_tags(project: @project), :contact) %>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`tag_cloud_links(tags, :contact)` expects `contact_tag_url(name)` to be defined
|
|
40
|
+
in the current view context.
|
|
41
|
+
|
|
42
|
+
## Tag editors with Select2
|
|
43
|
+
|
|
44
|
+
Provided by `Redmineup::FormTagHelper`:
|
|
45
|
+
|
|
46
|
+
- `select2_tag(name, option_tags = nil, options = {})`
|
|
47
|
+
- `select2(...)` (alias)
|
|
48
|
+
- `tag_list_field_tag(name, value = [], options = {})`
|
|
49
|
+
- `transform_to_select2(type, options = {})`
|
|
50
|
+
|
|
51
|
+
`ActionView::Helpers::FormBuilder` is extended with:
|
|
52
|
+
|
|
53
|
+
- `f.tag_list_field(:tag_list, **options)`
|
|
54
|
+
|
|
55
|
+
### Example: form object API
|
|
56
|
+
|
|
57
|
+
```erb
|
|
58
|
+
<%= f.tag_list_field :tag_list, width: '95%' %>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Example: standalone field API
|
|
62
|
+
|
|
63
|
+
```erb
|
|
64
|
+
<%= tag_list_field_tag 'product[tag_list]', @product.tag_list, taggable_type: 'Product' %>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Example: query/filter select2 transform
|
|
68
|
+
|
|
69
|
+
```erb
|
|
70
|
+
<%= transform_to_select2 'product_tags',
|
|
71
|
+
url: auto_complete_taggable_tags_path(project_id: @project, taggable_type: 'Product') %>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Tag autocomplete endpoint
|
|
75
|
+
|
|
76
|
+
`redmineup` adds a shared route:
|
|
77
|
+
|
|
78
|
+
- `GET /auto_completes/taggable_tags`
|
|
79
|
+
|
|
80
|
+
Named route:
|
|
81
|
+
|
|
82
|
+
- `auto_complete_taggable_tags_path`
|
|
83
|
+
|
|
84
|
+
Typical params used by plugins:
|
|
85
|
+
|
|
86
|
+
- `taggable_type`: model class name (`Contact`, `Person`, `Product`, `Issue`, `DriveEntry`)
|
|
87
|
+
- `project_id`: optional project scope
|
|
88
|
+
- `limit`: optional result size limit
|
|
89
|
+
|
|
90
|
+
Response format:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
[
|
|
94
|
+
{ "id": "important", "text": "important" },
|
|
95
|
+
{ "id": "vip", "text": "vip" }
|
|
96
|
+
]
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Real plugin usage
|
|
100
|
+
|
|
101
|
+
Patterns above are used by:
|
|
102
|
+
|
|
103
|
+
- `redmine_contacts` (`contact_tag_url`, `contact_tag_links`, `f.tag_list_field`)
|
|
104
|
+
- `redmine_people` (`people_tag_url`, `tag_cloud_links`, bulk edit tag forms)
|
|
105
|
+
- `redmine_products` (`product_tag_url`, `tag_list_field_tag`, select2 filters)
|
|
106
|
+
- `redmine_questions` (`question_tag_url`, `tag_cloud_links`)
|
|
107
|
+
- `redmine_drive` (`drive_entry_tag_url`, select2 tag filters)
|
|
108
|
+
- `redmineup_tags` (issue tag forms with `tag_list_field_tag`)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module ActionCable
|
|
2
|
+
module Connection
|
|
3
|
+
class RupConnection < ActionCable::Connection::Base
|
|
4
|
+
identified_by :current_user
|
|
5
|
+
|
|
6
|
+
def connect
|
|
7
|
+
self.current_user = find_verified_user
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def find_verified_user
|
|
13
|
+
User.find_by(id: @request.session[:user_id]) || User.anonymous
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'digest/md5'
|
|
2
|
+
|
|
1
3
|
module Redmineup
|
|
2
4
|
module ActsAsTaggable #:nodoc:
|
|
3
5
|
class Tag < ActiveRecord::Base #:nodoc:
|
|
@@ -17,6 +19,10 @@ module Redmineup
|
|
|
17
19
|
where("LOWER(name) LIKE LOWER(?)", name).first || create(:name => name)
|
|
18
20
|
end
|
|
19
21
|
|
|
22
|
+
def self.color_from_name(str)
|
|
23
|
+
"##{Digest::MD5.hexdigest(str.to_s)[0..5]}"
|
|
24
|
+
end
|
|
25
|
+
|
|
20
26
|
def ==(object)
|
|
21
27
|
super || (object.is_a?(Tag) && name == object.name)
|
|
22
28
|
end
|
|
@@ -30,11 +36,15 @@ module Redmineup
|
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
def color
|
|
33
|
-
|
|
39
|
+
if self.class.column_names.include?('color')
|
|
40
|
+
db_color = read_attribute(:color)
|
|
41
|
+
return ('#' + "%06x" % db_color) unless db_color.nil?
|
|
42
|
+
end
|
|
43
|
+
self.class.color_from_name(name)
|
|
34
44
|
end
|
|
35
45
|
|
|
36
46
|
def color=(color)
|
|
37
|
-
write_attribute(:color, color.
|
|
47
|
+
write_attribute(:color, color.sub(/\A#/, '').hex) unless color.blank?
|
|
38
48
|
end
|
|
39
49
|
|
|
40
50
|
class << self
|
|
@@ -74,7 +84,7 @@ module Redmineup
|
|
|
74
84
|
having = 'COUNT(*) > 0'
|
|
75
85
|
having = [having, at_least, at_most].compact.join(' AND ')
|
|
76
86
|
group_by = "#{Tag.table_name}.id, #{Tag.table_name}.name"
|
|
77
|
-
|
|
87
|
+
group_by << ", #{Tag.table_name}.color" if column_names.include?('color')
|
|
78
88
|
|
|
79
89
|
select_condition = if self.column_names.include?('color')
|
|
80
90
|
"#{Tag.table_name}.id, #{Tag.table_name}.name, #{Tag.table_name}.color, COUNT(*) AS count"
|
|
@@ -52,6 +52,7 @@ module Redmineup
|
|
|
52
52
|
if !self.connection.table_exists?(tag_name_table)
|
|
53
53
|
self.connection.create_table(tag_name_table) do |t|
|
|
54
54
|
t.column :name, :string
|
|
55
|
+
t.column :color, :integer
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
58
|
|
|
@@ -64,6 +65,7 @@ module Redmineup
|
|
|
64
65
|
# You should make sure that the column created is
|
|
65
66
|
# long enough to store the required class names.
|
|
66
67
|
t.column :taggable_type, :string
|
|
68
|
+
t.column :color, :integer, default: nil
|
|
67
69
|
|
|
68
70
|
t.column :created_at, :datetime
|
|
69
71
|
end
|
|
@@ -82,16 +84,16 @@ module Redmineup
|
|
|
82
84
|
#
|
|
83
85
|
# E.g.: ActiveRecord::Base.add_tags_column(:tags, name: :color, type: :string, default: nil)
|
|
84
86
|
def add_tags_column(table_name = :tags, **options)
|
|
85
|
-
tag_column = options
|
|
87
|
+
tag_column = options
|
|
86
88
|
tag_column.assert_valid_keys(:name, :type, :default)
|
|
87
89
|
|
|
88
90
|
raise ArgumentError, "Table `#{table_name}' not found" unless self.connection.table_exists?(table_name)
|
|
89
91
|
|
|
90
92
|
self.table_name = table_name
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
return if connection.column_exists?(table_name, tag_column[:name])
|
|
94
|
+
|
|
95
|
+
connection.add_column table_name, tag_column[:name], tag_column[:type], default: tag_column[:default]
|
|
96
|
+
reset_column_information
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
# Remove the up_acts_as_taggable specific columns
|
|
@@ -140,13 +142,14 @@ module Redmineup
|
|
|
140
142
|
scope = scope.where("#{table_name}.project_id IN (%s)", projects.map(&:id).join(','))
|
|
141
143
|
end
|
|
142
144
|
|
|
143
|
-
if options[:name_like]
|
|
145
|
+
if options[:name_like].present?
|
|
144
146
|
scope = scope.where("LOWER(#{Tag.table_name}.name) LIKE LOWER(?)", "%#{options[:name_like]}%")
|
|
145
147
|
end
|
|
146
148
|
|
|
147
149
|
group_fields = ''
|
|
148
150
|
group_fields << ", #{Tag.table_name}.created_at" if Tag.respond_to?(:created_at)
|
|
149
151
|
group_fields << ", #{Tag.table_name}.updated_at" if Tag.respond_to?(:updated_at)
|
|
152
|
+
group_fields << ", #{Tag.table_name}.color" if Tag.column_names.include?('color')
|
|
150
153
|
|
|
151
154
|
if base_class.respond_to?(:visible_condition)
|
|
152
155
|
visible_condition = base_class.visible_condition(User.current)
|
data/lib/redmineup/engine.rb
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
module Redmineup
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
class Engine < Rails::Engine
|
|
3
|
+
config.to_prepare do
|
|
4
|
+
next unless defined?(::Redmine::Plugin)
|
|
5
|
+
|
|
6
|
+
require 'auto_completes_controller'
|
|
7
|
+
|
|
8
|
+
require File.expand_path('../redmineup/patches/compatibility_patch', __dir__)
|
|
9
|
+
require File.expand_path('../redmineup/patches/auto_completes_controller_patch', __dir__)
|
|
10
|
+
|
|
11
|
+
require File.expand_path('../redmineup/hooks/views_layouts_hook', __dir__)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
4
14
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Redmineup
|
|
2
|
+
module DatetimeHelper
|
|
3
|
+
def convert_time_to_user_timezone(time)
|
|
4
|
+
if User.current.time_zone
|
|
5
|
+
time.in_time_zone(User.current.time_zone)
|
|
6
|
+
else
|
|
7
|
+
time.utc? ? time.localtime : time
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def convert_time_to_utc(time = Time.now)
|
|
12
|
+
return Time.now.utc if time.blank?
|
|
13
|
+
return time.utc if time.respond_to?(:utc)
|
|
14
|
+
|
|
15
|
+
time_zone = User.current.time_zone
|
|
16
|
+
return Time.parse(time).utc unless time_zone
|
|
17
|
+
|
|
18
|
+
Time.use_zone(time_zone) do
|
|
19
|
+
Time.zone.parse(time).utc
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -2,19 +2,27 @@ module Redmineup
|
|
|
2
2
|
module ExternalAssetsHelper
|
|
3
3
|
include ActionView::Helpers::JavaScriptHelper
|
|
4
4
|
|
|
5
|
+
def redmineup_assets
|
|
6
|
+
return if @redmineup_assets_included
|
|
7
|
+
|
|
8
|
+
@redmineup_assets_included = true
|
|
9
|
+
javascript_include_tag('consumer', plugin: GEM_NAME) +
|
|
10
|
+
javascript_include_tag('select2', plugin: GEM_NAME) +
|
|
11
|
+
javascript_include_tag('select2_helpers', plugin: GEM_NAME) +
|
|
12
|
+
javascript_include_tag('jquery.colorPicker.min', plugin: GEM_NAME) +
|
|
13
|
+
stylesheet_link_tag('redmineup', plugin: GEM_NAME) +
|
|
14
|
+
javascript_tag("window.redmineupWorkerUrl = #{asset_path('consumer_worker.js', plugin: GEM_NAME).to_json};")
|
|
15
|
+
end
|
|
16
|
+
|
|
5
17
|
def select2_assets
|
|
6
|
-
|
|
7
|
-
@select2_tag_included = true
|
|
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)
|
|
18
|
+
redmineup_assets
|
|
11
19
|
end
|
|
12
20
|
|
|
13
21
|
def chartjs_assets
|
|
14
22
|
return if @chartjs_tag_included
|
|
23
|
+
|
|
15
24
|
@chartjs_tag_included = true
|
|
16
25
|
javascript_include_tag('chart.min', plugin: GEM_NAME)
|
|
17
26
|
end
|
|
18
|
-
|
|
19
27
|
end
|
|
20
28
|
end
|