View customize plugin の v2.2.0 をリリースしました。
Easy Redmineへの対応となります。
View customize plugin の v2.2.0 をリリースしました。
Easy Redmineへの対応となります。
CSVファイルをPostgreSQLにロードするツールを作りました。
事前にテーブルを作っておく必要は無いので、とりあえずCSVファイルをPostgreSQLにロードしていじりたいって時に便利かと思います。
テーブルはCSVのヘッダに記載のフィールド名を元に作成されます。なお、既にテーブルがある場合は作りません。
内部的にはCOPYコマンドを使っているので、とても早いと思います。(もともとバッチINSERTを使った実装をしていましたが、COPYコマンド使うように変えたら50倍早くなりました)
実行にはJava(JDK8以上)が必要となります。
下記から最新の実行ファイル(csv2postgresql-x.x.x-all.jar
)を入手します。
入手したjarファイルを指定してアプリケーションを実行します。
java -jar csv2postgresql-1.0.0-all.jar config.properties table1 data.csv
引数は下記の通りです。
実行すると、下記のように処理したレコード件数、かかった時間が出力されます。
Loading... Loading is completed. (Number of records: 100,000 / Elapsed millsecods: 322)
設定ファイルには、PostgreSQLの接続先情報と、CSVファイルのエンコーディングを記載します。
database.url
JDBC接続URLdatabase.user
DBユーザ名database.password
DBパスワードcsv.encoding
CSVファイルのエンコーディング以下は例です。
database.url=jdbc:postgresql://192.168.33.10:5432/testdb database.user=user1 database.password=pass1 csv.encoding=UTF-8
ロード先のテーブル名を指定します。
テーブルが存在しなかった場合、新規にテーブルを作成します。この際、各カラムはtext
型として作成されます。
CSVファイルのヘッダは必須です。ヘッダに記載のフィールド名を使って、ロード先のテーブルのカラムとマッピングします。
なお、英数字以外の文字が指定されていた場合、アンダースコア(_
)に置換されます。
たとえばUser Name
というフィールドがあった場合、データベースのカラムとしてはuser_name
にマッピングされます。
PostgreSQLを起動するためのVagrant環境と、設定ファイルとCSVファイルのサンプルが用意してあります。 これらを使うことによって、簡単に本ツールを試せます。
vagrant
フォルダにてvagrant up
を実行すると、PostgreSQL11をインストールした仮想環境(192.168.33.10)が立ち上がります。
sample
フォルダ配下の設定ファイルとCSVファイルを利用してロードを行います。
java -jar csv2postgresql-1.0.0-all.jar sample/config.properties test_table sample/sample-100000.csv
ソースコードからビルドして利用する場合、Java(JDK8以上)がインストールされた環境で、下記コマンドでアプリケーションをビルドします。
gradlew shadowJar
build/libs/csv2postgresql-x.x.x-all.jar
という実行ファイルが出来上がります。(x.x.x
はバージョン番号)
Ed Sheeran(エド・シーラン)のライブに嫁さんと一緒に参戦してきました。
15時過ぎに東京ドームについて、まずは物販からということで、Tシャツとタオルをを購入。物販は10分程度並んだだけで、そんな待たずに買えました。
席は1階スタンドです。ステージから真正面ですが遠いです。S席の範囲がとても広く、どこになるかは運任せなのでしょうがないですね。
17時45分からオープニングアクトでONE OK ROCKです。チケット購入した後に発表されたオープニングアクトですが、ワンオクも聞けるなんて、、すごい得した気分です。エド・シーランと交流があるのは有名な話だったので、もしかしたらなーって思っていたけど、まさか本当にそうなるなんて!!
狭いステージを動き回るTakaかっこいい。
オープニングアクトは45分くらいで終わり、19時からエド・シーランのライブ開始です。
ギターとループステーションだけでライブやりきってしまうというのは知っていましたが、いや、ほんと凄すぎました。ループステーションを使ってどんどん音を重ねていって、歌いながらプラスしてさらにギター、、エド・シーラン一人によってすごい複雑な音楽が作り出されます。
特に最後のYou Need Me, I Don’t Need Youは圧巻で、鳥肌が立ちました。ほんと最高のライブでした。
チケットを作成して、関連付けを行いたいという問い合わせがあったので書いてみました。
チケットの関連付けには下記のAPIを使います。
.*
Bottom of issue detail
$(function() { var projectId = $('#issue_project_id').val(); var trackerId = $('#issue_tracker_id').val(); var subject = $('#issue_subject').val(); var priorityId = $('#issue_priority_id').val(); var currentIssueId = ViewCustomize.context.issue.id; // 関連チケットとして作成する情報 var issueChildren = [ { 'issue': { 'project_id': projectId, 'tracker_id': trackerId, 'subject': subject + ' - 関連チケット1', 'priority_id': priorityId } }, { 'issue': { 'project_id': projectId, 'tracker_id': trackerId, 'subject': subject + ' - 関連チケット2', 'priority_id': priorityId } }, { 'issue': { 'project_id': projectId, 'tracker_id': trackerId, 'subject': subject + ' - 関連チケット3', 'priority_id': priorityId } } ]; var link = $('<a title="関連チケットの一括作成" class="icon icon-add" href="#">関連チケットの一括作成</a>'); $('#issue_tree').before($('<p>').append(link)); link.on('click', function() { if (!confirm('関連チケットをまとめて作成します。よろしいですか。')) { return; } // チケット作成処理(非同期)を順次実行し、最後にリロード var defer = $.Deferred(); var promise = defer.promise(); for (var i = 0; i < issueChildren.length; i++) { promise = promise.then(createIssue(issueChildren[i])); } promise .done(function() { // 成功したらリロード location.reload(); }) .fail(function() { alert('失敗しました'); }); defer.resolve(); }); function createIssue(issue) { return function() { return $.ajax({ type: 'POST', url: '/issues.json', headers: { 'X-Redmine-API-Key': ViewCustomize.context.user.apiKey }, dataType: 'json', contentType: 'application/json', data: JSON.stringify(issue) }) .then(function(response) { var createdIssueId = response.issue.id; return $.ajax({ type: 'POST', url: '/issues/' + currentIssueId + '/relations.json', headers: { 'X-Redmine-API-Key': ViewCustomize.context.user.apiKey }, dataType: 'json', contentType: 'application/json', data: JSON.stringify({ 'relation' : { 'issue_to_id' : createdIssueId, 'relation_type' : 'relates' } }) }) }) }; } })
先日2.1.0をリリースしてHTMLをそのまま埋め込めるようになったので、それを利用したサンプルということで、テキストエリアで入力補完的なことを行うサンプルを書いてみました。
やっていることは、下記のGreasemonkeyで行っていたものと基本的には同じです。
今回は、textile記法の補完だけでなく、テンプレート的なものも埋め込めるようにしています。
<pre
と入力したら、<pre><code class="java">
のようなシンタックスハイライト{{
と入力したら、{{thumbnail(image.png)}}
のようなマクロtemplate
と入力したら、テンプレート文面JavaScriptだけでも書けなくはないですが、、外部JSを読み込むのと、CSSを書かなければならないので、HTMLで書けたほうが楽だと思います。
.*
Head of all pages
HTML
注:Edgeだとうまく動作しないことがわかったため、外部ライブラリ読み込み時のasync
を消しました。(2019-07-29)
<script src="https://cdnjs.cloudflare.com/ajax/libs/at.js/1.5.2/js/jquery.atwho.min.js" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Caret.js/0.3.1/jquery.caret.min.js" defer></script> <style> .atwho-view { position:absolute; top: 0; left: 0; display: none; margin-top: 18px; background: white; color: black; border: 1px solid #DDD; border-radius: 3px; box-shadow: 0 0 5px rgba(0,0,0,0.1); min-width: 120px; z-index: 11110 !important; } .atwho-view .atwho-header { padding: 5px; margin: 5px; cursor: pointer; border-bottom: solid 1px #eaeff1; color: #6f8092; font-size: 11px; font-weight: bold; } .atwho-view .atwho-header .small { color: #6f8092; float: right; padding-top: 2px; margin-right: -5px; font-size: 12px; font-weight: normal; } .atwho-view .atwho-header:hover { cursor: default; } .atwho-view .cur { background: #3366FF; color: white; } .atwho-view .cur small { color: white; } .atwho-view strong { color: #3366FF; } .atwho-view .cur strong { color: white; font:bold; } .atwho-view ul { /* width: 100px; */ list-style:none; padding:0; margin:auto; max-height: 200px; overflow-y: auto; } .atwho-view ul li { display: block; padding: 5px 10px; border-bottom: 1px solid #DDD; cursor: pointer; /* border-top: 1px solid #C8C8C8; */ } .atwho-view small { font-size: smaller; color: #777; font-weight: normal; } </style> <script> $(function() { $('textarea.wiki-edit').atwho({ at: '<pre', data: [ {name: 'java', content: '<pre><code class="java">\n</code></pre>'}, {name: 'sql', content: '<pre><code class="sql">\n</code></pre>'}], insertTpl: '${content}', suffix: '' }).atwho({ at: '{{', data: [ {name: 'collapse', content: '{{collapse(詳細を表示...)\n}}'}, {name: 'thumbnail', content: '{{thumbnail(image.png)}}'}], insertTpl: '${content}', suffix: '' }).atwho({ at: 'template', data: [ {name: 'バグ', content: 'h2. 発生バージョン\n\nh2. 再現手順\n\nh2. ログ\n\n'}, {name: '問い合わせ', content: 'h2. 問い合わせ内容\n\nh2. 回答期限\n\n'}], insertTpl: '${content}', suffix: '' }); }); </script>
下記のような感じで、特定の文字をトリガーにして候補が表示され、候補を選ぶと文字列が埋め込まれます。
View customize plugin の v2.1.0 をリリースしました。
cat-in-136 さんからいただいたプルリクエストを取り込み、種別にHTMLが追加されました。
種別でHTMLを選ぶと、そのままHTMLとして埋め込まれます。これが使えて便利だと思うシチュエーションは、外部JavaScriptを読み込む際です。
今まで外部JavaScriptの読み込みはJavaScriptのコードとして書かなければなりませんでした。
$(document.createElement("script")).attr({ type: "application/javascript", src: "https://some.cdn.example.com/path/to/javascript.js", defer: "defer", async: "async" }).appendTo("head");
それが種別HTMLで行うと、script
タグでそのまま書けることになります。
<script type="application/javascript" src="https://some.cdn.example.com/path/to/javascript.js" defer async></script>
あとはCSSとJavaScriptをまとめて書くといったことも、今回からできることになります。
今までのJavaScript、CSSといった種別できていたことは、全てHTMLに置き換えられますが、今のところ種別をHTMLにまとめる予定はありません。HTMLにするまでも無いことは、今までどおりJavaScript、CSSを使っていただいたほうが、いちいちタグを書なくて済むので。
社内勉強会でView customizeについて発表(LT)しました。
www.slideshare.net
例がメインで、しかも最後のほうはアニメーションGIFです。Slideshareにアップロードするとアニメーションじゃなくなってしまうのでわかりずらいですね、、