プリザンターの通知をMicrosoftTeamsにカード型で通知してみる
プリザンターとは
Pleasanter(プリザンター)はオープンソースのビジネスアプリケーションプラットフォームです。顧客管理や営業支援、プロジェクト管理など様々な業務をノンプログラミングでWebデータベース化することができます。動作が軽く、汎用性が高いため、日常的なコミュニケーションやマネジメントの支援ツールとして利用できます。
-
https://github.com/Implem/Implem.Pleasanter参照
- Qiita内では、
@Implem
さんの記事です。
- Qiita内では、
ダウンロード
セットアップモジュールのダウンロードサイトです。
http://pleasanter.org
MicrosoftTeamsの通知方法
設定手順
-
実は、通知手順は、プリザンターでしっかりと説明されているので説明は省きます。
-
以下のサイトをよく確認の上、作業してください。
-
Microsoft Teamsに通知する場合の設定
- 簡単説明
- MicrosoftTeamsに
Incoming Webhookコネクタ
の追加 - コネクタのURLの取得
- プリザンターの通知設定
- MicrosoftTeamsに
- 簡単説明
-
Microsoft Teamsに通知する場合の設定
-
上記手順だけで、MicrosoftTeamsへは通知することができます。
-
でも、そのままだと通知が見にくいので、カードタイプの通知をしてみるってのが今回の目的です。
-
もし、Teamsのストアになかった場合は、
Incoming Webhook コネクタ
がシステム管理者に許可されていない場合がありますので、システム管理者に連絡してストアアプリの許可をしてもらってください。 -
上記の手順のままだとつらつらと表示される通知で誰が更新したのかもわからない状態なので、Azure DevOpsの通知のようにカード形式で実装します。
通知方式
アダプティブ カード形式
Office 365 コネクタは、現時点ではアダプティブ カード形式をサポートしていません。 Office 365 コネクタを実装している場合は、MessageCard 形式のリファレンスを参照してください。
ということで、やっぱり旧型式のメッセージカード使って、MicrosoftTeamsへ通知をします。
メッセージ カード形式
カードはひとめでわかる読みやすい情報を提供し、ユーザーがすぐに理解して、該当する場合にそれを基に行動を起こせるようであるべきです。したがって、優れたカードをデザインするための指針は「クロムよりもコンテンツ」です。つまり、カードは要点をついたものとし、アイコンやカスタム色などの煩雑になりかねないものの使用は最小限に抑えるということです。
となっていますが、注意書きに以下のような記載があります。
注意
このドキュメントでは、操作可能なメッセージ カード形式の元の JSON 形式について説明します。 これは、アダプティブ カード形式に置き換えられました。 Microsoft は新しい操作可能なメッセージの統合には、アダプティブ カード形式の使用をおすすめします。既存の統合は、アダプティブ カード形式への更新を検討してください。
と書いてあるので、将来的にはアダプティブカード形式に変更する必要がありそうです。
ソースコードの修正
Notification.csの修正
- 修正前
case Types.Teams:
if (Parameters.Notification.Teams)
{
new Teams(context,"*{0}{1}*\n{2}\n{3}".Params(Prefix, title, url, body).Send(Address);
}
- 修正後
case Types.Teams:
if (Parameters.Notification.Teams)
{
new Teams(context, Prefix, title, url, body).Send(Address);
}
Teams.csの修正
カード用のJSONクラスの作成
- 別のクラスファイルで行った方が良いかと思いますが、今回は簡易的な作業なため、同じファイル内に記述します。
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Implem.Pleasanter.Libraries.DataSources
{
public class Teams
{
// ~~中略~~
// ~~ここに追記~~
public class CardObject
{
[JsonProperty("@context")]
public string context { get; set; }
[JsonProperty("@type")]
public string type { get; set; }
[JsonProperty("summary")]
public string summary { get; set; }
[JsonProperty("themeColor")]
public string themeColor { get; set; }
[JsonProperty("title")]
public string title { get; set; }
[JsonProperty("sections")]
public List<CardSection> sections { get; set; }
[JsonProperty("Potentialaction")]
public List<PotentialAction> potentialAction { get; set; }
}
public class CardSection
{
[JsonProperty("activityTitle")]
public string activityTitle { get; set; }
[JsonProperty("activitySubtitle")]
public string activitySubtitle { get; set; }
[JsonProperty("text")]
public string text { get; set; }
[JsonProperty("activityImage")]
public string activityImage { get; set; }
}
public class PotentialAction
{
[JsonProperty("@type")]
public string type { get; set; }
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("targets")]
public List<CardTarget> targets { get; set; }
}
public class CardTarget
{
[JsonProperty("os")]
public string os { get; set; }
[JsonProperty("uri")]
public string uri { get; set; }
}
}
}
カード用のJSONクラスの宣言
- 修正前
public class Teams
{
public Context context;
public string text;
- 修正後
public class Teams
{
public Context context;
public string text;
public CardObject cardObject; //追記
メッセージカードクラスへ格納
- 修正前
public Teams(Context , _text)
{
context = _context;
text = _text; //削除予定
}
- 修正後
public Teams(Context _context, string _Prefix, string _title, string _url, string _body)
{
context = _context;
cardObject = new CardObject();
var cardSection = new List<CardSection>();
var potentialAction = new List<PotentialAction>();
var cardTarget = new List<CardTarget>();
cardSection.Add(new CardSection()
{
activityTitle = _title,
activitySubtitle = "Updated by " + context.User.Name.Trim(),
text = _body.Replace("\n", "\n\n")
activityImage = "",
});
cardTarget.Add(new CardTarget
{
os = "default",
uri = _url
});
potentialAction.Add(new PotentialAction()
{
type = "OpenUri",
name = "View",
targets = cardTarget
});
cardObject.context = "https://schema.org/extensions";
cardObject.type = "MessageCard";
cardObject.summary = _Prefix;
cardObject.themeColor = "0078D7";
cardObject.sections = cardSection;
cardObject.potentialAction = potentialAction;
}
JSONシリアライズ
- 修正前
public void Send(string address)
{
foreach (var url in address.Split(',').Select(x => x.Trim()))
{
Task.Run(() =>
{
try
{
using (var client = new WebClient())
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(new { text }); //ここを修正予定
client.Headers[HttpRequestHeader.ContentType] = "application/json;charset=UTF-8";
client.Headers[HttpRequestHeader.Accept] = "application/json";
client.Encoding = Encoding.UTF8;
client.UploadString(url, "POST", json);
}
}
catch (Exception e)
{
new SysLogModel(context, e);
}
});
}
}
- 修正後
public void Send(string address)
{
foreach (var url in address.Split(',').Select(x => x.Trim()))
{
Task.Run(() =>
{
try
{
using (var client = new WebClient())
{
string json = Newtonsoft.Json.JsonConvert.SerializeObject(cardObject); //修正
client.Headers[HttpRequestHeader.ContentType] = "application/json;charset=UTF-8";
client.Headers[HttpRequestHeader.Accept] = "application/json";
client.Encoding = Encoding.UTF8;
client.UploadString(url, "POST", json);
}
}
catch (Exception e)
{
new SysLogModel(context, e);
}
});
}
}
完成
- あとは、WebDeployでAzureに発行すれば、完成です。
- 通知のイメージは以下のようになります。
- Viewボタンを押せば、プリザンターのEditページを開けるようにしました。
- 更新者名も表示するようにしました。
まとめ
-
Microsoft Teams
も使用したことがなかったのですが、改めてそちらも覚えることが多々ありそうです。 - いろいろ活用場面がありそうなので、しばらく検証期間としてAzure上に立てて目下検証中です。
-
プリザンター
は、実に素晴らしいソフトウェアです。- ただ我儘を言えば、
- もう少しAPIについて機能追加がされればよいなとは、思います。。。
- 認証もAzureADの認証が増えればよいなぁとも思います。
- GitHub上がマスターバージョンのみってのも前のバージョンが落とせないので、バージョンアップさせにくいです。
- ただ我儘を言えば、
追記(2019/01/08)
- Usingが漏れていたので修正しました。
- Context内にUser情報があったので、パラメータから外しました。