- 投稿日:2020-09-15T22:30:17+09:00
ElectronをバージョンアップしたらMacアプリのCode Signができなくなった話
前回に引き続きElectron9のにバージョンアップした際に困ったことメモです
MacアプリのCode Sign
- Macアプリは10.14.5以降、署名と公証されていないといけなくなっています参考
- なのでアプリの配布には署名作業が必須
- 使っているライブラリ
- 署名用ライブラリ: electron-osx-sign
- アプリのビルド: electron-builder
Electron9へバージョンアップした後.appへの署名に失敗
- [ERROR] app is not signed [xxxxxx.app]
- と言われた
対策
- electron-osx-signを最新化 v0.4.11 --> v0.4.17
- electron-builderを最新化 v22.1.0 --> v22.7.0
これで署名できた!
参考
- 投稿日:2020-09-15T21:04:02+09:00
discord.js スタートガイド(スマホ可)
どうも すえきゅーです
今回はdiscordのbotを作りたい方向けのスタートガイドをここに書きたいと思います使うもの・Heroku ・Github ・discord developer portalまずdiscord developer portalでbotを登録しましょう
Botを登録する
こ↑こ↓ でNew applicationを押します
訳:Botの名前を決めてね!
Botの名前はわかりやすくて他人に見られてもいいようにしましょう
名前を決めたら↓のような画面になります
アイコンは決めておきましょう
次は三本線を押してBotというところを押します
なんか下のようなものが出てくるのでAdd Botを押しましょう
本当にするの?(下)が出てくるのでYes, do it!を押しましょう。
こいつはBotを動かすために使うパスワードをコピーするボタンですね
注意!これを人に教えると乗っ取られます!絶対に教えないようにしましょう。
もし教えてしまったら隣のRegenerateというボタンを押しましょう。
登録作業はこれで終わり!
Botの中身をつくる
まずこ↑こ↓にアクセスしUse this Templateを押す
そしたら
こんな感じにリポジトリを作る
これで中身は完成
こいつ自体にライセンスはないです
index.jsがbotの中身だよ!
これで中身を作る作業は終わりこれで最後の作業だ!頑張れ!
Herokuで稼働させる
herokuでアカウンk…アカウントを登録しましょう
職業の欄は学生でいいと思います
では次!
Newってところを押してcreate a New appを押します
そしてSettings(歯車のマーク)を押しここに行きます
こんな画面になると思うので
まずは Reveal Config Varsを押し
KEYにDISCORD_BOT_TOKENと入力したらVALUEにBOT登録作業で手に入れたTOKENをぶち込みます
次はAdd bulid packを押しNodejsを押します
なんか警告文見たいのが出ますが気にしないでください
最後!!!!
Deployで下にスクロールするとGithubとかよくわかんないのが並んでますがGithubを押しましょう それでリポジトリを作ったGithubアカウントでログインします
それでなんか下のようなところが出てくるので(語彙力0)
さっき作ったリポジトリの名前をぶち込んでサーチを押したらリポジトリが出てくるのでconnectします。
そしたら Enable Automatic Deployを押して Deploy Branchを押す
これで動くはずです…動かなかったら discordで index#7595 にフレンド申請して質問するか 自鯖で質問してください。
最後まで見てくれてありがとうございます!
初めての記事なのであまり質が良くないかも知れません。
- 投稿日:2020-09-15T18:13:14+09:00
HerokuでLINEとDiscordをつないでみる
はじめに
KC3 2020の勉強会で話した内容です。
DiscordとLINEでテキストメッセージのやり取りができるようにします。
画像のメッセージのやり取りの実装などは別記事でやります。LINEでメッセージ送信 → LINE BotがHerokuにメッセージの内容を送信 → HerokuがDiscord Webhookにメッセージの内容を送信 → Discordでメッセージが表示される
Discordでメッセージ送信 → Discord BotがHerokuにメッセージの内容を送信 → HerokuがLINE Botにメッセージの内容を送信 → LINE Botが発言
大まかにはこのような構成になっています。LINE Botの準備
LINE Developersにログイン
LINE Developersにログイン。LINEアカウントでログインできる。
Providerを作成
Providers一覧の上の”Create”ボタンを押し、名前を決めて新規作成。
Channelを作成
作成したProviderのChannelを作成する。Create a Messaging API Channelを選択。
入力項目を埋めてChannelを作成する。
このとき、ブラウザの拡張機能が干渉してインプットが消えてしまうことがあった。
LINE Botの設定を変更
LINE Official Account Managerの応答設定からLINE Botの設定のWebhookをオンにする。
LINE Botと友だちになる/グループに招待
グループに参加させるにはLINE DevelopersのChannel設定のMessaging APIタブからグループ参加を有効にする必要がある。
友だち追加はBasic settingsタブのQRコードなどから可能。
グループの各メンバーはBotを友だち追加する必要がある。これでLINE Botの準備は完了。
[環境変数の登録などの諸設定](https://qiita.com/sanbasan/items/8145140bb67c4c6ef516#%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AE%E7%99%BB%E9%8C%B2%E3%81%AA%E3%81%A9%E3%81%AE%E8%AB%B8%E8%A8%AD%E5%AE%9Aでアクセストークンの確認とWebhook URLの設定をするためにLINE Developersを開く。
Discord Botの準備
Discord Developer Portalにログイン
Discord Developer Portalにログインする。
Applicationを作成
右上の"New Application"を押して名前を指定し、Applicationを新規作成する。
Discord Botの作成
Discord Botをサーバーに招待
OAuth2タブで適宜必要なチェックを入れて生成されたURLを開く。
そのページでBotをサーバーに招待する。
これでDiscord Botの準備は完了。Botはサーバーに参加していてオフラインの状態。コードを書いてHerokuにデプロイ
Node.js(今回は12.8.3を使用)でHerokuで行う処理を記述する。
下準備
git init
やnpm init
など叩いてgit・npmが使える状態にする。ここは割愛。
Heroku CLIを使用するのでインストールしておく。必要なパッケージの導入
$ npm install @line/bot-sdk discord.js express axiosを実行してパッケージを導入。
LINE → Discordの処理
jsファイルを作成してコードを書いていく。
linebot.jsconst express = require('express'); const axios = require('axios'); const line = require('@line/bot-sdk'); const PORT = process.env.PORT || 5000; const lineConfig = { channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN, channelSecret: process.env.LINE_CHANNEL_SECRET, }; const lineClient = new line.Client(lineConfig); const discordWebhookUrl = process.env.DISCORD_WEBHOOK_URL; const discordWebhookConfig = { headers: { 'Accept': 'application/json', 'Content-type': 'application/json', }, }; const generatePostData = (event, profile) => { const type = event.message.type; if (type !== 'text') { return { username: profile.displayName, avatar_url: `${profile.pictureUrl}.png`, content: 'テキスト以外のメッセージを送信しました。', }; } return { username: profile.displayName, avatar_url: `${profile.pictureUrl}.png`, content: event.message.text, }; }; const lineBot = async (req, res) => { res.status(200).end(); // 'status 200'をLINEのAPIに送信 const events = req.body.events; events.forEach(async (event) => { try { const profile = await lineClient.getProfile(event.source.userId); const postData = await generatePostData(event, profile); // DiscordのWebHookにPOST await axios.post(discordWebhookUrl, postData, discordWebhookConfig); } catch(error) { console.error(error); } }); }; const app = express(); app.post('/linehook/', line.middleware(lineConfig), (req, res) => lineBot(req, res)); app.listen(PORT, () => console.log(`Listening on ${ PORT } for LINE Messaging API.`));expressでLINE BotからのPOSTを受けてDiscord WebhookにPOSTしている。
LINEのアイコンと名前をDiscordで出力する際に反映させている。Discord → LINEの処理
おなじくjsファイルを作成してコードを書いていく。
discordbot.jsconst line = require('@line/bot-sdk'); const discord = require('discord.js'); const lineConfig = { channelAccessToken: process.env.LINE_CHANNEL_ACCESS_TOKEN, channelSecret: process.env.LINE_CHANNEL_SECRET, }; const lineClient = new line.Client(lineConfig); const discordClient = new discord.Client(); const generateMessage = (event) => { const content = event.content; if (content.length === 0) { return { type: 'text', text: 'Discordで非対応の形式のメッセージを送信しました。', sender: { name: event.author.username, iconUrl: event.author.displayAvatarURL().replace('.webp', '.png'), }, }; } return { type: 'text', text: `${content}`, sender: { name: event.author.username, iconUrl: event.author.displayAvatarURL().replace('.webp', '.png'), }, }; }; discordClient.on('message', async (event) => { try { // BOTのメッセージはスルー if (!event.author.bot) { const message = generateMessage(event); await lineClient.pushMessage( // 送信先のトークルームのグループ/ユーザーID process.env.LINE_TARGET_ID, message, ); } } catch(error) { console.error(error); } }); discordClient.login(process.env.DISCORD_ACCESS_TOKEN);DiscordのアイコンとユーザーIDをLINE Botが発言するときに使用する。
Procfileの記述
Herokuでjsファイルが実行できるようにProcfileを書いておく。
line: node linebot.js dicord: node discordbot.jsHerokuにデプロイ
Heroku スターターガイド (Node.js)にあるようにHeroku CLIでデプロイする。
まだこの時点では動作しない。
環境変数の登録などの諸設定
Heroku DashboardのSettingsのConfig Varsから環境変数を設定できる。
Heroku CLIからも可能。Herokuで環境変数を設定する方法 - Qiita
上のコードだと以下の5つを設定する。
LINEのChannel access token
LINE DevelopersのChannelの設定画面のMessaging APIタブの一番下にChannel access token (long-lived)がある。
上のコードではLINE_CHANNEL_ACCESS_TOKEN
として設定する。
LINEのChannel secret
LINE DevelopersのChannel設定画面のBasic settingsタブにChannel secretがある。
上のコードではLINE_CHANNEL_SECRET
として設定する。
LINE Messaging APIのWebhook URLを設定
LINE DevelopersのChannelの設定画面のMessaging APIタブでWebhook URLを"https://<Herokuのアプリ名>.heroku.com/linehook"に設定する。
設定するとVerifyというボタンが出る。押してSuccessと出れば成功。
DiscordのWebhook URL
タイトル: Webhooksへの序章 – Discord - Discord SupportのようにWebhook URLを取得し、それを上のコードでは
DISCORD_WEBHOOK_URL
として設定する。DiscordのToken
Discord Developer Portalの作成したアプリケーションの画面のBotタブからTokenを取得し、上のコードでは
DISCORD_ACCESS_TOKEN
として設定する。
Botが発言するトークルームのID
LINE Botが発言するトークルームのIDを指定しておく必要がある。
グループチャット | LINE Developersにあるようにメッセージイベントのsource
プロパティからIDを取得できる。linebot.js
にコードを書き足してログに表示するようにしておけばHerokuの実行ログから確認できる。それを上のコードではLINE_TARGET_ID
として設定する。dynoを起動
Heroku Dashboardからdynoを起動する。
これでテキストメッセージのやり取りはできるようになる。参照
- ドキュメントトップ | LINE Developers
- Discord Developer Portal
- Heroku Dev Center
- @line/bot-sdk - npm
- discord.js - npm
- express - npm
- axios - npm
- Herokuで環境変数を設定する方法 - Qiita
- Heroku Schedulerの設定方法 - Qiita
これらの記事も参考になると思います。
- 投稿日:2020-09-15T16:57:35+09:00
Microsoft TeamsのWebhook URLにNode.jsから情報を送ってみる
最近仕事のやりとりでTemasを使う機会が増えてきました。
Teamsのハックを出来ないかと調べてみているメモです。
Webhook URLの取得
自分が管理権限があるチームの左下に
アプリ
ボタンがあると思います。ここから
Incomming Webhook
を探してチームに追加します。利用するチャンネルを選びます。
名前を適当に決めましょう。
作成ボタンを押すと
https://outlook.office.com/webhook/~~~
というアドレスが発行されます。CURLで試す
cURLだと以下をコピペで実行できます。
$ curl -H 'Content-Type: application/json' -d '{"text": "Hello World"}' <YOUR WEBHOOK URL>実行結果はこんな感じです。
ここまできたらこちらのものですね。
Node.jsから試す
axiosを利用します。
$ npm ini -y $ npm i axiosapp.js'use strict' const axios = require('axios'); const URL = `https://outlook.office.com/webhook/~~~`; //各自のWebhook URL axios.post(URL, {text: 'Node.jsから送信'}) .then(res => console.log(res.data));シンプルなコードですね。
実行します。$ node app.js 1
res.data
には1という数字が返ってくる模様。所感
Webhook URLの発行で結構迷いました。Slack, LINE, Discordなど様々なBOTを触りましたが今回はどんなパターンだろう......といった感じです。今のところの結論はSlack BOTに近いような印象です。Incoming WebhookのアプリというかBOTアカウントをチームに追加すると、連動しているWebhook URLが発行されるといった流れ。
他にもやり方ある気がするので引き続き調べてみます。
- 投稿日:2020-09-15T13:56:49+09:00
PervasiveデータベースにNode.jsから接続するサンプル
はじめに
20世紀に作られ現在も稼働中のVBのシステムにデータ出力の要件があったので、Node.jsで実装してみました。
あまりにも情報が少なすぎて苦労したので備忘録として残します。環境
項目 内容 データベース Pervasive PSQL v10
(サービスとして起動)OS Windwos10 node v13.9.0 jdbcライブラリ jdbc@0.7.2 準備
Pervasiveのインストールディレクトリ配下にある以下の3ファイルが必要です。
- pvjdbc2.jar
- pvjdbc2x.jar
- jpscs.jar
プロジェクトディレクトリに drivers というディレクトリを作ってコピーしておきます。
ソース
PervasiveのMYDATAデータベースのMYTABLEテーブルから全レコードを取得してJSONを返すAPIサーバーのサンプルです。
なお、このプログラムにルーティングするExpress/Routerのプログラムが別途必要です。
Pervasiveのサービスが起動しているホスト上でプログラムが実行されることを前提としています。const express = require("express"); const router = express.Router(); const JDBC = require("jdbc"); const jinst = require("jdbc/lib/jinst"); if (!jinst.isJvmCreated()) { jinst.addOption("-Xrs"); jinst.setupClasspath([ "./drivers/pvjdbc2.jar", "./drivers/pvjdbc2x.jar", "./drivers/jpscs.jar" ]); } const conf = { url: "jdbc:pervasive://localhost:1583/MYDATA?transport=tcp", drivername: "com.pervasive.jdbc.v2.Driver", minpoolsize: 10, maxpoolsize: 100, properties: {} }; const initializeCB = err => { if (err) { console.log(err); } }; const reserveCB = (err, connObj, sql) => { return new Promise((resolve, reject) => { if (!connObj) { console.log("connObj is undefined"); reject(err); } const conn = connObj.conn; conn.createStatement((err, statement) => { if (err) { console.log(err); reject(err); } statement.executeQuery(sql, (err, resultset) => { if (err) { console.log(err); reject(err); } resultset.toObjArray((err, result) => { resolve(result); }); }); }); }); }; module.exports = router; /** * テーブルから全レコードを取得しJSONを返す */ router.post("/", (req, res) => { const jdbc = new JDBC(conf); jdbc.initialize(initializeCB); jdbc.reserve((err, connObj) => { reserveCB(err, connObj, "SELECT * FROM MYTABLE") .then(data => { const headers = {"Content-Type": "text/json;charset=utf-8"}; res.set(headers).json(data); }) .then(() => {jdbc.release(connObj, (err) => {if (err) {console.log(err.message);}}) }) .then(() => {jdbc.purge(err => {});}); }); });
- 投稿日:2020-09-15T10:57:34+09:00
もうBacklogやRedmineは要らない? Exmentでガントチャート付きタスク管理を実践する
どうも、業務改善が大好きな筆者です。
さて、連日Exmentの記事を書いているわけですが、そろそろタスク管理についても触れたいなと思っています。
タスク管理といえば、TrelloやAsana、BacklogやRedmineなど、SaaSのサービスが乱立してますよね。(Redmineはオンプレも可能ですが)
一方で、Excelやスプレッドシートに書き込んで、お手製のタスク管理をされている方もいらっしゃると思います。
ガントチャート好きな人、多いですよね
筆者個人が、タスク管理でどうしても外せないのがガントチャートです。ガントチャート機能付きのタスク管理サービスというと、どうしても選択肢がせばまってきます。
今はToggl Planという名前になってTogglファミリーとなった、かつてのTeamweekが、個人的には一番好きでした。
Redmineにもガントチャートがありますが、デフォルトのあれはダメでしたね。何が良くて何がダメなのか。それはマウスでガントチャートを伸ばしたり縮めたりできるかどうかだと思ってます。
Teamweekはそれが出来たのですが、Redmineはタスクの日付を変えない限り伸び縮みしてくれませんでした…(デフォルトの話です)
ガントチャート使えるサービス、有料SaaSが多い件
Backlogのガントチャートもマウスで伸び縮みできるそうなんですが、Backlogは一零細副業家(筆者は副業の管理にExmentを試験導入しています)にとっては手が出せない価格なんですよね。基本1人で使うし… Asanaも有料プランですし…
Redmineはオンプレで使えますが、ガントチャート自体の昨日が今一つなので、試してすぐやめました…
もしガントチャート使えるのなら、タスク管理もExmentでやってみたい…
というわけで、これまでタスク管理は色々なものを主に無料プランで使ってきましたが、どれも一長一短で馴染むものがありませんでした。ガントチャートでいえばTeamweek(現:Toggl Plan)でしたが、カンバンの良さでいえばTrelloですよね…
そこに来て、現在筆者は
をExmentに集約しているので、タスク管理もここで案件と紐づけつつやってみたいなあ、という思いに至りました。なので、今回はExmentでタスク管理しつつ、API経由でガントチャートビューも実装してみたいと思います。
フロントにFrappe Ganttを採用
色々なJavaScriptのガントチャートライブラリを一通り調べてみましたが、シンプルさと機能の両立で言うと、Frappe Ganttが良いな、と思い今回採用してみました。
もちろんマウスで伸び縮み出来ますし、バーを横に動かすこともできます。しかも進捗率もマウスで変更できます。
それでは、実装していきましょう。
Exment側のテーブル設計
まずは、Exment側のカスタムテーブルを用意します。カスタムテーブル名は「タスク管理」としました。
テーブル設計は
列名 列のタイプ タイトル 1行テキスト 開始日 日付と時刻 終了日 日付と時刻 担当者 ユーザー 案件名 選択肢 (他のテーブルの値一覧から選択) 進捗率 整数(0~100) ステータス 選択肢(値・見出しを登録) ステータスの値と見出しは以下の通りです。
1,未整理 2,未着手 3,進行中 4,チェック待ち 5,完了 6,対応しないフロントはExpress + pugでHTMLを出力
コスト管理(原価計算)の時のように、Express + pugで出力します。この時のapp.jsを使いまわそうと思います。なので、Expressやpugはインストール済みという前提にしたいと思います。
app.jsapp.get('/tasks', async (req, res) => { ;(async () => { const exmentToken = JSON.parse(await fs.readFileSync('./exment_tokens.txt')).access_token let tasksData = await axios.get('https://example.com/api/data/tasks/?orderby=start_at', { headers: { 'Authorization': 'Bearer ' + exmentToken } }) .then(res => { return res.data.data }) .catch(err => { console.error(err) }) let tasksArray = [] tasksData.forEach(item => { const id = item.id const name = item.value.title const start = moment(item.value.start_at).format('YYYY-MM-DD') const end = moment(item.value.end_at).format('YYYY-MM-DD') const progress = item.value.progress const custom_class = 'uplift-task' tasksArray.push({ id: String(id), name: name, start: start, end: end, progress: progress, custom_class: custom_class }) }) // console.log(tasksArray) res.render('tasks-gantt', { tasks: JSON.stringify(tasksArray) }) })() })まずは、タスクデータの取得です。ExmentのAPIからGETで取得し、Frappe Ganttのtaskデータ形式に整形しています。
次に、viewです。
tasks-gantt.pug<!DOCTYPE html> html(lang="en") head meta(charset="UTF-8") meta(name="viewport", content="width=device-width, initial-scale=1.0") title Document link(rel="stylesheet", href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css", integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z", crossorigin="anonymous") . <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/frappe-gantt/0.5.0/frappe-gantt.min.css" integrity="sha512-j2JEichKxgq6udg7yAJpsSwGLrHtxeTinqv4kzc+SXCJEhYzDT/JclOOOU28pD1jk1IEdt2FCQ/CnqdOzt7e6Q==" crossorigin="anonymous" /> body #gantt .btn-group(role='group', aria-label='Basic example') button.btn.btn-secondary(type='button' onClick="changeDay()") Day button.btn.btn-secondary(type='button' onClick="changeWeek()") Week button.btn.btn-secondary(type='button' onClick="changeMonth()") Month . <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js" integrity="sha512-QkuqGuFAgaPp3RTyTyJZnB1IuwbVAqpVGN58UJ93pwZel7NZ8wJOGmpO1zPxZGehX+0pc9/dpNG9QdL52aI4Cg==" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/snap.svg/0.5.1/snap.svg-min.js" integrity="sha512-Gk+uNk8NWN235mIkS6B7/424TsDuPDaoAsUekJCKTWLKP6wlaPv+PBGfO7dbvZeibVPGW+mYidz0vL0XaWwz4w==" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/frappe-gantt/0.5.0/frappe-gantt.min.js" integrity="sha512-5M8ejeX3DuiV4VGIFjHP5gpryPQb1dWYjzTUhBUKj81aT6ZZz6+wIG8k89nbjsiHFJHQbi/CByHQTe4mJOi3hw==" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.20.0/axios.min.js" integrity="sha512-quHCp3WbBNkwLfYUMd+KwBAgpVukJu5MncuQaWXgCrfgcxCJAq/fo+oqrRKOj+UKEmyMCG3tb8RB63W+EmrOBg==" crossorigin="anonymous"></script> script. const tasks = !{tasks} const options = { header_height: 50, column_width: 30, step: 24, view_modes: ['Day', 'Week', 'Month'], bar_height: 50, bar_corner_radius: 3 , arrow_curve: 5, padding: 18, view_mode: 'Day', date_format: 'YYYY-MM-DD', custom_popup_html: null, on_date_change: function(task, start, end) { axios.put('/tasks/date',{ id: task.id, start_at: moment(start).format('YYYY-MM-DD HH:mm:ss'), end_at: moment(end).format('YYYY-MM-DD HH:mm:ss') }) .then(function(res) { console.log(res) }) .catch(function(err) { console.log(err) }) }, on_progress_change: function(task, progress) { console.log(task, progress); axios.put('/tasks/progress',{ id: task.id, progress: progress }) .then(function(res) { console.log(res) }) .catch(function(err) { console.log(err) }) }, } const gantt = new Gantt('#gantt', tasks, options) function changeDay() { gantt.change_view_mode('Day') } function changeWeek() { gantt.change_view_mode('Week') } function changeMonth() { gantt.change_view_mode('Month') }とりあえず動く、までが目標なので、あんまりきれいにまとまっていません。
まず、Frappe GanttはCDNから読み込みました。Frappe Ganttのdependanciesである、momentとsnap-svgもCDNから。Frappe GanttのinitもHTMLにべた書きです。
on_date_changeと、on_progress_changeが、バーを伸ばしたり進捗率を変更したときのコールバックになります。ここで、CDNから読み込んだaxiosを呼び出して、Exment側へPUTしています。
ExmentのAPIをJSから直接叩いても良かったのですが、認証のこともありますし、一旦Express側にAPIを作って、そこからデータを送っています。フロントとバックエンドで2回axiosのお世話になるという、なんだかなー、ということになってますが…
下記が、app.jsのPUTの箇所です。
app.jsapp.put('/tasks/date', async (req, res) => { ;(async () => { const exmentToken = JSON.parse(await fs.readFileSync('./exment_tokens.txt')).access_token // console.log(req.body) await axios.put('https://example.com/api/data/tasks/' + req.body.id, { value: { start_at: req.body.start_at, end_at: req.body.end_at } }, { headers: { 'Authorization': 'Bearer ' + exmentToken } }) .then(res => { return res }) .catch(err => { console.error(err) }) })() }) app.put('/tasks/progress', async (req, res) => { ;(async () => { const exmentToken = JSON.parse(await fs.readFileSync('./exment_tokens.txt')).access_token // console.log(req.body) await axios.put('https://example.com/api/data/tasks/' + req.body.id, { value: { progress: req.body.progress } }, { headers: { 'Authorization': 'Bearer ' + exmentToken } }) .then(res => { return res }) .catch(err => { console.error(err) }) })() })さて、うまく行けば下記のようになっているはずです。
いい感じですね。
では、ドラッグアンドドロップのテストをしたいと思います。
先にExmentを開いて、開始日終了日の日付を確認しておきましょう。
↑まず、日付はこうなっています。
次に、ガントチャート側でバーをドラッグして長さも変更してみましょう。
ついでに、進捗率も変えちゃいましょう。
では、Exment側に戻り、同じタスクの詳細画面をリロードします。
しっかりと変更されてました!
しかし、課題もあります
タスクの依存関係が作れない
Frappe Gantt側ではその機能はあるのですが、Exmentでバックエンドを実装すると、同じカスタムテーブル内のレコード同士を紐づける設定が今のところないので、タスク同士の紐づけができません。
無理やり整数のカラムを作って、レコードIDを手入力することも考えられますが、それも何だかなあといった感じです。
日本語化されてない
月の表記が英語です。月だけは日本語化できそうなので、暇なときにプルリク作って送っておきますか。
土日祝日の色変更ができない
なんかIssueにはそれっぽいのが上がってるのですが、結局どうやって変更すればいいのか分かりませんでした。
ただまあ、個人的にはこれらの課題は些末なことだったので…
一旦ガントチャートにできれば十分だったので、この結果は満足しています。
もし、高度なガントチャートが必要であれば、別のライブラリを使えばいいと思います。
まとめ
- ExmentのAPIを使って、タスクをガントチャート化できるよ!(BacklogとかRedmineいらないかも)
- ガントチャートライブラリは色々あるけど、マウスでバーを伸び縮みできるのがいいなら、Frappe Ganttがおすすめ(課題はあるけど)
- ガントチャートライブラリは、お好みのものを選べばいいと思う。もっと高機能なものもあるしね!
といったところでしょうか。
個人的には、MFクラウド請求書で受注した見積書とタスクが紐づくことによって、Togglの記録とも連動させて
- 営業判断
- 工数原価管理
- タスク管理
が一元化したのが気持ちいいなー、と思っています。BacklogやRedmineも良いですが、Exmentでタスク管理始めてみませんか?
- 投稿日:2020-09-15T10:34:16+09:00
AWS lambdaで、node httpsモジュールでpostする
AWS lambda node、標準のhttpsモジュールで、chatwork APIにpostしたいと思ったが、検索してもrequest-promiseを追加しろみたいな話しかなく、AWS lambdaの標準パッケージでサクッと試したいだけだったのにサクっといかなかった。
https://nodejs.org/api/https.html#https_https_request_options_callback
公式にはgetの記述しかないのでpostができないのか、と思ったらできた。writeにたどりつかなかった……
(参考)
https://qastack.jp/programming/6158933/how-is-an-http-post-request-made-in-node-jsconst https = require('https'); const querystring = require('querystring'); exports.handler = function(event, context){ var postMessage = 'テスト' var post_data = querystring.stringify({body:postMessage}); let options = { host: 'api.chatwork.com', path: '/v2/rooms/{roomid}/messages', port: 443, headers: { 'X-ChatWorkToken': '{X-ChatWorkToken}', 'Content-Type': 'application/x-www-form-urlencoded', }, method: 'POST', }; var post_req = https.request(options, function(res) { res.setEncoding('utf8'); res.on('data', function (chunk) { console.log('Response: ' + chunk); context.succeed(); }); res.on('error', function (e) { console.log("Got error: " + e.message); context.done(null, 'FAILURE'); }); }); post_req.write(post_data); post_req.end(); };