master 86fbfc17eb92 cached
166 files
423.0 KB
112.0k tokens
382 symbols
1 requests
Download .txt
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

[![Plugin info at redmine.org](https://img.shields.io/badge/Redmine-plugin-green.svg?)](http://www.redmine.org/plugins/redmine_issue_templates)
[![CircleCI](https://circleci.com/gh/akiko-pusu/redmine_issue_templates/tree/master.svg?style=shield)](https://circleci.com/gh/akiko-pusu/redmine_issue_templates/tree/master)
[![Sider](https://img.shields.io/badge/Special%20Thanks!-Sider-blue.svg?)](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="#">&times;</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="#">&times;</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),
                       
Download .txt
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
Download .txt
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[![Plugin info at redmine.org](https://img.shields.io/badge/Redmine-plugin-green.svg?)"
  },
  {
    "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.

Copied to clipboard!