149 Commits
0.9.9 ... 1.0.7

Author SHA1 Message Date
Alexander Meindl
49c9f42343 fix coding standards and bump version 2020-08-22 18:56:45 +02:00
Alexander Meindl
4a2d652163 Merge pull request #72 from Ujifman/master
Added feature to send messages directly to users to be notified
2020-08-22 18:41:38 +02:00
Igor Pronin
f4382f7d86 Added feature to send messages directly to users to be notified
Added setting to enable this feature.
Tested on RocketChatIntegration
2020-08-20 16:33:08 +03:00
Alexander Meindl
18b0ea1adf Fixing coding standards 2020-08-09 08:37:45 +02:00
Alexander Meindl
c58c93005d tag helper instead of content_tag 2020-06-09 14:48:05 +02:00
Alexander Meindl
e0e35e6edf Make rubocop happy, again 2020-06-09 09:23:06 +02:00
Alexander Meindl
8702f062fa Merge pull request #65 from WuCris/master
Update Readme.md to add missing description of plugin settings
2020-06-09 09:17:03 +02:00
wucris
4cdd909889 update readme to add missing description of plugin settings 2020-05-05 18:46:28 -04:00
Alexander Meindl
8501a98486 remove debug infos 2020-04-28 11:45:47 +02:00
Alexander Meindl
b1d7309d97 Fix problem with & in project name 2020-04-28 11:41:21 +02:00
Alexander Meindl
03fab2c28e #61 fixed bug with description for issue update 2020-04-17 11:13:04 +02:00
Alexander Meindl
e82efa6180 Ruby 2.4 or higher is required 2020-04-16 13:00:50 +02:00
Alexander Meindl
b6afda186e Loading problem caused by https://www.redmine.org/issues/33290 2020-04-15 14:58:23 +02:00
Alexander Meindl
25b2694018 Db check required because of broken installation of redmine - caused by query with User.current 2020-04-15 12:38:48 +02:00
Alexander Meindl
57f8ef4092 Merge pull request #60 from jcppkkk/master
Fix formatting error of estimated_hours
2020-04-15 08:21:49 +02:00
Jethro Yu
f13d5c1e55 Fix formatting error of estimated_hours
To fix following error on Redmine 4.1.1
```
NoMethodError (undefined method `floor' for "1.0":String):

lib/redmine/i18n.rb:90:in `format_hours'
plugins/redmine_messenger/app/models/messenger.rb:209:in `detail_to_field'
```

Use redmine's `to_hours` convention on estimated_hours
```
lib/redmine/core_ext/string/conversions.rb
29:        def to_hours

app/models/issue.rb
454:    write_attribute :estimated_hours, (h.is_a?(String) ? (h.to_hours || h) : h)
```
2020-04-15 12:42:35 +08:00
Alexander Meindl
54de15db0b Patch integration cleanups 2020-04-12 15:49:13 +02:00
Alexander Meindl
294f435452 Patch integration cleanups 2020-04-12 09:35:10 +02:00
Alexander Meindl
8519130cee New ruby version for travis 2020-04-04 16:45:12 +02:00
Alexander Meindl
39cab0e954 Update github actions 2020-04-01 08:19:43 +02:00
Alexander Meindl
0074475a66 Merge pull request #59 from ZerooCool/master
Upgrade Fr Language
2020-04-01 08:14:20 +02:00
Alexander Meindl
731e616b7d do not use COVERAGE, because Redmine core use it already 2020-03-29 18:08:23 +02:00
Alexander Meindl
e54c4406e1 remove rcov 2020-03-29 17:07:49 +02:00
Alexander Meindl
74e39b918e remove rcov format 2020-03-29 15:48:12 +02:00
Alexander Meindl
6167b64112 remove skip_coverage export 2020-03-29 11:49:23 +02:00
Zer00CooL
f95fd57ab8 Update fr.yml 2020-03-28 23:09:39 +01:00
ZerooCool
24a7b99b7f fr.yml - Translation. 2020-03-28 23:02:52 +01:00
Alexander Meindl
73a623c791 Optimize testing 2020-03-26 07:53:31 +01:00
Alexander Meindl
e25d02a110 Badge update 2020-03-25 20:31:42 +01:00
Alexander Meindl
8398d32c4f One more badge for tests 2020-03-25 20:20:45 +01:00
Alexander Meindl
c3ffdff7d3 Disable COVERAGE as default 2020-03-25 20:10:17 +01:00
Alexander Meindl
ba82f825bf Add github actions test 2020-03-25 20:02:59 +01:00
Alexander Meindl
15dc372bb2 add badget 2020-03-25 19:51:26 +01:00
Alexander Meindl
dd410756c2 remove debug code 2020-03-25 19:47:15 +01:00
Alexander Meindl
3178a6e921 Add gem sources 2020-03-25 19:44:13 +01:00
Alexander Meindl
f4b62005b4 Use github actions for rubocop 2020-03-25 19:42:14 +01:00
Alexander Meindl
edc63d1ee5 Travis cleanup 2020-03-03 15:45:21 +01:00
Alexander Meindl
fa9127cb24 Update rubocop configuration and changelog 2020-03-03 15:22:00 +01:00
Alexander Meindl
d2ad1fb020 Show attachments in new issues and show flag if private comment 2020-03-03 15:16:02 +01:00
Alexander Meindl
48c4b99882 Always send attachments with payload, to get improved output without attachments with Rocket.Chat 2020-02-23 10:45:31 +01:00
Alexander Meindl
e4eee286ba Fix outgoing hook settings for non-admins within projects 2020-02-21 10:30:47 +01:00
Alexander Meindl
ee9347d8fb Increase number of translation to fix test 2020-02-11 09:53:13 +01:00
Ji-Hyeon Gim
873cbe1021 initial Korean translation
Signed-off-by: Ji-Hyeon Gim <potatogim@gluesys.com>
2020-02-11 09:51:56 +01:00
Alexander Meindl
5d037719c7 #56 fix 2020-02-11 09:27:54 +01:00
Alexander Meindl
49e847794f Show db entries and password names, if available 2020-01-25 11:59:13 +01:00
Alexander Meindl
442c3fb320 #53 add legend to fieldset. Remove comments in fr.yml to have same line amount (for easier administration of strings) 2020-01-25 11:08:38 +01:00
Alexander Meindl
0b4425399a Fix strings for tests 2020-01-20 18:08:13 +01:00
Alexander Meindl
de5cce957c #50 use formated result for estimated_hours 2020-01-17 10:26:27 +01:00
Alexander Meindl
31d0ce3748 Merge pull request #46 from ZerooCool/patch-1
Update config/locales/fr.yml 01/2020.
2020-01-16 08:45:17 +01:00
ZerooCool
6fa21f3648 Update config/locales/fr.yml 01/2020. 2020-01-15 06:09:27 +01:00
ZerooCool
e71bba934a Langue fusionnée sur patch-1. 2020-01-15 02:01:44 +01:00
Alexander Meindl
164bc700e1 Fix bug with assigned_to field twice and fallback values, if objects do not exist anymore 2020-01-07 13:22:53 +01:00
Alexander Meindl
b2e7cca639 #38 fix for Redmine 4.1 for frozen string 2020-01-07 08:33:58 +01:00
Alexander Meindl
b0977a54e8 Add uninstall test to travis 2020-01-01 18:40:00 +01:00
Alexander Meindl
43b5ad945a Add bug to Changelog 2019-12-31 13:50:14 +01:00
Alexander Meindl
8e4bc584d7 Update documentationg 2019-12-31 13:45:16 +01:00
Alexander Meindl
2563b8007c Fix another problem with notes 2019-12-31 13:43:06 +01:00
Alexander Meindl
3a9101eda9 Fix password label 2019-12-27 07:59:43 +01:00
Alexander Meindl
8b1fad1745 Fix template for password fieldset 2019-12-27 07:57:33 +01:00
Alexander Meindl
d027d77141 Add administrator link to project settings 2019-12-27 06:23:47 +01:00
Alexander Meindl
7cba13f8cd Fix custom fields 2019-12-26 18:25:19 +01:00
Alexander Meindl
9be229f1c4 Add rubocop to travis 2019-12-26 17:42:36 +01:00
Alexander Meindl
49b282e638 #38 fix problem with escaping 2019-12-26 17:24:28 +01:00
Alexander Meindl
0ae4da5e40 #35 fixed description info 2019-12-26 15:35:20 +01:00
Alexander Meindl
94a09c0803 #40 fixed status and priority information 2019-12-26 15:08:38 +01:00
Alexander Meindl
0e9235875b #43 documentation has been added for older redmine 2019-12-22 10:08:18 +01:00
Alexander Meindl
b68d2d9f6f Working on Redmine 4.1 support; drop Redmine 3.x support 2019-12-22 09:05:18 +01:00
Alexander Meindl
543f8ff49b Add mysql for travis tests 2019-08-07 20:32:17 +02:00
Alexander Meindl
96f9e93e31 Add notice to use right directory name 2019-07-07 17:07:38 +02:00
Alexander Meindl
c7a9f0c8da remove rubocop from Gemfile, till redmine 4 is required 2019-06-03 21:11:13 +02:00
Alexander Meindl
bf8d2d3d4d Ruby 2.3.x or newer is required. Bump to 1.0.5 2019-05-15 20:06:35 +02:00
Alexander Meindl
c670b5606d Fix channel settings 2019-04-11 14:55:28 +02:00
Alexander Meindl
8c60b1ae0b Because of bundler version conflict switch back to ruby 2.4.5 on travis 2019-04-11 10:37:24 +02:00
Alexander Meindl
56fa966d92 Fix test for new fr translation and some cleanups 2019-04-11 10:32:42 +02:00
Alexander Meindl
b658906ee6 Merge pull request #36 from ZerooCool/master
Thanks for contributing to this plugin! I'll take care of the broken test.
2019-04-11 10:18:59 +02:00
Zer00CooL
7fd5910d50 fr.yml
Nouveau fichier de langue pour redmine_messenger en français.
2019-04-11 01:39:05 +02:00
Zer00CooL
3df2d55fef French translation
French translation.
2019-04-10 01:05:47 +02:00
Alexander Meindl
712fbcd69a Some cleanup and travis updates 2018-12-30 10:04:09 +01:00
Alexander Meindl
1d7e53fd9c settings supports migration from redmine 3.x to redmine 4 2018-12-29 21:38:05 +01:00
Alexander Meindl
23673170b4 removed unused code 2018-11-17 22:25:38 +01:00
Alexander Meindl
2a73c105e6 Adjust rubocop settings 2018-11-17 08:19:40 +01:00
Alexander Meindl
da9102c741 Fix settings for rails 5 2018-09-26 17:20:43 +02:00
Alexander Meindl
8067fd40e8 Fix migration problem with Rails 5.2 2018-09-26 12:53:39 +02:00
Alexander Meindl
d3e3bbde0f New ruby version for travis tests and adjustments for latest redmine master changes 2018-09-24 09:48:38 +02:00
Alexander Meindl
58b4a890ca Fix new coding standards 2018-09-10 17:45:53 +02:00
Alexander Meindl
94212d2f3d try to deal with inconsistent data, as in https://github.com/mikitex70/redmine_drawio/issues/59 2018-09-09 15:30:50 +02:00
Alexander Meindl
c1b8c033d4 More cleanups 2018-07-27 20:00:24 +02:00
Alexander Meindl
c7f97afc0c patch apply refactored 2018-07-27 19:58:10 +02:00
Alexander Meindl
4f5868cc57 Use project helper instead of helper patch 2018-07-27 19:49:36 +02:00
Alexander Meindl
f670a44c66 Creating db once is enough 2018-07-16 17:21:25 +02:00
Alexander Meindl
b2780bf618 drop SafeAttributes 2018-07-16 15:59:01 +02:00
Alexander Meindl
ca62927d19 Fix tests for Redmine 4 2018-07-16 14:01:28 +02:00
Alexander Meindl
ba65df0ece Fix project patch 2018-07-16 13:37:23 +02:00
Alexander Meindl
06d1edd5cc Fix build for master 2018-07-16 13:33:16 +02:00
Alexander Meindl
0c4482b3a5 Working on Redmine 4 support 2018-07-16 13:31:55 +02:00
Alexander Meindl
504730e337 Do not show warning with tests 2018-07-16 13:13:03 +02:00
Alexander Meindl
c0b892e983 Do not show warning with tests 2018-07-16 13:09:24 +02:00
Alexander Meindl
9454e06766 Do not show warning with tests 2018-07-16 13:02:39 +02:00
Alexander Meindl
9339ad53b2 More work on travis 2018-07-16 12:56:57 +02:00
Alexander Meindl
bb1920f1ce More work on travis 2018-07-16 12:52:39 +02:00
Alexander Meindl
ddf87dd2dc More work on travis 2018-07-16 12:48:51 +02:00
Alexander Meindl
41a510fbb4 More work on travis 2018-07-16 12:45:41 +02:00
Alexander Meindl
91977c8b83 More work on travis 2018-07-16 12:33:17 +02:00
Alexander Meindl
4392789a1b More work on travis 2018-07-16 12:31:30 +02:00
Alexander Meindl
466c676e40 Add skip coverage 2018-07-16 11:57:57 +02:00
Alexander Meindl
aecc9572c2 Add travis configuration 2018-07-16 11:56:03 +02:00
Alexander Meindl
6ba0ea782a Fix ruby version 2018-07-09 21:49:58 +02:00
Alexander Meindl
183f8dfa00 Update index 2018-05-30 08:58:31 +02:00
Alexander Meindl
2cdd0c0cce Fix patch include 2018-05-11 07:10:15 +02:00
Alexander Meindl
0b91d86290 routes cleanup 2018-02-17 16:16:21 +01:00
Alexander Meindl
0dc906e61d #14 fixed routing cleanup bug 2018-01-31 07:03:20 +01:00
Alexander Meindl
835174d831 Add TODO comment 2018-01-28 12:32:21 +01:00
Alexander Meindl
25744d4337 Add wrapper to do markup_format later on 2018-01-28 12:29:31 +01:00
Alexander Meindl
585d49bdec remove comments 2018-01-28 11:51:41 +01:00
Alexander Meindl
b1a527fc52 Cleanup routings 2018-01-28 11:47:25 +01:00
Alexander Meindl
f44366bd75 Add documentation to use plugin with Discord #7 2018-01-25 18:47:28 +01:00
Alexander Meindl
7339e9e382 Add is_private support for db and contacts 2018-01-25 17:05:28 +01:00
Alexander Meindl
4d447f75ab Do not show watcher info, if no watcher is assigned 2018-01-25 15:37:12 +01:00
Alexander Meindl
593d7055e0 slim templates, subdirectory bug fixed #9, other solution of #12 included 2018-01-24 12:03:28 +01:00
Alexander Meindl
c16dec39e4 Remove comments 2018-01-02 13:07:27 +01:00
Alexander Meindl
0ee9fa36e6 Fix ignore file problem 2017-12-13 10:26:25 +01:00
Alexander Meindl
95a914f1ae stylelint configuration 2017-12-12 22:14:43 +01:00
Alexander Meindl
d683f08eef Add disable rule to rubocop for timestamp 2017-12-12 18:36:45 +01:00
Alexander Meindl
1085b042e5 add coverage to ignore list 2017-12-11 21:42:20 +01:00
Alexander Meindl
454437cbf5 Add eslintignore 2017-12-11 21:39:36 +01:00
Alexander Meindl
a53fd43ef4 add linter configuration 2017-12-11 21:11:18 +01:00
Alexander Meindl
7a3d335065 Updated, rails optimized common rubocop configuration 2017-10-15 09:33:41 +02:00
Alexander Meindl
b2d71d2a0e Use space in front of To 2017-10-10 19:21:36 +02:00
Alexander Meindl
2a1672f024 Fix issue with settings 2017-10-10 18:56:15 +02:00
Alexander Meindl
2c3b503f68 Some code cleanups 2017-10-10 18:25:17 +02:00
Alexander Meindl
0427b97a46 Support for existion database and some cosmetics 2017-10-10 18:15:11 +02:00
Alessandro Grassi
bbd6a69f8d Add support for default mentions
Signed-off-by: Alessandro Grassi <alessandro.grassi@2ndquadrant.com>
2017-10-10 16:52:38 +02:00
Alexander Meindl
763cf347f6 use references instead of belongs_to 2017-08-05 09:57:21 +02:00
Alexander Meindl
3687fbbe90 Update changelog 2017-08-05 07:20:47 +02:00
Alexander Meindl
9a8295247c Add unit test for parsing ja strings 2017-08-05 07:12:05 +02:00
Alexander Meindl
fe8d1fd856 Merge pull request #5 from Yoto/japanese
Add a Japanese support. Thanks for your help!
2017-08-05 06:52:29 +02:00
Yusuke Yoshimura
53e75212cb Add a Japanese support 2017-08-05 13:28:50 +09:00
Alexander Meindl
c98e4fc989 Add settings string 2017-07-31 13:27:57 +02:00
Alexander Meindl
18a2856aa2 Documentation fix for installation 2017-07-29 11:24:55 +02:00
Alexander Meindl
df46bf0f15 Improve installation and uninstall documentation 2017-07-29 06:59:43 +02:00
Alexander Meindl
5d6495f009 Redmine 3.4.x support and version bump to 1.0.0 2017-07-13 12:32:43 +02:00
Alexander Meindl
8162eeb01d Remove issue.save from changeset hook 2017-07-12 19:00:22 +02:00
Alexander Meindl
7e9a994c03 Merge pull request #3 from danfai/master
Send repository update message only if updates should be sent
2017-07-12 18:48:50 +02:00
danfai
2e2e2c4286 Send repository update message only if updates should be sent 2017-07-12 17:08:18 +02:00
Alexander Meindl
5882bad2cb Merge pull request #2 from TRIOTECH-fr/master
Fixed undefined project variable
2017-07-11 15:28:47 +02:00
qkdreyer
92f0c40b50 Merge branch 'master' of https://github.com/TRIOTECH-fr/redmine_messenger 2017-07-01 10:45:21 +02:00
qkdreyer
a91795a818 Fixed undefined project variable 2017-06-30 17:17:23 +02:00
Alexander Meindl
6295fb3b26 add_filter init.rb 2017-06-28 16:19:37 +02:00
Alexander Meindl
a68e3a2fb1 Add code coverage to tests 2017-06-28 15:21:30 +02:00
55 changed files with 1512 additions and 861 deletions

17
.eslintrc.yml Normal file
View File

@@ -0,0 +1,17 @@
env:
browser: true
jquery: true
extends: 'eslint:recommended'
rules:
indent:
- error
- 2
linebreak-style:
- error
- unix
quotes:
- error
- single
semi:
- error
- always

34
.github/workflows/rubocop.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Run RuboCop
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up Ruby 2.6
uses: actions/setup-ruby@v1
with:
ruby-version: 2.6.x
- name: Set Gemfile
run: |
echo "">> Gemfile
echo "group :test do">> Gemfile
echo " gem 'rubocop', require: false" >> Gemfile
echo " gem 'rubocop-performance', require: false" >> Gemfile
echo " gem 'rubocop-rails', require: false" >> Gemfile
echo "end">> Gemfile
- name: Setup gems
run: |
gem install bundler
bundle install --jobs 4 --retry 3
- name: Run RuboCop
run: |
bundle exec rubocop -S

31
.github/workflows/tests.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Run Tests
on:
push:
pull_request:
schedule:
- cron: '0 5 * * *'
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
redmine:
- v4.0
- v4.1
- trunk
ruby:
- v2.4
- v2.6
database:
- sqlite3
- postgres
steps:
- name: Redmine plugin test
uses: two-pack/redmine-plugin-test-action@v2
with:
plugin_name: redmine_messenger
redmine_version: ${{ matrix.redmine }}
ruby_version: ${{ matrix.ruby }}

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
.DS_Store
coverage/
.buildpath
.project
.settings/

View File

@@ -1,43 +1,53 @@
require:
- rubocop-performance
- rubocop-rails
Rails:
Enabled: true
AllCops:
TargetRubyVersion: 2.4
TargetRailsVersion: 5.2
NewCops: enable
Metrics:
Enabled: false
Layout/LineLength:
Max: 140
Rails/ApplicationJob:
Enabled: false
Rails/ApplicationRecord:
Enabled: false
AllCops:
TargetRubyVersion: 2.1
Rails/CreateTableWithTimestamps:
Enabled: false
Metrics/LineLength:
Max: 140
Rails/HelperInstanceVariable:
Enabled: false
# Offense count: 34
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 60
Rails/SkipsModelValidations:
Enabled: false
# Offense count: 11
Metrics/CyclomaticComplexity:
Max: 13
Performance/ChainArrayAllocation:
Enabled: true
# Offense count: 10
Metrics/PerceivedComplexity:
Max: 14
Style/AutoResourceCleanup:
Enabled: true
# Offense count: 15
Metrics/AbcSize:
Max: 65
Metrics/ModuleLength:
Max: 300
Metrics/ClassLength:
Max: 300
Style/FrozenStringLiteralComment:
Enabled: false
Style/Documentation:
Enabled: false
Rails/HttpPositionalArguments:
Style/ExpandPathArguments:
Enabled: false
Metrics/BlockLength:
Max: 50
Style/HashTransformKeys:
Enabled: false
Style/HashTransformValues:
Enabled: false

3
.slim-lint.yml Normal file
View File

@@ -0,0 +1,3 @@
linters:
LineLength:
max: 140

163
.stylelintrc.json Normal file
View File

@@ -0,0 +1,163 @@
{
"rules": {
"at-rule-no-unknown": true,
"block-no-empty": true,
"color-no-invalid-hex": true,
"comment-no-empty": true,
"declaration-block-no-duplicate-properties": [
true,
{
"ignore": [
"consecutive-duplicates-with-different-values"
]
}
],
"declaration-block-no-redundant-longhand-properties": true,
"declaration-block-no-shorthand-property-overrides": true,
"font-family-no-duplicate-names": true,
"font-family-no-missing-generic-family-keyword": true,
"function-calc-no-unspaced-operator": true,
"function-linear-gradient-no-nonstandard-direction": true,
"keyframe-declaration-no-important": true,
"media-feature-name-no-unknown": true,
"no-descending-specificity": true,
"no-duplicate-at-import-rules": true,
"no-duplicate-selectors": true,
"no-empty-source": true,
"no-extra-semicolons": true,
"no-invalid-double-slash-comments": true,
"property-no-unknown": true,
"selector-pseudo-class-no-unknown": true,
"selector-pseudo-element-no-unknown": true,
"selector-type-no-unknown": true,
"string-no-newline": true,
"unit-no-unknown": true,
"at-rule-empty-line-before": [
"always",
{
"except": [
"blockless-after-same-name-blockless",
"first-nested"
],
"ignore": [
"after-comment"
]
}
],
"at-rule-name-case": "lower",
"at-rule-name-space-after": "always-single-line",
"at-rule-semicolon-newline-after": "always",
"block-closing-brace-empty-line-before": "never",
"block-closing-brace-newline-after": "always",
"block-closing-brace-newline-before": "always-multi-line",
"block-closing-brace-space-before": "always-single-line",
"block-opening-brace-newline-after": "always-multi-line",
"block-opening-brace-space-after": "always-single-line",
"block-opening-brace-space-before": "always",
"color-hex-case": "lower",
"color-hex-length": "short",
"comment-empty-line-before": [
"always",
{
"except": [
"first-nested"
],
"ignore": [
"stylelint-commands"
]
}
],
"comment-whitespace-inside": "always",
"custom-property-empty-line-before": [
"always",
{
"except": [
"after-custom-property",
"first-nested"
],
"ignore": [
"after-comment",
"inside-single-line-block"
]
}
],
"declaration-bang-space-after": "never",
"declaration-bang-space-before": "always",
"declaration-block-semicolon-newline-after": "always-multi-line",
"declaration-block-semicolon-space-after": "always-single-line",
"declaration-block-semicolon-space-before": "never",
"declaration-block-single-line-max-declarations": 1,
"declaration-block-trailing-semicolon": "always",
"declaration-colon-newline-after": "always-multi-line",
"declaration-colon-space-after": "always-single-line",
"declaration-colon-space-before": "never",
"declaration-empty-line-before": [
"always",
{
"except": [
"after-declaration",
"first-nested"
],
"ignore": [
"after-comment",
"inside-single-line-block"
]
}
],
"function-comma-newline-after": "always-multi-line",
"function-comma-space-after": "always-single-line",
"function-comma-space-before": "never",
"function-max-empty-lines": 0,
"function-name-case": "lower",
"function-parentheses-newline-inside": "always-multi-line",
"function-parentheses-space-inside": "never-single-line",
"function-whitespace-after": "always",
"indentation": 2,
"length-zero-no-unit": true,
"max-empty-lines": 1,
"media-feature-colon-space-after": "always",
"media-feature-colon-space-before": "never",
"media-feature-name-case": "lower",
"media-feature-parentheses-space-inside": "never",
"media-feature-range-operator-space-after": "always",
"media-feature-range-operator-space-before": "always",
"media-query-list-comma-newline-after": "always-multi-line",
"media-query-list-comma-space-after": "always-single-line",
"media-query-list-comma-space-before": "never",
"no-eol-whitespace": true,
"no-missing-end-of-source-newline": true,
"number-leading-zero": "always",
"number-no-trailing-zeros": true,
"property-case": "lower",
"rule-empty-line-before": [
"always-multi-line",
{
"except": [
"first-nested"
],
"ignore": [
"after-comment"
]
}
],
"selector-attribute-brackets-space-inside": "never",
"selector-attribute-operator-space-after": "never",
"selector-attribute-operator-space-before": "never",
"selector-combinator-space-after": "always",
"selector-combinator-space-before": "always",
"selector-descendant-combinator-no-non-space": true,
"selector-list-comma-newline-after": "always",
"selector-list-comma-space-before": "never",
"selector-max-empty-lines": 0,
"selector-pseudo-class-case": "lower",
"selector-pseudo-class-parentheses-space-inside": "never",
"selector-pseudo-element-case": "lower",
"selector-pseudo-element-colon-notation": "double",
"selector-type-case": "lower",
"unit-case": "lower",
"value-list-comma-newline-after": "always-multi-line",
"value-list-comma-space-after": "always-single-line",
"value-list-comma-space-before": "never",
"value-list-max-empty-lines": 0
}
}

47
.travis.yml Normal file
View File

@@ -0,0 +1,47 @@
language: ruby
os: linux
dist: xenial
rvm:
- 2.6.6
- 2.5.8
- 2.4.9
services:
- mysql
- postgresql
env:
- REDMINE_VER=4.0-stable DB=postgresql
- REDMINE_VER=master DB=postgresql
- REDMINE_VER=4.0-stable DB=mysql
- REDMINE_VER=master DB=mysql
notifications:
webhooks:
urls:
secure: "lwJzu9BU7AVhHnROzEA6agagwsqVAaTzgtvwTlw4CwSUv0ypNXNi9kjJUvOgSit3BnkSccC9xYlYNOYw5OOmsmjyUDU4/LUVqd0DRQjW3FXU9EFFPGQq9srJikHOHobfnutxGwMYFE4ftLI08PzsL7bYEg39Ps3pwwWsiIKnKKI0DPmdQH5PzC63jF/EByrLZsfqGHOirgXDnxmwgmrQ14vOpp3lHjgNgx9wNALpSgAztKeK1Wd8KayLYXweu+LQx9IwJfLqvk6hhWW15vjkIhvK7ooYSGXx+Hlwg3jyFSyX5jButUT4vwlWdJeAoNO/sWpdKXv4AifGXYsbcF/LMHCaaVgwBm/pe/YlK2LrqFlpm7MFuqyO1w4AnIA7rC8wZp/dUU5bJITZgN3sTAbLyTIbF8cbMfbDy3IWP8Oub7K/0ATUD7vNBVuyxfdGG61xOv/RDQhzrGwUArJ/xJfdU77MZkQUnaGb0vcwmRLIxyPdZWPz9ntzCbBxFblPWApCw+CWOeM3OuR6tdVqSVuZx3aG87TTzW+S9lLe8PJ5HYgA6+rPkc04zolJMftnFVlUl3LQIKvV2QkPSnr9bcePR5YSoJJKLBVofUsg/btVkQ1OxhWn53Td/nQp7u8qosmyQjCjMiP6Po1e9Enr89FY8Yxkw2dQba5sumQRbB39bj0="
on_success: change
on_failure: always
before_install:
- export PLUGIN_NAME=redmine_messenger
- export REDMINE_GIT_REPO=git://github.com/redmine/redmine.git
- export REDMINE_PATH=$HOME/redmine
- export BUNDLE_GEMFILE=$REDMINE_PATH/Gemfile
- export RAILS_ENV=test
- git clone $REDMINE_GIT_REPO $REDMINE_PATH
- cd $REDMINE_PATH
- if [[ "$REDMINE_VER" != "master" ]]; then git checkout -b $REDMINE_VER origin/$REDMINE_VER; fi
- if [[ "$REDMINE_VER" != "master" ]]; then cp $TRAVIS_BUILD_DIR/test/support/Gemfile.local $REDMINE_PATH; fi
- ln -s $TRAVIS_BUILD_DIR $REDMINE_PATH/plugins/$PLUGIN_NAME
- cp $TRAVIS_BUILD_DIR/test/support/additional_environment.rb $REDMINE_PATH/config/
- cp $TRAVIS_BUILD_DIR/test/support/database-$DB-travis.yml $REDMINE_PATH/config/database.yml
before_script:
- bundle exec rake db:create db:migrate redmine:plugins:migrate
script:
- if [[ "$REDMINE_VER" != "master" ]] && [[ "$DB" == "postgresql" ]]; then rubocop plugins/$PLUGIN_NAME; fi
- bundle exec rake redmine:plugins:test NAME=$PLUGIN_NAME RUBYOPT="-W0"
- bundle exec rake redmine:plugins:migrate NAME=$PLUGIN_NAME VERSION=0

View File

@@ -1,35 +1,96 @@
Changelog
=========
## 0.9.9
1.0.7
-----
- Added feature to send messages directly to users to be notified - thanks to @Ujifman
* All global messenger settings can be overwritten project based
* Locale support added
* Wiki added supported for notification
* Contact added/updated supported for notification (if redmine_contacts is installed)
* Password added/updated supported for notification (if redmine_passwords is installed)
* DB entry added/updated supported for notification (if redmine_db is installed)
* SSL verify can be disabled
* Lots of refactoring and code cleanups
* Swith from httpclient to net/http
* Fork of redmine_rocketchat, redmine_slack and redmine_mattermost (base functions for all three messenger)
1.0.6
-----
## v0.6.1
- Redmine 4 is required. Use git tag 1.0.5, if you use an older version.
- Redmine 4.1 support
- Fix problems with changed fields, description and notes
- Fix problems with quotes #38
- Redundant status and priority in messages #56
- Show attachments for new issues
- Show indicator for private comment on issue
- Ruby 2.4 or higher is required
- Fix project name with &
1.0.5
-----
- ruby 2.4.x or newer is required
1.0.4
-----
- Frensh translation added - thanks to @ZerooCool
1.0.3
-----
- Redmine 4 support
1.0.2
-----
- Bug fixed with issue urls, if Redmine is in subdirectory
- slim is used as template engine
- add private contacts, db and passwords support (if plugins are installed)
- Discord support added to documentation
1.0.1
-----
- Japanese translation has been added - thanks @Yoto
- Default mentions has been added - thanks @xstasi
1.0.0
-----
- Redmine 3.4.x compatibility
- Commit message issue bug fix
- Some code cleanups
0.9.9
-----
- All global messenger settings can be overwritten project based
- Locale support added
- Wiki added supported for notification
- Contact added/updated supported for notification (if redmine_contacts is installed)
- Password added/updated supported for notification (if redmine_passwords is installed)
- DB entry added/updated supported for notification (if redmine_db is installed)
- SSL verify can be disabled
- Lots of refactoring and code cleanups
- Swith from httpclient to net/http
- Fork of redmine_rocketchat, redmine_slack and redmine_mattermost (base functions for all three messenger)
v0.6.1
------
unknown changes
## v0.4
v0.4
----
unknown changes
## v0.3
v0.3
----
unknown changes
## v0.2
v0.2
----
unknown changes
## v0.1
v0.1
----
unknown changes

4
Gemfile Normal file
View File

@@ -0,0 +1,4 @@
source 'https://rubygems.org'
gem 'slim-rails'
gem 'validate_url'

View File

@@ -1,10 +1,12 @@
# Messenger plugin for Redmine
Messenger plugin for Redmine
============================
This plugin posts updates to issues in your Redmine installation to [Slack](https://slack.com/), [Rocket.Chat](https://rocket.chat/) or [Mattermost](https://about.mattermost.com/) channel.
This plugin posts updates to issues in your Redmine installation to [Slack](https://slack.com/), [Rocket.Chat](https://rocket.chat/), [Discord](https://discordapp.com/) or [Mattermost](https://about.mattermost.com/) channel.
[![Dependency Status](https://gemnasium.com/badges/github.com/AlphaNodes/redmine_messenger.svg)](https://gemnasium.com/github.com/AlphaNodes/redmine_messenger) ![Jenkins Build Status](https://pm.alphanodes.com/jenkins/buildStatus/icon?job=Devel-build-redmine-messenger)
[![Rate at redmine.org](https://img.shields.io/badge/rate%20at-redmine.org-blue.svg?style=fla)](https://www.redmine.org/plugins/redmine_messenger) [![Build Status](https://travis-ci.org/AlphaNodes/redmine_messenger.svg?branch=master)](https://travis-ci.org/AlphaNodes/redmine_messenger) ![Run RuboCop](https://github.com/AlphaNodes/redmine_messenger/workflows/Run%20RuboCop/badge.svg) ![Run Tests](https://github.com/AlphaNodes/redmine_messenger/workflows/Run%20Tests/badge.svg)
## Features
Features
--------
* Post information to messenger channel
* post issue updates
@@ -15,11 +17,13 @@ This plugin posts updates to issues in your Redmine installation to [Slack](http
* post db entry (if redmine_db is installed) updates
* post password (if redmine_passwords is installed) updates
* post contact (if redmine_contacts is installed) updates
* Post information directly to users to be notified (users names should be the same in Redmine and chat). Tested with Rocket.Chat
* overwrite messenger settings at project level
* parent project support (inherit messenger settings from parent project)
* multiple channel support (define one or more channels to deliver note)
## Screenshot
Screenshot
----------
Mattermost output:
@@ -29,7 +33,24 @@ Redmine configuration:
![screenshot](https://raw.githubusercontent.com/alphanodes/redmine_messenger/master/assets/images/screenshot_redmine_settings.png)
## Prepare your messenger service
* **Convert names to mentions:** Automatically converts Redmine mentions into Slack mentions so a user is notified through Slack when mentioned in a Redmine note. Depends on Redmine Mentions plugin.
* **Display watchers:** Issue watchers are included in notifications.
* **Post issue updates:** All newly created notes on an issue generate a notification (does not include private issues).
* **Description in new issue:** Include the text description of a new issue in the notification.
* **Description in update issue:** Include the text encompassed in a note upon updating the issue in the notification.
* **Post updates for private issue:** Same as *Post issue updates* but for private issues.
* **Post private notes:** Same as *Description in update issue* but for private issues.
* **Post wiki updates:** Generates a notification when a projects Wiki is updated.
Prepare your messenger service
------------------------------
### Slack
@@ -39,25 +60,35 @@ Go to Slack documentation [Incoming Webhooks](https://api.slack.com/incoming-web
Go to Mattermost documentation [Incoming Webhooks](https://docs.mattermost.com/developer/webhooks-incoming.html) for more information to set up Incoming WebHook
### Discord
Go to Discord documentation [Intro to Webhooks ](https://support.discordapp.com/hc/en-us/articles/228383668) for more information to set up Incoming WebHook
You have to add /slack after your webhook url.
### Rocket.Chat
Go to Rocket.Chat documentation [Incoming WebHook Scripting](https://rocket.chat/docs/administrator-guides/integrations/) for more information to set up Incoming WebHook
## Requirements
Requirements
------------
* Redmine version >= 3.0.0
* Ruby version >= 2.1.5
* Redmine version >= 4.0.0
* Ruby version >= 2.4.0
If you want to use it with Redmine 3.x, use git tag 1.0.5
## Installation
Installation
------------
Install ``redmine_messenger`` plugin for `Redmine`
cd $REDMINE_ROOT
git clone git://github.com/alphanodes/redmine_messenger.git plugins/redmine_messenger
bundle exec rake db:migrate_plugins
git clone https://github.com/AlphaNodes/redmine_messenger.git plugins/redmine_messenger
bundle update
bundle exec rake redmine:plugins:migrate RAILS_ENV=production
Make sure that the directory is named `redmine_messenger` (you cannot use another name for it)!
Restart Redmine (application server) and you should see the plugin show up in the Plugins page.
Under the configuration options, set the Messenger API URL to the URL for an
Incoming WebHook integration in your Messenger account and also set the Messenger
@@ -66,18 +97,20 @@ visible to users, you can find each channel's handle by navigating inside the ch
and clicking the down-arrow and selecting view info).
## Uninstall
Uninstall
---------
Uninstall ``redmine_messenger``
cd $REDMINE_ROOT
bundle exec rake db:migrate_plugins NAME=redmine_messenger VERSION=0
bundle exec rake redmine:plugins:migrate NAME=redmine_messenger VERSION=0 RAILS_ENV=production
rm -rf plugins/redmine_messenger
Restart Redmine (application server)
## Credits
Credits
-------
The source code is forked from

View File

@@ -1,35 +1,47 @@
# Redmine Messenger plugin for Redmine
class MessengerSettingsController < ApplicationController
layout 'base'
before_action :find_project_by_project_id
before_action :authorize
before_action :find_project, :authorize, :find_user
def save
def update
setting = MessengerSetting.find_or_create @project.id
begin
setting.transaction do
# setting.auto_preview_enabled = auto_preview_enabled
setting.assign_attributes(params[:setting])
setting.save!
if setting.update allowed_params
flash[:notice] = l :notice_successful_update
redirect_to settings_project_path(@project, tab: 'messenger')
else
flash[:error] = setting.errors.full_messages.flatten.join("\n")
respond_to do |format|
format.html { redirect_back_or_default(settings_project_path(@project, tab: 'messenger')) }
format.api { render_validation_errors(setting) }
end
flash[:notice] = l(:notice_successful_update)
rescue => e
flash[:error] = 'Updating failed.' + e.message
end
redirect_to controller: 'projects', action: 'settings', id: @project, tab: 'messenger'
end
private
def find_project
@project = Project.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
def find_user
@user = User.current
def allowed_params
params.require(:setting).permit :messenger_url,
:messenger_icon,
:messenger_channel,
:messenger_username,
:messenger_verify_ssl,
:messenger_direct_users_messages,
:auto_mentions,
:default_mentions,
:display_watchers,
:post_updates,
:new_include_description,
:updated_include_description,
:post_private_issues,
:post_private_notes,
:post_wiki,
:post_wiki_updates,
:post_db,
:post_db_updates,
:post_private_db,
:post_contact,
:post_contact_updates,
:post_private_contacts,
:post_password,
:post_password_updates
end
end

View File

@@ -0,0 +1,14 @@
module MessengerProjectsHelper
def project_settings_tabs
tabs = super
if User.current.allowed_to?(:manage_messenger, @project)
tabs << { name: 'messenger',
action: :show,
partial: 'messenger_settings/show',
label: :label_messenger }
end
tabs
end
end

View File

@@ -1,234 +1,312 @@
# Redmine Messenger plugin for Redmine
require 'net/http'
require 'uri'
class Messenger
include Redmine::I18n
def self.speak(msg, channels, url, options)
url = RedmineMessenger.settings[:messenger_url] unless url
class << self
def markup_format(text)
# TODO: output format should be markdown, but at the moment there is no
# solution without using pandoc (http://pandoc.org/), which requires
# packages on os level
#
# Redmine::WikiFormatting.html_parser.to_text(text)
return if url.blank?
return if channels.blank?
text = +text.to_s
params = {
text: msg,
link_names: 1
}
# @see https://api.slack.com/reference/surfaces/formatting#escaping
username = Messenger.textfield_for_project(options[:project], :messenger_username)
params[:username] = username if username.present?
params[:attachments] = [options[:attachment]] if options[:attachment] && options[:attachment].any?
text.gsub!('&', '&amp;')
text.gsub!('<', '&lt;')
text.gsub!('>', '&gt;')
icon = Messenger.textfield_for_project(options[:project], :messenger_icon)
if icon.present?
if icon.start_with? ':'
params[:icon_emoji] = icon
else
params[:icon_url] = icon
end
text
end
channels.each do |channel|
uri = URI(url)
params[:channel] = channel
http_options = { use_ssl: uri.scheme == 'https' }
if RedmineMessenger.settings[:messenger_verify_ssl] != 1
http_options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
end
def default_url_options
{ only_path: true, script_name: Redmine::Utils.relative_url_root }
end
begin
req = Net::HTTP::Post.new(uri)
req.set_form_data(payload: params.to_json)
Net::HTTP.start(uri.hostname, uri.port, http_options) do |http|
response = http.request(req)
unless [Net::HTTPSuccess, Net::HTTPRedirection, Net::HTTPOK].include? response
Rails.logger.warn(response)
end
def speak(msg, channels, url, options)
url ||= RedmineMessenger.settings[:messenger_url]
return if url.blank? || channels.blank?
params = { text: msg, link_names: 1 }
username = textfield_for_project(options[:project], :messenger_username)
params[:username] = username if username.present?
params[:attachments] = options[:attachment]&.any? ? [options[:attachment]] : []
icon = textfield_for_project options[:project], :messenger_icon
if icon.present?
if icon.start_with? ':'
params[:icon_emoji] = icon
else
params[:icon_url] = icon
end
end
channels.each do |channel|
uri = URI(url)
params[:channel] = channel
http_options = { use_ssl: uri.scheme == 'https' }
http_options[:verify_mode] = OpenSSL::SSL::VERIFY_NONE unless RedmineMessenger.setting?(:messenger_verify_ssl)
begin
req = Net::HTTP::Post.new uri
req.set_form_data payload: params.to_json
Net::HTTP.start(uri.hostname, uri.port, http_options) do |http|
response = http.request req
Rails.logger.warn(response.inspect) unless [Net::HTTPSuccess, Net::HTTPRedirection, Net::HTTPOK].include? response
end
rescue StandardError => e
Rails.logger.warn "cannot connect to #{url}"
Rails.logger.warn e
end
rescue StandardError => e
Rails.logger.warn("cannot connect to #{url}")
Rails.logger.warn(e)
end
end
end
def self.object_url(obj)
if Setting.host_name.to_s =~ %r{/\A(https?\:\/\/)?(.+?)(\:(\d+))?(\/.+)?\z/i}
host = Regexp.last_match(2)
port = Regexp.last_match(4)
prefix = Regexp.last_match(5)
Rails.application.routes.url_for(obj.event_url(host: host, protocol: Setting.protocol, port: port, script_name: prefix))
else
Rails.application.routes.url_for(obj.event_url(host: Setting.host_name, protocol: Setting.protocol))
def object_url(obj)
if Setting.host_name.to_s =~ %r{\A(https?://)?(.+?)(:(\d+))?(/.+)?\z}i
host = Regexp.last_match 2
port = Regexp.last_match 4
prefix = Regexp.last_match 5
Rails.application.routes.url_for(obj.event_url(host: host, protocol: Setting.protocol, port: port, script_name: prefix))
else
Rails.application.routes.url_for(obj.event_url(host: Setting.host_name, protocol: Setting.protocol, script_name: ''))
end
end
end
def self.url_for_project(proj)
return if proj.blank?
# project based
pm = MessengerSetting.find_by(project_id: proj.id)
return pm.messenger_url if !pm.nil? && pm.messenger_url.present?
# parent project based
parent_url = url_for_project(proj.parent)
return parent_url if parent_url.present?
# system based
return RedmineMessenger.settings[:messenger_url] if RedmineMessenger.settings[:messenger_url].present?
nil
end
def url_for_project(proj)
return if proj.blank?
def self.textfield_for_project(proj, config)
return if proj.blank?
# project based
pm = MessengerSetting.find_by(project_id: proj.id)
return pm.send(config) if !pm.nil? && pm.send(config).present?
default_textfield(proj, config)
end
# project based
pm = MessengerSetting.find_by project_id: proj.id
return pm.messenger_url if !pm.nil? && pm.messenger_url.present?
def self.default_textfield(proj, config)
# parent project based
parent_field = textfield_for_project(proj.parent, config)
return parent_field if parent_field.present?
if RedmineMessenger.settings[config].present?
return RedmineMessenger.settings[config]
# parent project based
parent_url = url_for_project proj.parent
return parent_url if parent_url.present?
# system based
return RedmineMessenger.settings[:messenger_url] if RedmineMessenger.settings[:messenger_url].present?
nil
end
''
end
def self.channels_for_project(proj)
return [] if proj.blank?
# project based
pm = MessengerSetting.find_by(project_id: proj.id)
if !pm.nil? && pm.messenger_channel.present?
return [] if pm.messenger_channel == '-'
return pm.messenger_channel.split(',').map(&:strip).uniq
def project_url_markdown(project)
"[#{project.name}](#{object_url project})"
end
default_project_channels(proj)
end
def self.default_project_channels(proj)
# parent project based
parent_channel = channels_for_project(proj.parent)
return parent_channel if parent_channel.present?
# system based
if RedmineMessenger.settings[:messenger_channel].present? &&
RedmineMessenger.settings[:messenger_channel] != '-'
return RedmineMessenger.settings[:messenger_channel].split(',').map(&:strip).uniq
def url_markdown(obj, name)
"[#{name}](#{object_url obj})"
end
[]
end
def self.setting_for_project(proj, config)
return false if proj.blank?
@setting_found = 0
# project based
pm = MessengerSetting.find_by(project_id: proj.id)
unless pm.nil? || pm.send(config).zero?
@setting_found = 1
return false if pm.send(config) == 1
return true if pm.send(config) == 2
# 0 = use system based settings
def textfield_for_project(proj, config)
return if proj.blank?
# project based
pm = MessengerSetting.find_by project_id: proj.id
return pm.send(config) if !pm.nil? && pm.send(config).present?
default_textfield proj, config
end
default_project_setting(proj, config)
end
def self.default_project_setting(proj, config)
if proj.present? && proj.parent.present?
parent_setting = setting_for_project(proj.parent, config)
return parent_setting if @setting_found == 1
def default_textfield(proj, config)
# parent project based
parent_field = textfield_for_project proj.parent, config
return parent_field if parent_field.present?
return RedmineMessenger.settings[config] if RedmineMessenger.settings[config].present?
''
end
# system based
return true if RedmineMessenger.settings[config].present? && RedmineMessenger.settings[config] == '1'
false
end
def self.detail_to_field(detail)
field_format = nil
key = nil
escape = true
def channels_for_project(proj)
return [] if proj.blank?
if detail.property == 'cf'
key = CustomField.find(detail.prop_key).name rescue nil
title = key
field_format = CustomField.find(detail.prop_key).field_format rescue nil
elsif detail.property == 'attachment'
key = 'attachment'
title = I18n.t :label_attachment
else
key = detail.prop_key.to_s.sub('_id', '')
title = if key == 'parent'
I18n.t "field_#{key}_issue"
# project based
pm = MessengerSetting.find_by(project_id: proj.id)
if !pm.nil? && pm.messenger_channel.present?
return [] if pm.messenger_channel == '-'
return pm.messenger_channel.split(',').map!(&:strip).uniq
end
default_project_channels proj
end
def setting_for_project(proj, config)
return false if proj.blank?
@setting_found = 0
# project based
pm = MessengerSetting.find_by(project_id: proj.id)
unless pm.nil? || pm.send(config).zero?
@setting_found = 1
return false if pm.send(config) == 1
return true if pm.send(config) == 2
# 0 = use system based settings
end
default_project_setting(proj, config)
end
def default_project_setting(proj, config)
if proj.present? && proj.parent.present?
parent_setting = setting_for_project proj.parent, config
return parent_setting if @setting_found == 1
end
# system based
return true if RedmineMessenger.settings[config].present? && RedmineMessenger.setting?(config)
false
end
def attachment_text_from_journal(journal)
obj = journal.details.detect { |j| j.prop_key == 'description' && j.property == 'attr' }
text = obj.value if obj.present?
if journal.notes.present?
if text.present?
text << "\n\n*#{l :label_comment}*\n"
text << journal.notes
else
text = journal.notes
end
end
text.present? ? markup_format(text) : nil
end
def detail_to_field(detail, prj = nil)
field_format = nil
key = nil
escape = true
value = detail.value.to_s
if detail.property == 'cf'
key = CustomField.find(detail.prop_key)&.name
unless key.nil?
title = key
field_format = CustomField.find(detail.prop_key)&.field_format
value = IssuesController.helpers.format_value(detail.value, detail.custom_field) if detail.value.present?
end
elsif detail.property == 'attachment'
key = 'attachment'
title = I18n.t :label_attachment
value = detail.value.to_s
elsif detail.property == 'attr' &&
detail.prop_key == 'db_relation'
return { short: true } unless setting_for_project(prj, :post_db)
title = I18n.t :field_db_relation
if detail.value.present?
entry = DbEntry.visible.find_by id: detail.value
value = entry.present? ? entry.name : detail.value.to_s
end
elsif detail.property == 'attr' &&
detail.prop_key == 'password_relation'
return { short: true } unless setting_for_project(prj, :post_password)
title = I18n.t :field_password_relation
if detail.value.present?
entry = Password.visible.find_by id: detail.value
value = entry.present? ? entry.name : detail.value.to_s
end
else
key = detail.prop_key.to_s.sub('_id', '')
title = if key == 'parent'
I18n.t "field_#{key}_issue"
else
I18n.t "field_#{key}"
end
value = detail.value.to_s
end
short = true
case key
when 'title', 'subject'
short = false
when 'description'
return
when 'tracker'
value = object_field_value Tracker, detail.value
when 'estimated_hours'
value = format_hours(value.is_a?(String) ? (value.to_hours || value) : value)
when 'project'
value = object_field_value Project, detail.value
when 'status'
value = object_field_value IssueStatus, detail.value
when 'priority'
value = object_field_value IssuePriority, detail.value
when 'category'
value = object_field_value IssueCategory, detail.value
when 'assigned_to'
value = object_field_value User, detail.value
when 'fixed_version'
value = object_field_value Version, detail.value
when 'attachment'
attachment = Attachment.find(detail.prop_key)
value = if attachment.present?
escape = false
"<#{object_url attachment}|#{markup_format attachment.filename}>"
else
detail.prop_key.to_s
end
when 'parent'
issue = Issue.find detail.value
value = if issue.present?
escape = false
"<#{object_url issue}|#{markup_format issue}>"
else
detail.value.to_s
end
end
value = object_field_value(Version, detail.value) if detail.property == 'cf' && field_format == 'version'
value = if value.present?
if escape
markup_format value
else
value
end
else
I18n.t "field_#{key}"
'-'
end
result = { title: title, value: value }
result[:short] = true if short
result
end
short = true
value = detail.value.to_s
case key
when 'title', 'subject', 'description'
short = false
when 'tracker'
tracker = Tracker.find(detail.value)
value = tracker.to_s if tracker.present?
when 'project'
project = Project.find(detail.value)
value = project.to_s if project.present?
when 'status'
status = IssueStatus.find(detail.value)
value = status.to_s if status.present?
when 'priority'
priority = IssuePriority.find(detail.value)
value = priority.to_s if priority.present?
when 'category'
category = IssueCategory.find(detail.value)
value = category.to_s if category.present?
when 'assigned_to'
user = User.find(detail.value)
value = user.to_s if user.present?
when 'fixed_version'
fixed_version = Version.find(detail.value)
value = fixed_version.to_s if fixed_version.present?
when 'attachment'
attachment = Attachment.find(detail.prop_key)
value = "<#{Messenger.object_url attachment}|#{ERB::Util.html_escape(attachment.filename)}>" if attachment.present?
escape = false
when 'parent'
issue = Issue.find(detail.value)
value = "<#{Messenger.object_url issue}|#{ERB::Util.html_escape(issue)}>" if issue.present?
escape = false
def mentions(project, text)
names = []
textfield_for_project(project, :default_mentions).split(',').each { |m| names.push m.strip }
names += extract_usernames(text) unless text.nil?
names.present? ? " To: #{names.uniq.join ', '}" : nil
end
if detail.property == 'cf' && field_format == 'version'
version = Version.find(detail.value)
value = version.to_s if version.present?
private
def object_field_value(klass, id)
obj = klass.find_by id: id
obj.nil? ? id.to_s : obj.to_s
end
value = if value.present?
if escape
ERB::Util.html_escape(value)
else
value
end
else
'-'
end
def extract_usernames(text)
text = '' if text.nil?
# messenger usernames may only contain lowercase letters, numbers,
# dashes, dots and underscores and must start with a letter or number.
text.scan(/@[a-z0-9][a-z0-9_\-.]*/).uniq
end
result = { title: title, value: value }
result[:short] = true if short
result
end
def default_project_channels(proj)
# parent project based
parent_channel = channels_for_project proj.parent
return parent_channel if parent_channel.present?
# system based
if RedmineMessenger.settings[:messenger_channel].present? &&
RedmineMessenger.settings[:messenger_channel] != '-'
return RedmineMessenger.settings[:messenger_channel].split(',').map!(&:strip).uniq
end
def self.mentions(text)
return nil if text.nil?
names = extract_usernames(text)
names.present? ? '\nTo: ' + names.join(', ') : nil
end
def self.extract_usernames(text)
text = '' if text.nil?
# messenger usernames may only contain lowercase letters, numbers,
# dashes, dots and underscores and must start with a letter or number.
text.scan(/@[a-z0-9][a-z0-9_\-.]*/).uniq
[]
end
end
end

View File

@@ -1,55 +1,10 @@
# Redmine Messenger plugin for Redmine
class MessengerSetting < ActiveRecord::Base
include Redmine::SafeAttributes
belongs_to :project
validates :project_id, presence: true
safe_attributes 'messenger_url',
'messenger_icon',
'messenger_channel',
'messenger_username',
'messenger_verify_ssl',
'auto_mentions',
'display_watchers',
'post_updates',
'new_include_description',
'updated_include_description',
'post_private_issues',
'post_private_notes',
'post_wiki',
'post_wiki_updates',
'post_db',
'post_db_updates',
'post_contact',
'post_contact_updates',
'post_password',
'post_password_updates'
attr_accessible :messenger_url,
:messenger_icon,
:messenger_channel,
:messenger_username,
:messenger_verify_ssl,
:auto_mentions,
:display_watchers,
:post_updates,
:new_include_description,
:updated_include_description,
:post_private_issues,
:post_private_notes,
:post_wiki,
:post_wiki_updates,
:post_db,
:post_db_updates,
:post_contact,
:post_contact_updates,
:post_password,
:post_password_updates
validates :messenger_url, url: { allow_blank: true, message: l(:error_messenger_invalid_url) }
def self.find_or_create(p_id)
setting = MessengerSetting.find_by(project_id: p_id)
setting = MessengerSetting.find_by project_id: p_id
unless setting
setting = MessengerSetting.new
setting.project_id = p_id

View File

@@ -1,4 +0,0 @@
<p>
<%= f.select mf, project_messenger_options(@messenger_setting.send(mf)), label: l("label_settings_#{mf}") %>
<em class="info" style="display: inline;"><%= l(:label_default) %>: <%= project_setting_messenger_default_value(mf) %></em>
</p>

View File

@@ -0,0 +1,7 @@
p
= f.select mf, project_messenger_options(@messenger_setting.send(mf)), label: l("label_settings_#{mf}")
'
em.info[style="display: inline;"]
= l(:label_default)
' :
= project_setting_messenger_default_value(mf)

View File

@@ -1,4 +0,0 @@
<p>
<%= f.text_field mf, size: size, label: l("label_settings_#{mf}") %>
<em class="info"><%= l(:label_messenger_project_text_field_info) %> (<%= l(:label_default) %>: <%= Messenger.default_textfield(@project, mf) %>)</em>
</p>

View File

@@ -0,0 +1,9 @@
p
= f.text_field mf, size: size, label: l("label_settings_#{mf}")
em.info
= l(:label_messenger_project_text_field_info)
| (
= l(:label_default)
' :
= Messenger.default_textfield(@project, mf)
| )

View File

@@ -1,74 +0,0 @@
<div class="box tabular messenger_settings">
<%
@messenger_setting = MessengerSetting.find_or_create(@project.id)
%>
<%= labelled_form_for :setting, @messenger_setting,
url: { controller: 'messenger_settings',
action: 'save', id: @project, tab: 'messenger',
partial: 'messenger_settings/save',
setting_id: @messenger_setting.id } do |f| %>
<%= error_messages_for 'messenger_setting' %>
<div class="box">
<div class="info"><%= t(:messenger_settings_project_intro) %></div><br />
<p><%= f.text_field :messenger_url, size: 60, label: l(:label_settings_messenger_url) %><em class="info"><%= l(:label_messenger_project_text_field_info) %> (<%= l(:label_messenger_default_not_visible) %>)</em></p>
<%= render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :messenger_icon, size: 60 } %>
<%= render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :messenger_channel, size: 30 } %>
<%= render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :messenger_username, size: 30 } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :messenger_verify_ssl } %>
<br />
<h3><%= l(:label_issue_plural) %></h3>
<div class="info"><%= t(:messenger_issue_intro) %></div><br />
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :auto_mentions } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :display_watchers } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_updates } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :new_include_description } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :updated_include_description } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_issues } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_notes } %>
<br />
<h3><%= l(:label_wiki) %></h3>
<div class="info"><%= t(:messenger_wiki_intro) %></div><br />
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_wiki } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_wiki_updates } %>
<% if RedmineMessenger::REDMINE_DB_SUPPORT && User.current.allowed_to?(:view_db_entries, @project) %>
<br />
<h3><%= l(:label_db_entry_plural) %></h3>
<div class="info"><%= t(:messenger_db_intro) %></div><br />
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_db } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_db_updates } %>
<% end %>
<% if RedmineMessenger::REDMINE_CONTACTS_SUPPORT && User.current.allowed_to?(:view_contacts, @project) %>
<br />
<h3><%= l(:label_contact_plural) %></h3>
<div class="info"><%= t(:messenger_contacts_intro) %></div><br />
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_contact } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_contact_updates } %>
<% end %>
<% if Redmine::Plugin.installed?('redmine_passwords') && User.current.allowed_to?(:view_passwords, @project) %>
<br />
<h3><%= l(:label_settings_post_password) %></h3>
<div class="info"><%= t(:messenger_passwords_intro) %></div><br />
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_password } %>
<%= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_password_updates } %>
<% end %>
</div>
<%= submit_tag l(:button_save) %>
<% end %>
</div>

View File

@@ -0,0 +1,78 @@
= error_messages_for 'messenger_setting'
- @messenger_setting = MessengerSetting.find_or_create(@project.id)
= labelled_form_for :setting,
@messenger_setting,
url: project_messenger_setting_path(project_id: @project),
method: :put,
class: 'tabular' do |f|
fieldset#messenger_settings.box.tabular
legend = l(:label_messenger_outgoing_webhook)
- if User.current.admin?
.contextual
= link_to l(:label_administration), plugin_settings_path(id: 'redmine_messenger'), class: 'icon icon-settings'
.info = t(:messenger_settings_project_intro)
br
p
= f.text_field :messenger_url, size: 60, label: l(:label_settings_messenger_url)
em.info
= l(:label_messenger_project_text_field_info)
| (
= l(:label_messenger_default_not_visible)
| )
= render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :messenger_icon, size: 60 }
= render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :messenger_channel, size: 30 }
= render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :messenger_username, size: 30 }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :messenger_verify_ssl }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :messenger_direct_users_messages }
fieldset#messenger_settings.box.tabular
legend = l(:label_issue_plural)
.info = t(:messenger_issue_intro)
br
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :auto_mentions }
= render partial: 'messenger_settings/messenger_text', locals: { f: f, mf: :default_mentions, size: 30 }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :display_watchers }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_updates }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :new_include_description }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :updated_include_description }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_issues }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_notes }
fieldset#messenger_settings.box.tabular
legend = l(:label_wiki)
.info = t(:messenger_wiki_intro)
br
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_wiki }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_wiki_updates }
- if RedmineMessenger::REDMINE_DB_SUPPORT && User.current.allowed_to?(:view_db_entries, @project)
fieldset#messenger_settings.box.tabular
legend = l(:field_db_entries)
.info = t(:messenger_db_intro)
br
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_db }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_db_updates }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_db }
- if RedmineMessenger::REDMINE_CONTACTS_SUPPORT && User.current.allowed_to?(:view_contacts, @project)
fieldset#messenger_settings.box.tabular
legend = l(:label_contact_plural)
.info = t(:messenger_contacts_intro)
br
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_contact }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_contact_updates }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_private_contacts }
- if Redmine::Plugin.installed?('redmine_passwords') && User.current.allowed_to?(:view_passwords, @project)
fieldset#messenger_settings.box.tabular
legend = l(:field_passwords)
.info = t(:messenger_passwords_intro)
br
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_password }
= render partial: 'messenger_settings/messenger_select', locals: { f: f, mf: :post_password_updates }
= submit_tag l(:button_save)

View File

@@ -1,126 +0,0 @@
<div class="info"><%= t(:messenger_settings_intro) %></div><br />
<p>
<%= content_tag(:label, l(:label_settings_messenger_url)) %>
<%= text_field_tag('settings[messenger_url]', @settings[:messenger_url], size: 60, placeholder: 'https://rocket.chat/hooks/my_rocket_chat_token') %>
<em class="info"><%= t(:messenger_url_info_html) %></em>
</p>
<p>
<%= content_tag(:label, l(:label_settings_messenger_icon)) %>
<%= text_field_tag('settings[messenger_icon]', @settings[:messenger_icon], size: 60) %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_messenger_channel)) %>
<%= text_field_tag('settings[messenger_channel]', @settings[:messenger_channel], size: 30, placeholder: 'redmine') %>
<em class="info"><%= t(:messenger_channel_info_html) %></em>
</p>
<p>
<%= content_tag(:label, l(:label_settings_messenger_username)) %>
<%= text_field_tag('settings[messenger_username]', @settings[:messenger_username], size: 30) %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_messenger_verify_ssl)) %>
<%= check_box_tag 'settings[messenger_verify_ssl]', 1, @settings[:messenger_verify_ssl] %>
<em class="info"><%= t(:messenger_verify_ssl_info_html) %></em>
</p>
<br />
<h3><%= l(:label_issue_plural) %></h3>
<div class="info"><%= t(:messenger_issue_intro) %></div><br />
<p>
<%= content_tag(:label, l(:label_settings_auto_mentions)) %>
<%= check_box_tag 'settings[auto_mentions]', 1, @settings[:auto_mentions] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_display_watchers)) %>
<%= check_box_tag 'settings[display_watchers]', 1, @settings[:display_watchers] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_post_updates)) %>
<%= check_box_tag 'settings[post_updates]', 1, @settings[:post_updates] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_new_include_description)) %>
<%= check_box_tag 'settings[new_include_description]', 1, @settings[:new_include_description] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_updated_include_description)) %>
<%= check_box_tag 'settings[updated_include_description]', 1, @settings[:updated_include_description] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_post_private_issues)) %>
<%= check_box_tag 'settings[post_private_issues]', 1, @settings[:post_private_issues] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_post_private_notes)) %>
<%= check_box_tag 'settings[post_private_notes]', 1, @settings[:post_private_notes] %>
</p>
<br />
<h3><%= l(:label_wiki) %></h3>
<div class="info"><%= t(:messenger_wiki_intro) %></div><br />
<p>
<%= content_tag(:label, l(:label_settings_post_wiki)) %>
<%= check_box_tag 'settings[post_wiki]', 1, @settings[:post_wiki] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_post_wiki_updates)) %>
<%= check_box_tag 'settings[post_wiki_updates]', 1, @settings[:post_wiki_updates] %>
</p>
<% if RedmineMessenger::REDMINE_DB_SUPPORT %>
<br />
<h3><%= l(:label_db_entry_plural) %></h3>
<div class="info"><%= t(:messenger_db_intro) %></div><br />
<p>
<%= content_tag(:label, l(:label_settings_post_db)) %>
<%= check_box_tag 'settings[post_db]', 1, @settings[:post_db] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_post_db_updates)) %>
<%= check_box_tag 'settings[post_db_updates]', 1, @settings[:post_db_updates] %>
</p>
<% end %>
<% if RedmineMessenger::REDMINE_CONTACTS_SUPPORT %>
<br />
<h3><%= l(:label_contact_plural) %></h3>
<div class="info"><%= t(:messenger_contacts_intro) %></div><br />
<p>
<%= content_tag(:label, l(:label_settings_post_contact)) %>
<%= check_box_tag 'settings[post_contact]', 1, @settings[:post_contact] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_post_contact_updates)) %>
<%= check_box_tag 'settings[post_contact_updates]', 1, @settings[:post_contact_updates] %>
</p>
<% end %>
<% if Redmine::Plugin.installed?('redmine_passwords') %>
<br />
<h3><%= l(:label_password_plural) %></h3>
<div class="info"><%= t(:messenger_passwords_intro) %></div><br />
<p>
<%= content_tag(:label, l(:label_settings_post_password)) %>
<%= check_box_tag 'settings[post_password]', 1, @settings[:post_password] %>
</p>
<p>
<%= content_tag(:label, l(:label_settings_post_password_updates)) %>
<%= check_box_tag 'settings[post_password_updates]', 1, @settings[:post_password_updates] %>
</p>
<% end %>

View File

@@ -0,0 +1,110 @@
.info = t(:messenger_settings_intro)
br
fieldset#messenger_settings.box.tabular
legend = l(:label_messenger_outgoing_webhook)
p
= tag.label l(:label_settings_messenger_url)
= text_field_tag('settings[messenger_url]', @settings[:messenger_url], size: 60, placeholder: 'https://webhook.url')
em.info = t(:messenger_url_info_html)
p
= tag.label l(:label_settings_messenger_icon)
= text_field_tag('settings[messenger_icon]', @settings[:messenger_icon], size: 60)
p
= tag.label l(:label_settings_messenger_channel)
= text_field_tag('settings[messenger_channel]', @settings[:messenger_channel], size: 30, placeholder: 'redmine')
em.info = t(:messenger_channel_info_html)
p
= tag.label l(:label_settings_messenger_username)
= text_field_tag('settings[messenger_username]', @settings[:messenger_username], size: 30)
p
= tag.label l(:label_settings_messenger_verify_ssl)
= check_box_tag 'settings[messenger_verify_ssl]', 1, @settings[:messenger_verify_ssl].to_i == 1
em.info = t(:messenger_verify_ssl_info_html)
p
= tag.label l(:label_settings_messenger_direct_users_messages)
= check_box_tag 'settings[messenger_direct_users_messages]', 1, @settings[:messenger_direct_users_messages].to_i == 1
em.info = t(:messenger_direct_users_messages_info_html)
fieldset#messenger_settings.box.tabular
legend = l(:label_issue_plural)
.info = t(:messenger_issue_intro)
br
p
= tag.label l(:label_settings_auto_mentions)
= check_box_tag 'settings[auto_mentions]', 1, @settings[:auto_mentions].to_i == 1
p
= tag.label l(:label_settings_default_mentions)
= text_field_tag('settings[default_mentions]', @settings[:default_mentions], size: 30)
em.info = t(:default_mentionsl_info)
p
= tag.label l(:label_settings_display_watchers)
= check_box_tag 'settings[display_watchers]', 1, @settings[:display_watchers].to_i == 1
p
= tag.label l(:label_settings_post_updates)
= check_box_tag 'settings[post_updates]', 1, @settings[:post_updates].to_i == 1
p
= tag.label l(:label_settings_new_include_description)
= check_box_tag 'settings[new_include_description]', 1, @settings[:new_include_description].to_i == 1
p
= tag.label l(:label_settings_updated_include_description)
= check_box_tag 'settings[updated_include_description]', 1, @settings[:updated_include_description].to_i == 1
p
= tag.label l(:label_settings_post_private_issues)
= check_box_tag 'settings[post_private_issues]', 1, @settings[:post_private_issues].to_i == 1
p
= tag.label l(:label_settings_post_private_notes)
= check_box_tag 'settings[post_private_notes]', 1, @settings[:post_private_notes].to_i == 1
fieldset#messenger_settings.box.tabular
legend = l(:label_wiki)
.info = t(:messenger_wiki_intro)
br
p
= tag.label l(:label_settings_post_wiki)
= check_box_tag 'settings[post_wiki]', 1, @settings[:post_wiki].to_i == 1
p
= tag.label l(:label_settings_post_wiki_updates)
= check_box_tag 'settings[post_wiki_updates]', 1, @settings[:post_wiki_updates].to_i == 1
- if RedmineMessenger::REDMINE_DB_SUPPORT
fieldset#messenger_settings.box.tabular
legend = l(:field_db_entries)
.info = t(:messenger_db_intro)
br
p
= tag.label l(:label_settings_post_db)
= check_box_tag 'settings[post_db]', 1, @settings[:post_db].to_i == 1
p
= tag.label l(:label_settings_post_db_updates)
= check_box_tag 'settings[post_db_updates]', 1, @settings[:post_db_updates].to_i == 1
p
= tag.label l(:label_settings_post_private_db)
= check_box_tag 'settings[post_private_db]', 1, @settings[:post_private_db].to_i == 1
- if RedmineMessenger::REDMINE_CONTACTS_SUPPORT
fieldset#messenger_settings.box.tabular
legend = l(:label_contact_plural)
.info = t(:messenger_contacts_intro)
br
p
= tag.label l(:label_settings_post_contact)
= check_box_tag 'settings[post_contact]', 1, @settings[:post_contact].to_i == 1
p
= tag.label l(:label_settings_post_contact_updates)
= check_box_tag 'settings[post_contact_updates]', 1, @settings[:post_contact_updates].to_i == 1
p
= tag.label l(:label_settings_post_private_contacts)
= check_box_tag 'settings[post_private_contacts]', 1, @settings[:post_private_contacts].to_i == 1
- if Redmine::Plugin.installed?('redmine_passwords')
fieldset#messenger_settings.box.tabular
legend = l(:field_passwords)
.info = t(:messenger_passwords_intro)
br
p
= tag.label l(:label_settings_post_password)
= check_box_tag 'settings[post_password]', 1, @settings[:post_password].to_i == 1
p
= tag.label l(:label_settings_post_password_updates)
= check_box_tag 'settings[post_password_updates]', 1, @settings[:post_password_updates].to_i == 1

View File

@@ -0,0 +1 @@
# eslint ignore file

View File

@@ -0,0 +1 @@
# stylelint ignore file

View File

@@ -1,23 +1,27 @@
# German strings
de:
permission_manage_messenger: Messenger verwalten
label_messenger_contact_created: "[%{project_url}] Kontakt %{url} erstellt von *%{user}*"
label_messenger_contact_updated: "[%{project_url}] Kontakt %{url} aktualisiert von *%{user}*"
label_messenger_db_entry_created: "[%{project_url}] DB Eintrag %{url} erstellt von *%{user}*"
label_messenger_db_entry_updated: "[%{project_url}] DB Eintrag %{url} aktualisiert von *%{user}*"
default_mentionsl_info: Benutzer, die immer mit Mentions benachrichtet werden sollen. Mehrere Namen können mit Komma getrennt angegeben werden (z.B. @all, @here).
error_messenger_invalid_url: "ist keine gültige URL"
label_messenger_contact_created: "%{project_url} - Kontakt %{url} erstellt von *%{user}*"
label_messenger_contact_updated: "%{project_url} - Kontakt %{url} aktualisiert von *%{user}*"
label_messenger_db_entry_created: "%{project_url} - DB Eintrag %{url} erstellt von *%{user}*"
label_messenger_db_entry_updated: "%{project_url} - DB Eintrag %{url} aktualisiert von *%{user}*"
label_messenger_default_not_visible: Standardeinstellung wird aus Sicherheitsgründen nicht angezeigt
label_messenger_issue_created: "[%{project_url}] Ticket %{url} erstellt von *%{user}*"
label_messenger_issue_updated: "[%{project_url}] Ticket %{url} aktualisiert von *%{user}*"
label_messenger_password_created: "[%{project_url}] Kennwort %{url} erstellt von *%{user}*"
label_messenger_password_updated: "[%{project_url}] Kennwort %{url} aktualisiert von *%{user}*"
label_messenger_issue_created: "%{project_url} - Ticket %{url} erstellt von *%{user}*"
label_messenger_issue_updated: "%{project_url} - Ticket %{url} aktualisiert von *%{user}*"
label_messenger_outgoing_webhook: Ausgehender Webhook
label_messenger_password_created: "%{project_url} - Kennwort %{url} erstellt von *%{user}*"
label_messenger_password_updated: "%{project_url} - Kennwort %{url} aktualisiert von *%{user}*"
label_messenger_project_text_field_info: Leer lassen für Systemstandard.
label_messenger_setting: Messenger Einstellung
label_messenger_settings_default: Standardeinstellung
label_messenger_settings_disabled: Deaktiviert
label_messenger_settings_enabled: Aktiviert
label_messenger_wiki_created: "[%{project_url}] Wiki %{url} erstellt von *%{user}*"
label_messenger_wiki_updated: "[%{project_url}] Wiki %{url} aktualisiert von *%{user}*"
label_messenger_wiki_created: "%{project_url} - Wiki %{url} erstellt von *%{user}*"
label_messenger_wiki_updated: "%{project_url} - Wiki %{url} aktualisiert von *%{user}*"
label_messenger: Messenger
label_settings_auto_mentions: Namen für Mentions konvertiert?
label_settings_default_mentions: Standardbenutzer für Mentions
label_settings_display_watchers: Beobachter?
label_settings_messenger_channel: Messenger Channel
label_settings_messenger_icon: Messenger Icon
@@ -27,10 +31,12 @@ de:
label_settings_new_include_description: Neue Ticketeschreibung?
label_settings_post_contact_updates: Kontakt Updates?
label_settings_post_contact: Neue Kontakte?
label_settings_post_db_updates: DB entry Updates?
label_settings_post_db: Neue DB entries?
label_settings_post_db_updates: DB Einträge Updates?
label_settings_post_db: Neue DB Einträge?
label_settings_post_password_updates: Passwort Updates?
label_settings_post_password: Neue Passwörter?
label_settings_post_private_contacts: Private Kontakte?
label_settings_post_private_db: Private DB Einträge?
label_settings_post_private_issues: Private Ticket Updates?
label_settings_post_private_notes: Private Notizen?
label_settings_post_updates: Ticket Updates?
@@ -47,3 +53,4 @@ de:
messenger_url_info_html: 'Generiere eine <a target="_blank" href="https://github.com/AlphaNodes/redmine_messenger#prepare-your-messenger-service">Incoming WebHook</a> URL vom Messenger Service. Um nur aus bestimmten Projekten Nachrichten zu versenden, kann diese URL leer bleiben und in den Projekteinstellungen gesetzt werden.'
messenger_verify_ssl_info_html: 'Falls der Messenger Service ein ungültiges oder selbst erstelltes (self-signed) SSL Zertifikat verwendet bitte deaktivieren.'
messenger_wiki_intro: Legen Sie fest welche Einträge oder Änderungen für Wikis im angegebenen Messenger Channel versendet werden.
permission_manage_messenger: Messenger verwalten

View File

@@ -1,29 +1,34 @@
# English strings
en:
permission_manage_messenger: Manage messenger
label_messenger_contact_created: "[%{project_url}] Contact %{url} created by *%{user}*"
label_messenger_contact_updated: "[%{project_url}] Contact %{url} updated by *%{user}*"
label_messenger_db_entry_created: "[%{project_url}] DB entry %{url} created by *%{user}*"
label_messenger_db_entry_updated: "[%{project_url}] DB entry %{url} updated by *%{user}*"
default_mentionsl_info: Default people to notify, comma separated (e.g. @all, @here)
error_messenger_invalid_url: is not a valid URL
label_messenger_contact_created: "%{project_url} - Contact %{url} created by *%{user}*"
label_messenger_contact_updated: "%{project_url} - Contact %{url} updated by *%{user}*"
label_messenger_db_entry_created: "%{project_url} - DB entry %{url} created by *%{user}*"
label_messenger_db_entry_updated: "%{project_url} - DB entry %{url} updated by *%{user}*"
label_messenger_default_not_visible: Default setting is not visible for security reasons
label_messenger_issue_created: "[%{project_url}] Issue %{url} created by *%{user}*"
label_messenger_issue_updated: "[%{project_url}] Issue %{url} updated by *%{user}*"
label_messenger_password_created: "[%{project_url}] Kennwort %{url} created by *%{user}*"
label_messenger_password_updated: "[%{project_url}] Kennwort %{url} updated by *%{user}*"
label_messenger_issue_created: "%{project_url} - Issue %{url} created by *%{user}*"
label_messenger_issue_updated: "%{project_url} - Issue %{url} updated by *%{user}*"
label_messenger_outgoing_webhook: Outgoing Webhook
label_messenger_password_created: "%{project_url} - Password %{url} created by *%{user}*"
label_messenger_password_updated: "%{project_url} - Password %{url} updated by *%{user}*"
label_messenger_project_text_field_info: Leave it blank for system default.
label_messenger_setting: Messenger Settings
label_messenger_settings_default: System default
label_messenger_settings_disabled: Disabled
label_messenger_settings_enabled: Enabled
label_messenger_wiki_created: "[%{project_url}] Wiki %{url} created by *%{user}*"
label_messenger_wiki_updated: "[%{project_url}] Wiki %{url} updated by *%{user}*"
label_messenger_wiki_created: "%{project_url} - Wiki %{url} created by *%{user}*"
label_messenger_wiki_updated: "%{project_url} - Wiki %{url} updated by *%{user}*"
label_messenger: Messenger
label_settings_auto_mentions: Convert names to mentions?
label_settings_default_mentions: Default people for mentions
label_settings_display_watchers: Display watchers?
label_settings_messenger_channel: Messenger Channel
label_settings_messenger_icon: Messenger Icon
label_settings_messenger_url: Messenger URL
label_settings_messenger_username: Messenger username
label_settings_messenger_verify_ssl: Verify SSL
label_settings_messenger_direct_users_messages: Send direct messages
label_settings_new_include_description: New issue description?
label_settings_post_contact_updates: Contact updates?
label_settings_post_contact: Contact added?
@@ -31,6 +36,8 @@ en:
label_settings_post_db: DB entry added?
label_settings_post_password_updates: Password updates?
label_settings_post_password: Password added?
label_settings_post_private_contacts: Private contacts?
label_settings_post_private_db: Private DB entries?
label_settings_post_private_issues: Private issue updates?
label_settings_post_private_notes: Private notes updates?
label_settings_post_updates: Issue updates?
@@ -46,4 +53,6 @@ en:
messenger_settings_project_intro: "If you left empty the Messenger URL in the administration area in case to be not globally notified by all project changes you can configure your Messenger URL in the project settings."
messenger_url_info_html: 'Generate an <a target="_blank" href="https://github.com/AlphaNodes/redmine_messenger#prepare-your-messenger-service">Incoming WebHook</a> URL from the messenger service. Leave it empty, if you only want to activate specific projects with project based settings'
messenger_verify_ssl_info_html: 'If your Messenger service uses an invalid or self-signed SSL certificate, disable it.'
messenger_direct_users_messages_info_html: 'If enabled Messenger will post http requests to each user as channel(direct message in RocketChat) along with post in channel'
messenger_wiki_intro: Activate the changes for Wikis that should be sent to the pre-defined Messenger channel.
permission_manage_messenger: Manage messenger

56
config/locales/fr.yml Normal file
View File

@@ -0,0 +1,56 @@
# French strings
fr:
default_mentionsl_info: Personnes à notifier par défaut, séparées par des virgules (@all, @here)
error_messenger_invalid_url: n'est pas une URL valide
label_messenger_contact_created: "%{project_url} - Le contact %{url} créé par *%{user}*"
label_messenger_contact_updated: "%{project_url} - Le contact %{url} mis à jour par *%{user}*"
label_messenger_db_entry_created: "%{project_url} - Entrée de base de données %{url} créée par *%{user}*"
label_messenger_db_entry_updated: "%{project_url} - Entrée de base de données %{url} mis à jour par *%{user}*"
label_messenger_default_not_visible: Le paramètre par défaut n'est pas visible pour des raisons de sécurité
label_messenger_issue_created: "%{project_url} - Ticket %{url} créé par *%{user}*"
label_messenger_issue_updated: "%{project_url} - Ticket %{url} mis à jour par *%{user}*"
label_messenger_outgoing_webhook: Webhook sortant
label_messenger_password_created: "%{project_url} - Mot de passe %{url} créé par *%{user}*"
label_messenger_password_updated: "%{project_url} - Mot de passe %{url} mis à jour par *%{user}*"
label_messenger_project_text_field_info: Laissez ce champ vide pour le système par défaut.
label_messenger_setting: Paramètres de messagerie
label_messenger_settings_default: Choix de l'option
label_messenger_settings_disabled: Désactivé
label_messenger_settings_enabled: Activé
label_messenger_wiki_created: "%{project_url} - Wiki %{url} créé par *%{user}*"
label_messenger_wiki_updated: "%{project_url} - Wiki %{url} mis à jour par *%{user}*"
label_messenger: Messenger
label_settings_auto_mentions: Convertir les noms en mentions
label_settings_default_mentions: Personnes mentionnées par défaut
label_settings_display_watchers: Afficher l'utilisateur assigné au ticket
label_settings_messenger_channel: Nom du salon
label_settings_messenger_icon: Icône affiché
label_settings_messenger_url: URL WebHook entrant
label_settings_messenger_username: Nom du robot
label_settings_messenger_verify_ssl: Vérifier SSL
label_settings_new_include_description: Inclure la description des nouveaux tickets
label_settings_post_contact_updates: Mises à jour de contact ?
label_settings_post_contact: Contact ajouté ?
label_settings_post_db_updates: Mises à jour des entrées de base de données ?
label_settings_post_db: Entrée de base de données ajoutée ?
label_settings_post_password_updates: Mises à jour du mot de passe ?
label_settings_post_password: Mot de passe ajouté ?
label_settings_post_private_contacts: Contacts privés ?
label_settings_post_private_db: Entrées de base de données privées ?
label_settings_post_private_issues: Inclure les mises à jour des tickets privés
label_settings_post_private_notes: Inclure les mises à jour des notes privées
label_settings_post_updates: Inclure toutes les mises à jour
label_settings_post_wiki_updates: Inclure les mises à jour du wiki
label_settings_post_wiki: Inclure les publications du wiki
label_settings_updated_include_description: Inclure la description suite à une mise à jour
messenger_channel_info_html: 'Spécifier le canal à utiliser. Vous pouvez définir plusieurs canaux, séparés par une virgule.'
messenger_contacts_intro: Activer les modifications pour les contacts à envoyer au canal Messenger prédéfini.
messenger_db_intro: Activer les modifications pour la base de données à envoyer au canal Messenger prédéfini.
messenger_issue_intro: Activer les modifications pour les tickets à envoyer au canal Messenger prédéfini.
messenger_passwords_intro: Activez les modifications pour les mots de passe devant être envoyés au canal Messenger prédéfini.
messenger_settings_intro: "Laisser l'URL de Messenger dans la zone d'administration vide pour ne pas envoyer de messages de Redmine à Messenger. Peu importe ce que vous avez configuré ici. Si vous souhaitez envoyer des messages de tous les projets Redmine à Messenger, renseignez lURL. Les messages seront envoyés au canal spécifique. Si vous souhaitez uniquement être averti par certains des projets (pas tous), laissez l'URL du messager ici vide et accédez à la configuration du projet spécifique."
messenger_settings_project_intro: "Si vous laissez vide l'URL de Messenger dans la zone d'administration au cas où vous ne seriez pas averti globalement de toutes les modifications apportées au projet, vous pouvez configurer votre URL Messenger dans les paramètres du projet."
messenger_url_info_html: 'Générer une adresse <a target="_blank" href="https://github.com/AlphaNodes/redmine_messenger#prepare-your-messenger-service">Incoming WebHook</a> pour le service global de Messenger. Laisser ce champ vide pour activer uniquement des projets spécifiques avec des paramètres personnalisés pour chaque projet.'
messenger_verify_ssl_info_html: 'Désactiver cette vérification si votre service Messenger utilise un certificat SSL non valide ou auto-signé.'
messenger_wiki_intro: Activer les notifications a envoyer au canal Messenger pour l'ensemble des wikis.
permission_manage_messenger: Gérer Messenger

56
config/locales/ja.yml Normal file
View File

@@ -0,0 +1,56 @@
# Japanese strings
ja:
default_mentionsl_info: Default people to notify, comma separated (e.g. @all, @here)
error_messenger_invalid_url: is not a valid URL
label_messenger_contact_created: "%{project_url} - コンタクト %{url} が *%{user}* によって作成されました。"
label_messenger_contact_updated: "%{project_url} - コンタクト %{url} が*%{user}* によって更新されました。"
label_messenger_db_entry_created: "%{project_url} - DB entry %{url} created by *%{user}*"
label_messenger_db_entry_updated: "%{project_url} - DB entry %{url} updated by *%{user}*"
label_messenger_default_not_visible: デフォルトの設定はセキュリティ上の理由により表示されません。
label_messenger_issue_created: "%{project_url} - チケット %{url} が *%{user}* によって作成されました。"
label_messenger_issue_updated: "%{project_url} - チケット %{url} が *%{user}* によって更新されました。"
label_messenger_outgoing_webhook: Outgoing Webhook
label_messenger_password_created: "%{project_url} - Password %{url} created by *%{user}*"
label_messenger_password_updated: "%{project_url} - Password %{url} updated by *%{user}*"
label_messenger_project_text_field_info: デフォルトの設定を使う場合空欄にしてください。
label_messenger_setting: メッセンジャーの設定
label_messenger_settings_default: デフォルト
label_messenger_settings_disabled: 無効
label_messenger_settings_enabled: 有効
label_messenger_wiki_created: "%{project_url} - Wiki %{url} が by *%{user}* によって作成されました。"
label_messenger_wiki_updated: "%{project_url} - Wiki %{url} が *%{user}* によって更新されました。"
label_messenger: メッセンジャー
label_settings_auto_mentions: ユーザー名をその人についての投稿(@ユーザー名)に変換する
label_settings_default_mentions: Default people for mentions
label_settings_display_watchers: ウォッチャーを表示する
label_settings_messenger_channel: メッセンジャーのチャンネル
label_settings_messenger_icon: メッセンジャーのアイコン
label_settings_messenger_url: メッセンジャーのURL
label_settings_messenger_username: メッセンジャーのユーザー名
label_settings_messenger_verify_ssl: SSL証明書の検証
label_settings_new_include_description: チケット作成時に説明を含める
label_settings_post_contact_updates: コンタクトの更新
label_settings_post_contact: コンタクトの作成
label_settings_post_db_updates: DB entry updates?
label_settings_post_db: DB entry added?
label_settings_post_password_updates: Password updates?
label_settings_post_password: Password added?
label_settings_post_private_contacts: Private contacts?
label_settings_post_private_db: Private DB entries?
label_settings_post_private_issues: プライベートチケットの更新
label_settings_post_private_notes: プライベート注記の更新
label_settings_post_updates: チケットの更新
label_settings_post_wiki_updates: Wikiの更新
label_settings_post_wiki: Wikiの作成
label_settings_updated_include_description: チケット更新時に説明を含める
messenger_channel_info_html: チャンネルを指定する必要があります。複数のチャンネルを指定する場合は,(カンマ)で区切って下さい。
messenger_contacts_intro: メッセンジャーに送信するチケットのイベントにチェックを入れて下さい。
messenger_db_intro: Activate the changes for DB that should be sent to the pre-defined Messenger channel.
messenger_issue_intro: メッセンジャーに送信するチケットのイベントにチェックを入れて下さい。
messenger_passwords_intro: Activate the changes for Passwords that should be sent to the pre-defined Messenger channel.
messenger_settings_intro: 管理画面でメッセンジャーのURLを指定した場合、全てのプロジェクトのデフォルトの送信先になります。プロジェクト毎の送信先を設定する場合はプロジェクトの設定画面で設定して下さい。
messenger_settings_project_intro: メッセンジャーのURLを指定しない場合、管理者が指定したチャンネルにメッセージが送信されます。(管理者がチャンネルを指定していない場合は、空欄にすると機能は無効になります)
messenger_url_info_html: 'メッセンジャー サービスで <a target="_blank" href="https://github.com/AlphaNodes/redmine_messenger#prepare-your-messenger-service">内向きのウェブフック</a>のURLを作成して下さい。プロジェクト毎に設定を変えたい場合は空欄として下さい。'
messenger_verify_ssl_info_html: 'メッセンジャー サービスが自己署名証明書や不正な証明書を使っている場合、無効として下さい。'
messenger_wiki_intro: メッセンジャーに送信するWikiのイベントにチェックを入れて下さい。
permission_manage_messenger: メッセンジャーの管理

56
config/locales/ko.yml Normal file
View File

@@ -0,0 +1,56 @@
# Korean strings
ko:
default_mentionsl_info: 알림을 받을 기본 사용자를 나타내며, 쉼표로 구분 (e.g. @all, @here)
error_messenger_invalid_url: 유효한 URL이 아님
label_messenger_contact_created: "%{project_url} - *%{user}*님이 연락처(%{url})를 만들었습니다."
label_messenger_contact_updated: "%{project_url} - *%{user}*님이 연락처(%{url})를 수정했습니다."
label_messenger_db_entry_created: "%{project_url} - *%{user}*님이 데이터베이스 항목(%{url})을 만들었습니다."
label_messenger_db_entry_updated: "%{project_url} - *%{user}*님이 데이터베이스 항목(%{url})을 수정했습니다."
label_messenger_default_not_visible: 보안 상의 이유로 기본값이 보여지지 않습니다.
label_messenger_issue_created: "%{project_url} - *%{user}*님이 일감(%{url})을 만들었습니다."
label_messenger_issue_updated: "%{project_url} - *%{user}*님이 일감(%{url})을 수정했습니다."
label_messenger_outgoing_webhook: 웹훅 발신
label_messenger_password_created: "%{project_url} - *%{user}*님이 암호(%{url})를 만들었습니다."
label_messenger_password_updated: "%{project_url} - *%{user}*님이 암호(%{url})를 수정했습니다."
label_messenger_project_text_field_info: 시스템 기본값을 사용하려면 빈 값으로 두세요.
label_messenger_setting: 메신저 설정
label_messenger_settings_default: 시스템 기본값
label_messenger_settings_disabled: 비활성화
label_messenger_settings_enabled: 활성화
label_messenger_wiki_created: "%{project_url} - *%{user}*님이 위키(%{url})를 만들었습니다."
label_messenger_wiki_updated: "%{project_url} - *%{user}*님이 위키(%{url})를 수정했습니다."
label_messenger: 메신저
label_settings_auto_mentions: 이름을 멘션으로 변환
label_settings_default_mentions: 멘션될 기본 사용자
label_settings_display_watchers: 지켜보는 사용자들을 보여줌
label_settings_messenger_channel: 메신저 채널
label_settings_messenger_icon: 메신저 아이콘
label_settings_messenger_url: 메신저 URL
label_settings_messenger_username: 메신저 사용자 이름
label_settings_messenger_verify_ssl: SSL
label_settings_new_include_description: 새로운 이슈의 설명을 포함
label_settings_post_contact_updates: 연락처 수정
label_settings_post_contact: 연락처 추가
label_settings_post_db_updates: 데이터베이스 항목 수정
label_settings_post_db: 데이터베이스 항목 추가
label_settings_post_password_updates: 암호 수정
label_settings_post_password: 암호 추가
label_settings_post_private_contacts: 비공개 연락처를 포함
label_settings_post_private_db: 비공개 데이터베이스 항목을 포함
label_settings_post_private_issues: 비공개 일감을 포함
label_settings_post_private_notes: 비공개 노트를 포함
label_settings_post_updates: 일감 수정
label_settings_post_wiki_updates: 위키 수정
label_settings_post_wiki: 위키 추가
label_settings_updated_include_description: 수정된 일감의 설명을 포함
messenger_channel_info_html: '메시지를 보낼 채널들을 선택합니다. 쉼표로 구분하여 여러 채널을 선택할 수 있습니다.'
messenger_contacts_intro: 사전에 정의된 메신저 채널로 연락처의 변경 사항을 보냅니다.
messenger_db_intro: 사전에 정의된 메신저 채널로 데이터베이스의 변경 사항을 보냅니다.
messenger_issue_intro: 사전에 정의된 메신저 채널로 일감의 변경 사항을 보냅니다.
messenger_passwords_intro: 사전에 정의된 메신저 채널로 암호의 변경 사항을 보냅니다.
messenger_settings_intro: "레드마인에서 메신저로 메시지를 보내지 않으려면 플러그인 관리 페이지에서 메신저 URL을 빈 값으로 둡니다. 여기에서 설정을 하면 모든 레드마인 프로젝트의 메시지들이 여기에서 설정된 URL의 지정된 채널로 전달됩니다. 일부 프로젝트에 대해서만 전달되게 하고 싶다면 여기에선 URL을 빈 값으로 두고 각 프로젝트에서 설정합니다."
messenger_settings_project_intro: "플러그인 관리 페이지에서 메신저 URL을 빈 값으로 두면 각 프로젝트 설정에서 메신저 URL을 설정함으로써 모든 프로젝트의 변경을 전역적으로 수신하지 않게 됩니다."
messenger_url_info_html: '메신저 서비스에서 <a target="_blank" href="https://github.com/AlphaNodes/redmine_messenger#prepare-your-messenger-service">Incoming WebHook</a> URL을 만드세요. 전역 설정을 따르려면 빈 값으로 둡니다.'
messenger_verify_ssl_info_html: '메신저 서비스가 유효하지 않거나 자가 서명된 SSL 인증서를 사용한다면 비활성화하세요.'
messenger_wiki_intro: 사전에 정의된 메신저 채널로 위키의 변경 사항을 보냅니다.
permission_manage_messenger: 메신저 관리

View File

@@ -1,7 +1,8 @@
# Redmine Messenger plugin for Redmine
# Plugin's routes
# See: http://guides.rubyonrails.org/routing.html
RedmineApp::Application.routes.draw do
match 'projects/:id/messenger_settings/save',
to: 'messenger_settings#save',
via: %i[post put patch]
# Don't create routes for repositories resources with only: []
# do not override Redmine's routes.
resources :projects, only: [] do
resource :messenger_setting, only: %i[show update]
end

View File

@@ -1,9 +1,7 @@
# Redmine Messenger plugin for Redmine
class CreateMessengerSettings < ActiveRecord::Migration
class CreateMessengerSettings < ActiveRecord::Migration[4.2]
def change
create_table :messenger_settings do |t|
t.belongs_to :project, null: false
t.references :project, null: false, index: true
t.string :messenger_url
t.string :messenger_icon
t.string :messenger_channel

View File

@@ -0,0 +1,5 @@
class AddDefaultMentions < ActiveRecord::Migration[4.2]
def change
add_column :messenger_settings, :default_mentions, :string
end
end

View File

@@ -0,0 +1,6 @@
class AddPrivateSettings < ActiveRecord::Migration[4.2]
def change
add_column :messenger_settings, :post_private_contacts, :integer, default: 0, null: false
add_column :messenger_settings, :post_private_db, :integer, default: 0, null: false
end
end

View File

@@ -0,0 +1,5 @@
class AddDirectMessages < ActiveRecord::Migration[4.2]
def change
add_column :messenger_settings, :messenger_direct_users_messages, :integer, default: 0, null: false
end
end

27
init.rb
View File

@@ -1,19 +1,16 @@
# Redmine Messenger plugin for Redmine
require 'redmine'
require 'redmine_messenger'
raise "\n\033[31mredmine_messenger requires ruby 2.4 or newer. Please update your ruby version.\033[0m" if RUBY_VERSION < '2.4'
Redmine::Plugin.register :redmine_messenger do
name 'Redmine Messenger'
author 'AlphaNodes GmbH'
url 'https://github.com/alphanodes/redmine_messenger'
author_url 'https://alphanodes.com/'
description 'Messenger integration for Slack, Rocketchat and Mattermost support'
version '0.9.9'
description 'Messenger integration for Slack, Discord, Rocketchat and Mattermost support'
version '1.0.7'
requires_redmine version_or_higher: '3.0.0'
requires_redmine version_or_higher: '4.0.0'
permission :manage_messenger, projects: :settings, messenger_settings: :save
permission :manage_messenger, projects: :settings, messenger_settings: :update
settings default: {
messenger_url: '',
@@ -21,13 +18,17 @@ Redmine::Plugin.register :redmine_messenger do
messenger_channel: 'redmine',
messenger_username: 'robot',
messenger_verify_ssl: '1',
auto_mentions: '1',
messenger_direct_users_messages: '0',
auto_mentions: '0',
default_mentions: '',
display_watchers: '0',
post_updates: '1',
new_include_description: '1',
updated_include_description: '1',
post_private_issues: '1',
post_private_notes: '1',
post_private_contacts: '0',
post_private_db: '0',
post_private_issues: '0',
post_private_notes: '0',
post_wiki: '0',
post_wiki_updates: '0',
post_db: '0',
@@ -38,3 +39,7 @@ Redmine::Plugin.register :redmine_messenger do
post_password_updates: '0'
}, partial: 'settings/messenger_settings'
end
Rails.configuration.to_prepare do
RedmineMessenger.setup
end

View File

@@ -1,29 +1,41 @@
# Redmine Messenger plugin for Redmine
Rails.configuration.to_prepare do
# Patches
require_dependency 'redmine_messenger/patches/issue_patch'
require_dependency 'redmine_messenger/patches/wiki_page_patch'
require_dependency 'redmine_messenger/patches/projects_helper_patch'
require 'redmine_messenger/patches/contact_patch' if RedmineMessenger::REDMINE_CONTACTS_SUPPORT
require 'redmine_messenger/patches/db_entry_patch' if RedmineMessenger::REDMINE_DB_SUPPORT
require 'redmine_messenger/patches/password_patch' if Redmine::Plugin.installed?('redmine_passwords')
# Global helpers
require_dependency 'redmine_messenger/helpers'
# Hooks
require_dependency 'redmine_messenger/hooks'
end
module RedmineMessenger
REDMINE_CONTACTS_SUPPORT = Redmine::Plugin.installed?('redmine_contacts') ? true : false
REDMINE_DB_SUPPORT = Redmine::Plugin.installed?('redmine_db') ? true : false
# this does not work at the moment, because redmine loads passwords after messener plugin
REDMINE_PASSWORDS_SUPPORT = Redmine::Plugin.installed?('redmine_passwords') ? true : false
def self.settings
Setting[:plugin_redmine_messenger].blank? ? {} : Setting[:plugin_redmine_messenger]
class << self
def setup
# Patches
Issue.include RedmineMessenger::Patches::IssuePatch
WikiPage.include RedmineMessenger::Patches::WikiPagePatch
ProjectsController.send :helper, MessengerProjectsHelper
Contact.include(RedmineMessenger::Patches::ContactPatch) if RedmineMessenger::REDMINE_CONTACTS_SUPPORT
DbEntry.include(RedmineMessenger::Patches::DbEntryPatch) if RedmineMessenger::REDMINE_DB_SUPPORT
Password.include(RedmineMessenger::Patches::PasswordPatch) if Redmine::Plugin.installed?('redmine_passwords')
# Global helpers
ActionView::Base.include RedmineMessenger::Helpers
# Hooks
require_dependency 'redmine_messenger/hooks'
end
def settings
if Setting[:plugin_redmine_messenger].class == Hash
new_settings = ActiveSupport::HashWithIndifferentAccess.new(Setting[:plugin_redmine_messenger])
Setting.plugin_redmine_messenger = new_settings
new_settings
else
# Rails 5 uses ActiveSupport::HashWithIndifferentAccess
Setting[:plugin_redmine_messenger]
end
end
def setting?(value)
return true if settings[value].to_i == 1
false
end
end
end

View File

@@ -1,21 +1,17 @@
# Redmine Messenger plugin for Redmine
module RedmineMessenger
module Helpers
def project_messenger_options(active)
options_for_select({ l(:label_messenger_settings_default) => 0,
l(:label_messenger_settings_disabled) => 1,
l(:label_messenger_settings_enabled) => 2 }, active)
options_for_select({ l(:label_messenger_settings_default) => '0',
l(:label_messenger_settings_disabled) => '1',
l(:label_messenger_settings_enabled) => '2' }, active)
end
def project_setting_messenger_default_value(value)
if Messenger.default_project_setting(@project, value)
l(:label_messenger_settings_enabled)
l :label_messenger_settings_enabled
else
l(:label_messenger_settings_disabled)
l :label_messenger_settings_disabled
end
end
end
end
ActionView::Base.send :include, RedmineMessenger::Helpers

View File

@@ -1,5 +1,3 @@
# Redmine Messenger plugin for Redmine
module RedmineMessenger
class MessengerListener < Redmine::Hook::Listener
def model_changeset_scan_commit_for_issue_ids_pre_issue_update(context = {})
@@ -10,14 +8,15 @@ module RedmineMessenger
channels = Messenger.channels_for_project issue.project
url = Messenger.url_for_project issue.project
return unless channels.present? && url && issue.save
return if issue.is_private? && !Messenger.setting_for_project(project, :post_private_issues)
return unless channels.present? && url && issue.changes.any? && Messenger.setting_for_project(issue.project, :post_updates)
return if issue.is_private? && !Messenger.setting_for_project(issue.project, :post_private_issues)
msg = "[#{ERB::Util.html_escape(issue.project)}] #{ERB::Util.html_escape(journal.user.to_s)} updated <#{Messenger.object_url issue}|#{ERB::Util.html_escape(issue)}>"
msg = "[#{Messenger.markup_format issue.project}]" \
" #{Messenger.markup_format journal.user.to_s} updated <#{Messenger.object_url issue}|#{Messenger.markup_format issue}>"
repository = changeset.repository
if Setting.host_name.to_s =~ %r{/\A(https?\:\/\/)?(.+?)(\:(\d+))?(\/.+)?\z/i}
if Setting.host_name.to_s =~ %r{/\A(https?://)?(.+?)(:(\d+))?(/.+)?\z/i}
host = Regexp.last_match(2)
port = Regexp.last_match(4)
prefix = Regexp.last_match(5)
@@ -45,10 +44,12 @@ module RedmineMessenger
end
attachment = {}
attachment[:text] = ll(Setting.default_language, :text_status_changed_by_changeset, "<#{revision_url}|#{ERB::Util.html_escape(changeset.comments)}>")
attachment[:text] = ll(Setting.default_language,
:text_status_changed_by_changeset,
"<#{revision_url}|#{Messenger.markup_format changeset.comments}>")
attachment[:fields] = journal.details.map { |d| Messenger.detail_to_field d }
Messenger.speak(msg, channels, url, attachment: attachment, project: project)
Messenger.speak msg, channels, url, attachment: attachment, project: repository.project
end
end
end

View File

@@ -1,51 +1,52 @@
# Redmine Messenger plugin for Redmine
module RedmineMessenger
module Patches
module ContactPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
after_create :send_messenger_create
after_update :send_messenger_update
end
extend ActiveSupport::Concern
included do
include InstanceMethods
after_create_commit :send_messenger_create
after_update_commit :send_messenger_update
end
module InstanceMethods
def send_messenger_create
return unless Messenger.setting_for_project(project, :post_contact)
return unless Messenger.setting_for_project project, :post_contact
return if is_private? && !Messenger.setting_for_project(project, :post_private_contacts)
set_language_if_valid Setting.default_language
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
return unless channels.present? && url
Messenger.speak(l(:label_messenger_contact_created,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{name}>",
Messenger.speak l(:label_messenger_contact_created,
project_url: Messenger.project_url_markdown(project),
url: Messenger.url_markdown(self, name),
user: User.current),
channels, url, project: project)
channels, url, project: project
end
def send_messenger_update
return unless Messenger.setting_for_project(project, :post_contact_updates)
return unless Messenger.setting_for_project project, :post_contact_updates
return if is_private? && !Messenger.setting_for_project(project, :post_private_contacts)
set_language_if_valid Setting.default_language
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
return unless channels.present? && url
Messenger.speak(l(:label_messenger_contact_updated,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{name}>",
Messenger.speak l(:label_messenger_contact_updated,
project_url: Messenger.project_url_markdown(project),
url: Messenger.url_markdown(self, name),
user: User.current),
channels, url, project: project)
channels, url, project: project
end
end
end
end
end
unless Contact.included_modules.include? RedmineMessenger::Patches::ContactPatch
Contact.send(:include, RedmineMessenger::Patches::ContactPatch)
end

View File

@@ -1,51 +1,52 @@
# Redmine Messenger plugin for Redmine
module RedmineMessenger
module Patches
module DbEntryPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
after_create :send_messenger_create
after_update :send_messenger_update
end
extend ActiveSupport::Concern
included do
include InstanceMethods
after_create_commit :send_messenger_create
after_update_commit :send_messenger_update
end
module InstanceMethods
def send_messenger_create
return unless Messenger.setting_for_project(project, :post_db)
return unless Messenger.setting_for_project project, :post_db
return if is_private? && !Messenger.setting_for_project(project, :post_private_db)
set_language_if_valid Setting.default_language
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
return unless channels.present? && url
Messenger.speak(l(:label_messenger_db_entry_created,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{name}>",
Messenger.speak l(:label_messenger_db_entry_created,
project_url: Messenger.project_url_markdown(project),
url: Messenger.url_markdown(self, name),
user: User.current),
channels, url, project: project)
channels, url, project: project
end
def send_messenger_update
return unless Messenger.setting_for_project(project, :post_db_updates)
return unless Messenger.setting_for_project project, :post_db_updates
return if is_private? && !Messenger.setting_for_project(project, :post_private_db)
set_language_if_valid Setting.default_language
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
return unless channels.present? && url
Messenger.speak(l(:label_messenger_db_entry_updated,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{name}>",
Messenger.speak l(:label_messenger_db_entry_updated,
project_url: Messenger.project_url_markdown(project),
url: Messenger.url_markdown(self, name),
user: User.current),
channels, url, project: project)
channels, url, project: project
end
end
end
end
end
unless DbEntry.included_modules.include? RedmineMessenger::Patches::DbEntryPatch
DbEntry.send(:include, RedmineMessenger::Patches::DbEntryPatch)
end

View File

@@ -1,14 +1,13 @@
# Redmine Messenger plugin for Redmine
module RedmineMessenger
module Patches
module IssuePatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
after_create :send_messenger_create
after_update :send_messenger_update
end
extend ActiveSupport::Concern
included do
include InstanceMethods
after_create_commit :send_messenger_create
after_update_commit :send_messenger_update
end
module InstanceMethods
@@ -16,6 +15,12 @@ module RedmineMessenger
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
if Messenger.setting_for_project(project, :messenger_direct_users_messages)
notified_users.each do |user|
channels.append "@#{user.login}" if user.login != author.login
end
end
return unless channels.present? && url
return if is_private? && !Messenger.setting_for_project(project, :post_private_issues)
@@ -23,35 +28,39 @@ module RedmineMessenger
attachment = {}
if description.present? && Messenger.setting_for_project(project, :new_include_description)
attachment[:text] = ERB::Util.html_escape(description)
attachment[:text] = Messenger.markup_format description
end
attachment[:fields] = [{ title: I18n.t(:field_status),
value: Messenger.markup_format(status.to_s),
short: true },
{ title: I18n.t(:field_priority),
value: Messenger.markup_format(priority.to_s),
short: true }]
if assigned_to.present?
attachment[:fields] << { title: I18n.t(:field_assigned_to),
value: Messenger.markup_format(assigned_to.to_s),
short: true }
end
attachment[:fields] = [{
title: I18n.t(:field_status),
value: ERB::Util.html_escape(status.to_s),
short: true
}, {
title: I18n.t(:field_priority),
value: ERB::Util.html_escape(priority.to_s),
short: true
}, {
title: I18n.t(:field_assigned_to),
value: ERB::Util.html_escape(assigned_to.to_s),
short: true
}]
if RedmineMessenger.settings[:display_watchers] == '1'
attachments.each do |att|
attachment[:fields] << { title: I18n.t(:label_attachment),
value: "<#{Messenger.object_url att}|#{ERB::Util.html_escape att.filename}>",
short: true }
end
if RedmineMessenger.setting?(:display_watchers) && watcher_users.count.positive?
attachment[:fields] << {
title: I18n.t(:field_watcher),
value: ERB::Util.html_escape(watcher_users.join(', ')),
value: Messenger.markup_format(watcher_users.join(', ')),
short: true
}
end
Messenger.speak(l(:label_messenger_issue_created,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url(self)}|#{ERB::Util.html_escape(self)}>#{Messenger.mentions description if RedmineMessenger.settings[:auto_mentions] == '1'}",
Messenger.speak l(:label_messenger_issue_created,
project_url: Messenger.project_url_markdown(project),
url: send_messenger_mention_url(project, description),
user: author),
channels, url, attachment: attachment, project: project)
channels, url, attachment: attachment, project: project
end
def send_messenger_update
@@ -60,6 +69,12 @@ module RedmineMessenger
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
if Messenger.setting_for_project(project, :messenger_direct_users_messages)
notified_users.each do |user|
channels.append "@#{user.login}" if user.login != current_journal.user.login
end
end
return unless channels.present? && url && Messenger.setting_for_project(project, :post_updates)
return if is_private? && !Messenger.setting_for_project(project, :post_private_issues)
return if current_journal.private_notes? && !Messenger.setting_for_project(project, :post_private_notes)
@@ -67,23 +82,34 @@ module RedmineMessenger
set_language_if_valid Setting.default_language
attachment = {}
if current_journal.notes.present? && Messenger.setting_for_project(project, :updated_include_description)
attachment[:text] = ERB::Util.html_escape(current_journal.notes)
if Messenger.setting_for_project(project, :updated_include_description)
attachment_text = Messenger.attachment_text_from_journal current_journal
attachment[:text] = attachment_text if attachment_text.present?
end
fields = current_journal.details.map { |d| Messenger.detail_to_field d }
fields = current_journal.details.map { |d| Messenger.detail_to_field(d, project) }
fields << { title: I18n.t(:field_is_private), short: true } if current_journal.private_notes?
fields.compact!
attachment[:fields] = fields if fields.any?
Messenger.speak(l(:label_messenger_issue_updated,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{ERB::Util.html_escape(self)}>#{Messenger.mentions(current_journal.notes) if Messenger.setting_for_project(project, :auto_mentions)}",
Messenger.speak l(:label_messenger_issue_updated,
project_url: Messenger.project_url_markdown(project),
url: send_messenger_mention_url(project, description),
user: current_journal.user),
channels, url, attachment: attachment, project: project)
channels, url, attachment: attachment, project: project
end
private
def send_messenger_mention_url(project, text)
mention_to = ''
if Messenger.setting_for_project(project, :auto_mentions) ||
Messenger.textfield_for_project(project, :default_mentions).present?
mention_to = Messenger.mentions project, text
end
"<#{Messenger.object_url self}|#{Messenger.markup_format self}>#{mention_to}"
end
end
end
end
end
unless WikiPage.included_modules.include? RedmineMessenger::Patches::WikiPagePatch
WikiPage.send(:include, RedmineMessenger::Patches::WikiPagePatch)
end

View File

@@ -1,51 +1,52 @@
# Redmine Messenger plugin for Redmine
module RedmineMessenger
module Patches
module PasswordPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
after_create :send_messenger_create
after_update :send_messenger_update
end
extend ActiveSupport::Concern
included do
include InstanceMethods
after_create_commit :send_messenger_create
after_update_commit :send_messenger_update
end
module InstanceMethods
def send_messenger_create
return unless Messenger.setting_for_project(project, :post_password)
return unless Messenger.setting_for_project project, :post_password
return if is_private?
set_language_if_valid Setting.default_language
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
return unless channels.present? && url
Messenger.speak(l(:label_messenger_password_created,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{name}>",
Messenger.speak l(:label_messenger_password_created,
project_url: Messenger.project_url_markdown(project),
url: Messenger.url_markdown(self, name),
user: User.current),
channels, url, project: project)
channels, url, project: project
end
def send_messenger_update
return unless Messenger.setting_for_project(project, :post_password_updates)
return unless Messenger.setting_for_project project, :post_password_updates
return if is_private?
set_language_if_valid Setting.default_language
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
return unless channels.present? && url
Messenger.speak(l(:label_messenger_password_updated,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{name}>",
Messenger.speak l(:label_messenger_password_updated,
project_url: Messenger.project_url_markdown(project),
url: Messenger.url_markdown(self, name),
user: User.current),
channels, url, project: project)
channels, url, project: project
end
end
end
end
end
unless Password.included_modules.include? RedmineMessenger::Patches::PasswordPatch
Password.send(:include, RedmineMessenger::Patches::PasswordPatch)
end

View File

@@ -1,32 +0,0 @@
# Redmine Messenger plugin for Redmine
module RedmineMessenger
module Patches
module ProjectsHelperPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
alias_method_chain :project_settings_tabs, :messenger
end
end
module InstanceMethods
def project_settings_tabs_with_messenger
tabs = project_settings_tabs_without_messenger
action = { name: 'messenger',
controller: 'messenger_settings',
action: :show,
partial: 'messenger_settings/show',
label: :label_messenger }
tabs << action if User.current.allowed_to?(:manage_messenger, @project)
tabs
end
end
end
end
end
unless ProjectsHelper.included_modules.include?(RedmineMessenger::Patches::ProjectsHelperPatch)
ProjectsHelper.send(:include, RedmineMessenger::Patches::ProjectsHelperPatch)
end

View File

@@ -1,34 +1,36 @@
# Redmine Messenger plugin for Redmine
module RedmineMessenger
module Patches
module WikiPagePatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
after_create :send_messenger_create
after_update :send_messenger_update
end
extend ActiveSupport::Concern
included do
include InstanceMethods
after_create_commit :send_messenger_create
after_update_commit :send_messenger_update
end
module InstanceMethods
def send_messenger_create
return unless Messenger.setting_for_project(project, :post_wiki)
return unless Messenger.setting_for_project project, :post_wiki
set_language_if_valid Setting.default_language
channels = Messenger.channels_for_project project
url = Messenger.url_for_project project
return unless channels.present? && url
Messenger.speak(l(:label_messenger_wiki_created,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{title}>",
Messenger.speak l(:label_messenger_wiki_created,
project_url: Messenger.project_url_markdown(project),
url: Messenger.url_markdown(self, title),
user: User.current),
channels, url, project: project)
channels, url, project: project
end
def send_messenger_update
return unless Messenger.setting_for_project(project, :post_wiki_updates)
return unless Messenger.setting_for_project project, :post_wiki_updates
set_language_if_valid Setting.default_language
channels = Messenger.channels_for_project project
@@ -37,22 +39,18 @@ module RedmineMessenger
return unless channels.present? && url
attachment = nil
unless content.comments.empty?
if !content.nil? && content.comments.present?
attachment = {}
attachment[:text] = ERB::Util.html_escape(content.comments.to_s)
attachment[:text] = Messenger.markup_format content.comments.to_s
end
Messenger.speak(l(:label_messenger_wiki_updated,
project_url: "<#{Messenger.object_url project}|#{ERB::Util.html_escape(project)}>",
url: "<#{Messenger.object_url self}|#{title}>",
Messenger.speak l(:label_messenger_wiki_updated,
project_url: Messenger.project_url_markdown(project),
url: Messenger.url_markdown(self, title),
user: content.author),
channels, url, project: project, attachment: attachment)
channels, url, project: project, attachment: attachment
end
end
end
end
end
unless Issue.included_modules.include? RedmineMessenger::Patches::IssuePatch
Issue.send(:include, RedmineMessenger::Patches::IssuePatch)
end

View File

@@ -1,6 +1,4 @@
# Redmine Messenger plugin for Redmine
require File.expand_path('../../test_helper', __FILE__)
require File.expand_path '../../test_helper', __FILE__
class CommonViewsTest < Redmine::IntegrationTest
fixtures :projects,
@@ -20,10 +18,6 @@ class CommonViewsTest < Redmine::IntegrationTest
def setup
RedmineMessenger::TestCase.prepare
@request = ActionController::TestRequest.new
@response = ActionController::TestResponse.new
@request.env['HTTP_REFERER'] = '/'
end
test 'View user' do

View File

@@ -0,0 +1,8 @@
require File.expand_path '../../test_helper', __FILE__
class RoutingTest < Redmine::RoutingTest
test 'routing messenger' do
should_route 'GET /projects/1/settings/messenger' => 'projects#settings', id: '1', tab: 'messenger'
should_route 'PUT /projects/1/messenger_setting' => 'messenger_settings#update', project_id: '1'
end
end

View File

@@ -0,0 +1,3 @@
gem 'rubocop', require: false
gem 'rubocop-performance', require: false
gem 'rubocop-rails', require: false

View File

@@ -0,0 +1,4 @@
# for travis debugging
# config.logger = Logger.new(STDOUT)
# config.logger.level = Logger::INFO
# config.log_level = :info

View File

@@ -0,0 +1,8 @@
test:
adapter: mysql2
database: travis_ci_test
host: localhost
username: root
password:
pool: 5
encoding: utf8mb4

View File

@@ -0,0 +1,8 @@
test:
adapter: postgresql
encoding: unicode
pool: 5
database: travis_ci_test
user: postgres

View File

@@ -1,33 +1,18 @@
# Redmine Messenger plugin for Redmine
$VERBOSE = nil
require File.expand_path(File.dirname(__FILE__) + '/../../../test/test_helper')
if ENV['JENKINS']
require 'simplecov'
SimpleCov.start :rails do
add_filter 'init.rb'
root File.expand_path "#{File.dirname __FILE__}/.."
end
end
require File.expand_path "#{File.dirname __FILE__}/../../../test/test_helper"
module RedmineMessenger
class TestCase
include ActionDispatch::TestProcess
def self.plugin_fixtures(plugin, *fixture_names)
plugin_fixture_path = "#{Redmine::Plugin.find(plugin).directory}/test/fixtures"
if fixture_names.first == :all
fixture_names = Dir["#{plugin_fixture_path}/**/*.{yml}"]
fixture_names.map! { |f| f[(plugin_fixture_path.size + 1)..-5] }
else
fixture_names = fixture_names.flatten.map(&:to_s)
end
ActiveRecord::Fixtures.create_fixtures(plugin_fixture_path, fixture_names)
end
def uploaded_test_file(name, mime)
ActionController::TestUploadedFile.new(ActiveSupport::TestCase.fixture_path + "/files/#{name}", mime, true)
end
def self.arrays_equal?(a1, a2)
(a1 - a2) - (a2 - a1) == []
end
def self.create_fixtures(fixtures_directory, table_names, _class_names = {})
ActiveRecord::FixtureSet.create_fixtures(fixtures_directory, table_names, _class_names = {})
end
def self.prepare
Role.where(id: [1, 2]).each do |r|
@@ -36,7 +21,7 @@ module RedmineMessenger
end
Project.where(id: [1, 2]).each do |project|
EnabledModule.create(project: project, name: 'issue_tracking')
EnabledModule.create project: project, name: 'issue_tracking'
end
end
end

View File

@@ -1,41 +1,34 @@
# Redmine Messenger plugin for Redmine
require File.expand_path '../../test_helper', __FILE__
require File.expand_path('../../test_helper', __FILE__)
class I18nTest < ActiveSupport::TestCase
include Redmine::I18n
module Redmine
class I18nTest < ActiveSupport::TestCase
include Redmine::I18n
def setup
User.current = nil
end
def setup
User.current = nil
end
def teardown
set_language_if_valid 'en'
end
def test_valid_languages
assert valid_languages.is_a?(Array)
assert valid_languages.first.is_a?(Symbol)
end
def test_locales_validness
lang_files_count = Dir[Rails.root.join('plugins',
'redmine_messenger',
'config',
'locales',
'*.yml')].size
assert_equal lang_files_count, 2
valid_languages.each do |lang|
assert set_language_if_valid(lang)
end
# check if parse error exists
::I18n.locale = 'de'
assert_equal 'Messenger Benutzer', l(:label_settings_messenger_username)
::I18n.locale = 'en'
assert_equal 'Messenger username', l(:label_settings_messenger_username)
set_language_if_valid('en')
def teardown
set_language_if_valid 'en'
end
def test_valid_languages
assert valid_languages.is_a?(Array)
assert valid_languages.first.is_a?(Symbol)
end
def test_locales_validness
lang_files_count = Dir[Rails.root.join('plugins/redmine_messenger/config/locales/*.yml')].size
assert_equal lang_files_count, 5
valid_languages.each do |lang|
assert set_language_if_valid(lang)
end
# check if parse error exists
::I18n.locale = 'de'
assert_equal 'Messenger Benutzer', l(:label_settings_messenger_username)
::I18n.locale = 'en'
assert_equal 'Messenger username', l(:label_settings_messenger_username)
::I18n.locale = 'ja'
assert_equal 'メッセンジャーのユーザー名', l(:label_settings_messenger_username)
set_language_if_valid('en')
end
end

View File

@@ -1,6 +1,4 @@
# Redmine Messenger plugin for Redmine
require File.expand_path('../../test_helper', __FILE__)
require File.expand_path '../../test_helper', __FILE__
class IssueTest < ActiveSupport::TestCase
fixtures :projects, :users, :members, :member_roles, :roles,

View File

@@ -1,23 +1,4 @@
# This file is a part of redmine_reporting,
# a reporting and statistics plugin for Redmine.
#
# Copyright (c) 2016-2017 AlphaNodes GmbH
# https://alphanodes.com
#
# redmine_reporting is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# redmine_reporting is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with redmine_reporting. If not, see <http://www.gnu.org/licenses/>.
require File.expand_path('../../test_helper', __FILE__)
require File.expand_path '../../test_helper', __FILE__
class ProjectTest < ActiveSupport::TestCase
fixtures :projects, :trackers, :issue_statuses, :issues,