Weitere ähnliche Inhalte Ähnlich wie Alfresco勉強会20120829: やさしいShareダッシュレットの作り方 (20) Alfresco勉強会20120829: やさしいShareダッシュレットの作り方1. 第9回 勉強会
やさしいShareダッシュレットの作り方
© 2012 aegif
2. 自己紹介
林 智行(@linzhixing)
自然言語好き(人工言語も好き)
プログラミング言語は駆け出し
社内のAlfresco管理 / ダッシュレット作成
aegif OC最年少
勉強会で発表的なアクティビティは初めて
2
3. Shareダッシュレットとは(1)
ダッシュレットとは
– Alfresco Shareのダッシュボード上に配置される、ユーザが操作可能なウィジェット
– WebScriptsの一種
– desc.xmlで<family>dashlet</family>を指定したものがダッシュレット(user-dashlet/site-dashletも)
Alfresco Repositpry
$TOMCAT_HOME/webapps//alfresco
REST API CMIS API
利用している
Alfresco Share 外部システム
$TOMCAT_HOME/webapps/share
WebScripts
Shareダッシュレット
ユーザ
3
5. ダッシュレット = 1,2,3...無限大
基本的なパターン(リポジトリの情報を取得してダッシュボードに表示する)
– AlfrescoのリポジトリからAPIでデータを取得
– データを受け取って加工し、表示用のテンプレート(FreeMarker)に渡す
– 表示用テンプレートで、ダッシュレットの見た目を記述する
• WebScriptsとしては、HTTPメソッドがGETのWebscriptsになる
1 2 3
Alfresco Share
データ取得 データ処理 プレゼンテー
リポジトリ ダッシュボード
ション
少し複雑なパターン(ダッシュレット上からデータを送信したり、結果を返したり)
– ほかのWebScripts(POSTプロトコルなど)や外部システムのREST APIなどを組み合わせる
– 上記RESTに対し、テンプレート上でAjax処理を書く(YUIが使える)
今日は1,2,3の部分、の1,2,2.5くらいの部分を扱います
– プレゼンテーション部分の、ShareのYUI作法は結構複雑
• 知らなくても一応いける
5
6. WebScriptsの構成
WebScripts = AlfrescoのREST APIを自前でつくれる (for both リポジトリ, Share)
定義(.desc.xml)、ロジック(Javascript, Java)、プレゼンテーション(Freemarker)、設定
(.config.xml, .properties)
命名規約により複数ファイルがひとかたまりのWebScriptsとして機能
– <webscriptsの名前>.<HTTPメソッド>.<ファイルの種類>
• HTTPメソッド: GET, POST etc.
• ファイルの種類: desc.xml, js, config.xml etc.
• e.g. site_inbox.get.desc.xml, site_inbox.get_ja.properties, site_inbox.get.html.ftl
– Javaロジックの場合は、$TOMCAT_HOME/shared/classes/web-extension下に*-context.xmlでbean
定義も必要
Alfrescoへのデプロイ方法
– JAR: WARを汚さないで着脱簡単。
• インストールは$TOMCAT_HOME/shared/libに。
– クラスロードの関係で、/shared/lib下のJARではJavaロジックは動作しない
– ロジックにリポジトリのJava APIが使えない
• 内部構成
– alfrescoフォルダ: WebScriptsを構成するファイル
– META-INFフォルダ: クライアンサイドで読み込むリソース(css、画像、javascript etc.)
• Alfresco的にはAMPの方が推奨されているようだが、share-extraのサイトではすべてJARで提供されている。
– AMP: WARの中を書き変える。モジュールとして独自に管理される。
• インストールはapply_amps.shで実行
• 内部構成: マッピングはWiki参照
6
7. Shareダッシュレットの作り方
定義/設定情報
.desc.xml
– WebScriptsの定義ファイル
– REST APIとしてのURLを定義
.config.xml
– ユーザ固有の情報保存(動的/静的)にも使える
– Javascriptからの呼び出し
• var config = new XML(config.script); ${config.siteId}
– FTLからの呼び出し
• ${config.site_inbox.siteId}
.properties
– プレゼンテーション用のメッセージ
– G10Nでプレースホルダ化した項目の値を定義
• .desc.xmlなどにも使える
– _ja.propertiesなどとして、ロケールごとにL18N
7
8. Shareダッシュレットの作り方
ロジック(データ取得 & データ処理)
REST APIでデータ取得
– WebクライアントのWebscriptsであれば、JavaかJavascriptか問題になったが……
– JSONでデータを取得して軽く加工するだけであればJavascriptで充分、というかJavaは向いていない
• リポジトリのJava APIは使えない(alfresco.warとshare.warは別のWebアプリケーション)
• WebクライアントのJavascriptで出来ていたことも出来なかったり
– e.g.search.xpathsearchが使えない
• $TOMCAT/shared/lib下にJARで配置する場合、クラスロードの関係でJavaが使えない
– それでもJavaを使いたい場合
• AMP形式でインストール
• e.g.ダッシュレットから外部のLDAPにJNDIでアクセスしたい
– Javascriptであればremote.call(url)でREST APIを呼べる
REST APIについての情報源
– Webscripts一覧(<localhost>/alfresco/share/page/index, <localhost>/share/share/page/index)
– ネット
データの処理
– 表示用テンプレートのFreeMarker上でも<#if>や<#assign>などを使ってデータ加工できてしまうが、望ま
しくないし面倒くさい
8
9. Shareダッシュレットの作り方
REST APIで取得したJSONデータ
サイト内の特定フォルダの内容
alfresco/service/slingshot/doclib/doclist/documents/site/<サイトID>/<サイト内のフォルダパス>
{
"totalRecords": 5,
"startIndex": 0,
"metadata":
{
//省略
},
"items":
[
{
"nodeRef": "workspace://SpacesStore/84debbfe-60bc-458a-bc17-8c4913285852",
"nodeType": "cm:content",
"type": "document",
"mimetype": "text/plain",
"isFolder": false,
"isLink": false,
"fileName": "test1.txt",
"displayName": "test1.txt",
"status": "",
"title": "",
"description": "",
"author": "",
"createdOn": "2012-08-29T15:19:12.989+09:00",
"createdBy": "Administrator",
"createdByUser": "admin",
"modifiedOn": "2012-08-29T15:19:12.989+09:00",
"modifiedBy": "Administrator",
"modifiedByUser": "admin",
"lockedBy": "",
"lockedByUser": "",
"size": "4",
"version": "1.0",
"contentUrl": "api/node/content/workspace/SpacesStore/84debbfe-60bc-458a-bc17-8c4913285852/test1.txt",
"webdavUrl": "/webdav/%e3%82%b5%e3%82%a4%e3%83%88/aegifportal/documentLibrary/%e5%8f%97%e4%bf%a1BOX/admin/
test1.txt",
//以下省略
9
10. Shareダッシュレットの作り方
ロジック( .get.js)のソースコード
<import resource="classpath:/alfresco/templates/org/alfresco/import/alfresco-util.js">
function main(){
var s = new XML(config.script); ■.config.xmlから設定情報読み取り
var userid = context.user.id;
■Surfが提供しているbuilt-inオブジェクトから読み取り
//documents API
var documentsAPIUrl = "/slingshot/doclib/doclist/documents/site/" + s.target.siteid.toString() + "/documentLibrary/" + s.target.folder.toString() + "/" + userid;
var data = doclistAPI(documentsAPIUrl);
//folder info
if(typeof data.metadata === "undefined"){
model.folder = {}; REST APIのURL
}else{
if(typeof data.metadata.parent === "undefined"){
model.folder = {};
}else{
model.folder = data.metadata.parent;
}
}
プレゼンテーション用にデータ
//documents info
if(typeof data.items === "undefined"){ を渡すためmodelに格納 標準で用意されているメソッ
model.items = [];
}else{ ドを使用
//date conversion
for(i=0; i < data.items.length; i++){
data.items[i].formattedModifiedOn = AlfrescoUtil.fromISO8601(data.items[i].modifiedOn);
}
//sorting by date in descending order
data.items.sort(
function(a,b){ return b.formattedModifiedOn - a.formattedModifiedOn }
);
//slice to the limited number
var maxShow = Number(s.maxShow.toString());
data.items = data.items.slice(0, maxShow);
model.items = data.items;
model.maxShow = maxShow;
} Surfが提供している
}
remoteオブジェクトを使用
function doclistAPI(url){
var connector = remote.connect("alfresco");
var json = remote.call(encodeURI(url));
var data = eval (" (" + json + ") ") ;
return data;
}
main();
処理をmain関数にまとめて、main();
で実行するのがお作法らしい
10
11. Shareダッシュレットの作り方
プレゼンテーション部分
まずFreeMarker開発環境を整える
– EclipseではJBoss ToolのプラグインにFreeMarker IDEがある
デフォルトで色々読み込まれてる
– header.get.html.ftl: templateArgs.siteIdなどの値を利用可能
– Alfresco.widgetのYUIコンポーネント
– basic.css
– etc.
WebScriptsのロジックからデータを受け取れる
– Javascriptでmodel.<property>に格納した値を、${property}でinterpoleできる
FreeMarkerの${...}で使うデータは存在判定を忘れずに!
– ?? , ?has_context , ! etc.
11
12. Shareダッシュレットの作り方
プレゼンテーション( .get.head.ftl)のソースコード
リソースファイルへのJar内部のフォルダ構成を指定
/aegif/components/dashlets
<#include "/org/alfresco/components/component.head.inc">
<#--
Uncomment the lines below to wire in the client-side assets. Other files will
also be required if additional functionality, e.g. config dialogues, are needed.
-->
<@script type="text/javascript" src="${page.url.context}/res/aegif/components/dashlets/site_inbox.js"></@script>
<@link rel="stylesheet" type="text/css" href="${page.url.context}/res/aegif/components/dashlets/site_inbox.css" />
12
13. Shareダッシュレットの作り方
プレゼンテーション( .get.html.ftl)のソースコード
<script type="text/javascript">//<![CDATA[
new Alfresco.widget.DashletResizer("${args.htmlid}", "${instance.object.id}"); 標準のYUIコンポーネント
//]]></script>
呼び出し
<div class="dashlet">
<div class="title">${msg("header")}</div>
<div class="body scrollableList"<#-- if args.height??> style="height: ${args.height}px;"</#if -->>
<div class="detail-list-item first-item last-item">
<span> .config.xmlや.propertiesから設
<#if items?has_content> 定情報を読み込んで利用
<#if folder?has_content>
<a href="${url.context}/page/site/${config.script.site_inbox.target.siteid}/documentlibrary#filter=path|/$
{config.script.site_inbox.target.folder}/${user.id}" class="theme-color-1">${msg("message.inbox1")}</a>
</#if> ロジック部分から受け
${msg("message.inbox2")}${msg("message.listnum.latest")}${maxShow}${msg("message.listnum.display")}<br/>
取ったデータを利用
<table class="site_inbox" border="0" rules="rows" width=100%>
<#list items as item>
<#assign fileExtIndex = item.fileName?last_index_of(".")>
<#assign fileExt = (fileExtIndex > -1)?string(item.fileName?substring(fileExtIndex + 1)?lower_case,
"generic")>
ファイル拡張子を取得
<tr class="site_inbox">
<td class="site_inbox fileimage"> (標準で用意されてるかも)
<a href="${url.context}/page/site/${config.script.site_inbox.target.siteid}/document-details?nodeRef=$
{item.nodeRef}">
<img src="${url.context}/res/components/images/filetypes/${fileExt}-file-32.png"
onerror="this.src='${url.context}/res/components/images/filetypes/generic-file-32.png'" alt="${item.displayName}" title="$
{item.displayName}">
</a>
</td>
<td>
<h3 class="filename">
<a href="${url.context}/page/site/${config.script.site_inbox.target.siteid}/document-details?
nodeRef=${item.nodeRef}" class="theme-color-1">${item.displayName}</a><br/>
</h3>
<span class="site_inbox">${msg("message.modifiedDate")}<span>${item.formattedModifiedOn?string("yyyy年MM月
dd日 HH:mm")}</span></span><br/>
</td>
</tr>
</#list>
13
14. その他 開発上のTIPS
Shareを別のtomcatインスタンスで起動する
– デバッグ(とくにFreeMarker)のスピードUp
• Share単体なら15sくらいで起動
– 必要な設定
• $TOMCAT_HOME/conf/server.xml
– <Server port="8005" shutdown="SHUTDOWN">
– Define a non-SSL HTTP/1.1 Connector on port 8080--><Connector port="8180" protocol="HTTP/1.1"
• $TOMCAT_HOME/conf/catalina.properties
– shared.loader=${catalina.base}/shared/classes,${catalina.base}/shared/lib/*.jar
– 上記フォルダを作っておく。/shared/classesフォルダには元のヴァニラAlfrescoからweb-extensionをコピー
標準のCSSのかかり方をFirebugで調べる
FreeMarkerのデバッグ良い方法ないかな……
14
15. おまけ
他にも、こんなダッシュレットがつくれます
MyShareLocale
– Shareのダッシュレット上からShareの表示言語(ロケール)を切り替える
– 仕組み
• Surfの仕組みとして、各ページ読み込みのたびにLocaleResolverでロケールが解決されている
• LocaleResolverのbean定義を自前のLocaleResolverに変更する(/web-extensionの-context.xmlで書き換え)
• 自前のLocaleResolverはユーザのCookieを読み込んでロケールを解決する
• ユーザはダッシュレットおよびログインページで、表示させたいロケールを選択しCookieに保存する:
– どんな時に便利?
• 正直、ブラウザのアドオンでロケール変更するのでOK(IEだと少し面倒くさいけれど……)
• Shareの翻訳に便利
– Alfresco Shareクリンゴン語Language Packの翻訳にも便利
LDAP Utility
– Shareのダッシュレット上から、連携しているLDAPのユーザパスワードをユーザが変更できるようにする
– 仕組み
• Java-backed Webscriptsとして、JNDI機能によりLDAPサーバを叩いている
• GET/POST両方のWebScriptを定義。ダッシュレットはGETの方だが、YUIによるAjaxでPOSTを呼んでいる。
15
Hinweis der Redaktion \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n