diff --git a/README.ja.md b/README.ja.md
new file mode 100644
index 0000000..7207927
--- /dev/null
+++ b/README.ja.md
@@ -0,0 +1,135 @@
+# Redmine view customize plugin
+
+[Redmine](http://www.redmine.org)の画面をカスタマイズするためのプラグインです。
+
+## 機能
+
+条件に一致した画面に対して、JavaScript、CSSを埋め込むことで、画面をカスタマイズします。
+
+## インストール方法
+
+Redmineのプラグインディレクトリに、このリポジトリを`view_customize`としてクローンします。
+
+ cd {RAILS_ROOT}/plugins
+ git clone https://github.com/onozaty/redmine-view-customize.git view_customize
+ cd ../
+ bundle exec rake redmine:plugins:migrate RAILS_ENV=production
+
+**注意: ディレクトリ名は`view_customize`とする必要があります。ディレクトリ名が異なると、プラグインの実行に失敗します。**
+
+## 使用方法
+
+### 追加
+
+プラグインをインストールすると、管理者メニューに「View customize」が追加されます。
+
+![Screenshot of admin menu](screenshots/admin.en.png)
+
+「View customize」を押下すると、一覧画面に遷移します。
+
+![Screenshot of list new](screenshots/list_new.en.png)
+
+「New view customize」を押下し、各種項目を入力します。
+
+![Screenshot of new](screenshots/new.en.png)
+
+「Path pattern」は正規表現で指定します。ページのパスと一致すると、コードを挿入して実行します。
+以下は設定例です。
+* `.*` : 全てのページ
+* `/issues$` : チケット一覧
+* `/issues/[0-9]+` : 個々のチケットの内容表示画面
+
+「Insertion position」は、コードの挿入位置です。v1.2.0にて追加された項目になります。
+* 「Head of all pages」 : 全てのページのヘッダ部分。(v1.2.0より前のバージョンと同じ位置)
+* 「Bottom of issue form」 : チケットの入力欄の下部。
+チケットの入力欄は、トラッカーやステータスを変えると再構成されますが、「Bottom of issue form」を指定しておくと再構成された際に再度実行されるので、入力欄に対する処理はこれを指定すると便利です。
+* 「Bottom of issue detail」 : チケットの詳細表示の下部。
+
+該当ページにコードの挿入位置に該当する箇所が無かった場合、コードは埋め込まれません。たとえば、「Path pattern」で`.*`で全ページを指定しても、「Insertion position」に「Bottom of issue detail」を指定していると、チケットの詳細表示画面でしか実行されないことになります。
+
+「Type」にてコードの種類(「JavaScript」または「CSS」)を選択し、「Code」に実際のコードを入力します。
+
+「Comment」にはカスタマイズに対する概要を記載できます。ここで入力した内容は、一覧表示で表示されます。(Commentが入力されていればComment、Commentが入力されていない場合はCodeが一覧に表示)
+
+「Create」ボタン押下で新規カスタマイズの追加が完了です。
+
+「Path pattern」に一致したページで指定のコードが実行され、画面がカスタマイズされるようになります。
+
+![Screenshot of example](screenshots/example.en.png)
+
+### 編集/削除
+
+![Screenshot of list edit](screenshots/list_edit.en.png)
+
+カスタマイズ一覧の番号を押下すると、カスタマイズ詳細画面へ遷移します。
+
+![Screenshot of detail](screenshots/detail.en.png)
+
+「Delete」を押下すると削除できます。「Edit」を押下すると、編集画面へ遷移します。
+
+入力項目は新規カスタマイズ作成時と同じです。
+
+### 無効化 / プライベート
+
+「Enabled」のチェックを外すと、無効化することができます。「Private」をチェックすると、作成者のみに有効となります。
+
+![Screenshot of enabled and private](screenshots/enable_private.en.png)
+
+まずは「Private」で動作確認したうえで、動作に問題なければ全体に公開するといった使い方ができます。
+
+### ViewCustomize.context (JavaScript)
+
+JavaScriptのコードでは、`ViewCustomize.context`としてユーザやプロジェクトの情報にアクセスすることができます。
+
+`ViewCustomize.context`の情報は下記のようなイメージです。
+
+```javascript
+ViewCustomize = {
+ "context": {
+ "user": {
+ "id": 1,
+ "login": "admin",
+ "admin": true,
+ "firstname": "Redmine",
+ "lastname": "Admin",
+ "groups": [
+ {"id": 5, "name": "Group1"}
+ ],
+ "roles": [ // ユーザに紐づく全てのロール(全プロジェクト)
+ {"id": 4, "name": "Developer"},
+ {"id": 6, "name": "RoleX"}
+ ],
+ "apiKey": "3dd35b5ad8456d90d21ef882f7aea651d367a9d8",
+ "customFields": [
+ {"id": 1, "name": "[Custom field] Text", "value": "text"},
+ {"id": 2, "name": "[Custom field] List", "value": ["B", "A"]},
+ {"id": 3, "name": "[Custom field] Boolean", "value": "1"}
+ ]
+ },
+ "project": {
+ "identifier": "project-a",
+ "name": "Project A",
+ "roles": [ // プロジェクト内でのロール
+ {"id": 6, "name": "RoleX"}
+ ]
+ },
+ "issue": {
+ "id": 1
+ }
+ }
+}
+```
+
+例えばユーザのAPIキーにアクセスするには`ViewCustomize.context.user.apiKey`となります。
+
+## 設定例
+
+* [onozaty/redmine\-view\-customize\-scripts: Script list for "Redmine View Customize Plugin"](https://github.com/onozaty/redmine-view-customize-scripts)
+
+## サポートバージョン
+
+* Redmine 2.0.x 以降
+
+## ライセンス
+
+このプラグインは [GNU General Public License](http://www.gnu.org/licenses/gpl-2.0.html) バージョン2またはそれ以降の条件で利用できます。
diff --git a/README.md b/README.md
index 7abd65f..888c463 100644
--- a/README.md
+++ b/README.md
@@ -1,52 +1,143 @@
-Redmine view customize plugin
-===========================
+# Redmine view customize plugin
This a plugin allows you to customize the view for the [Redmine](http://www.redmine.org).
-Features
-------------
+## Features
-By adding JavaScript or CSS to the matched path, a screen is made customizable.
+Customize the page by inserting JavaScript or CSS on the page that matched the condition.
-
-Installation
-------------
+## Installation
Install the plugin in your Redmine plugins directory, clone this repository as `view_customize`:
- cd {RAILS_ROOT}/plugins
- git clone https://github.com/onozaty/redmine-view-customize.git view_customize
- cd ../
- bundle exec rake redmine:plugins:migrate RAILS_ENV=production
+```
+cd {RAILS_ROOT}/plugins
+git clone https://github.com/onozaty/redmine-view-customize.git view_customize
+cd ../
+bundle exec rake redmine:plugins:migrate RAILS_ENV=production
+```
**note: The directory name must be a `view_customize`. Directory name is different, it will fail to run the Plugin.**
-Usage
-------------
-
-### Setting
-
-1. After you install the Plugin, "View customize" the administrator menu is added.
-![Screenshot of admin menu](screenshots/admin.png)
-![Screenshot of list](screenshots/list_new.png)
-2. Add a new setting.
-![Screenshot of new](screenshots/new.png)
-3. Path pattern is specified with a regular expression. (ex. /issues/[0-9]+)
-If there is a match with the path of the page, the code(JavaScript/StyleSheet) is executed.
-![Screenshot of new path pattern](screenshots/new_pathpattern.png)
-4. Input code.
-![Screenshot of new JavaScript](screenshots/new_javascript.png)
-![Screenshot of new StyleSheet](screenshots/new_stylesheet.png)
-5. Matches the path, StyleSheet or JavaScrpt is embedded, the screen display is changed.
-![Screenshot of view JavaScript](screenshots/view_javascript.png)
-![Screenshot of view StyleSheet](screenshots/view_stylesheet.png)
-
-Supported versions
-------------------
+## Usage
+
+### Add
+
+When installing the plugin, "View customize" is added to the administrator menu.
+
+![Screenshot of admin menu](screenshots/admin.en.png)
+
+Click "View customize" go to the list screen.
+
+![Screenshot of list new](screenshots/list_new.en.png)
+
+Click "New view customize" and enter items.
+
+![Screenshot of new](screenshots/new.en.png)
+
+"Path pattern" is specified by regular expression. If it matches the path of the page, insert the code and execute it.
+
+The following is an example.
+* `.*` : All pages
+* `/issues$` : Issue list
+* `/issues/[0-9]+` : Issue detail page
+
+"Insertion position" is the code insertion position. It becomes item added in v1.2.0.
+
+* "Head of all pages" (The same position as the version before v1.2.0)
+* "Bottom of issue form"
+Issue input fields are reconstructed when trackers or statuses are changed. If "Bottom of issue form" is specified, it will be executed again when reconstructed.
+* "Bottom of issue detail"
+
+If there is no part corresponding to the insertion position of the code on the page, the code is not insert.
+For example, even if you specify `.*` in "Path pattern", if "Bottom of issue detail" is specified for "Insertion position", it will be executed only on the issue detail page.
+
+In "Type", select the type of code ("JavaScript" or "CSS") and enter the actual code in "Code".
+
+For "Comment" you can put an overview on customization. The contents entered here are displayed in the list display.
+When "Comment" is entered, "Comment" is displayed on the list.
+If "Comment" is not entered, "Code" is displayed in the list.
+
+Addition is completed by clicking "Create" button.
+
+The specified code is executed on the page that matches "Path pattern", and the page will be customized.
+
+![Screenshot of example](screenshots/example.en.png)
+
+### Edit / Delete
+
+![Screenshot of list edit](screenshots/list_edit.en.png)
+
+When you click the number of the customize list, go to the detail page.
+
+![Screenshot of detail](screenshots/detail.en.png)
+
+You can delete it by clicking "Delete".
+
+Click "Edit" to switch to the edit page.
+The input item is the same as when creating a new one.
+
+### Disable / Private
+
+You can disable it by unchecking "Enabled". If you check "Private", it will be enable only for the author.
+
+![Screenshot of enabled and private](screenshots/enable_private.en.png)
+
+If you check the operation with "Private" and there is no problem in operation, it will be good to release it to the all.
+
+### ViewCustomize.context (JavaScript)
+
+You can access information on users and projects using `ViewCustomize.context`.
+
+`ViewCustomize.context` is as follows.
+
+```javascript
+ViewCustomize = {
+ "context": {
+ "user": {
+ "id": 1,
+ "login": "admin",
+ "admin": true,
+ "firstname": "Redmine",
+ "lastname": "Admin",
+ "groups": [
+ {"id": 5, "name": "Group1"}
+ ],
+ "roles": [ // All roles associated with users (all projects)
+ {"id": 4, "name": "Developer"},
+ {"id": 6, "name": "RoleX"}
+ ],
+ "apiKey": "3dd35b5ad8456d90d21ef882f7aea651d367a9d8",
+ "customFields": [
+ {"id": 1, "name": "[Custom field] Text", "value": "text"},
+ {"id": 2, "name": "[Custom field] List", "value": ["B", "A"]},
+ {"id": 3, "name": "[Custom field] Boolean", "value": "1"}
+ ]
+ },
+ "project": {
+ "identifier": "project-a",
+ "name": "Project A",
+ "roles": [ // Roles in the project
+ {"id": 6, "name": "RoleX"}
+ ]
+ },
+ "issue": {
+ "id": 1
+ }
+ }
+}
+```
+
+For example, to access the user's API key is `ViewCustomize.context.user.apiKey`.
+
+## Examples
+
+* [onozaty/redmine\-view\-customize\-scripts: Script list for "Redmine View Customize Plugin"](https://github.com/onozaty/redmine-view-customize-scripts)
+
+## Redmine 2.0.x or later
* Redmine 2.0.x or later
-License
--------
+## License
The plugin is available under the terms of the [GNU General Public License](http://www.gnu.org/licenses/gpl-2.0.html), version 2 or later.
diff --git a/app/controllers/view_customizes_controller.rb b/app/controllers/view_customizes_controller.rb
index 89113bc..d1da765 100644
--- a/app/controllers/view_customizes_controller.rb
+++ b/app/controllers/view_customizes_controller.rb
@@ -6,8 +6,13 @@ class ViewCustomizesController < ApplicationController
before_filter :require_admin
before_filter :find_view_customize, :except => [:index, :new, :create]
+ helper :sort
+ include SortHelper
+
def index
- @view_customizes = ViewCustomize.all
+ sort_init 'id', 'desc'
+ sort_update %w(id path_pattern insertion_position customize_type code comments is_enabled is_private)
+ @view_customizes = ViewCustomize.all.order(sort_clause)
end
def new
diff --git a/app/models/view_customize.rb b/app/models/view_customize.rb
index 41a4006..95b39ba 100644
--- a/app/models/view_customize.rb
+++ b/app/models/view_customize.rb
@@ -1,5 +1,3 @@
-
-
class ViewCustomize < ActiveRecord::Base
unloadable
@@ -14,28 +12,46 @@ class ViewCustomize < ActiveRecord::Base
attr_protected :id
- TYPE_JAVASCRIPT = 1
- TYPE_STYLESHEET = 2
+ TYPE_JAVASCRIPT = "javascript"
+ TYPE_CSS = "css"
@@customize_types = {
- "JavaScript" => TYPE_JAVASCRIPT,
- "StyleSheet" => TYPE_STYLESHEET
+ :label_javascript => TYPE_JAVASCRIPT,
+ :label_css => TYPE_CSS
+ }
+
+ INSERTION_POSITION_HTML_HEAD = "html_head"
+ INSERTION_POSITION_ISSUE_FORM = "issue_form"
+ INSERTION_POSITION_ISSUE_SHOW = "issue_show"
+
+ @@insertion_positions = {
+ :label_insertion_position_html_head => INSERTION_POSITION_HTML_HEAD,
+ :label_insertion_position_issue_form => INSERTION_POSITION_ISSUE_FORM,
+ :label_insertion_position_issue_show => INSERTION_POSITION_ISSUE_SHOW
}
def customize_types
@@customize_types
end
- def customize_type_name
+ def customize_type_label
@@customize_types.key(customize_type)
end
+ def insertion_positions
+ @@insertion_positions
+ end
+
+ def insertion_position_label
+ @@insertion_positions.key(insertion_position)
+ end
+
def is_javascript?
customize_type == TYPE_JAVASCRIPT
end
- def is_stylesheet?
- customize_type == TYPE_STYLESHEET
+ def is_css?
+ customize_type == TYPE_CSS
end
def available?(user=User.current)
diff --git a/app/views/view_customizes/_form.html.erb b/app/views/view_customizes/_form.html.erb
index ae718ec..223bc85 100644
--- a/app/views/view_customizes/_form.html.erb
+++ b/app/views/view_customizes/_form.html.erb
@@ -8,14 +8,26 @@
<%= l(:text_path_pattern_match_info) %>
+ <%= form.select :insertion_position, + options_for_select( + @view_customize.insertion_positions.map {|key, val| [l(key), val]}, + :selected => @view_customize.insertion_position), + :required => true %> +
<%= form.select :customize_type, - options_for_select(@view_customize.customize_types, :selected => @view_customize.customize_type), - :required => true %> + options_for_select( + @view_customize.customize_types.map {|key, val| [l(key), val]}, + :selected => @view_customize.customize_type), + :required => true %>
<%= form.text_area :code, - :required => true, :rows => 12 %> + :required => true, :rows => 12 %> +
++ <%= form.text_field :comments, :size => 100 %>
<%= form.check_box :is_enabled %> diff --git a/app/views/view_customizes/_header.html.erb b/app/views/view_customizes/_header.html.erb deleted file mode 100644 index 1747646..0000000 --- a/app/views/view_customizes/_header.html.erb +++ /dev/null @@ -1 +0,0 @@ -<%= stylesheet_link_tag "view_customize.css", :plugin => 'view_customize' %> diff --git a/app/views/view_customizes/edit.html.erb b/app/views/view_customizes/edit.html.erb index 533d690..9a4878c 100644 --- a/app/views/view_customizes/edit.html.erb +++ b/app/views/view_customizes/edit.html.erb @@ -1,5 +1,3 @@ -<%= render :partial => 'view_customizes/header' %> - <%= title [l(:label_view_customize_plural), view_customizes_path], @view_customize.id %> <%= labelled_form_for :view_customize, @view_customize, diff --git a/app/views/view_customizes/index.html.erb b/app/views/view_customizes/index.html.erb index 3d23c8c..bc854a6 100644 --- a/app/views/view_customizes/index.html.erb +++ b/app/views/view_customizes/index.html.erb @@ -1,5 +1,3 @@ -<%= render :partial => 'view_customizes/header' %> -
<%= l(:label_no_data) %>
<% else %> -# | -<%=h l(:field_path_pattern) %> | -<%=h l(:field_customize_type) %> | -<%=h l(:field_code) %> | -<%=h l(:field_is_enabled) %> | -<%=h l(:field_is_private) %> | - + <%= sort_header_tag('id', :caption => '#') %> + <%= sort_header_tag('path_pattern', :caption => l(:field_path_pattern)) %> + <%= sort_header_tag('insertion_position', :caption => l(:field_insertion_position)) %> + <%= sort_header_tag('customize_type', :caption => l(:field_customize_type)) %> + <%= sort_header_tag('comments', :caption => l(:field_comments) + ' / ' + l(:field_code)) %> + <%= sort_header_tag('is_private', :caption => l(:field_is_private)) %>|||
---|---|---|---|---|---|---|---|---|
<%= link_to view_customize.id, view_customize_path(view_customize.id) %> | <%=h view_customize.path_pattern %> | -<%=h view_customize.customize_type_name %> | -<%=h truncate(view_customize.code, :length => 80) %> | -<%=h view_customize.is_enabled ? l(:general_text_yes) : l(:general_text_no) %> | +<%=h l(view_customize.insertion_position_label) %> | +<%=h l(view_customize.customize_type_label) %> | +<%=h view_customize.comments.present? ? view_customize.comments : truncate(view_customize.code, :length => 80) %> | <%=h view_customize.is_private ? l(:general_text_yes) : l(:general_text_no) %> | -<%=h l(:field_path_pattern) %>: | <%=h @view_customize.path_pattern %> | +
<%=h l(:field_insertion_position) %>: | +<%=h l(@view_customize.insertion_position_label) %> | +|||||||
<%=h l(:field_customize_type) %>: | -<%=h @view_customize.customize_type_name %> | +<%=h l(@view_customize.customize_type_label) %> | ||||||
<%=h l(:field_code) %>: | <%= highlight_by_language( - @view_customize.code, @view_customize.customize_type == 1 ? :js : :css) %> | + @view_customize.code, @view_customize.is_javascript? ? :js : :css) %> +|||||||
<%=h l(:field_comments) %>: | +<%=h @view_customize.comments %> | |||||||
<%=h l(:field_is_enabled) %>: | diff --git a/assets/images/view_customize.png b/assets/images/view_customize.png new file mode 100644 index 0000000..106f5aa Binary files /dev/null and b/assets/images/view_customize.png differ diff --git a/assets/stylesheets/view_customize.css b/assets/stylesheets/view_customize.css index ce10904..509cccf 100644 --- a/assets/stylesheets/view_customize.css +++ b/assets/stylesheets/view_customize.css @@ -1,24 +1,31 @@ -table.list td.code, table.list td.path { +table.view_customize.list td.path, table.view_customize.list td.comments { text-align: left; + word-break: break-word; + overflow-wrap: break-word; + word-wrap : break-word; } -table.list td.id { - min-width: 40px; +table.view_customize.list td.id { + padding-left: 5px; } -table.list tr.disable { +table.view_customize.list td.insertion_position { + white-space: nowrap; +} + +table.view_customize.list tr.disable { color: #aaaaaa; } -table.list tr.private { +table.view_customize.list tr.private { font-style: italic; } -table.view_customize { +table.view_customize.box { width: 100%; } -table.view_customize th { +table.view_customize.box th { text-align: right; vertical-align: top; width: 10%; @@ -26,11 +33,11 @@ table.view_customize th { white-space: nowrap; } -table.view_customize td { +table.view_customize.box td { vertical-align: top; } -table.view_customize td pre { +table.view_customize.box td pre { margin: 0; padding: 2px 4px; background-color: #FFFFFF; @@ -42,6 +49,10 @@ textarea#view_customize_code { width: 95%; } -#admin-menu a.view_customize { - background-image: url("../images/server_key.png"); +input#view_customize_comments { + width: 95%; +} + +.icon-view_customize { + background-image: url("../images/view_customize.png"); } diff --git a/config/locales/en.yml b/config/locales/en.yml index dd7db9b..413a775 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -3,11 +3,18 @@ en: label_view_customize: "View customize" label_view_customize_plural: "View customizes" label_view_customizes_new: "New view customize" + label_javascript: "JavaScript" + label_css: "CSS" + label_insertion_position_html_head: "Head of all pages" + label_insertion_position_issue_form: "Bottom of issue form" + label_insertion_position_issue_show: "Bottom of issue detail" field_path_pattern: "Path pattern" + field_insertion_position: "Insertion position" field_customize_type: "Type" field_code: "Code" + field_comments: "Comment" field_is_private: "Private" field_is_enabled: "Enabled" field_author: "Author" text_path_pattern_info: "Path pattern is specified with a regular expression. (ex. /issues/[0-9]+)" - text_path_pattern_match_info: "If there is a match with the path of the page, the following code is executed." + text_path_pattern_match_info: "If there is a match with the path of the page, insert the following code and execute it." diff --git a/config/locales/ja.yml b/config/locales/ja.yml new file mode 100644 index 0000000..b71e9ec --- /dev/null +++ b/config/locales/ja.yml @@ -0,0 +1,19 @@ +ja: + label_view_customize: "表示のカスタマイズ" + label_view_customize_plural: "表示のカスタマイズ" + label_view_customizes_new: "新しい表示のカスタマイズ" + label_javascript: "JavaScript" + label_css: "CSS" + label_insertion_position_html_head: "全てのページのヘッダ" + label_insertion_position_issue_form: "チケット入力欄の下" + label_insertion_position_issue_show: "チケット詳細の下" + field_path_pattern: "パスのパターン" + field_insertion_position: "挿入位置" + field_customize_type: "種別" + field_code: "コード" + field_comments: "コメント" + field_is_private: "プライベート" + field_is_enabled: "有効" + field_author: "作成者" + text_path_pattern_info: "パスのパターンは正規表現で指定します。 (例 /issues/[0-9]+)" + text_path_pattern_match_info: "ページのパスが一致した場合、以下のコードを挿入し、実行します。" diff --git a/db/migrate/003_add_insertion_position_to_view_customizes.rb b/db/migrate/003_add_insertion_position_to_view_customizes.rb new file mode 100644 index 0000000..b7bed77 --- /dev/null +++ b/db/migrate/003_add_insertion_position_to_view_customizes.rb @@ -0,0 +1,27 @@ +class AddInsertionPositionToViewCustomizes < ActiveRecord::Migration + def up + add_column :view_customizes, :insertion_position, :string, :null => false, :default => "html_head" + + rename_column :view_customizes, :customize_type, :customize_type_old + add_column :view_customizes, :customize_type, :string, :null => false, :default => "javascript" + ActiveRecord::Base.connection.execute( + "UPDATE view_customizes SET customize_type = 'css' WHERE customize_type_old = 2") + remove_column :view_customizes, :customize_type_old + + change_column_null :view_customizes, :path_pattern, false + change_column_null :view_customizes, :code, false + end + + def down + change_column_null :view_customizes, :path_pattern, true + change_column_null :view_customizes, :code, true + + rename_column :view_customizes, :customize_type, :customize_type_new + add_column :view_customizes, :customize_type, :integer, :default => 1 + ActiveRecord::Base.connection.execute( + "UPDATE view_customizes SET customize_type = 1 WHERE customize_type_new = 'css'") + remove_column :view_customizes, :customize_type_new + + remove_column :view_customizes, :insertion_position + end +end diff --git a/db/migrate/004_add_comments_to_view_customizes.rb b/db/migrate/004_add_comments_to_view_customizes.rb new file mode 100644 index 0000000..e14024e --- /dev/null +++ b/db/migrate/004_add_comments_to_view_customizes.rb @@ -0,0 +1,9 @@ +class AddCommentsToViewCustomizes < ActiveRecord::Migration + def up + add_column :view_customizes, :comments, :string, :null => true + end + + def down + remove_column :view_customizes, :comments + end +end diff --git a/init.rb b/init.rb index dfd84c1..39e702b 100644 --- a/init.rb +++ b/init.rb @@ -1,17 +1,17 @@ -require_dependency 'view_customize/view_layouts_base_html_head_hook' +require_dependency 'view_customize/view_hook' Redmine::Plugin.register :view_customize do name 'View Customize plugin' author 'onozaty' description 'View Customize plugin for Redmine' - version '1.1.4' + version '1.2.0' url 'https://github.com/onozaty/redmine-view-customize' author_url 'https://github.com/onozaty' menu :admin_menu, :view_customizes, { :controller => 'view_customizes', :action => 'index' }, :caption => :label_view_customize, - :html => { :class => 'settings'}, + :html => { :class => 'icon icon-view_customize'}, :if => Proc.new { User.current.admin? } end diff --git a/lib/view_customize/view_hook.rb b/lib/view_customize/view_hook.rb new file mode 100644 index 0000000..85df8f7 --- /dev/null +++ b/lib/view_customize/view_hook.rb @@ -0,0 +1,100 @@ +module RedmineViewCustomize + class ViewHook < Redmine::Hook::ViewListener + def view_layouts_base_html_head(context={}) + + path = context[:request].path_info; + + html = "\n\n" + html << stylesheet_link_tag("view_customize", plugin: "view_customize") + html << "" + + html << create_view_customize_html(path, ViewCustomize::INSERTION_POSITION_HTML_HEAD) + + return html + end + + def view_issues_form_details_bottom(context={}) + + return create_view_customize_html(context[:request].path_info, ViewCustomize::INSERTION_POSITION_ISSUE_FORM) + end + + def view_issues_show_details_bottom(context={}) + + html = "" + + html << create_view_customize_html(context[:request].path_info, ViewCustomize::INSERTION_POSITION_ISSUE_SHOW) + + return html + end + + private + + def create_view_customize_html(path, insertion_position) + + view_customize_html_parts = match_customize(path, insertion_position).map {|item| + to_html(item) + } + return view_customize_html_parts.join("\n").html_safe + + end + + def match_customize(path, insertion_position) + + ViewCustomize.all.select {|item| + item.available? \ + && item.insertion_position == insertion_position \ + && path =~ Regexp.new(item.path_pattern) + } + end + + def to_html(view_customize) + + html = "\n" + + if view_customize.is_javascript? + html << "" + elsif view_customize.is_css? + html << "" + end + + return html + end + + def create_view_customize_context(view_hook_context) + + user = User.current + context = { + "user" => { + "id" => user.id, + "login" => user.login, + "admin" => user.admin?, + "firstname" => user.firstname, + "lastname" => user.lastname, + "groups" => user.groups.map {|group| { "id" => group.id, "name" => group.name }}, + "roles" => user.roles.map {|role| { "id" => role.id, "name" => role.name }}, + "apiKey" => (user.api_token.value unless user.api_token.nil?), + "customFields" => user.custom_field_values.map {|field| { "id" => field.custom_field.id, "name" => field.custom_field.name, "value" => field.value }} + } + } + + project = view_hook_context[:project] + if project + context["project"] = { + "identifier" => project.identifier, + "name" => project.name, + "roles" => user.roles_for_project(project).map {|role| { "id" => role.id, "name" => role.name }} + } + end + + return context + end + end +end diff --git a/lib/view_customize/view_layouts_base_html_head_hook.rb b/lib/view_customize/view_layouts_base_html_head_hook.rb deleted file mode 100644 index b29875d..0000000 --- a/lib/view_customize/view_layouts_base_html_head_hook.rb +++ /dev/null @@ -1,39 +0,0 @@ -module RedmineViewCustomize - class ViewLayoutsBaseHtmlHeadHook < Redmine::Hook::ViewListener - def view_layouts_base_html_head(context={}) - - view_customize_html_parts = match_customize(context[:request].path_info).map {|item| - html(item) - } - - return "\n" + - view_customize_html_parts.join("\n").html_safe - end - - private - - def match_customize(path) - - ViewCustomize.all.select {|item| - item.available? && path =~ Regexp.new(item.path_pattern) - } - end - - def html(view_customize) - - html = "\n" - - if view_customize.is_javascript? then - html << "" - elsif view_customize.is_stylesheet? then - html << "" - end - - return html - end - end -end diff --git a/screenshots/admin.en.png b/screenshots/admin.en.png new file mode 100644 index 0000000..36f0b4d Binary files /dev/null and b/screenshots/admin.en.png differ diff --git a/screenshots/admin.png b/screenshots/admin.png deleted file mode 100644 index ad910ad..0000000 Binary files a/screenshots/admin.png and /dev/null differ diff --git a/screenshots/detail.en.png b/screenshots/detail.en.png new file mode 100644 index 0000000..98fa619 Binary files /dev/null and b/screenshots/detail.en.png differ diff --git a/screenshots/enable_private.en.png b/screenshots/enable_private.en.png new file mode 100644 index 0000000..117803f Binary files /dev/null and b/screenshots/enable_private.en.png differ diff --git a/screenshots/example.en.png b/screenshots/example.en.png new file mode 100644 index 0000000..8bb3a26 Binary files /dev/null and b/screenshots/example.en.png differ diff --git a/screenshots/list_edit.en.png b/screenshots/list_edit.en.png new file mode 100644 index 0000000..a69e47d Binary files /dev/null and b/screenshots/list_edit.en.png differ diff --git a/screenshots/list_new.en.png b/screenshots/list_new.en.png new file mode 100644 index 0000000..0d33473 Binary files /dev/null and b/screenshots/list_new.en.png differ diff --git a/screenshots/list_new.png b/screenshots/list_new.png deleted file mode 100644 index 0aa3492..0000000 Binary files a/screenshots/list_new.png and /dev/null differ diff --git a/screenshots/new.en.png b/screenshots/new.en.png new file mode 100644 index 0000000..067a334 Binary files /dev/null and b/screenshots/new.en.png differ diff --git a/screenshots/new.png b/screenshots/new.png deleted file mode 100644 index 714f441..0000000 Binary files a/screenshots/new.png and /dev/null differ diff --git a/screenshots/new_javascript.png b/screenshots/new_javascript.png deleted file mode 100644 index 093e66f..0000000 Binary files a/screenshots/new_javascript.png and /dev/null differ diff --git a/screenshots/new_pathpattern.png b/screenshots/new_pathpattern.png deleted file mode 100644 index bb7560a..0000000 Binary files a/screenshots/new_pathpattern.png and /dev/null differ diff --git a/screenshots/new_stylesheet.png b/screenshots/new_stylesheet.png deleted file mode 100644 index 071f8b3..0000000 Binary files a/screenshots/new_stylesheet.png and /dev/null differ diff --git a/screenshots/view_javascript.png b/screenshots/view_javascript.png deleted file mode 100644 index d280f39..0000000 Binary files a/screenshots/view_javascript.png and /dev/null differ diff --git a/screenshots/view_stylesheet.png b/screenshots/view_stylesheet.png deleted file mode 100644 index 2b287b6..0000000 Binary files a/screenshots/view_stylesheet.png and /dev/null differ