Title: タスクの投稿/編集フォームや表示をカスタマイズするには
注意
ここで紹介しているカスタマイズ方法は TeamPage 5.0 時代のものです。現行の TeamPage 6.2 でも動作しますが、推奨されません。TeamPage 6.2 でのカスタマイズ方法は、下記リンク先ページで解説しています。
タスク、プロジェクト、マイルストーンなどの投稿/編集フォーム(GWTフォーム)の項目やデザインは、次の3つのファイルで定義されています。
- フォームの定義ファイル (FormName.properties)
- XML テンプレート用ファイル (フォーム名.sdl)
- HTML レンダリング用ファイル (オプション)
これらのファイルを編集することで、フォームに新しい項目を追加したり既存の項目を削除(非表示)したりできます。
ここでは、タスクの投稿/編集フォームに「管理番号」と「問い合わせ」の入力欄を追加した「問い合わせチケット (Inquiry Ticket)」を作成する例で解説します。
メモ
ここで作成する「inquiryticket」は、「タスクの一種であるが、標準のタスクとは別のもの」になります。標準のタスクをそのまま残し、新たに「改造版タスク」を追加するカスタマイズです。一方、下記のリンク先記事では、「標準のプロジェクトを改造する方法(別の改造版プロジェクトを作らない方法)」を解説しています。
注意: ここでは TeamPage 6.0.06 を使って説明します。他のバージョンでは、設定ファイルの記述や必要なファイルの名前などが異なる場合があります。
変更内容をプラグインとして組み込む
参照 : FAQ1683: TeamPage プラグイン概要
上書きを避けるためのプラグイン化
タスクの投稿/編集フォームのテンプレートは、TeamPage がインストールされた server ディレクトリ下の、config/data/forms フォルダにある taskinline.sdl です。 このファイルを直接編集しないよにしましょう。何故なら、TeamPage をバージョンアップするときに taskinline.sdl が上書きインストールされてしまい、せっかくの編集内容が消えてしまうからです。
バージョンアップによる上書きを避けるため、バージョンアップでは上書きされない場所に taskinline.sdl をコピーし、そのコピーされたファイルを編集します。その上書きされない場所が、server ディレクトリの「plugins」フォルダです。ここに必要なファイルをコピーして編集する作業が、いわゆるプラグイン開発になります。
プラグイン開発で初めにやること
通常、サブフォルダ名は開発者(開発社)の「ドメイン名を逆にしたもの+プラグイン名称」にします。
例えば、今回作るプラグイン名称を「form.inquiryticket」、自社のドメイン名が「traction.com」だとすると、プラグインのサブフォルダ名は「com.traction.form.inquiryticket」になります。
新規作成したサブフォルダ「com.traction.form.inquiryticket」の中に、プラグインの全般的な設定(名称やバージョン番号など)をする「plugin.properties」ファイルを作成します。
テキストエディタで開き、次のようなことを書いて保存します。「name」属性の値は、上記で作成したサブフォルダ名になります。バージョン番号などは適当にどうぞ。コメントとしてのメモを残しておくと(このスレッドの番号など)後から参照するときに便利です。
display_name=Inquiry Ticket Form Example
description=This plug-in allows you to use the inquiry ticket form and widget.
name=com.traction.form.inquiryticket
version=1.0
db_config=false
db_settings=
server_config=false
server_settings=
project_config=false
project_settings=
user_config=false
user_settings=
# メモ
# 行頭に「#」を付けるとコメントになります。
# 変更履歴や参照URLなどを書いておくと後々のためになります。
動作反映のためにキャッシュをクリアする
ファイルやフォルダを作成や保存したら、サーバーセットアップ > 一般 > サーバー管理 で [キャッシュクリア] を実行します。キャッシュクリアを実行後、サーバーセットアップ > プラグイン を開くと、「Inquiry Ticket Form Example」プラグインが表示されているはずです。
投稿/編集フォームのカスタマイズ
フォームの定義ファイル
フォームの定義ファイルは、server ディレクトリの下の、config/data/forms フォルダに置かれている拡張子 .properties ファイルです。
プラグインのサブフォルダ「com.traction.form.inquiryticket」の中に、これと同じ階層構造を作成し、その中に新しい「Inquiryticket」フォームの定義ファイルを設置します。すなわち、 config/data/forms のパスをサブフォルダ内に再現し、その中に inquiryticket.properties というファイルを作成します。
この inquiryticket.properties をテキストエディタで開いて次のように記述します。
__inherits=taskdialog
# フォームの表示名
display_name=Inquiry Ticket
# フォームの XML 定義ファイル (SDL ファイル)
xml=config.data.forms.inquiry-model
# フォームの HTML レンダリング定義ファイル (SDL ファイル)
sdl=config.data.forms.inquiry-view
# フォームで投稿されたエントリ(記事)の「種類」の定義
entry_custom_type=task
entry_class=inquiry
# フォームで投稿された記事本文に自動的に埋め込むトークンを指定
entry_content_append=[[ /token inquiry_info ]]
xml= 行で下記の「フォームの XML テンプレート」のファイルを指定しています。また、sdl= 行は下記の「フォームの HTML レンダリング」のファイルを指定しています。
どちらもフォルダの階層はドット記号で表され、最後の拡張子 .sdl は省略されます。例えば
xml=config.data.forms.inquiry-model
は、「config」フォルダの中の、「data」フォルダの中の、「forms」フォルダの中の、「inquiry-model.sdl」というファイル、という意味になります。
フォームの XML テンプレート
上記の xml= 行で指定されたファイルを作成します。今回の「inquiryticket」フォームは、既存のタスク用フォームをカスタマイズして作るので、既存のタスク用フォームの XML テンプレートファイルをコピーして編集することにします。
既存のタスクのフォームの XML テンプレートファイルは、server ディレクトリの下の config/data/forms フォルダにある taskinline.sdl です。このファイルを、プラグインのサブフォルダの、config/data/forms にコピーします。そして、ファイル名を inquiry-model.sdl に変更します。
inquiry-model.sdl をテキストエディタで開き、次のように記述します。(fields-basic、fields-details、fields-datesなどの不要な関数を削除します)
<?xml version="1.0"?>
<form title="Inquiry Ticket Editor" class="task-form-dialog fm-html fm-inquiry" save="#{Save}" width="800px" templates="true">
<#fields />
</form>
<sdl.function name="fields">
<config.data.forms.taskinline#fields-basic />
<config.data.forms.taskinline#fields-details />
<property.defined name="fqid">
<field tabindex="2026" type="text" name="property_edit_desc"></field>
</property.defined>
<#fields-inquiry />
</sdl.function>
<sdl.function name="fields-inquiry">
<field tabindex="2007" type="text" name="property_inquiryid" size="16"></field>
<field tabindex="2008" type="text" name="property_inquirername" size="16"></field>
</sdl.function>
「fields」関数の <config.data.forms.taskinline#fields-basic />
は、「server ディレクトリの下の、config の下の、data の下の、forms の中にある、taskinline.sdl の『fields-basic』という関数を呼び出せ」という意味です。
同じく「fields」関数の <#fields-inquiry />
は、「同じファイルの中の『fields-inquiry』関数を呼び出せ」という意味です。
その「fields-inquiry」関数では、「property_inquiryid」と「property_inquirername」という 2 つの名前のテキストボックスのフィールドを定義しています。名前が「property_」で始まるフィールドは、値が投稿時に エントリー プロパティ として保存されることを意味しています。
フィールドの設定についての詳細は field element を参照してください。
フォームの HTML レンダリング
前述の sdl= 行で指定されたファイルを作成します。
プラグインのサブフォルダの、config/data/forms の中に、次の内容のテキスト ファイルを inquiry-view.sdl という名前で保存します。
<#form>
<sdl.function name="form">
<gwt.rpc.form form="inquiryticket">
<#form-layout>
</gwt.rpc.form>
</sdl.function>
<sdl.function name="form-layout">
<div class="task-form expanded">
<com.traction.sdl.tasks.taskform#field-error />
<com.traction.sdl.tasks.taskform#destination classname="fm-loc">
<div class="o">
<com.traction.sdl.tasks.taskdialog#form-minimal />
<#form-expanded />
</div>
</div>
</sdl.function>
<sdl.function name="form-expanded">
<table width="100%" class="task-formlayout">
<com.traction.sdl.tasks.taskform#row-description>
<#row-inquiryid-inquirer />
<com.traction.sdl.tasks.taskform#row-labels-attachments>
<com.traction.sdl.tasks.taskform#row-assignee-priority-with-default>
<com.traction.sdl.tasks.taskform#row-subscribed-estimate>
<com.traction.sdl.tasks.taskform#row-start-duration>
<com.traction.sdl.tasks.taskform#row-due>
</table>
</sdl.function>
<sdl.function name="row-inquiryid-inquirer">
<tr>
<td class="td1 g"><label>Inquiry ID</label></td>
<td class="td2 g">
<gwt.rpc.field name="property_inquiryid"></gwt.rpc.field>
</td>
<td class="td3 g"><label>Inquirer Name</label></td>
<td class="td4 g">
<gwt.rpc.field name="property_inquirername"></gwt.rpc.field>
</td>
</tr>
</sdl.function>
1 行目の <#form> は、「同じファイル内の『form』という関数を呼び出せ」という意味です。
その「form」関数は、3 行目〜 7 行目で定義されています。ここでフォーム名を form="inquiryticket"
として指定しています。つまり、この inquiry-view.sdl で「●●フィールドを表示せよ」と指定すると、「inquiryticket」という名前のフォームは inquiryticket.properties で定義されているので、その inquiryticket.properties の xml= で定義された inquiry-model.sdl の中の「●●フィールド」が参照されます。
「form」関数からは「form-layout」関数が呼び出されており、その「form-layout」関数では、多くの部分が既存のタスク用フォームから流用されています。例えば、<com.traction.sdl.tasks.taskdialog#form-minimal />
は、「server ディレクトリの下の、src の下の、com の下の、traction の下の、sdl の下の、tasks の下の、taskdialog.sdl の中の、『form-minimal』関数を呼び出せ」という意味です。
「form-expanded」関数でも、多くの部分を既存のタスク用フォームから流用していますが、<#row-inquiryid-inquirer />
という行は例外で、これは「同じファイル内の『row-inquiryid-inquirer』関数を呼び出せ」という意味です。
その「row-inquiryid-inquirer」では、<gwt.rpc.field name="フィールド名"></gwt.rpc.field>
で、フォームに表示するフィールドを指定しています。上述の通り、ここで指定されたフィールドは、inquiryticket.properties の xml= で定義された inquiry-model.sdl の中のフィールドになります。
記事クラスの設定
記事クラス (Entry Class) とは、大雑把に説明すると、「記事の種類」「投稿の種類」のことです。TeamPage には「タスク」「プロジェクト」「近況アップデート」などの「種類」があります。これらは「カスタム エントリー タイプ」と呼ばれており、そのサブ的な種類として「記事クラス」を設定できます。今回は「タスク」のカスタム エントリー タイプの中に、新しい「inquiry」という名前の記事クラスを作成します。
フォームの定義ファイル config/data/forms/inquiryticket.properties で、このフォームを使って投稿される記事(エントリー)のクラス (Entry Class) を次のように「inquiry」としました。
entry_class=inquiry
この「inquiry」という Entry Class の定義ファイルを config/entry/classes フォルダに作成します。Entry Class 名が「inquiry」なので、ここで作成するファイルの名前は inquiry.properties になります。(EntryClass名.properties にします)
inquiry.properties をテキストエディタで開いて次のように記述します。
__inherits=task
display_name=Inquiry Ticket
# The config/data/forms FormFactory that is the default for creating
# entries that will have this custom entry type.
newentry_form=inquiryticket
# The config/data/forms FormFactory to use to edit entries that have
# this custom entry type.
editentry_form=inquiryticket
# The default link text to show for the new link or button.
newentry_link_text=New Inquiry Ticket
# The default link text to show for the edit link or button.
editentry_link_text=Edit Inquiry Ticket
ファイルを保存し、サーバーセットアップでキャッシュのクリアを実行してください。これで「inquiry」という名前の記事クラスを TeamPage が識別するようになりました。
セクションの追加ボタンで記事クラスを確認する
セクションの設定では、セクションの [追加] ボタンから追加(投稿)する記事クラス (Entry Class) を選択できます。別の言い方をすると、セクションの [追加] ボタンをクリックしたときに表示される投稿/編集フォームの種類を指定できます。
上記で「inquiry」という名前の Entry Class (表示名は「Inquiry Ticket」です)を定義したので、セクションの設定画面で選択できるようになりました。
このセクションの [追加] ボタンをクリックすると、「Inquiry Ticket」のフォームが表示されます。
サイドバーに投稿/編集ボタンを設置するには
参照: DocSDK137: サイドバーの「新しい〜」メニューに独自の項目を追加するには
サイドバーの「新しい〜」ボタンをクリックすると投稿用フォームが表示されますが、この「フォームを表示する」という動作は「アクション」と呼ばれており、そのアクションは config/actions フォルダの .properties ファイルで定義されています。
また、サイドバーの「新しい〜」ボタンにどんな項目を表示するか(=どのアクションへのリンクを表示するか)は、com/traction/sdl/gwtrpc/shared.sdl でプログラミングされています。
つまり、サイドバーに Inquiry Ticket の投稿フォームを表示するためのボタンを設置するには、次の 2 つの設定が必要です。
- 「Inquiry Ticket 投稿フォームを表示する」というアクションを定義する。
- そのアクションを shared.sdl で指定し、サイドバーの「新しい〜」に表示されるようにする。
投稿フォーム表示アクションを定義する
プラグインの config フォルダ内に新しい「actions」フォルダを作成します。
テキストエディタで次のように記述し、その「actions」フォルダに NewInquiry.properties という名前で保存します。
__inherits=NewTask
entryclass=inquiry
アクションを呼び出す
プラグインの com/traction/sdl/gwtrpc フォルダを作成し、その中に「shared.sdl」というファイルを作成します。
テキストエディタ開いて次のように記述し、保存します。
<sdl.function name="addmenu-options">
<##addmenu-options />
<#addmenu-inquiry />
</sdl.function>
<sdl.function name="addmenu-inquiry">
<#addmenu-action actionName="NewInquiry" actionKey="inquiry" />
</sdl.function>
「新しい〜」ボタンに並ぶ項目は、この「addmenu-options」関数で決められています。 「addmenu-options」関数内の、シャープ記号が 2 つ重なった <##addmenu-options>
は、「元々の addmenu-options 関数、すなわち標準の(src/com/traction/sdl/gwtpc にある) shared.sdl の中の addmenu-options 関数を参照せよ」という意味です。その下の <#addmenu-inquiry /> は、「同じファイル内の addmenu-inquiry 関数を参照せよ」という意味です。
その「addmenu-inquiry」関数では、アクション名として上記の config/actions フォルダに作成した .properties ファイルの名前(拡張子を除いた部分)を指定しています。
つまり、「標準の addmenu-options 関数で設定されている、新しい記事、新しいタスク、新しいプロジェクト…に加えて、新しい inquiry ticket のアクションを登録する」という動作になります。
動作確認する
サーバーセットアップでキャッシュをクリアし、画面を再ロードしてサイドバーのボタンに「New Inquiry Ticket」が出現し、クリックして投稿フォームが表示されることを確認します。
ここで「『New Inquiry Ticket』ではなく日本語で『新しい問い合わせチケット』のように表示したい」と思うことでしょう。TeamPage の画面に表示される文言を国際化および日本語化するにはひと工夫必要です。詳しくは 独自の日本語リソースを追加して使用するには を参照してください。
追加フィールドの値を表示するには
上記までの手順で、タスクの投稿フォームをカスタマイズし、「Inquiry ID」と「Inquirer Name」という 2 つのテキスト入力欄(フィールド)を追加した「Inquiry Ticket」という新しいフォームと、その記事クラスを作成しました。
しかし、まだ問題があります。フォーム上の「Inquiry ID」と「Inquirer Name」欄の情報は、記事投稿時にエントリー プロパティとして記事の見えない場所に保存されるのですが、それをどのように表示するのかを決めていません。そのため、投稿しても「Inquiry ID」と「Inquirer Name」情報は画面のどこにも表示されません。
例えば、フォームに下図のように記入して投稿すると
この問い合わせチケット記事は、下図のように、通常のタスクと同じように表示され、「Inquiry ID」と「Inquirer Name」情報は表示されません。
そこで、次に、「Inquiry Ticket というクラスの記事を表示するときは、Inquiry ID と Inquirer Name のエントリープロパティを読み取り、画面に表示する」ようにします。
追加フィールドの値を表示するトークン
フォームの定義ファイル (config/data/forms の inquiryticket.properties) の一番下に次の記述がありました。
# フォームで投稿された記事本文に自動的に埋め込むトークンを指定
entry_content_append=[[ /token inquiry_info ]]
これは、「このフォーム(inquiryticket)を使って投稿された記事には、自動的に『inquiry_info』という名前のトークン(ウィジェット)を埋め込みなさい」という意味です。
トークンの作成
それでは、この「inquiry_info」トークンを作成しましょう。
トークンの定義ファイルをプラグインの config/entry/tokens/html に設置します。ファイルの名前は inquiry_info.properties です。(「トークン名.properties」になります)
テキストエディタで次の 1 行を記述し、config/entry/tokens/html に inquiry_info.properties というファイル名で保存します。これは「com フォルダの下の、traction の下の、sdl の下の、token の下の、inquiry.sdl の中の『bodyinfo』という関数を呼び出して SDL テンプレートとして使いなさい」という意味です。
sdl=com.traction.sdl.token.inquiry#bodyinfo
それでは、その inquiry.sdl を、プラグインの com/traction/sdl/token に設置しましょう。
inquiry.sdl の内容は次のとおりです。
<sdl.function name="bodyinfo">
<#info-table />
</sdl.function>
<sdl.function name="info-table">
<table class="normaltable inquiry-info">
<#table-row text="Inquiry ID" eprop="inquiryid" >
<#table-row text="Inquirer Name" eprop="inquirername" >
</table>
</sdl.function>
<sdl.function name="table-row">
<tr>
<td class="heading">
#$text$
</td>
<td class="value">
<entry.property.value name="#$eprop$" />
</td>
</tr>
</sdl.function>
トークンとして呼び出されるのは(inquiry_info.properties の sdl= で指定されたのは)、1行目の「bodyinfo」関数です。この「bodyinfo」関数は、「info-table」関数を呼び出します。「bodyinfo」関数の <#info-table />
は、「同じファイル内の『info-table』関数を呼び出せ」という意味です。
「info-table」関数では、HTML の <table>〜</table>
タグの中で「table-row」関数を 2 回呼び出しています。パラメーター「text」で画面に表示するテキストを、パラメーター「eprop」でエントリープロパティの名前を「table-row」関数に渡していることに注目してください。
呼び出された先の「table-row」関数では、渡されたパラメーターの値を #$パラメーター名$
で取得できます。エントリープロパティの値は <entry.property.value name="パラメーター名" />
で取得しています。
トークンの動作確認
トークンが正しく動作するかどうかを、投稿済みの問い合わせチケットを編修するか、または新しく問い合わせチケットを投稿するかして確認します。投稿後、下図のようにトークン(ウィジェット)によって「Inquiry ID」と「Inquirer Name」が表示されれば成功です。
インデックス エントリー タイプの設定
「インデックス エントリー タイプ」とは、検索用のインデックスにおける種別のことです。今回作成した「Inquiry Ticket」はタスクの一種ですが、標準のタスクとは別に「Inquiry Ticket」の投稿だけを分類するには、このインデックス エントリー タイプを設定を行い、「この『Inquiry Ticket』は通常のタスクとは別の種類なのだ」ということが TeamPage にわかるようにする必要があります。
設定ファイルの設置
インデックス エントリー タイプ (Index Entry Type) の設定ファイル inquiry.properties を、プラグインの config/entry/indextypes に設置します。
この inquiry.properties ファイルをテキストエディタで開き、次のように記述して保存します。
class=com.traction.sdk.IndexEntryType
match_entry_class_name=true
display_name=Inquiry Ticket
type_filter_display_name=Inquiry Tickets
query_short_type_name=inquiry
ファイルを保存したら、サーバーセットアップ > 一般 > サーバー管理で、[(オプション) 次回の起動時にインデックスを再構築する] チェックボックスをオンにして [TeamPage の再起動] をクリックします。
サイドバーのフィルターの設定
サー バーセットアップ > 一般 > 検索設定 の コンテンツ タイプのフィルタ で、アクティビティ画面のサイドバーの「フィルタ」欄に [Inquiry Tickets] を表示させ、すべての記事の中から問い合わせチケットを素早く絞り込みできるようにできます。
プラグインのダウンロード
ここをクリックして、この記事で解説した内容のプラグインをダウンロードできます。