Redmine: View customize plugin の v1.2.0 をリリースしました

View customize plugin の v1.2.0 をリリースしました。2年ぶりの新バージョンになります。

リリース内容

今回のリリースには、2つの新規機能と細々とした変更がいくつか入っています。

  1. コードの挿入位置が選択できるように
  2. ユーザやプロジェクトの情報にJavaScriptでアクセス可能に
  3. ローカライズ対応 (日本語リソースの追加)
  4. 一覧をソート可能に
  5. コメント欄を追加し、一覧表示の際にコメントがあればそちらを表示するように (コメントが無かった時にコードを)
  6. View customizeのアイコンが表示されていなかった問題対処

以降はリリース内容の詳細です。

1. コードの挿入位置が選択できるように

今までView customizeでは、ヘッダ部分にコードを挿入していました。 それが1.2.0からは、下記の3パターンから選べるようになります。

  • Head of all pages (全てのページのヘッダ) ※v1.2.0より前と同じ
  • Bottom of issue form (チケット入力欄の下)
  • Bottom of issue detail (チケット詳細の下)

「Bottom of issue form」は、今まで嵌る人が多かった「チケット入力欄がトラッカーやステータスを変えた際に再構築されてしまい、View customizeでの変更内容がクリアされてしまう」といった問題に対応するためのものです。これを使うと、入力フォームが再構築される際にもコードが再度埋め込まれて実行されるので、今までのような考慮が不要になります。

なお、埋め込み箇所が存在しないページでは埋め込まれないことになるので、Path patternとの組み合わせにご注意ください。 たとえば、「Bottom of issue detail」はチケット詳細でしか埋め込まれないので、Path patternとして.*で全ページを指定していてもチケット詳細画面でのみ実行されるようになります。(Path patternで正規表現を細かく考えなくて済むので、それはそれで便利かと)

2. ユーザやプロジェクトの情報にJavaScriptでアクセス可能に

View customizeでは、画面にある情報以外にアクセスするのは大変でした。まったく参照するのが不可な情報も多いですし、出来たとしてもREST API叩いたり、スクレイピングしたり、、と面倒でした。

私自身も、ロールやグループの情報を使って適用する人を区別したいといったことがあり、それら情報にアクセスする手段として、ViewCustomize.contextといったオブジェクトを用意しました。

ユーザに紐づく情報として、ID、氏名以外にも、APIキー、グループ、ロール、カスタムフィールドといった情報に参照することができます。プロジェクトの情報としても識別子やロール、またチケットの情報としてIDを参照できるようにしました。 プロジェクトの識別子やチケットのIDは、今までも画面に存在する情報から取得可能でしたが、利用頻度が多いため、より直感的に書けるように、、ということで加えました。

オブジェクト全体のイメージは下記の通りです。

ViewCustomize = {
  "context": {
    "user": {
      "id": 1,
      "login": "admin",
      "admin": true,
      "firstname": "Redmine",
      "lastname": "Admin",
      "groups": [
        {"id": 5, "name": "Group1"}
      ],
      "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
    }
  }
}

追記@2018-10-20 user.roles は、Redmineのバージョンによってはエラーとなってしまっていたため、1.2.2にて削除しています。上記にも反映しました。

例えばユーザのAPIキーにアクセスするにはViewCustomize.context.user.apiKeyとなります。

3. ローカライズ対応 (日本語リソースの追加)

今回日本語リソースを追加し、ロケールとして日本語を選択しているユーザに対しては、日本語で表示されるようになりました。ずっと英語だったので、今まで使っていた方々には違和感を感じる人も多いかもしれませんが、きっと慣れてもらえると思います。(私も最初は違和感ありましたが、やっと慣れました)

母国語じゃない、、ってだけで、敷居をあげてしまうということは実際あるので、いつかやらなきゃな、、と思っていたのですが、今回Pull requestをもらったのもあって、入れることにしました。今後は他の言語も入れて行きたいと思っています。

その他

一覧系に関することで、下記の2点の修正を行っています。

  • 一覧をソート可能に
  • コメント欄を追加し、一覧表示の際にコメントがあればそちらを表示するように (コメントが無かった時にコードを)

コメント欄ですが、View customizeの設定が多くなってくると、内容を判断するための情報がコードの先頭部分だけだと厳しくなってきたため、コメント欄として別途設けることにしました。コメントが入力されていなかった場合には、今までどおりコードの先頭部分が表示されます。

f:id:onozaty:20181001000424p:plain

他は細かいBugfixなので、詳細は省略します。

最後に

今回の新しい機能の使用例を、次回のredmine.tokyoでお話させていただく予定です。

あと、もうすぐリリースされそうなRedime4に対する対応は、Redmine4がリリースされたらすぐに出す予定です。(対応方法は既に確認済みですので、大丈夫かと、、)

Redmineの検索欄に素早く移動する (ShortcutKey2URL)

人から聞いたチケット番号を元にチケットを開いたり、何かキーワードで検索したり、ってのが良くあるのですが、その際にすぐにRedmineの検索欄に飛べるように、ShortcutKey2URLという拡張機能を使っています。

ShortcutKey2URL

ShortcutKey2URLは、ショートカットキーを使用してURLを開いたり、移動したり、JavaScriptを実行できる拡張機能です。Chrome版とFirefox版があります。

スタートアップキーであらかじめ設定しておいた動作の一覧を表示し、次のキーでその動作を実行するような動きとなっています。

キーとして使用できる文字は1文字に限定されません。複数文字として設定しておくことが可能です。ShrotcutKey2URLは、キーとして連続して入力された文字から、対象が1つに絞り込まれた時点でその動作を実行します。

動作として設定できるものには、下記のようなものがあります。

  • URLへの移動。既に開いているURLの場合は、そのタブへ移動し、開かれていない場合には、新しいタブとして開く。
  • 新規タブとしてURLを開く。
  • 現在のタブにURLを開く。
  • 現在のタブで指定したJavaScriptを実行する。
  • 新規タブとしてURLを開いて、その後に指定したJavaScriptを実行する。

Redmineの検索欄に素早く移動する

ということで、Redmineの検索欄に素早く移動できるようにショートカットキーを設定します。

新しいタブでRedmineのページを開いて、その後にJavaScriptで検索欄にフォーカスを当てます。

document.getElementById('q').focus();

こんな感じの設定になります。(http://192.168.33.11/ がRedmineのURL)

f:id:onozaty:20180905005706p:plain

動作イメージは以下のような感じです。

f:id:onozaty:20180905010958g:plain

ShortcutKey2URLは他にもいろいろ使える場面があると思うので、ぜひご利用ください!!

RUANN - RUANN TOUR 2018 SUMMER "LOVE & HOPE" (2018年8月26日@新宿ReNY)

ずっと行きたかったRUANNのライブにやっといけました。嫁さんと一緒での参戦でした。

半分ぐらいの曲がギターでの弾き語りで、他の曲はダンスしながらと、とても元気なパフォーマンスを見せてくれました。

洋楽アーティストのライブみたいな感じをイメージしていたのですが、みんなで歌うって感じじゃなくて、みんな聴き入っている、、っていうのが多かったです。実際ギターの弾き語りはすごくよくて、自分も聴き入ってしまいました。

オリジナル曲の歌詞は、若い子向けかなってのもあって、ちょっと自分の世代(40代..)だと共感というより、娘はこんな感じなのかな(長女とRUANNは1歳違い)、、と思いながら聴く曲もあります。アンコールのときのMCは、実際に娘のことを考えながら聞いてしまい、ちょっと涙ぐんでしまいました。ほんと頑張って欲しい。応援してる!

洋楽のカバーもいくつか入れてきましたが、Lady Gaga の「Born This Way」は特に良かったです。英語の歌詞で力強く歌う声がすごくいい。RUANNのことを好きになったのも、この力強い声と、ギター1本でのパフォーマンスでした。

メジャーデビューも決まっているので、これからいろんな人がRUANNの存在に気がつくと思います。若いのに、、とかじゃなく、年齢関係なくすごいアーティストなので、これからのパフォーマンスがとても楽しみです。

セットリスト

  1. I Want You Back (Jackson 5)
  2. The Beautiful girl is about u
  3. Born This Way (Lady Gaga)
  4. Wherever you are (ONE OK ROCK)
  5. I AM STANDING
  6. TT (TWICE)
  7. 頑張る君へ
  8. instagram (DEAN)
  9. Perfect life
  10. Pinky World
  11. GET THE GLORY
  12. LOVE & HOPE
  13. (アンコール) I'm just walking without you
  14. (アンコール) The Beautiful girl is about u -TeddyLoid ver.-

ShortcutKey2URL(Firefox版)の 4.0.1 をリリースしました(クリップボードへの書き込みを許可)

4.0.1 を先ほどリリースしました。クリップボードへの書き込みを許可するようにしただけとなります。(Chrome版はもともと出来たのですが、Firefox版のほうだとPermissionが異なっていて、デフォルトだと許可されていませんでした)

現在開いているタブのタイトルとURLをクリップボードに書き込むスクリプトは下記のように書きます。(Action: Execute script として設定)

var copyUrl = (e) => {
  e.clipboardData.setData('text/plain', document.title + ' ' + location.href);
  e.preventDefault();
  document.removeEventListener('copy', copyUrl);
}

document.addEventListener('copy', copyUrl);
document.execCommand('copy');

copyイベントを発生させて、そのイベントハンドラ内でクリップボードの内容を書き換える、、といった書き方になります。(直接クリップボードを触りたいけど、許可されていないのでやもえない、、)

PostgreSQLのデータフォルダ(PGDATA)をtmpfsに置いてみる(Vagrant)

ユニットテスト用のPostgreSQLを立ち上げる際に、データフォルダ(PGDATA)をtmpfsに置けたらI/Oが早くなって、テスト時間短縮になるかなっておもって試してみました。テスト用ならば、シャットダウンでデータが消えてしまっても問題ないので。

Windows上で動かしたかったので、今回はVagrantでやりました。各種セットアップはAnsibleでやっています。

上記フォルダで、vagrant upとすると、CentOS7.3でPostgreSQL10のインストールを行い、tmpfsとしてマウントした/mnt/ram配下にデータフォルダを作成します。 また、testdbというDBを作成し、user1というユーザを作成しています。

pgbenchによるパフォーマンス測定

実際tmpfsにして早くなっているのか見るために、pgbenchを流してみます。

postgresql-contribをインストールします。

[root@localhost ~]# yum install postgresql10-contrib

テスト用のテーブルおよびデータを作成します。

[root@localhost ~]# /usr/pgsql-10/bin/pgbench -i testdb -U user1
Password:
NOTICE:  table "pgbench_history" does not exist, skipping
NOTICE:  table "pgbench_tellers" does not exist, skipping
NOTICE:  table "pgbench_accounts" does not exist, skipping
NOTICE:  table "pgbench_branches" does not exist, skipping
creating tables...
100000 of 100000 tuples (100%) done (elapsed 0.12 s, remaining 0.00 s)
vacuum...
set primary keys...
done.

10クライアントから1000回のトランザクションを発行します。

まずはtmpfsでは無い場合を試してみます。 (https://github.com/onozaty/sandbox/blob/master/postgresql/tmpfs/vars.ymlpostgresql_data_dirを削除すると、デフォルトのデータフォルダになります)

[root@localhost ~]# /usr/pgsql-10/bin/pgbench -c 10 -t 1000 testdb -U user1
Password:
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
latency average = 10.335 ms
tps = 967.558734 (including connections establishing)
tps = 967.906273 (excluding connections establishing)
[root@localhost ~]# /usr/pgsql-10/bin/pgbench -c 10 -t 1000 testdb -U user1
Password:
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
latency average = 10.013 ms
tps = 998.726630 (including connections establishing)
tps = 999.077213 (excluding connections establishing)

2回計りました。tps(1秒間に実行できたトランザクションの数)は900後半でした。

続いてtmpfsの場合。こちらも2回計ってみます。

[root@localhost ~]# /usr/pgsql-10/bin/pgbench -c 10 -t 1000 testdb -U user1
Password:
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
latency average = 7.276 ms
tps = 1374.364210 (including connections establishing)
tps = 1374.912095 (excluding connections establishing)
[root@localhost ~]# /usr/pgsql-10/bin/pgbench -c 10 -t 1000 testdb -U user1
Password:
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 1
query mode: simple
number of clients: 10
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
latency average = 7.619 ms
tps = 1312.520754 (including connections establishing)
tps = 1313.168002 (excluding connections establishing)

tpsは1300台でした。tmpfsにすることによって、1.3~1.4倍くらいの性能が出ています。ちなみにホストのストレージはSSDなので、これがもっと遅いストレージだと、もう少し差が大きくなるかもしれません。

おわりに

tmpfsにすることによってpgbenchでのパフォーマンスはあがりました。

ただ、tmpfsにしたために毎回起動時にinitdbから始めているので、その分余計な時間がかかることになります。トータルとして時間短縮の効果があるのかを判断しながら、使い分けてみようと思います。

ShortcutKey2URLのFirefox WebExtensions版をリリースしました

もともとFirefoxで提供していたShrotcutKey2URLという拡張機能ですが、WebExtensions版を実装するうえで課題となっていた部分がFirefox60で解決したので、やっとWebExtensions版をリリースすることが出来ました。

ShortcutKey2URL は、ショートカットキーを使用してURLを開いたり、移動したり、JavaScriptを実行できる拡張機能です。

スタートアップキー(デフォルトはCtrl+Period、MacはCommand+Period)であらかじめ設定しておいた動作の一覧を表示し、次のキーでその動作を実行します。この2段階動作が、ShortcutKey2URLの特徴です。

f:id:onozaty:20180529001824p:plain

キーとして設定しておける文字は1文字に限定されません。2文字以上で設定することも可能です。これによって、キーの自由度が高まります。たとえば、Googleのサービスは先頭1文字は"G"として、2文字目で各サービスを表すといったような、階層を持たせることができます。

また動作として設定できるものには、下記のようなものがあります。

  • URLへの移動。既に開いているURLの場合は、そのタブへ移動し、開かれていない場合には、新しいタブとして開く。
  • 新規タブとしてURLを開く。
  • 現在のタブにURLを開く。
  • 現在のタブで指定したJavaScriptを実行する。
  • 新規タブとしてURLを開いて、その後に指定したJavaScriptを実行する。

アドオンのIDはWebExtensions以前と同じものにしていますので、もしも古いものが入ったままで無効となっている人は、更新していただければ新しいもの(バージョン4.0.0)が入ります。なお、実装が大きく変わっていることもあり、設定は引き継がれません。申し訳ありません。

一部Firefox用に調整した部分もありますが、機能的には下記Chrome版と同じです。

Firefox 60 で解決したもの

ShortcutKey2URLのWebExtensions版を実装するうえで課題となっていたのは、下記の2つに関するものでした。

1番目は、browser actionで開いたポップアップウインドウにフォーカスが設定されないといった問題で、ShortcutKey2URLは、ポップアップウインドウ上でのキー入力を拾うようになっているため、これができないと先に進めない状態でした。

2番目は、拡張のショートカットキーを変更する仕組みです。ShortcutKey2URLの起動キーは自由に変えられないと使い勝手が悪すぎるので、とても重要な機能です。

なお、Chromeではショートカットキーを変更するUIがありますが、Firefoxはいったん上書きするAPIだけ提供されました。UIの部分は、下記で検討されています。

UI的なものを1から実装するのはかなり面倒なため、今回はPiroさんの下記ライブラリを利用させていただいています。ありがとうございます。

Elevator Saga にチャレンジしてみた & 自動実行できるようにした

Elevator Sagaが社内で再度話題になっていたので、いまさらながらですが、チャレンジしてみました。

Elevator Sagaは、エレベータを操作するプログラムをJavaScriptで書いて実行できるゲームです。全18面あって、クリアの条件が異なります。

f:id:onozaty:20180526123259p:plain

最終的なコードは下記になりました。アロー関数使ってたりするので、IEだと動かないです。

成功率は下記のような形となりました。各Challenge200回実行しています。同じChallengeでも実行毎に難易度がかなり異なる印象で、200回でも収束しているのかちょっと怪しい感じです。

All         :  84.03 (3025/3600)
Challenge  1: 100.00 (200/200)
Challenge  2:  83.50 (167/200)
Challenge  3:  96.50 (193/200)
Challenge  4: 100.00 (200/200)
Challenge  5:  93.00 (186/200)
Challenge  6: 100.00 (200/200)
Challenge  7:  95.00 (190/200)
Challenge  8:  99.00 (198/200)
Challenge  9:  99.50 (199/200)
Challenge 10:  58.50 (117/200)
Challenge 11:  97.00 (194/200)
Challenge 12:  86.50 (173/200)
Challenge 13:  37.50 (75/200)
Challenge 14:  45.00 (90/200)
Challenge 15:  95.00 (190/200)
Challenge 16: 100.00 (200/200)
Challenge 17:  86.50 (173/200)
Challenge 18:  40.00 (80/200)

上記はSeleniumで自動実行するプログラム作って検証しています。プログラムの評価するのに、ある程度繰り返し実行しないと判断できなかったので作りました。

書いてみてかなり楽しめました。ただ、これ以上良くする方法が今のところ思いついていないので、ぜひもっと良いアルゴリズム書けるぜ!!って方は教えてください。

自分の辿った考え方は下記にまとめてあるので、ご参考まで。