Showing preview only (486K chars total). Download the full file or copy to clipboard to get everything.
Repository: akiko-pusu/redmine_issue_templates
Branch: master
Commit: 86fbfc17eb92
Files: 166
Total size: 423.0 KB
Directory structure:
gitextract_qmbduvvp/
├── .circleci/
│ └── config.yml
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── greetings.yml
├── .gitignore
├── .rubocop.yml
├── .rubocop_todo.yml
├── Dockerfile
├── Gemfile.local
├── ISSUE_TEMPLATE.md
├── LICENSE.txt
├── README.md
├── RELEASE-NOTES.md
├── _config.yml
├── app/
│ ├── controllers/
│ │ ├── concerns/
│ │ │ ├── issue_templates_common.rb
│ │ │ └── project_templates_common.rb
│ │ ├── global_issue_templates_controller.rb
│ │ ├── global_note_templates_controller.rb
│ │ ├── issue_templates_controller.rb
│ │ ├── issue_templates_settings_controller.rb
│ │ └── note_templates_controller.rb
│ ├── helpers/
│ │ └── issue_templates_helper.rb
│ ├── models/
│ │ ├── concerns/
│ │ │ └── issue_template/
│ │ │ └── common.rb
│ │ ├── global_issue_template.rb
│ │ ├── global_note_template.rb
│ │ ├── global_note_template_project.rb
│ │ ├── global_note_visible_role.rb
│ │ ├── issue_template.rb
│ │ ├── issue_template_setting.rb
│ │ ├── note_template.rb
│ │ └── note_visible_role.rb
│ └── views/
│ ├── common/
│ │ ├── _nodata.html.erb
│ │ ├── _orphaned.html.erb
│ │ └── _template_links.html.erb
│ ├── global_issue_templates/
│ │ ├── _form.html.erb
│ │ ├── index.html.erb
│ │ ├── new.html.erb
│ │ └── show.html.erb
│ ├── global_note_templates/
│ │ ├── _form.html.erb
│ │ ├── index.html.erb
│ │ ├── new.html.erb
│ │ └── show.html.erb
│ ├── issue_templates/
│ │ ├── _form.html.erb
│ │ ├── _issue_select_form.html.erb
│ │ ├── _issue_template_link.html.erb
│ │ ├── _list_templates.api.rsb
│ │ ├── _list_templates.html.erb
│ │ ├── _note_form.html.erb
│ │ ├── _template_pulldown.html.erb
│ │ ├── index.api.rsb
│ │ ├── index.html.erb
│ │ ├── new.html.erb
│ │ └── show.html.erb
│ ├── issue_templates_settings/
│ │ └── index.html.erb
│ ├── note_templates/
│ │ ├── _form.html.erb
│ │ ├── _list_note_templates.html.erb
│ │ ├── index.api.rsb
│ │ ├── index.html.erb
│ │ ├── new.html.erb
│ │ └── show.html.erb
│ └── settings/
│ └── _redmine_issue_templates.html.erb
├── assets/
│ ├── javascripts/
│ │ ├── issue_templates.js
│ │ └── template_fields.js
│ └── stylesheets/
│ └── issue_templates.css
├── config/
│ ├── locales/
│ │ ├── bg.yml
│ │ ├── da.yml
│ │ ├── de.yml
│ │ ├── en.yml
│ │ ├── es.yml
│ │ ├── fr.yml
│ │ ├── it.yml
│ │ ├── ja.yml
│ │ ├── ko.yml
│ │ ├── pl.yml
│ │ ├── pt-BR.yml
│ │ ├── pt.yml
│ │ ├── ru.yml
│ │ ├── sr-YU.yml
│ │ ├── zh-TW.yml
│ │ └── zh.yml
│ └── routes.rb
├── db/
│ └── migrate/
│ ├── 0001_create_issue_templates.rb
│ ├── 0002_create_issue_template_settings.rb
│ ├── 0003_add_issue_title_to_issue_templates.rb
│ ├── 0004_add_position_to_issue_templates.rb
│ ├── 20121208150810_add_is_default_to_issue_templates.rb
│ ├── 20130630141710_add_enabled_sharing_to_issue_templates.rb
│ ├── 20130701024625_add_inherit_templates_to_issue_template_settings.rb
│ ├── 2014020191500_add_should_replaced_to_issue_template_settings.rb
│ ├── 20140307024626_create_global_issue_templates.rb
│ ├── 20140312054531_create_global_issue_templates_projects.rb
│ ├── 20140330155030_remove_is_default_from_global_issue_templates.rb
│ ├── 20160727222420_add_checklist_json_to_issue_templates.rb
│ ├── 20160828190000_add_checklist_json_to_global_issue_templates.rb
│ ├── 20160829001500_change_issue_template_enabled_column.rb
│ ├── 20160829001530_change_global_issue_template_enabled_column.rb
│ ├── 20170317082100_add_is_default_to_global_issue_templates.rb
│ ├── 20181104065200_add_unique_key_to_global_issue_templates_projects.rb
│ ├── 20190303082102_create_note_templates.rb
│ ├── 20190714171020_create_note_visible_roles.rb
│ ├── 20190714211530_add_visibility_to_note_templates.rb
│ ├── 20200101204020_add_related_link_to_issue_templates.rb
│ ├── 20200101204220_add_related_link_to_global_issue_templates.rb
│ ├── 20200102204815_add_link_title_to_issue_templates.rb
│ ├── 20200102205044_add_link_title_to_global_issue_templates.rb
│ ├── 20200103213630_add_builtin_fields_json_to_issue_templates.rb
│ ├── 20200115073600_add_builtin_fields_json_to_global_issue_templates.rb
│ ├── 20200314132500_change_column_note_template_description.rb
│ ├── 20200405115700_create_global_note_templates.rb
│ ├── 20200405120700_create_global_note_visible_roles.rb
│ └── 20200418114157_create_join_table_global_note_template_project.rb
├── docker-compose.yml
├── goodcheck.yml
├── init.rb
├── lang/
│ └── en.yml
├── lib/
│ ├── issue_templates/
│ │ ├── issues_hook.rb
│ │ └── journals_hook.rb
│ └── tasks/
│ ├── test.rake
│ └── util.rake
├── script/
│ └── circleci-setup.sh
├── spec/
│ ├── controllers/
│ │ ├── concerns/
│ │ │ └── issue_templates_common_spec.rb
│ │ ├── global_issue_templates_controller_spec.rb
│ │ ├── issue_templates_controller_spec.rb
│ │ └── settings_controller_spec.rb
│ ├── factories/
│ │ ├── enabled_modules.rb
│ │ ├── global_issue_templates.rb
│ │ ├── global_note_templates.rb
│ │ ├── issue_statuses.rb
│ │ ├── issue_template_settings.rb
│ │ ├── issue_templates.rb
│ │ ├── projects.rb
│ │ ├── role.rb
│ │ ├── trackers.rb
│ │ └── users.rb
│ ├── features/
│ │ ├── admin_spec.rb
│ │ ├── drag_and_drop_spec.rb
│ │ ├── issue_template_popup_spec.rb
│ │ ├── issue_template_spec.rb
│ │ └── update_issue_spec.rb
│ ├── helpers/
│ │ └── issue_templates_helper_spec.rb
│ ├── models/
│ │ ├── global_issue_template_spec.rb
│ │ ├── global_note_template_spec.rb
│ │ ├── issue_template_setting_spec.rb
│ │ ├── issue_template_spec.rb
│ │ └── note_visible_role_spec.rb
│ ├── rails_helper.rb
│ ├── requests/
│ │ ├── global_note_templates_spec.rb
│ │ └── note_templates_spec.rb
│ ├── spec_helper.rb
│ └── support/
│ ├── controller_helper.rb
│ └── login_helper.rb
└── test/
├── fixtures/
│ ├── global_issue_templates.yml
│ ├── global_issue_templates_projects.yml
│ ├── issue_template_settings.yml
│ └── issue_templates.yml
├── functional/
│ ├── global_issue_templates_controller_test.rb
│ ├── issue_templates_controller_test.rb
│ ├── issue_templates_settings_controller_test.rb
│ ├── issues_controller_test.rb
│ └── projects_controller_test.rb
├── integration/
│ └── layout_test.rb
├── test_helper.rb
└── unit/
├── global_issue_templates_test.rb
├── issue_template_setting_test.rb
├── issue_template_test.rb
└── note_template_test.rb
================================================
FILE CONTENTS
================================================
================================================
FILE: .circleci/config.yml
================================================
# Ruby CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-ruby/ for more details
#
version: 2
general:
artifacts:
- coverage/${CIRCLE_PROJECT_REPONAME}_test/index.html
jobs:
build:
docker:
# specify the version you desire here (ruby 2.6.x)
- image: circleci/ruby:2.6-browsers-legacy
steps:
- checkout
test:
docker:
# specify the version you desire here
- image: circleci/ruby:2.6-browsers-legacy
environment:
RAILS_ENV: test
DB_HOST: 127.0.0.1
DRIVER: headless
TZ: /usr/share/zoneinfo/Asia/Tokyo
- image: mysql:5.7
command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --innodb-large-prefix=true --innodb-file-format=Barracuda --sql-mode=""
environment:
MYSQL_USER: root
MYSQL_ALLOW_EMPTY_PASSWORD: yes
working_directory: ~/repo
steps:
- checkout
- run:
name: ready for redmine
command: |
REDMINE_BRANCH=master sh script/circleci-setup.sh
- run: perl -pi -e "s/gem \"capybara\".*$/gem \"capybara\"/g" Gemfile
- run: bundle install --path vendor/bundle --without postgresql rmagick && bundle update
- run: bundle exec rails g rspec:install
- run: bundle exec rake db:create RAILS_ENV=test
- run: bundle exec rake db:migrate RAILS_ENV=test
- run: bundle exec rake redmine:plugins:migrate RAILS_ENV=test
- run:
command: |
bundle exec rake ${CIRCLE_PROJECT_REPONAME}:test RAILS_ENV=test
- run:
command: |
bundle exec rspec -I plugins/redmine_issue_templates/spec --format documentation plugins/redmine_issue_templates/spec/models/
- run:
command: |
bundle exec rspec -I plugins/redmine_issue_templates/spec --format documentation plugins/redmine_issue_templates/spec/helpers/
- run:
command: |
bundle exec rspec -I plugins/redmine_issue_templates/spec --format documentation plugins/redmine_issue_templates/spec/controllers/
- run:
command: |
bundle exec rspec -I plugins/redmine_issue_templates/spec --format documentation plugins/redmine_issue_templates/spec/requests/
- run:
command: |
bundle exec rspec -I plugins/redmine_issue_templates/spec --format documentation plugins/redmine_issue_templates/spec/features/
- run:
command: |
bundle exec rake redmine:plugins:migrate NAME=${CIRCLE_PROJECT_REPONAME} \
VERSION=0 RAILS_ENV=test
- run:
command: |
mkdir -p /tmp/coverage
cp -r coverage/${CIRCLE_PROJECT_REPONAME}_test /tmp/coverage/
cp -r coverage/${CIRCLE_PROJECT_REPONAME}_spec /tmp/coverage/
- store_artifacts:
path: /tmp/coverage
workflows:
version: 2
build_and_test:
jobs:
- build
- test:
requires:
- build
filters:
branches:
ignore:
- /v0.2.x-support-Redmine3.*/
================================================
FILE: .gitattributes
================================================
.gitattributes export-ignore
.gitignore export-ignore
wercker.yml export-ignore
script/ export-ignore
.rubocop* export-ignore
Gemfile.local export-ignore
.circleci/ export-ignore
docker-compose.yml export-ignore
Dockerfile export-ignore
_config.yml export-ignore
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
ko_fi: akikopusu
================================================
FILE: .github/workflows/greetings.yml
================================================
name: Greetings
on: [issues]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thank you for contributing to Redmine Issue Templates plugin!'' first issue'
pr-message: 'Thanks you for contributing to Redmine Issue Templates plugin!'' first pr'
================================================
FILE: .gitignore
================================================
coverage/
doc/
.yardoc/
Gemfile.lock
Gemfile
.history
.wercker
================================================
FILE: .rubocop.yml
================================================
inherit_from: .rubocop_todo.yml
require:
- rubocop-rails
AllCops:
TargetRubyVersion: 2.4
Exclude:
- 'db/**/*'
================================================
FILE: .rubocop_todo.yml
================================================
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2016-06-01 07:37:41 +0900 using RuboCop version 0.40.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 3
Metrics/AbcSize:
Max: 55
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 200
Exclude:
- 'spec/**/*'
- 'test/**/*'
# "Line is too long"を無効
Layout/LineLength:
Enabled: false
# Offense count: 1
Metrics/CyclomaticComplexity:
Max: 10
# Offense count: 1
Metrics/PerceivedComplexity:
Max: 10
Metrics/BlockLength:
Max: 30
Exclude:
- 'spec/**/*'
- 'test/**/*'
# Avoid methods longer than 10 lines of code
MethodLength:
CountComments: true # count full line comments?
Max: 45
# Aboid Missing top-level module documentation comment.
Documentation:
Enabled: false
EndOfLine:
Enabled: false
Metrics/ModuleLength:
Max: 120
Rails/ApplicationRecord:
Enabled: false
Rails/UniqueValidationWithoutIndex:
Enabled: false
Rails/InverseOf:
Enabled: false
Rails/LexicallyScopedActionFilter:
Enabled: false
Rails/SkipsModelValidations:
Enabled: false
================================================
FILE: Dockerfile
================================================
FROM ruby:2.6
LABEL maintainer="AKIKO TAKANO / (Twitter: @akiko_pusu)" \
description="Image to run Redmine simply with sqlite to try/review plugin."
### get Redmine source
### Replace shell with bash so we can source files ###
RUN rm /bin/sh && ln -s /bin/bash /bin/sh
### install default sys packeges ###
RUN apt-get update
RUN apt-get install -qq -y \
git vim \
sqlite3 default-libmysqlclient-dev
RUN apt-get install -qq -y build-essential libc6-dev
# for e2e test env
RUN sh -c 'echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
RUN apt-get update && apt-get install -y google-chrome-stable
RUN google-chrome --version | perl -pe 's/([^0-9]+)([0-9]+)(\.[0-9]+).+/$2/g' > chrome-version-major
RUN curl https://chromedriver.storage.googleapis.com/LATEST_RELEASE_`cat chrome-version-major` > chrome-version
RUN curl -O -L http://chromedriver.storage.googleapis.com/`cat chrome-version`/chromedriver_linux64.zip && rm chrome-version*
RUN unzip chromedriver_linux64.zip && mv chromedriver /usr/local/bin
RUN cd /tmp && svn co http://svn.redmine.org/redmine/trunk redmine
WORKDIR /tmp/redmine
COPY . /tmp/redmine/plugins/redmine_issue_templates/
# add database.yml (for development, development with mysql, test)
RUN echo $'test:\n\
adapter: sqlite3\n\
database: /tmp/data/redmine_test.sqlite3\n\
encoding: utf8mb4\n\
development:\n\
adapter: sqlite3\n\
database: /tmp/data/redmine_development.sqlite3\n\
encoding: utf8mb4\n\
development_mysql:\n\
adapter: mysql2\n\
host: mysql\n\
password: pasword\n\
database: redemine_development\n\
username: root\n'\
>> config/database.yml
RUN gem update bundler
RUN bundle install
RUN bundle exec rake db:migrate
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]
================================================
FILE: Gemfile.local
================================================
group :test do
gem 'simplecov-rcov', require: false
gem 'rspec-rails'
gem 'factory_bot_rails'
gem 'launchy'
gem 'database_cleaner'
end
# for Debug
group :development, :test do
gem 'pry-rails'
gem 'pry-byebug'
end
================================================
FILE: ISSUE_TEMPLATE.md
================================================
This is a template to report bug related to redmine issue templates plugin.
You can fill in any format, free style in case report features or questions.
## Summary
## Description
## Environment
These informations are greatly helpful to support quickly.
You can get these informations from Redmine's information page.
(E.g. http://example.com/admin/info)
- Redmine version
- Installed plugins
- Ruby version
- OS Platform
- Database (MariaDB, MySQL, PostgreSQL) and its version
- Rails Env
## Visual Proof / Screenshot
When reporting an application error, post the error stack trace that
you should find in the **log file** (eg. log/production.log).
Screen shot would be also helpful.
## Expected Results
## Actual Results
## Workaround
Please let me know if you have any workaround.
================================================
FILE: LICENSE.txt
================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
================================================
FILE: README.md
================================================
# Redmine Issue Templates Plugin
[](http://www.redmine.org/plugins/redmine_issue_templates)
[](https://circleci.com/gh/akiko-pusu/redmine_issue_templates/tree/master)
[](https://sider.review/features)
Plugin to generate and use issue templates for each project to assist issue
creation. The latest version 1.0.x **is not compatible with IE11**. (Related: #310)
Please use version 0.3.8 or **[0.3-stable](https://github.com/akiko-pusu/redmine_issue_templates/tree/0.3-stable) branch** (uing jQuery version) as a stable release for Redmine4.x.
## Repository
* <https://github.com/akiko-pusu/redmine_issue_templates>
## Plugin installation
1. Copy the plugin directory into the $REDMINE_ROOT/plugins directory. Please
note that plugin's folder name should be "redmine_issue_templates". If
changed, some migration task will be failed.
2. Do migration task.
e.g. rails redmine:plugins:migrate RAILS_ENV=production
3. (Re)Start Redmine.
## Uninstall
Try this:
* rails redmine:plugins:migrate NAME=redmine_issue_templates VERSION=0
RAILS_ENV=production
### When migration error
If the migration is cancelled with the error like following message for the first time you try to install this plugin:
> Caused by: Mysql2::Error: Table 'DATABASE_FOR_REDMINE.issue_templates' doesn't exist
You can fix this error to remove migration records related to this plugin from shema_migrations table.
If you can access and select database for Redmine, try this command:
```sql
select * from schema_migrations where version like '%redmine_issue_templates%';
```
If there are any records shown like this and there is no table named 'issue_templates', your installation has been incomplete state.
```sql
1-redmine_issue_templates
2-redmine_issue_templates
```
So, you should better to uninstall task first, and retry the migration.
If you have not created any template records yet, and hope to uninstall and re-install this plugin, please see README.
**Uninstall:**
```ruby
rails db:migrate_plugins NAME=redmine_issue_templates VERSION=0 RAILS_ENV=production
```
After that, records of migration are removed from schema_migrations table.
**Re-install:**
```ruby
rails db:migrate_plugins NAME=redmine_issue_templates RAILS_ENV=production (for Redmine4.x)
```
**Related issue:**
* <https://github.com/akiko-pusu/redmine_issue_templates/issues/285>
* <https://github.com/akiko-pusu/redmine_issue_templates/issues/169>
* <https://github.com/akiko-pusu/redmine_issue_templates/issues/82#issuecomment-302000185>
## Required Settings
1. Login to your Redmine install as an Administrator
2. Enable the permissions for your Roles:
* Show issue templates: User can show issue templates and use templates when creating/updating issues.
* Edit issue templates: User can create/update/activate templates for each project.
* Manage issue templates: User can edit help message of templates for each project.
3. Enable the module "Issue Template" on the project setting page.
4. The link to the plugin should appear on that project's navigation.
## Note
This plugin aims to assist contributor's feedback by using template if the
project has some format for issues.
## Troubleshoot for bundle intall and startup problem
This plugin repository includes some test code and gem settings. If you have
some trouble related "bundle install", please try --without option.
> Exp. bundle install --without test
## WebPage
* <https://www.redmine.org/plugins/redmine_issue_templates> (Redmine Plugin List)
* <https://github.com/akiko-pusu/redmine_issue_templates> (Repository & Issues)
If you have any requests, bug reports, please use GitHub issues. <https://github.com/akiko-pusu/redmine_issue_templates>
## Description and usage info
* <https://github.com/akiko-pusu/redmine_issue_templates/wiki>
## Changelog
### 1.1.0
Drop off the feature to integrate with Checklist plugin, for maintenance reason.
Please see for more details: <https://github.com/akiko-pusu/redmine_issue_templates/issues/363>
### 1.0.5
Bugfix and final release to support Checklist integration.
Please see: <https://github.com/akiko-pusu/redmine_issue_templates/issues/363>
* Bugfix: template_type is not defined error (GitHub: #364 / Thanks for reporting issue, @toku463ne)
### 1.0.4
Release to implemented some additional built-in/custom fields support.
* Feature: Add preselected watchers to templates. (GitHub: #302)
* Feature: Enabled to define assignees and categories. (GitHub: #362)
* Bugfix: Template duplicates when changing Status or Category fields. (GitHub: #354)
* Bugfix: Template body not loaded into issue answer (v.1.0.3 only) (GitHub: #356)
* Update JavaScript and Spec.
Thank you for the valuable information and feedback, @ChrisUHZ!
RESTRICTION: This version **is still not compatible with IE11**. (Related: #310)
### 1.0.3
NOTE: Mainly, maintenance, bugfix and refactoring only. There is no additional feature.
* Refactor JavaScript to work properly under jQuery 3.x (for Redmine trunk).
* Add some feature specs to test Builtin-fields support.
RESTRICTION: This version **is still not compatible with IE11**. (Related: #310)
### 1.0.2
Release to implememted Global note templates feature.
NOTE: **Migration is required** to use global note template.
* Feature: Implement Global Note Template. (GitHub: #268, #336)
* Feature: Improve the input form for built-In / custom fields setting. (GitHub: #345)
* Bugfix: Selecting note template browser "jumps" to top of page. (GitHub: #338)
* Bugfix: Change to make the selector more specific. Thanks, @sandratatarevicova (GitHub: #332, #333)
* Apply Bulgarian translation. Thanks, @jwalkerbg (GitHub: #330)
* Update README: `--without` argument for `bundle` is no longer necessary. (GitHub: #335 / by @vividtone)
* Update German Translation (by Christian Friebel).
RESTRICTION: This version **is still not compatible with IE11**. (Related: #310)
### 1.0.1
This is bugfix release against v1.0.0.
Updating to 1.0.1 is highly recommended, if you're using 1.0.0.
Migration is also required.
* Bugfix: Can't create a new templates optional settings. (GitHub: #322)
* Migration: Change the column type to text. (GitHub: #323)
* Update JavaScript.
Thank you for the valuable information and feedback, @AlUser71!
### 1.0.0
RESTRICTION: This version **is not compatible with IE11**. (Related: #310)
Please use version **0.3.8** or **[0.3-stable](https://github.com/akiko-pusu/redmine_issue_templates/tree/0.3-stable) branch** (uing jQuery version) if you need to support IE11.
NOTE: **Migration is required**.
Since ``Support Built-In / Custom Fields`` is an experimental feature, please **be careful** if you hope to try it.
* Feature: Add feature to show template usage / example (#303)
* Using Vue.js v2.6.11
* Feature: Support Built-In / Custom Fields (#304)
* Rewrite JavaSctipt code from jQuery into plain JavaScript.
And some browsers may not work fine because Support Built-In / Custom Fields feature uses Vue.js for frontend.
So feedback, issue report, suggestion highly appreciate!
### 0.3.8
This is bugfix release.
* Bugfix: Fix that Issue Templates plugin changes the cursor icon for "Information" menu on Redmine's administration page (by vividtone, GitHub #316)
* Bugfix: Orphaned template list is not displayed (GitHub #337)
* Update Russian translation (GitHub #340)
* Update Bulgarian translation (GitHub #329)
* Update Korean translation (update Korean translation)
* Bugfix: enabled to create a new issue template setting. (GitHub #322)
### 0.3.7
This is bugfix release to prevent the conflict with other plugins.
* Bugfix: Tooltip for template body preview is hidden. (GitHub PR #300)
* Refactor: Change to use project menu to prevent the project setting tab's conflict. (GitHub PR #299)
Thank you for the valuable information and feedback, @ChrisUHZ!
### 0.3.6
This is bugfix release against v0.3.5.
Updating to 0.3.6 is highly recommended!
* Update zh-TW locale. #281 (by Vongola)
* Refactor: Update test code / Change Validation check.
* Add troubleshooting for migration error and uninstall.
* Add workaround to prevent other plugin's conflict. (#282)
* Add workaround to load right templates if the project has subproject and subproject selected. (#289)
* Apply the patch by @dmakurin to prevent the error when the user can't edit tracker id. (#288)
* Only wipe issue subject and description if replace flag. (#284, Applied Pull Request by @mattgill)
### 0.3.5
NOTE: This version requires migration command to enhance note template's feature.
``Note Template visibility per role`` feature is still a prototype, so feedback highly appreciate!
* Design: PR / Mrliptontea theme compatibility #266 (by mrliptontea)
* Bugfix: #270 / Apply polyfill code for IE11. (reported by yui-har)
* Feature: Note Template visibility per role. #267
* Bugfix: Fix the request URL for accessing note_templates/load #261 (by ishikawa999)
* Bugfix: Note Template does not work on CKEDitor. #275
* Update README for contribution #273
### 0.3.4
This is bugfix release against v0.3.3.
* Add navigation link between issue template and note template.
* Refactor: Change to use let / const instead of var.
* Update test environment, especially E2E. (Follow up Redmine4.1)
* Bugfix #256 / Related to checklists.
### 0.3.3
This is bugfix release against v0.3.2.
Updating to 0.3.3 is highly recommended!
* Revert and Bugfix #230
* Merge pull request #252 from ishikawa999/fix/248 by @ishikawa999
* Bugfix: #234 / Enable to save checklists when updating a template.
### 0.3.2
* Bugfix: Adding issue templates with checklists occurs internal error.(#243)
* Merge PR commit: bca2fe481 by @two-pack, restored missing newline. (Related: #242)
* Feature: Add clear subject/body option when tracker changed which has no template. (#230)
* Code refactoring.
### 0.3.1
* Basic feature implemented of note template.
* Enabled to use issue templates when updating issue.
* Go to global template admin setting, and turn on "apply_template_when_edit_issue" flag.
* Bugfix: Prevent conflict against issue controller helper. (#217)
* Update readme: Merged PR #219. Thanks Arnaud Venturi!
NOTE: This version requires migration command to use note template feature.
```bash
rails redmine:plugins:migrate RAILS_ENV=production
```
### 0.3.0
* Support Redmine 4.x.
* Now master branch unsupports Redmine 3.x.
* Please use ver **0.2.x** or ``v0.2.x-support-Redmine3`` branch
in case using Redmine3.x.
* Follow Redmine's preview option to the wiki toolbar.
* Show additional navigation message when plugin is applied to Redmine 3.x.
NOTE: Mainly, maintenance, bugfix and refactoring only. There is no additional feature, translation in this release.
Thank you for creating patch, Mizuki Ishikawa!
### 0.2.1
Mainly, bugfix and refactoring release.
Updating to 0.2.1 is highly recommended in case using CKEditor or MySQL replication.
NOTE: Migration is required, especially using MySQL replication.
* Bugfix: Fix "Page not found" error when try to create project template from project setting. (GitHub: #192, #199)
* Bugfix: Add composite unique index to support MySQL group replication. (GitHub: #197)
* Workaround: Wait fot 200 msec until CKE Editor's ajax callback done. (GitHub: #193)
* Add feature to hide confirmation dialog when overwritten issue subject and description, with using user cookie. (GitHub: #190)
* Refactoring: Minitest and so on.
A cookie named "issue_template_confirm_to_replace_hide_dialog" is stored from this release. (Related: #190)
### 0.2.0
Bugfix and refactoring release.
Updating from v0.1.9 to 0.2.0 is highly recommended.
In this release, some methods which implemented on Redmine v3.3 are ported
for plugin's compatibility. (To support Redmine 3.0 - 3.4)
* Bugfix: Prevent to call unimplemened methods prior to Redmine3.2. (GitHub: #180)
* Refactoring: Code format. (JS, CSS) / Update config for E2E test.
* Updated Simplified Chinese translation, thanks Steven.W. (GitHub PR: #179)
* Applied responsive layout against template list (index) page.
Thank you for reviewing, Tatsuya Saito!
For release notes before v0.2.0, please see: [RELEASE-NOTES.md](RELEASE-NOTES.md)
### Contributing
Pull requests, reporting issues, stars are always welcome!
I'm always thrilled to receive pull requests, and do my best to process them as fast as possible.
Not sure if that typo is worth a pull request? Do it! I will appreciate it.
* Fork it!
* Create your feature branch: git checkout -b my-new-feature
* Commit your changes: git commit -am 'Add some feature'
* Push to the branch: git push origin my-new-feature
* Submit a pull request :D
### Language and I18n contributors
* Brazilian: Adriano Ceccarelli / Pedro Moritz de Carvalho Neto
* Korean: Jaebok Oh
* Chinese: Steven Wong, vongola12324 (zh-TW)
* Bulgarian: Ivan Cenov
* Russian: Denny Brain, danaivehr
* German: Terence Miller, Christian Friebel and anonymous contributor
* French: Anonymous one
* Serbian: Miodrag Milic
* Polish: Paweł Budikom and Krzysztof Wosinski
* Spanish: Andres Arias
* Italian: Luca Lesinigo
* Danish: AThomsen
### Rake Tasks
You can see rake task, with (bundle exec) rake -T, related to this plugin.
Exp.
```bash
# Apply inhelit template setting to child projects
$ rake redmine_issue_templates:apply_inhelit_template_to_child_projects[project_id]
# Run test for redmine_issue_template plugin
$ rake redmine_issue_templates:default
# Run spec for redmine_issue_template plugin
$ rake redmine_issue_templates:spec
# Run tests
$ rake redmine_issue_templates:test
# Unapply inhelit template setting from child projects
$ rake redmine_issue_templates:unapply_inhelit_template_from_child_projects[project_id]
# Generate YARD Documentation for redmine_issue_template plugin
$ rake redmine_issue_templates:yardoc
```
You can apply/unapply inherit templates for all the hild projects.
```bash
rake redmine_issue_templates:apply_inhelit_template_to_child_projects[project_id] # Apply inhelit template setting to child projects
rake redmine_issue_templates:unapply_inhelit_template_from_child_projects[project_id] # Unapply inhelit template setting from child projects
```
If you want to apply inherit templates setting all the child project of project_id: 1 (as parent project), please run rake command like this:
rake redmine_issue_templates:apply_inhelit_template_to_child_projects[1]
### Run test
Please see .circleci/config.yml for more details.
```bash
% cd REDMINE_ROOT_DIR
% cp plugins/redmine_issue_templates/Gemfile.local plugins/redmine_issue_templates/Gemfile
% bundle install --with test
% export RAILS_ENV=test
% bundle exec ruby -I"lib:test" -I plugins/redmine_issue_templates/test plugins/redmine_issue_templates/test/functional/issue_templates_controller_test.rb
```
or
```bash
% bundle exec rails redmine_issue_templates:test
```
#### Run spec
Please see .circleci/config.yml for more details.
```bash
% cd REDMINE_ROOT_DIR
% cp plugins/redmine_issue_templates/Gemfile.local plugins/redmine_issue_templates/Gemfile
% bundle install --with test
% export RAILS_ENV=test
% bundle exec rspec -I plugins/redmine_issue_templates/spec --format documentation plugins/redmine_issue_templates/spec/
```
By default, use chrome as a webdriver. If you set environment variable
'DRIVER' to 'headless', headless_chrome is used.
```bash
% DRIVER='headless' bundle exec rspec -I plugins/redmine_issue_templates/spec --format documentation plugins/redmine_issue_templates/spec/
```
### License
This software is licensed under the GNU GPL v2.
================================================
FILE: RELEASE-NOTES.md
================================================
# Releas notes before v0.2.0
### 0.1.9
Bugfix and refactoring release.
* Bugfix: Fix wrong template sort ordering. (GitHub: #174)
* Change UI to reorder templates with using drag and drop.
* Add feature to copy template (Now project scope template only.)
* Code refactoring. Use Headless Chrome for feature spec. Change to use CircleCI for build and test.
* PR: Update Bulgarian translation. Thank you so much, Ivan Cenov! (GitHub: #171)
* PR: Update Update pt-BR.yml Thank you so much, Adriano Baptistella! (GitHub: #173)
* Bugfix: Wrong column label in "Preview Template Contents" modal dialog. (GitHub: #154)
* PR: Updates to German language file. Thank you so much, Tobias Fischer! (GitHub: #164)
### 0.1.8
Bugfix release.
* Bugfix: Prevent "undefined local variable or method" error when listing project orphaned templates. (GitHub: #150)
* PR: Add Portuguese translation. Thank you so much, Adriano Baptistella! (GitHub: #149)
* Change url of Redmine Plugin Directory. (Changed identifier from issue_templates to redmine_issue_templates.)
### 0.1.7
Bugfix release, and some code refactorings.
#### Bugfix
* After related tracker is removed, index (list) templates failed with exception. (#139)
* Checklist not loading from Template. (#141)
#### Refactoring
* Remove all unlodable statement.
* Remove unused rake task.
* Rename modules.
### 0.1.6
Maintenance release to follow Redmine's update, and some refactoring related to test, namespace.
Other additional updates are following:
* Change support Redmine version to 3.0 or higher.
* Stop to use jbuilder for rendering json. (#124)
* Now any gemfile is not used.
* PR: UI improvement / Correct CSS. Thanks taqueci! (#120, #123)
* Bugfix: Add exception handler and not to work rake task if rake task name is not specified. (#130)
* Logging if template is deleted. (#118)
* Change Template UI related to delete action. (#117)
* Prevent unexpected deletion of template.
* PR: Add to confirm before replacing description and subject. Thanks, Tatsuya Saito. (#111)
* PR: Fix CSS setting. Thanks, Tatsuya Saito. (#110)
* Updated Simplified Chinese translation, thanks Steven.W. (#105, #113)
### 0.1.5
NOTE: Please run "rake redmine:plugins:migrate" task because new column is added.
#### Feature for Global issue templates
* Add feature enabled to mark global issue template as "default".
* Add plugin setting option to apply global issue templates to all the project.
* This option is on the plugin configuration screen. Please read help content before activate this option!
#### Other updates
* Update Russian translation. Thanks danaivehr! (GitHub: #95)
* Prevent to locate template pulldown above "tracker" field and soon after jump below "tracker" field. (GitHub: #96)
* Unselect projects on global issue template edit screen does not work correctly. (GitHub: #99)
* Feature: Add “Revert” Icon to revert applied template. (Github: #98)
* Change the place of message to notice "default template loaded" now to bottom of the page.
* Change the place of "Check all | Uncheck all” link in global issue template create / edit screen, to above the project list. (GitHub: #90)
* In case the list of projects is very long and would be much more comfortable to have the option on top.
* Project select checkbox area is collapsed by default.
* Also, in case the list of projects is very long, administrator has to scroll to submit "Save" button.
### 0.1.4.1
Bugfix version for #83, #92. Correct some methods not to use named parameters,
because ruby 1.9x does not support named parameters.
* Bugfix: GitHub: #83, #92
* Bug: Italian translation should be start with "it". (GitHub: #87)
### 0.1.4
Maintenance release to follow Redmine's update, and some refactoring related to test, namespace.
Other additional updates are following:
* Change css and default width setting for template filter modal dialog. (GitHub: #78)
* Add Italian translation. Thank you so much, Luca Lesinigo! (GitHub: #75)
* Add Danish translation. Thank you so much, AThomsen! (GitHub: #68)
* Do not append template contents if the content hasn't been edited. (GitHub: #62)
* Add rake task to apply/unapply inherit templates for all the hild projects. (GitHub: #61)
### 0.1.3
NOTE: Please run "rake redmine:plugins:migrate" task because new column is
added.
* Code refactoring. (Thank you so much for SideCI!)
* Enabled to use template in case no project parameter passed. (GitHub: #43)
* Updated the German locale. Thanks, jwciss!
* Template is loaded after the error when required fields are not filled.
(GitHub: #50)
* First implement to integrate Checklist plugin. (GitHub: #39)
### 0.1.2
* Move repository from Bitbucket to Github.
* Add Spanish translation. Thanks, Andres Arias (r-labs #1413)
* Add popup to preview template description and filter template. (Featured:
r-labs 1410)
* Bugfix: Prevent to load default template in case updated issue form
triggered by states change event. (Related: bitbucket#36, Template loads
every time Status is changed.)
* Update Simplified Chinese Localization. Thanks, Steven Wong.
* Support REST API with json format. (prototype. r-labs #1324)
* Code refactoring.
### 0.1.1
Bugfix release.
* Update Brazilian translation file. (Bitbucket Pull Request: #4)
* Removed deprecation warnings and adjusted gemfile to redmine 3.1.x
(Bitbucket Pull Request: #5)
* Bug fix, prevent load template and overwrite description when status
changed. (Bitbucket Issue: #36)
* Hide templates Element on Trackers without Issue Template. (Bitbucket
Issue: #57)
* Bug fix, when issue create issue from copy, template should not overwrite
description. (Bitbucket Issue: #70)
Special thanks all contributors, and Mattani-san, to this release.
### 0.1.0
NOTE: Please run "rake redmine:plugins:migrate" task because new column is
added.
* Support Redmine 3.0. (r-labs: #1366)
* Add Sort to Global Templates. (r-labs: #1364)
* Add Polish translation file. (r-labs: #1354)
### 0.0.9
Bug fix release.
* Fix bug on ruby 1.8. (#52)
* Remove feature to use JQuery tooltip to preview description, because
useless. (#50)
* Change css definition to avoide conflict with Redmine's base style. (#45)
* Correct migration file to prevent uninstall error. (Related: #54)
### 0.0.8
NOTE: Please run "rake redmine:plugins:migrate" task because new column is
added.
* Fix some bugs.
* Support global issue templates.
* Try to use JQueryUI's tooltip.
* Add Chinese / zh-TW translation file. Thank you so much, Chinese Spporter!
Known issue:
* Template loads every time Status is changed
* <https://bitbucket.org/akiko_pusu/redmine_issue_templates/issue/36>
* Only happned in case using default template.
### 0.0.7
NOTE: Please run "rake redmine:plugins:migrate" task because new column is
added.
* Fix some bugs.
* Compatible with CKEditor. (#1280)
* Add feature to show warning message for orphaned templates. (#1278)
* Inherited templates only should be listed which tracker is the same to
child project use. (#1278)
* Add French translation file. (Bitbucket IssueID:33)
* Add Serbian translation. Thank you so much, Miodrag Milic. (Bitbucket
IssueID:34)
* Add option to change append or replace with template. (#1176)
### 0.0.6
* Inherited templates from parent project. (#1267)
* Add links to template list/edit at project setting tab. (#1269)
* Add link to erase issue subject and description text.
* Replace :rubygems in Gemfile with 'https://rubygems.org'. Thanks for
JohnArcher.
* Fixed invalid encoding. Thank you so much, Christoph. (#1178)
* Fixed append "null" string to issue title field. (IssueID: #1268)
* Prevent to load template when update and redirect with validation error.
(#1151, #1254)
### 0.0.5
* Load default template. (#1088)
* Show warning message in case no project trackers are assigned.
* Change CSS style when showing template. (#1141)
### 0.0.4
* Support Redmine 2.1.x (Now unsupport Redmine 2.0.x. Please use ver 0.0.3
for Redmine2.0.x) Thak you so much, Viktor Muth, that gave me some
feedback.
* Now insert template text just after the text that is already in the
description field. (#1115)
================================================
FILE: _config.yml
================================================
theme: jekyll-theme-slate
================================================
FILE: app/controllers/concerns/issue_templates_common.rb
================================================
# frozen_string_literal: true
module Concerns
module IssueTemplatesCommon
extend ActiveSupport::Concern
class InvalidTemplateFormatError < StandardError; end
included do
before_action :log_action, only: [:destroy]
# logging action
def log_action
logger&.info "[#{self.class}] #{action_name} called by #{User.current.name}"
end
def plugin_setting
Setting.plugin_redmine_issue_templates
end
def apply_all_projects?
plugin_setting['apply_global_template_to_all_projects'].to_s == 'true'
end
def apply_template_when_edit_issue?
plugin_setting['apply_template_when_edit_issue'].to_s == 'true'
end
def builtin_fields_enabled?
plugin_setting['enable_builtin_fields'].to_s == 'true'
end
end
def load_selectable_fields
tracker_id = params[:tracker_id]
project_id = params[:project_id]
render plain: {} && return if tracker_id.blank?
custom_fields = core_fields_map_by_tracker_id(tracker_id: tracker_id, project_id: project_id).merge(custom_fields_map_by_tracker_id(tracker_id))
render plain: { custom_fields: custom_fields }.to_json
end
def orphaned_templates
render partial: 'common/orphaned', locals: { orphaned_templates: orphaned }
end
def apply_all_projects?
plugin_setting['apply_global_template_to_all_projects'].to_s == 'true'
end
def builtin_fields_json
value = template_params[:builtin_fields].blank? ? {} : JSON.parse(template_params[:builtin_fields])
return value if value.is_a?(Hash)
raise InvalidTemplateFormatError
end
def valid_params
attributes = template_params.except(:builtin_fields)
attributes[:builtin_fields_json] = builtin_fields_json if builtin_fields_enabled?
attributes
end
def destroy
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
end
#
# TODO: Code should be refactored
#
def core_fields_map_by_tracker_id(tracker_id: nil, project_id: nil)
return {} unless builtin_fields_enabled?
fields = %w[status_id priority_id]
fields << 'watcher_user_ids' if project_id.present?
# exclude "description"
tracker = Tracker.find_by(id: tracker_id)
fields += tracker.core_fields.reject { |field| field == 'description' } if tracker.present?
fields.reject! { |field| %w[category_id fixed_version_id assigned_to_id].include?(field) } if project_id.blank?
map = {}
fields.each do |field|
id = "issue_#{field}"
name = I18n.t('field_' + field.gsub(/_id$/, ''))
value = { name: name, core_field_id: id }
if field == 'priority_id'
value[:possible_values] = IssuePriority.active.pluck(:name)
value[:field_format] = 'list'
end
if field == 'status_id' && tracker.present?
value[:possible_values] = tracker.issue_statuses.pluck(:name)
value[:field_format] = 'list'
end
if field == 'category_id' && project_id.present?
categories = IssueCategory.where(project_id: project_id)
value[:possible_values] = categories.pluck(:name)
value[:field_format] = 'list'
end
if field == 'assigned_to_id' && project_id.present?
project = Project.find(project_id)
assignable_users = (project.assignable_users(tracker).to_a + [project.default_assigned_to]).uniq.compact
value[:possible_values] = assignable_users.map { |user| user.name }
value[:field_format] = 'list'
end
if field == 'watcher_user_ids' && project_id.present?
issue = Issue.new(tracker_id: tracker_id, project_id: project_id)
watchers = helpers.users_for_new_issue_watchers(issue)
value[:field_format] = 'list'
value[:possible_values] = watchers.map { |user| "#{user.name} :#{user.id}" }
value[:name] = I18n.t('field_watcher')
value[:multiple] = true
end
value[:field_format] = 'date' if %(start_date due_date).include?(field)
value[:field_format] = 'ratio' if field == 'done_ratio'
map[id] = value
end
map
rescue StandardError => e
logger&.info "core_fields_map_by_tracker_id failed due to this error: #{e.message}"
{}
end
def custom_fields_map_by_tracker_id(tracker_id = nil)
return {} unless builtin_fields_enabled?
return {} if tracker_id.blank?
tracker = Tracker.find_by(id: tracker_id)
ids = tracker&.custom_field_ids || []
fields = IssueCustomField.where(id: ids)
map = {}
fields.each do |field|
id = "issue_custom_field_values_#{field.id}"
attributes = field.attributes
attributes = attributes.merge(possible_values: field.possible_values_options.map { |value| value[0] }) if field.format.name == 'bool'
map[id] = attributes
end
map
rescue StandardError => e
logger&.info "core_fields_map_by_tracker_id failed due to this error: #{e.message}"
{}
end
end
end
================================================
FILE: app/controllers/concerns/project_templates_common.rb
================================================
# frozen_string_literal: true
module Concerns
module ProjectTemplatesCommon
extend ActiveSupport::Concern
included do
before_action :find_user, :find_project, :authorize, except: %i[preview load load_selectable_fields]
before_action :find_object, only: %i[show edit update destroy]
accept_api_auth :index, :list_templates, :load
end
def show
render render_form_params
end
def destroy
unless template.destroy
flash[:error] = l(:enabled_template_cannot_destroy)
redirect_to action: :show, project_id: @project, id: template
return
end
flash[:notice] = l(:notice_successful_delete)
redirect_to action: 'index', project_id: @project
end
def save_and_flash(message, action_on_failure)
unless template.save
render render_form_params.merge(action: action_on_failure)
return
end
respond_to do |format|
format.html do
flash[:notice] = l(message)
redirect_to action: 'show', id: template.id, project_id: @project
end
format.js { head 200 }
end
rescue NoteTemplate::NoteTemplateError => e
flash[:error] = e.message
render render_form_params.merge(action: action_on_failure)
nil
end
def plugin_setting
Setting.plugin_redmine_issue_templates
end
def apply_all_projects?
plugin_setting['apply_global_template_to_all_projects'].to_s == 'true'
end
private
def template
raise NotImplementedError, "You must implement #{self.class}##{__method__}"
end
def find_user
@user = User.current
end
def find_tracker
@tracker = Tracker.find(params[:issue_tracker_id])
end
def find_project
@project = Project.find(params[:project_id])
rescue ActiveRecord::RecordNotFound
render_404
end
end
end
================================================
FILE: app/controllers/global_issue_templates_controller.rb
================================================
# frozen_string_literal: true
# noinspection RubocopInspection
class GlobalIssueTemplatesController < ApplicationController
layout 'base'
helper :issues
include IssueTemplatesHelper
include Concerns::IssueTemplatesCommon
menu_item :issues
before_action :find_object, only: %i[show edit update destroy]
before_action :find_project, only: %i[edit update]
before_action :require_admin, only: %i[index new show], excep: [:preview]
#
# Action for global template : Admin right is required.
#
def index
trackers = Tracker.all
template_map = {}
trackers.each do |tracker|
tracker_id = tracker.id
templates = GlobalIssueTemplate.search_by_tracker(tracker_id).sorted
template_map[Tracker.find(tracker_id)] = templates if templates.any?
end
render layout: !request.xhr?, locals: { template_map: template_map, trackers: trackers }
end
def new
# create empty instance
@global_issue_template = GlobalIssueTemplate.new
render render_form_params
end
def create
@global_issue_template = GlobalIssueTemplate.new
@global_issue_template.author = User.current
begin
@global_issue_template.safe_attributes = valid_params
rescue ActiveRecord::SerializationTypeMismatch, Concerns::IssueTemplatesCommon::InvalidTemplateFormatError
flash[:error] = I18n.t(:builtin_fields_should_be_valid_json, default: 'Please enter a valid JSON fotmat string.')
render render_form_params.merge(action: :new)
return
end
save_and_flash(:notice_successful_create, :new) && return
end
def show
render render_form_params
end
def update
begin
@global_issue_template.safe_attributes = valid_params
rescue ActiveRecord::SerializationTypeMismatch, Concerns::IssueTemplatesCommon::InvalidTemplateFormatError
flash[:error] = I18n.t(:builtin_fields_should_be_valid_json, default: 'Please enter a valid JSON fotmat string.')
render render_form_params.merge(action: :show)
return
end
save_and_flash(:notice_successful_update, :show)
end
def edit
# Change from request.post to request.patch for Rails4.
return unless request.patch? || request.put?
begin
@global_issue_template.safe_attributes = valid_params
rescue ActiveRecord::SerializationTypeMismatch
flash[:error] = I18n.t(:builtin_fields_should_be_valid_json, default: 'Please enter a valid JSON fotmat string.')
render render_form_params.merge(action: :show)
return
end
save_and_flash(:notice_successful_update, :show)
end
def destroy
unless @global_issue_template.destroy
flash[:error] = l(:enabled_template_cannot_destroy)
redirect_to action: :show, id: @global_issue_template
return
end
flash[:notice] = l(:notice_successful_delete)
redirect_to action: 'index'
end
# preview
def preview
global_issue_template = params[:global_issue_template]
id = params[:id]
@text = (global_issue_template ? global_issue_template[:description] : nil)
@global_issue_template = GlobalIssueTemplate.find(id) if id
render partial: 'common/preview'
end
private
def orphaned
GlobalIssueTemplate.orphaned
end
def find_project
@projects = Project.all
end
def find_object
@global_issue_template = GlobalIssueTemplate.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
def save_and_flash(message, action_on_failure)
unless @global_issue_template.save
render render_form_params.merge(action: action_on_failure)
return
end
respond_to do |format|
format.html do
flash[:notice] = l(message)
redirect_to action: 'show', id: @global_issue_template.id
end
format.js { head 200 }
end
end
def template_params
params.require(:global_issue_template)
.permit(:title, :tracker_id, :issue_title, :description, :note, :is_default, :enabled,
:author_id, :position, :related_link, :link_title, :builtin_fields,
project_ids: [])
end
def render_form_params
trackers = Tracker.all
projects = Project.all
tracker_id = @global_issue_template.tracker_id
custom_fields = core_fields_map_by_tracker_id(tracker_id: tracker_id)
.merge(custom_fields_map_by_tracker_id(tracker_id)).to_json
{ layout: !request.xhr?,
locals: { trackers: trackers, apply_all_projects: apply_all_projects?,
issue_template: @global_issue_template, projects: projects, custom_fields: custom_fields.to_s,
builtin_fields_enable: builtin_fields_enabled? } }
end
end
================================================
FILE: app/controllers/global_note_templates_controller.rb
================================================
# frozen_string_literal: true
# noinspection RubocopInspection
class GlobalNoteTemplatesController < ApplicationController
layout 'base'
helper :issues
helper :issue_templates
menu_item :issues
before_action :find_object, only: %i[show update destroy]
before_action :find_project, only: %i[update]
before_action :require_admin, only: %i[index new show], excep: [:preview]
#
# Action for global template : Admin right is required.
#
def index
trackers = Tracker.all
template_map = {}
trackers.each do |tracker|
tracker_id = tracker.id
templates = GlobalNoteTemplate.search_by_tracker(tracker_id).sorted
template_map[Tracker.find(tracker_id)] = templates if templates.any?
end
render layout: !request.xhr?, locals: { template_map: template_map, trackers: trackers }
end
def new
# create empty instance
@global_note_template = GlobalNoteTemplate.new
render render_form_params
end
def create
@global_note_template = GlobalNoteTemplate.new(template_params)
@global_note_template.author = User.current
save_and_flash(:notice_successful_create, :new) && return
end
def show
render render_form_params
end
def update
# Workaround in case author id is null
@global_note_template.author = User.current if @global_note_template.author.blank?
@global_note_template.safe_attributes = template_params
save_and_flash(:notice_successful_update, :show)
end
def destroy
unless @global_note_template.destroy
flash[:error] = l(:enabled_template_cannot_destroy)
redirect_to action: :show, id: @global_note_template
return
end
flash[:notice] = l(:notice_successful_delete)
redirect_to action: 'index'
end
def find_project
@projects = Project.all
end
def find_object
@global_note_template = GlobalNoteTemplate.find(params[:id])
rescue ActiveRecord::RecordNotFound
render_404
end
def save_and_flash(message, action_on_failure)
unless @global_note_template.save
render render_form_params.merge(action: action_on_failure)
return
end
respond_to do |format|
format.html do
flash[:notice] = l(message)
redirect_to action: 'show', id: @global_note_template.id
end
format.js { head 200 }
end
end
def template_params
params.require(:global_note_template)
.permit(:global_note_template_id, :tracker_id, :name, :memo, :description,
:enabled, :author_id, :position, :visibility, role_ids: [], project_ids: [])
end
def render_form_params
trackers = Tracker.all
projects = Project.all
{ layout: !request.xhr?,
locals: { trackers: trackers, apply_all_projects: apply_all_projects?,
note_template: @global_note_template, projects: projects } }
end
def apply_all_projects?
plugin_setting['apply_global_template_to_all_projects'].to_s == 'true'
end
def plugin_setting
Setting.plugin_redmine_issue_templates
end
end
================================================
FILE: app/controllers/issue_templates_controller.rb
================================================
# frozen_string_literal: true
# noinspection ALL
class IssueTemplatesController < ApplicationController
layout 'base'
helper :issues
include Concerns::IssueTemplatesCommon
include Concerns::ProjectTemplatesCommon
menu_item :issues
before_action :find_tracker, :find_templates, only: %i[set_pulldown list_templates]
def index
project_id = @project.id
project_templates = IssueTemplate.search_by_project(project_id)
# pick up used tracker ids
tracker_ids = @project.trackers.pluck(:id)
@template_map = {}
tracker_ids.each do |tracker_id|
templates = project_templates.search_by_tracker(tracker_id).sorted
@template_map[Tracker.find(tracker_id)] = templates if templates.any?
end
setting = IssueTemplateSetting.find_or_create(project_id)
@inherit_templates = setting.get_inherit_templates
@global_issue_templates = global_templates(tracker_ids)
respond_to do |format|
format.html do
render layout: !request.xhr?,
locals: { apply_all_projects: apply_all_projects?, tracker_ids: tracker_ids }
end
format.api do
render formats: :json, locals: { project_templates: project_templates }
end
end
end
def new
if params[:copy_from].present?
@issue_template = IssueTemplate.find(params[:copy_from]).dup
@issue_template.title = @issue_template.copy_title
else
# create empty instance
@issue_template ||= IssueTemplate.new(author: @user, project: @project)
end
render render_form_params
end
def create
@issue_template = IssueTemplate.new
@issue_template.author = User.current
@issue_template.project = @project
begin
@issue_template.safe_attributes = valid_params
rescue ActiveRecord::SerializationTypeMismatch, Concerns::IssueTemplatesCommon::InvalidTemplateFormatError
flash[:error] = I18n.t(:builtin_fields_should_be_valid_json, default: 'Please enter a valid JSON fotmat string.')
render render_form_params.merge(action: :new)
return
end
# TODO: Should return validation error in case mandatory fields are blank.
save_and_flash(:notice_successful_create, :new) && return
end
def update
begin
@issue_template.safe_attributes = valid_params
rescue ActiveRecord::SerializationTypeMismatch, Concerns::IssueTemplatesCommon::InvalidTemplateFormatError
flash[:error] = I18n.t(:builtin_fields_should_be_valid_json, default: 'Please enter a valid JSON fotmat string.')
render render_form_params.merge(action: :show)
return
end
save_and_flash(:notice_successful_update, :show)
end
# load template description
def load
issue_template_id = params[:template_id]
template_type = params[:template_type]
issue_template = if template_type.present? && template_type == 'global'
GlobalIssueTemplate.find(issue_template_id)
else
IssueTemplate.find(issue_template_id)
end
rendered_json = builtin_fields_enabled? ? issue_template.template_json : issue_template.template_json(except: 'builtin_fields_json')
render plain: rendered_json
end
# update pulldown
def set_pulldown
@group = []
@default_template = nil
add_templates_to_group(@issue_templates)
add_templates_to_group(@inherit_templates, class: 'inherited')
add_templates_to_group(@global_templates, class: 'global')
if loadable_trigger?
@group[@default_template].selected = 'selected'
end
render action: '_template_pulldown', layout: false,
locals: { is_triggered_by: request.parameters[:is_triggered_by], grouped_options: @group,
should_replaced: setting.should_replaced, default_template: @default_template }
end
#
# List templates associated with tracker and project.
# TODO: refactor here. Duplicate with set_pulldown....
#
def list_templates
(default_global, default_inherit, default_project) = default_templates
default_template = default_inherit.presence || default_global
default_template = default_project.presence || default_template
respond_to do |format|
format.html do
render action: '_list_templates',
layout: false,
locals: { default_template: default_template,
issue_templates: @issue_templates,
inherit_templates: @inherit_templates,
global_issue_templates: @global_templates }
end
format.api do
render action: '_list_templates',
locals: { default_template: default_template,
issue_templates: @issue_templates,
inherit_templates: @inherit_templates,
global_issue_templates: @global_templates }
end
end
end
def menu_items
{ issue_templates: { default: :issue_templates, actions: {} } }
end
# preview
def preview
issue_template = params[:issue_template]
@text = (issue_template ? issue_template[:description] : nil)
render partial: 'common/preview'
end
private
def orphaned
IssueTemplate.orphaned(@project.id)
end
def find_object
@issue_template = IssueTemplate.find(params[:id])
@project = @issue_template.project
rescue ActiveRecord::RecordNotFound
render_404
end
def find_templates
@issue_templates = issue_templates
@inherit_templates = inherit_templates
@global_templates = global_templates(@tracker.id)
end
def template
@issue_template
end
def setting
IssueTemplateSetting.find_or_create(@project.id)
end
def global_templates(tracker_id)
return [] if apply_all_projects? && templates_exist?
project_id = apply_all_projects? ? nil : @project.id
GlobalIssueTemplate.get_templates_for_project_tracker(project_id, tracker_id)
end
def default_templates
[@global_templates, @inherit_templates, @issue_templates].map do |templates|
templates.try(:is_default).try(:first)
end
end
def default_template_index
@default_template.blank? ? @group.length - 1 : @default_template
end
def add_templates_to_group(templates, option = {})
templates.each do |template|
@group << template.template_struct(option)
next unless template.is_default == true
@default_template = default_template_index
end
end
def issue_templates
if params[:issue_project_id]
@project = Project.find(params[:issue_project_id])
end
IssueTemplate.get_templates_for_project_tracker(@project.id, @tracker.id)
end
def inherit_templates
setting.get_inherit_templates(@tracker)
end
def template_params
params.require(:issue_template).permit(:tracker_id, :title, :note, :issue_title, :description, :is_default,
:enabled, :author_id, :position, :enabled_sharing,
:related_link, :link_title, :builtin_fields)
end
def templates_exist?
@inherit_templates.present? || @issue_templates.present?
end
def render_form_params
child_project_used_count = template&.used_projects&.count
custom_fields = core_fields_map_by_tracker_id(tracker_id: template&.tracker_id, project_id: @project.id)
.merge(custom_fields_map_by_tracker_id(template&.tracker_id)).to_json
{ layout: !request.xhr?,
locals: { issue_template: template, project: @project, child_project_used_count: child_project_used_count,
custom_fields: custom_fields.to_s, builtin_fields_enable: builtin_fields_enabled? } }
end
def loadable_trigger?
is_triggered_by = request.parameters[:is_triggered_by]
is_update_issue = request.parameters[:is_update_issue]
return false if is_triggered_by.present? && is_triggered_by != 'is_update_issue'
return @default_template.present? && (is_update_issue.blank? || is_update_issue != 'true')
end
end
================================================
FILE: app/controllers/issue_templates_settings_controller.rb
================================================
# frozen_string_literal: true
# noinspection RubocopInspection
class IssueTemplatesSettingsController < ApplicationController
before_action :find_project, :find_user
before_action :authorize, :find_issue_templates_setting, except: %i[preview]
def index; end
def edit
return if params[:settings].blank?
update_template_setting
flash[:notice] = l(:notice_successful_update)
redirect_to action: 'index', project_id: @project
end
def preview
@text = params[:settings][:help_message]
render partial: 'common/preview'
end
def menu_items
{ issue_templates_settings: { default: :issue_templates, actions: {} } }
end
private
def find_user
@user = User.current
end
def find_project
@project = Project.find(params[:project_id])
rescue ActiveRecord::RecordNotFound
render_404
end
def find_issue_templates_setting
@issue_templates_setting = IssueTemplateSetting.find_or_create(@project.id)
end
def update_template_setting
issue_templates_setting = IssueTemplateSetting.find_or_create(@project.id)
attribute = params[:settings]
issue_templates_setting.update(enabled: attribute[:enabled],
help_message: attribute[:help_message],
inherit_templates: attribute[:inherit_templates],
should_replaced: attribute[:should_replaced])
end
end
================================================
FILE: app/controllers/note_templates_controller.rb
================================================
# frozen_string_literal: true
class NoteTemplatesController < ApplicationController
include Concerns::ProjectTemplatesCommon
layout 'base'
helper :issue_templates
menu_item :issues
def index
project_id = @project.id
note_templates = NoteTemplate.search_by_project(project_id).sorted
# pick up used tracker ids
tracker_ids = @project.trackers.pluck(:id)
@template_map = {}
tracker_ids.each do |tracker_id|
templates = note_templates.search_by_tracker(tracker_id)
@template_map[Tracker.find(tracker_id)] = templates if templates.any?
end
@global_note_templates = global_templates(tracker_ids)
respond_to do |format|
format.html do
render layout: !request.xhr?,
locals: { apply_all_projects: apply_all_projects?, tracker_ids: tracker_ids }
end
format.api do
render formats: :json, locals: { note_templates: note_templates }
end
end
end
def new
@note_template ||= NoteTemplate.new(author: @user, project: @project)
render render_form_params
end
def create
@note_template = NoteTemplate.new(template_params)
@note_template.author = User.current
@note_template.project = @project
save_and_flash(:notice_successful_create, :new) && return
end
def update
# Workaround in case author id is null
@note_template.author = User.current if @note_template.author.blank?
@note_template.safe_attributes = template_params
@note_template.role_ids = template_params[:role_ids]
save_and_flash(:notice_successful_update, :show)
end
# load template description
def load
note_template_id = template_params[:note_template_id]
template_type = template_params[:template_type]
if template_type.present? && template_type == 'global'
project_id = template_params[:project_id]
note_template = GlobalNoteTemplate.find(note_template_id)
# prevent to load if the template visibility does not match.
raise ActiveRecord::RecordNotFound unless note_template.loadable?(user_id: User.current.id, project_id: project_id)
else
note_template = NoteTemplate.find(note_template_id)
# prevent to load if the template visibility does not match.
raise ActiveRecord::RecordNotFound unless note_template.loadable?(user_id: User.current.id)
end
render plain: note_template.template_json
rescue ActiveRecord::RecordNotFound
render_404
end
def list_templates
tracker_id = params[:tracker_id]
project_id = params[:project_id]
note_templates = NoteTemplate.visible_note_templates_condition(
user_id: User.current.id, project_id: project_id, tracker_id: tracker_id
)
global_note_templates = GlobalNoteTemplate.visible_note_templates_condition(
user_id: User.current.id, project_id: project_id, tracker_id: tracker_id
)
respond_to do |format|
format.html do
render action: '_list_note_templates',
layout: false,
locals: { note_templates: note_templates, global_note_templates: global_note_templates }
end
end
end
def destroy
unless @note_template.destroy
flash[:error] = l(:enabled_template_cannot_destroy)
redirect_to action: :show, project_id: @project, id: @note_template
return
end
flash[:notice] = l(:notice_successful_delete)
redirect_to action: 'index', project_id: @project
end
def menu_items
{ note_templates: { default: :issue_templates, actions: {} } }
end
private
def find_object
@note_template = NoteTemplate.find(params[:id])
@project = @note_template.project
rescue ActiveRecord::RecordNotFound
render_404
end
def template_params
params.require(:note_template)
.permit(:note_template_id, :project_id, :template_type, :tracker_id, :name, :memo, :description,
:enabled, :author_id, :position, :visibility, role_ids: [])
end
def template
@note_template
end
def render_form_params
{ layout: !request.xhr?,
locals: { note_template: template, project: @project } }
end
def templates_exist?
@note_templates.present?
end
def global_templates(tracker_id)
return [] if apply_all_projects? && templates_exist?
project_id = apply_all_projects? ? nil : @project.id
GlobalNoteTemplate.get_templates_for_project_tracker(project_id, tracker_id)
end
end
================================================
FILE: app/helpers/issue_templates_helper.rb
================================================
module IssueTemplatesHelper
def project_tracker?(tracker, project)
return false unless tracker.present?
project.trackers.exists?(tracker.id)
end
def non_project_tracker_msg(flag)
return '' if flag
"<font class=\"non_project_tracker\">#{l(:unused_tracker_at_this_project)}</font>".html_safe
end
def template_target_trackers(project, issue_template)
trackers = project.trackers
trackers |= [issue_template.tracker] unless issue_template.tracker.blank?
trackers.collect { |obj| [obj.name, obj.id] }
end
def options_for_template_pulldown(options)
options.map do |option|
text = option.try(:name).to_s
tag_builder.content_tag_string(:option, text, option, true)
end.join("\n").html_safe
end
end
================================================
FILE: app/models/concerns/issue_template/common.rb
================================================
# frozen_string_literal: true
module Concerns
module IssueTemplate
module Common
extend ActiveSupport::Concern
#
# Common scope both global and project scope template.
#
included do
belongs_to :author, class_name: 'User', foreign_key: 'author_id'
belongs_to :tracker
before_save :check_default
before_destroy :confirm_disabled
validates :title, presence: true
validates :tracker, presence: true
validates :related_link, format: { with: URI::DEFAULT_PARSER.make_regexp }, allow_blank: true
scope :enabled, -> { where(enabled: true) }
scope :sorted, -> { order(:position) }
scope :search_by_tracker, lambda { |tracker_id|
where(tracker_id: tracker_id) if tracker_id.present?
}
scope :is_default, -> { where(is_default: true) }
scope :not_default, -> { where(is_default: false) }
scope :orphaned, lambda { |project_id = nil|
condition = all
if project_id.present? && try(:name) == 'IssueTemplate'
condition = condition.where(project_id: project_id)
ids = Tracker.joins(:projects).where(projects: { id: project_id }).pluck(:id)
else
ids = Tracker.pluck(:id)
end
condition.where.not(tracker_id: ids)
}
after_destroy do |template|
logger.info("[Destroy] #{self.class}: #{template.inspect}")
end
# ActiveRecord::SerializationTypeMismatch may be thrown if non hash object is assigned.
serialize :builtin_fields_json, Hash
end
#
# Common methods both global and project scope template.
#
def enabled?
enabled
end
def <=>(other)
position <=> other.position
end
# Keep this method for a while, but this will be deprecated.
# Please see: https://github.com/akiko-pusu/redmine_issue_templates/issues/363
def checklist
return [] if checklist_json.blank?
begin
JSON.parse(checklist_json)
rescue StandardError
[]
end
end
def template_json(except: nil)
template = {}
template[self.class::Config::JSON_OBJECT_NAME] = generate_json
return template.to_json(root: true) if except.blank?
template.to_json(root: true, except: [except])
end
def builtin_fields
builtin_fields_json.to_json
end
def generate_json
result = attributes
result[:link_title] = link_title.presence || I18n.t(:issue_template_related_link, default: 'Related Link')
result[:checklist] = checklist
result.except('checklist_json')
end
def template_struct(option = {})
Struct.new(:value, :name, :class, :selected).new(id, title, option[:class])
end
def log_destroy_action(template)
logger.info "[Destroy] #{self.class}: #{template.inspect}" if logger&.info
end
def confirm_disabled
return unless enabled?
errors.add :base, 'enabled_template_cannot_destroy'
throw :abort
end
def copy_title
"copy_of_#{title}"
end
end
end
end
================================================
FILE: app/models/global_issue_template.rb
================================================
# frozen_string_literal: true
class GlobalIssueTemplate < ActiveRecord::Base
include Redmine::SafeAttributes
include Concerns::IssueTemplate::Common
validates :title, uniqueness: { scope: :tracker_id }
has_and_belongs_to_many :projects
acts_as_positioned scope: [:tracker_id]
safe_attributes 'title',
'description',
'tracker_id',
'note',
'enabled',
'is_default',
'issue_title',
'project_ids',
'position',
'author_id',
'related_link',
'link_title',
'builtin_fields_json'
# for intermediate table assosciations
scope :search_by_project, lambda { |project_id|
joins(:projects).where(projects: { id: project_id }) if project_id.present?
}
module Config
JSON_OBJECT_NAME = 'global_issue_template'
end
Config.freeze
#
# In case set is_default and updated, others are also updated.
#
def check_default
return unless is_default? && is_default_changed?
self.class.search_by_tracker(tracker_id).update_all(is_default: false)
end
#
# Class method
#
class << self
def get_templates_for_project_tracker(project_id, tracker_id = nil)
GlobalIssueTemplate.search_by_tracker(tracker_id)
.search_by_project(project_id)
.enabled
.sorted
end
end
end
================================================
FILE: app/models/global_note_template.rb
================================================
# frozen_string_literal: true
class GlobalNoteTemplate < ActiveRecord::Base
include Redmine::SafeAttributes
include ActiveModel::Validations
# author and project should be stable.
safe_attributes 'name',
'description',
'enabled',
'memo',
'tracker_id',
'position',
'visibility',
'role_ids',
'project_ids'
validates :role_ids, presence: true, if: :roles?
belongs_to :author, class_name: 'User', inverse_of: false, foreign_key: 'author_id'
belongs_to :tracker
has_many :global_note_template_projects, dependent: :nullify
has_many :projects, through: :global_note_template_projects
has_many :global_note_visible_roles, dependent: :nullify
has_many :roles, through: :global_note_visible_roles
validates :name, presence: true
acts_as_positioned scope: %i[tracker_id]
enum visibility: { roles: 1, open: 2 }
scope :mine_condition, lambda { |user_id|
where(author_id: user_id).mine if user_id.present?
}
scope :roles_condition, lambda { |role_ids|
joins(:global_note_visible_roles).where(global_note_visible_roles: { role_id: role_ids })
}
scope :enabled, -> { where(enabled: true) }
scope :sorted, -> { order(:position) }
scope :search_by_tracker, lambda { |tracker_id|
where(tracker_id: tracker_id) if tracker_id.present?
}
# for intermediate table assosciations
scope :search_by_project, lambda { |project_id|
joins(:projects).where(projects: { id: project_id }) if project_id.present?
}
before_save :check_visible_roles
after_save :note_visible_roles!
before_destroy :confirm_disabled
def <=>(other)
position <=> other.position
end
def template_json
template = {}
template['note_template'] = generate_json
template.to_json(root: true)
end
def generate_json
attributes
end
def note_visible_roles!
return unless roles?
if role_ids.blank?
raise NoteTemplateError, l(:please_select_at_least_one_role,
default: 'Please select at least one role.')
end
ActiveRecord::Base.transaction do
GlobalNoteVisibleRole.where(global_note_template_id: id).delete_all if global_note_visible_roles.present?
role_ids.each do |role_id|
GlobalNoteVisibleRole.create!(global_note_template_id: id, role_id: role_id)
end
end
end
def loadable?(user_id:, project_id:)
return true if open?
project = Project.find(project_id)
user_project_roles = User.find(user_id).roles_for_project(project).pluck(:id)
match_roles = user_project_roles & roles.ids
return true if roles? && match_roles.present?
false
end
private
def check_visible_roles
return if roles? || global_note_visible_roles.empty?
# Remove roles in case template visible scope is not "roles".
# This remove action is included the same transaction scope.
GlobalNoteVisibleRole.where(global_note_template_id: id).delete_all
end
def confirm_disabled
return unless enabled?
errors.add :base, 'enabled_template_cannot_destroy'
throw :abort
end
#
# Class method
#
class << self
def visible_note_templates_condition(user_id:, project_id:, tracker_id:)
user = User.find(user_id)
project = Project.find(project_id)
user_project_roles = user.roles_for_project(project).pluck(:id)
base_condition = GlobalNoteTemplate.search_by_tracker(tracker_id)
base_condition = base_condition.search_by_project(project_id) unless apply_all_projects?
open_ids = base_condition.open.pluck(:id)
role_ids = base_condition.roles_condition(user_project_roles).pluck(:id)
# return uniq ids
ids = open_ids | role_ids
GlobalNoteTemplate.where(id: ids).includes(:global_note_visible_roles)
end
def get_templates_for_project_tracker(project_id, tracker_id = nil)
GlobalNoteTemplate.search_by_tracker(tracker_id)
.search_by_project(project_id)
.enabled
.sorted
end
def plugin_setting
Setting.plugin_redmine_issue_templates
end
def apply_all_projects?
plugin_setting['apply_global_template_to_all_projects'].to_s == 'true'
end
end
end
================================================
FILE: app/models/global_note_template_project.rb
================================================
# frozen_string_literal: true
class GlobalNoteTemplateProject < ActiveRecord::Base
belongs_to :project
belongs_to :global_note_template, optional: true
end
================================================
FILE: app/models/global_note_visible_role.rb
================================================
# frozen_string_literal: true
class GlobalNoteVisibleRole < ActiveRecord::Base
include Redmine::SafeAttributes
safe_attributes 'global_note_template_id', 'role_id'
belongs_to :role
belongs_to :global_note_template, optional: true
validates :role_id, presence: true
validates :global_note_template_id, presence: true
scope :search_by_note_template, lambda { |note_template_id|
where(global_note_template_id: note_template_id)
}
end
================================================
FILE: app/models/issue_template.rb
================================================
# frozen_string_literal: true
class IssueTemplate < ActiveRecord::Base
include Redmine::SafeAttributes
include Concerns::IssueTemplate::Common
belongs_to :project
validates :project_id, presence: true
validates :title, uniqueness: { scope: :project_id }
acts_as_positioned scope: %i[project_id tracker_id]
# author and project should be stable.
safe_attributes 'title',
'description',
'tracker_id',
'note',
'enabled',
'issue_title',
'is_default',
'enabled_sharing',
'visible_children',
'position',
'related_link',
'link_title',
'builtin_fields_json'
scope :enabled_sharing, -> { where(enabled_sharing: true) }
scope :search_by_project, lambda { |prolect_id|
where(project_id: prolect_id)
}
module Config
JSON_OBJECT_NAME = 'issue_template'
end
Config.freeze
#
# In case set is_default and updated, others are also updated.
#
def check_default
return unless is_default? && is_default_changed?
self.class.search_by_project(project_id).search_by_tracker(tracker_id).update_all(is_default: false)
end
# return projects that use this template
def used_projects
return [] unless enabled_sharing
projects = project.descendants
.joins(:trackers, :enabled_modules).merge(Tracker.where(id: tracker_id)).merge(EnabledModule.where(name: 'issue_templates'))
IssueTemplateSetting.where(project_id: projects).inherit_templates.select(:project_id)
end
#
# Class method
#
class << self
def get_inherit_templates(project_ids, tracker_id)
# keep ordering of project tree
IssueTemplate.search_by_project(project_ids)
.search_by_tracker(tracker_id)
.enabled
.enabled_sharing
.sorted
end
def get_templates_for_project_tracker(project_id, tracker_id = nil)
IssueTemplate.search_by_project(project_id)
.search_by_tracker(tracker_id)
.enabled
.sorted
end
end
end
================================================
FILE: app/models/issue_template_setting.rb
================================================
class IssueTemplateSetting < ActiveRecord::Base
include Redmine::SafeAttributes
belongs_to :project
validates_uniqueness_of :project_id
validates_presence_of :project_id
safe_attributes 'help_message', 'enabled', 'inherit_templates', 'should_replaced'
scope :inherit_templates, -> { where(inherit_templates: true) }
def self.find_or_create(project_id)
setting = IssueTemplateSetting.where(project_id: project_id).first
unless setting.present?
setting = IssueTemplateSetting.new
setting.project_id = project_id
setting.save!
end
setting
end
#
# Class method
#
class << self
def apply_template_to_child_projects(project_id)
setting = find_setting(project_id)
setting.apply_template_to_child_projects
end
def unapply_template_from_child_projects(project_id)
setting = find_setting(project_id)
setting.unapply_template_from_child_projects
end
private
def find_setting(project_id)
raise ArgumentError, 'Please specify valid project_id.' if project_id.blank?
setting = IssueTemplateSetting.where(project_id: project_id).first
raise ActiveRecord::RecordNotFound if setting.blank?
setting
end
end
def enable_help?
enabled == true && !help_message.blank?
end
def enabled_inherit_templates?
inherit_templates
end
def child_projects
project.descendants
end
def apply_template_to_child_projects
update_inherit_template_of_child_projects(true)
end
def unapply_template_from_child_projects
update_inherit_template_of_child_projects(false)
end
def get_inherit_templates(tracker = nil)
return [] unless enabled_inherit_templates?
project_ids = project.ancestors.collect(&:id)
tracker = project.trackers.pluck(:tracker_id) if tracker.blank?
# first: get inherit_templates
IssueTemplate.get_inherit_templates(project_ids, tracker)
end
private
def update_inherit_template_of_child_projects(value)
IssueTemplateSetting.where(project_id: child_projects).update_all(inherit_templates: value)
end
end
================================================
FILE: app/models/note_template.rb
================================================
# frozen_string_literal: true
class NoteTemplate < ActiveRecord::Base
include Redmine::SafeAttributes
include ActiveModel::Validations
class NoteTemplateError < StandardError; end
# author and project should be stable.
safe_attributes 'name', 'description', 'enabled', 'memo', 'tracker_id',
'project_id', 'position', 'visibility'
attr_accessor :role_ids
validates :role_ids, presence: true, if: :roles?
belongs_to :project
belongs_to :author, class_name: 'User', foreign_key: 'author_id'
belongs_to :tracker
has_many :note_visible_roles, dependent: :nullify
has_many :roles, through: :note_visible_roles
validates :project_id, presence: true
validates :name, uniqueness: { scope: :project_id }
validates :name, presence: true
acts_as_positioned scope: %i[project_id tracker_id]
enum visibility: { mine: 0, roles: 1, open: 2 }
scope :mine_condition, lambda { |user_id|
where(author_id: user_id).mine if user_id.present?
}
scope :roles_condition, lambda { |role_ids|
joins(:note_visible_roles).where(note_visible_roles: { role_id: role_ids })
}
scope :enabled, -> { where(enabled: true) }
scope :sorted, -> { order(:position) }
scope :search_by_tracker, lambda { |tracker_id|
where(tracker_id: tracker_id) if tracker_id.present?
}
scope :search_by_project, lambda { |prolect_id|
where(project_id: prolect_id) if prolect_id.present?
}
before_save :check_visible_roles
after_save :note_visible_roles!
before_destroy :confirm_disabled
def <=>(other)
position <=> other.position
end
def template_json
template = {}
template['note_template'] = generate_json
template.to_json(root: true)
end
def generate_json
attributes
end
def note_visible_roles!
return unless roles?
if role_ids.blank?
raise NoteTemplateError, l(:please_select_at_least_one_role,
default: 'Please select at least one role.')
end
ActiveRecord::Base.transaction do
NoteVisibleRole.where(note_template_id: id).delete_all if note_visible_roles.present?
role_ids.each do |role_id|
NoteVisibleRole.create!(note_template_id: id, role_id: role_id)
end
end
end
def loadable?(user_id:)
return true if open?
return true if mine? && user_id == author_id
user_project_roles = User.find(user_id).roles_for_project(project).pluck(:id)
match_roles = user_project_roles & roles.ids
return true if roles? && !match_roles.empty?
false
end
private
def check_visible_roles
return if roles? || note_visible_roles.empty?
# Remove roles in case template visible scope is not "roles".
# This remove action is included the same transaction scope.
NoteVisibleRole.where(note_template_id: id).delete_all
end
def confirm_disabled
return unless enabled?
errors.add :base, 'enabled_template_cannot_destroy'
throw :abort
end
#
# Class method
#
class << self
def visible_note_templates_condition(user_id:, project_id:, tracker_id:)
user = User.find(user_id)
project = Project.find(project_id)
user_project_roles = user.roles_for_project(project).pluck(:id)
base_condition = NoteTemplate.search_by_project(project_id).search_by_tracker(tracker_id)
open_ids = base_condition.open.pluck(:id)
mine_ids = base_condition.mine_condition(user_id).pluck(:id)
role_ids = base_condition.roles_condition(user_project_roles).pluck(:id)
# return uniq ids
ids = open_ids | mine_ids | role_ids
NoteTemplate.where(id: ids).includes(:note_visible_roles)
end
end
end
================================================
FILE: app/models/note_visible_role.rb
================================================
# frozen_string_literal: true
class NoteVisibleRole < ActiveRecord::Base
include Redmine::SafeAttributes
safe_attributes 'note_template_id', 'role_id'
belongs_to :role
belongs_to :note_template, optional: true
validates :role_id, presence: true
validates :note_template_id, presence: true
scope :search_by_note_template, lambda { |note_template_id|
where(note_template_id: note_template_id)
}
end
================================================
FILE: app/views/common/_nodata.html.erb
================================================
<% if trackers.blank? %>
<div class='nodata'>
<%= simple_format(l(:text_no_tracker_enabled)) %>
</div>
<% end %>
================================================
FILE: app/views/common/_orphaned.html.erb
================================================
<h3 class='template_tracker'><%= l(:orphaned_template) %></h3>
<table class='list issues template_list'>
<thead>
<tr>
<th>#</th>
<th class='hideable'><%= l(:issue_template_name) %></th>
<th><%= l(:label_preview) %></th>
<th class='hideable'><%= l(:field_tracker) %></th>
<th><%= l(:field_author) %></th>
<th class='hideable'><%= l(:field_updated_on) %></th>
</tr>
</thead>
<tbody>
<% orphaned_templates.each do |issue_template| %>
<tr class='<%= cycle('odd', 'even') %> issue_template issue'>
<td>
<%= link_to h(issue_template.id),
{ controller: controller.controller_name, action: 'show',
id: issue_template.id,
}.merge(issue_template.try(:project_id) ? { project_id: issue_template.project } : {}),
{ title: issue_template.note } %>
</td>
<td class='hideable template_title'>
<%= link_to h(issue_template.title),
{ controller: controller.controller_name,
id: issue_template.id, action: 'show' },
{ title: "#{html_escape(issue_template.note) }"} %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%= issue_template.title %></span>
<%= textilizable(issue_template.description) %>
</div>
</div>
</td>
<td class='hideable'><%= "ID: #{issue_template.tracker_id}" %></td>
<td><%=h issue_template.author %></td>
<td class='hideable'><%= format_time(issue_template.updated_on) %> </td>
</tr>
<tr class='<%= current_cycle %>' style='display: none;' id='template_description-<%= issue_template.id %>'>
<td class='description' colspan='8'>
<div class='wiki'><%= textilizable(issue_template.description) %></div></td>
</tr>
<% end %>
</tbody>
</table>
================================================
FILE: app/views/common/_template_links.html.erb
================================================
<div style='display: flex; float: right; padding-top: 40px;
position: relative; bottom: 6px; right: 0;'>
<div class='template_link_area'>
<label><%= l(:issue_template) %>: </label>
<%= link_to(l(:label_list_templates),
{ controller: 'issue_templates',
action: 'index',
project_id: @project}, class: 'icon icon-template') %> |
<%= link_to_if_authorized(l(:label_new_templates),
{ controller: 'issue_templates', action: 'new', project_id: @project },
class: 'icon icon-add') %>
</div>
<div class='template_link_area'>
<label><%= l(:note_template) %>: </label>
<%= link_to(l(:label_list_templates),
{ controller: 'note_templates',
action: 'index',
project_id: @project}, class: 'icon icon-template') %> |
<%= link_to_if_authorized(l(:label_new_templates),
{ controller: 'note_templates', action: 'new', project_id: @project },
class: 'icon icon-add') %>
</div>
<div class='template_link_area'>
<label><%= l(:issue_templates_optional_settings, default: 'Templates Optional Settings') %>: </label>
<%= link_to_if_authorized(l(:label_settings, default: 'Settings'),
{ controller: 'issue_templates_settings', action: 'index', project_id: @project },
class: 'icon icon-settings') %>
</div>
</div>
================================================
FILE: app/views/global_issue_templates/_form.html.erb
================================================
<%= error_messages_for 'global_issue_template' %>
<div class='box tabular box-white'>
<p><%= f.text_field :title, required: true, size: 80, label: l(:issue_template_name) %></p>
<fieldset class='issue'>
<legend class='issue'><%= l(:label_applied_for_issue) %></legend>
<p>
<% if issue_template.tracker.blank? %>
<%= f.select :tracker_id, trackers.collect { |t| [t.name, t.id] }, { required: true },
required: true, label: l(:label_tracker) %>
<%= h issue_template.tracker.present? ? issue_template.tracker.name :
l(:orphaned_template, default: 'Orphaned template from tracker') %>
<% else %>
<%= f.select :tracker_id, trackers.collect { |t| [t.name, t.id] }, { required: true },
required: true, label: l(:label_tracker), selected: issue_template.tracker.id %>
<% end %>
</p>
<p><%= f.text_field :issue_title, required: false, size: 80, label: l(:issue_title) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='issue_title_help_area'
data-tooltip-content='issue_title_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='issue_title_help_area'></span>
</a>
</p>
<p>
<%= f.text_area :description, cols: 78, rows: 12,
required: true,
label: l(:issue_description), class: 'wiki-edit', style: 'overflow: auto;' %>
</p>
<!-- for Builtin Fields -->
<!-- buildin field Generator -->
<% if builtin_fields_enable %>
<div id="json_generator">
<p>
<label><%= l(:label_select_field, default: 'Select a field') %></label>
<select v-model='newItemTitle'>
<option v-for='(value, key) in customFields' v-bind:value='key'>
{{ value.name }}
</option>
</select>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='builtin_fields_help_area'
data-tooltip-content='builtin_fields_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='builtin_fields_help_area'></span>
</a>
</p>
<p>
<label><%= l(:field_value) %></label>
<textarea id='issue_template_json_setting_field' v-if='fieldFormat() == "text"' rows=6
placeholder='<%= l(:enter_value, default: 'Please enter a value') %>' v-model='newItemValue'>
</textarea>
<input id='issue_template_json_setting_field' v-if='fieldFormat() == "string"'
type='text'
placeholder='<%= l(:enter_value, default: 'Please enter a value') %>' v-model='newItemValue'>
<input id='issue_template_json_setting_field' v-if='fieldFormat() == "int"'
:max='customFields[newItemTitle].max_length' :min='customFields[newItemTitle].min_length'
type="number" placeholder='<%= l(:enter_value, default: 'Please enter a value') %>' v-model='newItemValue'>
<input type='date' id='issue_template_json_setting_field' v-if='fieldFormat() == "date"' v-model='newItemValue'>
<select v-model='newItemValue' v-if='fieldFormat() == "ratio"'>
<option v-for="ratio in [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]">{{ ratio }} %</option>
</select>
<select v-model='newItemValue' :multiple='customFields[newItemTitle].multiple == true'
v-if='fieldFormat() == "list" || fieldFormat() == "bool"'>
<option v-for="value in possibleValues()">{{ value }}</option>
</select>
<span style='margin-left: 4px;' class='icon icon-add' v-on:click='addField(newItemTitle, newItemValue)'>
<%= l(:button_add) %>
</span>
</p>
<div id='field_information' class='wiki' v-if='newItemTitle != ""'>
<b><%= l(:label_field_information, default: 'Field information') %></b>
<a v-if='customFieldUrl' v-bind:href="customFieldUrl" target="_blank" rel="noopener" class="icon icon-custom-fields">
<%= l(:label_custom_field, default: 'Custom field') %>: {{ customFields[newItemTitle].name }}
</a>
<pre>{{ customFields[newItemTitle] }}</pre>
</div>
<div id='fields_setting_display_area'>
<ul class='json-list' v-if='items.length > 0'>
<li v-for='item in items'>
<span v-if='customFields[item.title]'>
<b>{{ customFields[item.title].name }}</b>: {{ item.value }} / {{ item.title }}
</span>
<span v-if='!customFields[item.title]'>
<i class='issue_template help_content'>
<%= l(:unavailable_fields_for_this_tracker, default: 'Unavailable field for this tarcker') %>
: {{ item.value }} / {{ item.title }}
</i>
</span>
<i class='icon icon-del' v-on:click='deleteField(item)'></i>
</li>
</ul>
<pre id='builtin_fields_data_via_vue' style='display: none;'>{{ items }}</pre>
<span class='icon icon-reload' id='reset-json' v-on:click='loadField()'><%= l(:button_reset) %></span>
<span class='icon icon-checked' id='paste-json'><%= l(:button_apply) %></span>
</div>
<!-- buildin field Generator -->
<p style='opacity: 0.6;'>
<%= f.text_area :builtin_fields,
required: false, cols: 60, rows: 4,
label: l(:label_builtin_fields_json, default: 'JSON for fields') %>
</p>
<div id='builtin_fields_help_content' class='wiki' style='display: none;'>
<%= l(:label_builtin_fields_help_message, default: 'Enter builtin filds or custom fields default values with JSON format. ') %>
</div>
</div>
<% end %>
<!-- for Builtin Fields -->
</fieldset>
<p>
<%= f.text_area :note, cols: 70, rows: 3,
required: false,
label: l(:issue_template_note), style: 'overflow:auto;' %>
</p>
<p><%= f.text_field :related_link, type: 'url',
size: 70, label: l(:issue_template_related_link, default: 'Related link') %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='related_link_help_content'
data-tooltip-area='related_link_help_area'
data-tooltip-content='related_link_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='related_link_help_area'></span>
</a>
</p>
<p id='link_title_paragraph'><%= f.text_field :link_title, size: 70, label: l(:issue_template_link_title, default: 'Link title') %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='link_title_help_content'
data-tooltip-area='link_title_help_area'
data-tooltip-content='link_title_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='link_title_help_area'></span>
</a>
</p>
<p><%= f.check_box :is_default, label: l(:field_is_default) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='isdefault_help_content'
data-tooltip-area='isdefault_help_area'
data-tooltip-content='isdefault_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='isdefault_help_area'></span>
</a>
</p>
<p><%= f.check_box :enabled, label: l(:label_enabled) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='enabled_help_content'
data-tooltip-area='enabled_help_area'
data-tooltip-content='enabled_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='enabled_help_area'></span>
</a>
</p>
</div>
<%= wikitoolbar_for 'global_issue_template_description' %>
<!-- tooltip content -->
<div id='issue_title_help_content' class='wiki' style='display: none;'>
<%= l(:help_for_issue_title) %>
</div>
<div id='isdefault_help_content' class='wiki' style='display: none;'>
<%= l(:label_isdefault_help_message) %>
</div>
<div id='related_link_help_content' class='wiki' style='display: none;'>
<%= l(:label_related_link_help_message, default: 'If there are some example pages or sample issues which using issue template, please specify the link. So operator can see them as an usage or example for template.') %>
</div>
<div id='link_title_help_content' class='wiki' style='display: none;'>
<%= l(:label_link_title_help_message, default: 'If there are some example pages or sample issues which using issue template, please specify the link. So operator can see them as an usage or example for template.') %>
</div>
<div id='enabled_help_content' class='wiki' style='display: none;'>
<%= l(:label_enabled_help_message) %>
</div>
<!-- tooltip content -->
<div class='box'>
<% if apply_all_projects %>
<p>
<i class='issue_template icon settings'></i>
<span class='issue_template help_content'>
<%= l(:note_apply_global_template_to_all_projects_setting_enabled) %>
</span>
(
<%= link_to(l(:label_settings),
{ controller: 'settings', action: 'plugin', id: 'redmine_issue_templates' },
class: 'issue_template icon plugins') %> )
</p>
<% end %>
<% if projects.any? %>
<fieldset class='box box-white' id='global_issue_template_project_ids'
style='<%= apply_all_projects ? 'opacity: 0.6' : '' %>'>
<a class='collapsible collapsed template-help' data-template-help-target='all_projects'>
<%= l(:project_list_associated_this_template, { applied: issue_template.projects.length, all: projects.length }) %>
</a>
<div id='all_projects' style='display: none;'>
<p><%= check_all_links 'global_issue_template_project_ids' %></p>
<legend><%= l(:label_project_plural) %></legend>
<%= render_project_nested_lists(projects) do |p|
content_tag('label', check_box_tag('global_issue_template[project_ids][]',
p.id, issue_template.projects.to_a.include?(p),
id: nil, disabled: apply_all_projects,
checked: issue_template.projects.to_a.include?(p) ) + ' ' + h(p))
end %>
</div>
</fieldset>
<% end %>
<%= hidden_field_tag 'global_issue_template[project_ids][]', '' %>
</div>
<%= submit_tag l(issue_template.new_record? ? :button_create : :button_save) %>
<%= link_to l(:button_cancel), { action: 'index' }, data: { confirm: l(:text_are_you_sure) } %>
<script>
const baseUrl = "<%= url_for(controller: 'issue_templates', action: 'load_selectable_fields') %>"
const templateId = "<%= issue_template&.id || '' %>"
const templateType = 'global_issue_template'
const trackerPulldownId = templateType + '_tracker_id'
const base_builtin_fields = <%= issue_template.builtin_fields.html_safe %>
const base_custom_fields = <%= custom_fields.html_safe %>
const relativeUrlRoot = "<%= Redmine::Utils.relative_url_root %>"
</script>
<% if builtin_fields_enable %>
<%= javascript_include_tag('vue.min', plugin: 'redmine_issue_templates') %>
<%= javascript_include_tag('template_fields', plugin: 'redmine_issue_templates') %>
<% end %>
================================================
FILE: app/views/global_issue_templates/index.html.erb
================================================
<h2 class='global_issue_template'><%=h "#{l(:global_issue_templates)}" %></h2>
<%= render partial: 'common/nodata', locals: { trackers: trackers } %>
<div class='contextual issue_templates'>
<%= link_to(l(:label_new_templates),
{ controller: 'global_issue_templates', action: 'new' }, class: 'icon icon-add') %>
<%= link_to(l(:global_note_templates, default: 'Global Note Templates'),
{ controller: 'global_note_templates', action: 'index' },
class: 'icon icon-template') %>
<%= link_to(l(:label_settings),
{ controller: 'settings', action: 'plugin', id: 'redmine_issue_templates' },
class: 'issue_template icon plugins') %>
</div>
<div style='clear: both;'></div>
<% if template_map.blank? %>
<div class='template_box'>
<%= l(:no_issue_templates_for_this_redmine) %>
</div>
<% end %>
<% template_map.each_key do |tracker| %>
<div class='template_box'>
<h3 class='template_tracker'><%= tracker.name %></h3>
<table class='list issues template_list ui-sortable table-sortable'>
<thead>
<tr>
<th>#</th>
<th class='hideable'><%= l(:issue_template_name) %></th>
<th><%= l(:label_preview) %></th>
<th class='hideable'><%= l(:field_tracker) %></th>
<th class='hideable'><%= l(:field_author) %></th>
<th class='hideable'><%= l(:field_updated_on) %></th>
<th><%= l(:field_is_default) %></th>
<th><%= l(:label_enabled) %></th>
<th><%=l(:button_sort)%></th>
</tr>
</thead>
<tbody>
<% template_map[tracker].sorted.each do |issue_template| %>
<tr class='<%= cycle('odd', 'even') %> issue_template issue'>
<td><%= link_to h(issue_template.id), { controller: 'global_issue_templates',
id: issue_template.id, action: 'show' },
{ title: issue_template.title } %>
</td>
<td class='hideable template_title'>
<%= link_to h(issue_template.title), { controller: 'global_issue_templates',
id: issue_template.id, action: 'show' },
{ title: "#{html_escape(issue_template.note)}" } %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%= issue_template.title %></span>
<%= textilizable(issue_template.description) %>
<% if issue_template.related_link.present? %>
<hr/>
<%= link_to issue_template.link_title.present? ? issue_template.link_title : l(:issue_template_related_link, default: 'Related link'),
issue_template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
<% end %>
</div>
</div>
</a>
</td>
<td class='hideable'><%=h issue_template.tracker.name %></td>
<td class='hideable'><%=h issue_template.author %></td>
<td class='hideable'><%= format_time(issue_template.updated_on)%> </td>
<td class='center'><%= checked_image issue_template.is_default? %></td>
<td class='center'><%= checked_image issue_template.enabled? %></td>
<td class='buttons'>
<%= reorder_handle(issue_template, :url => url_for({ controller: 'global_issue_templates',
id: issue_template.id, action: 'update' })) %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<%= javascript_tag do %>
// NOTE: Sortable feature depends on Redmine's sorting jQuery plugin.
$(function() { $('table.table-sortable tbody').positionedItems() })
<% end %>
<% end %>
<a id='orphaned_template_link' class='icon template_tooltip orphaned_template_link template-help collapsible collapsed'
title='<%= l(:orphaned_templates) %>'
data-template-help-target='orphaned_templates'
data-url='<%= orphaned_templates_global_issue_templates_path %>'>
<%= l(:orphaned_templates, default: 'Orphaned Templates') %>
</a>
<div id='orphaned_templates' style='display: none'></div>
================================================
FILE: app/views/global_issue_templates/new.html.erb
================================================
<div class='contextual'>
<%= link_to(l(:label_list_templates),
{ controller: 'global_issue_templates', action: 'index' }, class: 'icon icon-template') %>
</div>
<h2 class='global_issue_template'><%=h "#{l(:issue_templates)} / #{l(:button_add)}" %></h2>
<%= labelled_form_for :global_issue_template, issue_template,
url: { controller: 'global_issue_templates', action: 'create' },
html: { id: 'global_issue_template-form',
class: nil, multipart: false } do |f| %>
<%= render 'form', { f: f, trackers: trackers, projects: projects,
issue_template: issue_template, apply_all_projects: apply_all_projects,
custom_fields: custom_fields, builtin_fields_enable: builtin_fields_enable } %>
<% end %>
================================================
FILE: app/views/global_issue_templates/show.html.erb
================================================
<div class='contextual'>
<%= link_to l(:button_delete),
{ controller: 'global_issue_templates', action: 'destroy', id: issue_template },
data: { confirm: l(:text_are_you_sure) },
title: l(:enabled_template_cannot_destroy, default: 'Only disabled template can be destroyed.'),
disabled: issue_template.enabled?, method: 'delete', class: 'icon icon-del template-disabled-link' %>
<%= link_to(l(:label_list_templates),
{ controller: 'global_issue_templates', action: 'index' }, class: 'icon icon-template') %>
</div>
<h2 class='global_issue_template'>
<%= l(:global_issue_templates, default: 'Global Template for note') %>: #<%= issue_template.id %> <%= issue_template.title %>
<%= avatar(issue_template.author, size: '24') %>
</h2>
<%= labelled_form_for :global_issue_template,
issue_template,
url: { controller: 'global_issue_templates', action: 'update', id: issue_template },
html: { id: 'global_issue_template-form', class: nil,
multipart: false } do |f| %>
<%= render 'form', { f: f, trackers: trackers,
issue_template: issue_template, projects: projects, apply_all_projects: apply_all_projects,
custom_fields: custom_fields, builtin_fields_enable: builtin_fields_enable } %>
<% end %>
================================================
FILE: app/views/global_note_templates/_form.html.erb
================================================
<%= error_messages_for 'global_note_template' %>
<div class='box tabular box-white'>
<p><%= f.text_field :name, required: true, size: 80, label: l(:issue_template_name) %></p>
<fieldset class='issue'>
<legend class='issue'><%= l(:label_applied_for_issue) %></legend>
<p>
<% if note_template.tracker.blank? %>
<%= f.select :tracker_id, trackers.collect { |t| [t.name, t.id] }, { required: true },
required: true, label: l(:label_tracker) %>
<%= h note_template.tracker.present? ? note_template.tracker.name :
l(:orphaned_template, default: 'Orphaned template from tracker') %>
<% else %>
<%= f.select :tracker_id, trackers.collect { |t| [t.name, t.id] }, { required: true },
required: true, label: l(:label_tracker), selected: note_template.tracker.id %>
<% end %>
</p>
<p>
<%= f.text_area :description, cols: 78, rows: 12,
required: true,
label: l(:label_comment), class: 'wiki-edit' %>
</p>
<p>
<%= f.select :visibility, GlobalNoteTemplate.visibilities.map { |k, v| [t("note_templates.visibility.#{k}"), k] },
selected: note_template.visibility,
required: true, label: l(:field_template_visibility) %>
</p>
<p id='visible_roles_checkbox'
style='display: <%= note_template.visibility == 'roles' ? 'block;' : 'none;' %>'>
<label for='global_note_visible_roles[role_ids]'><%= l(:label_role) %></label>
<% Role.givable.each do |role| %>
<%= check_box_tag('global_note_template[role_ids][]',
role.id,
note_template.global_note_visible_roles.pluck(:role_id).to_a.include?(role.id)) %>
<%= role.name %>
<% end %>
</p>
</fieldset>
<p>
<%= f.text_area :memo, cols: 70, rows: 3,
required: false,
label: l(:issue_template_note) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='memo_help_area'
data-tooltip-content='memo_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='memo_help_area'></span>
</a>
</p>
<p>
<%= f.check_box :enabled, label: l(:label_enabled) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='enabled_help_area'
data-tooltip-content='enabled_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='enabled_help_area'></span>
</a>
</p>
</div>
<%= wikitoolbar_for 'global_note_template_description' %>
<!-- help content -->
<div id='issue_title_help_content' class='wiki' style='display: none;'>
<%= l(:help_for_issue_title) %>
</div>
<div id='enabled_help_content' class='wiki' style='display: none;'>
<%= l(:label_enabled_help_message) %>
</div>
<div id='memo_help_content' class='wiki' style='display: none;'>
<%= l(:label_memo_help_message, default: 'Please set up a note explaining when applying this template.') %>
</div>
<!-- help content -->
<div class='box'>
<% if apply_all_projects %>
<p>
<i class='issue_template icon settings'></i>
<span class='issue_template help_content'>
<%= l(:note_apply_global_template_to_all_projects_setting_enabled) %>
</span>
(
<%= link_to(l(:label_settings),
{ controller: 'settings', action: 'plugin', id: 'redmine_issue_templates' },
class: 'issue_template icon plugins') %> )
</p>
<% end %>
<% if projects.any? %>
<fieldset class='box box-white' id='global_note_template_project_ids'
style='<%= apply_all_projects ? 'opacity: 0.6' : '' %>'>
<a class='collapsible collapsed template-help' data-template-help-target='all_projects'>
<%= l(:project_list_associated_this_template, { applied: note_template.projects.length, all: projects.length }) %>
</a>
<div id='all_projects' style='display: none;'>
<p><%= check_all_links 'global_note_template_project_ids' %></p>
<legend><%= l(:label_project_plural) %></legend>
<%= render_project_nested_lists(projects) do |p|
content_tag('label', check_box_tag('global_note_template[project_ids][]',
p.id, note_template.projects.to_a.include?(p),
id: nil, disabled: apply_all_projects,
checked: note_template.projects.to_a.include?(p) ) + ' ' + h(p))
end %>
</div>
</fieldset>
<% end %>
<%= hidden_field_tag 'global_note_template[project_ids][]', '' %>
</div>
<script type='text/javascript'>
const visibility_select = document.getElementById('global_note_template_visibility')
const roles_checkbox = document.getElementById('visible_roles_checkbox')
visibility_select.addEventListener('change', (e) => {
if (e.target.value == 'roles') {
roles_checkbox.style.display = 'block'
} else {
roles_checkbox.style.display = 'none'
}
})
</script>
================================================
FILE: app/views/global_note_templates/index.html.erb
================================================
<h2 class='global_note_template'><%=h "#{l(:global_note_templates, default: 'Global Note Templates')}" %></h2>
<%= render partial: 'common/nodata', locals: { trackers: trackers } %>
<div class='contextual issue_templates'>
<%= link_to(l(:label_new_templates),
{ controller: 'global_note_templates', action: 'new' }, class: 'icon icon-add') %>
<%= link_to(l(:global_issue_templates),
{ controller: 'global_issue_templates', action: 'index' },
class: 'icon icon-template') %>
<%= link_to(l(:label_settings),
{ controller: 'settings', action: 'plugin', id: 'redmine_issue_templates' },
class: 'issue_template icon plugins') %>
</div>
<div style='clear: both;'></div>
<% if template_map.blank? %>
<div class='template_box'>
<%= l(:no_note_templates_for_this_redmine, default: 'No global note templates are defined for this Redmine site.') %>
</div>
<% end %>
<% template_map.each_key do |tracker| %>
<div class='template_box'>
<h3 class='template_tracker'><%= tracker.name %></h3>
<table class='list template_list issues ui-sortable table-sortable'>
<thead>
<tr>
<th>#</th>
<th class='hideable'><%= l(:issue_template_name) %></th>
<th><%= l(:label_preview) %></th>
<th class='hideable'><%= l(:field_tracker) %></th>
<th class='hideable'><%= l(:field_author) %></th>
<th class='hideable'><%= l(:field_updated_at) %></th>
<th><%= l(:label_enabled) %></th>
<th><%=l(:button_sort)%></th>
</tr>
</thead>
<tbody>
<% template_map[tracker].sorted.each do |note_template| %>
<tr class='<%= cycle('odd', 'even') %> issue_template issue'>
<td><%= link_to h(note_template.id), { controller: 'global_note_templates',
id: note_template.id, action: 'show' },
{ title: note_template.name } %>
</td>
<td class='hideable template_title'>
<%= link_to h(note_template.name), { controller: 'global_note_templates',
id: note_template.id, action: 'show' },
{ title: "#{html_escape(note_template.memo)}" } %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%= note_template.name %></span>
<%= textilizable(note_template.description) %>
</div>
</div>
</a>
</td>
<td class='hideable'><%=h note_template.tracker.name %></td>
<td class='hideable'><%=h note_template.author %></td>
<td class='hideable'><%= format_time(note_template.updated_at)%> </td>
<td class='center'><%= checked_image note_template.enabled? %></td>
<td class='buttons'>
<%= reorder_handle(note_template, :url => url_for({ controller: 'global_note_templates',
id: note_template.id, action: 'update' })) %>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<%= javascript_tag do %>
// NOTE: Sortable feature depends on Redmine's sorting jQuery plugin.
$(function() { $('table.table-sortable tbody').positionedItems() })
<% end %>
<% end %>
================================================
FILE: app/views/global_note_templates/new.html.erb
================================================
<div class='contextual'>
<%= link_to(l(:label_list_templates),
{ controller: 'global_note_templates', action: 'index' }, class: 'icon icon-template') %>
</div>
<h2 class='global_note_template'><%=h "#{l(:global_note_templates, default: 'Global Template for note') } / #{l(:button_add)}" %></h2>
<%= labelled_form_for :global_note_template, note_template,
url: { controller: 'global_note_templates', action: 'create' },
html: { id: 'global_note_template-form', class: nil, multipart: false } do |f| %>
<%= render 'form', { f: f, trackers: trackers,
note_template: note_template, projects: projects, apply_all_projects: apply_all_projects } %>
<div id='preview' class='wiki'></div>
<%= submit_tag l(:button_create) %>
<%= link_to l(:button_cancel), { action: 'index'}, data: { confirm: l(:text_are_you_sure) } %>
<% end %>
================================================
FILE: app/views/global_note_templates/show.html.erb
================================================
<div class='contextual'>
<%= link_to l(:button_delete),
{ controller: 'global_note_templates', action: 'destroy', id: note_template },
data: { confirm: l(:text_are_you_sure) },
name: l(:enabled_template_cannot_destroy, default: 'Only disabled template can be destroyed.'),
disabled: note_template.enabled?, method: 'delete', class: 'icon icon-del template-disabled-link' %>
<%= link_to(l(:label_list_templates),
{ controller: 'global_note_templates', action: 'index' }, class: 'icon icon-template') %>
</div>
<h2 class='global_note_template'>
<%= l(:global_note_templates) %>: #<%= note_template.id %> <%= note_template.name %>
<%= avatar(note_template.author, size: '24') %>
</h2>
<%= labelled_form_for :global_note_template,
note_template,
url: { controller: 'global_note_templates', action: 'update', id: note_template },
html: { id: 'global_note_template-form', class: nil,
multipart: false } do |f| %>
<%= render 'form', { f: f, trackers: trackers,
note_template: note_template, projects: projects, apply_all_projects: apply_all_projects } %>
<div id='preview' class='wiki'></div>
<%= submit_tag l(:button_save) %>
<%= link_to l(:button_cancel), { action: 'index' },
onclick: 'Element.hide("edit-note_template"); return false' %>
<% end %>
================================================
FILE: app/views/issue_templates/_form.html.erb
================================================
<%= error_messages_for 'issue_template' %>
<div class='box tabular box-white'>
<p><%= f.text_field :title, required: true, size: 80, label: l(:issue_template_name) %></p>
<fieldset class='issue'>
<legend class='issue'><%= l(:label_applied_for_issue) %></legend>
<p>
<% if issue_template.tracker.blank? %>
<%= f.select :tracker_id, template_target_trackers(project, issue_template),
required: true, label: l(:label_tracker), include_blank: true %>
<%= h issue_template.tracker.present? ? issue_template.tracker.name :
l(:orphaned_template, default: 'Orphaned template from tracker') %>
<% else %>
<%= f.select :tracker_id, template_target_trackers(project, issue_template),
required: true, label: l(:label_tracker), selected: issue_template.tracker.id %>
<% unless project_tracker?(issue_template.tracker, project) %><br/>
<%= non_project_tracker_msg(project_tracker?(issue_template.tracker, project)) %>
<% end %>
<% end %>
</p>
<p><%= f.text_field :issue_title, required: false, size: 80, label: l(:issue_title) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='issue_title_help_area'
data-tooltip-content='issue_title_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='issue_title_help_area'></span>
</a>
</p>
<p>
<%= f.text_area :description, cols: 78, rows: 12,
required: true,
label: l(:issue_description), class: 'wiki-edit', style: 'overflow: auto;' %>
</p>
<!-- for Builtin Fields -->
<!-- buildin field Generator -->
<% if builtin_fields_enable %>
<div id="json_generator">
<p>
<label><%= l(:label_select_field, default: 'Select a field') %></label>
<select v-model='newItemTitle' id='field_selector'>
<option v-for='(value, key) in customFields' v-bind:value='key'>
{{ value.name }}
</option>
</select>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='builtin_fields_help_area'
data-tooltip-content='builtin_fields_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='builtin_fields_help_area'></span>
</a>
</p>
<p>
<label for='value_selector'><%= l(:field_value) %></label>
<textarea id='issue_template_json_setting_field' v-if='fieldFormat() == "text"' rows=6
placeholder='<%= l(:enter_value, default: 'Please enter a value') %>' v-model='newItemValue'>
</textarea>
<input id='issue_template_json_setting_field' v-if='fieldFormat() == "string"'
type='text'
placeholder='<%= l(:enter_value, default: 'Please enter a value') %>' v-model='newItemValue'>
<input id='issue_template_json_setting_field' v-if='fieldFormat() == "int"'
:max='customFields[newItemTitle].max_length' :min='customFields[newItemTitle].min_length'
type="number" placeholder='<%= l(:enter_value, default: 'Please enter a value') %>' v-model='newItemValue'>
<input type='date' id='issue_template_json_setting_field' v-if='fieldFormat() == "date"' v-model='newItemValue'>
<select v-model='newItemValue' v-if='fieldFormat() == "ratio"'>
<option v-for="ratio in [10, 20, 30, 40, 50, 60, 70, 80, 90, 100]">{{ ratio }} %</option>
</select>
<select v-model='newItemValue' :multiple='customFields[newItemTitle].multiple == true'
v-if='fieldFormat() == "list" || fieldFormat() == "bool"' id='value_selector'>
<option v-for="value in possibleValues()">{{ value }}</option>
</select>
<span style='margin-left: 4px;' class='icon icon-add' v-on:click='addField(newItemTitle, newItemValue)'>
<%= l(:button_add) %>
</span>
</p>
<div id='field_information' class='wiki' v-if='newItemTitle != ""'>
<b><%= l(:label_field_information, default: 'Field information') %></b>
<pre>{{ customFields[newItemTitle] }}</pre>
</div>
<div id='fields_setting_display_area'>
<ul class='json-list' v-if='items.length > 0'>
<li v-for='item in items'>
<span v-if='customFields[item.title]'>
<b>{{ customFields[item.title].name }}</b>: {{ item.value }} / {{ item.title }}
</span>
<span v-if='!customFields[item.title]'>
<i class='issue_template help_content'>
<%= l(:unavailable_fields_for_this_tracker, default: 'Unavailable field for this tarcker') %>
: {{ item.value }} / {{ item.title }}
</i>
</span>
<i class='icon icon-del' v-on:click='deleteField(item)'></i>
</li>
</ul>
<pre id='builtin_fields_data_via_vue' style='display: none;'>{{ items }}</pre>
<span class='icon icon-reload' id='reset-json' v-on:click='loadField()'><%= l(:button_reset) %></span>
<span class='icon icon-checked' id='paste-json'><%= l(:button_apply) %></span>
</div>
<!-- buildin field Generator -->
<p style='opacity: 0.6;'>
<%= f.text_area :builtin_fields,
required: false, cols: 60, rows: 4,
label: l(:label_builtin_fields_json, default: 'JSON for fields') %>
</p>
<div id='builtin_fields_help_content' class='wiki' style='display: none;'>
<%= l(:label_builtin_fields_help_message, default: 'Enter builtin filds or custom fields default values with JSON format. ') %>
</div>
</div>
<% end %>
<!-- for Builtin Fields -->
</fieldset>
<p>
<%= f.text_area :note, cols: 70, rows: 3,
required: false,
label: l(:issue_template_note), style: 'overflow:auto;' %>
</p>
<p><%= f.text_field :related_link, type: 'url',
size: 70, label: l(:issue_template_related_link, default: 'Related link') %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='related_link_help_content'
data-tooltip-area='related_link_help_area'
data-tooltip-content='related_link_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='related_link_help_area'></span>
</a>
</p>
<p id='link_title_paragraph'><%= f.text_field :link_title, size: 70, label: l(:issue_template_link_title, default: 'Link title') %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='link_title_help_content'
data-tooltip-area='link_title_help_area'
data-tooltip-content='link_title_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='link_title_help_area'></span>
</a>
</p>
<p><%= f.check_box :is_default, label: l(:field_is_default) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='isdefault_help_content'
data-tooltip-area='isdefault_help_area'
data-tooltip-content='isdefault_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='isdefault_help_area'></span>
</a>
</p>
<p><%= f.check_box :enabled, label: l(:label_enabled) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='enabled_help_content'
data-tooltip-area='enabled_help_area'
data-tooltip-content='enabled_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='enabled_help_area'></span>
</a>
</p>
<p>
<%= f.check_box :enabled_sharing, label: l(:label_enabled_sharing) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='enabledsharing_help_area'
data-tooltip-content='enabledsharing_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='enabledsharing_help_area'></span>
</a>
</p>
</div>
<%= wikitoolbar_for 'issue_template_description' %>
<!-- tooltip content -->
<div id='issue_title_help_content' class='wiki' style='display: none;'>
<%= l(:help_for_issue_title) %>
</div>
<div id='isdefault_help_content' class='wiki' style='display: none;'>
<%= l(:label_isdefault_help_message) %>
</div>
<div id='related_link_help_content' class='wiki' style='display: none;'>
<%= l(:label_related_link_help_message, default: 'If there are some example pages or sample issues which using issue template, please specify the link. So operator can see them as an usage or example for template.') %>
</div>
<div id='link_title_help_content' class='wiki' style='display: none;'>
<%= l(:label_link_title_help_message, default: 'If there are some example pages or sample issues which using issue template, please specify the link. So operator can see them as an usage or example for template.') %>
</div>
<div id='enabled_help_content' class='wiki' style='display: none;'>
<%= l(:label_enabled_help_message) %>
</div>
<div id='enabledsharing_help_content' class='wiki' style='display: none;'>
<%= l(:label_enabledshaing_help_message) %>
</div>
<!-- tooltip content -->
<script>
const baseUrl = "<%= url_for(controller: 'issue_templates', action: 'load_selectable_fields') %>"
const templateId = "<%= issue_template&.id || '' %>"
const templateType = 'issue_template'
const trackerPulldownId = templateType + '_tracker_id'
const base_builtin_fields = <%= issue_template.builtin_fields.html_safe %>
const base_custom_fields = <%= custom_fields.html_safe %>
const projectId = "<%= project.id %>"
</script>
<% if builtin_fields_enable %>
<%= javascript_include_tag('vue.min', plugin: 'redmine_issue_templates') %>
<%= javascript_include_tag('template_fields', plugin: 'redmine_issue_templates') %>
<% end %>
================================================
FILE: app/views/issue_templates/_issue_select_form.html.erb
================================================
<% return '' unless @issue.project.module_enabled? :issue_templates %>
<% return '' unless User.current.allowed_to?(:show_issue_templates, @issue.project) %>
<div id='template_area' style='display: none;'>
<p>
<label for='issue_template'><%=h l(:issue_template)%></label>
<select id='issue_template' name='issue_template'>
<option value="">---</option>
</select>
<a class='icon icon-hint' id='issue_template_related_link' style='display: none;' target='_blank' rel='noopener'></a>
<a class='icon template_tooltip' id='link_template_dialog' href='#issue_template_dialog'>
<%=h l(:display_and_filter_issue_templates_in_dialog, default: 'Filter Templates') %>
</a>
<% if setting.enable_help? %>
<a class='icon icon-help template-help' title='<%= l(:about_template_help_message) %>'
data-tooltip-area='template-help-message-area'
data-tooltip-content='template_help_content'>
<%= l(:label_help_message) %>
<span class='tooltip-area' id='template-help-message-area'></span>
</a>
<% end %>
<a class='icon icon-erase' title='<%= l(:erase_issue_subject_and_description, default: 'Erase') %>' id='erase_template'>
<%= l(:erase_issue_subject_and_description, default: 'Erase') %>
</a>
<a class='icon icon-reload disabled' title='<%= l(:revert_before_applying_template, default: 'Revert') %>'
id='revert_template' disabled='disabled'>
<%= l(:revert_before_applying_template, default: 'Revert') %>
</a>
<span id='original_subject' style='display: none;'></span>
<span id='original_description' style='display: none;'></span>
<span id='template_status-area'></span>
</p>
<!-- dialog box -->
<div id='issue_template_dialog' class='overlay'>
<div class='popup'>
<div class='header_wrapper'>
<div class='popup_header'>
<h2><span id='issue_template_dialog_title'></span><a class="close" href="#">×</a></h2>
</div>
</div>
<div class='template_search_filter_wrapper'>
<label for='template_search_filter'>
<%=h l(:label_filter_template, default: 'Filter template:') %>
</label>
<input type='text' name='template_search_filter' id='template_search_filter' class='autocomplete'>
</div>
<div id='filtered_templates_list'></div>
</div>
</div>
<div id='issue_template_confirm_to_replace_dialog' class='overlay'>
<a id='issue_template_confirm_to_replace_dialog_cancel' class='cancel' target='#'></a>
<div class='popup small'>
<p><b><%=h l(:label_msg_confirm_to_replace) %></b></p>
<p><input type='checkbox' id='issue_template_confirm_to_replace_hide_dialog'>
<%= h l(:label_hide_confirm_dialog_in_the_future,
default: 'Hide this confirmation in the future, just overwrite.') %>
</p>
<div class='footer_wrapper'>
<div class='popup_footer' style='text-align: center;'>
<i id='overwrite_yes' class='overwrite_confirm_btn'><%=h l(:general_text_Yes) %></i>
<i id='overwrite_no' class='overwrite_confirm_btn'><%=h l(:general_text_No) %></i>
</div>
</div>
</div>
</div>
<!-- dialog box -->
<div class='wiki' id='template_help_content' style='display: none;'>
<%= textilizable(setting.help_message) %>
</div>
</div>
<script type='text/javascript'>
//<![CDATA[
var templateConfig = {
pulldownUrl: '<%= pulldown_url %>',
isTriggeredBy: '<%= is_triggered_by %>',
loadUrl: '<%= url_for(controller: 'issue_templates', action: 'load', project_id: project_id, is_triggered_by: is_triggered_by) %>',
shouldReplaced: '<%= setting.should_replaced %>',
generalTextYes: '<%=h l(:general_text_Yes) %>',
generalTextNo : '<%=h l(:general_text_No) %>',
confirmMessage: '<%=h l(:label_template_applied, default: "Issue template is applied. You can revert with click 'Revert' link.") %>'
}
var templateNS = templateNS || new ISSUE_TEMPLATE(templateConfig)
templateNS.isTriggeredBy = '<%= is_triggered_by %>'
templateNS.setPulldown('<%= @issue.tracker.id %>')
document.getElementById('issue_template').addEventListener('change', (event) => {
templateNS.changeTemplatePlace()
templateNS.loadTemplate()
})
// Show dialog
document.getElementById('link_template_dialog').addEventListener('click', (event) => {
let templateListUrl = '<%= url_for(controller: 'issue_templates',
action:'list_templates', project_id: project_id, issue_tracker_id: @issue.tracker.id) %>'
let templateListTitle = '<%= "#{l(:issue_template)}: #{@issue.tracker.name}".html_safe %>'
templateNS.openDialog(templateListUrl, templateListTitle)
})
// revert template
document.getElementById('revert_template').addEventListener('click', (event) => {
templateNS.revertAppliedTemplate()
})
document.getElementById('erase_template').addEventListener('click', (event) => {
templateNS.eraseSubjectAndDescription()
})
// keydown keyup
document.querySelector("input[name='template_search_filter']").addEventListener('keydown', (event) => {
templateNS.filterTemplate(event)
})
document.querySelector("input[name='template_search_filter']").addEventListener('keyup', (event) => {
templateNS.filterTemplate(event)
})
// NOTE: Workaround for GitHub issue: 193
// Start observing the target node for configured mutations
try {
if (CKEDITOR.instances) {
// Create an observer instance linked to the callback function
let observer = new MutationObserver(callback)
// Select the node that will be observed for mutations
let targetNode = document.querySelector('#issue_description_and_toolbar')
// Options for the observer (which mutations to observe)
let config = { attributes: true, childList: true, characterData: true, subtree: true }
// Callback function to execute when mutations are observed
let callback = function (mutationsList) {
for (let i = 0, len = mutationsList.length; i < len; ++i) {
let mutation = mutationsList[i]
if (mutation.type === 'attributes') {
console.log('The ' + mutation.attributeName + ' attribute was modified.')
if (mutation.target.className == 'cke_contents cke_reset') {
// Wait for a while til CKE Editor's textarea is rendered, and after that
// apply template text.
setTimeout('templateNS.replaceCkeContent()', 200)
observer.disconnect()
}
}
}
}
observer.observe(targetNode, config)
}
} catch (e) {
// do nothing.
}
</script>
================================================
FILE: app/views/issue_templates/_issue_template_link.html.erb
================================================
<% if authorize_for('issue_templates', 'show') %>
<h3><%= l(:issue_template) %></h3>
<ul>
<li>
<%= link_to(l(:label_list_templates),
controller: 'issue_templates',
action: 'index',
project_id: @project) %>
</li>
<li>
<%= link_to_if_authorized(l(:label_new_templates),
{ controller: 'issue_templates', action: 'new', project_id: @project }) %>
</li>
</ul>
<%- end -%>
<% if authorize_for('note_templates', 'show') %>
<h3><%= l(:note_template) %></h3>
<ul>
<li>
<%= link_to(l(:label_list_templates),
controller: 'note_templates',
action: 'index',
project_id: @project) %>
</li>
<li>
<%= link_to_if_authorized(l(:label_new_templates),
{ controller: 'note_templates', action: 'new', project_id: @project }) %>
</li>
</ul>
<%- end -%>
================================================
FILE: app/views/issue_templates/_list_templates.api.rsb
================================================
api.array :global_issue_templates do
global_issue_templates.each do |template|
api.template do
api.id template.id
api.tracker_id template.tracker_id
api.tracker_name template.tracker.id
api.title template.title
api.issue_title template.issue_title
api.description template.description
api.note template.note
api.enabled template.enabled
api.updated_on template.updated_on
api.created_on template.created_on
api.updated_on template.updated_on
end
end
end
api.array :inherit_templates do
inherit_templates.each do |template|
api.template do
api.id template.id
api.tracker_id template.tracker_id
api.tracker_name template.tracker.name
api.title template.title
api.issue_title template.issue_title
api.description template.description
api.note template.note
api.enabled template.enabled
api.is_default template.id == default_template
api.enabled_sharing template.enabled_sharing
api.position template.position
api.updated_on template.updated_on
api.created_on template.created_on
api.updated_on template.updated_on
end
end
end
api.array :issue_templates do
issue_templates.each do |template|
api.template do
api.id template.id
api.tracker_id template.tracker_id
api.tracker_name template.tracker.name
api.title template.title
api.issue_title template.issue_title
api.description template.description
api.note template.note
api.enabled template.enabled
api.is_default template.is_default
api.enabled_sharing template.enabled_sharing
api.position template.position
api.updated_on template.updated_on
api.created_on template.created_on
api.updated_on template.updated_on
end
end
end
================================================
FILE: app/views/issue_templates/_list_templates.html.erb
================================================
<table class='list template_list'>
<thead>
<tr>
<th><%=h l(:issue_template_name) %></th>
<th><%=h l(:issue_title) %></th>
<th><%=h l(:issue_description) %></th>
<th><%= l(:field_is_default) %></th>
<th><%=h l(:button_apply, default: 'Apply') %></th>
</tr>
</thead>
<% issue_templates.each do |template| %>
<tr class='<%= cycle('odd', 'even') %> template_data'>
<td>
<%= template.title %>
</td>
<td>
<%= template.issue_title %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' href='#' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%= template.title %></span>
<%= textilizable(template.description) %>
<% if template.related_link.present? %>
<hr/>
<%= link_to template.link_title.present? ? template.link_title : l(:issue_template_related_link, default: 'Related link'),
template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
<% end %>
</div>
</div>
</td>
<td class='center'><%= checked_image template.is_default? %></td>
<td>
<i data-issue-template-id='<%= template.id %>'
class='icon icon-test template-update-link'></i>
</td>
</tr>
<% end %>
<% inherit_templates.each do |template| %>
<tr class="<%= cycle('odd', 'even') %> template_data">
<td>
<%= template.title %>
</td>
<td>
<%= template.issue_title %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' href='#' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class="title"><%= template.title %></span>
<%= textilizable(template.description) %>
<% if template.related_link.present? %>
<hr/>
<%= link_to template.link_title.present? ? template.link_title : l(:issue_template_related_link, default: 'Related link'),
template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
<% end %>
</div>
</div>
</td>
<td class='center'><%= checked_image template == default_template %></td>
<td>
<i data-issue-template-id='<%= template.id %>'
class='icon icon-test template-update-link'></i>
</td>
</tr>
<% end %>
<% global_issue_templates.each do |template| %>
<tr class='<%= cycle('odd', 'even') %> template_data'>
<td>
<%= template.title %>
</td>
<td>
<%= template.issue_title %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' href='#' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%= template.issue_title %></span>
<%= textilizable(template.description) %>
<% if template.related_link.present? %>
<hr/>
<%= link_to template.link_title.present? ? template.link_title : l(:issue_template_related_link, default: 'Related link'),
template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
<% end %>
</div>
</div>
</td>
<td class='center'><%= checked_image template == default_template %></td>
<td>
<i data-issue-template-id='<%= template.id %>'
class='icon icon-test template-update-link template-global cursor: pointer;'></i>
</td>
</tr>
<% end %>
</table>
<script type="text/javascript">
const templateElements = document.querySelectorAll('i.template-update-link')
const templateNS = new ISSUE_TEMPLATE()
Array.from(templateElements).forEach(el => {
el.addEventListener('click', (event) => {
templateNS.updateTemplateSelect(event)
})
})
</script>
================================================
FILE: app/views/issue_templates/_note_form.html.erb
================================================
<%
element_id = type
if type == 'template_edit_journal'
element_id = "template_journal_#{@journal.id}_notes"
end
project_id = issue&.project_id
tracker_id = issue&.tracker_id
%>
<div id='<%= element_id %>'>
<label for='select_note_template' style='font-weight: bold;'>
<%=h l(:label_template_for_note, default: 'Template for note') %>
</label>
<a class='icon template_tooltip' id='link_<%= element_id %>_dialog' href='#<%= element_id %>_dialog' onclick='noteTemplateNS.changeNoteTemplateList("<%= element_id %>")'>
<%=h l(:display_and_filter_issue_templates_in_dialog, default: 'Filter Templates') %>
</a>
<!-- dialog box -->
<div id='<%= element_id %>_dialog' class='overlay'>
<div class='popup'>
<div class='header_wrapper'>
<div class='popup_header'>
<h2><%=h l(:label_template_for_note, default: 'Select template for note') %> <a class="close" href="#">×</a></h2>
</div>
</div>
<div class='filtered_templates_list'>
<!-- Replaced contemts -->
</div>
</div>
</div>
</div>
<script type='text/javascript'>
var noteTemplateConfig = {
baseElementId: '<%= element_id %>',
baseTemplateListUrl: '<%= url_for(controller: 'note_templates', action:'list_templates') %>',
baseTrackerId: <%= tracker_id %>,
baseProjectId: <%= project_id %>,
loadNoteTemplateUrl: '<%= load_note_templates_path %>'
}
// let baseElementId = '<%= element_id %>'
let content = document.querySelectorAll('#' + noteTemplateConfig.baseElementId)
if (content.length === 1) {
let element = content[0].closest('form')
if (noteTemplateConfig.baseElementId === 'template_issue_notes') {
element = content[0].closest('fieldset')
}
element.insertBefore(content[0], element.firstChild)
}
var noteTemplateNS = noteTemplateNS || new NOTE_TEMPLATE(noteTemplateConfig)
</script>
================================================
FILE: app/views/issue_templates/_template_pulldown.html.erb
================================================
<option value=''>---</option>
<optgroup label='<%=h @tracker.name %>'>
<%= options_for_template_pulldown(grouped_options) %>
</optgroup>
================================================
FILE: app/views/issue_templates/index.api.rsb
================================================
api.array :global_issue_templates do
@global_issue_templates.each do |template|
api.template do
api.id template.id
api.tracker_id template.tracker_id
api.tracker_name template.tracker.try(:name) || nil
api.title template.title
api.issue_title template.issue_title
api.description template.description
api.note template.note
api.enabled template.enabled
api.updated_on template.updated_on
api.created_on template.created_on
api.updated_on template.updated_on
end
end
end
api.array :inherit_templates do
@inherit_templates.each do |template|
api.template do
api.id template.id
api.tracker_id template.tracker_id
api.tracker_name template.tracker.tracker.try(:name) || nil
api.title template.title
api.issue_title template.issue_title
api.description template.description
api.note template.note
api.enabled template.enabled
api.is_default template.is_default
api.enabled_sharing template.enabled_sharing
api.position template.position
api.updated_on template.updated_on
api.created_on template.created_on
api.updated_on template.updated_on
end
end
end
api.array :issue_templates do
project_templates.each do |template|
api.template do
api.id template.id
api.tracker_id template.tracker_id
api.tracker_name template.tracker.try(:name) || nil
api.title template.title
api.issue_title template.issue_title
api.description template.description
api.note template.note
api.enabled template.enabled
api.is_default template.is_default
api.enabled_sharing template.enabled_sharing
api.position template.position
api.updated_on template.updated_on
api.created_on template.created_on
api.updated_on template.updated_on
end
end
end
================================================
FILE: app/views/issue_templates/index.html.erb
================================================
<h2 class='issue_template'><%=h "#{l(:issue_template)}" %></h2>
<%= render partial: 'common/nodata', locals: { trackers: tracker_ids } %>
<div class='contextual issue_templates'>
<%= link_to_if_authorized(l(:label_new_templates),
{ controller: 'issue_templates', action: 'new', project_id: @project },
class: 'icon icon-add') %>
</div>
<div style='clear: both;'></div>
<% if @notice -%>
<div class='flash notice'><%= @notice -%></div>
<% end -%>
<% if @template_map.empty? %>
<div class='template_box'>
<%= l(:no_issue_templates_for_this_project) %>
</div>
<% end %>
<% @template_map.each_key do |tracker| %>
<div class='template_box'>
<h3 class='template_tracker'><%= tracker.name %></h3>
<%= non_project_tracker_msg(project_tracker?(tracker, @project)) %>
<table class='list issues table-sortable template_list'>
<thead>
<tr>
<th>#</th>
<th class='hideable'><%= l(:issue_template_name) %></th>
<th><%= l(:label_preview) %></th>
<th class='hideable'><%= l(:field_tracker) %></th>
<th class='hideable'><%= l(:field_author) %></th>
<th class='hideable'><%= l(:field_updated_on) %></th>
<th><%= l(:field_is_default) %></th>
<th><%= l(:label_enabled) %></th>
<% if authorize_for('issue_templates', 'edit') %>
<th><%=l(:button_sort)%></th>
<% end %>
</tr>
</thead>
<tbody>
<% @template_map[tracker].each do |issue_template| %>
<tr class='<%= cycle('odd', 'even') %> issue_template issue'>
<td>
<%= link_to h(issue_template.id),
{ controller: :issue_templates, action: 'show',
id: issue_template.id, project_id: issue_template.project
},
{ title: issue_template.note } %>
</td>
<td class='hideable template_title'>
<%= link_to h(issue_template.title),
{ controller: 'issue_templates',
id: issue_template.id, action: 'show' },
{ title: "#{html_escape(issue_template.note) }"} %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class="title"><%= issue_template.title %></span>
<%= textilizable(issue_template.description) %>
<% if issue_template.related_link.present? %>
<hr/>
<%= link_to issue_template.link_title.present? ? issue_template.link_title : l(:issue_template_related_link, default: 'Related link'),
issue_template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
<% end %>
</div>
</div>
</td>
<td class='hideable'><%=h issue_template.tracker.name %></td>
<td class='hideable'><%=h issue_template.author %></td>
<td class='hideable'><%= format_time(issue_template.updated_on)%> </td>
<td class='center'><%= checked_image issue_template.is_default? %></td>
<td class='center'><%= checked_image issue_template.enabled? %></td>
<% if authorize_for('issue_templates', 'edit') %>
<td class='buttons'>
<%= reorder_handle(issue_template,
url: url_for(:controller => 'issue_templates',
:action => 'update', :id => issue_template.id,
:project_id => issue_template.project)) %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
</div>
<%= javascript_tag do %>
// NOTE: Sortable feature depends on Redmine's sorting jQuery plugin.
$(function() { $('table.table-sortable tbody').positionedItems() })
<% end %>
<% end %>
<% unless @inherit_templates.blank? %>
<h2 class='issue_template'><%=h "#{l(:label_inherited_templates)}" %></h2>
<div class='template_box'>
<table class='list issues template_list'>
<thead>
<tr>
<th>#</th>
<th class='hideable'><%= l(:issue_template_name) %></th>
<th><%= l(:label_preview) %></th>
<th class='hideable'><%= l(:field_tracker) %></th>
<th class='hideable'><%= l(:field_author) %></th>
<th class='hideable'><%= l(:field_updated_on) %></th>
<th><%= l(:field_is_default) %></th>
<th><%= l(:label_enabled) %></th>
</tr>
</thead>
<tbody>
<% @inherit_templates.each do |issue_template| %>
<tr class='<%= cycle('odd', 'even') %> issue_template issue'>
<td>
<%= link_to h(issue_template.id),
{ controller: 'issue_templates',
action: 'show', id: issue_template.id,
project_id: issue_template.project_id },
{ title: issue_template.note } %>
</td>
<td class='hideable template_title'>
<%= link_to h(issue_template.title),
{ controller: 'issue_templates',
project_id: issue_template.project_id,
id: issue_template.id, action: 'show' },
{ title: "#{html_escape(issue_template.note)}" } %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%=h issue_template.title %></span>
<%=h textilizable(issue_template.description) %>
<% if issue_template.related_link.present? %>
<hr/>
<%= link_to issue_template.link_title.present? ? issue_template.link_title : l(:issue_template_related_link, default: 'Related link'),
issue_template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
<% end %>
</div>
</div>
</td>
<td class='hideable'><%=h issue_template.tracker.name %></td>
<td class='hideable'><%=h issue_template.author %></td>
<td class='hideable'><%=h format_time(issue_template.updated_on)%> </td>
<td class='center'><%= checked_image issue_template.is_default? %></td>
<td class='center'><%= checked_image issue_template.enabled? %></td>
</tr>
<tr class='<%= current_cycle %>' style='display: none;' id='template_description-<%= issue_template.id %>'>
<td class="description" colspan="8">
<div class="wiki"><%=h textilizable(issue_template.description) %>
<hr/>
<%= link_to_if issue_template.related_link.present?,
issue_template.link_title.present? ? issue_template.link_title : l(:issue_template_related_link, default: 'Related link'),
issue_template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% end %>
<% unless @global_issue_templates.blank? %>
<h2 class='issue_template'><%=h "#{l(:global_issue_templates)}" %></h2>
<div class='template_box'>
<% if apply_all_projects %>
<p>
<i class='issue_template icon settings'></i>
<span class="issue_template help_content">
<%= l(:note_apply_global_template_to_all_projects_setting_enabled) %><br/>
<%= l(:note_project_local_template_override_global_template) %>
</span>
</p>
<% end %>
<%= l(:only_admin_can_associate_global_template) %>
<table class='list issues template_list'>
<thead>
<tr>
<th>#</th>
<th class='hideable'><%= l(:issue_template_name) %></th>
<th><%= l(:label_preview) %></th>
<th class='hideable'><%= l(:field_tracker) %></th>
<th class='hideable'><%= l(:field_author) %></th>
<th class='hideable'><%= l(:field_updated_on) %></th>
<th><%= l(:field_is_default) %></th>
</tr>
</thead>
<tbody>
<% @global_issue_templates.each do |issue_template| %>
<tr class='<%= cycle('odd', 'even') %> issue_template issue'>
<td>
<% if User.current.admin? %>
<%= link_to h(issue_template.id),
{ controller: 'global_issue_templates',
action: 'show', id: issue_template.id, },
{ title: issue_template.note } %>
<% else %>
<%=h issue_template.id %>
<% end %>
</td>
<td class='hideable template_title'>
<%= link_to h(issue_template.title),
{ controller: 'global_issue_templates',
id: issue_template.id, action: 'show' },
{ title: "#{html_escape(issue_template.note)}" } %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%=h issue_template.title %></span>
<%=h textilizable(issue_template.description) %>
<% if issue_template.related_link.present? %>
<hr/>
<%= link_to issue_template.link_title.present? ? issue_template.link_title : l(:issue_template_related_link, default: 'Related link'),
issue_template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
<% end %>
</div>
</div>
</td>
<td class='hideable'>
<% if issue_template.tracker.present? %>
<%= h issue_template.tracker.try(:name) || "ID: #{issue_template.tracker_id}" %>
<% else %>
<span title="<%= l(:orphaned_template, default: 'Orphaned template from tracker') %>">
<%= "ID: #{issue_template.tracker_id}" %>
</span>
<% end %>
</td>
<td class='hideable'><%=h issue_template.author %></td>
<td class='hideable'><%=h format_time(issue_template.updated_on)%> </td>
<td class='center'><%= checked_image issue_template.is_default? %></td>
</tr>
<tr class='<%= current_cycle %>' style='display: none;' id='global_template_description-<%= issue_template.id %>'>
<td class='description' colspan='8'>
<div class="wiki"><%=h textilizable(issue_template.description) %>
<% if issue_template.related_link.present? %>
<hr/>
<%= link_to issue_template.link_title.present? ? issue_template.link_title : l(:issue_template_related_link, default: 'Related link'),
issue_template.related_link, target: '_blank', rel: 'nofollow noopener', class: 'external' %>
<% end %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
</div>
<% end %>
<a id='orphaned_template_link' class='icon template_tooltip orphaned_template_link template-help collapsible collapsed'
title='<%= l(:orphaned_templates) %>'
data-template-help-target='orphaned_templates'
data-url='<%= orphaned_templates_project_issue_templates_path %>'>
<%= l(:orphaned_templates, default: 'Orphaned Templates') %>
</a>
<div id='orphaned_templates' style='display: none'></div>
<%= render partial: 'common/template_links' %>
================================================
FILE: app/views/issue_templates/new.html.erb
================================================
<div class='contextual'>
<%= link_to(l(:label_list_templates),
{ controller: 'issue_templates',
action: 'index', project_id: project }, class: 'icon icon-template') %>
</div>
<h2 class='issue_template'><%=h "#{l(:issue_templates)} / #{l(:button_add)}" %></h2>
<%= render partial: 'common/nodata', locals: { trackers: project.trackers } %>
<% if project.trackers.any? %>
<%= labelled_form_for :issue_template, @issue_template,
url: { controller: 'issue_templates', action: 'create', project_id: project },
html: { id: 'issue_template-form', class: nil, multipart: false } do |f| %>
<%= render 'form', { f: f, issue_template: issue_template, project: project, custom_fields: custom_fields,
builtin_fields_enable: builtin_fields_enable } %>
<div id='preview' class='wiki'></div>
<%= submit_tag l(:button_create) %>
<%= link_to l(:button_cancel), { action: 'index'}, data: { confirm: l(:text_are_you_sure) } %>
<% end %>
<% end %>
<div style='float: right;'><%= render partial: 'common/template_links' %></div>
================================================
FILE: app/views/issue_templates/show.html.erb
================================================
<div class='contextual'>
<%= link_to_if_authorized l(:button_edit),
{ controller: 'issue_templates', action: 'update', id: issue_template,
project_id: project },
title: l(:button_edit),
class: 'icon icon-edit', accesskey: accesskey(:edit),
onclick: "document.getElementById('edit-issue_template').style.display = 'block'; return false;" %>
<%= link_to l(:button_copy),
{ controller: 'issue_templates',
action: 'new', project_id: project, copy_from: issue_template.id },
class: 'icon icon-copy', title: 'copy!' %>
<%= link_to_if_authorized l(:button_delete),
{ controller: 'issue_templates', action: 'destroy',
id: issue_template, project_id: project },
title: l(:enabled_template_cannot_destroy, default: 'Only disabled template can be destroyed.'),
data: { confirm: l(:template_remove_confirm,
{ count: child_project_used_count, default: 'Are you sure to remove this template? %{count} subprojects use this template.' }) },
method: 'delete', class: 'icon icon-del template-disabled-link',
disabled: issue_template.enabled?
%>
<%= link_to(l(:label_list_templates),
{ controller: 'issue_templates',
action: 'index',
project_id: project }, class: 'icon icon-template') %>
</div>
<h2 class='issue_template'>
<%= l(:issue_templates) %>: #<%= issue_template.id %> <%= issue_template.title %>
<%= avatar(issue_template.author, size: '24') %>
</h2>
<%= render partial: 'common/nodata', locals: { trackers: project.trackers } %>
<% if authorize_for('issue_templates', 'update') %>
<div id='edit-issue_template'>
<%= labelled_form_for :issue_template, issue_template,
url: { controller: 'issue_templates', action: 'update',
project_id: project, id: issue_template },
html: { id: 'issue_template-form', class: nil, multipart: false } do |f| %>
<%= render 'form', { f: f, issue_template: issue_template, project: project,
custom_fields: custom_fields, builtin_fields_enable: builtin_fields_enable } %>
<div id='preview' class='wiki'></div>
<%= submit_tag l(:button_save) %>
<%= link_to l(:button_cancel), { action: 'index' },
onclick: 'Element.hide("edit-issue_template"); return false;' %>
<% end %>
<hr/>
</div>
<% else %>
<div class='box tabular box-white'>
<p>
<label><%= l(:issue_template_name) %></label>
<%= h issue_template.title %>
</p>
<fieldset class='issue'>
<legend class='issue'><%= l(:label_applied_for_issue) %></legend>
<p><label><%= l(:label_tracker) %></label>
<%= h issue_template.tracker.present? ? issue_template.tracker.name :
l(:orphaned_template, default: 'Orphaned template from tracker') %>
<br/>
<%= non_project_tracker_msg(project_tracker?(issue_template.tracker, project)) %>
</p>
<p>
<label><%= l(:issue_title) %></label>
<%= h issue_template.issue_title %>
</p>
<p>
<strong style='margin-left: -100px;'><%= l(:issue_description) %></strong>
</p>
<div class='wiki issue_template'><%= textilizable(issue_template.description) %></div>
</fieldset>
<p><label><%= l(:issue_template_note) %></label>
<%= issue_template.note.blank? ? l(:label_none) : issue_template.note %>
</p>
<p><label><%= l(:issue_template_related_link, default: 'Related Link') %></label>
<%= issue_template.related_link.blank? ? l(:label_none) : issue_template.related_link %>
</p>
<p><label><%= l(:field_is_default) %></label>
<%= checked_image issue_template.is_default? %>
</p>
<p><label><%= l(:label_enabled) %></label>
<%= checked_image issue_template.enabled? %>
</p>
<p><label><%= l(:label_enabled_sharing) %></label>
<%= checked_image issue_template.enabled_sharing? %>
<%= l(:label_number_of_subprojects_use_this_template, {
count: child_project_used_count, default: '%{count} subprojects use this template.....' }) %>
</p>
<p><label><%= l(:field_author) %></label>
<%= authoring issue_template.created_on, issue_template.author %>
<% if issue_template.created_on != issue_template.updated_on %>
(<%= l(:label_updated_time, time_tag(issue_template.updated_on)).html_safe %>)
<% end %>
</p>
</div>
<% end %>
<%= render partial: 'common/template_links' %>
================================================
FILE: app/views/issue_templates_settings/index.html.erb
================================================
<div id='issue_templates_settings'>
<%= render partial: 'common/nodata', locals: { trackers: @project.trackers } %>
<h2 class='issue_template_setting'><%= l(:issue_templates_settings, default: 'Issue Templates Setting') %></h2>
<p></p>
<div class='template_box'>
<h2><%= l(:issue_templates_optional_settings, default: 'Templates Optional Settings') %></h2>
<p><%= l(:about_help_message) %></p>
<%= labelled_form_for :settings, @issue_templates_setting,
url: { controller: 'issue_templates_settings',
action: 'edit', project_id: @project,
setting_id: @issue_templates_setting.id },
html: { id: 'issue_templates_settings' } do |f| %>
<%= error_messages_for 'issue_templates_setting' %>
<div class='box tabular'>
<p><%= f.check_box :inherit_templates, label: l(:label_inherit_templates) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='inherit_templates_help_area'
data-tooltip-content='inherit_templates_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='inherit_templates_help_area'></span>
</a>
</p>
<p>
<%= f.check_box :should_replaced, label: l(:label_should_replaced) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-template-help-target='should_replaced_help_content'
data-tooltip-area='should_replaced_help_area'
data-tooltip-content='should_replaced_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='should_replaced_help_area'></span>
</a>
</p>
<p><%= f.check_box :enabled, label: l(:label_show_help_message) %></p>
<p>
<label><%=l(:label_help_message)%></label>
<%=content_tag(:label, l(:label_help_message)) %>
<%=text_area_tag 'settings[help_message]', @issue_templates_setting['help_message'], size: '50x5',
class: 'wiki-edit' %>
<br/>
</p>
<%= wikitoolbar_for 'settings_help_message' %>
</div>
<%= submit_tag l(:button_save) %>
<% end %>
</div>
<!--- help content -->
<div id='inherit_templates_help_content' class='wiki' style='display: none;'>
<%= l(:label_inherit_templates_help_message) %>
</div>
<div id='should_replaced_help_content' class='wiki' style='display: none;'>
<%= l(:label_should_replaced_help_message) %>
</div>
<!--- help content -->
</div>
<div style='float: right;'><%= render partial: 'common/template_links' %></div>
================================================
FILE: app/views/note_templates/_form.html.erb
================================================
<%= error_messages_for 'note_template' %>
<div class='box tabular box-white'>
<p><%= f.text_field :name, required: true, size: 80, label: l(:issue_template_name) %></p>
<fieldset class='issue'>
<legend class='issue'><%= l(:label_applied_for_issue) %></legend>
<p>
<% if note_template.tracker.blank? %>
<%= f.select :tracker_id, template_target_trackers(project, note_template),
required: true, label: l(:label_tracker), include_blank: true %>
<%= h note_template.tracker.present? ? note_template.tracker.name :
l(:orphaned_template, default: 'Orphaned template from tracker') %>
<% else %>
<%= f.select :tracker_id, template_target_trackers(project, note_template),
required: true, label: l(:label_tracker), selected: note_template.tracker.id %>
<% unless project_tracker?(note_template.tracker, project) %><br/>
<%= non_project_tracker_msg(project_tracker?(note_template.tracker, project)) %>
<% end %>
<% end %>
</p>
<p>
<%= f.text_area :description, cols: 78, rows: 12,
required: true,
label: l(:label_comment), class: 'wiki-edit' %>
</p>
<p>
<%= f.select :visibility, NoteTemplate.visibilities.map { |k, v| [t("note_templates.visibility.#{k}"), k] },
selected: note_template.visibility,
required: true, label: l(:field_template_visibility) %>
</p>
<p id='visible_roles_checkbox'
style='display: <%= note_template.visibility == 'roles' ? 'block;' : 'none;' %>'>
<label for='note_visible_roles[role_ids]'><%= l(:label_role) %></label>
<% Role.givable.each do |role| %>
<%= check_box_tag('note_template[role_ids][]',
role.id,
note_template.note_visible_roles.pluck(:role_id).to_a.include?(role.id)) %>
<%= role.name %>
<% end %>
</p>
</fieldset>
<p>
<%= f.text_area :memo, cols: 70, rows: 3,
required: false,
label: l(:issue_template_note) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='memo_help_area'
data-tooltip-content='memo_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='memo_help_area'></span>
</a>
</p>
<p>
<%= f.check_box :enabled, label: l(:label_enabled) %>
<a class='icon icon-help template-help' title='<%= l(:help_for_this_field) %>'
data-tooltip-area='enabled_help_area'
data-tooltip-content='enabled_help_content'>
<%= l(:help_for_this_field) %>
<span class='tooltip-area' id='enabled_help_area'></span>
</a>
</p>
</div>
<%= wikitoolbar_for 'note_template_description' %>
<!-- help content -->
<div id='issue_title_help_content' class='wiki' style='display: none;'>
<%= l(:help_for_issue_title) %>
</div>
<div id='enabled_help_content' class='wiki' style='display: none;'>
<%= l(:label_enabled_help_message) %>
</div>
<div id='memo_help_content' class='wiki' style='display: none;'>
<%= l(:label_memo_help_message, default: 'Please set up a note explaining when applying this template.') %>
</div>
<!-- help content -->
<script type='text/javascript'>
const visibility_select = document.getElementById('note_template_visibility')
const roles_checkbox = document.getElementById('visible_roles_checkbox')
visibility_select.addEventListener('change', (e) => {
if (e.target.value == 'roles') {
roles_checkbox.style.display = 'block'
} else {
roles_checkbox.style.display = 'none'
}
})
</script>
================================================
FILE: app/views/note_templates/_list_note_templates.html.erb
================================================
<table class='list template_list'>
<thead>
<tr>
<th><%=h l(:note_template_name, default: "Name") %></th>
<th><%=h l(:note_description, default: "Comment Body") %></th>
<th><%=h l(:button_apply, default: 'Apply') %></th>
</tr>
</thead>
<% note_templates.each do |template| %>
<tr class="<%= cycle('odd', 'even') %> template_data">
<td>
<%= template.name %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' href='#' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%= template.name %></span>
<%= textilizable(template.description) %>
<hr/>
<span class='title'><%= l(:issue_template_note) %></span>
<%= textilizable(template.try(:memo)) %>
</div>
</div>
</td>
<td>
<a data-note-template-id='<%= template.id %>'
onclick='noteTemplateNS.applyNoteTemplate(this)'
class='icon icon-test template-update-link'></a>
</td>
</tr>
<% end %>
<% global_note_templates.each do |template| %>
<tr class="<%= cycle('odd', 'even') %> template_data">
<td>
<%= template.name %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' href='#' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%= template.name %></span>
<%= textilizable(template.description) %>
<hr/>
<span class='title'><%= l(:issue_template_note) %></span>
<%= textilizable(template.try(:memo)) %>
</div>
</div>
</td>
<td>
<a data-note-template-id='<%= template.id %>'
onclick='noteTemplateNS.applyNoteTemplate(this)'
class='icon icon-test template-global template-update-link'></a>
</td>
</tr>
<% end %>
</table>
================================================
FILE: app/views/note_templates/index.api.rsb
================================================
api.array :note_templates do
note_templates.each do |template|
api.template do
api.id template.id
api.tracker_id template.tracker_id
api.tracker_name template.tracker.name
api.title template.title
api.description template.description
api.enabled template.enabled
api.created_on template.created_on
api.updated_on template.updated_on
end
end
end
================================================
FILE: app/views/note_templates/index.html.erb
================================================
<h2 class='note_template'><%=h "#{l(:note_template)}" %></h2>
<%= render partial: 'common/nodata', locals: { trackers: tracker_ids } %>
<div class='contextual note_templates'>
<%= link_to_if_authorized(l(:label_new_templates),
{ controller: 'note_templates', action: 'new', project_id: @project },
class: 'icon icon-add') %>
</div>
<div style='clear: both;'></div>
<% if @notice -%>
<div class='flash notice'><%= @notice -%></div>
<% end -%>
<% if @template_map.empty? %>
<div class='template_box'>
<%= l(:no_note_templates_for_this_project) %>
</div>
<% end %>
<% @template_map.each_key do |tracker| %>
<div class='template_box'>
<h3 class='template_tracker'><%= tracker.name %></h3>
<table class='list issues table-sortable template_list'>
<thead>
<tr>
<th>#</th>
<th class='hideable'><%= l(:issue_template_name) %></th>
<th><%= l(:label_preview) %></th>
<th class='hideable'><%= l(:field_tracker) %></th>
<th class='hideable'><%= l(:field_author) %></th>
<th class='hideable'><%= l(:field_updated_on) %></th>
<th><%= l(:label_enabled) %></th>
<% if authorize_for('note_templates', 'edit') %>
<th><%=l(:button_sort)%></th>
<% end %>
</tr>
</thead>
<tbody>
<% @template_map[tracker].each do |note_template| %>
<tr class='<%= cycle('odd', 'even') %> note_template issue'>
<td>
<%= link_to h(note_template.id),
{ controller: :note_templates, action: 'show',
id: note_template.id, project_id: note_template.project
},
{ title: note_template.memo } %>
</td>
<td class='hideable template_title'>
<%= link_to h(note_template.name),
{ controller: 'note_templates',
id: note_template.id, action: 'show' },
{ title: "#{html_escape(note_template.memo)}" } %>
</td>
<td>
<div class='template_tooltip_wrapper'>
<a class='icon template_tooltip' title='<%= l(:label_preview) %>'></a>
<div class='wiki template_tooltip_body'>
<span class='title'><%= note_template.name %></span>
<%= textilizable(note_template.description) %>
</div>
</div>
</td>
<td class='hideable'><%=h note_template.tracker.name %></td>
<td class='hideable'><%=h note_template.author %></td>
<td class='hideable'><%= format_time(note_template.updated_at)%> </td>
<td class='center'><%= checked_image note_template.enabled? %></td>
<% if authorize_for('note_templates', 'edit') %>
<td class='buttons'>
<%= reorder_handle(note_template,
url: url_for(:controller => 'note_templates',
:action => 'update', :id => note_template.id,
:project_id => note_template.project)) %>
</td>
<% end %>
</tr>
<% end %>
</tbody>
</table>
</div>
<%= javascript_tag do %>
// NOTE: Sortable feature depends on Redmine's sorting jQuery plugin.
$(function() { $('table.table-sortable tbody').positionedItems() })
<% end %>
<% end %>
<% if @global_note_templates.present? %>
<h2 class='issue_template'><%=h "#{l(:global_note_templates)}" %></h2>
<div class='template_box'>
<% if apply_all_projects %>
<p>
<i class='issue_template icon settings'></i>
<span class="issue_template help_content">
<%= l(:note_apply_global_template_to_all_projects_setting_enabled) %><br/>
<%= l(:note_project_local_template_override_global_template) %>
</span>
</p>
<% end %>
<%= l(:only_admin_can_associate_global_template) %>
<table class='list template_list issues'>
<thead>
<tr>
<th>#</th>
<th class='hideable'><%= l(:issue_template_name) %></th>
<th><%= l(:label_preview) %></th>
<th class='hideable'><%= l(:field_tracker) %></th>
<th class='hideable'><%= l(:field_author) %></th>
<th class='hideable'><%= l(:field_updated_on) %></th>
<th><%= l(:label_enabled) %></th>
</tr>
</thead>
<tbody>
<% @global_note_templates.each do |note_template| %>
<tr class='<%= cycle('odd', 'even') %> issue_template issue'>
<td>
<% if User.current.admin? %>
<%= link_to h(note_template.id),
gitextract_qmbduvvp/
├── .circleci/
│ └── config.yml
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── greetings.yml
├── .gitignore
├── .rubocop.yml
├── .rubocop_todo.yml
├── Dockerfile
├── Gemfile.local
├── ISSUE_TEMPLATE.md
├── LICENSE.txt
├── README.md
├── RELEASE-NOTES.md
├── _config.yml
├── app/
│ ├── controllers/
│ │ ├── concerns/
│ │ │ ├── issue_templates_common.rb
│ │ │ └── project_templates_common.rb
│ │ ├── global_issue_templates_controller.rb
│ │ ├── global_note_templates_controller.rb
│ │ ├── issue_templates_controller.rb
│ │ ├── issue_templates_settings_controller.rb
│ │ └── note_templates_controller.rb
│ ├── helpers/
│ │ └── issue_templates_helper.rb
│ ├── models/
│ │ ├── concerns/
│ │ │ └── issue_template/
│ │ │ └── common.rb
│ │ ├── global_issue_template.rb
│ │ ├── global_note_template.rb
│ │ ├── global_note_template_project.rb
│ │ ├── global_note_visible_role.rb
│ │ ├── issue_template.rb
│ │ ├── issue_template_setting.rb
│ │ ├── note_template.rb
│ │ └── note_visible_role.rb
│ └── views/
│ ├── common/
│ │ ├── _nodata.html.erb
│ │ ├── _orphaned.html.erb
│ │ └── _template_links.html.erb
│ ├── global_issue_templates/
│ │ ├── _form.html.erb
│ │ ├── index.html.erb
│ │ ├── new.html.erb
│ │ └── show.html.erb
│ ├── global_note_templates/
│ │ ├── _form.html.erb
│ │ ├── index.html.erb
│ │ ├── new.html.erb
│ │ └── show.html.erb
│ ├── issue_templates/
│ │ ├── _form.html.erb
│ │ ├── _issue_select_form.html.erb
│ │ ├── _issue_template_link.html.erb
│ │ ├── _list_templates.api.rsb
│ │ ├── _list_templates.html.erb
│ │ ├── _note_form.html.erb
│ │ ├── _template_pulldown.html.erb
│ │ ├── index.api.rsb
│ │ ├── index.html.erb
│ │ ├── new.html.erb
│ │ └── show.html.erb
│ ├── issue_templates_settings/
│ │ └── index.html.erb
│ ├── note_templates/
│ │ ├── _form.html.erb
│ │ ├── _list_note_templates.html.erb
│ │ ├── index.api.rsb
│ │ ├── index.html.erb
│ │ ├── new.html.erb
│ │ └── show.html.erb
│ └── settings/
│ └── _redmine_issue_templates.html.erb
├── assets/
│ ├── javascripts/
│ │ ├── issue_templates.js
│ │ └── template_fields.js
│ └── stylesheets/
│ └── issue_templates.css
├── config/
│ ├── locales/
│ │ ├── bg.yml
│ │ ├── da.yml
│ │ ├── de.yml
│ │ ├── en.yml
│ │ ├── es.yml
│ │ ├── fr.yml
│ │ ├── it.yml
│ │ ├── ja.yml
│ │ ├── ko.yml
│ │ ├── pl.yml
│ │ ├── pt-BR.yml
│ │ ├── pt.yml
│ │ ├── ru.yml
│ │ ├── sr-YU.yml
│ │ ├── zh-TW.yml
│ │ └── zh.yml
│ └── routes.rb
├── db/
│ └── migrate/
│ ├── 0001_create_issue_templates.rb
│ ├── 0002_create_issue_template_settings.rb
│ ├── 0003_add_issue_title_to_issue_templates.rb
│ ├── 0004_add_position_to_issue_templates.rb
│ ├── 20121208150810_add_is_default_to_issue_templates.rb
│ ├── 20130630141710_add_enabled_sharing_to_issue_templates.rb
│ ├── 20130701024625_add_inherit_templates_to_issue_template_settings.rb
│ ├── 2014020191500_add_should_replaced_to_issue_template_settings.rb
│ ├── 20140307024626_create_global_issue_templates.rb
│ ├── 20140312054531_create_global_issue_templates_projects.rb
│ ├── 20140330155030_remove_is_default_from_global_issue_templates.rb
│ ├── 20160727222420_add_checklist_json_to_issue_templates.rb
│ ├── 20160828190000_add_checklist_json_to_global_issue_templates.rb
│ ├── 20160829001500_change_issue_template_enabled_column.rb
│ ├── 20160829001530_change_global_issue_template_enabled_column.rb
│ ├── 20170317082100_add_is_default_to_global_issue_templates.rb
│ ├── 20181104065200_add_unique_key_to_global_issue_templates_projects.rb
│ ├── 20190303082102_create_note_templates.rb
│ ├── 20190714171020_create_note_visible_roles.rb
│ ├── 20190714211530_add_visibility_to_note_templates.rb
│ ├── 20200101204020_add_related_link_to_issue_templates.rb
│ ├── 20200101204220_add_related_link_to_global_issue_templates.rb
│ ├── 20200102204815_add_link_title_to_issue_templates.rb
│ ├── 20200102205044_add_link_title_to_global_issue_templates.rb
│ ├── 20200103213630_add_builtin_fields_json_to_issue_templates.rb
│ ├── 20200115073600_add_builtin_fields_json_to_global_issue_templates.rb
│ ├── 20200314132500_change_column_note_template_description.rb
│ ├── 20200405115700_create_global_note_templates.rb
│ ├── 20200405120700_create_global_note_visible_roles.rb
│ └── 20200418114157_create_join_table_global_note_template_project.rb
├── docker-compose.yml
├── goodcheck.yml
├── init.rb
├── lang/
│ └── en.yml
├── lib/
│ ├── issue_templates/
│ │ ├── issues_hook.rb
│ │ └── journals_hook.rb
│ └── tasks/
│ ├── test.rake
│ └── util.rake
├── script/
│ └── circleci-setup.sh
├── spec/
│ ├── controllers/
│ │ ├── concerns/
│ │ │ └── issue_templates_common_spec.rb
│ │ ├── global_issue_templates_controller_spec.rb
│ │ ├── issue_templates_controller_spec.rb
│ │ └── settings_controller_spec.rb
│ ├── factories/
│ │ ├── enabled_modules.rb
│ │ ├── global_issue_templates.rb
│ │ ├── global_note_templates.rb
│ │ ├── issue_statuses.rb
│ │ ├── issue_template_settings.rb
│ │ ├── issue_templates.rb
│ │ ├── projects.rb
│ │ ├── role.rb
│ │ ├── trackers.rb
│ │ └── users.rb
│ ├── features/
│ │ ├── admin_spec.rb
│ │ ├── drag_and_drop_spec.rb
│ │ ├── issue_template_popup_spec.rb
│ │ ├── issue_template_spec.rb
│ │ └── update_issue_spec.rb
│ ├── helpers/
│ │ └── issue_templates_helper_spec.rb
│ ├── models/
│ │ ├── global_issue_template_spec.rb
│ │ ├── global_note_template_spec.rb
│ │ ├── issue_template_setting_spec.rb
│ │ ├── issue_template_spec.rb
│ │ └── note_visible_role_spec.rb
│ ├── rails_helper.rb
│ ├── requests/
│ │ ├── global_note_templates_spec.rb
│ │ └── note_templates_spec.rb
│ ├── spec_helper.rb
│ └── support/
│ ├── controller_helper.rb
│ └── login_helper.rb
└── test/
├── fixtures/
│ ├── global_issue_templates.yml
│ ├── global_issue_templates_projects.yml
│ ├── issue_template_settings.yml
│ └── issue_templates.yml
├── functional/
│ ├── global_issue_templates_controller_test.rb
│ ├── issue_templates_controller_test.rb
│ ├── issue_templates_settings_controller_test.rb
│ ├── issues_controller_test.rb
│ └── projects_controller_test.rb
├── integration/
│ └── layout_test.rb
├── test_helper.rb
└── unit/
├── global_issue_templates_test.rb
├── issue_template_setting_test.rb
├── issue_template_test.rb
└── note_template_test.rb
SYMBOL INDEX (382 symbols across 67 files)
FILE: app/controllers/concerns/issue_templates_common.rb
type Concerns (line 3) | module Concerns
type IssueTemplatesCommon (line 4) | module IssueTemplatesCommon
class InvalidTemplateFormatError (line 7) | class InvalidTemplateFormatError < StandardError; end
function log_action (line 13) | def log_action
function plugin_setting (line 17) | def plugin_setting
function apply_all_projects? (line 21) | def apply_all_projects?
function apply_template_when_edit_issue? (line 25) | def apply_template_when_edit_issue?
function builtin_fields_enabled? (line 29) | def builtin_fields_enabled?
function load_selectable_fields (line 34) | def load_selectable_fields
function orphaned_templates (line 43) | def orphaned_templates
function apply_all_projects? (line 47) | def apply_all_projects?
function builtin_fields_json (line 51) | def builtin_fields_json
function valid_params (line 58) | def valid_params
function destroy (line 64) | def destroy
function core_fields_map_by_tracker_id (line 71) | def core_fields_map_by_tracker_id(tracker_id: nil, project_id: nil)
function custom_fields_map_by_tracker_id (line 133) | def custom_fields_map_by_tracker_id(tracker_id = nil)
FILE: app/controllers/concerns/project_templates_common.rb
type Concerns (line 3) | module Concerns
type ProjectTemplatesCommon (line 4) | module ProjectTemplatesCommon
function show (line 12) | def show
function destroy (line 16) | def destroy
function save_and_flash (line 27) | def save_and_flash(message, action_on_failure)
function plugin_setting (line 46) | def plugin_setting
function apply_all_projects? (line 50) | def apply_all_projects?
function template (line 56) | def template
function find_user (line 60) | def find_user
function find_tracker (line 64) | def find_tracker
function find_project (line 68) | def find_project
FILE: app/controllers/global_issue_templates_controller.rb
class GlobalIssueTemplatesController (line 4) | class GlobalIssueTemplatesController < ApplicationController
method index (line 17) | def index
method new (line 28) | def new
method create (line 34) | def create
method show (line 48) | def show
method update (line 52) | def update
method edit (line 64) | def edit
method destroy (line 79) | def destroy
method preview (line 91) | def preview
method orphaned (line 101) | def orphaned
method find_project (line 105) | def find_project
method find_object (line 109) | def find_object
method save_and_flash (line 115) | def save_and_flash(message, action_on_failure)
method template_params (line 130) | def template_params
method render_form_params (line 137) | def render_form_params
FILE: app/controllers/global_note_templates_controller.rb
class GlobalNoteTemplatesController (line 4) | class GlobalNoteTemplatesController < ApplicationController
method index (line 17) | def index
method new (line 29) | def new
method create (line 35) | def create
method show (line 42) | def show
method update (line 46) | def update
method destroy (line 54) | def destroy
method find_project (line 65) | def find_project
method find_object (line 69) | def find_object
method save_and_flash (line 75) | def save_and_flash(message, action_on_failure)
method template_params (line 90) | def template_params
method render_form_params (line 96) | def render_form_params
method apply_all_projects? (line 105) | def apply_all_projects?
method plugin_setting (line 109) | def plugin_setting
FILE: app/controllers/issue_templates_controller.rb
class IssueTemplatesController (line 4) | class IssueTemplatesController < ApplicationController
method index (line 12) | def index
method new (line 41) | def new
method create (line 52) | def create
method update (line 69) | def update
method load (line 81) | def load
method set_pulldown (line 95) | def set_pulldown
method list_templates (line 116) | def list_templates
method menu_items (line 141) | def menu_items
method preview (line 146) | def preview
method orphaned (line 154) | def orphaned
method find_object (line 158) | def find_object
method find_templates (line 165) | def find_templates
method template (line 171) | def template
method setting (line 175) | def setting
method global_templates (line 179) | def global_templates(tracker_id)
method default_templates (line 186) | def default_templates
method default_template_index (line 192) | def default_template_index
method add_templates_to_group (line 196) | def add_templates_to_group(templates, option = {})
method issue_templates (line 205) | def issue_templates
method inherit_templates (line 212) | def inherit_templates
method template_params (line 216) | def template_params
method templates_exist? (line 222) | def templates_exist?
method render_form_params (line 226) | def render_form_params
method loadable_trigger? (line 236) | def loadable_trigger?
FILE: app/controllers/issue_templates_settings_controller.rb
class IssueTemplatesSettingsController (line 4) | class IssueTemplatesSettingsController < ApplicationController
method index (line 8) | def index; end
method edit (line 10) | def edit
method preview (line 18) | def preview
method menu_items (line 23) | def menu_items
method find_user (line 29) | def find_user
method find_project (line 33) | def find_project
method find_issue_templates_setting (line 39) | def find_issue_templates_setting
method update_template_setting (line 43) | def update_template_setting
FILE: app/controllers/note_templates_controller.rb
class NoteTemplatesController (line 3) | class NoteTemplatesController < ApplicationController
method index (line 9) | def index
method new (line 35) | def new
method create (line 40) | def create
method update (line 47) | def update
method load (line 57) | def load
method list_templates (line 78) | def list_templates
method destroy (line 99) | def destroy
method menu_items (line 110) | def menu_items
method find_object (line 116) | def find_object
method template_params (line 123) | def template_params
method template (line 129) | def template
method render_form_params (line 133) | def render_form_params
method templates_exist? (line 138) | def templates_exist?
method global_templates (line 142) | def global_templates(tracker_id)
FILE: app/helpers/issue_templates_helper.rb
type IssueTemplatesHelper (line 1) | module IssueTemplatesHelper
function project_tracker? (line 2) | def project_tracker?(tracker, project)
function non_project_tracker_msg (line 8) | def non_project_tracker_msg(flag)
function template_target_trackers (line 14) | def template_target_trackers(project, issue_template)
function options_for_template_pulldown (line 20) | def options_for_template_pulldown(options)
FILE: app/models/concerns/issue_template/common.rb
type Concerns (line 3) | module Concerns
type IssueTemplate (line 4) | module IssueTemplate
type Common (line 5) | module Common
function enabled? (line 53) | def enabled?
function <=> (line 57) | def <=>(other)
function checklist (line 63) | def checklist
function template_json (line 73) | def template_json(except: nil)
function builtin_fields (line 81) | def builtin_fields
function generate_json (line 85) | def generate_json
function template_struct (line 92) | def template_struct(option = {})
function log_destroy_action (line 96) | def log_destroy_action(template)
function confirm_disabled (line 100) | def confirm_disabled
function copy_title (line 107) | def copy_title
FILE: app/models/global_issue_template.rb
class GlobalIssueTemplate (line 3) | class GlobalIssueTemplate < ActiveRecord::Base
type Config (line 30) | module Config
method check_default (line 38) | def check_default
method get_templates_for_project_tracker (line 48) | def get_templates_for_project_tracker(project_id, tracker_id = nil)
FILE: app/models/global_note_template.rb
class GlobalNoteTemplate (line 3) | class GlobalNoteTemplate < ActiveRecord::Base
method <=> (line 57) | def <=>(other)
method template_json (line 61) | def template_json
method generate_json (line 67) | def generate_json
method note_visible_roles! (line 71) | def note_visible_roles!
method loadable? (line 87) | def loadable?(user_id:, project_id:)
method check_visible_roles (line 101) | def check_visible_roles
method confirm_disabled (line 109) | def confirm_disabled
method visible_note_templates_condition (line 120) | def visible_note_templates_condition(user_id:, project_id:, tracker_id:)
method get_templates_for_project_tracker (line 136) | def get_templates_for_project_tracker(project_id, tracker_id = nil)
method plugin_setting (line 143) | def plugin_setting
method apply_all_projects? (line 147) | def apply_all_projects?
FILE: app/models/global_note_template_project.rb
class GlobalNoteTemplateProject (line 3) | class GlobalNoteTemplateProject < ActiveRecord::Base
FILE: app/models/global_note_visible_role.rb
class GlobalNoteVisibleRole (line 3) | class GlobalNoteVisibleRole < ActiveRecord::Base
FILE: app/models/issue_template.rb
class IssueTemplate (line 3) | class IssueTemplate < ActiveRecord::Base
type Config (line 31) | module Config
method check_default (line 39) | def check_default
method used_projects (line 46) | def used_projects
method get_inherit_templates (line 58) | def get_inherit_templates(project_ids, tracker_id)
method get_templates_for_project_tracker (line 67) | def get_templates_for_project_tracker(project_id, tracker_id = nil)
FILE: app/models/issue_template_setting.rb
class IssueTemplateSetting (line 1) | class IssueTemplateSetting < ActiveRecord::Base
method find_or_create (line 12) | def self.find_or_create(project_id)
method apply_template_to_child_projects (line 26) | def apply_template_to_child_projects(project_id)
method unapply_template_from_child_projects (line 31) | def unapply_template_from_child_projects(project_id)
method find_setting (line 38) | def find_setting(project_id)
method enable_help? (line 48) | def enable_help?
method enabled_inherit_templates? (line 52) | def enabled_inherit_templates?
method child_projects (line 56) | def child_projects
method apply_template_to_child_projects (line 60) | def apply_template_to_child_projects
method unapply_template_from_child_projects (line 64) | def unapply_template_from_child_projects
method get_inherit_templates (line 68) | def get_inherit_templates(tracker = nil)
method update_inherit_template_of_child_projects (line 80) | def update_inherit_template_of_child_projects(value)
FILE: app/models/note_template.rb
class NoteTemplate (line 3) | class NoteTemplate < ActiveRecord::Base
class NoteTemplateError (line 7) | class NoteTemplateError < StandardError; end
method <=> (line 50) | def <=>(other)
method template_json (line 54) | def template_json
method generate_json (line 60) | def generate_json
method note_visible_roles! (line 64) | def note_visible_roles!
method loadable? (line 80) | def loadable?(user_id:)
method check_visible_roles (line 93) | def check_visible_roles
method confirm_disabled (line 101) | def confirm_disabled
method visible_note_templates_condition (line 112) | def visible_note_templates_condition(user_id:, project_id:, tracker_id:)
FILE: app/models/note_visible_role.rb
class NoteVisibleRole (line 3) | class NoteVisibleRole < ActiveRecord::Base
FILE: assets/javascripts/issue_templates.js
function ISSUE_TEMPLATE (line 10) | function ISSUE_TEMPLATE (config) {
function NOTE_TEMPLATE (line 554) | function NOTE_TEMPLATE (config) {
FILE: db/migrate/0001_create_issue_templates.rb
class CreateIssueTemplates (line 1) | class CreateIssueTemplates < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 19) | def self.down
FILE: db/migrate/0002_create_issue_template_settings.rb
class CreateIssueTemplateSettings (line 1) | class CreateIssueTemplateSettings < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 12) | def self.down
FILE: db/migrate/0003_add_issue_title_to_issue_templates.rb
class AddIssueTitleToIssueTemplates (line 1) | class AddIssueTitleToIssueTemplates < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 13) | def self.down
FILE: db/migrate/0004_add_position_to_issue_templates.rb
class AddPositionToIssueTemplates (line 1) | class AddPositionToIssueTemplates < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 13) | def self.down
FILE: db/migrate/20121208150810_add_is_default_to_issue_templates.rb
class AddIsDefaultToIssueTemplates (line 1) | class AddIsDefaultToIssueTemplates < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20130630141710_add_enabled_sharing_to_issue_templates.rb
class AddEnabledSharingToIssueTemplates (line 1) | class AddEnabledSharingToIssueTemplates < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20130701024625_add_inherit_templates_to_issue_template_settings.rb
class AddInheritTemplatesToIssueTemplateSettings (line 1) | class AddInheritTemplatesToIssueTemplateSettings < ActiveRecord::Migrati...
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/2014020191500_add_should_replaced_to_issue_template_settings.rb
class AddShouldReplacedToIssueTemplateSettings (line 1) | class AddShouldReplacedToIssueTemplateSettings < ActiveRecord::Migration...
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20140307024626_create_global_issue_templates.rb
class CreateGlobalIssueTemplates (line 1) | class CreateGlobalIssueTemplates < ActiveRecord::Migration[4.2]
method change (line 2) | def change
method down (line 20) | def self.down
FILE: db/migrate/20140312054531_create_global_issue_templates_projects.rb
class CreateGlobalIssueTemplatesProjects (line 1) | class CreateGlobalIssueTemplatesProjects < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 9) | def self.down
FILE: db/migrate/20140330155030_remove_is_default_from_global_issue_templates.rb
class RemoveIsDefaultFromGlobalIssueTemplates (line 1) | class RemoveIsDefaultFromGlobalIssueTemplates < ActiveRecord::Migration[...
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20160727222420_add_checklist_json_to_issue_templates.rb
class AddChecklistJsonToIssueTemplates (line 1) | class AddChecklistJsonToIssueTemplates < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20160828190000_add_checklist_json_to_global_issue_templates.rb
class AddChecklistJsonToGlobalIssueTemplates (line 1) | class AddChecklistJsonToGlobalIssueTemplates < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20160829001500_change_issue_template_enabled_column.rb
class ChangeIssueTemplateEnabledColumn (line 1) | class ChangeIssueTemplateEnabledColumn < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20160829001530_change_global_issue_template_enabled_column.rb
class ChangeGlobalIssueTemplateEnabledColumn (line 1) | class ChangeGlobalIssueTemplateEnabledColumn < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20170317082100_add_is_default_to_global_issue_templates.rb
class AddIsDefaultToGlobalIssueTemplates (line 1) | class AddIsDefaultToGlobalIssueTemplates < ActiveRecord::Migration[4.2]
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20181104065200_add_unique_key_to_global_issue_templates_projects.rb
class AddUniqueKeyToGlobalIssueTemplatesProjects (line 1) | class AddUniqueKeyToGlobalIssueTemplatesProjects < ActiveRecord::Migrati...
method up (line 2) | def self.up
method down (line 8) | def self.down
FILE: db/migrate/20190303082102_create_note_templates.rb
class CreateNoteTemplates (line 1) | class CreateNoteTemplates < ActiveRecord::Migration[5.1]
method up (line 2) | def up
method down (line 20) | def down
FILE: db/migrate/20190714171020_create_note_visible_roles.rb
class CreateNoteVisibleRoles (line 3) | class CreateNoteVisibleRoles < ActiveRecord::Migration[5.1]
method up (line 4) | def up
method down (line 14) | def down
FILE: db/migrate/20190714211530_add_visibility_to_note_templates.rb
class AddVisibilityToNoteTemplates (line 3) | class AddVisibilityToNoteTemplates < ActiveRecord::Migration[5.1]
method up (line 4) | def self.up
method down (line 8) | def self.down
FILE: db/migrate/20200101204020_add_related_link_to_issue_templates.rb
class AddRelatedLinkToIssueTemplates (line 3) | class AddRelatedLinkToIssueTemplates < ActiveRecord::Migration[5.2]
method up (line 4) | def self.up
method down (line 8) | def self.down
FILE: db/migrate/20200101204220_add_related_link_to_global_issue_templates.rb
class AddRelatedLinkToGlobalIssueTemplates (line 3) | class AddRelatedLinkToGlobalIssueTemplates < ActiveRecord::Migration[5.2]
method up (line 4) | def self.up
method down (line 8) | def self.down
FILE: db/migrate/20200102204815_add_link_title_to_issue_templates.rb
class AddLinkTitleToIssueTemplates (line 3) | class AddLinkTitleToIssueTemplates < ActiveRecord::Migration[5.2]
method up (line 4) | def self.up
method down (line 8) | def self.down
FILE: db/migrate/20200102205044_add_link_title_to_global_issue_templates.rb
class AddLinkTitleToGlobalIssueTemplates (line 3) | class AddLinkTitleToGlobalIssueTemplates < ActiveRecord::Migration[5.2]
method up (line 4) | def self.up
method down (line 8) | def self.down
FILE: db/migrate/20200103213630_add_builtin_fields_json_to_issue_templates.rb
class AddBuiltinFieldsJsonToIssueTemplates (line 1) | class AddBuiltinFieldsJsonToIssueTemplates < ActiveRecord::Migration[5.2]
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20200115073600_add_builtin_fields_json_to_global_issue_templates.rb
class AddBuiltinFieldsJsonToGlobalIssueTemplates (line 1) | class AddBuiltinFieldsJsonToGlobalIssueTemplates < ActiveRecord::Migrati...
method up (line 2) | def self.up
method down (line 6) | def self.down
FILE: db/migrate/20200314132500_change_column_note_template_description.rb
class ChangeColumnNoteTemplateDescription (line 1) | class ChangeColumnNoteTemplateDescription < ActiveRecord::Migration[5.2]
method up (line 2) | def self.up
method down (line 6) | def down
FILE: db/migrate/20200405115700_create_global_note_templates.rb
class CreateGlobalNoteTemplates (line 3) | class CreateGlobalNoteTemplates < ActiveRecord::Migration[5.1]
method up (line 4) | def up
method down (line 21) | def down
FILE: db/migrate/20200405120700_create_global_note_visible_roles.rb
class CreateGlobalNoteVisibleRoles (line 3) | class CreateGlobalNoteVisibleRoles < ActiveRecord::Migration[5.1]
method up (line 4) | def up
method down (line 14) | def down
FILE: db/migrate/20200418114157_create_join_table_global_note_template_project.rb
class CreateJoinTableGlobalNoteTemplateProject (line 1) | class CreateJoinTableGlobalNoteTemplateProject < ActiveRecord::Migration...
method change (line 2) | def change
FILE: init.rb
function issue_template_version_message (line 28) | def issue_template_version_message(original_message = nil)
function template_menu_allowed? (line 41) | def template_menu_allowed?
FILE: lib/issue_templates/issues_hook.rb
type IssueTemplates (line 3) | module IssueTemplates
class IssuesHook (line 4) | class IssuesHook < Redmine::Hook::ViewListener
method view_layouts_base_html_head (line 15) | def view_layouts_base_html_head(context = {})
method view_issues_form_details_top (line 21) | def view_issues_form_details_top(context = {})
method existing_issue? (line 42) | def existing_issue?(issue)
method copied_issue? (line 48) | def copied_issue?(parameters)
method create_action? (line 55) | def create_action?(action)
method setting (line 61) | def setting(project_id)
method need_template_js? (line 65) | def need_template_js?(controller)
method plugin_setting (line 69) | def plugin_setting
method apply_all_projects? (line 73) | def apply_all_projects?
method apply_template_when_edit_issue? (line 77) | def apply_template_when_edit_issue?
method locals_params (line 81) | def locals_params(issue, project_id, is_triggered_by)
method pulldown_url (line 89) | def pulldown_url(issue, project_id, is_triggered_by)
FILE: lib/issue_templates/journals_hook.rb
type IssueTemplates (line 5) | module IssueTemplates
class JournalsHook (line 6) | class JournalsHook < Redmine::Hook::ViewListener
method view_journals_notes_form_after_notes (line 7) | def view_journals_notes_form_after_notes(context = {})
method view_issues_edit_notes_bottom (line 22) | def view_issues_edit_notes_bottom(context = {})
method target_templates (line 35) | def target_templates(context, tracker_id)
method global_note_templates (line 42) | def global_note_templates(context, tracker_id)
method tracker_project_ids (line 49) | def tracker_project_ids(context, tracker_id)
FILE: spec/controllers/concerns/issue_templates_common_spec.rb
class FakesController (line 7) | class FakesController < ApplicationController
FILE: spec/features/drag_and_drop_spec.rb
function visit_template_list (line 54) | def visit_template_list(user)
function offset_array (line 61) | def offset_array(from, to)
function element_position (line 68) | def element_position(element)
FILE: spec/features/issue_template_popup_spec.rb
function visit_new_issue (line 125) | def visit_new_issue(user)
FILE: spec/features/update_issue_spec.rb
function visit_update_issue (line 144) | def visit_update_issue(user)
FILE: spec/support/controller_helper.rb
type ControllerHelper (line 1) | module ControllerHelper
function auth_with_user (line 3) | def auth_with_user(user)
function clear_token (line 7) | def clear_token
function login_request (line 11) | def login_request(login, password)
function assign_template_priv (line 15) | def assign_template_priv(role, add_permission: nil, remove_permission:...
FILE: spec/support/login_helper.rb
type LoginHelper (line 3) | module LoginHelper
function log_user (line 4) | def log_user(login, password)
function assign_template_priv (line 14) | def assign_template_priv(role, add_permission: nil, remove_permission:...
function wait_for_ajax (line 21) | def wait_for_ajax
function finished_all_ajax_requests? (line 27) | def finished_all_ajax_requests?
FILE: test/functional/global_issue_templates_controller_test.rb
class GlobalIssueTemplatesControllerTest (line 4) | class GlobalIssueTemplatesControllerTest < Redmine::ControllerTest
method setup (line 11) | def setup
method test_get_index (line 20) | def test_get_index
method test_update_template (line 25) | def test_update_template
method test_update_template_with_empty_title (line 35) | def test_update_template_with_empty_title
method test_destroy_template (line 48) | def test_destroy_template
method test_new_template (line 55) | def test_new_template
method test_create_template (line 60) | def test_create_template
method test_create_template_fail (line 79) | def test_create_template_fail
method test_preview_template (line 96) | def test_preview_template
FILE: test/functional/issue_templates_controller_test.rb
class IssueTemplatesControllerTest (line 4) | class IssueTemplatesControllerTest < Redmine::ControllerTest
method setup (line 11) | def setup
method test_get_index_with_non_existing_project (line 23) | def test_get_index_with_non_existing_project
method test_get_index_without_show_permission (line 29) | def test_get_index_without_show_permission
method test_get_index_with_normal (line 35) | def test_get_index_with_normal
method test_show_with_non_existing_template (line 40) | def test_show_with_non_existing_template
method test_show_return_json_hash (line 45) | def test_show_return_json_hash
method test_show_return_json_hash_of_global (line 51) | def test_show_return_json_hash_of_global
method test_show_render_pulldown (line 57) | def test_show_render_pulldown
method test_new_template (line 64) | def test_new_template
method test_create_template (line 71) | def test_create_template
method test_create_template_with_empty_title (line 98) | def test_create_template_with_empty_title
method test_preview_template (line 116) | def test_preview_template
method test_update_template (line 123) | def test_update_template
method test_update_template_with_empty_title (line 137) | def test_update_template_with_empty_title
method test_delete_template_fail_if_enabled (line 156) | def test_delete_template_fail_if_enabled
method test_delete_template_success_if_disabled (line 166) | def test_delete_template_success_if_disabled
method test_edit_template_failed_with_project_id_and_safe_attributes (line 179) | def test_edit_template_failed_with_project_id_and_safe_attributes
method test_child_project_index (line 196) | def test_child_project_index
method test_child_project_index_with_inherit_templates (line 210) | def test_child_project_index_with_inherit_templates
method test_child_project_render_pulldown_with_parent_template (line 222) | def test_child_project_render_pulldown_with_parent_template
method json_response (line 235) | def json_response
method child_project_setup (line 239) | def child_project_setup
method edit_permission (line 248) | def edit_permission
FILE: test/functional/issue_templates_settings_controller_test.rb
class IssueTemplatesSettingsControllerTest (line 5) | class IssueTemplatesSettingsControllerTest < Redmine::ControllerTest
method setup (line 14) | def setup
method test_update_without_permission (line 28) | def test_update_without_permission
method test_update_with_permission_and_non_project (line 36) | def test_update_with_permission_and_non_project
method test_update_with_permission_and_redirect (line 43) | def test_update_with_permission_and_redirect
method test_preview_template_setting (line 52) | def test_preview_template_setting
method test_create_template_setting (line 59) | def test_create_template_setting
FILE: test/functional/issues_controller_test.rb
class IssuesControllerTest (line 5) | class IssuesControllerTest < Redmine::ControllerTest
method setup (line 29) | def setup
method test_index_without_project (line 45) | def test_index_without_project
method test_index (line 51) | def test_index
method test_index_with_edit_permission (line 60) | def test_index_with_edit_permission
method test_new (line 67) | def test_new
method test_copy (line 74) | def test_copy
method test_new_without_project (line 80) | def test_new_without_project
FILE: test/functional/projects_controller_test.rb
class ProjectsControllerTest (line 4) | class ProjectsControllerTest < Redmine::ControllerTest
method setup (line 7) | def setup
method test_settings (line 17) | def test_settings
FILE: test/integration/layout_test.rb
class LayoutTest (line 3) | class LayoutTest < Redmine::IntegrationTest
method test_issue_template_not_visible_when_module_off (line 14) | def test_issue_template_not_visible_when_module_off
method test_issue_template_visible_when_module_on (line 28) | def test_issue_template_visible_when_module_on
FILE: test/unit/global_issue_templates_test.rb
class GlobalIssueTemplatesTest (line 3) | class GlobalIssueTemplatesTest < ActiveSupport::TestCase
method setup (line 6) | def setup
method test_truth (line 10) | def test_truth
method test_template_enabled (line 14) | def test_template_enabled
method test_sort_by_position (line 24) | def test_sort_by_position
FILE: test/unit/issue_template_setting_test.rb
class IssueTemplateSettingTest (line 3) | class IssueTemplateSettingTest < ActiveSupport::TestCase
method setup (line 6) | def setup
method test_truth (line 10) | def test_truth
method test_help_message_enabled (line 14) | def test_help_message_enabled
method test_duplicate_project_setting (line 20) | def test_duplicate_project_setting
method test_help_message_disabled (line 31) | def test_help_message_disabled
method test_find_template_setting (line 38) | def test_find_template_setting
FILE: test/unit/issue_template_test.rb
class IssueTemplateTest (line 3) | class IssueTemplateTest < ActiveSupport::TestCase
method setup (line 6) | def setup
method test_truth (line 10) | def test_truth
method test_template_enabled (line 14) | def test_template_enabled
method test_sort_by_position (line 24) | def test_sort_by_position
method test_is_default (line 30) | def test_is_default
FILE: test/unit/note_template_test.rb
class NoteTemplateTest (line 5) | class NoteTemplateTest < ActiveSupport::TestCase
method setup (line 8) | def setup
method teardown (line 22) | def teardown; end
method test_truth (line 24) | def test_truth
method test_template_enabled (line 28) | def test_template_enabled
method test_sort_by_position (line 38) | def test_sort_by_position
method test_visibility_with_success (line 44) | def test_visibility_with_success
method test_visibility_without_role_ids (line 56) | def test_visibility_without_role_ids
method test_visibility_from_mine_to_roles (line 69) | def test_visibility_from_mine_to_roles
Condensed preview — 166 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (477K chars).
[
{
"path": ".circleci/config.yml",
"chars": 3138,
"preview": "# Ruby CircleCI 2.0 configuration file\n#\n# Check https://circleci.com/docs/2.0/language-ruby/ for more details\n#\nversion"
},
{
"path": ".gitattributes",
"chars": 263,
"preview": ".gitattributes export-ignore\n.gitignore export-ignore\nwercker.yml export-ignore\nscript/ export-ignore\n.rubocop* export-i"
},
{
"path": ".github/FUNDING.yml",
"chars": 64,
"preview": "# These are supported funding model platforms\nko_fi: akikopusu\n\n"
},
{
"path": ".github/workflows/greetings.yml",
"chars": 385,
"preview": "name: Greetings\n\non: [issues]\n\njobs:\n greeting:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/first-interac"
},
{
"path": ".gitignore",
"chars": 63,
"preview": "coverage/\ndoc/\n.yardoc/\nGemfile.lock\nGemfile\n.history\n.wercker\n"
},
{
"path": ".rubocop.yml",
"chars": 121,
"preview": "inherit_from: .rubocop_todo.yml\nrequire:\n - rubocop-rails\nAllCops:\n TargetRubyVersion: 2.4\n Exclude:\n - 'db/**/*'\n"
},
{
"path": ".rubocop_todo.yml",
"chars": 1343,
"preview": "# This configuration was generated by\n# `rubocop --auto-gen-config`\n# on 2016-06-01 07:37:41 +0900 using RuboCop version"
},
{
"path": "Dockerfile",
"chars": 1891,
"preview": "FROM ruby:2.6\nLABEL maintainer=\"AKIKO TAKANO / (Twitter: @akiko_pusu)\" \\\n description=\"Image to run Redmine simply with"
},
{
"path": "Gemfile.local",
"chars": 228,
"preview": "group :test do\n gem 'simplecov-rcov', require: false\n gem 'rspec-rails'\n gem 'factory_bot_rails'\n gem 'launchy'\n ge"
},
{
"path": "ISSUE_TEMPLATE.md",
"chars": 801,
"preview": "This is a template to report bug related to redmine issue templates plugin.\nYou can fill in any format, free style in ca"
},
{
"path": "LICENSE.txt",
"chars": 17987,
"preview": "\t\t GNU GENERAL PUBLIC LICENSE\n\t\t Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc."
},
{
"path": "README.md",
"chars": 15834,
"preview": "# Redmine Issue Templates Plugin\n\n["
},
{
"path": "RELEASE-NOTES.md",
"chars": 8189,
"preview": "# Releas notes before v0.2.0\n\n### 0.1.9\n\nBugfix and refactoring release.\n\n* Bugfix: Fix wrong template sort ordering. ("
},
{
"path": "_config.yml",
"chars": 25,
"preview": "theme: jekyll-theme-slate"
},
{
"path": "app/controllers/concerns/issue_templates_common.rb",
"chars": 5143,
"preview": "# frozen_string_literal: true\n\nmodule Concerns\n module IssueTemplatesCommon\n extend ActiveSupport::Concern\n\n clas"
},
{
"path": "app/controllers/concerns/project_templates_common.rb",
"chars": 1894,
"preview": "# frozen_string_literal: true\n\nmodule Concerns\n module ProjectTemplatesCommon\n extend ActiveSupport::Concern\n inc"
},
{
"path": "app/controllers/global_issue_templates_controller.rb",
"chars": 4664,
"preview": "# frozen_string_literal: true\n\n# noinspection RubocopInspection\nclass GlobalIssueTemplatesController < ApplicationContro"
},
{
"path": "app/controllers/global_note_templates_controller.rb",
"chars": 3032,
"preview": "# frozen_string_literal: true\n\n# noinspection RubocopInspection\nclass GlobalNoteTemplatesController < ApplicationControl"
},
{
"path": "app/controllers/issue_templates_controller.rb",
"chars": 8021,
"preview": "# frozen_string_literal: true\n\n# noinspection ALL\nclass IssueTemplatesController < ApplicationController\n layout 'base'"
},
{
"path": "app/controllers/issue_templates_settings_controller.rb",
"chars": 1429,
"preview": "# frozen_string_literal: true\n\n# noinspection RubocopInspection\nclass IssueTemplatesSettingsController < ApplicationCont"
},
{
"path": "app/controllers/note_templates_controller.rb",
"chars": 4424,
"preview": "# frozen_string_literal: true\n\nclass NoteTemplatesController < ApplicationController\n include Concerns::ProjectTemplate"
},
{
"path": "app/helpers/issue_templates_helper.rb",
"chars": 759,
"preview": "module IssueTemplatesHelper\n def project_tracker?(tracker, project)\n return false unless tracker.present?\n\n proje"
},
{
"path": "app/models/concerns/issue_template/common.rb",
"chars": 3234,
"preview": "# frozen_string_literal: true\n\nmodule Concerns\n module IssueTemplate\n module Common\n extend ActiveSupport::Conc"
},
{
"path": "app/models/global_issue_template.rb",
"chars": 1503,
"preview": "# frozen_string_literal: true\n\nclass GlobalIssueTemplate < ActiveRecord::Base\n include Redmine::SafeAttributes\n includ"
},
{
"path": "app/models/global_note_template.rb",
"chars": 4350,
"preview": "# frozen_string_literal: true\n\nclass GlobalNoteTemplate < ActiveRecord::Base\n include Redmine::SafeAttributes\n include"
},
{
"path": "app/models/global_note_template_project.rb",
"chars": 161,
"preview": "# frozen_string_literal: true\n\nclass GlobalNoteTemplateProject < ActiveRecord::Base\n belongs_to :project\n belongs_to :"
},
{
"path": "app/models/global_note_visible_role.rb",
"chars": 455,
"preview": "# frozen_string_literal: true\n\nclass GlobalNoteVisibleRole < ActiveRecord::Base\n include Redmine::SafeAttributes\n\n saf"
},
{
"path": "app/models/issue_template.rb",
"chars": 2235,
"preview": "# frozen_string_literal: true\n\nclass IssueTemplate < ActiveRecord::Base\n include Redmine::SafeAttributes\n include Conc"
},
{
"path": "app/models/issue_template_setting.rb",
"chars": 2108,
"preview": "class IssueTemplateSetting < ActiveRecord::Base\n include Redmine::SafeAttributes\n belongs_to :project\n\n validates_uni"
},
{
"path": "app/models/note_template.rb",
"chars": 3665,
"preview": "# frozen_string_literal: true\n\nclass NoteTemplate < ActiveRecord::Base\n include Redmine::SafeAttributes\n include Activ"
},
{
"path": "app/models/note_visible_role.rb",
"chars": 421,
"preview": "# frozen_string_literal: true\n\nclass NoteVisibleRole < ActiveRecord::Base\n include Redmine::SafeAttributes\n\n safe_attr"
},
{
"path": "app/views/common/_nodata.html.erb",
"chars": 126,
"preview": "<% if trackers.blank? %>\n <div class='nodata'>\n <%= simple_format(l(:text_no_tracker_enabled)) %>\n </div>\n<% "
},
{
"path": "app/views/common/_orphaned.html.erb",
"chars": 2061,
"preview": "<h3 class='template_tracker'><%= l(:orphaned_template) %></h3>\n<table class='list issues template_list'>\n <thead>\n <tr"
},
{
"path": "app/views/common/_template_links.html.erb",
"chars": 1570,
"preview": "<div style='display: flex; float: right; padding-top: 40px;\n position: relative; bottom: 6px; right: "
},
{
"path": "app/views/global_issue_templates/_form.html.erb",
"chars": 11502,
"preview": "<%= error_messages_for 'global_issue_template' %>\n<div class='box tabular box-white'>\n <p><%= f.text_field :title, requ"
},
{
"path": "app/views/global_issue_templates/index.html.erb",
"chars": 4582,
"preview": "<h2 class='global_issue_template'><%=h \"#{l(:global_issue_templates)}\" %></h2>\n<%= render partial: 'common/nodata', loca"
},
{
"path": "app/views/global_issue_templates/new.html.erb",
"chars": 839,
"preview": "<div class='contextual'>\n <%= link_to(l(:label_list_templates),\n { controller: 'global_issue_templates', a"
},
{
"path": "app/views/global_issue_templates/show.html.erb",
"chars": 1369,
"preview": "<div class='contextual'>\n<%= link_to l(:button_delete),\n { controller: 'global_issue_templates', action: 'destroy', id:"
},
{
"path": "app/views/global_note_templates/_form.html.erb",
"chars": 5237,
"preview": "<%= error_messages_for 'global_note_template' %>\n<div class='box tabular box-white'>\n <p><%= f.text_field :name, requir"
},
{
"path": "app/views/global_note_templates/index.html.erb",
"chars": 3692,
"preview": "<h2 class='global_note_template'><%=h \"#{l(:global_note_templates, default: 'Global Note Templates')}\" %></h2>\n<%= rende"
},
{
"path": "app/views/global_note_templates/new.html.erb",
"chars": 921,
"preview": "<div class='contextual'>\n <%= link_to(l(:label_list_templates),\n { controller: 'global_note_templates', ac"
},
{
"path": "app/views/global_note_templates/show.html.erb",
"chars": 1413,
"preview": "<div class='contextual'>\n<%= link_to l(:button_delete),\n { controller: 'global_note_templates', action: 'destroy', id: "
},
{
"path": "app/views/issue_templates/_form.html.erb",
"chars": 10160,
"preview": "<%= error_messages_for 'issue_template' %>\n<div class='box tabular box-white'>\n <p><%= f.text_field :title, required: t"
},
{
"path": "app/views/issue_templates/_issue_select_form.html.erb",
"chars": 6686,
"preview": "<% return '' unless @issue.project.module_enabled? :issue_templates %>\n<% return '' unless User.current.allowed_to?(:sho"
},
{
"path": "app/views/issue_templates/_issue_template_link.html.erb",
"chars": 793,
"preview": "<% if authorize_for('issue_templates', 'show') %>\n<h3><%= l(:issue_template) %></h3>\n<ul>\n <li>\n <%= link_to(l(:labe"
},
{
"path": "app/views/issue_templates/_list_templates.api.rsb",
"chars": 1846,
"preview": "api.array :global_issue_templates do\n global_issue_templates.each do |template|\n api.template do\n api.id templa"
},
{
"path": "app/views/issue_templates/_list_templates.html.erb",
"chars": 4240,
"preview": "<table class='list template_list'>\n <thead>\n <tr>\n <th><%=h l(:issue_template_name) %></th>\n <th><%=h l(:issue_t"
},
{
"path": "app/views/issue_templates/_note_form.html.erb",
"chars": 1898,
"preview": "<%\n element_id = type\n if type == 'template_edit_journal'\n element_id = \"template_journal_#{@journal.id}_notes\"\n e"
},
{
"path": "app/views/issue_templates/_template_pulldown.html.erb",
"chars": 139,
"preview": "<option value=''>---</option>\n<optgroup label='<%=h @tracker.name %>'>\n <%= options_for_template_pulldown(grouped_optio"
},
{
"path": "app/views/issue_templates/index.api.rsb",
"chars": 1887,
"preview": "api.array :global_issue_templates do\n @global_issue_templates.each do |template|\n api.template do\n api.id templ"
},
{
"path": "app/views/issue_templates/index.html.erb",
"chars": 12813,
"preview": "<h2 class='issue_template'><%=h \"#{l(:issue_template)}\" %></h2>\n<%= render partial: 'common/nodata', locals: { trackers:"
},
{
"path": "app/views/issue_templates/new.html.erb",
"chars": 1145,
"preview": "<div class='contextual'>\n <%= link_to(l(:label_list_templates),\n { controller: 'issue_templates',\n "
},
{
"path": "app/views/issue_templates/show.html.erb",
"chars": 4805,
"preview": "<div class='contextual'>\n <%= link_to_if_authorized l(:button_edit),\n { controller: 'issue_t"
},
{
"path": "app/views/issue_templates_settings/index.html.erb",
"chars": 2848,
"preview": "<div id='issue_templates_settings'>\n <%= render partial: 'common/nodata', locals: { trackers: @project.trackers } %>\n\n "
},
{
"path": "app/views/note_templates/_form.html.erb",
"chars": 3732,
"preview": "<%= error_messages_for 'note_template' %>\n<div class='box tabular box-white'>\n <p><%= f.text_field :name, required: tru"
},
{
"path": "app/views/note_templates/_list_note_templates.html.erb",
"chars": 2107,
"preview": "<table class='list template_list'>\n <thead>\n <tr>\n <th><%=h l(:note_template_name, default: \"Name\") %></th>\n <th"
},
{
"path": "app/views/note_templates/index.api.rsb",
"chars": 405,
"preview": "api.array :note_templates do\n note_templates.each do |template|\n api.template do\n api.id template.id\n api."
},
{
"path": "app/views/note_templates/index.html.erb",
"chars": 6571,
"preview": "<h2 class='note_template'><%=h \"#{l(:note_template)}\" %></h2>\n<%= render partial: 'common/nodata', locals: { trackers: t"
},
{
"path": "app/views/note_templates/new.html.erb",
"chars": 920,
"preview": "<div class='contextual'>\n <%= link_to(l(:label_list_templates),\n { controller: 'note_templates',\n "
},
{
"path": "app/views/note_templates/show.html.erb",
"chars": 3706,
"preview": "<div class='contextual'>\n <%= link_to_if_authorized l(:button_edit),\n { controller: 'note_te"
},
{
"path": "app/views/settings/_redmine_issue_templates.html.erb",
"chars": 2681,
"preview": "<div class='form-inline issue_templates'>\n <p>\n <label for='settings_apply_global_template_to_all_projects'><%= l(:l"
},
{
"path": "assets/javascripts/issue_templates.js",
"chars": 22781,
"preview": "/*\n * To change this template, choose Tools | Templates\n * and open the template in the editor.\n *\n * Use '==' operator "
},
{
"path": "assets/javascripts/template_fields.js",
"chars": 4457,
"preview": "// This JS is used only when create / edit template. (Using Vue.js)\n'use strict'\nconst vm = new Vue({\n el: '#json_gener"
},
{
"path": "assets/stylesheets/issue_templates.css",
"chars": 9136,
"preview": "fieldset.issue {\n padding-top: 5px;\n padding-bottom: 5px;\n background-color: #F6F6F6;\n margin-top: 10px;\n "
},
{
"path": "config/locales/bg.yml",
"chars": 7683,
"preview": "# Bulgarian translation\r\nbg:\r\n issue_templates: Шаблони\r\n issue_template: Шаблони за задачи\r\n issue_template_note: Оп"
},
{
"path": "config/locales/da.yml",
"chars": 2962,
"preview": "# Danish strings go here for Rails i18n\nda:\n issue_templates: Sagsskabeloner\n issue_template: Sagsskabelon\n issue_te"
},
{
"path": "config/locales/de.yml",
"chars": 7687,
"preview": "# German strings go here for Rails i18n\r\nde:\r\n issue_templates: Vorlagen\r\n issue_template: Ticketvorlage\r\n issue_temp"
},
{
"path": "config/locales/en.yml",
"chars": 7426,
"preview": "# English strings go here for Rails i18n\nen:\n issue_templates: Issue templates\n issue_template: Issue template\n issue"
},
{
"path": "config/locales/es.yml",
"chars": 3533,
"preview": "# Spanish strings go here for Rails i18n\n# Translation by Andres Arias https://github.com/mrlocke\nes:\n issue_templates:"
},
{
"path": "config/locales/fr.yml",
"chars": 3397,
"preview": "# Les chaines en français sont définies ici pour Rails i18n\nfr:\n issue_templates: \"Gabarits\"\n issue_template: \"Gabarit"
},
{
"path": "config/locales/it.yml",
"chars": 3522,
"preview": "# Italian strings go here for Rails i18n\nit:\n issue_templates: Modelli segnalazioni\n issue_template: Modello segnalazi"
},
{
"path": "config/locales/ja.yml",
"chars": 5320,
"preview": "# Japanese translation\nja:\n issue_templates: チケットテンプレート\n issue_template: チケットテンプレート\n issue_template_note: メモ\n label_"
},
{
"path": "config/locales/ko.yml",
"chars": 5128,
"preview": "# Korean translation\r\nko:\r\n issue_templates: 템플릿\r\n issue_template: 일감 템플릿\r\n issue_template_note: 메모\r\n label_enabled:"
},
{
"path": "config/locales/pl.yml",
"chars": 3335,
"preview": "# Polish strings go here for Rails i18n\npl:\n issue_templates: Szablony zagadnień\n issue_template: Szablon zagadnienia\n"
},
{
"path": "config/locales/pt-BR.yml",
"chars": 5125,
"preview": "# Brazilian strings go here for Rails i18n\npt-BR:\n issue_templates: Modelos de tarefas\n issue_template: Modelo de tare"
},
{
"path": "config/locales/pt.yml",
"chars": 3249,
"preview": "# Brazilian strings go here for Rails i18n\npt:\n issue_templates: Modelos de tarefas\n issue_template: Modelo de tarefas"
},
{
"path": "config/locales/ru.yml",
"chars": 4844,
"preview": "# Russian strings go here for Rails i18n\nru:\n issue_templates: Шаблоны\n issue_template: Шаблон задачи\n issue_template"
},
{
"path": "config/locales/sr-YU.yml",
"chars": 2305,
"preview": "# English strings go here for Rails i18n\nsr:\n issue_templates: Šabloni problema\n issue_template: Šablon problema\n iss"
},
{
"path": "config/locales/zh-TW.yml",
"chars": 3518,
"preview": "# Tranditional Chinese strings go here for Rails i18n\nzh-TW:\n issue_templates: \"問題樣板\"\n issue_template: \"問題樣板\"\n issue_"
},
{
"path": "config/locales/zh.yml",
"chars": 3207,
"preview": "# Simplified Chinese strings go here for Rails i18n, based on file ja.yml\nzh:\n issue_templates: ISSUE模板管理\n issue_templ"
},
{
"path": "config/routes.rb",
"chars": 1291,
"preview": "#\n# TODO: Clean up routing.\n#\nRails.application.routes.draw do\n concern :tamplate_common do\n get 'orphaned_templates"
},
{
"path": "db/migrate/0001_create_issue_templates.rb",
"chars": 814,
"preview": "class CreateIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n create_table :issue_templates do |t|\n t"
},
{
"path": "db/migrate/0002_create_issue_template_settings.rb",
"chars": 318,
"preview": "class CreateIssueTemplateSettings < ActiveRecord::Migration[4.2]\n def self.up\n create_table :issue_template_settings"
},
{
"path": "db/migrate/0003_add_issue_title_to_issue_templates.rb",
"chars": 385,
"preview": "class AddIssueTitleToIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n add_column :issue_templates, :issue"
},
{
"path": "db/migrate/0004_add_position_to_issue_templates.rb",
"chars": 472,
"preview": "class AddPositionToIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n add_column :issue_templates, :positio"
},
{
"path": "db/migrate/20121208150810_add_is_default_to_issue_templates.rb",
"chars": 232,
"preview": "class AddIsDefaultToIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n add_column :issue_templates, :is_def"
},
{
"path": "db/migrate/20130630141710_add_enabled_sharing_to_issue_templates.rb",
"chars": 247,
"preview": "class AddEnabledSharingToIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n add_column :issue_templates, :e"
},
{
"path": "db/migrate/20130701024625_add_inherit_templates_to_issue_template_settings.rb",
"chars": 289,
"preview": "class AddInheritTemplatesToIssueTemplateSettings < ActiveRecord::Migration[4.2]\n def self.up\n add_column :issue_temp"
},
{
"path": "db/migrate/2014020191500_add_should_replaced_to_issue_template_settings.rb",
"chars": 270,
"preview": "class AddShouldReplacedToIssueTemplateSettings < ActiveRecord::Migration[4.2]\n def self.up\n add_column :issue_templa"
},
{
"path": "db/migrate/20140307024626_create_global_issue_templates.rb",
"chars": 704,
"preview": "class CreateGlobalIssueTemplates < ActiveRecord::Migration[4.2]\n def change\n create_table :global_issue_templates do"
},
{
"path": "db/migrate/20140312054531_create_global_issue_templates_projects.rb",
"chars": 313,
"preview": "class CreateGlobalIssueTemplatesProjects < ActiveRecord::Migration[4.2]\n def self.up\n create_table :global_issue_tem"
},
{
"path": "db/migrate/20140330155030_remove_is_default_from_global_issue_templates.rb",
"chars": 179,
"preview": "class RemoveIsDefaultFromGlobalIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n remove_column :global_iss"
},
{
"path": "db/migrate/20160727222420_add_checklist_json_to_issue_templates.rb",
"chars": 225,
"preview": "class AddChecklistJsonToIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n add_column :issue_templates, :ch"
},
{
"path": "db/migrate/20160828190000_add_checklist_json_to_global_issue_templates.rb",
"chars": 245,
"preview": "class AddChecklistJsonToGlobalIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n add_column :global_issue_t"
},
{
"path": "db/migrate/20160829001500_change_issue_template_enabled_column.rb",
"chars": 256,
"preview": "class ChangeIssueTemplateEnabledColumn < ActiveRecord::Migration[4.2]\n def self.up\n change_column :issue_templates, "
},
{
"path": "db/migrate/20160829001530_change_global_issue_template_enabled_column.rb",
"chars": 276,
"preview": "class ChangeGlobalIssueTemplateEnabledColumn < ActiveRecord::Migration[4.2]\n def self.up\n change_column :global_issu"
},
{
"path": "db/migrate/20170317082100_add_is_default_to_global_issue_templates.rb",
"chars": 265,
"preview": "class AddIsDefaultToGlobalIssueTemplates < ActiveRecord::Migration[4.2]\n def self.up\n add_column :global_issue_templ"
},
{
"path": "db/migrate/20181104065200_add_unique_key_to_global_issue_templates_projects.rb",
"chars": 390,
"preview": "class AddUniqueKeyToGlobalIssueTemplatesProjects < ActiveRecord::Migration[4.2]\n def self.up\n add_index :global_issu"
},
{
"path": "db/migrate/20190303082102_create_note_templates.rb",
"chars": 744,
"preview": "class CreateNoteTemplates < ActiveRecord::Migration[5.1]\n def up\n create_table :note_templates do |t|\n t.string"
},
{
"path": "db/migrate/20190714171020_create_note_visible_roles.rb",
"chars": 493,
"preview": "# frozen_string_literal: true\n\nclass CreateNoteVisibleRoles < ActiveRecord::Migration[5.1]\n def up\n create_table :no"
},
{
"path": "db/migrate/20190714211530_add_visibility_to_note_templates.rb",
"chars": 257,
"preview": "# frozen_string_literal: true\n\nclass AddVisibilityToNoteTemplates < ActiveRecord::Migration[5.1]\n def self.up\n add_c"
},
{
"path": "db/migrate/20200101204020_add_related_link_to_issue_templates.rb",
"chars": 250,
"preview": "# frozen_string_literal: true\n\nclass AddRelatedLinkToIssueTemplates < ActiveRecord::Migration[5.2]\n def self.up\n add"
},
{
"path": "db/migrate/20200101204220_add_related_link_to_global_issue_templates.rb",
"chars": 270,
"preview": "# frozen_string_literal: true\n\nclass AddRelatedLinkToGlobalIssueTemplates < ActiveRecord::Migration[5.2]\n def self.up\n "
},
{
"path": "db/migrate/20200102204815_add_link_title_to_issue_templates.rb",
"chars": 244,
"preview": "# frozen_string_literal: true\n\nclass AddLinkTitleToIssueTemplates < ActiveRecord::Migration[5.2]\n def self.up\n add_c"
},
{
"path": "db/migrate/20200102205044_add_link_title_to_global_issue_templates.rb",
"chars": 264,
"preview": "# frozen_string_literal: true\n\nclass AddLinkTitleToGlobalIssueTemplates < ActiveRecord::Migration[5.2]\n def self.up\n "
},
{
"path": "db/migrate/20200103213630_add_builtin_fields_json_to_issue_templates.rb",
"chars": 239,
"preview": "class AddBuiltinFieldsJsonToIssueTemplates < ActiveRecord::Migration[5.2]\n def self.up\n add_column :issue_templates,"
},
{
"path": "db/migrate/20200115073600_add_builtin_fields_json_to_global_issue_templates.rb",
"chars": 259,
"preview": "class AddBuiltinFieldsJsonToGlobalIssueTemplates < ActiveRecord::Migration[5.2]\n def self.up\n add_column :global_iss"
},
{
"path": "db/migrate/20200314132500_change_column_note_template_description.rb",
"chars": 228,
"preview": "class ChangeColumnNoteTemplateDescription < ActiveRecord::Migration[5.2]\n def self.up\n change_column :note_templates"
},
{
"path": "db/migrate/20200405115700_create_global_note_templates.rb",
"chars": 758,
"preview": "# frozen_string_literal: true\n\nclass CreateGlobalNoteTemplates < ActiveRecord::Migration[5.1]\n def up\n create_table "
},
{
"path": "db/migrate/20200405120700_create_global_note_visible_roles.rb",
"chars": 562,
"preview": "# frozen_string_literal: true\n\nclass CreateGlobalNoteVisibleRoles < ActiveRecord::Migration[5.1]\n def up\n create_tab"
},
{
"path": "db/migrate/20200418114157_create_join_table_global_note_template_project.rb",
"chars": 328,
"preview": "class CreateJoinTableGlobalNoteTemplateProject < ActiveRecord::Migration[5.2]\n def change\n create_join_table :global"
},
{
"path": "docker-compose.yml",
"chars": 782,
"preview": "version: '3.2'\nservices:\n # start service for redmine with plugin\n # 1. $ docker-compose build --force-rm --no-cache\n "
},
{
"path": "goodcheck.yml",
"chars": 614,
"preview": "rules:\n - id: akiko.redmine.user_password\n pattern: 'FactoryBot.create(:user, :password_same_login, login:' \n mes"
},
{
"path": "init.rb",
"chars": 3386,
"preview": "# frozen_string_literal: true\n\n# Redmine Issue Template Plugin\n#\n# This is a plugin for Redmine to generate and use issu"
},
{
"path": "lang/en.yml",
"chars": 49,
"preview": "# English strings go here\r\nmy_label: \"My label\"\r\n"
},
{
"path": "lib/issue_templates/issues_hook.rb",
"chars": 3356,
"preview": "# To change this template, choose Tools | Templates\n# and open the template in the editor.\nmodule IssueTemplates\n class"
},
{
"path": "lib/issue_templates/journals_hook.rb",
"chars": 2046,
"preview": "# frozen_string_literal: true\n\n# To change this template, choose Tools | Templates\n# and open the template in the editor"
},
{
"path": "lib/tasks/test.rake",
"chars": 1005,
"preview": "require 'rake/testtask'\n\nnamespace :redmine_issue_templates do\n desc 'Run test for redmine_issue_template plugin.'\n ta"
},
{
"path": "lib/tasks/util.rake",
"chars": 969,
"preview": "namespace :redmine_issue_templates do\n desc 'Apply inhelit template setting to child projects.'\n task :apply_inhelit_t"
},
{
"path": "script/circleci-setup.sh",
"chars": 721,
"preview": "#!/bin/sh\ncd /tmp/\ngit clone --depth 1 -b $REDMINE_BRANCH https://github.com/redmine/redmine redmine\n\n# switch target ve"
},
{
"path": "spec/controllers/concerns/issue_templates_common_spec.rb",
"chars": 644,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../../spec_helper'\n\ndescribe 'IssueTemplatesCommon' do\n before do\n "
},
{
"path": "spec/controllers/global_issue_templates_controller_spec.rb",
"chars": 5299,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\nrequire File.expand_path(File.dirname(__FILE__) + '/../"
},
{
"path": "spec/controllers/issue_templates_controller_spec.rb",
"chars": 7972,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\nrequire File.expand_path(File.dirname(__FILE__) + '/../"
},
{
"path": "spec/controllers/settings_controller_spec.rb",
"chars": 1464,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\nrequire File.expand_path(File.dirname(__FILE__) + '/../"
},
{
"path": "spec/factories/enabled_modules.rb",
"chars": 112,
"preview": "FactoryBot.define do\n factory :enabled_module do\n project_id { 1 }\n name { 'issue_templates' }\n end\nend\n"
},
{
"path": "spec/factories/global_issue_templates.rb",
"chars": 675,
"preview": "FactoryBot.define do\n factory :global_issue_template do |t|\n association :tracker\n t.sequence(:title) { |n| \"glob"
},
{
"path": "spec/factories/global_note_templates.rb",
"chars": 673,
"preview": "FactoryBot.define do\n factory :global_note_template do |t|\n association :tracker\n t.sequence(:name) { |n| \"global"
},
{
"path": "spec/factories/issue_statuses.rb",
"chars": 168,
"preview": "FactoryBot.define do\n factory :issue_status do\n sequence(:name) { |n| \"status-name: #{n}\" }\n sequence(:positi"
},
{
"path": "spec/factories/issue_template_settings.rb",
"chars": 254,
"preview": "FactoryBot.define do\n factory :issue_template_setting do |t|\n association :project\n t.sequence(:help_message) { |"
},
{
"path": "spec/factories/issue_templates.rb",
"chars": 464,
"preview": "FactoryBot.define do\n factory :issue_template do |t|\n association :project\n association :tracker\n t.sequence(:"
},
{
"path": "spec/factories/projects.rb",
"chars": 646,
"preview": "FactoryBot.define do\n factory :project do\n sequence(:name) { |n| \"project-name: #{n}\" }\n sequence(:description) {"
},
{
"path": "spec/factories/role.rb",
"chars": 2488,
"preview": "# frozen_string_literal: true\n\nFactoryBot.define do\n factory :role do\n sequence(:name) { |n| \"Developer: #{n}\" }\n "
},
{
"path": "spec/factories/trackers.rb",
"chars": 349,
"preview": "FactoryBot.define do\n factory :tracker do\n sequence(:name) { |n| \"tracker-name: #{n}\" }\n sequence(:position) "
},
{
"path": "spec/factories/users.rb",
"chars": 876,
"preview": "# frozen_string_literal: true\n\nFactoryBot.define do\n factory :user do |u|\n # sequence -> exp. :login -> user1, user2"
},
{
"path": "spec/features/admin_spec.rb",
"chars": 1693,
"preview": "require_relative '../spec_helper'\nrequire_relative '../rails_helper'\nrequire_relative '../support/login_helper'\n\nRSpec.c"
},
{
"path": "spec/features/drag_and_drop_spec.rb",
"chars": 2796,
"preview": "# frozen_string_literal: true\n\nrequire File.expand_path(File.dirname(__FILE__) + '/../rails_helper')\nrequire File.expand"
},
{
"path": "spec/features/issue_template_popup_spec.rb",
"chars": 5365,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\nrequire_relative '../rails_helper'\nrequire_relative '.."
},
{
"path": "spec/features/issue_template_spec.rb",
"chars": 12709,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\nrequire_relative '../rails_helper'\nrequire_relative '.."
},
{
"path": "spec/features/update_issue_spec.rb",
"chars": 5583,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\nrequire_relative '../rails_helper'\nrequire_relative '.."
},
{
"path": "spec/helpers/issue_templates_helper_spec.rb",
"chars": 1837,
"preview": "require_relative '../spec_helper'\n\ndescribe IssueTemplatesHelper do\n describe '#project_tracker?' do\n let(:trackers)"
},
{
"path": "spec/models/global_issue_template_spec.rb",
"chars": 1290,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\n\ndescribe GlobalIssueTemplate do\n describe '#valid?' d"
},
{
"path": "spec/models/global_note_template_spec.rb",
"chars": 1072,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\n\ndescribe GlobalNoteTemplate do\n let(:tracker) { Facto"
},
{
"path": "spec/models/issue_template_setting_spec.rb",
"chars": 4336,
"preview": "require_relative '../spec_helper'\n\ndescribe IssueTemplateSetting do\n let(:project) { FactoryBot.create(:project) }\n le"
},
{
"path": "spec/models/issue_template_spec.rb",
"chars": 2892,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\n\ndescribe IssueTemplate do\n let(:tracker) { FactoryBot"
},
{
"path": "spec/models/note_visible_role_spec.rb",
"chars": 242,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\n\ndescribe NoteVisibleRole do\n let(:instance) { describ"
},
{
"path": "spec/rails_helper.rb",
"chars": 2419,
"preview": "# frozen_string_literal: true\n\n# This file is copied to spec/ when you run 'rails generate rspec:install'\nENV['RAILS_ENV"
},
{
"path": "spec/requests/global_note_templates_spec.rb",
"chars": 1452,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\nrequire File.expand_path(File.dirname(__FILE__) + '/../"
},
{
"path": "spec/requests/note_templates_spec.rb",
"chars": 1809,
"preview": "# frozen_string_literal: true\n\nrequire_relative '../spec_helper'\nrequire File.expand_path(File.dirname(__FILE__) + '/../"
},
{
"path": "spec/spec_helper.rb",
"chars": 910,
"preview": "require File.expand_path('../../../../config/environment', __FILE__)\nrequire 'rspec/rails'\nrequire 'simplecov'\nrequire '"
},
{
"path": "spec/support/controller_helper.rb",
"chars": 1158,
"preview": "module ControllerHelper\n # AuthHeader with api key (Ref.http://www.redmine.org/projects/redmine/wiki/Rest_api)\n def au"
},
{
"path": "spec/support/login_helper.rb",
"chars": 788,
"preview": "# frozen_string_literal: true\n\nmodule LoginHelper\n def log_user(login, password)\n visit '/login'\n\n within('#login"
},
{
"path": "test/fixtures/global_issue_templates.yml",
"chars": 930,
"preview": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\r\none:\r\n id: 1\r\n \r\n tracker_id: 1\r\n \r\n auth"
},
{
"path": "test/fixtures/global_issue_templates_projects.yml",
"chars": 170,
"preview": "global_issue_templates_projects_001:\r\n project_id: 1\r\n global_issue_template_id: 1\r\nglobal_issue_templates_projects_00"
},
{
"path": "test/fixtures/issue_template_settings.yml",
"chars": 417,
"preview": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\r\none:\r\n id: 1\r\n\r\n project_id: 1\r\n\r\n help_mes"
},
{
"path": "test/fixtures/issue_templates.yml",
"chars": 1222,
"preview": "# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html\r\none:\r\n id: 1\r\n\r\n project_id: 1\r\n \r\n tracke"
},
{
"path": "test/functional/global_issue_templates_controller_test.rb",
"chars": 3763,
"preview": "require File.expand_path('../test_helper', __dir__)\nrequire 'minitest/autorun'\n\nclass GlobalIssueTemplatesControllerTest"
},
{
"path": "test/functional/issue_templates_controller_test.rb",
"chars": 7962,
"preview": "require File.expand_path('../test_helper', __dir__)\nrequire 'minitest/autorun'\n\nclass IssueTemplatesControllerTest < Red"
},
{
"path": "test/functional/issue_templates_settings_controller_test.rb",
"chars": 2407,
"preview": "# frozen_string_literal: true\n\nrequire File.expand_path('../test_helper', __dir__)\n\nclass IssueTemplatesSettingsControll"
},
{
"path": "test/functional/issues_controller_test.rb",
"chars": 2482,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../test_helper')\nrequire 'issues_controller'\n\n# Test for view hooks."
},
{
"path": "test/functional/projects_controller_test.rb",
"chars": 717,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../test_helper')\nrequire 'projects_controller'\n\nclass ProjectsContro"
},
{
"path": "test/integration/layout_test.rb",
"chars": 1225,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../test_helper')\n\nclass LayoutTest < Redmine::IntegrationTest\n fixt"
},
{
"path": "test/test_helper.rb",
"chars": 1188,
"preview": "begin\n require 'simplecov'\n require 'simplecov-rcov'\nrescue LoadError => ex\n puts <<-\"EOS\"\n This test should be call"
},
{
"path": "test/unit/global_issue_templates_test.rb",
"chars": 896,
"preview": "require File.expand_path('../test_helper', __dir__)\n\nclass GlobalIssueTemplatesTest < ActiveSupport::TestCase\n fixtures"
},
{
"path": "test/unit/issue_template_setting_test.rb",
"chars": 1354,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../test_helper')\n\nclass IssueTemplateSettingTest < ActiveSupport::Te"
},
{
"path": "test/unit/issue_template_test.rb",
"chars": 1267,
"preview": "require File.expand_path(File.dirname(__FILE__) + '/../test_helper')\n\nclass IssueTemplateTest < ActiveSupport::TestCase\n"
},
{
"path": "test/unit/note_template_test.rb",
"chars": 2592,
"preview": "# frozen_string_literal: true\n\nrequire File.expand_path(File.dirname(__FILE__) + '/../test_helper')\n\nclass NoteTemplateT"
}
]
About this extraction
This page contains the full source code of the akiko-pusu/redmine_issue_templates GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 166 files (423.0 KB), approximately 112.0k tokens, and a symbol index with 382 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.