前前回
ブックマークレットを作ってみたものの、クロスドメインエラーが出て動かなかった
前回
Chrome extensionで認証情報を取得できるようにした
ソースはここ。
認証情報を取得できるようにしたので、その情報を使ってTaskWorldにPOSTしてタスクを登録します。
目次
script.js
Redmineから情報を収集する
Redmineチケット画面から、以下の情報を収集します。
セレクタがわかりやすいので、Jqueryを使って取得。
Redmine側 | TaskWorld側 |
チケットのURL | description |
タイトル | title |
担当者のUserID | list_idの振り分けに使用 |
期日 | due_date |
担当者と期日は設定されていない場合があります。
また、Redmineの設定によっては期日の区切り文字が異なる場合があるようです。
とりあえず、想定しているもの以外が設定されていた時のために、try~catchにしておきました。
期日は当日の19時にするため、"T10:00:00.000Z"を設定します。
日本はUTC+09:00なので、T00:00:00.000Zを設定した場合は9時になります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var dueDate; try { dueDate = $(".due-date .value").text(); // Redmineの作りによって区切り文字が違うようなので分岐 if(dueDate.indexOf("/") != -1){ dueDate = dueDate.split("/"); dueDate = dueDate[0] + "-" + dueDate[1] + "-" + dueDate[2] + "T10:00:00.000Z"; }else if(dueDate.indexOf("-") != -1){ dueDate = dueDate + "T10:00:00.000Z"; } } catch (e) { attributeNum = ""; } |
task.createでタスクを作成する
TaskWorldに登録するデータを収集したら、APIでタスクを作成します。
1回で作成出来たらいいのですが、なぜかこのAPI、作成時はタイトルしか設定できません。。。
仕方ないので、task.createでタスクを作った後、レスポンスのtask_idを使って残りの情報をtask.updateで登録するようにします。
本当はspace_idとproject_idもオプションで取得できるようにすればよかったんですが、今回は複数のプロジェクトに対応することを考えていないのでConstに持たせました。
attributeNumでlist_idを振り分けていますが、switchだと人が増えるたびに分岐を増やさないといけないので、ループしてif文で処理したほうがよかったですね…。
(今回は直しませんが)
cDataにtask.createに渡すデータを詰めて返します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
function createTasWorldData(rData, accessToken) { if(!accessToken){ alert("オプションでaccess tokenを取得してください。"); }; var pId = userData.pId; var sId = userData.sId; var lId; switch(rData.attributeNum){ case ("3"): lId = userData.lId.ito; break; default: lId = userData.lId.default; break; }; var cData = { "access_token": accessToken, "space_id": sId, "project_id": pId, "list_id": lId, "title": rData.title }; return cData; } |
task.updateで追加の情報を登録する
task.updateに渡すデータを作ります。
updateには、createのレスポンスで帰ってくるtask_idが必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function updateTasWorldData(resCreateData, rData, accessToken) { var tId = resCreateData.task.task_id; var sId = userData.sId; var uData = { "access_token": accessToken, "space_id": sId, "task_id": tId, "description": rData.rUrl }; if(rData.dueDate){ uData["due_date"] = rData.dueDate; }; return uData; } |
作った処理をpromiseを使ってつなげる
background.jsから値を取得するgetLocalStorageとpostAPIは非同期処理です。
今回は値を取得してから次の処理を実行する必要があるので、promiseで非同期処理が終わるのを待ってから実行するようにします。
promiseを入れ子にしてみましたが、これが正しい書き方なのかは自信がありません…。
動くことは動くのですが。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) { if (request == "Action") { var rData = acquireRedmineData(); console.log("redmineから取得した情報"); console.log(rData); var accessToken; var gPromise = getLocalStorage("token"); gPromise.done(function(data){ console.log("Task Createの実行結果"); console.log(data); accessToken = data; return data; }) .fail(function(){ console.log("tokenの取得に失敗しました") }); gPromise.then(function(){ var cData = createTasWorldData(rData, accessToken); console.log("Task Createに使用する情報"); console.log(cData); var cPromise = postAPI(apiUrl.taskCreate, cData); cPromise.done(function(data){ console.log("Task Createの実行結果"); console.log(data); return data; }) .fail(function(){ console.log("Task Createに失敗しました") }); cPromise.then(function(resCreateData){ var uData = updateTasWorldData(resCreateData, rData, accessToken); console.log("Task Updateに使用する情報"); console.log(uData); var uPromise = postAPI(apiUrl.taskUpdate, uData); uPromise.done(function(resUpdateData){ console.log("Task Updateの実行結果"); console.log(resUpdateData); if(resUpdateData.ok){ alert("登録に成功しました"); } }).fail(function(){ console.log("Task Updateに失敗しました") alert("Errorが発生しました"); }) }) }) } }); |
chromeに読み込ませて実行してみる
全部の処理を作り終わったので、実際に使ってみます。
chromeでその他のツール > 拡張機能画面を開きます。
デベロッパーモードがOFFになっている人はONにしてください。
パッケージ化されていない拡張機能を読み込むボタンを押し、scriptがあるフォルダ(今回はRtoT)を選択します。
読み込まれたら、オプションで認証情報を取得しておきます。
次に、background.jsで指定したドメインのRedmineのチケット画面を開きます。
extensionボタンが有効化しているはずなので、クリックします。
TaskWorldにタスクが登録されました。
extensionを作ってみて
最初はbackground.jsとcontent_scriptsの関係、非同期処理の仕方がよくわからなくて苦労しましたが、何とか形になりました。
ブックマークレットでは文字数の問題や、改行できなくて可読性が落ちるなどがあり、複雑な処理をしにくいですが、extensionにしてしまえば好きなだけ処理をかけます。
もしいいものができたら、公開料5ドルが必要ですが、chrome ウェブストアに公開することもできます。
今回JSで開発を行いましたが、最近はNode.jsでサーバーサイド、Typescriptで大規模開発とJSの活用の幅が広がっているので、今のうちにJSマスターになっておくといいかもしれませんね。