リストフォームに採番機能を実装する(PowerApps編)

前回に引き続きPowerAppsネタです。

このたびもSharePointあるある要望、カスタムのIDをアイテムに振りたい!というので採番機能を実装してみます。
採番のやり方はいろいろあると思いますが、今回は最後に登録されたアイテムのIDをインクリメントする方法をとりました。

あらかじめ、SharePointリストにはcustomIDという1行テキスト列を作成しておきます。
PowerAppsでフォームを開き、customIDのデータカードで、詳細設定のロックを解除します。
ユーザーが任意の値を入れられないよう、DisplayModeプロパティをDisplayMode.Viewに設定します。

次に、Defaultと、フォームの編集中にほかのユーザーが新しくアイテムを作ったケースに備え、Updateにもに以下の式を設定します。

If(SharePointForm1.Mode=New, 
Concatenate("Custom-",Text(First(SortByColumns(customList, "ID", Descending)).ID + 1, "000")),
ThisItem.customID)

これで、新規フォームを開くとcustomIDに以下のように最後のIDをインクリメントした値が表示されます。

※Text関数で、3桁になるよう0埋め表示にしています。

なお、最後に登録されたアイテムのIDの取り方ですが、First関数でなくLast関数やMax関数、あるいはIDを使わずCountRows関数などでもいいんではないか、という意見があると思います。
しかし、PowerAppsには委任問題というものがありまして・・・
かいつまんでいうと、委任とは関数による計算を直接データソース側でできるということと解釈してます。
では、委任されていない関数を使った場合どうなるかというと、最初の500件のデータだけローカルにダウンロードして、計算対象とするということのようです。
SharePointをデータソースとする場合、委任できる関数はSort、Filter、Search関連の関数だけなので、LastやMaxを使うと最初の500件しか使われないので正しくIDが取れないのですね。
そのため、IDの降順でソートして、最初にきたアイテムのIDを参照するようにしています。
委任については、以下Microsoftのドキュメントも参考にしてください。(何をいってるかよくわからん部分もありますが)
委任について

まあ、PowerAppsの機能は日々進化しているようなので、何か月かしたら委任できる関数も増えているかもしれないですけどね。
ともあれ、通常のSharePointリストフォームだと、最後に登録されたアイテムのIDを参照するのは骨が折れますが、PowerAppsだと関数一発でとれるのでちょっと感動しました!

広告

新規フォームにログインユーザー名を表示(PowerApps編)

さて、SharePoint OnlineではPowerAppsを利用してフォームのカスタマイズができるようになりましたね。
PowerApps を使用した SharePointリストフォームのカスタマイズ
こうなるとInfoPathは完全に過去の遺物ですね・・・

というので、さっそくSharePointあるある要望、新規フォームのPeople Pickerにログインユーザーをデフォルト表示をPowerAppsで実装してみました。

まずはMicrosoft公式の以下の情報を元に試しました。
PowerAppsユーザーに関する情報を表示する
でも、User()関数をそのままPeople Pickerのデフォルト値に設定してみてもうまくいきません。
たぶん、データ型がテキストでないとだめなんでしょうね・・・

で、調べた結果下記スレッドを発見。
https://powerusers.microsoft.com/t5/General-Discussion/Set-current-user-as-default-value-of-Person-or-Group-field/td-p/78744
しかし、ここに書いてあるようにドロップダウンのデフォルト値やDataCardのUpdateに設定したりしてみたもののやはりうまくいかず・・・

いろいろ試した結果、DataCardのデフォルト値に以下の式を書いたところうまくいきました!

If(SharePointForm1.Mode = New,
{'@odata.type':"#Microsoft.Azure.Connectors.SharePoint.SPListExpandedUser",
Claims:Concatenate("i:0#.f|membership|",User().Email),DisplayName:User().FullName,
Email:User().Email},
ThisItem.Requestor)

ついでに、上のサンプルではDataCardの中にLabelを2つ設置し、People Pickerで選択したユーザのメールアドレスと部署を表示するようにしています。
設定方法ですが、事前にOffice365 Userへのデータ接続を追加しておき、LabelのTextに以下のような式を書くだけです。

Concatenate(
"Mail: ",
Office365ユーザー.UserProfile(DataCardValue11.Selected.Email).Mail
)

※DataCardValueのところは、お使いの環境に合わせて変更してください。
なお、Office365 Userに接続してユーザーのプロファイル情報をもってくるやり方は、以下Microsoftのドキュメントを参考にしました。
PowerApps から Office 365 ユーザーの接続に接続する

PowerAppsについてはまだまだ情報も少なく全貌をつかめてませんが、なんかいろいろできそうな予感がしてます。
また新たな発見があれば、記事にしたいと思います!

列の書式設定を試してたらIE11のバグに遭遇した話

こんにちは。
めずらしくSharePoint Onlineの話題でも。
モダンUIの案件管理リストで、ステータス列に赤青黄色の信号機を表示しようと列の書式設定をいろいろ試していたときのお話です。

手始めにMicrosoftの公式ドキュメントを見ていたら、
列の書式設定で SharePoint をカスタマイズする
以下git-hubレポジトリにほぼそのものなサンプルがあったので、さっそく拝借します。
Traffic Light (Red-Yellow-Green) Status Indicator
できたできた、と喜んでいたところ、IE11でみたときだけ上下センタリングが効かず上に張り付いちゃってます。

なんでだ・・・と頭を悩ましつつ、CSSを調べてみたところ、列の書式設定をすると自動的に「.sp-field-customFormatter」というクラスが当たるみたいなんですが、ここのalign-items: centerが効いていないようです。

さらに調べると、これIE11のバグの模様。
https://github.com/philipwalton/flexbugs/issues/231
display:flexの要素で、min-heightを指定するとalign-items: centerが効かなくなるみたいです・・・
Microsoftぅー!!!という感じですが、気を取り直して上記スレッドのworkaroundを試してみました。
min-heightより小さい値、ということでheightに10pxほど指定してみます。
おおー、うまくいきました!

以下、サンプルコードです。

事情を知らない人からみたら意味不明のスタイル指定ですが、指摘されたらIE11で中央揃えにするオマジナイだと言ってあげてください。
(てゆーかIE11のバグを直してほしいですけどね!)

コンテンツ検索 web パーツでホバーパネルを表示してみた

前回のポスト
コンテンツ検索webパーツの表示をカスタマイズする
のオマケです。

SharePoint2013では、検索結果のアイテムにカーソルをあてると詳細がホバーパネルで表示されます。
しかし、コンテンツ検索 web パーツではホバーパネルが表示されません。そこで、なんとか表示させるべくカスタマイズしてみました。

完成イメージはこちら。
20150828
ホバーパネルの表示テンプレートは、マスターページギャラリー>Display Templates>Searchフォルダの中にあります。
このうち、Item_xxx_HoverPanel.htmlというのがそれです。検索結果のファイルタイプによって、表示テンプレートが細かく分けられているのですね。
今回は、Item_Default_HoverPanel.htmlをダウンロードして使います。
ダウンロードしたItem_Default_HoverPanel.htmlを開き、中身を以下のように書き換えます。

書き換えたファイルを「Item_Blog_HoverPanel.html」とリネームして保存し、Searchフォルダにアップロードします。

次に、前回のポストで作成した「Item_BlogPost.html」をダウンロードし、以下のように書き換えます。

書き換えたItem_BlogPost.htmlを、Content Web Partsフォルダにアップロードします。
以上です!
もし、カスタマイズが反映されない場合はコンテンツ検索webパーツの表示テンプレートで「For Blog Post」をえらびなおし、プロパティのマッピングで以下のように選択しなおしてみてください。
20150828-2

なお、カスタマイズにあたってはこちらの記事を参考にしました。
The SharepointWallah: Sharepoint 2013 Search – Adding a hover panel to a content search webpart display template.
C/D/H Talks Tech » Custom Hover Panel on the Content Search Web Part using a Custom Display Template

若干、無理やりな感じもありますが・・・参考になればうれしいです。

コンテンツ検索webパーツの表示をカスタマイズする

だいぶ前になりますが、コンテンツ検索webパーツでブログの新着を表示するやり方を紹介しました。
【2013】コンテンツ検索 webパーツでBlogの新着情報を表示する | Me & SharePoint.

今回の記事と、次回の記事
コンテンツ検索 web パーツでホバーパネルを表示してみた
はその続きとなります。

前回のままではタイトルとサムネイルだけでさびしいので、本文の一部、投稿日、それから「Read More」ボタンを表示してみたいと思います。
完成イメージです。
20150826

これを実現するには、「表示テンプレート」というものをカスタマイズします。
表示テンプレートのカスタマイズについては、MSのサポートチームのブログで詳しく紹介されていますので参考にしてください。
SharePoint 2013 お知らせアイテムを新着順に表示するコンテンツ検索 Web パーツを作成する – Japan SharePoint Support Team Blog – Site Home – TechNet Blogs.
SharePoint 2013 検索結果の表示を制御する表示テンプレート – Japan SharePoint Support Team Blog – Site Home – TechNet Blogs.

さて、マスターページギャラリーからDisplay Templates>Content Web Parts とフォルダをたどって、Item_Picture3Lines.htmlをダウンロードします。
ダウンロードしたテンプレートを「Item_BlogPost.html」とリネームします。
テンプレートを開き、以下のように書き換えます。

<html xmlns:mso="urn:schemas-microsoft-com:office:office" xmlns:msdt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"> 
<head>
<title>For Blog Post</title>

<!--[if gte mso 9]><xml>
<mso:CustomDocumentProperties>
<mso:TemplateHidden msdt:dt="string">0</mso:TemplateHidden>
<mso:ManagedPropertyMapping msdt:dt="string">'Picture URL'{画像の URL}:'PublishingImage;PictureURL;PictureThumbnailURL','Link URL'{リンクの URL}:'Path','Line 1'{行 1}:'Title','Line 2'{行 2}:'DiscussionPost','Line 3'{行 3}:'Created', 'SecondaryFileExtension','ContentTypeId'</mso:ManagedPropertyMapping>
<mso:MasterPageDescription msdt:dt="string">このアイテム表示テンプレートでは、100 x 100 の大きさでアイテムの画像が左側に表示されます。画像の右側には、タイトル、既定アイテムの説明、カスタムの管理プロパティ用の行が表示されます。</mso:MasterPageDescription>
<mso:ContentTypeId msdt:dt="string">0x0101002039C03B61C64EC4A04F5361F385106603</mso:ContentTypeId>
<mso:TargetControlType msdt:dt="string">;#Content Web Parts;#</mso:TargetControlType>
<mso:HtmlDesignAssociated msdt:dt="string">1</mso:HtmlDesignAssociated>
</mso:CustomDocumentProperties>
</xml><![endif]-->
</head>

<body>

    <!--
            Warning: Do not try to add HTML to this section. Only the contents of the first <div>
            inside the <body> tag will be used while executing Display Template code. Any HTML that
            you add to this section will NOT become part of your Display Template.
    -->
    <script>
        $includeLanguageScript(this.url, "~sitecollection/_catalogs/masterpage/Display Templates/Language Files/{Locale}/CustomStrings.js");
    </script>

    <!--
        Use the div below to author your Display Template. Here are some things to keep in mind:
        * Surround any JavaScript logic as shown below using a "pound underscore" (#_ ... _#) token
        inside a comment.

        * Use the values assigned to your variables using an "underscore pound equals"
        (_#= ... =#_) token.
    -->

    <div id="Item_BlogPost">

<!--#_

var encodedId = $htmlEncode(ctx.ClientControl.get_nextUniqueId() + "_BlogPost_");

var linkURL = $getItemValue(ctx, "Link URL");
linkURL.overrideValueRenderer($urlHtmlEncodeValueObject);

var line1 = $getItemValue(ctx, "Line 1");
var line2 = $getItemValue(ctx, "Line 2");
var line3 = $getItemValue(ctx, "Line 3");

var StrLine2 = line2.value;
if (StrLine2.length > 150){
    StrLine2 = StrLine2.substr(0, 150) + "...";
}

var pictureURL = $getItemValue(ctx, "Picture URL");
var pictureId = encodedId + "picture";
var pictureMarkup = Srch.ContentBySearch.getPictureMarkup(pictureURL, 100, 100, ctx.CurrentItem, "cbs-picture3LinesImg", line1, pictureId);

line1.overrideValueRenderer($contentLineText);
line2.overrideValueRenderer($contentLineText);
line3.overrideValueRenderer($contentLineText);

var containerId = encodedId + "container";
var pictureLinkId = encodedId + "pictureLink";
var pictureContainerId = encodedId + "pictureContainer";
var dataContainerId = encodedId + "dataContainer";
var line1LinkId = encodedId + "line1Link";
var line1Id = encodedId + "line1";
var line2Id = encodedId + "line2";
var line3Id = encodedId + "line3";

var dataDisplayTemplateTitle = "BlogPost";

 _#-->
        <div class="cbs-picture3LinesContainer" id="_#= containerId =#_" data-displaytemplate="_#= $htmlEncode(dataDisplayTemplateTitle) =#_">
            <div class="cbs-picture3LinesImageContainer" id="_#= pictureContainerId =#_">
<!--#_
if(!linkURL.isEmpty)
{
_#-->
                <a class="cbs-pictureImgLink" href="_#= linkURL =#_" title="_#= $htmlEncode(line1.defaultValueRenderer(line1)) =#_" id="_#= pictureLinkId =#_">
<!--#_
}
_#-->
                    _#= pictureMarkup =#_
<!--#_
if(!linkURL.isEmpty)
{
_#-->
                </a>
<!--#_
}
_#-->
            </div>
            <div class="cbs-picture3LinesDataContainer" id="_#= dataContainerId =#_">
                <a class="cbs-picture3LinesLine1Link" href="_#= linkURL =#_" title="_#= $htmlEncode(line1.defaultValueRenderer(line1)) =#_" id="_#= line1LinkId =#_">
                    <h4 class="cbs-picture3LinesLine1 ms-accentText2 ms-noWrap" id="_#= line1Id =#_"> _#= line1 =#_</h4>
                </a>
<!--#_
if(!line2.isEmpty)
{
_#-->
                <div class="cbs-picture3LinesLine2" style="height:auto;" id="_#= line2Id =#_" > _#= StrLine2 =#_ </div>
<!--#_
}
_#-->
                <div style="overflow:hidden;">
<!--#_
if(!line3.isEmpty)
{
_#--> 
                    <span class="cbs-picture3LinesLine3 ms-textSmall ms-noWrap" id="_#= line3Id =#_" style="float:left;">[Posted : _#= line3 =#_ ]</span>
<!--#_
}
_#-->
                    <a class="cbs-button1" href="_#= linkURL =#_" style="float:right;">Read More</a>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

書き換えたItem_BlogPost.htmlを、ダウンロード元のフォルダにアップロードし、タイトルに「For Blog Post」と入力して保存します。

コンテンツ検索webパーツを設置したページに戻り、webパーツを編集状態にします。
「表示テンプレート」セクションの「アイテム」で、先ほどテンプレートのタイトルに設定した「For Blog Post」を選択します。

20150826-2

もし、うまく内容が反映されない場合は「プロパティのマッピング」でデフォルトで入力されているプロパティを再度選択しなおしてから保存してみてください。

最後に、「Read More」のリンクをボタン状にし、全体の見栄えを整えるためのCSSをページに埋め込みます。
ページを編集状態にし、「スクリプトエディター」を挿入して、コードスニペットのに以下のコードを貼り付けて保存します。

<style>
.cbs-picture3LinesContainer {
    padding: 20px 0;
    margin: 5px;
}
.cbs-picture3LinesImageContainer {
    margin-top: 5px;
}
.cbs-button1{
    text-decoration: none;
    text-align: center;
    display: inline-block;
    background-color: #59b1eb;
    border: 2px solid #59b1eb;
    color: #fff;
    padding: 0 30px;
}
.cbs-button1:visited{
    color: #fff;
}
.cbs-button1:hover {
    background-color: #fff;
    border-color: #59b1eb;
    color: #59b1eb;
    text-decoration: none;
}
.cbs-button1::before,
.cbs-button1::after {
    position: absolute;
    z-index: -1;
    display: block;
    content: '';
}
.cbs-button1,
.cbs-button1::before,
.cbs-button1::after {
    box-sizing: border-box;
    transition: all .3s;
}
</style>

これでOKです!
おなじみのコンテンツクエリwebパーツよりは、xslスタイルシートをいじらなくて済む分カスタマイズのハードルは低いですよね。
これからどんどん使っていきたいと思います!

SharePointサイトをレスポンシブ・デザインにするときの情報源

こんにちは。世間は夏休み真っ盛りですが、私は絶賛仕事中です!!
電車が空いててうれしいぞ!!!

さて、ここのところSharePointサイトをモバイルでも美しく表示できるようにするべく、いろいろと実験していたのですがそのとき参考にした情報を備忘録として載せておきます。

基本的な前提と方針は、
・バージョンはSharePoint2013
・SharePoint Onlineへのマイグレーションも見据え、カスタムマスタページは作らない
(参考:Latest Advice on Office 365 Branding | Microsoft Trends.)
・よって、デバイスチャネルも使わず、レスポンシブデザインで設計
・とはいえ、JavaScriptは使いたいのでマスタページでのJavaScriptの参照は(しぶしぶ)許容する
といったところです。

デフォルトマスタページを使い、CSSだけで何とかするやり方はもうほぼこれでOKではないかと。
Making seattle.master Responsive | Our SharePoint Experience.

レスポンシブなCSSグリッド・システムを導入するやり方。まだ試してないけど、そのうちやってみたいと思います。
Apply grid system to SharePoint using SUSY | Stefan Bauer – n8d

マスタページをいじくらずにviewportを設定する裏ワザ。
Add viewport meta without editing the master page | Stefan Bauer – n8d.

グローバルナビゲーションをモバイルではアコーディオンメニューにしたい!
巷にあふれるプラグインをしつこくいろいろ試した結果これがよさそうです。
レスポンシブメニューを作成できるjQueryプラグイン「MeanMenu」 | たすデザイン.
具体的な導入方法は、いずれ別のエントリで書きます。

JavaScript内でユーザーエージェントを判別したいとき。
2015年版JavaScriptユーザエージェント判別・判定.

viewportの設定になやんだら?
もう逃げない。HTMLのviewportをちゃんと理解する – Qiita.

マスタページをいじくらずともサイト全体にカスタムJavaScriptを適用するにはこんなやり方もあるです。
JavaScript を使用して SharePoint サイト UI をカスタマイズする.
MSの推奨はたぶんこれ。私はまだ試してないです。アドイン作れとか言われると、とたんにハードルが・・・(汗)

新たにいい情報が出てきたら、今後も追加していく予定です。
また、こんなのも参考になるよ!なんてのがあったらTwitterでもなんでもお知らせください。