├── .github └── workflows │ └── rubyonrails.yml ├── .rubocop.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Gemfile ├── LICENSE ├── README.md ├── after_init.rb ├── app ├── controllers │ └── custom_workflows_controller.rb ├── models │ ├── custom_workflow.rb │ └── custom_workflow_mailer.rb └── views │ ├── custom_workflow_mailer │ ├── custom_email.html.erb │ └── custom_email.text.erb │ ├── custom_workflows │ ├── _form.html.erb │ ├── edit.html.erb │ ├── index.html.erb │ ├── new.html.erb │ └── reorder.js.erb │ └── projects │ └── settings │ └── _custom_workflow.html.erb ├── assets └── stylesheets │ └── custom_workflows.css ├── config ├── locales │ ├── cs.yml │ ├── en.yml │ ├── es.yml │ └── pt-BR.yml └── routes.rb ├── db └── migrate │ ├── 20110915084858_create_custom_workflows.rb │ ├── 20120601054047_alter_custom_workflows.rb │ ├── 20120601054557_create_custom_workflows_projects.rb │ ├── 20120628060102_change_custom_workflows_description_type.rb │ ├── 20120908085222_add_after_save_to_custom_workflows.rb │ ├── 20121005085252_add_is_for_all_to_custom_workflows.rb │ ├── 20150522134436_make_after_save_and_before_save_nullable.rb │ ├── 20150522134437_set_position_field_nullable.rb │ ├── 20150525083345_add_author_to_custom_workflows.rb │ ├── 20150526132244_create_example_workflow.rb │ ├── 20150526134840_add_active_field_to_custom_workflows.rb │ ├── 20150619135811_add_observable_field_to_custom_workflows.rb │ ├── 20150619162054_add_additional_script_fields_to_custom_workflows.rb │ ├── 20151122120000_add_before_and_after_destroy_to_custom_workflows.rb │ ├── 20210210144000_change_default_active_boolean_value_to_custom_workflows.rb │ └── 20230413125201_name_unique_index.rb ├── init.rb ├── lib ├── redmine_custom_workflows.rb └── redmine_custom_workflows │ ├── errors │ └── workflow_error.rb │ ├── hooks │ └── views │ │ └── base_view_hooks.rb │ └── patches │ ├── controllers │ ├── attachments_controller_patch.rb │ ├── groups_controller_patch.rb │ ├── issue_relations_controller_patch.rb │ ├── issues_controller_patch.rb │ ├── members_controller_patch.rb │ ├── projects_controller_patch.rb │ ├── timelog_controller_patch.rb │ ├── users_controller_patch.rb │ ├── versions_controller_patch.rb │ └── wiki_controller_patch.rb │ ├── helpers │ └── projects_helper_patch.rb │ └── models │ ├── attachment_patch.rb │ ├── group_patch.rb │ ├── issue_patch.rb │ ├── issue_relation_patch.rb │ ├── member_patch.rb │ ├── project_patch.rb │ ├── time_entry_patch.rb │ ├── user_patch.rb │ ├── version_patch.rb │ ├── wiki_content_patch.rb │ └── wiki_page_patch.rb └── test ├── fixtures ├── custom_workflows.yml └── custom_workflows_projects.yml ├── functional ├── attachments_controller_patch_test.rb ├── custom_workflows_controller_test.rb ├── groups_controller_patch_test.rb ├── issue_relations_controller_patch_test.rb ├── issues_controller_patch_test.rb ├── members_controller_patch_test.rb ├── projects_controller_patch_test.rb ├── timelog_controller_patch_test.rb ├── users_controller_patch_test.rb ├── versions_controller_patch_test.rb └── wiki_controller_patch_test.rb ├── test_case.rb ├── test_helper.rb ├── unit ├── attachment_patch_test.rb ├── custom_workflow_mailer_test.rb ├── custom_workflow_test.rb ├── group_patch_test.rb ├── issue_patch_test.rb ├── issue_relation_patch_test.rb ├── member_patch_test.rb ├── project_patch_test.rb ├── time_entry_patch_test.rb ├── user_patch_test.rb ├── version_patch_test.rb ├── wiki_content_patch_test.rb └── wiki_page_patch_test.rb └── unit_test.rb /.github/workflows/rubyonrails.yml: -------------------------------------------------------------------------------- 1 | # Redmine plugin for Custom Workflows 2 | # 3 | # Karel Pičman 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public License 7 | # as published by the Free Software Foundation; either version 2 8 | # of the License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | # 19 | # GitHub CI script 20 | 21 | name: "GitHub CI" 22 | on: 23 | push: 24 | branches: ["master"] 25 | pull_request: 26 | branches: ["master"] 27 | jobs: 28 | plugin_tests: 29 | strategy: 30 | matrix: 31 | engine: [mysql, postgresql, sqlite] 32 | include: 33 | - engine: mysql 34 | # Database configuration for Redmine 35 | database_configuration: > 36 | test: 37 | adapter: mysql2 38 | database: test 39 | username: redmine 40 | password: redmine 41 | encoding: utf8mb4 42 | collation: utf8mb4_unicode_ci 43 | # SQL commands to create a database for Redmine 44 | sql1: CREATE DATABASE IF NOT EXISTS test CHARACTER SET utf8mb4; 45 | sql2: CREATE USER 'redmine'@'localhost' IDENTIFIED BY 'redmine'; 46 | sql3: GRANT ALL PRIVILEGES ON test.* TO 'redmine'@'localhost'; 47 | # SQL client command 48 | database_command: mysql -uroot -proot -e 49 | # SQl service 50 | database_service: mysql 51 | - engine: postgresql 52 | # Database configuration for Redmine 53 | database_configuration: > 54 | test: 55 | adapter: postgresql 56 | database: test 57 | username: redmine 58 | password: redmine 59 | host: localhost 60 | # SQL commands to create a database for Redmine 61 | sql1: CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'redmine' NOINHERIT VALID UNTIL 'infinity'; 62 | sql2: CREATE DATABASE test WITH ENCODING='UTF8' OWNER=redmine; 63 | sql3: ALTER USER redmine CREATEDB; 64 | # SQL client command 65 | database_command: sudo -u postgres psql -c 66 | # SQL service 67 | database_service: postgresql 68 | - engine: sqlite 69 | # Database configuration for Redmine 70 | database_configuration: > 71 | test: 72 | adapter: sqlite3 73 | database: db/redmine.sqlite3 74 | # No database needed here. It's just a file. 75 | runs-on: ubuntu-latest 76 | env: 77 | RAILS_ENV: test 78 | NAME: redmine_custom_workflows 79 | steps: 80 | - name: Install dependencies 81 | run: | 82 | sudo apt-get update 83 | sudo apt-get install subversion 84 | - name: Clone Redmine 85 | # Get the latest stable Redmine 86 | run: svn export http://svn.redmine.org/redmine/branches/6.0-stable/ /opt/redmine 87 | - name: Checkout code 88 | uses: actions/checkout@v3 89 | - name: Link the plugin 90 | # Link the plugin to the redmine folder 91 | run: | 92 | ln -s $(pwd) /opt/redmine/plugins/redmine_custom_workflows 93 | - name: Install Ruby and gems 94 | uses: ruby/setup-ruby@v1 # v1.115.3 95 | with: 96 | bundler-cache: true 97 | ruby-version: '3.2' 98 | - name: Setup database 99 | # Create the database 100 | run: | 101 | echo "${{matrix.database_configuration}}" > /opt/redmine/config/database.yml 102 | if [[ "${{matrix.database_service}}" ]]; then 103 | sudo systemctl start ${{matrix.engine}} 104 | fi 105 | if [[ "${{matrix.database_command}}" ]]; then 106 | ${{matrix.database_command}} "${{matrix.sql1}}" 107 | ${{matrix.database_command}} "${{matrix.sql2}}" 108 | ${{matrix.database_command}} "${{matrix.sql3}}" 109 | fi 110 | - name: Install Redmine 111 | # Install Redmine 112 | run: | 113 | cd /opt/redmine 114 | bundle config set --local without 'rmagick development' 115 | bundle install 116 | bundle exec rake generate_secret_token 117 | bundle exec rake db:migrate 118 | bundle exec rake redmine:plugins:migrate 119 | bundle exec rake redmine:load_default_data 120 | bundle exec rake assets:precompile 121 | env: 122 | REDMINE_LANG: en 123 | - name: Standard tests 124 | # Run the tests 125 | run: | 126 | cd /opt/redmine 127 | bundle exec rake redmine:plugins:test:units 128 | bundle exec rake redmine:plugins:test:functionals 129 | - name: Rubocop 130 | # Run the Rubocop tests 131 | run: | 132 | cd /opt/redmine 133 | bundle exec rubocop -c plugins/redmine_custom_workflows/.rubocop.yml plugins/redmine_custom_workflows/ 134 | - name: Cleanup 135 | # Rollback plugin's changes to the database 136 | # Stop the database engine 137 | run: | 138 | cd /opt/redmine 139 | bundle exec rake redmine:plugins:migrate VERSION=0 140 | if [[ "${{matrix.database_service}}" ]]; then 141 | sudo systemctl stop ${{matrix.engine}} 142 | fi 143 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # Redmine plugin for Custom Workflows 2 | # 3 | # Anton Argirov, Karel Pičman 4 | # 5 | # This program is free software; you can redistribute it and/or 6 | # modify it under the terms of the GNU General Public License 7 | # as published by the Free Software Foundation; either version 2 8 | # of the License, or (at your option) any later version. 9 | # 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program; if not, write to the Free Software 17 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | AllCops: 20 | TargetRubyVersion: 3.2 21 | TargetRailsVersion: 7.1 22 | 23 | NewCops: enable 24 | 25 | Exclude: 26 | - '**/vendor/**/*' 27 | 28 | # Enable extensions 29 | require: 30 | - rubocop-performance 31 | - rubocop-rails 32 | 33 | # Rules for CustomWorkflows 34 | Metrics/BlockLength: 35 | Enabled: false 36 | 37 | Metrics/ClassLength: 38 | Enabled: false 39 | 40 | Metrics/MethodLength: 41 | Enabled: false 42 | 43 | Metrics/AbcSize: 44 | Enabled: false 45 | 46 | Metrics/PerceivedComplexity: 47 | Enabled: false 48 | 49 | Metrics/CyclomaticComplexity: 50 | Enabled: false 51 | 52 | Rails/HasAndBelongsToMany: 53 | Enabled: false 54 | 55 | Rails/SkipsModelValidations: 56 | Exclude: 57 | - db/migrate/20210210144000_change_default_active_boolean_value_to_custom_workflows.rb 58 | 59 | Style/ExpandPathArguments: 60 | Enabled: false 61 | 62 | Style/HashSyntax: 63 | EnforcedShorthandSyntax: either 64 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog for Custom Workflows 2 | ============================== 3 | 4 | 3.0.1 *2025-05-10* 5 | ------------------ 6 | 7 | SQL Server compatibility 8 | 9 | * Bug: #359 - Can't install plugin with redmine 6.0.5 in docker container 10 | * Bug: #358 - Plugin failed to install 11 | * New: #354 - Update compatibility section in README 12 | 13 | 3.0.0 *2024-12-06* 14 | ------------------ 15 | 16 | Redmine 6 17 | 18 | * New: #350 - Redmine 6.0.0 19 | 20 | 2.1.2 *2024-06-28* 21 | ------------------ 22 | 23 | Custom emails 24 | 25 | * Bug: #340 - Send email to address in custom field? 26 | 27 | 2.1.1 *2024-05-07* 28 | ------------------ 29 | Email notifications 30 | 31 | * New: #330 - Send mail to the author when an issue is created 32 | * Bug: #328 - Mail sending from custom workflows 33 | 34 | IMPORTANT: Parameters of *CustomWorkflowMailer.deliver_custom_email* method has changed. 35 | 36 | before: `CustomWorkflowMailer.deliver_custom_email(user, subject, text)` 37 | 38 | now: `CustomWorkflowMailer.deliver_custom_email(user, headers = {})` 39 | 40 | To achieve the same behaviour you have to modify an existing callig as follows 41 | 42 | `CustomWorkflowMailer.deliver_custom_email(user, subject: subject, text_body: text)` 43 | 44 | 2.1.0 *2023-11-15* 45 | ------------------ 46 | Member as an observable object 47 | Redmine 5.1 compatibility 48 | 49 | * New: #324 - Add Member as a observable object 50 | * Bug: #322 - Problem with upgrading from 2.0.3 to 2.0.9 51 | * New: #320 - Interference with other redmine-plugins 52 | 53 | 2.0.9 *2023-06-06* 54 | ------------------ 55 | More robust XML import 56 | Rubocop tests of plugin's source codes 57 | 58 | 2.0.8 *2023-02-10* 59 | ------------------ 60 | Better error log messages 61 | 62 | * New: #295 - production.log 63 | 64 | 2.0.7 *2022-11-09* 65 | ------------------ 66 | Bug fix 67 | 68 | * Bug: #285 - Viewing wiki version raises a error 69 | 70 | 2.0.6 *2022-11-01* 71 | ------------------ 72 | Flash messages 73 | 74 | * Bug: #281 - Internal error 500 75 | * New: #280 - Q: check for REST API access (user impersonation or remote IP) in workflow 76 | * New: #275 - When using Before Destruction on issues, no error gets displayed 77 | * New: #85 - Preventing issue attachments to be deleted 78 | * New: #39 - Ability to raise a warning or info (similar to raise WorkflowError, “Your message”) 79 | 80 | 2.0.5 *2022-09-20* 81 | ------------------ 82 | GitHub CI 83 | 84 | 2.0.4 *2022-06-24* 85 | ------------------ 86 | Maintenance release 87 | 88 | * Bug: #261 - Uninitialized constant CustomWorkflow::WorkflowError 89 | 90 | 2.0.3 *2022-05-26* 91 | ------------------ 92 | Redmine 4.2 compatibility 93 | 94 | * Bug: #260 - Upgrade from 1.0.4 to 2.0.2, has an error, redmine 4.2.3 to 4.2.6 95 | 96 | 2.0.2 *2022-05-18* 97 | ------------------ 98 | Ruby 3.0 compatibility 99 | 100 | * Bug: #258 - Tried to create Proc object without a block (again and better) 101 | 102 | 2.0.1 *2022-05-13* 103 | ------------------ 104 | Ruby 2.7 backward compatibility 105 | 106 | * Bug: #257 - IssueRelation.to_s is broken after #257 bug 107 | * Bug: #258 - Tried to create Proc object without a block 108 | 109 | 2.0.0 *2022-04-27* 110 | ------------------ 111 | Redmine 5.0 112 | 113 | * New: #255 - Can you update it to Redmine 5.0.0 114 | * New: #252 - Rails 6 115 | * Bug: #248 - Redmine 4.2.3 doesn't start after installing custom workflow plugin 116 | * New: #239 - Gitlab CI enhancement 117 | 118 | 1.0.7 *2021-10-20* 119 | ------------------ 120 | Spanish localisation 121 | 122 | 1.0.6 *2021-10-08* 123 | ------------------ 124 | Maintenance release 125 | 126 | 1.0.5 *2021-04-30* 127 | ------------------ 128 | SQLite 3 compatibility 129 | 130 | * Bug: #204 - Rails 4: sqlite3 t/f -> 1/0 131 | 132 | 1.0.4 *2020-11-25* 133 | ------------------ 134 | Maintenance release 135 | 136 | * Bug: #193 - Error after install on fresh 4.1.1 137 | * New: #190 - Execute workflows in order of their positioning 138 | * New: #189 - Enable custom workflows for issue relations 139 | * New: #183 - Add link to repo with some examples 140 | 141 | 1.0.3 *2020-06-12* 142 | ------------------ 143 | Redmine's look&feel 144 | 145 | * Bug: #168 - Check last version of plugin KO 146 | * Bug: #167 - Crash when delete project 147 | 148 | 1.0.2 *2020-01-21* 149 | ------------------ 150 | Redmine 4.1 compatibility 151 | 152 | * Bug: #149 - Error install on Redmine 4.1.0 153 | * Bug: #141 - Bug when using PT-BR 154 | 155 | 1.0.1 *2019-09-13* 156 | ------------------ 157 | Custom emails 158 | 159 | * Bug: #128 - Undefined method `custom_email` 160 | * Bug: #122 - NameError: uninitialized constant 161 | * Bug: #119 - PostgreSQL querry error 162 | 163 | 1.0.0 164 | ----- 165 | Redmine 4.0 compatibility 166 | 167 | * Bug: #116 - raise errors bug 168 | * New: #114 - rails 5 169 | * Bug: #112 - devel 1.0.0 on redmine 4.0.0 problem. bug 170 | * New: #111 - Travis CI help wanted 171 | * New: #109 - Redmine 4.0 compatibility enhancement 172 | * Bug: #89 - Custom workflow for @time_entry doesn't raise on submit of issue form if spent time subform filled bug wontfix 173 | * Bug: #88 - Rendering bug after upgrading to Redmine 3.4.2 bug 174 | * Bug: #63 - Redmine 3.2.1 - Internal Server Error on new Issue with MS SQL bug 175 | * Bug: #60 - Fresh new install on 3.2.2.stable don't work bug 176 | * Bug: #46 - Error in pt-br.yml file bug 177 | 178 | 0.1.6 179 | ----- 180 | 181 | * New observable objects added (TimeEntry, Version) 182 | * Bug fixes 183 | 184 | 0.1.5 185 | ----- 186 | 187 | * New observable objects added (Project, Wiki Content, Attachment, Issue Attachments, Project Attachments, Wiki Page Attachments) 188 | * Ability to hook before_destroy and after_destroy events 189 | 190 | 0.1.4 191 | ----- 192 | 193 | * Ability to exit current workflow with `return` or `return true` and cancel workflow's execution chain with `return false` 194 | * Non-active workflows are now not checked for syntax. Now you can import non-valid (for your Redmine instance for example) workflow, make changes to it and then activate. 195 | 196 | 0.1.3 197 | ----- 198 | 199 | * Compatibility with Redmine 2.x.x returned, support of Redmine 1.x.x cancelled 200 | 201 | 0.1.2 202 | ----- 203 | 204 | * Added new observable objects. Along with Issue objects you can now watch for changes in User and Group objects 205 | * Added support of shared workflows - special workflows that running before all other workflows and can provide functions and classes for it 206 | * Added Mailer helper for sending custom emails from workflows (check Wiki) 207 | 208 | 0.1.1 209 | ----- 210 | 211 | * Import/export ability 212 | * Administrator can activate/deactivate workflows globally 213 | 214 | 0.1.0 215 | ----- 216 | 217 | * Compatibility with Redmine 3.x, support of Redmine 2.x.x has dropped (for Redmine 2.x.x please use version 0.0.6) 218 | 219 | 0.0.6 220 | ----- 221 | 222 | * Import/export ability 223 | 224 | 0.0.5 225 | ----- 226 | 227 | * Compatibility with latest versions of Redmine 2.x.x 228 | 229 | 0.0.4 230 | ----- 231 | 232 | * Added ability to enable workflows globally for all projects. No need to enable 'Custom workflows' project module anymore. Just go to the 'Administration' -> 'Custom workflows' section and enable or disable your workflows in one place. 233 | * Fixed bug with 'Status transition prohibited' when updating the issue status by the repository commit 234 | 235 | 0.0.3 236 | ----- 237 | 238 | * Compatibility with 1.2.x, 1.3.x 239 | 240 | 0.0.2 241 | ----- 242 | 243 | * Added ability to define after_save script along with before_save, improved logging, changed context of executing script to the issue. 244 | 245 | 0.0.1 246 | ----- 247 | 248 | * Initial commit 249 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at karel.picman@kontron.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## How to contribute to Redmine Custom Workflows plugin 2 | 3 | #### **Did you find a bug?** 4 | 5 | * **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/anteo/redmine_custom_workflows/issues). 6 | * If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/anteo/redmine_custom_workflows/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, **Redmine and the plugin version**, a part of the **production.log** related to the issue and **screen-shots**. 7 | 8 | #### **A wrong or missing translation?** 9 | 10 | * Feel free to update language files (_config/locales/*.yml_) in your mother language or languages you are familiar with and send them back to us via a **pull request**. 11 | 12 | #### **Do you want to patch the existing code?** 13 | 14 | * Make a new fork of the current development branch (_devel_). Make your changes and [create a pull request](https://github.com/anteo/redmine_custom_workflows/compare). Only pull requests into the **development branch** except those fixing serious errors will be accepted. 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | source 'https://rubygems.org' do 22 | gem 'acts_as_list' 23 | end 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Custom Workflows plug-in 3.0.1 2 | 3 | [![GitHub CI](https://github.com/anteo/redmine_custom_workflows/actions/workflows/rubyonrails.yml/badge.svg?branch=master)](https://github.com/anteo/redmine_custom_workflows/actions/workflows/rubyonrails.yml) 4 | [![Support Ukraine Badge](https://bit.ly/support-ukraine-now)](https://github.com/support-ukraine/support-ukraine) 5 | 6 | This plug-in provides a great functionality for those who is familiar with the Ruby language. 7 | It allows to customize workflow by defining own rules for issues processing. It's possible: 8 | 9 | * To change issue properties if some conditions are met. 10 | * To create new issues programmatically, if the conditions are met (for example you can create an issue in another 11 | project if the status of source issue is changed to specific value). 12 | * To raise custom errors which will be displayed to the user, if he does something wrong. 13 | * To do anything that conforms to your needs. 14 | 15 | Supported observable objects: 16 | 17 | * Attachment 18 | * Group 19 | * Issue 20 | * Issue relations 21 | * Time entry 22 | * User 23 | * Member 24 | * Version 25 | * Wiki 26 | * \ 27 | 28 | `` - a special type for workflows that are running before all other workflows and can provide libraries of 29 | additional functions or classes. 30 | 31 | Thanks to 32 | --------- 33 | 34 | The initial development was supported by [DOM Digital Online Media GmbH](https://www.dom.de). The present development 35 | is supported by [Kontron](https://www.kontron.com) 36 | 37 | Getting help 38 | ------------ 39 | 40 | Create an issue if you want to propose a feature or report a bug: 41 | 42 | https://github.com/anteo/redmine_custom_workflows/issues 43 | 44 | Check Wiki for examples and programming hints: 45 | 46 | https://github.com/anteo/redmine_custom_workflows/wiki 47 | 48 | Check this repo with some tested in work custom workflows: 49 | 50 | https://github.com/VoronyukM/custom-workwlows 51 | 52 | Installation 53 | ------------ 54 | 55 | From a ZIP file: 56 | 57 | * Download the latest version of the plugin. 58 | * In case of an upgrade, remove the original *plugins/redmine_custom_workflows* folder. 59 | * Unzip it to /plugins. 60 | 61 | From the Git repository: 62 | 63 | * Clone the repository: 64 | 65 | ```shell 66 | cd redmine/plugins 67 | git clone https://github.com/anteo/redmine_custom_workflows.git 68 | ``` 69 | 70 | After download: 71 | 72 | * Run migrations and restart the application: 73 | 74 | ```shell 75 | cd redmine 76 | bundle install 77 | bundle exec rake redmine:plugins:migrate NAME=redmine_custom_workflows RAILS_ENV=production 78 | chown -R www-data:www-data plugins/redmine_custom_workflows 79 | systemctl restart apache2 80 | ``` 81 | 82 | Configuration 83 | ------------- 84 | 85 | First, you need to define your own custom workflow(s). We already included one, called "Duration/Done Ratio/Status 86 | correlation". You'll find it after installing the plug-in. It demonstrates some possibilities of the plug-in. 87 | 88 | Go to the **_Administration_** section, then select **_Custom workflows_**. A list of defined workflows will appear. Here 89 | you can create a new workflow, update, reorder or delete the existing workflows. The order of workflows specifies the 90 | order in which the workflow scripts will be executed. 91 | 92 | Then click the **Create a custom workflow** button. Enter a short name and full description. Below you will see two text 93 | areas. Fill one or both text areas with Ruby-language scripts that will be executed before and after saving the issue 94 | (on _before_save_ and _after_save_ callbacks respectively). 95 | 96 | Both scripts are executed in the context of the issue. So, access properties and methods of the issue directly (or 97 | through keyword `self`). You can also raise exceptions by raising `RedmineCustomWorkflows::Errors::WorkflowError` exception. 98 | If you change some properties of the issue before saving it, it will be revalidated then and additional validation errors 99 | can appear. 100 | 101 | E.g.: 102 | 103 | ```ruby 104 | raise RedmineCustomWorkflows::Errors::WorkflowError, 'Your message' 105 | ``` 106 | 107 | You can also display an info/warning/error message to the user using an observed object property `custom_workflow_messages`. 108 | 109 | E.g.: 110 | 111 | ```ruby 112 | self.custom_workflow_messages[:notice] = 'Custom workflow info' 113 | self.custom_workflow_messages[:warning] = 'Custom workflow warning' 114 | self.custom_workflow_messages[:error] = 'Custom workflow error' 115 | ``` 116 | 117 | Some environmental variables are available in observable objects. 118 | 119 | E.g.: 120 | 121 | ```ruby 122 | self.custom_workflow_env[:remote_ip] 123 | ``` 124 | 125 | An email can be sent from within a script. 126 | 127 | E.g.: 128 | 129 | ```ruby 130 | CustomWorkflowMailer.deliver_custom_email(user, subject: subject, text_body: text) 131 | ``` 132 | 133 | Enabling custom workflows for projects 134 | -------------------------------------- 135 | 136 | After you defined your custom workflow(s), you need to enable it for particular project(s). (This is valid for project 137 | related observable objects.) There are two ways of doing 138 | this. 139 | * While editing existing or creating a new custom workflow; 140 | * In the project's settings (if the user has appropriate permission). Open **_Project settings_**. Go to 141 | **_Custom workflows_** tab of the project's settings and enable those workflows you need for this project. 142 | 143 | Now go to the **_Issues_** and test it. 144 | 145 | Examples 146 | -------- 147 | 148 | ### Duration/Done Ratio/Status correlation example 149 | 150 | Fill the "before save" script with: 151 | 152 | ```ruby 153 | if done_ratio_changed? 154 | if (done_ratio == 100) && (status_id == 2) 155 | self.status_id = 3 156 | elsif [1,3,4].include?(status_id) && (done_ratio < 100) 157 | self.status_id = 2 158 | end 159 | end 160 | 161 | if status_id_changed? 162 | if (status_id == 2) 163 | self.start_date ||= Time.now 164 | end 165 | if (status_id == 3) 166 | self.done_ratio = 100 167 | self.start_date ||= created_on 168 | self.due_date ||= Time.now 169 | end 170 | end 171 | ``` 172 | 173 | ### Example of creating subtask if the issue's status has changed 174 | 175 | Fill the "before save" script with: 176 | 177 | ```ruby 178 | @need_create = status_id_changed? && !new_record? 179 | ``` 180 | 181 | Fill the "after save" script with: 182 | 183 | ```ruby 184 | if @need_create 185 | issue = Issue.new( 186 | author: User.current, 187 | project: project, 188 | tracker: tracker, 189 | assigned_to: author, 190 | parent_issue_id: id, 191 | subject: 'Subtask', 192 | description: 'Description') 193 | issue.save! 194 | end 195 | ``` 196 | 197 | Do not forget to check whether the issue is just created. Here, we create a new issue and newly created issue will also 198 | be passed to this script on save event. So, without a check, it will create another sub-issue. And so on. Thus, it will 199 | fall into infinite loop. 200 | 201 | Compatibility 202 | ------------- 203 | 204 | This plugin requires **Redmine 6.x** to function properly. Ensure that your Redmine installation is up-to-date before proceeding with the installation. 205 | 206 | If you are using an older version of Redmine, please check the available plugin releases: 207 | 👉 [Redmine Custom Workflows Releases](https://github.com/anteo/redmine_custom_workflows/releases) 208 | 209 | **Note:** 210 | When downloading the plugin from a ZIP file, ensure that the extracted folder does **not** contain version numbers in its name (e.g., `redmine_custom_workflows-3.0.0`). Rename the folder to just `redmine_custom_workflows` before proceeding with the installation to avoid any compatibility issues. 211 | 212 | -------------------------------------------------------------------------------- /after_init.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require 'redmine' 22 | require "#{File.dirname(__FILE__)}/lib/redmine_custom_workflows" 23 | 24 | def custom_workflows_init 25 | # Administration menu extension 26 | Redmine::MenuManager.map :admin_menu do |menu| 27 | menu.push :custom_workflows, { controller: 'custom_workflows', action: 'index' }, 28 | caption: :label_custom_workflow_plural, icon: 'workflows', 29 | html: { class: 'icon icon-workflows workflows' } 30 | end 31 | end 32 | 33 | if Redmine::Plugin.installed?('easy_extensions') 34 | ActiveSupport.on_load(:easyproject, yield: true) do 35 | custom_workflows_init 36 | end 37 | else 38 | custom_workflows_init 39 | end 40 | -------------------------------------------------------------------------------- /app/controllers/custom_workflows_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Custom workflows controller 22 | class CustomWorkflowsController < ApplicationController 23 | layout 'admin' 24 | before_action :require_admin 25 | before_action :find_workflow, only: %i[show edit update destroy export change_status reorder] 26 | 27 | def reorder 28 | from = @workflow.position 29 | to = params[:custom_workflow][:position].to_i 30 | CustomWorkflow.transaction do 31 | CustomWorkflow.find_each do |wf| 32 | if wf.position == from 33 | wf.position = to 34 | elsif wf.position >= to && wf.position < from 35 | # Move up 36 | wf.position = wf.position + 1 37 | elsif wf.position <= to && wf.position > from 38 | # Move down 39 | wf.position = wf.position - 1 40 | end 41 | wf.save 42 | end 43 | end 44 | respond_to do |format| 45 | format.html 46 | format.js 47 | end 48 | end 49 | 50 | def index 51 | @workflows = CustomWorkflow.includes(:projects).order(position: :asc) 52 | respond_to do |format| 53 | format.html 54 | end 55 | end 56 | 57 | def export 58 | send_data @workflow.export_as_xml, filename: "#{@workflow.name}.xml", type: :xml 59 | end 60 | 61 | def show 62 | respond_to do |format| 63 | format.html { redirect_to edit_custom_workflow_path } 64 | end 65 | end 66 | 67 | def new 68 | @workflow = CustomWorkflow.new 69 | @workflow.author = cookies[:custom_workflows_author] 70 | respond_to do |format| 71 | format.html 72 | end 73 | end 74 | 75 | def edit; end 76 | 77 | def import 78 | xml = params[:file].read 79 | begin 80 | @workflow = CustomWorkflow.import_from_xml(xml) 81 | @workflow.active = false 82 | if @workflow.save 83 | flash[:notice] = l(:notice_successful_import) 84 | else 85 | flash[:error] = @workflow.errors.full_messages.to_sentence 86 | end 87 | rescue StandardError => e 88 | Rails.logger.warn "Workflow import error: #{e.message}\n #{e.backtrace.join("\n ")}" 89 | flash[:error] = l(:error_failed_import) 90 | end 91 | respond_to do |format| 92 | format.html { redirect_to(custom_workflows_path) } 93 | end 94 | end 95 | 96 | def create 97 | @workflow = CustomWorkflow.new 98 | @workflow.position = CustomWorkflow.count + 1 99 | @workflow.observable = params[:custom_workflow][:observable] 100 | update_from_params 101 | respond_to do |format| 102 | if params.key?(:commit) && @workflow.save 103 | flash[:notice] = l(:notice_successful_create) 104 | cookies[:custom_workflows_author] = @workflow.author 105 | format.html { redirect_to(custom_workflows_path) } 106 | else 107 | format.html { render action: :new } 108 | end 109 | end 110 | end 111 | 112 | def change_status 113 | respond_to do |format| 114 | if @workflow.update(active: params[:active]) 115 | flash[:notice] = l(:notice_successful_status_change) 116 | format.html { redirect_to(custom_workflows_path) } 117 | else 118 | format.html { render action: :edit } 119 | end 120 | end 121 | end 122 | 123 | def update 124 | respond_to do |format| 125 | update_from_params 126 | if params.key?(:commit) && @workflow.save 127 | flash[:notice] = l(:notice_successful_update) 128 | format.html { redirect_to(custom_workflows_path) } 129 | else 130 | format.html { render action: :edit } 131 | end 132 | end 133 | end 134 | 135 | def destroy 136 | @workflow.destroy 137 | respond_to do |format| 138 | flash[:notice] = l(:notice_successful_delete) 139 | format.html { redirect_to(custom_workflows_path) } 140 | end 141 | end 142 | 143 | private 144 | 145 | def find_workflow 146 | @workflow = CustomWorkflow.find(params[:id]) 147 | rescue ActiveRecord::RecordNotFound 148 | render_404 149 | end 150 | 151 | def update_from_params 152 | @workflow.before_save = params[:custom_workflow][:before_save] 153 | @workflow.after_save = params[:custom_workflow][:after_save] 154 | @workflow.name = params[:custom_workflow][:name] 155 | @workflow.description = params[:custom_workflow][:description] 156 | @workflow.is_for_all = params[:custom_workflow][:is_for_all] == '1' 157 | @workflow.author = params[:custom_workflow][:author] 158 | @workflow.active = params[:custom_workflow][:active] 159 | @workflow.shared_code = params[:custom_workflow][:shared_code] 160 | @workflow.before_add = params[:custom_workflow][:before_add] 161 | @workflow.after_add = params[:custom_workflow][:after_add] 162 | @workflow.before_remove = params[:custom_workflow][:before_remove] 163 | @workflow.after_remove = params[:custom_workflow][:after_remove] 164 | @workflow.before_destroy = params[:custom_workflow][:before_destroy] 165 | @workflow.after_destroy = params[:custom_workflow][:after_destroy] 166 | @workflow.project_ids = params[:custom_workflow][:project_ids] 167 | end 168 | end 169 | -------------------------------------------------------------------------------- /app/models/custom_workflow_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require 'mailer' 22 | 23 | # Custom workflow mailer model 24 | class CustomWorkflowMailer < Mailer 25 | layout 'mailer' 26 | 27 | def self.deliver_custom_email(user, headers = {}) 28 | custom_email(user, headers, headers.dup).deliver_later 29 | end 30 | 31 | def custom_email(user, headers, cw_headers) 32 | headers[:to] ||= user.mail 33 | text_body = cw_headers[:text_body] 34 | html_body = cw_headers[:html_body] 35 | template_name = cw_headers[:template_name] 36 | template_params = cw_headers[:template_params] || {} 37 | if text_body || html_body 38 | mail headers do |format| 39 | format.text { render plain: text_body } if text_body.present? 40 | format.html { render plain: html_body } if html_body.present? && !Setting.plain_text_mail? 41 | end 42 | elsif template_name 43 | template_params.each { |k, v| instance_variable_set(:"@#{k}", v) } 44 | mail headers do |format| 45 | format.text { render template_name } 46 | format.html { render template_name } unless Setting.plain_text_mail? 47 | end 48 | else 49 | raise 'Not :text_body, :html_body or :template_name specified' 50 | end 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /app/views/custom_workflow_mailer/custom_email.html.erb: -------------------------------------------------------------------------------- 1 | <% 2 | # Redmine plugin for Custom Workflows 3 | # 4 | # Anton Argirov, Karel Pičman 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | %> 20 | 21 |

22 | <%= @text %> 23 |

24 | -------------------------------------------------------------------------------- /app/views/custom_workflow_mailer/custom_email.text.erb: -------------------------------------------------------------------------------- 1 | <% 2 | # Redmine plugin for Custom Workflows 3 | # 4 | # Anton Argirov, Karel Pičman 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | %> 20 | 21 | <%= @text %> 22 | -------------------------------------------------------------------------------- /app/views/custom_workflows/_form.html.erb: -------------------------------------------------------------------------------- 1 | <% 2 | # Redmine plugin for Custom Workflows 3 | # 4 | # Anton Argirov, Karel Pičman 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | %> 20 | 21 |
22 |
23 |
24 |

<%= f.text_field :name, required: true %>

25 |

<%= f.text_field :author, label: :field_custom_workflow_author %> 26 | <%= l(:text_custom_workflow_author) %> 27 |

28 |

<%= f.select :observable, 29 | CustomWorkflow::OBSERVABLES.collect { |o| [l("custom_workflow_observable_#{o}"), o] }, {}, 30 | onchange: 'this.form.submit()', 31 | disabled: !@workflow.new_record? %>

32 |

<%= f.text_area :description, class: 'wiki-edit' %>

33 | <% if @workflow.projects_association? %> 34 |

35 | <%= f.check_box :is_for_all, onclick: "checkAndDisable('custom_workflow_enabled_projects', this.checked);", 36 | label: :field_enabled_for_all_projects %> 37 |

38 | <% end %> 39 |

<%= f.check_box :active, label: l(:field_active) %>

40 |
41 |
42 | <% if @workflow.projects_association? %> 43 |
44 |
45 | <%= content_tag 'fieldset', id: 'custom_workflow_enabled_projects' do %> 46 | 47 | <%= toggle_checkboxes_link("#custom_workflow_enabled_projects input[type=checkbox]") %> 48 | <%= l(:label_project_plural) %> 49 | 50 | <%= render_project_nested_lists(Project.visible.active) do |p| %> 51 | <%= content_tag 'label', 52 | check_box_tag('custom_workflow[project_ids][]', p.id, 53 | @workflow.project_ids.include?(p.id) || @workflow.is_for_all?, id: nil, 54 | disabled: @workflow.is_for_all?) + ' ' + h(p), class: 'block' %> 55 | <% end %> 56 | <%= hidden_field_tag 'custom_workflow[project_ids][]', '', id: nil %> 57 | <% end %> 58 |
59 |
60 | <% end %> 61 |
62 | 63 |
64 |
65 | <%= l(:label_workflow_scripts) %> 66 | <% observable = @workflow.observable.to_sym %> 67 |
68 | <%= l("text_custom_workflow_#{observable}_code_note") %> 69 |
70 | <% case observable %> 71 | <% when :shared %> 72 | <%= f.text_area :shared_code, cols: 40, rows: 20, wrap: 'off', class: 'custom_workflow_script' %> 73 | <% when *CustomWorkflow::COLLECTION_OBSERVABLES %> 74 | <% collapsed = !(@workflow.before_add.present? || @workflow.after_add.present? || @workflow.errors[:base].present?) %> 75 | 88 | <% collapsed = !(@workflow.before_remove.present? || @workflow.after_remove.present?) %> 89 | 102 | <% when *CustomWorkflow::SINGLE_OBSERVABLES %> 103 | <% collapsed = (not (@workflow.before_save.present? or @workflow.after_save.present? or @workflow.errors[:base].present?)) %> 104 | 123 | <% collapsed = !(@workflow.before_destroy.present? || @workflow.after_destroy.present?) %> 124 | 138 | <% end %> 139 |
140 |
141 | 142 | <%= wikitoolbar_for :custom_workflow_description %> 143 | -------------------------------------------------------------------------------- /app/views/custom_workflows/edit.html.erb: -------------------------------------------------------------------------------- 1 | <% 2 | # Redmine plugin for Custom Workflows 3 | # 4 | # Anton Argirov, Karel Pičman 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | %> 20 | 21 |

<%= link_to l(:label_custom_workflow_plural), custom_workflows_path %> » <%= @workflow %>

22 | 23 | <%= error_messages_for 'workflow' %> 24 | 25 | <%= labelled_form_for @workflow do |f| %> 26 | <%= render partial: 'form', locals: { f: f } %> 27 | <%= submit_tag l(:button_save) %> 28 | <% end %> 29 | 30 | <% html_title l(:label_custom_workflow_plural), @workflow, l(:label_administration) %> 31 | -------------------------------------------------------------------------------- /app/views/custom_workflows/index.html.erb: -------------------------------------------------------------------------------- 1 | <% 2 | # Redmine plugin for Custom Workflows 3 | # 4 | # Anton Argirov, Karel Pičman 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | %> 20 | 21 | <% html_title l(:label_custom_workflow_plural) %> 22 |
23 | <%= link_to sprite_icon('add', l(:label_custom_workflow_new)), new_custom_workflow_path, class: 'icon icon-add' %> 24 | <%= actions_dropdown do %> 25 | <%= link_to sprite_icon('import', l(:label_custom_workflow_import)), '#', class: 'icon icon-move', 26 | onclick: "showModal('import-dialog', '450px'); return false;" %> 27 | <% end %> 28 |
29 | 30 |

<%= l(:label_custom_workflow_plural) %>

31 | 32 |
33 | <% if @workflows.any? %> 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | <% @workflows.each do |workflow| %> 45 | 46 | 47 | 48 | 49 | 64 | 65 | <% end %> 66 | 67 |
<%= l(:field_name) %><%= l(:field_observable) %><%= l(:field_author) %>
<%= link_to workflow.name, edit_custom_workflow_path(workflow) %><%= l("custom_workflow_observable_#{workflow.observable}") %><%= mail_to workflow.author if workflow.author.present? %> 50 | <%= reorder_handle workflow, url: url_for(action: 'reorder', id: workflow) %> 51 | <% if workflow.active? %> 52 | <%= link_to sprite_icon('lock', l(:button_custom_workflow_deactivate)), 53 | custom_workflow_status_path(workflow, active: false), class: 'icon icon-lock', 54 | method: :post %> 55 | <% else %> 56 | <%= link_to sprite_icon('unlock', l(:button_activate)), 57 | custom_workflow_status_path(workflow, active: true), class: 'icon icon-unlock', 58 | method: :post %> 59 | <% end %> 60 | <%= link_to sprite_icon('download', l(:label_custom_workflow_export)), 61 | export_custom_workflow_path(workflow), class: 'icon icon-download', method: :get %> 62 | <%= delete_link custom_workflow_path(workflow) %> 63 |
68 | <% else %> 69 |

<%= l(:label_no_data) %>

70 | <% end %> 71 |
72 |
73 |

<%= l(:label_custom_workflow_import) %>

74 | <%= form_tag import_custom_workflow_path, :multipart => true do %> 75 |

76 | <%= l(:field_custom_workflow_file) %>: 77 |

78 |

79 | <%= file_field_tag 'file', accept: 'application/xml' %> 80 |

81 |

82 | <%= submit_tag l(:button_import), name: nil, onclick: 'hideModal(this);' %> 83 | <%= submit_tag l(:button_cancel), name: nil, onclick: 'hideModal(this);', type: 'button' %> 84 |

85 | <% end %> 86 |
87 | 88 | <%= javascript_tag do %> 89 | $(function() { 90 | $("table.custom-workflows tbody").positionedItems(); 91 | }); 92 | <% end %> 93 | -------------------------------------------------------------------------------- /app/views/custom_workflows/new.html.erb: -------------------------------------------------------------------------------- 1 | <% 2 | # Redmine plugin for Custom Workflows 3 | # 4 | # Anton Argirov, Karel Pičman 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | %> 20 | 21 |

<%= link_to l(:label_custom_workflow_plural), custom_workflows_path %> » <%= l(:label_custom_workflow_new) %>

22 | 23 | <%= error_messages_for 'workflow' %> 24 | 25 | <%= labelled_form_for @workflow do |f| %> 26 | <%= render partial: 'form', locals: { f: f } %> 27 | <%= submit_tag l(:button_create) %> 28 | <% end %> 29 | 30 | <% html_title l(:label_custom_workflow_plural), l(:label_custom_workflow_new), l(:label_administration) %> 31 | -------------------------------------------------------------------------------- /app/views/custom_workflows/reorder.js.erb: -------------------------------------------------------------------------------- 1 | <% 2 | # encoding: utf-8 3 | # 4 | # Redmine plugin for Custom Workflows 5 | # 6 | # Anton Argirov, Karel Pičman 7 | # 8 | # This program is free software; you can redistribute it and/or 9 | # modify it under the terms of the GNU General Public License 10 | # as published by the Free Software Foundation; either version 2 11 | # of the License, or (at your option) any later version. 12 | # 13 | # This program is distributed in the hope that it will be useful, 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | # GNU General Public License for more details. 17 | # 18 | # You should have received a copy of the GNU General Public License 19 | # along with this program; if not, write to the Free Software 20 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 21 | %> 22 | 23 | location.replace('<%= custom_workflows_path %>'); 24 | -------------------------------------------------------------------------------- /app/views/projects/settings/_custom_workflow.html.erb: -------------------------------------------------------------------------------- 1 | <% 2 | # Redmine plugin for Custom Workflows 3 | # 4 | # Anton Argirov, Karel Pičman 5 | # 6 | # This program is free software; you can redistribute it and/or 7 | # modify it under the terms of the GNU General Public License 8 | # as published by the Free Software Foundation; either version 2 9 | # of the License, or (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with this program; if not, write to the Free Software 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | %> 20 | 21 | <%= form_for @project do %> 22 | <%= hidden_field_tag :tab, 'custom_workflow' %> 23 | <%= hidden_field_tag 'project[custom_workflow_ids][]', '' %> 24 |
25 | <%= l(:text_select_project_custom_workflows) %> 26 | <% cws = CustomWorkflow.where(observable: CustomWorkflow::PROJECT_OBSERVABLES) %> 27 | <% if cws.any? %> 28 |
29 | <% cws.find_each do |w| %> 30 |
31 | 40 |
41 |
<%= textilizable w.description %>
42 | <% end %> 43 |
44 | <% else %> 45 |

<%= l(:label_no_data) %>

46 | <% end %> 47 |
48 | <%= submit_tag l(:button_save) %> 49 | <% end %> 50 | -------------------------------------------------------------------------------- /assets/stylesheets/custom_workflows.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Redmine plugin for Document Management System "Features" 3 | * 4 | * Anton Argirov, Karel Pičman 5 | * 6 | * This program is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU General Public License 8 | * as published by the Free Software Foundation; either version 2 9 | * of the License, or (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 | */ 20 | 21 | #tab-content-custom_workflows .disabled { 22 | color: silver; 23 | } 24 | 25 | table.list.custom-workflows tr.disabled { 26 | color: silver; 27 | } 28 | 29 | #custom_workflow_enabled_projects ul.root { 30 | max-height: 400px; 31 | overflow-y: auto; 32 | } 33 | 34 | .custom-workflow-hidden { 35 | display: none; 36 | } 37 | 38 | .custom-workflow-info { 39 | text-align: justify; 40 | margin-bottom: 1em; 41 | } 42 | 43 | div#custom_workflow_scripts label { 44 | font-weight: normal; 45 | text-align: left; 46 | margin-left: 0; 47 | width: auto; 48 | } -------------------------------------------------------------------------------- /config/locales/cs.yml: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | # 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | cs: 22 | project_module_custom_workflows_module: Uživatelské procesy 23 | permission_manage_project_workflow: Spravovat uživatelské procesy 24 | 25 | label_custom_workflow: Uživatelský proces 26 | label_custom_workflow_plural: Uživatelské procesy 27 | label_custom_workflow_new: Vytvořit uživatelský proces 28 | label_workflow_scripts: Skript procesu 29 | label_custom_workflow_export: Export 30 | label_custom_workflow_import: Importovat proces 31 | label_save_workflows: Uložení sledovaných objektů 32 | label_destroy_workflows: Smazání sledovaných objektů 33 | label_add_workflows: Přidání sledovaných objektů do sezanmu 34 | label_remove_workflows: Odstranění sledovaných objektů za seznamu 35 | 36 | button_custom_workflow_deactivate: Deaktivovat 37 | 38 | field_after_save: Skript spuštěný po uložení sledovaného objektu 39 | field_before_save: Skript spuštěný před uložením sledovaného objektu 40 | field_after_destroy: Skript spuštěný po smazání sledovaného objektu 41 | field_before_destroy: Skript spuštěný před smazáním sledovaného objektu 42 | field_after_add: Skript spuštěný po přidání sledovaného objektu do seznamu 43 | field_before_add: Skript spuštěný před přidáním sledovaného objektu do seznamu 44 | field_after_remove: Skript spuštěný po odstranění sledovaného objektu ze seznamu 45 | field_before_remove: Skript spuštěný před odstraněním sledovaného objektu ze seznamu 46 | field_shared_code: Sdílený kód 47 | field_observable: Sledovaný objekt 48 | field_enabled_for_all_projects: Povoleno pro všechny projekty 49 | field_custom_workflow_author: Autorův e-mail 50 | field_custom_workflow_file: Select the XML file previously exported process 51 | field_custom_workflow: 52 | script: Skript 53 | 54 | notice_successful_import: Uživatelský proces byl úspěšně naimportován 55 | notice_successful_status_change: Status byl úspěšně změněn 56 | error_failed_import: Chyba při importu uživatelského procesu (Neznámý formát? Podívejte se do logu.) 57 | 58 | activerecord: 59 | errors: 60 | messages: 61 | invalid_script: "obsahuje chyby: %{error}" 62 | custom_workflow_error: Chyba uživatelského procesu (kontaktujte administrátora) 63 | new_status_invalid: "změna z '%{old_status}' na '%{new_status}' není povolena" 64 | scripts_absent: Musí být definován alespoň jeden skript 65 | 66 | text_select_project_custom_workflows: Vyberte uživatelský skript projektu 67 | text_custom_workflow_before_save_note: Zde můžete měnit vlastnosti úkolu. Ve skriptu nevytvářejte ani neměňte 68 | související úkoly. Pro ukončení skriptu chybou použijte `raise RedmineCustomWorkflows::Errors::WorkflowError, 'Zpráva uživateli'`. 69 | text_custom_workflow_after_save_note: Zde můžete aktualizovat nebo vytvářet souvissející úkoly. Mějte na paměti, že 70 | tento skript bude také vykonán pro nově vytvořené úkoly. Takže nezapomeňte udělat vhodné kontroly pro zabránění 71 | rekurzivnímu volání. 72 | text_custom_workflow_issue_code_note: Skripty jsou vykonávány v rámci objektu úkolu stejně jako volání `before_save` 73 | a `after_save` funkcí. Takže lze použít přímo vlastností úkolů. Proměnné (@variable) jsou rovněž dostupné a lze jich 74 | použít. 75 | text_custom_workflow_issue_relation_code_note: Skripty jsou vykonávány v rámci objektu vazby mezi úkoly stejně jako 76 | volání `before_save` a `after_save` funkcí. Takže lze použít přímo vlastností vazby mezi úkoly. Proměnné (@variable) 77 | jsou rovněž dostupné a lze jich použít. 78 | text_custom_workflow_shared_code_note: Tento kód bude spuštěn před jakýmkoli jiným procesem a může obsahovat sdílený 79 | kód, např. funkce a třídy, které jsou potřeba v jiných procesech 80 | text_custom_workflow_user_code_note: Skripty jsou vykonávány v rámci objektu uživatel, když se objekt mění (maže). 81 | Můžete přímo použít metody a vlastnosti objektu. 82 | text_custom_workflow_member_code_note: Skripty jsou vykonávány v rámci objektu člen, když se objekt mění (maže). 83 | Můžete přímo použít metody a vlastnosti objektu. 84 | text_custom_workflow_group_code_note: Skripty jsou vykonávány v rámci objektu skupina, když se objekt mění (maže). 85 | Můžete přímo použít metody a vlastnosti objektu. 86 | text_custom_workflow_group_users_code_note: Tyto skripty jsou vykonávány, když je uživatel přidán nebo odebrán ze 87 | skupiny. Pro přístup k objektům použijte proměnné @user a @group. 88 | text_custom_workflow_attachment_code_note: Skripty jsou vykonávány v rámci objektu příloha, když se tento objekt mění 89 | (maže se). Můžete přímo použít metody a vlastnosti objektu. Mějte na paměti, že se to týká všech typů příloh 90 | (u úkolů, dokumentů, wiki stránek, atd.), takže byste měli zkontrolovat proměnnou 'container_type' pro určení, 91 | o jakou přílohu se jedná. 92 | text_custom_workflow_issue_attachments_code_note: Tento skripty se vykonávají když je příloha přidána nebo odebrába 93 | z úkolu. Můžete použít proměnné @issue a @attachment pro přístup k těmto objektům ve skriptu. 94 | text_custom_workflow_project_code_note: SSkripty jsou vykonávány v rámci objektu projekt, když se objekt mění (maže). 95 | Můžete přímo použít metody a vlastnosti objektu. 96 | text_custom_workflow_project_attachments_code_note: Tyto skripty jsou vykonávány, když se přidává nebo se maže soubor 97 | u projektu. Můžete použít proměnné @project a @attachment pro přístup k těmto objektům ve skriptu. 98 | text_custom_workflow_wiki_content_code_note: Tyto kripty jsou vykonávány v rámci objektu Wiki, když se mění nebo se 99 | maže. Můžete přímo použít metody a vlastnosti objektu. 100 | text_custom_workflow_wiki_page_attachments_code_note: Tyto skripty jsou vykonávány, když se přidává nebo se maže 101 | příloha u wiki stránky. Můžete použít proměnné @page a @attachment pro přístup k těmto objektům ve skriptu. 102 | text_custom_workflow_time_entry_code_note: Skripty jsou vykonávány v rámci objektu časový záznam, kdyže se mění nebo 103 | se maže. Můžete přímo použít metody a vlastnosti objektu. 104 | text_custom_workflow_version_code_note: Skripty jsou vykonávány v rámci objektu verze, když se mění nebo se maže. 105 | Můžete přímo použít metody a vlastnosti objektu. 106 | text_custom_workflow_before_destroy_note: Zabránit smazání objektu lze pomocí `return false`. 107 | 108 | text_no_enabled_projects: Žádné projekty 109 | text_custom_workflow_author: Bude zahrnuto do exportovaného XML 110 | text_custom_workflow_disabled: zakázáno administrátorem 111 | text_custom_workflow_is_for_all: povoleno pro všechny projekty 112 | 113 | custom_workflow_observable_shared: 114 | custom_workflow_observable_issue: Úkol 115 | custom_workflow_observable_issue_attachments: Přílohy úkolů 116 | custom_workflow_observable_group: Skupina 117 | custom_workflow_observable_user: Uživatel 118 | custom_workflow_observable_attachment: Příloha 119 | custom_workflow_observable_member: Člen 120 | custom_workflow_observable_project: Projekt 121 | custom_workflow_observable_project_attachments: Soubory 122 | custom_workflow_observable_wiki_content: Wiki 123 | custom_workflow_observable_wiki_page_attachments: Přílohy na wiki 124 | custom_workflow_observable_group_users: Uživatelé skupin 125 | custom_workflow_observable_time_entry: Časový záznam 126 | custom_workflow_observable_version: Verze 127 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | RedmineApp::Application.routes.draw do 22 | resources :custom_workflows do 23 | member do 24 | # Nothing 25 | end 26 | end 27 | post '/custom_workflows/import', to: 'custom_workflows#import', as: 'import_custom_workflow' 28 | post '/custom_workflows/:id', to: 'custom_workflows#update' 29 | get '/custom_workflows/:id/export', to: 'custom_workflows#export', as: 'export_custom_workflow' 30 | post '/custom_workflows/:id/change_status', to: 'custom_workflows#change_status', as: 'custom_workflow_status' 31 | put '/custom_workflows/:id/reorder', to: 'custom_workflows#reorder' 32 | end 33 | -------------------------------------------------------------------------------- /db/migrate/20110915084858_create_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Create the model table 22 | class CreateCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def change 24 | create_table :custom_workflows, force: true do |t| 25 | t.references :project 26 | t.text :script, null: true, default: nil 27 | t.boolean :is_enabled, null: false, default: false 28 | t.timestamps 29 | t.index :project_id, unique: true 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /db/migrate/20120601054047_alter_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Modify the table 22 | class AlterCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def up 24 | change_table(:custom_workflows, bulk: true) do |t| 25 | t.remove_index :project_id 26 | t.remove :project_id 27 | # TODO: The column cannot be removed on SQL server due to NOT NULL constraint. 28 | # The constraint's name is random and therefore cannot be easily removed. 29 | t.remove :is_enabled if ActiveRecord::Base.connection.adapter_name.downcase != 'sqlserver' 30 | t.string :name, null: false, default: '' 31 | t.string :description, :string, null: false, default: '' 32 | t.integer :position, :integer, null: false, default: 1 33 | end 34 | end 35 | 36 | def down 37 | change_table(:custom_workflows, bulk: true) do |t| 38 | t.references :project 39 | t.index :project_id, unique: true 40 | t.boolean :is_enabled, null: false, default: false 41 | t.remove :name 42 | t.remove :description 43 | t.remove :position 44 | end 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /db/migrate/20120601054557_create_custom_workflows_projects.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Add table custom_workflows_projects 22 | class CreateCustomWorkflowsProjects < ActiveRecord::Migration[4.2] 23 | def change 24 | create_join_table :projects, :custom_workflows 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /db/migrate/20120628060102_change_custom_workflows_description_type.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Modify column 22 | class ChangeCustomWorkflowsDescriptionType < ActiveRecord::Migration[4.2] 23 | def up 24 | change_column :custom_workflows, :description, :text, null: true, default: nil 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /db/migrate/20120908085222_add_after_save_to_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Modify columns 22 | class AddAfterSaveToCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def up 24 | change_table(:custom_workflows, bulk: true) do |t| 25 | t.rename :script, :before_save 26 | t.text :after_save, null: true, after: :before_save 27 | end 28 | end 29 | 30 | def down 31 | change_table(:custom_workflows, bulk: true) do |t| 32 | t.remove :after_save 33 | t.rename :before_save, :script 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /db/migrate/20121005085252_add_is_for_all_to_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Add column 22 | class AddIsForAllToCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def change 24 | add_column :custom_workflows, :is_for_all, :boolean, 25 | null: false, default: false 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /db/migrate/20150522134436_make_after_save_and_before_save_nullable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Modify columns 22 | class MakeAfterSaveAndBeforeSaveNullable < ActiveRecord::Migration[4.2] 23 | def up 24 | change_table(:custom_workflows, bulk: true) do |t| 25 | t.change :before_save, :text, null: true, default: nil 26 | t.change :after_save, :text, null: true, default: nil 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /db/migrate/20150522134437_set_position_field_nullable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Modify the column position 22 | class SetPositionFieldNullable < ActiveRecord::Migration[4.2] 23 | def up 24 | change_column :custom_workflows, :position, :integer, null: true 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /db/migrate/20150525083345_add_author_to_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Add timestamp 22 | class AddAuthorToCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def change 24 | change_table(:custom_workflows, bulk: true) do |t| 25 | t.string :author, null: true 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /db/migrate/20150526132244_create_example_workflow.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Add an example 22 | class CreateExampleWorkflow < ActiveRecord::Migration[4.2] 23 | def up 24 | CustomWorkflow.reset_column_information 25 | name = 'Duration/Done Ratio/Status correlation' 26 | old = CustomWorkflow.where(name: name).first 27 | old&.destroy 28 | cw = CustomWorkflow.new 29 | cw.name = name 30 | cw.author = 'anton.argirov@gmail.com' 31 | cw.description = %( 32 | Set up a correlation between the start date, due date, done ratio and status of issues. 33 | 34 | * If done ratio is changed to 100% and status is "In Process", status changes to "Resolved" 35 | * If status is "New", "Resolved" or "Feedback" and done ratio is changed to value less than 100%, status changes 36 | to "In process" 37 | * If status is changed to "In process" and start date is not set, then it sets to current date 38 | * If status is changed to "Resolved" and end date is not set, then it set to due date 39 | 40 | To use this script properly, turn off "Use current date as start date for new issues" option in the settings as 41 | this script already do it own way. 42 | ) 43 | cw.before_save = %( 44 | if @issue.done_ratio_changed? 45 | if (@issue.done_ratio == 100) && (@issue.status_id == 2) 46 | @issue.status_id = 3 47 | elsif [1,3,4].include?(@issue.status_id) && (@issue.done_ratio < 100) 48 | @issue.status_id = 2 49 | end 50 | end 51 | 52 | if @issue.status_id_changed? 53 | if @issue.status_id == 2 54 | @issue.start_date ||= Time.now 55 | end 56 | if @issue.status_id == 3 57 | @issue.done_ratio = 100 58 | @issue.start_date ||= @issue.created_on 59 | @issue.due_date ||= Time.now 60 | end 61 | end 62 | ) 63 | cw.save! 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /db/migrate/20150526134840_add_active_field_to_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Extend custom_workflows table 22 | class AddActiveFieldToCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def change 24 | add_column :custom_workflows, :active, :boolean, null: false, default: true 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /db/migrate/20150619135811_add_observable_field_to_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Extend custom_workflows table 22 | class AddObservableFieldToCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def change 24 | add_column :custom_workflows, :observable, :string, 25 | null: false, default: 'issue' 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /db/migrate/20150619162054_add_additional_script_fields_to_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Extend custom workflows table 22 | class AddAdditionalScriptFieldsToCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def change 24 | change_table(:custom_workflows, bulk: true) do |t| 25 | t.text :shared_code, null: true 26 | t.text :before_add, null: true 27 | t.text :after_add, null: true 28 | t.text :before_remove, null: true 29 | t.text :after_remove, null: true 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /db/migrate/20151122120000_add_before_and_after_destroy_to_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Extend custom_workflows table 22 | class AddBeforeAndAfterDestroyToCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def change 24 | change_table(:custom_workflows, bulk: true) do |t| 25 | t.text :before_destroy, null: true 26 | t.text :after_destroy, null: true 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /db/migrate/20210210144000_change_default_active_boolean_value_to_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # SQLite boolean migration 22 | class ChangeDefaultActiveBooleanValueToCustomWorkflows < ActiveRecord::Migration[4.2] 23 | def up 24 | return unless ActiveRecord::Base.connection.adapter_name.match?(/sqlite/i) 25 | 26 | change_column_default :custom_workflows, :active, from: true, to: 1 27 | CustomWorkflow.where(active: 't').update_all active: 1 28 | CustomWorkflow.where(active: 'f').update_all active: 0 29 | end 30 | 31 | def down 32 | return unless ActiveRecord::Base.connection.adapter_name.match?(/sqlite/i) 33 | 34 | change_column_default :custom_workflows, :active, from: 1, to: true 35 | CustomWorkflow.where(active: 1).update_all active: 't' 36 | CustomWorkflow.where(active: 0).update_all active: 'f' 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /db/migrate/20230413125201_name_unique_index.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Unique index on name 22 | class NameUniqueIndex < ActiveRecord::Migration[4.2] 23 | def change 24 | add_index :custom_workflows, :name, unique: true 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | Redmine::Plugin.register :redmine_custom_workflows do 22 | name 'Redmine Custom Workflow plugin' 23 | url 'https://www.redmine.org/plugins/redmine_custom_workflows' 24 | author_url 'https://github.com/anteo/redmine_custom_workflows/graphs/contributors' 25 | author 'Anton Argirov/Karel Pičman' 26 | description 'It allows to create custom workflows for objects, defined in a plain Ruby language' 27 | version '3.0.1' 28 | 29 | requires_redmine version_or_higher: '6.0.0' 30 | 31 | permission :manage_project_workflow, {}, require: :member 32 | end 33 | 34 | require_relative 'after_init' unless Redmine::Plugin.installed?('easy_extensions') 35 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Hooks 22 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/hooks/views/base_view_hooks" 23 | 24 | # Errors 25 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/errors/workflow_error" 26 | 27 | # Patches 28 | 29 | # Models 30 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/attachment_patch" 31 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/group_patch" 32 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/issue_patch" 33 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/issue_relation_patch" 34 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/project_patch" 35 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/time_entry_patch" 36 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/user_patch" 37 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/member_patch" 38 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/version_patch" 39 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/wiki_content_patch" 40 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/models/wiki_page_patch" 41 | 42 | # Controllers 43 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/issues_controller_patch" 44 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/attachments_controller_patch" 45 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/groups_controller_patch" 46 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/issue_relations_controller_patch" 47 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/projects_controller_patch" 48 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/timelog_controller_patch" 49 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/users_controller_patch" 50 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/members_controller_patch" 51 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/versions_controller_patch" 52 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/controllers/wiki_controller_patch" 53 | 54 | # Helpers 55 | require "#{File.dirname(__FILE__)}/redmine_custom_workflows/patches/helpers/projects_helper_patch" 56 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/errors/workflow_error.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Errors 23 | class WorkflowError < StandardError 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/hooks/views/base_view_hooks.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Hooks 23 | module Views 24 | # Base view hooks 25 | class BaseViewHooks < Redmine::Hook::ViewListener 26 | def view_layouts_base_html_head(context = {}) 27 | return unless /^(CustomWorkflows|Projects)/.match?(context[:controller].class.name) 28 | 29 | "\n".html_safe + stylesheet_link_tag('custom_workflows.css', plugin: :redmine_custom_workflows) 30 | end 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/attachments_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Attachments controller patch 25 | module AttachmentsControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @attachments 68 | @attachments 69 | elsif @attachment 70 | [@attachment] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | AttachmentsController.prepend RedmineCustomWorkflows::Patches::Controllers::AttachmentsControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/groups_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Groups controller patch 25 | module GroupsControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @groups 68 | @groups 69 | elsif @group 70 | [@group] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | GroupsController.prepend RedmineCustomWorkflows::Patches::Controllers::GroupsControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/issue_relations_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Issue relations controller patch 25 | module IssueRelationsControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @relations 68 | @relations 69 | elsif @relation 70 | [@relation] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | IssueRelationsController.prepend RedmineCustomWorkflows::Patches::Controllers::IssueRelationsControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/issues_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Issues controller patch 25 | module IssuesControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @issues 68 | @issues 69 | elsif @issue 70 | [@issue] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | IssuesController.prepend RedmineCustomWorkflows::Patches::Controllers::IssuesControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/members_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Members controller patch 25 | module MembersControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @members 68 | @members 69 | elsif @member 70 | [@member] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | MembersController.prepend RedmineCustomWorkflows::Patches::Controllers::MembersControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/projects_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Projects controller patch 25 | module ProjectsControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @projects 68 | @projects 69 | elsif @project 70 | [@project] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | ProjectsController.prepend RedmineCustomWorkflows::Patches::Controllers::ProjectsControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/timelog_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Timelog controller patch 25 | module TimelogControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @time_entries 68 | @time_entries 69 | elsif @time_entry 70 | [@time_entry] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | TimelogController.prepend RedmineCustomWorkflows::Patches::Controllers::TimelogControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/users_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Users controller patch 25 | module UsersControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @users 68 | @users 69 | elsif @user 70 | [@user] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | UsersController.prepend RedmineCustomWorkflows::Patches::Controllers::UsersControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/versions_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Versions controller patch 25 | module VersionsControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @versions 68 | @versions 69 | elsif @version 70 | [@version] 71 | end 72 | end 73 | end 74 | end 75 | end 76 | end 77 | 78 | VersionsController.prepend RedmineCustomWorkflows::Patches::Controllers::VersionsControllerPatch 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/controllers/wiki_controller_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Controllers 24 | # Wiki controller patch 25 | module WikiControllerPatch 26 | ################################################################################################################ 27 | # New methods 28 | # 29 | 30 | def self.prepended(base) 31 | base.class_eval do 32 | before_action :set_env 33 | after_action :display_custom_workflow_messages 34 | end 35 | end 36 | 37 | def set_env 38 | objects = model_objects 39 | return unless objects&.any? 40 | 41 | objects.each do |o| 42 | o.custom_workflow_env[:remote_ip] = request.remote_ip if request.remote_ip.present? 43 | end 44 | end 45 | 46 | def display_custom_workflow_messages 47 | objects = model_objects 48 | return unless objects&.any? 49 | 50 | objects.each do |o| 51 | next if o&.custom_workflow_messages&.empty? 52 | 53 | o.custom_workflow_messages.each do |key, value| 54 | if value.present? 55 | flash[key] = value 56 | else 57 | flash.delete key 58 | end 59 | end 60 | o.custom_workflow_messages.clear 61 | end 62 | end 63 | 64 | private 65 | 66 | def model_objects 67 | if @pages 68 | objects = @pages 69 | elsif @page 70 | objects = [@page] 71 | end 72 | # @content either WikiContent or WikiContentVersion 73 | # but plugin does not patch nor work with WikiContentVersion 74 | if @content.is_a? WikiContent 75 | objects ||= [] 76 | objects << @content 77 | end 78 | objects 79 | end 80 | end 81 | end 82 | end 83 | end 84 | 85 | WikiController.prepend RedmineCustomWorkflows::Patches::Controllers::WikiControllerPatch 86 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/helpers/projects_helper_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Helpers 24 | # Project helper patch 25 | module ProjectsHelperPatch 26 | def project_settings_tabs 27 | tabs = super 28 | if User.current.allowed_to?(:manage_project_workflow, @project) 29 | tabs << { 30 | name: 'custom_workflows', 31 | action: :manage_project_workflow, 32 | partial: 'projects/settings/custom_workflow', 33 | label: :label_custom_workflow_plural 34 | } 35 | end 36 | tabs 37 | end 38 | end 39 | end 40 | end 41 | end 42 | 43 | # Apply the patch 44 | if Redmine::Plugin.installed?('easy_extensions') 45 | RedmineExtensions::PatchManager.register_helper_patch 'ProjectsHelper', 46 | 'RedmineCustomWorkflows::Patches::Helpers::ProjectsHelperPatch', 47 | prepend: true 48 | else 49 | ProjectsController.send :helper, RedmineCustomWorkflows::Patches::Helpers::ProjectsHelperPatch 50 | end 51 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/attachment_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Attachment model patch 25 | module AttachmentPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | end 41 | end 42 | 43 | def before_save_custom_workflows 44 | @attachment = self 45 | @saved_attributes = attributes.dup 46 | CustomWorkflow.run_shared_code self 47 | CustomWorkflow.run_custom_workflows :attachment, self, :before_save 48 | throw :abort if errors.any? 49 | 50 | errors.empty? && (@saved_attributes == attributes || valid?) 51 | ensure 52 | @saved_attributes = nil 53 | end 54 | 55 | def after_save_custom_workflows 56 | CustomWorkflow.run_custom_workflows :attachment, self, :after_save 57 | end 58 | 59 | def before_destroy_custom_workflows 60 | res = CustomWorkflow.run_custom_workflows :attachment, self, :before_destroy 61 | throw :abort if res == false 62 | end 63 | 64 | def after_destroy_custom_workflows 65 | CustomWorkflow.run_custom_workflows :attachment, self, :after_destroy 66 | end 67 | end 68 | end 69 | end 70 | end 71 | 72 | # Apply the patch 73 | if Redmine::Plugin.installed?('easy_extensions') 74 | RedmineExtensions::PatchManager.register_model_patch 'Attachment', 75 | 'RedmineCustomWorkflows::Patches::Models::AttachmentPatch' 76 | else 77 | Attachment.prepend RedmineCustomWorkflows::Patches::Models::AttachmentPatch 78 | end 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/group_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Group model patch 25 | module GroupPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | 41 | has_and_belongs_to_many :users, # inherited 42 | join_table: "#{table_name_prefix}groups_users#{table_name_suffix}", # inherited 43 | before_add: proc {}, # => before_add_for_users 44 | after_add: :user_added, # inherited 45 | before_remove: proc {}, # => before_remove_for_users 46 | after_remove: :user_removed # inherited 47 | 48 | def self.users_callback(event, group, user) 49 | group.instance_variable_set :@group, group 50 | group.instance_variable_set :@user, user 51 | CustomWorkflow.run_shared_code(group) if event.to_s.starts_with? 'before_' 52 | CustomWorkflow.run_custom_workflows :group_users, group, event 53 | end 54 | 55 | %i[before_add before_remove after_add after_remove].each do |observable| 56 | send(:"#{observable}_for_users") << lambda { |event, group, user| 57 | Group.users_callback(event, group, user) 58 | } 59 | end 60 | end 61 | end 62 | 63 | def before_save_custom_workflows 64 | @group = self 65 | @saved_attributes = attributes.dup 66 | CustomWorkflow.run_shared_code self 67 | CustomWorkflow.run_custom_workflows :group, self, :before_save 68 | throw :abort if errors.any? 69 | 70 | errors.empty? && (@saved_attributes == attributes || valid?) 71 | ensure 72 | @saved_attributes = nil 73 | end 74 | 75 | def after_save_custom_workflows 76 | CustomWorkflow.run_custom_workflows :group, self, :after_save 77 | end 78 | 79 | def before_destroy_custom_workflows 80 | res = CustomWorkflow.run_custom_workflows :group, self, :before_destroy 81 | throw :abort if res == false 82 | end 83 | 84 | def after_destroy_custom_workflows 85 | CustomWorkflow.run_custom_workflows :group, self, :after_destroy 86 | end 87 | end 88 | end 89 | end 90 | end 91 | 92 | # Apply the patch 93 | if Redmine::Plugin.installed?('easy_extensions') 94 | RedmineExtensions::PatchManager.register_model_patch 'Group', 'RedmineCustomWorkflows::Patches::Models::GroupPatch' 95 | else 96 | Group.prepend RedmineCustomWorkflows::Patches::Models::GroupPatch 97 | end 98 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/issue_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Issue model patch 25 | module IssuePatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | validate :validate_status 41 | 42 | acts_as_attachable before_add: proc {}, # => before_add_for_attachments 43 | after_add: :attachment_added, # inherited 44 | before_remove: proc {}, # => before_remove_for_attachments 45 | after_remove: :attachment_removed # inherited 46 | 47 | def self.attachments_callback(event, issue, attachment) 48 | issue.instance_variable_set :@issue, issue 49 | issue.instance_variable_set :@attachment, attachment 50 | CustomWorkflow.run_shared_code(issue) if event.to_s.starts_with? 'before_' 51 | CustomWorkflow.run_custom_workflows :issue_attachments, issue, event 52 | end 53 | 54 | %i[before_add before_remove after_add after_remove].each do |observable| 55 | send(:"#{observable}_for_attachments") << lambda { |event, issue, attachment| 56 | Issue.attachments_callback event, issue, attachment 57 | } 58 | end 59 | end 60 | end 61 | 62 | def validate_status 63 | unless @saved_attributes && (@saved_attributes['status_id'] != status_id) && new_statuses_allowed_to( 64 | User.current, new_record? 65 | ).collect(&:id).exclude?(status_id) 66 | return true 67 | end 68 | 69 | status_was = IssueStatus.find_by(id: status_id_was) 70 | status_new = IssueStatus.find_by(id: status_id) 71 | errors.add :status, 72 | :new_status_invalid, 73 | old_status: status_was&.name, 74 | new_status: status_new&.name 75 | end 76 | 77 | def before_save_custom_workflows 78 | @issue = self 79 | @saved_attributes = attributes.dup 80 | CustomWorkflow.run_shared_code self 81 | CustomWorkflow.run_custom_workflows :issue, self, :before_save 82 | throw :abort if errors.any? 83 | 84 | errors.empty? && (@saved_attributes == attributes || valid?) 85 | ensure 86 | @saved_attributes = nil 87 | end 88 | 89 | def after_save_custom_workflows 90 | CustomWorkflow.run_custom_workflows :issue, self, :after_save 91 | end 92 | 93 | def before_destroy_custom_workflows 94 | res = CustomWorkflow.run_custom_workflows(:issue, self, :before_destroy) 95 | throw :abort if res == false 96 | end 97 | 98 | def after_destroy_custom_workflows 99 | CustomWorkflow.run_custom_workflows :issue, self, :after_destroy 100 | end 101 | end 102 | end 103 | end 104 | end 105 | 106 | # Apply the patch 107 | if Redmine::Plugin.installed?('easy_extensions') 108 | RedmineExtensions::PatchManager.register_model_patch 'Issue', 'RedmineCustomWorkflows::Patches::Models::IssuePatch' 109 | else 110 | Issue.prepend RedmineCustomWorkflows::Patches::Models::IssuePatch 111 | end 112 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/issue_relation_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Issue relation model patch 25 | module IssueRelationPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | end 41 | 42 | base.prepend InstanceMethods 43 | end 44 | 45 | # Instance methods module 46 | module InstanceMethods 47 | ############################################################################################################## 48 | # Overridden methods 49 | 50 | # Override IssueRelation.to_s to rescue NoMethodError during CustomWorkflow.validate_syntax due to 51 | # logging of temporarily instatiated IssueRelation with no related issues set. 52 | def to_s(issue = nil) 53 | super 54 | rescue NoMethodError => e 55 | raise e if issue_from.present? || issue_to.present? 56 | end 57 | 58 | ############################################################################################################## 59 | # New methods 60 | # 61 | def before_save_custom_workflows 62 | @issue_relation = self 63 | @saved_attributes = attributes.dup 64 | CustomWorkflow.run_shared_code self 65 | CustomWorkflow.run_custom_workflows :issue_relation, self, :before_save 66 | throw :abort if errors.any? 67 | errors.empty? && (@saved_attributes == attributes || valid?) 68 | ensure 69 | @saved_attributes = nil 70 | end 71 | 72 | def after_save_custom_workflows 73 | CustomWorkflow.run_custom_workflows :issue_relation, self, :after_save 74 | end 75 | 76 | def before_destroy_custom_workflows 77 | res = CustomWorkflow.run_custom_workflows :issue_relation, self, :before_destroy 78 | throw :abort if res == false 79 | end 80 | 81 | def after_destroy_custom_workflows 82 | CustomWorkflow.run_custom_workflows :issue_relation, self, :after_destroy 83 | end 84 | end 85 | end 86 | end 87 | end 88 | end 89 | 90 | # Apply the patch 91 | if Redmine::Plugin.installed?('easy_extensions') 92 | RedmineExtensions::PatchManager.register_model_patch 'IssueRelation', 93 | 'RedmineCustomWorkflows::Patches::Models::IssueRelationPatch' 94 | else 95 | IssueRelation.prepend RedmineCustomWorkflows::Patches::Models::IssueRelationPatch 96 | end 97 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/member_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Member model patch 25 | module MemberPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | end 41 | end 42 | 43 | def before_save_custom_workflows 44 | @member = self 45 | @saved_attributes = attributes.dup 46 | CustomWorkflow.run_shared_code self 47 | CustomWorkflow.run_custom_workflows :member, self, :before_save 48 | throw :abort if errors.any? 49 | 50 | errors.empty? && (@saved_attributes == attributes || valid?) 51 | ensure 52 | @saved_attributes = nil 53 | end 54 | 55 | def after_save_custom_workflows 56 | CustomWorkflow.run_custom_workflows :member, self, :after_save 57 | end 58 | 59 | def before_destroy_custom_workflows 60 | res = CustomWorkflow.run_custom_workflows :member, self, :before_destroy 61 | throw :abort if res == false 62 | end 63 | 64 | def after_destroy_custom_workflows 65 | CustomWorkflow.run_custom_workflows :member, self, :after_destroy 66 | end 67 | end 68 | end 69 | end 70 | end 71 | 72 | # Apply the patch 73 | if Redmine::Plugin.installed?('easy_extensions') 74 | RedmineExtensions::PatchManager.register_model_patch 'Member', 'RedmineCustomWorkflows::Patches::Models::MemberPatch' 75 | else 76 | Member.prepend RedmineCustomWorkflows::Patches::Models::MemberPatch 77 | end 78 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/project_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Project model patch 25 | module ProjectPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | has_and_belongs_to_many :custom_workflows 37 | 38 | safe_attributes :custom_workflow_ids, 39 | if: lambda { |project, user| 40 | project.new_record? || user.allowed_to?(:manage_project_workflow, project) 41 | } 42 | 43 | before_save :before_save_custom_workflows 44 | after_save :after_save_custom_workflows 45 | before_destroy :before_destroy_custom_workflows 46 | after_destroy :after_destroy_custom_workflows 47 | 48 | acts_as_attachable view_permission: :view_files, # inherited 49 | edit_permission: :manage_files, # inherited 50 | delete_permission: :manage_files, # inherited 51 | before_add: proc {}, # => before_add_for_attachments 52 | after_add: proc {}, # => after_add_for_attachments 53 | before_remove: proc {}, # => before_remove_for_attachments 54 | after_remove: proc {} # => after_remove_for_attachments 55 | 56 | def self.attachments_callback(event, project, attachment) 57 | project.instance_variable_set(:@project, project) 58 | project.instance_variable_set(:@attachment, attachment) 59 | CustomWorkflow.run_shared_code(project) if event.to_s.starts_with? 'before_' 60 | CustomWorkflow.run_custom_workflows(:project_attachments, project, event) 61 | end 62 | 63 | %i[before_add before_remove after_add after_remove].each do |observable| 64 | send(:"#{observable}_for_attachments") << lambda { |event, project, attachment| 65 | Project.attachments_callback event, project, attachment 66 | } 67 | end 68 | end 69 | end 70 | 71 | def before_save_custom_workflows 72 | @project = self 73 | @saved_attributes = attributes.dup 74 | CustomWorkflow.run_shared_code self 75 | CustomWorkflow.run_custom_workflows :project, self, :before_save 76 | throw :abort if errors.any? 77 | 78 | errors.empty? && (@saved_attributes == attributes || valid?) 79 | ensure 80 | @saved_attributes = nil 81 | end 82 | 83 | def after_save_custom_workflows 84 | CustomWorkflow.run_custom_workflows :project, self, :after_save 85 | end 86 | 87 | def before_destroy_custom_workflows 88 | res = CustomWorkflow.run_custom_workflows :project, self, :before_destroy 89 | throw :abort if res == false 90 | end 91 | 92 | def after_destroy_custom_workflows 93 | CustomWorkflow.run_custom_workflows :project, self, :after_destroy 94 | end 95 | end 96 | end 97 | end 98 | end 99 | 100 | # Apply the patch 101 | if Redmine::Plugin.installed?('easy_extensions') 102 | RedmineExtensions::PatchManager.register_model_patch 'Project', 103 | 'RedmineCustomWorkflows::Patches::Models::ProjectPatch' 104 | else 105 | Project.prepend RedmineCustomWorkflows::Patches::Models::ProjectPatch 106 | end 107 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/time_entry_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Time entry model patch 25 | module TimeEntryPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | end 41 | end 42 | 43 | def before_save_custom_workflows 44 | @time_entry = self 45 | @saved_attributes = attributes.dup 46 | CustomWorkflow.run_shared_code(self) 47 | CustomWorkflow.run_custom_workflows(:time_entry, self, :before_save) 48 | throw :abort if errors.any? 49 | 50 | errors.empty? && (@saved_attributes == attributes || valid?) 51 | ensure 52 | @saved_attributes = nil 53 | end 54 | 55 | def after_save_custom_workflows 56 | CustomWorkflow.run_custom_workflows :time_entry, self, :after_save 57 | end 58 | 59 | def before_destroy_custom_workflows 60 | res = CustomWorkflow.run_custom_workflows :time_entry, self, :before_destroy 61 | throw :abort if res == false 62 | end 63 | 64 | def after_destroy_custom_workflows 65 | CustomWorkflow.run_custom_workflows :time_entry, self, :after_destroy 66 | end 67 | end 68 | end 69 | end 70 | end 71 | 72 | # Apply the patch 73 | if Redmine::Plugin.installed?('easy_extensions') 74 | RedmineExtensions::PatchManager.register_model_patch 'TimeEntry', 75 | 'RedmineCustomWorkflows::Patches::Models::TimeEntryPatch' 76 | else 77 | TimeEntry.prepend RedmineCustomWorkflows::Patches::Models::TimeEntryPatch 78 | end 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/user_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # User model patch 25 | module UserPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | end 41 | end 42 | 43 | def before_save_custom_workflows 44 | @user = self 45 | @saved_attributes = attributes.dup 46 | CustomWorkflow.run_shared_code self 47 | CustomWorkflow.run_custom_workflows :user, self, :before_save 48 | throw :abort if errors.any? 49 | 50 | errors.empty? && (@saved_attributes == attributes || valid?) 51 | ensure 52 | @saved_attributes = nil 53 | end 54 | 55 | def after_save_custom_workflows 56 | CustomWorkflow.run_custom_workflows :user, self, :after_save 57 | end 58 | 59 | def before_destroy_custom_workflows 60 | res = CustomWorkflow.run_custom_workflows :user, self, :before_destroy 61 | throw :abort if res == false 62 | end 63 | 64 | def after_destroy_custom_workflows 65 | CustomWorkflow.run_custom_workflows :user, self, :after_destroy 66 | end 67 | end 68 | end 69 | end 70 | end 71 | 72 | # Apply the patch 73 | if Redmine::Plugin.installed?('easy_extensions') 74 | RedmineExtensions::PatchManager.register_model_patch 'User', 'RedmineCustomWorkflows::Patches::Models::UserPatch' 75 | else 76 | User.prepend RedmineCustomWorkflows::Patches::Models::UserPatch 77 | end 78 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/version_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Version model patch 25 | module VersionPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | end 41 | end 42 | 43 | def before_save_custom_workflows 44 | @version = self 45 | @saved_attributes = attributes.dup 46 | CustomWorkflow.run_shared_code self 47 | CustomWorkflow.run_custom_workflows :version, self, :before_save 48 | throw :abort if errors.any? 49 | 50 | errors.empty? && (@saved_attributes == attributes || valid?) 51 | ensure 52 | @saved_attributes = nil 53 | end 54 | 55 | def after_save_custom_workflows 56 | CustomWorkflow.run_custom_workflows :version, self, :after_save 57 | end 58 | 59 | def before_destroy_custom_workflows 60 | res = CustomWorkflow.run_custom_workflows :version, self, :before_destroy 61 | throw :abort if res == false 62 | end 63 | 64 | def after_destroy_custom_workflows 65 | CustomWorkflow.run_custom_workflows :version, self, :after_destroy 66 | end 67 | end 68 | end 69 | end 70 | end 71 | 72 | # Apply the patch 73 | if Redmine::Plugin.installed?('easy_extensions') 74 | RedmineExtensions::PatchManager.register_model_patch 'Version', 75 | 'RedmineCustomWorkflows::Patches::Models::VersionPatch' 76 | else 77 | Version.prepend RedmineCustomWorkflows::Patches::Models::VersionPatch 78 | end 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/wiki_content_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Wiki content model patch 25 | module WikiContentPatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | before_save :before_save_custom_workflows 37 | after_save :after_save_custom_workflows 38 | before_destroy :before_destroy_custom_workflows 39 | after_destroy :after_destroy_custom_workflows 40 | end 41 | end 42 | 43 | def before_save_custom_workflows 44 | @content = self 45 | @saved_attributes = attributes.dup 46 | CustomWorkflow.run_shared_code self 47 | CustomWorkflow.run_custom_workflows :wiki_content, self, :before_save 48 | throw :abort if errors.any? 49 | 50 | errors.empty? && (@saved_attributes == attributes || valid?) 51 | ensure 52 | @saved_attributes = nil 53 | end 54 | 55 | def after_save_custom_workflows 56 | CustomWorkflow.run_custom_workflows :wiki_content, self, :after_save 57 | end 58 | 59 | def before_destroy_custom_workflows 60 | res = CustomWorkflow.run_custom_workflows :wiki_content, self, :before_destroy 61 | throw :abort if res == false 62 | end 63 | 64 | def after_destroy_custom_workflows 65 | CustomWorkflow.run_custom_workflows :wiki_content, self, :after_destroy 66 | end 67 | end 68 | end 69 | end 70 | end 71 | 72 | # Apply the patch 73 | if Redmine::Plugin.installed?('easy_extensions') 74 | RedmineExtensions::PatchManager.register_model_patch 'WikiContent', 75 | 'RedmineCustomWorkflows::Patches::Models::WikiContentPatch' 76 | else 77 | WikiContent.prepend RedmineCustomWorkflows::Patches::Models::WikiContentPatch 78 | end 79 | -------------------------------------------------------------------------------- /lib/redmine_custom_workflows/patches/models/wiki_page_patch.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Patches 23 | module Models 24 | # Wiki page model patch 25 | module WikiPagePatch 26 | def custom_workflow_messages 27 | @custom_workflow_messages ||= {} 28 | end 29 | 30 | def custom_workflow_env 31 | @custom_workflow_env ||= {} 32 | end 33 | 34 | def self.prepended(base) 35 | base.class_eval do 36 | acts_as_attachable delete_permission: :delete_wiki_pages_attachments, # inherited 37 | before_add: proc {}, # => before_add_for_attachments 38 | after_add: proc {}, # => after_add_for_attachments 39 | before_remove: proc {}, # => before_remove_for_attachments 40 | after_remove: proc {} # => after_remove_for_attachments 41 | 42 | def self.attachments_callback(event, page, attachment) 43 | page.instance_variable_set :@page, page 44 | page.instance_variable_set :@attachment, attachment 45 | CustomWorkflow.run_shared_code(page) if event.to_s.starts_with? 'before_' 46 | CustomWorkflow.run_custom_workflows :wiki_page_attachments, page, event 47 | end 48 | 49 | %i[before_add before_remove after_add after_remove].each do |observable| 50 | send(:"#{observable}_for_attachments") << lambda { |event, page, attachment| 51 | WikiPage.attachments_callback(event, page, attachment) 52 | } 53 | end 54 | end 55 | end 56 | end 57 | end 58 | end 59 | end 60 | 61 | # Apply the patch 62 | if Redmine::Plugin.installed?('easy_extensions') 63 | RedmineExtensions::PatchManager.register_model_patch 'WikiPage', 64 | 'RedmineCustomWorkflows::Patches::Models::WikiPagePatch' 65 | else 66 | WikiPage.prepend RedmineCustomWorkflows::Patches::Models::WikiPagePatch 67 | end 68 | -------------------------------------------------------------------------------- /test/fixtures/custom_workflows_projects.yml: -------------------------------------------------------------------------------- 1 | --- 2 | custom_workflows_projects_001: 3 | project_id: 1 4 | custom_workflow_id: 1 # Issue 5 | 6 | custom_workflows_projects_002: 7 | project_id: 1 8 | custom_workflow_id: 2 # Version 9 | 10 | custom_workflows_projects_003: 11 | project_id: 1 12 | custom_workflow_id: 4 # Project 13 | 14 | custom_workflows_projects_004: 15 | project_id: 1 16 | custom_workflow_id: 8 # Time entry 17 | 18 | custom_workflows_projects_005: 19 | project_id: 1 20 | custom_workflow_id: 9 # Wiki content 21 | 22 | custom_workflows_projects_006: 23 | project_id: 1 24 | custom_workflow_id: 10 # Wiki page 25 | 26 | custom_workflows_projects_007: 27 | project_id: 1 28 | custom_workflow_id: 11 # Member 29 | -------------------------------------------------------------------------------- /test/functional/attachments_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Attachment controller patch test 24 | class AttachmentsControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :attachments, :enabled_modules, :custom_workflows, :custom_workflows_projects, 26 | :roles, :members, :member_roles 27 | 28 | def setup 29 | super 30 | @attachment8 = Attachment.find 8 31 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 32 | @controller = AttachmentsController.new 33 | end 34 | 35 | def test_delete_with_cw 36 | delete "/attachments/#{@attachment8.id}" 37 | assert_response :redirect 38 | assert_equal 'Custom workflow', @controller.flash[:notice] 39 | end 40 | 41 | def test_cw_env 42 | delete "/attachments/#{@attachment8.id}" 43 | assert_response :redirect 44 | assert_equal request.remote_ip, @controller.flash[:warning] 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /test/functional/custom_workflows_controller_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Custom workflows controller test 24 | class CustomWorkflowsControllerTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :custom_workflows 26 | 27 | def setup 28 | super 29 | @cw1 = CustomWorkflow.find 1 30 | end 31 | 32 | def test_truth 33 | assert_kind_of CustomWorkflow, @cw1 34 | end 35 | 36 | def test_index_admin 37 | post '/login', params: { username: 'admin', password: 'admin' } 38 | get '/custom_workflows' 39 | assert_response :success 40 | end 41 | 42 | def test_index_non_admin 43 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 44 | get '/custom_workflows' 45 | assert_response :forbidden 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/functional/groups_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Group controller patch test 24 | class GroupControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | include Rails.application.routes.url_helpers 26 | fixtures :custom_workflows, :custom_workflows_projects 27 | 28 | def setup 29 | super 30 | @group10 = Group.find 10 31 | post '/login', params: { username: 'admin', password: 'admin' } 32 | @controller = GroupsController.new 33 | default_url_options[:host] = 'www.example.com' 34 | end 35 | 36 | def test_update_with_cw 37 | @request.headers['Referer'] = edit_group_path(id: @group10.id) 38 | put "/groups/#{@group10.id}", params: { group: { name: 'Updated name' } } 39 | assert_redirected_to groups_path 40 | assert_equal 'Custom workflow', @controller.flash[:notice] 41 | end 42 | 43 | def test_cw_env 44 | @request.headers['Referer'] = edit_group_path(id: @group10.id) 45 | put "/groups/#{@group10.id}/", params: { group: { name: 'Updated name' } } 46 | assert_redirected_to groups_path 47 | assert_equal request.remote_ip, @controller.flash[:warning] 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/functional/issue_relations_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Issue relation controller patch test 24 | class IssueRelationsControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :user_preferences, :issues, :versions, :trackers, :projects_trackers, :issue_statuses, 26 | :enabled_modules, :enumerations, :issue_categories, :custom_workflows, :custom_workflows_projects, 27 | :issue_relations, :roles, :members, :member_roles, :attachments 28 | 29 | def setup 30 | super 31 | @ir1 = IssueRelation.find 1 32 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 33 | @controller = AttachmentsController.new 34 | end 35 | 36 | def test_delete_with_cw 37 | delete "/relations/#{@ir1.id}" 38 | assert_response :redirect 39 | assert_equal 'Custom workflow', @controller.flash[:notice] 40 | end 41 | 42 | def test_cw_env 43 | delete "/relations/#{@ir1.id}" 44 | assert_response :redirect 45 | assert_equal request.remote_ip, @controller.flash[:warning] 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/functional/issues_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Issue controller patch test 24 | class IssuesControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :user_preferences, :issues, :versions, :trackers, :projects_trackers, :issue_statuses, 26 | :enabled_modules, :enumerations, :issue_categories, :custom_workflows, :custom_workflows_projects, :roles, 27 | :members, :member_roles 28 | 29 | def setup 30 | super 31 | @issue1 = Issue.find 1 32 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 33 | @controller = IssuesController.new 34 | end 35 | 36 | def test_update_with_cw 37 | put "/issues/#{@issue1.id}", params: { issue: { subject: 'Updated subject' } } 38 | assert_redirected_to issue_path(@issue1) 39 | assert_equal 'Custom workflow', @controller.flash[:notice] 40 | end 41 | 42 | def test_delete_with_cw 43 | delete "/issues/#{@issue1.id}", params: { todo: 'destroy' } 44 | assert_response :redirect 45 | assert_equal 'Issue cannot be deleted', @controller.flash[:error] 46 | assert Issue.find_by(id: @issue1.id) 47 | end 48 | 49 | def test_cw_env 50 | put "/issues/#{@issue1.id}", params: { issue: { subject: 'Updated subject' } } 51 | assert_redirected_to issue_path(@issue1) 52 | assert_equal request.remote_ip, @controller.flash[:warning] 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/functional/members_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Users controller patch test 24 | class MembersControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :user_preferences, :roles, :members, :member_roles, :custom_workflows, :custom_workflows_projects 26 | 27 | def setup 28 | super 29 | @member1 = Member.find 1 30 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 31 | @controller = MembersController.new 32 | end 33 | 34 | def test_delete_with_cw 35 | delete "/memberships/#{@member1.id}" 36 | assert_response :redirect 37 | assert_equal 'Custom workflow', @controller.flash[:notice] 38 | end 39 | 40 | def test_cw_env 41 | delete "/memberships/#{@member1.id}" 42 | assert_response :redirect 43 | assert_equal request.remote_ip, @controller.flash[:warning] 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /test/functional/projects_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Project controller patch test 24 | class ProjectsControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :user_preferences, :issues, :versions, :trackers, :projects_trackers, :enabled_modules, 26 | :enumerations, :custom_workflows, :custom_workflows_projects, :roles, :members, :member_roles 27 | 28 | def setup 29 | super 30 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 31 | @controller = ProjectsController.new 32 | end 33 | 34 | def test_update_with_cw 35 | patch "/projects/#{@project1.id}", params: { project: { name: 'Updated name' } } 36 | assert_redirected_to settings_project_path(@project1) 37 | assert_equal 'Custom workflow', @controller.flash[:notice] 38 | end 39 | 40 | def test_cw_env 41 | patch "/projects/#{@project1.id}", params: { project: { name: 'Updated name' } } 42 | assert_redirected_to settings_project_path(@project1) 43 | assert_equal request.remote_ip, @controller.flash[:warning] 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /test/functional/timelog_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Time controller patch test 24 | class TimelogControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :user_preferences, :issues, :versions, :trackers, :projects_trackers, :issue_statuses, 26 | :enabled_modules, :enumerations, :issue_categories, :custom_workflows, :custom_workflows_projects, 27 | :time_entries, :roles, :members, :member_roles 28 | 29 | def setup 30 | super 31 | @te1 = TimeEntry.find 1 32 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 33 | @controller = TimelogController.new 34 | end 35 | 36 | def test_delete_with_cw 37 | delete "/time_entries/#{@te1.id}" 38 | assert_response :redirect 39 | assert_equal 'Custom workflow', @controller.flash[:notice] 40 | end 41 | 42 | def test_cw_env 43 | delete "/time_entries/#{@te1.id}" 44 | assert_response :redirect 45 | assert_equal request.remote_ip, @controller.flash[:warning] 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/functional/users_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Users controller patch test 24 | class UsersControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :custom_workflows, :custom_workflows_projects 26 | 27 | def setup 28 | super 29 | post '/login', params: { username: 'admin', password: 'admin' } 30 | @controller = UsersController.new 31 | end 32 | 33 | def test_update_with_cw 34 | put "/users/#{@jsmith.id}", params: { user: { lastname: 'updated_lastname' } } 35 | assert_redirected_to edit_user_path(@jsmith) 36 | assert_equal 'Custom workflow', @controller.flash[:notice] 37 | end 38 | 39 | def test_cw_env 40 | put "/users/#{@jsmith.id}", params: { user: { lastname: 'updated_lastname' } } 41 | assert_redirected_to edit_user_path(@jsmith) 42 | assert_equal request.remote_ip, @controller.flash[:warning] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/functional/versions_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Version controller patch test 24 | class VersionsControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :versions, :custom_workflows, :custom_workflows_projects, :roles, :members, :member_roles 26 | 27 | def setup 28 | super 29 | @version1 = Version.find 1 30 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 31 | @controller = VersionsController.new 32 | end 33 | 34 | def test_update_with_cw 35 | put "/versions/#{@version1.id}", params: { version: { name: 'Updated version' } } 36 | assert_redirected_to settings_project_path(id: @project1, tab: 'versions') 37 | assert_equal 'Custom workflow', @controller.flash[:notice] 38 | end 39 | 40 | def test_cw_env 41 | put "/versions/#{@version1.id}", params: { version: { name: 'Updated version' } } 42 | assert_redirected_to settings_project_path(id: @project1, tab: 'versions') 43 | assert_equal request.remote_ip, @controller.flash[:warning] 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /test/functional/wiki_controller_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Document Management System "Features" 4 | # 5 | # Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Wiki controller patch test 24 | class WikiControllerPatchTest < RedmineCustomWorkflows::Test::TestCase 25 | fixtures :user_preferences, :issues, :versions, :trackers, :projects_trackers, :enabled_modules, 26 | :enumerations, :wikis, :wiki_pages, :wiki_contents, :custom_workflows, :custom_workflows_projects, 27 | :roles, :members, :member_roles 28 | 29 | def setup 30 | super 31 | @wp1 = WikiPage.find 1 32 | post '/login', params: { username: 'jsmith', password: 'jsmith' } 33 | @controller = WikiController.new 34 | end 35 | 36 | def test_update_with_cw 37 | put "/projects/#{@project1.id}/wiki/Another_page", 38 | params: { 39 | content: { comments: 'my comments', text: 'edited', version: 1 } 40 | } 41 | assert_response :redirect 42 | assert_equal 'Custom workflow', @controller.flash[:notice] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/test_case.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Test 23 | # Test case base class 24 | class TestCase < ActionDispatch::IntegrationTest 25 | fixtures :users, :email_addresses, :projects 26 | 27 | # Allow us to override the fixtures method to implement fixtures for our plugin. 28 | # Ultimately it allows for better integration without blowing redmine fixtures up, 29 | # and allowing us to suppliment redmine fixtures if we need to. 30 | def self.fixtures(*table_names) 31 | dir = File.join(File.dirname(__FILE__), 'fixtures') 32 | redmine_table_names = [] 33 | table_names.each do |x| 34 | if File.exist?(File.join(dir, "#{x}.yml")) 35 | ActiveRecord::FixtureSet.create_fixtures(dir, x) 36 | else 37 | redmine_table_names << x 38 | end 39 | end 40 | super(redmine_table_names) if redmine_table_names.any? 41 | end 42 | 43 | def setup 44 | @jsmith = User.find_by(login: 'jsmith') 45 | @admin = User.find_by(login: 'admin') 46 | @project1 = Project.find 1 47 | User.current = nil 48 | end 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | # Load the normal Rails helper 22 | require File.expand_path('../../../../test/test_helper', __FILE__) 23 | 24 | require_relative 'unit_test' 25 | require_relative 'test_case' 26 | -------------------------------------------------------------------------------- /test/unit/attachment_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Attachment patch test class 24 | class AttachmentPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :attachments 26 | 27 | def setup 28 | @attachment1 = Attachment.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of Attachment, @attachment1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @attachment1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @attachment1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @attachment1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @attachment1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/custom_workflow_mailer_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Custom mailer test class 24 | class CustomWorkflowMailerTest < RedmineCustomWorkflows::Test::UnitTest 25 | include Redmine::I18n 26 | fixtures :users, :email_addresses 27 | 28 | def setup 29 | @user2 = User.find 2 30 | # Mailer settings 31 | ActionMailer::Base.deliveries.clear 32 | Setting.plain_text_mail = '0' 33 | Setting.default_language = 'en' 34 | User.current = nil 35 | end 36 | 37 | def test_truth 38 | assert_kind_of User, @user2 39 | end 40 | 41 | def test_custom_email 42 | CustomWorkflowMailer.deliver_custom_email @user2, subject: 'Subject', text_body: 'Body', html_body: 'Body' 43 | email = last_email 44 | return unless email # Sometimes it doesn't work. Especially on localhost. 45 | 46 | text = text_part(email).body 47 | html = html_part(email).body 48 | assert text.include?('Body'), "'Body' expected\n'#{text}' present'" 49 | assert html.include?('Body'), "'Body' expected\n'#{html}' present'" 50 | end 51 | 52 | def test_custom_email_template 53 | CustomWorkflowMailer.deliver_custom_email @user2, 54 | subject: 'Subject', 55 | template_name: 'mailer/test_email', 56 | template_params: { url: Setting.host_name } 57 | email = last_email 58 | return unless email # Sometimes it doesn't work. Especially on localhost. 59 | 60 | text = text_part(email).body 61 | html = html_part(email).body 62 | assert text.include?(Setting.host_name), "'#{Setting.host_name} expected\n'#{text}' present'" 63 | assert html.include?(Setting.host_name), "'#{Setting.host_name} expected\n'#{html}' present'" 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /test/unit/custom_workflow_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Custom workflow test class 24 | class CustomWorkflowTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :projects, :custom_workflows, :custom_workflows_projects 26 | 27 | def setup 28 | @cw1 = CustomWorkflow.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of CustomWorkflow, @cw1 33 | end 34 | 35 | def test_to_s 36 | assert_equal @cw1.name, @cw1.to_s 37 | end 38 | 39 | def test_import_from_xml 40 | xml = %( 41 | 42 | 20 43 | Rails.logger.info '>>> Okay' 44 | 45 | cw 1 46 | Desc. 47 | 4 48 | false 49 | karel.picman@kontron.com 50 | 2022-09-21T12:14:21Z 51 | 2022-09-21T12:14:21Z 52 | true 53 | issue 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 2022-09-21T12:31:17Z 62 | 2.0.6 devel 63 | 3.0.2-p107 64 | 6.1.6.1 65 | 66 | ) 67 | cw = CustomWorkflow.import_from_xml(xml) 68 | assert cw 69 | end 70 | 71 | def test_export_as_xml 72 | xml = @cw1.export_as_xml 73 | assert xml.include?("#{@cw1}") 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /test/unit/group_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Group patch test class 24 | class GroupPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :users 26 | 27 | def setup 28 | @group10 = Group.find 10 29 | end 30 | 31 | def test_truth 32 | assert_kind_of Group, @group10 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @group10.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @group10.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @group10.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @group10.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/issue_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Issue patch test class 24 | class IssuePatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :issues 26 | 27 | def setup 28 | @issue1 = Issue.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of Issue, @issue1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @issue1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @issue1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @issue1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @issue1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/issue_relation_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Issue relation patch test class 24 | class IssueRelationPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :issue_relations 26 | 27 | def setup 28 | @issue_relation1 = IssueRelation.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of IssueRelation, @issue_relation1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @issue_relation1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @issue_relation1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @issue_relation1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @issue_relation1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/member_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Member patch test class 24 | class MemberPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :members 26 | 27 | def setup 28 | @member1 = Member.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of Member, @member1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @member1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @member1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @member1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @member1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/project_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Project patch test class 24 | class ProjectPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :projects 26 | 27 | def setup 28 | @project1 = Project.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of Project, @project1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @project1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @project1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @project1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @project1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/time_entry_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Time entry patch test class 24 | class TimeEntryPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :time_entries 26 | 27 | def setup 28 | @time_entry1 = TimeEntry.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of TimeEntry, @time_entry1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @time_entry1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @time_entry1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @time_entry1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @time_entry1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/user_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # User patch test class 24 | class UserPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :users 26 | 27 | def setup 28 | @user1 = User.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of User, @user1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @user1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @user1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @user1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @user1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/version_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Version patch test class 24 | class VersionPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :versions 26 | 27 | def setup 28 | @version1 = Version.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of Version, @version1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @version1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @version1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @version1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @version1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/wiki_content_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Wiki content patch test class 24 | class WikiContentPatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :wiki_contents 26 | 27 | def setup 28 | @wiki_content1 = WikiContent.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of WikiContent, @wiki_content1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @wiki_content1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @wiki_content1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @wiki_content1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @wiki_content1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit/wiki_page_patch_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | require File.expand_path('../../test_helper', __FILE__) 22 | 23 | # Wiki page test class 24 | class WikiPagePatchTest < RedmineCustomWorkflows::Test::UnitTest 25 | fixtures :wiki_pages 26 | 27 | def setup 28 | @wiki_page1 = WikiPage.find 1 29 | end 30 | 31 | def test_truth 32 | assert_kind_of WikiPage, @wiki_page1 33 | end 34 | 35 | def test_custom_workflow_messages 36 | @wiki_page1.custom_workflow_messages[:notice] = 'Okay' 37 | assert_equal 'Okay', @wiki_page1.custom_workflow_messages[:notice] 38 | end 39 | 40 | def test_custom_workflow_env 41 | @wiki_page1.custom_workflow_env[:remote_ip] = '127.0.0.1' 42 | assert_equal '127.0.0.1', @wiki_page1.custom_workflow_env[:remote_ip] 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /test/unit_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Redmine plugin for Custom Workflows 4 | # 5 | # Anton Argirov, Karel Pičman 6 | # 7 | # This program is free software; you can redistribute it and/or 8 | # modify it under the terms of the GNU General Public License 9 | # as published by the Free Software Foundation; either version 2 10 | # of the License, or (at your option) any later version. 11 | # 12 | # This program is distributed in the hope that it will be useful, 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | # GNU General Public License for more details. 16 | # 17 | # You should have received a copy of the GNU General Public License 18 | # along with this program; if not, write to the Free Software 19 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 | 21 | module RedmineCustomWorkflows 22 | module Test 23 | # Unit test base class 24 | class UnitTest < ActiveSupport::TestCase 25 | # Allow us to override the fixtures method to implement fixtures for our plugin. 26 | # Ultimately it allows for better integration without blowing redmine fixtures up, 27 | # and allowing us to suppliment redmine fixtures if we need to. 28 | def self.fixtures(*table_names) 29 | dir = File.join(File.dirname(__FILE__), '/fixtures') 30 | table_names.each do |x| 31 | ActiveRecord::FixtureSet.create_fixtures(dir, x) if File.exist?("#{dir}/#{x}.yml") 32 | end 33 | super(table_names) 34 | end 35 | 36 | protected 37 | 38 | def last_email 39 | ActionMailer::Base.deliveries.last 40 | end 41 | 42 | def text_part(email) 43 | email.parts.detect { |part| part.content_type.include?('text/plain') } 44 | end 45 | 46 | def html_part(email) 47 | email.parts.detect { |part| part.content_type.include?('text/html') } 48 | end 49 | end 50 | end 51 | end 52 | --------------------------------------------------------------------------------