簡易な業務のWeb化に使えるOSS「プリザンター」作ってみた

## はじめに
ファイルサーバ、電子メール、そしてExcel。多くのデスクワーカーが扱える汎用的なツールとして様々な業務に利用されています。一方、データ量が多いケースや更新頻度が高いケース、利用者が多いケース等において専用の業務アプリが必要とされています。

ところが業務アプリの開発には沢山お金がかかります。そのためIT予算が確保できない組織では、無理やりExcel等で業務を組み立てる事が多いのではないでしょうか。無理なIT化は、作業効率の低下、作業品質の悪化、担当者の疲弊といった問題を引き起こします。なんとかならないものでしょうか。

## プリザンターとは
こうした問題を解決するため、プログラムを書かずに業務用のWebアプリを開発できるツールが増えてきました。そのため、簡易的な業務であればWeb化する事が容易になってきています。プリザンターは、この分野における1つの選択肢となる事を目指して作ってみました。主に以下のようなニーズに対応します。

| 項目       | 説明                          |
|:-----------|:------------------------------|
|ローカル環境|インストールして利用できる     |
|Windows OS  |Linuxがわからなくても利用できる|
|OSS        |MITライセンス                  |

## GitHub
ソースコードやセットアップ方法等は**[GitHub](https://github.com/Implem/Implem.Pleasanter/blob/master/README.md)**をご参照ください。

## 機能概要
プリザンターは主にファイルサーバ、電子メール、Excelで行われている業務のWeb化を目的とした機能を備えています。表形式やテキスト形式のデータの記録及び、データを活用したマネジメントを支援します。Excel等の汎用ツールではやりにくかった、多人数による頻繁な更新、[バージョン](#バージョン)管理、横断的な[キーワード検索](#キーワード検索)、自動的な更新[通知](#通知)といった機能も備えています。

現状はプロジェクトマネジメントを支援する機能が中心となっていますが、今後は**「マネジメント快適化」**をキーワードに業務で利用するWebアプリに必要な機能を拡充していく予定です。

## 機能一覧
プリザンターの機能一覧です。

| 項目               | 説明                                  |
|:-------------------|:--------------------------------------|
|[サイトツリー](#サイトツリー)|ファイルサーバのような階層構造|
|[サイト](#サイト)|情報の入れ物|
|[サイト設定](#サイト設定)|[サイト](#サイト)のカスタマイズ|
|[期限付きチケット](#期限付きチケット)|タスク管理など期限のあるデータを表形式で管理するチケットの入れ物|
|[記録チケット](#記録チケット)|顧客リストなど期限の無いデータを表形式で管理するチケットの入れ物|
|[Wiki](#Wiki)|[マークダウン](#マークダウン)記法に対応したマニュアルやリンク集のページ|
|[カスタムフィールド](#カスタムフィールド)|[期限付きチケット](#期限付きチケット)等のカスタマイズ可能な入力フィールドの設定|
|[フィルタ](#フィルタ)|[期限付きチケット](#期限付きチケット)等のフィルタリング|
|[ソータ](#ソータ)|[期限付きチケット](#期限付きチケット)等の[チケット一覧](#チケット一覧)の並び替え|
|[データビュー](#表示)|[期限付きチケット](#期限付きチケット)等の表形式を[チケット一覧](#チケット一覧)、[ガントチャート](#ガントチャート)、[バーンダウンチャート](#バーンダウンチャート)、[時系列チャート](#時系列チャート)、[カンバン](#カンバン)に切り替え|
|[チケット一覧](#チケット一覧)|[期限付きチケット](#期限付きチケット)等の表形式による一覧表示|
|[ガントチャート](#ガントチャート)|[期限付きチケット](#期限付きチケット)のガントチャート表示|
|[バーンダウンチャート](#バーンダウンチャート)|[期限付きチケット](#期限付きチケット)のバーンダウンチャート表示|
|[時系列チャート](#時系列チャート)|[期限付きチケット](#期限付きチケット)等のチケットの件数または数値フィールドの合計、平均、最大、最小を面グラフで表示|
|[カンバン](#カンバン)|[期限付きチケット](#期限付きチケット)等の状況やカスタムフィールドの分類をカンバン表示|
|[集計](#集計)|[期限付きチケット](#期限付きチケット)等の件数または数値フィールドの合計、平均、最大、最小を分類毎に集計して表示|
|[リンク](#リンク)|[期限付きチケット](#期限付きチケット)等でサイト間のチケットの親子関係を設定|
|[サマリ](#サマリ)|[リンク](#リンク)しているチケットの件数または数値フィールドの合計、平均、最大、最小を[カスタムフィールド](#カスタムフィールド)に格納|
|[計算式](#計算式)|[期限付きチケット](#期限付きチケット)等で四則演算の結果を[カスタムフィールド](#カスタムフィールド)に格納|
|[通知](#通知)|[期限付きチケット](#期限付きチケット)等でチケットの追加、変更、削除をSlackまたはメールで通知|
|[インポート](#インポート)|[期限付きチケット](#期限付きチケット)等をCSVファイルからインポート|
|[エクスポート](#エクスポート)|[期限付きチケット](#期限付きチケット)等をCSVファイルにエクスポート|
|[メール](#メール)|[期限付きチケット](#期限付きチケット)等からメールを送信|
|[コメント](#コメント)|[期限付きチケット](#期限付きチケット)等にコメントを追加|
|[分割](#分割)|[期限付きチケット](#期限付きチケット)を複数のチケットに分割|
|[バージョン](#バージョン)|[期限付きチケット](#期限付きチケット)等の更新履歴の保存と参照|
|[スクリプト](#スクリプト)|[サイト](#サイト)単位に設定可能なカスタムJavaScript|
|[スタイル](#スタイル)|[サイト](#サイト)単位に設定可能なカスタムCSS|
|[キーワード検索](#キーワード検索)|チケットやWikiの横断検索|
|[マークダウン](#マークダウン)|マークダウン記法でテキストをスタイリング|
|[アクセス制御](#アクセス制御)|[サイト](#サイト)単位に利用者の権限を設定|
|[認証](#認証)|ローカル認証、LDAP認証|
|[マルチ言語](#マルチ言語)|日英（拡張可能）|

## 各機能の概要説明と動画による動作イメージ

### サイトツリー
ファイルサーバのように階層的なデータ構造を提供します。この階層構造の中に[サイト](#サイト)を格納する事ができます。各[サイト](#サイト)はドラッグアンドドロップにより並び替えや、上層、下層への移動ができます。階層の深さに制限はありません。[サイト](#サイト)の移動や並び替えを行ってもURLは変更されません。

**動画による動作イメージ：** サイトの並び替え、下層への移動、上層への移動を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/8ee3d7b9-30b1-10a7-a4cc-3f3da296891a.gif

### サイト
[サイトツリー](#サイトツリー)の構成要素です。サイトの種別によって格納できる情報が異なります。[サイト設定](#サイト設定)や[アクセス制御](#アクセス制御)は、この単位に行います。各サイトには、最終更新日時からの経過時間、配下の情報の数、期限を超過したチケットの数が表示されます。サイトを削除すると配下の情報が全て削除されます。

サイトの種別

| 項目               | 説明                      |
|:-------------------|:--------------------------|
|サイト|階層的にサイトを格納できる情報の入れ物|
|[期限付きチケット](#期限付きチケット)|タスク管理など期限のあるデータを表形式で管理するチケットの入れ物|
|[記録チケット](#記録チケット)|顧客リストなど期限の無いデータを表形式で管理するチケットの入れ物|
|[Wiki](#Wiki)|[マークダウン](#マークダウン)記法に対応したマニュアルやリンク集のページ|

**動画による動作イメージ：** 新しい記録チケットの作成を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/c76df445-1cbe-4496-c238-d2b88bffd56d.gif


### サイト設定
各[サイト](#サイト)で使用する[カスタムフィールド](#カスタムフィールド)等、様々なカスタマイズを行う事で、簡易的なWebアプリを開発できます。[サイト](#サイト)種別によって設定できる項目が異なります。サイトをコピーするとサイト設定を引き継いだ別の[サイト](#サイト)を作成する事ができます。

サイト設定の内容

| 項目               | 説明                                  |
|:-------------------|:--------------------------------------|
|全般|サイトの名称、説明の設定|
|サイト画像|サイトに表示するアイコン画像の設定|
|一覧画面|[チケット一覧](#チケット一覧)に表示するフィールド、[フィルタ](#フィルタ)に使用するフィールド、[集計](#集計)等の設定|
|編集画面|編集画面に表示するフィールド、[リンク](#リンク)に表示するフィールド、[バージョン](#バージョン)に表示するフィールド、[計算式](#計算式)の設定|
|[サマリ](#サマリ)|[リンク](#リンク)しているチケットの件数または数値フィールドの合計、平均、最大、最小を[カスタムフィールド](#カスタムフィールド)に格納するための設定|
|[通知](#通知)|チケットの追加、変更、削除をSlackまたはメールで通知するための設定|
|[メール](#メール)|アドレス帳、既定の宛先の設定|
|[スクリプト](#スクリプト)|カスタムJavaScript|
|[スタイル](#スタイル)|カスタムCSS|

**動画による動作イメージ：** 編集画面に[カスタムフィールド](#カスタムフィールド)を追加して、機能分類というフィールド名を設定し、選択肢一覧の設定を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/12a31323-f588-0b92-1db7-a2e6e058cfee.gif

### 期限付きチケット
タスク管理など期限のあるデータを表形式で管理するチケットの入れ物です。Excelの表などで管理している業務をWeb化する際に使用します。[サイトツリー](#サイトツリー)に[期限付きチケット](#期限付きチケット)を追加したあと、[サイト設定](#サイト設定)により[カスタムフィールド](#カスタムフィールド)等の設定を行うことで、簡易的なWebアプリを開発できます。基本機能として、作成、変更、削除、一括削除、コピー、移動、一括移動、[フィルタ](#フィルタ)、[ソータ](#ソータ)、[データビュー](#データビュー)、[集計](#集計)、[リンク](#リンク)、[サマリ](#サマリ)、[計算式](#計算式)、[通知](#通知)、[キーワード検索](#キーワード検索)、[インポート](#インポート)、[エクスポート](#エクスポート)、[メール](#メール)、[分割](#分割)、[バージョン](#バージョン)、[コメント](#コメント)が使用できます。開始、完了、作業量、進捗率の各フィールドを変更すると[ガントチャート](#ガントチャート)や[バーンダウンチャート](#バーンダウンチャート)等の[データビュー](#データビュー)に反映します。

**動画による動作イメージ：** [チケット一覧](#チケット一覧)からチケットを開き、進捗率と状況を変更し、[コメント](#コメント)を追加する操作を行っています。プロジェクト管理のWBS(Work Breakdown Structure)を想定し[期限付きチケット](#期限付きチケット)をカスタマイズしたWebアプリです。編集画面のカスタマイズにより[カスタムフィールド](#カスタムフィールド)として作業工程、作業内容、機能分類が表示されています。
https://qiita-image-store.s3.amazonaws.com/0/78230/a58109a9-18ee-a120-fc0d-82d02f021fcf.gif

### 記録チケット
[期限付きチケット](#期限付きチケット)から期限を管理する機能群を除外したチケットの入れ物です。同様に[サイト設定](#サイト設定)により、簡易的なWebアプリを開発できます。

### Wiki
[マークダウン](#マークダウン)記法に対応したマニュアルやリンク集を作成できるページです。基本機能として、作成、変更、削除、[通知](#通知)、[キーワード検索](#キーワード検索)、[メール](#メール)、[バージョン](#バージョン)、[コメント](#コメント)が使用できます。[期限付きチケット](#期限付きチケット)等の分類フィールドの外部マスタデータとして使用する事もできます。Wikiによる外部マスタデータを使用すると、ユーザ選択の表示順を指定したり、複数の[サイト](#サイト)の分類フィールドを一元管理する事ができます。

**動画による動作イメージ：** 新しいWikiを作成し[マークダウン](#マークダウン)による表を使用した内容を保存しています。
https://qiita-image-store.s3.amazonaws.com/0/78230/862eceb4-572e-42a6-e577-dab2346cbb32.gif

### カスタムフィールド
[期限付きチケット](#期限付きチケット)等に、フィールドを追加する事ができます。フィールドは5種類あり、それぞれ異なる機能を提供します。種類毎に最大26フィールド（全130フィールド）が使用できます。各フィールドは有効化/無効化、表示順、フィールド名や既定値など詳細な設定が行えます。これらを組み合わせる事で、Excelの列に相当する入力フィールドを[サイト](#サイト)単位にカスタマイズする事ができます。

カスタムフィールドの種類

| 項目               | 説明                      |
|:-------------------|:--------------------------|
|分類|テキストフィールドまたは選択フィールドを提供、選択フィールドは[フィルタ](#フィルタ)、[集計](#集計)、[ガントチャート](#ガントチャート)、[バーンダウンチャート](#バーンダウンチャート)、[時系列チャート](#時系列チャート)、[カンバン](#カンバン)等に使用|
|数値|整数、少数のフィールドで[集計](#集計)、[計算式](#計算式)、[サマリ](#サマリ)等に使用|
|日付|日付フィールドで[フィルタ](#フィルタ)等に使用|
|説明|テキストエリアフィールドで[マークダウン](#マークダウン)記法等に使用|
|チェック|チェックボックスフィールドで[フィルタ](#フィルタ)等に使用|

**動画による動作イメージ：** 編集画面に複数のチェックフィールドを追加する設定を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/210b0121-33e5-6339-6137-388ab7a3368d.gif

### フィルタ
[期限付きチケット](#期限付きチケット)等の[チケット一覧](#チケット一覧)を絞り込んで表示します。全ての[データビュー](#データビュー)で使用できます。チェックボックスの選択、ドロップダウンリストからの選択、キーワード入力を組み合わせて絞り込みを行います。フィルタは画面遷移をしても保持されます。フィルタした状態で編集画面に遷移すると、次ボタンと前ボタンで移動できる範囲も絞り込んだチケットに限定されます。

**動画による動作イメージ：** 期限が近いチケット、期限が超過しているチケット、機能分類の選択、検索キーワードの組み合わせでフィルタリングを行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/5134eb6f-8a85-46f0-fbe1-8bb2c5c1b66c.gif

### ソータ
[期限付きチケット](#期限付きチケット)等の[チケット一覧](#チケット一覧)を任意の順序にソートします。複数のフィールドを組み合わせてソートする事できます。既定では保存された日時が新しい順に表示されます。ソータは画面遷移をしても保持されます。ソートした状態で編集画面に遷移すると、次ボタンと前ボタンで移動する順番もソートされます。

**動画による動作イメージ：** 担当者と作業量の降順でソートし、その後ソート順をリセットしています。
https://qiita-image-store.s3.amazonaws.com/0/78230/ac61f3a8-4138-7c7f-2be9-0d262747cd19.gif

### データビュー
[期限付きチケット](#期限付きチケット)等のビュー形式を切り替えます。[チケット一覧](#チケット一覧)、[ガントチャート](#ガントチャート)、[バーンダウンチャート](#バーンダウンチャート)、[時系列チャート](#時系列チャート)、[カンバン](#カンバン)から選択できます。[ガントチャート](#ガントチャート)、[バーンダウンチャート](#バーンダウンチャート)は、[記録チケット](#記録チケット)では使用出来ません。各ビューの上部には[フィルタ](#フィルタ)及び[集計](#集計)が共通的に表示されます。

**動画による動作イメージ：** ビューの切り替えを行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/727565f3-3b4b-864c-7c57-d7d437f33ead.gif

### チケット一覧
[期限付きチケット](#期限付きチケット)等を表形式で表示します。コメントフィールド等のテキスト量が多い場合は、先頭部分のみを表示しマウスオーバー時に全体を表示します。スクロールを行うと次のページのデータをロードします。[フィルタ](#フィルタ)を操作することで条件に合ったデータを抽出できます。[ソータ](#ソータ)を操作する事で任意のフィールドによる並び替えができます。[サイト設定](#サイト設定)により表示するフィールドをカスタマイズする事ができます。チェックボックスで選択したチケットの一括移動、一括削除を行う事ができます。CSVによる[インポート](#インポート)や[エクスポート](#エクスポート)もこの画面から行えます。

**動画による動作イメージ：** チケット一覧で[フィルタ](#フィルタ)を使用して目的のチケットを抽出し、編集画面に遷移する操作を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/e188b483-3a96-5cf1-eb51-7fadb37c153a.gif

### ガントチャート
[期限付きチケット](#期限付きチケット)をガントチャートの形式で表示します。ブルーのバーは完了、グリーンのバーは予定より前倒し、ピンクのバーは予定より遅延している事を表します。[フィルタ](#フィルタ)を操作することで条件に合ったデータを抽出できます。また、分類フィールドを使ってカテゴリ別や担当者別にグループ化して表示する事ができます。各チケットをクリックすると編集画面に遷移します。

**動画による動作イメージ：** ガントチャートを表示して[フィルタ](#フィルタ)の適用と解除、作業工程や担当者によるグループ表示を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/22ea31dc-93ae-196e-315d-976e78862111.gif

### バーンダウンチャート
[期限付きチケット](#期限付きチケット)をバーンダウンチャートの形式で表示します。グレーの線は予定、オレンジの線は実績、グリーンの線は作業の総量の推移を表しています。[フィルタ](#フィルタ)と組み合わせることで条件に合わせた表示を行う事ができます。チャートの下部には明細テーブルが表示されます。明細テーブルには1日単位、担当者単位の進捗量を表示するため、数字の内訳を確認する事ができます。明細行をクリックすると、進捗のあったチケットのタイトルと進捗量を表示します。各チケットをクリックすると編集画面に遷移します。

**動画による動作イメージ：** バーンダウンチャートを表示して[フィルタ](#フィルタ)の適用と解除、明細テーブルから過去3日間の、担当者別、チケット別の進捗状況を表示しています。
https://qiita-image-store.s3.amazonaws.com/0/78230/d52879f1-7061-2b95-b3b4-573f9900b9a3.gif

### 時系列チャート
[期限付きチケット](#期限付きチケット)等で[バージョン](#バージョン)に保存されたチケットの更新履歴を、時系列に面グラフとして表示します。縦軸は、件数または任意の数値フィールドの合計、平均、最大、最小を切り替える事ができます。また、分類フィールドを選択する事でカテゴリ別や担当者別の表示に切り替える事ができます。

**動画による動作イメージ：** 時系列チャートを表示して[フィルタ](#フィルタ)の適用と解除、分類フィールドによる切り口の変更、集計する数値データの変更を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/3d54194d-10c5-29ca-97fd-89f2fb26984f.gif

### カンバン
[期限付きチケット](#期限付きチケット)等でカンバンを表示します。カンバンは状況別だけでなくカテゴリ別や担当者別に表示する事ができます。[カスタムフィールド](#カスタムフィールド)で分類フィールドを追加するとカンバンの種類を増やすことができます。また、各カンバンのヘッダに任意の数値フィールドの合計、平均、最大、最小を切り替える事ができます。カンバンに表示されたチケットはドラッグアンドドロップで移動する事ができます。カンバン上でチケットの移動を行うと、チケットの内容が即座に変更されます。

**動画による動作イメージ：** カンバン表示でチケットの状況を変更した後、担当者別カンバンに切り替えて担当者の変更を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/5a6f61bf-8a27-df68-bbd2-0f5c6219ae68.gif

### 集計
[期限付きチケット](#期限付きチケット)等でチケットの件数または任意の数値フィールドの合計、平均、最大、最小の集計を行います。また分類フィールドと組み合わせることで、グループ化した単位に集計結果を表示できます。[フィルタ](#フィルタ)を使用するとフィルタリングされたデータで再集計を行います。グループ化した集計をクリックすると、その項目によるフィルタの適用/解除を行う事ができます。

**動画による動作イメージ：** [サイト設定](#サイト設定)で作業工程別の残作業量を集計に表示する設定を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/0195218f-e042-e8be-e3b1-d5fd5d52435e.gif

### リンク
[期限付きチケット](#期限付きチケット)等で[サイト](#サイト)間のチケットの親子関係を設定する事ができます。子[サイト](#サイト)の[サイト設定](#サイト設定)の分類フィールドに親[サイト](#サイト)のIDを指定することで設定します。[サイト](#サイト)間の親子関係が設定されると、親となる[サイト](#サイト)のチケット編集画面に、子チケットを作成するボタンが表示されます。このボタンから子チケットを作成すると親子双方のチケット編集画面に相互リンクが作成されます。相互リンクの一覧に表示するフィールドは[サイト設定](#サイト設定)によりカスタマイズできます。

**動画による動作イメージ：** WBS[サイト](#サイト)のチケットに、課題管理[サイト](#サイト)のチケットを関連付けて作成しています。双方のチケットに作成された相互リンクを確認しています。
https://qiita-image-store.s3.amazonaws.com/0/78230/ef6633c7-5820-b4de-2be5-fdadd2f6347c.gif

### サマリ
[期限付きチケット](#期限付きチケット)等で[リンク](#リンク)された子チケットの件数または数値フィールドの合計、平均、最大、最小を親チケットの[カスタムフィールド](#カスタムフィールド)に格納します。サマリはリンク先の子チケットが追加、変更、削除された際に動作しますが、サマリの設定を行う前に子チケットが存在している場合には、同期機能により親チケットを一括更新する事ができます。

**動画による動作イメージ：** レビュー記録[サイト](#サイト)のサマリ設定を行い、同期機能を使ってWBS[サイト](#サイト)のレビュー件数フィールドにレビュー記録のチケットの件数を格納しています。
https://qiita-image-store.s3.amazonaws.com/0/78230/657875e2-79c5-43f1-9238-8c41ff8de28d.gif

### 計算式
[期限付きチケット](#期限付きチケット)等で任意の数値フィールドの四則演算を行います。括弧を使って計算の優先順位を指定できます。計算にはフィールドに格納された数値及び定数を指定する事ができます。現在のところ関数を使用する事はできません。計算式はチケットが追加、変更、削除された際に動作しますが、計算式の設定を行う前にチケットが存在している場合には、同期機能により一括更新する事ができます。

**動画による動作イメージ：** WBS[サイト](#サイト)に「レビュー密度 = レビュー件数 / 作業量 * 100」という計算式を設定し、同期機能を使ってWBSのレビュー密度を更新しています。
https://qiita-image-store.s3.amazonaws.com/0/78230/89466fe0-2a47-726c-c2c1-44c5f63f787c.gif

### 通知
[期限付きチケット](#期限付きチケット)等でチケットの登録、更新、削除時にSlackまたはメールに自動通知を行います。Slackの場合は事前にWebHookを作成しておきます。メールの場合はメーリングリスト等を使用します。通知はチケットが追加、変更、削除された際に動作します。変更による通知は、変更を監視する項目に指定したフィールドが変更された場合のみ通知が行われます。

**動画による動作イメージ：** メールによる通知の設定を行っています。プレフィックスに入力した文字はメールのタイトルの先頭に記載されます。
https://qiita-image-store.s3.amazonaws.com/0/78230/234431ab-38d2-3839-5b61-edc36185baad.gif

### インポート
[期限付きチケット](#期限付きチケット)等に、CSV形式のデータをチケットとして取り込む事ができます。CSVの文字コードはShift-JISまたはUTF-8が使用できます。CSVの1行目には、各フィールドの名前を入れる必要があります。[サイト](#サイト)に存在しないフィールド名は無視されます。またサイトIDやチケットのIDは無視されます。既存のチケットを更新する事はできません。

**動画による動作イメージ：** CSVファイルのインポート操作を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/4ee99fbb-56f8-db66-09ed-6f011723f5cf.gif

### エクスポート
[期限付きチケット](#期限付きチケット)等のチケットをCSV形式で出力します。フィールドの順番や出力の要否を設定する事ができます。また設定した状態に名前をつけて保存しておく事ができます。設定は複数保存する事ができ、必要な設定を呼び出してエクスポートを行うことができます。

**動画による動作イメージ：** 内容フィールドを非表示にした設定を保存し、その後CSVファイルのエクスポート操作を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/eb2f4060-966a-9376-0072-cd3b38ec3730.gif

### メール
[期限付きチケット](#期限付きチケット)等の各チケットからメールを送信できます。メールにはチケットのURLが自動挿入されるため、メールの受信者は容易にチケットにアクセスできます。宛先は[サイト設定](#サイト設定)のアドレス帳及び既定の宛先に登録しておく事ができます。メールで送信した内容はチケット編集画面に表示されます。またメールの内容をキーワードに[キーワード検索](#キーワード検索)を行う事ができます。メールの転送先にはSMTPサーバまたはSendGridを使用する事ができます。

**動画による動作イメージ：** チケットからメール送信しています。その後、送信したメールの内容が編集画面の下部に表示されている事を確認しています。
https://qiita-image-store.s3.amazonaws.com/0/78230/675d4bce-a630-de24-8d55-75b233e8b2ef.gif

### コメント
[期限付きチケット](#期限付きチケット)等の各チケットにコメントを追加できます。コメントには自動的に日時と名前が挿入されます。コメントは[マークダウン](#マークダウン)記法で入力する事ができます。コメントに入力したURLやUNCパスは自動的にハイパーリンクとして表示されます。また、メールで受信した内容など長文を記入する事ができます。コメントに長文を入力した場合、チケット一覧上では先頭のみが表示され、マウスオーバーを行う事で全体を広げて表示します。コメントは削除できますが、追加後に編集することはできません。

**動画による動作イメージ：** チケットにコメントを記入した後、[チケット一覧](#チケット一覧)で内容の確認を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/294403c5-2f21-616a-5a55-b771bbe0272f.gif

### 分割
[期限付きチケット](#期限付きチケット)でチケットを分割する事ができます。分割する際にはタイトルの編集と作業量の割り振りを行う事ができます。分割されたチケットにはコメント欄に各チケットへのリンクが自動的に挿入されます。

**動画による動作イメージ：** チケットを3つに分割した後、[チケット一覧](#チケット一覧)で内容の確認を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/f5e72c03-e185-7e5b-53a8-db90ab8e5e3e.gif

### バージョン
チケットやWikiの変更の際に変更前のデータを旧バージョンとして保存します。保存した旧バージョンのデータはバージョン一覧で変更点を一覧で確認したり、開いて詳細な内容を確認する事ができます。バージョンは新バージョンで保存するチェックをつけた場合に追加されます。日を跨いでチケットを保存する場合、最後の保存者と現在の利用者が異なる場合はチェックを外す事ができません。そのため自動的にバージョンが追加されます。

**動画による動作イメージ：** チケットの過去の履歴を参照しています。
https://qiita-image-store.s3.amazonaws.com/0/78230/90efc529-a502-c9b1-f6d9-e7e3f8a155bb.gif

### スクリプト
[期限付きチケット](#期限付きチケット)等の[チケット一覧](#チケット一覧)、新規登録画面、編集画面に、JavaScriptを挿入する事ができます。

### スタイル
[期限付きチケット](#期限付きチケット)等の[チケット一覧](#チケット一覧)、新規登録画面、編集画面に、CSSを挿入する事ができます。

### キーワード検索
チケットに書き込んだ内容及び[コメント](#コメント)、[メール](#メール)等で記録された内容を、サイト横断で検索する事ができます。キーワードをスペースで区切るとand条件で検索できます。IDやタイトルにヒットした情報は上位に表示されます。検索結果はスクロール操作により次のページがロードされます。アクセス権の無い[サイト](#サイト)のデータは検索結果に表示されません。

**動画による動作イメージ：** 「ネットワーク テスト」というキーワードで検索を行い、ヒットしたチケットを開いています。
https://qiita-image-store.s3.amazonaws.com/0/78230/11327031-2f80-7b75-6344-b31ac1454670.gif

### マークダウン
マークダウン記法を使用しテキストのスタイリングを行う事ができます。[コメント](#コメント)や説明フィールドはマークダウン記法が使用できます。マークダウン書式を使用する場合には行頭に[md]と記述します。[md]と記述しない場合には通常のテキストとなるため、改行などがそのまま表示されます。

**動画による動作イメージ：** チケットにマークダウン記法を使用してコメントを記入した後、[チケット一覧](#チケット一覧)で内容の確認を行っています。
https://qiita-image-store.s3.amazonaws.com/0/78230/d2d4d8c8-f3f3-988e-9fd3-5cf31bbdd58a.gif

### アクセス制御
[サイト](#サイト)単位に利用者を制限する事ができます。[サイトツリー](#サイトツリー)のトップに[サイト](#サイト)を作成すると、作成者が管理者となります。2階層目以降に[サイト](#サイト)を作成すると1階層目の[サイト](#サイト)の権限設定を継承します。継承をはずす事もできます。アクセス権はユーザ単位またはユーザが所属する組織の単位に設定します。

権限は以下のとおりです。

| 項目               | 説明                      |
|:-------------------|:--------------------------|
|管理者|リーダーの権限に加え、サイトのアクセス権の設定が行える|
|リーダー|書き込みの権限に加え、インポート、エクスポート、サイト設定が行える|
|書き込み|読取りの権限に加え、書き込み及びメールの送信が行える|
|読取専用|読取りが行える|

**動画による動作イメージ：** demoプロジェクトのサイトのアクセス権に、読み取り専用として佐藤さんを追加しています。
https://qiita-image-store.s3.amazonaws.com/0/78230/ff959b54-f4d9-8442-f8c4-f3338e30a91e.gif

### 認証
認証はローカルユーザによる認証か、外部のActiveDirectory等LDAPによる認証を使用できます。現在のところ併用することはできません。

### マルチ言語
ユーザ単位に言語を切り替えて使用する事ができます。言語の切り替えはプロファイル画面から行います。現在は英語及び日本語に対応していますが、設定ファイルを編集することで中国語や韓国語など他の言語に対応する事ができます。

## 具体的な使い方
[プロジェクトマネジメントにおける実践的なデータ活用例](http://qiita.com/Implem/items/112bfd38433f7f5d7bb8)

## 動作条件
|条件|Windows Server 2012 R2|Windows 10|Microsoft Azure|
|:--|:--:|:--:|:--:|
|.NET Framework 4.5|導入済|導入済|-|
|IIS|◯|◯|-|
|ASP.NET 4.5|◯|◯|-|
|SQL Server 2012/2014/2016|◯|◯|-|
|Web Deploy v3.5|◯|◯|-|
|Microsoft Azure Web App|-|-|◯|
|Microsoft Azure SQL Database|-|-|◯|

## 開発環境
### 開発言語
- C# 6.0
- JavaScript

### 開発フレームワーク
- ASP.NET MVC

### 参照ライブラリ（サーバーサイド）
- DocumentFormat.OpenXml
- EnterpriseLibrary.TransientFaultHandling
- EnterpriseLibrary.TransientFaultHandling.Data
- Newtonsoft.Json
- SendGrid
- IX-Main
- kanaxs C# 拡張版

### 参照ライブラリ（クライアントサイド）
- jQuery v3.1.0
- jQuery UI - v1.12.0
- jQuery Validation Plugin - v1.15.0
- jQuery MultiSelect UI Widget 1.16pre
- marked.js
- d3.js

## 内部の仕組みについて
### 動的な入力フォーム等を実現するためにやったこと
プリザンターのデータベースには[SiteSettings](https://github.com/Implem/Implem.Pleasanter/blob/master/Implem.Pleasanter/Libraries/Settings/SiteSettings.cs)という[サイト設定](#サイト設定)用のクラスをJson化したデータを保持しています。Jsonデータには、フォーム上に表示するフィールドの種類、名前、順番、UIの種類やデザイン等を示す設計データが格納されています。[スクリプト](#スクリプト)等もこの中に格納されます。プリザンターが画面を表示する際、これらの設計情報に基づいたHTMLを生成します。

当初はこれをASP.NET MVCのRazorを使って実現しようとしたのですが、力量が足りず断念しました。そこで、StringBuilderを使用して生のHTMLを一筆書きで作成するための[ビューエンジン](https://github.com/Implem/Implem.Pleasanter/tree/master/Implem.Pleasanter/Libraries/Html)を作りました。C#のラムダ式とメソッドチェーンを使い、文字列結合でタグの木構造を生成しています。

データ層は[期限付きチケット](#期限付きチケット)と[記録チケット](#記録チケット)のテーブルに130のnull許容カラムを追加しました。[カスタムフィールド](#カスタムフィールド)のデータはここに格納しています。毎回130カラムを更新するのは効率が悪いので、変更点だけ更新する仕組みを作りました。モデルクラス内で変更前のデータとフォームから送信されたデータを比較して、変更箇所のみ更新するSQLを動的に生成できるようにしました。このあたりはEntity Frameworkを使えばもっとシンプルに実装できたかもしれません。

また、テーブルのカラム数が多いアプリを作ろうとすると、O/Rマッピングのような単純なコードの羅列が頻出するので、手作業でのコーディングが辛いです。そのため[パターン化が可能な部分のコードを自動生成するための仕組み](https://github.com/Implem/Implem.Pleasanter/tree/master/Implem.CodeDefiner)を作りました。後から知ったのですがVisual StudioのT4というものを使えば、自作しなくてもよかったかもしれないと反省しています。

## おわりに
[プリザンター](https://github.com/Implem/Implem.Pleasanter)は約2年くらい前から開発しており、近頃ようやく形になってきました。車輪の再発明的な事をしているので、オープンソースとしてはあまり参考にならないかもしれませんが、これからも時間をかけて少しずつ育てていきたいと考えております。