演習 - geo 位置情報機能を使用して SPFx ACE を作成する
この演習では、Viva Connectionsの地理位置情報機能を使用するプライマリ テキスト カード テンプレートを使用して、SharePoint Framework (SPFx) アダプティブ カード拡張機能 (ACE) を作成します。
実装するシナリオは、建物間を行き着くのに役立つシンプルなバージョンのキャンパス シャトル サービスです。 ACE はシャトルのダイバー向けです。 ドライバーは ACE を使用して旅行を予約し、乗客を迎えに行くか、目的地に乗客を引き渡す途中であることを示します。
前提条件
Viva Connections用の ACE を開発するには、テナントに Microsoft 365 テナント、SharePoint Online、Viva Connectionsを設定する必要があります。 テナントを準備するには、次のリソースを使用します。
ワークステーションに必要な開発者ツールもインストールする必要があります。
重要
ほとんどの場合、次のツールの最新バージョンをインストールすることをお勧めします。 ここに記載されているバージョンのリストは、このモジュールが発行され、最後にテストしたときに使用されたものです。
- Node.js - v16.*
- Gulp-cli - v2.3.*
- Yeoman - v4.3.*
- SharePoint 用 Yeoman ジェネレーター - v1.17.1
- Visual Studio Code
SharePoint リストを作成してデータを格納する
最初の手順では、各キャンパス シャトル ドライバーのデータを格納する新しい SharePoint リストを作成します。
ブラウザーで、この演習で作成するプロジェクトをテストする SharePoint サイトに移動します。
[ 新規 ] を選択し、使用可能なオプションから [一覧表示 ] を選択します。
[ リストの作成 ] ダイアログで、[ 空のリスト] を選択します。
一覧の [名前] を [キャンパス シャトル ] に設定し、[ 作成] を選択します。
ブラウザーが更新されて新しいリストが表示されたら、いくつかの列をリストに追加します。 [ 列の追加] を選択し、[ テキスト] を選択し、[ 次へ ] ボタンを選択します。 [ 列の作成 ] パネルで、次の値を入力し、[保存] を選択 します。
- 名前: OriginLocation
- 型: 1 行のテキスト
次の値を使用してこのプロセスを繰り返して、さらにいくつかの列を一覧に追加します。
- コラム:
- 名前: DestinationName
- 型: 1 行のテキスト
- コラム:
- 名前: DestinationLocation
- 型: 1 行のテキスト
- コラム:
- 名前: 状態
- 型: 選択
-
選択肢:
- 雇った
- en route
- 使用可能
ACE のデータを格納するリストを使用して、プロジェクトを作成できるようになりました。
SPFx プロジェクトを作成して準備する
コマンド プロンプトを開き、SPFx プロジェクトを作成するフォルダーに移動します。 その後、次のコマンドを実行して SharePoint Yeoman ジェネレーターを起動します。
yo @microsoft/sharepoint
表示されるプロンプトを完了するには、次のコマンドを使用します。
- ソリューション名は何ですか?: AceCampusShuttle
- 作成するクライアント側コンポーネントの種類:アダプティブ カード拡張機能
- どのテンプレートを使用しますか?: プライマリ テキスト テンプレート
- アダプティブ カード拡張機能の名前は何ですか?: Campus Shuttle
プロジェクトに必要なフォルダーをプロビジョニングした後、ジェネレーターは npm install を自動的に実行することで、すべての依存関係パッケージをインストールします。 NPM がすべての依存関係のダウンロードを完了したら、Visual Studio Code でプロジェクトを開きます。
サンプル データを追加する
作成する ACE を使用すると、シャトル ドライバーはリストから目的地を選択するか、マップ上のポイントを選択できます。
プロジェクトに新しいファイル ./src/adaptiveCardExtensions/campusShuttle/assets/campus_locations.json を作成し、場所オブジェクトの配列を追加します。 各場所には 、名前、 緯度、 経度 のプロパティが必要です。 または、フロリダ州ゲインズビルにあるフロリダ大学のいくつかの場所を含むファイルに、次の JSON を貼り付米国。
[
{ "title": "UF: Reitz Student Union", "latitude": 29.6463258, "longitude": -82.3499756 },
{ "title": "UF: The Hub", "latitude": 29.648018, "longitude": -82.345664 },
{ "title": "UF: Department of Computer and Information Science and Engineering", "latitude": 29.6476101, "longitude": -82.3466208 },
{ "title": "UF: Materials Science and Engineering", "latitude": 29.6476101, "longitude": -82.3466208 },
{ "title": "UF: Turlington Hall", "latitude": 29.6476101, "longitude": -82.3466208 },
{ "title": "UF: McCarty Hall A", "latitude": 29.6476101, "longitude": -82.3466208 },
{ "title": "UF: Peabody Hall", "latitude": 29.6502915, "longitude": -82.3433807 },
{ "title": "UF: Norman Hall", "latitude": 29.6486165, "longitude": -82.3398393 },
{ "title": "UF: Warrington College of Business", "latitude": 29.65093, "longitude": -82.3402091 },
{ "title": "UF: Mechanical and Aerospace Engineering Building A", "latitude": 29.6436917, "longitude": -82.3478054 },
{ "title": "UF: New Physics Building (NPB)", "latitude": 29.6439734, "longitude": -82.3506927 },
{ "title": "UF: Murphree Hall", "latitude": 29.6508923, "longitude": -82.3480633 }
]
SharePoint REST API サービス ヘルパーを追加する
次に、SharePoint REST サービスをプロジェクトに追加して、シャトル ドライバー データを格納するために作成した SharePoint リストへのすべての読み取りと書き込みを処理します。
プロジェクトに新しいファイル ./src/adaptiveCardExtensions/campusShuttle/sp.service.ts を作成し、次のコードを追加します。
import { AdaptiveCardExtensionContext } from '@microsoft/sp-adaptive-card-extension-base';
import { SPHttpClient } from '@microsoft/sp-http'
export const STATUS_HIRED = 'hired';
export const STATUS_ENROUTE = 'en route';
export const STATUS_AVAILABLE = 'available';
export interface ILocation {
latitude: number;
longitude: number;
}
export interface IListItem {
['@odata.type']?: string;
Id?: string;
Title: string;
Status: string;
OriginLocation?: string | ILocation;
DestinationName?: string;
DestinationLocation?: string | ILocation;
}
export const fetchListItem = async (spContext: AdaptiveCardExtensionContext, listId: string): Promise<IListItem> => {
if (!listId) { return Promise.reject('No listId specified.'); }
const listApiUrl = `${spContext.pageContext.web.absoluteUrl}/_api/web/lists/GetById(id='${listId}')`;
const user = spContext.pageContext.user.loginName;
const response: { value: IListItem[] } = await (await spContext.spHttpClient.get(
`${listApiUrl}/items/?$select=Id,Title,Status,OriginLocation,DestinationName,DestinationLocation&$filter=Title eq '${user}'&$top=1`,
SPHttpClient.configurations.v1
)).json();
if (response.value.length === 0) { return Promise.resolve(undefined); }
const convertedTrip = response.value[0];
if (convertedTrip) {
const origin = convertedTrip.OriginLocation as string;
convertedTrip.OriginLocation = <ILocation>{
latitude: Number(origin.split(',')[0]),
longitude: Number(origin.split(',')[1])
};
}
if (convertedTrip) {
const destination = convertedTrip.DestinationLocation as string;
convertedTrip.DestinationLocation = <ILocation>{
latitude: Number(destination.split(',')[0]),
longitude: Number(destination.split(',')[1])
};
}
return Promise.resolve(convertedTrip);
}
const getItemEntityType = async (spContext: AdaptiveCardExtensionContext, listApiUrl: string): Promise<string> => {
const response: { ListItemEntityTypeFullName: string } = await (await spContext.spHttpClient.get(
`${listApiUrl}?$select=ListItemEntityTypeFullName`,
SPHttpClient.configurations.v1
)).json();
return response.ListItemEntityTypeFullName;
}
const createListItem = async (
spContext: AdaptiveCardExtensionContext,
listApiUrl: string,
listItem: IListItem): Promise<void> => {
listItem['@odata.type'] = await getItemEntityType(spContext, listApiUrl);
await spContext.spHttpClient.post(
`${listApiUrl}/items`,
SPHttpClient.configurations.v1,
{
headers: {
'ACCEPT': 'application/json; odata.metadata=none',
'CONTENT-TYPE': 'application/json'
},
body: JSON.stringify(listItem)
}
);
return Promise.resolve();
}
export const upsertListItem = async (spContext: AdaptiveCardExtensionContext, listId: string, listItem: IListItem): Promise<void> => {
if (!listId) { return Promise.reject('No listId specified.'); }
const listApiUrl = `${spContext.pageContext.web.absoluteUrl}/_api/web/lists/GetById(id='${listId}')`;
const originLocationObj = (listItem.OriginLocation as ILocation);
listItem.OriginLocation = `${originLocationObj.latitude},${originLocationObj.longitude}`;
const destinationLocationObj = (listItem.DestinationLocation as ILocation);
listItem.DestinationLocation = `${destinationLocationObj.latitude},${destinationLocationObj.longitude}`;
if (!listItem['@odata.type']) { return createListItem(spContext, listApiUrl, listItem); }
await spContext.spHttpClient.post(
`${listApiUrl}/items(${listItem.Id})`,
SPHttpClient.configurations.v1,
{
headers: { 'IF-MATCH': '*', 'X-HTTP-METHOD': 'MERGE' },
body: JSON.stringify(<IListItem>{
Title: listItem.Title,
Status: listItem.Status,
OriginLocation: listItem.OriginLocation,
DestinationName: listItem.DestinationName,
DestinationLocation: listItem.DestinationLocation
})
}
);
return Promise.resolve();
}
export const deleteListItem = async (spContext: AdaptiveCardExtensionContext, listId: string, listItemId: number): Promise<void> => {
if (!listId) { return Promise.reject('No listId specified.'); }
if (!listItemId) { return Promise.reject('No listItemId specified.'); }
const listApiUrl = `${spContext.pageContext.web.absoluteUrl}/_api/web/lists/GetById(id='${listId}')`;
await spContext.spHttpClient.post(
`${listApiUrl}/items(${listItemId})`,
SPHttpClient.configurations.v1,
{
headers: { 'IF-MATCH': '*', 'X-HTTP-METHOD': 'DELETE' }
}
);
}
このサービスは、プロジェクト全体で使用する次のものをエクスポートします。
- 状態オプションの 3 つの定数 ():
STATUS_AVAILABLE
STATUS_ENROUTE
STATUS_HIRED
-
fetchListItem()
: このメソッドは、現在サインインしているドライバー レコード (存在する場合) を取得します。 -
upsertListItem()
: このメソッドは、新しいドライバー レコードを作成するか、既存のドライバー レコードを更新します。 -
deleteListItem()
: このメソッドは、ドライバー レコードが旅行中に長い場合に削除します。
プロジェクトを初期化する
プロジェクトにコア依存関係がいくつか追加されたので、ACE が最初にページに読み込まれるときに、いくつかのコア機能の初期化を実装してみましょう。 これには、ACE の状態を構成し、ドライバートリップの詳細を含むリストの ID をユーザーが設定できるようにする必要があります。
ユーザーが SharePoint リスト ID を設定できるように ACE を更新する
ファイル ./src/adaptiveCardExtensions/campusShuttle/CampusShuttleAdaptiveCardExtension.ts で ACE クラスを見つけて、VS Code で開きます。
ICampusShuttleAdaptiveCardExtensionProps
インターフェイスを見つけて、listId
プロパティを追加して、ドライバーの状態レコードを含む SharePoint リストの ID を格納します。
export interface ICampusShuttleAdaptiveCardExtensionProps {
title: string;
listId: string;
}
ファイル ./src/adaptiveCardExtensions/campusShuttle/CampusShuttlePropertyPane.tsを見つけて開きます。
groupFields
配列に新しいPropertyPaneTextField
を追加して、ドライバーの状態レコードを含むリストの ID を設定するオプションを追加します。
groupFields: [
PropertyPaneTextField('title', {
label: strings.TitleFieldLabel
}),
PropertyPaneTextField('listId', {
label: 'List ID (GUID)'
})
]
最後に、 CampusShuttleAdaptiveCardExtension.ts ファイルに戻り、次のメソッドを CampusShuttleAdaptiveCardExtension
クラスに追加します。 SPFx ランタイムは、プロパティ ウィンドウのプロパティの値が変更されると、このイベントを発生させます。 ドライバー レコードが見つかった場合は、ACE でリストの ID の変更を使用して ACE の状態を初期化します。
protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
if (propertyPath === 'listId' && newValue !== oldValue) {
if (newValue) {
(async () => {
const trip = await fetchListItem(this.context, this.properties.listId);
if (trip) { this.setState({ currentTrip: trip }); }
})();
}
}
}
ACE 状態と初期カード ビューを更新する
ファイル内の既存の import
ステートメントの後に、次のimport
ステートメントを追加します。
import {
IListItem,
fetchListItem,
STATUS_AVAILABLE
} from './sp.service';
状態インターフェイスの ICampusShuttleAdaptiveCardExtensionState
を見つけて、次のコードに示すように currentTrip
プロパティを追加します。
export interface ICampusShuttleAdaptiveCardExtensionState {
currentTrip: IListItem;
}
既存の onInit()
メソッドで state プロパティを初期化します。 既存の this.state = { };
を次のコードに置き換えて、状態を現在のドライバーのプレースホルダートリップに設定します。
this.state = {
currentTrip: {
Title: this.context.pageContext.user.loginName,
Status: STATUS_AVAILABLE
}
};
次に、 onInit()
メソッドに次のコードを追加します。 return Promise.resolve();
ステートメントの直前に、現在のドライバーのトリップ レコードを SharePoint リストから取得します。 一致する旅行が見つかった場合、ACE の状態がこの旅行に更新され、状態を初期化するときに作成した空の既定の旅行が上書きされます。
if (this.properties.listId) {
const trip = await fetchListItem(this.context, this.properties.listId);
if (trip) { this.setState({ currentTrip: trip }); }
}
このコードでは await
キーワード (keyword) を使用しますが、onInit()
メソッドシグネチャはPromise
を返しますが、必要なasync
キーワード (keyword)はありません。
onInit()
メソッド宣言を更新して、次のキーワード (keyword)を含めます。
public async onInit(): Promise<void> { .. }
既存の QuickView を削除し、最初の CardView を更新します
ACE をテストする前の最後の手順は、現在の QuickView を削除することです。 後で、ACE に複数の新しいクイック ビューを追加します。
まず、 CampusShuttleAdaptiveCardExtension.ts ファイルから次の行を削除します。
次の
import
ステートメントを削除します。import { QuickView } from './quickView/QuickView';
QuickView ID の
export
宣言を削除します。export const QUICK_VIEW_REGISTRY_ID: string = 'CampusShuttle_QUICK_VIEW';
CampusShuttleAdaptiveCardExtension
クラスのonInit()
メソッドで、QuickView を登録する次のステートメントを削除します。this.quickViewNavigator.register(QUICK_VIEW_REGISTRY_ID, () => new QuickView());
プロジェクトから次のファイルを削除します。
- ./src/adaptiveCardExtensions/campusShuttle/quickView/template/QuickViewTemplate.json
- ./src/adaptiveCardExtensions/campusShuttle/quickView/QuickView.ts
次に、CardView: ./src/adaptiveCardExtensions/campusShuttle/cardView/CardView.ts を見つけて開き、それに次の変更を加えます。
@microsoft/sp-adaptive-card-extension-base
パッケージの値を参照する既存のimport
ステートメントを見つけて、次の参照を削除します。- IExternalLinkCardAction
- IQuickViewCardAction
CampusShuttleAdaptiveCardExtension
モジュールの値を参照する既存のimport
ステートメントを見つけて、QUICK_VIEW_REGISTRY_ID
定数への参照を削除します。次の
import
ステートメントを、既存のimport
ステートメントの後に追加します:import { STATUS_AVAILABLE } from '../sp.service';
cardButtons()
アクセサー メンバーの内容を次のswitch
ステートメントに置き換えます。 ACE に新しい機能を追加するときに、この演習全体を通じてこの switch ステートメントを更新します。
public get cardButtons(): [ICardButton] | [ICardButton, ICardButton] | undefined {
switch (this.state.currentTrip.Status) {
default:
return undefined;
break;
}
}
-
data()
アクセサー メンバーを更新して、現在のカードに使用されるプロパティを返します。
public get data(): IPrimaryTextCardParameters {
return {
primaryText: strings.PrimaryText,
description: (this.state.currentTrip.Status === STATUS_AVAILABLE)
? `available for hire`
: `TODO`,
title: this.properties.title
};
}
- CardView にボタンがないため、既存の
onCardSelection()
アクセサー メンバーを削除します。
ACE をテストする
これで、ACE の初期状態をテストする準備ができました。
コンソールで、次のステートメントを実行します。
gulp serve --nobrowser
ブラウザーで、ドライバー レコードを格納するためにリストを作成したのと同じサイトの SharePoint ホストワークベンチに移動します。 たとえば、リスト URL が https://contoso.sharepoint.com/sites/MSLearningTeam/Lists/Campus%20Shuttle/AllItems.aspx
されている場合、ホストされているワークベンチの URL は https://contoso.sharepoint.com/sites/MSLearningTeam/_layouts/15/workbench.aspx
。
[ + ] アイコンを選択し、ツールボックスから [Campus Shuttle ] を選択します。
ACE コンポーネントの上にマウス ポインターを合わせ、鉛筆アイコンを選択してプロパティ ウィンドウを開きます。
[リスト ID] ボックスに SharePoint リストの ID を 入力し、右上隅にある [X ] アイコンを選択してプロパティ ウィンドウを閉じます。
ヒント
リストの ID は、リストの設定ページ URL から取得できます。
まずリストを参照し、スイート バーの歯車アイコンを選択してから、[ リスト設定 ] リンクを選択します。
リスト設定のページのクエリ文字列には、List=%7B93f11b8b-6201-4199-b263-3ca78408a73b%7D
などの List プロパティが含まれています。 これは、で囲まれた GUID を含む URL でエンコードされた文字列です。
%7B
プレフィックスとサフィックス%7D
削除して、リストの ID を取得します。 たとえば、このリスト ID は 93f11b8b-6201-4199-b263-3ca78408a73b
。
一覧にレコードがまだないため、ACE のレンダリングに変更があることに気付くことはありません。
この時点で、最小限のプロジェクトが動作しています。 QuickViews を使用して ACE への対話機能の追加を開始できます。
QuickViews を使用して旅行を作成する機能を追加する
次に、現在のユーザーが ACE を使用して新しい旅行を追加できるようにする機能を実装します。 旅行を作成するときは、次の 3 つを設定する必要があります。
- 旅行の配信元/開始場所
- 旅行の目的地の場所
- シャトルドライバーが出発地から乗客をピックアップする途中にある場合、または乗客をピックアップして目的地に向かう途中にある場合
これを実装するには、複数の QuickView を作成し、Viva Connectionsの ACE の地理的位置機能を使用します。
StartTrip QuickView を作成する
まず、./src/adaptiveCardExtensions/campusShuttle/quickView/template フォルダーに新しいファイル StartTripCard.jsonを作成し、次の JSON を追加します。 これにより、アダプティブ カードを使用して QuickView の内容が設定されます。
{
"$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
"type": "AdaptiveCard",
"version": "1.5",
"body": [
{
"type": "TextBlock",
"text": "Start a trip",
"size": "Large",
"weight": "Bolder"
},
{
"type": "TextBlock",
"text": "Select trip status:",
"size": "medium",
"weight": "Bolder"
},
{
"id": "tripType",
"type": "Input.ChoiceSet",
"value": "$trip.Status",
"choices": [
{
"title": "en route to pickup",
"value": "en route"
},
{
"title": "starting trip",
"value": "hired"
}
]
},
{
"type": "TextBlock",
"text": "Set trip details:",
"size": "medium",
"weight": "Bolder"
}
],
"actions": [
{
"id": "originLocation",
"type": "Action.Submit",
"title": "(1) Select trip origin from map"
},
{
"id": "destinationLocation",
"type": "Action.Submit",
"title": "(2) Select / set trip destination"
},
{
"id": "save",
"type": "Action.Submit",
"title": "Save trip",
"style": "positive"
}
]
}
次に、./src/adaptiveCardExtensions/campusShuttle/quickView フォルダーにファイル StartTrip.tsを作成します。 このファイルには、QuickView を実装するクラスが含まれます。
このファイルに次のコードを追加します。
import {
ISPFxAdaptiveCard,
BaseAdaptiveCardView,
IActionArguments
} from '@microsoft/sp-adaptive-card-extension-base';
import * as strings from 'CampusShuttleAdaptiveCardExtensionStrings';
import {
ICampusShuttleAdaptiveCardExtensionProps,
ICampusShuttleAdaptiveCardExtensionState
} from '../CampusShuttleAdaptiveCardExtension';
import { IListItem, upsertListItem } from '../sp.service';
export interface IStartTripData {
title: string;
trip: IListItem;
}
export class StartTrip extends BaseAdaptiveCardView<
ICampusShuttleAdaptiveCardExtensionProps,
ICampusShuttleAdaptiveCardExtensionState,
IStartTripData
> {
public get data(): IStartTripData {
return {
title: strings.Title,
trip: this.state.currentTrip
};
}
public get template(): ISPFxAdaptiveCard {
return require('./template/StartTripCard.json');
}
public onAction(action: IActionArguments): void {
if (action.type === 'Submit') {
if (action.data.tripType) {
const trip = this.state.currentTrip;
trip.Status = action.data.tripType;
this.setState({ currentTrip: trip });
}
if (action.id === 'originLocation') {
// TODO QuickView originLocation
} else if (action.id === 'destinationLocation') {
// TODO QuickView destinationLocation
} else if (action.id === 'save') {
(async () => {
await upsertListItem(this.context, this.properties.listId, this.state.currentTrip);
// TODO QuickView save
})();
}
}
}
}
このファイルの StartTrip
クラスには、次の 3 つのメンバーが含まれています。
-
data()
: このアクセサー メンバーは、プロパティを QuickView の実装に使用されるアダプティブ カードにバインドするために使用されるアダプティブ カード レンダリング エンジンにオブジェクトを返します。 -
template()
: このアクセサー メンバーは、アダプティブ カード定義を含む JSON オブジェクトを返します。 -
onAction()
: このメソッドは、アダプティブ カードで特定のアクションが発生したときに呼び出されます。 この時点で、コードは旅行の種類 (途中 | hired) の値を保存するだけで、プロジェクトに追加するより多くの QuickView カードのプレースホルダーが含まれています。
プロジェクトに含まれる QuickView の参照を簡略化するには、次のコード を含 む ./src/adaptiveCardExtensions/campusShuttle/quickView フォルダーに新しいファイル index.tsを追加します。
export * from './StartTrip';
StartTrip クイック ビューを登録して参照する
これを新しい QuickView を使用するには、ACE の QuickView ナビゲーターに登録する必要があります。 ./src/adaptiveCardExtensions/campusShuttle/CampusShuttleAdaptiveCardExtension.ts ファイルを開きます。
既存の import ステートメントの後に次の import
ステートメントを追加して、作成した新しい QuickView をインポートします。
import {
StartTrip
} from './quickView';
CampusShuttleAdaptiveCardExtension
クラス宣言の直前に定数を見つけて、次の宣言を追加します。
export const QUICK_VIEW_START_TRIP_REGISTRY_ID: string = 'CampusShuttle_StartTrip_QUICK_VIEW';
次に、クラスの onInit()
メソッドCampusShuttleAdaptiveCardExtension
で、次の行を見つけます。
this.cardNavigator.register(CARD_VIEW_REGISTRY_ID, () => new CardView());
次の行を追加して、StartTrip QuickView を QuickView ナビゲーターに登録します。
this.quickViewNavigator.register(QUICK_VIEW_START_TRIP_REGISTRY_ID, () => new StartTrip());
CardView に StartTrip クイック ビューを追加する
最後の手順では、QuickView を CardView に追加して使用します。 VS Code で次のファイルを見つけて開きます: ./src/adaptiveCardExtensions/campusShuttle/cardView/CardView.ts
ACE クラス宣言を含むファイルからプロパティと状態インターフェイスをインポートする import
ステートメントを見つけます。 StartTrip QuickView の ID を含む追加した定数を追加します。
import {
ICampusShuttleAdaptiveCardExtensionProps,
ICampusShuttleAdaptiveCardExtensionState,
QUICK_VIEW_START_TRIP_REGISTRY_ID // << add this
} from '../CampusShuttleAdaptiveCardExtension';
次に、cardButtons()
アクセサーの switch
ステートメントで、既存のdefault
の前に case
ステートメントを追加して、現在のドライバーの状態が使用可能なときに旅行を予約するためのボタンを表示します。
switch (this.state.currentTrip.Status) {
case STATUS_AVAILABLE:
return [{
title: 'Book a Trip',
action: {
type: 'QuickView',
parameters: { view: QUICK_VIEW_START_TRIP_REGISTRY_ID }
}
}];
break;
default:
return undefined;
break;
}
ACE をテストして、QuickView が動作していることを確認します。 以前にローカル Web サーバーを停止した場合は、コンソールで次のコマンドを実行して再起動します。
gulp serve --nobrowser
SharePoint でホストされているワークベンチに移動して、Campus Shuttle ACE を確認します。
[CardView で 旅行を予約 する] ボタンに注目してください。 上部のナビゲーションの右上セクションにある [プレビュー ] リンクを選択してテストします。 このページでは、編集モードからボタンを選択できる表示モードに切り替わります。
StartTrip QuickView の機能を実装してみましょう。
StartTrip QuickView に機能を追加する
これで、StartTrip クイック ビューで使用される 3 つのクイック ビューを追加します。 1 つは旅行の出発地の設定を処理し、もう 1 つは旅行の目的地の選択または設定を処理し、最後の 1 つは旅行を保存するときに確認通知として機能します。
次のコードを 使用 して、 ./src/adaptiveCardExtensions/campusShuttle/quickView/template フォルダーに新しいファイル SetOriginCard.jsonを追加します。
{ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.5", "body": [ { "type": "TextBlock", "weight": "Bolder", "size": "large", "text": "${title}" }, { "type": "TextBlock", "text": "${description}", "wrap": true } ], "actions": [ { "id": "originLocation", "type": "VivaAction.GetLocation", "title": "Select location on the map", "parameters": { "chooseLocationOnMap": true } } ] }
このアダプティブ カードの 1 つのアクションが VivaAction.GetLocation 型に設定されていることに注意してください。 これにより、ユーザーはデバイスから場所を選択し、座標を返すように求められます。
次のコードを使用して、./src/adaptiveCardExtensions/campusShuttle/quickView フォルダーに新しいファイル SetOrigin.tsを追加して、SetOrigin QuickView を実装します。
import { ISPFxAdaptiveCard, BaseAdaptiveCardView, IGetLocationActionArguments } from '@microsoft/sp-adaptive-card-extension-base'; import { ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState } from '../CampusShuttleAdaptiveCardExtension'; import { ILocation, IListItem } from '../sp.service'; export interface ISetOriginData { title: string; description: string; trip: IListItem; } export class SetOrigin extends BaseAdaptiveCardView< ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState, ISetOriginData > { public get data(): ISetOriginData { return { title: 'Set trip starting location', description: 'Select the trip origin location by selecting it on the map.', trip: this.state.currentTrip }; } public get template(): ISPFxAdaptiveCard { return require('./template/SetOriginCard.json'); } public onAction(action: IGetLocationActionArguments): void { if (action.type === 'VivaAction.GetLocation'){ const currentTrip = this.state.currentTrip; currentTrip.OriginLocation = <ILocation> { latitude: action.location.latitude, longitude: action.location.longitude }; this.setState({ currentTrip: currentTrip }); this.quickViewNavigator.pop(); } } }
このコードは、
onAction()
イベント ハンドラー内で、 VivaAction.GetLocation がアダプティブ カードによって送信されたときに、選択した場所を取得する方法に注目してください。 トリップで選択した場所を設定し、ACE の状態で trip オブジェクトを更新します。this.quickViewNavigator.pop()
を最後に呼び出すと、この QuickView が QuickView スタックから削除され、スタック内の次の QuickView の再レンダリングがトリガーされます。
次に、宛先の場所を設定するための同様の QuickView を実装します。
次のコードを 使用して、 新しいファイル SetDestinationCard.json を ./src/adaptiveCardExtensions/campusShuttle/quickView/template フォルダーに追加します。
{ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.5", "body": [ { "type": "TextBlock", "weight": "Bolder", "text": "${title}" }, { "type": "TextBlock", "text": "${description}" }, { "type": "TextBlock", "text": "Select a known location..." }, { "id": "knownDestinationSelection", "type": "Input.ChoiceSet", "choices": [ { "$data": "${campus_locations}", "title": "${title}", "value": "${latitude},${longitude}" } ] }, { "type": "TextBlock", "text": "... or select a specific location on the map:" } ], "actions": [ { "id": "destinationLocation", "type": "VivaAction.GetLocation", "title": "Select trip destination from map", "parameters": { "chooseLocationOnMap": true } }, { "id": "save", "type": "Action.Submit", "title": "Save destination location", "style": "positive" } ] }
このアダプティブ カードは、ユーザーがマップ上の場所を選択するか、定義済みの場所の一覧から選択できるように、配信元の場所に使用されるカードと似ています。 これらの定義済みの場所は、 ./src/adaptiveCardExtensions/campusShuttle/assets/campus_locations.json ファイルにあります。
アダプティブ カードには、別の送信アクション ボタンも含まれています。 設定された配信元 QuickView とは異なり、このボタンは、ユーザーが旅行先を選択するための 2 つのオプションを持つので、設定された目的地 QuickView を閉じるのに使用されます。
次のコードを使用して、./src/adaptiveCardExtensions/campusShuttle/quickView フォルダーに新しいファイル SetDestination.tsを追加して、SetDestination QuickView を実装します。
import { ISPFxAdaptiveCard, BaseAdaptiveCardView, IActionArguments, IGetLocationActionArguments } from '@microsoft/sp-adaptive-card-extension-base'; import { ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState } from '../CampusShuttleAdaptiveCardExtension'; import { ILocation, IListItem } from '../sp.service'; import { sortBy } from '@microsoft/sp-lodash-subset'; interface ICampusLocations { title: string; latitude: number; longitude: number; } export interface ISetDestinationData { title: string; description: string; campus_locations: ICampusLocations[]; trip: IListItem; } const LOCATIONS = require('../assets/campus_locations.json'); export class SetDestination extends BaseAdaptiveCardView< ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState, ISetDestinationData > { public get data(): ISetDestinationData { return { title: 'Set trip destination location', description: 'Pick from a list of known locations, or set the destination by selecting it on the map.', campus_locations: sortBy(LOCATIONS, (l) => l.title), trip: this.state.currentTrip }; } public get template(): ISPFxAdaptiveCard { return require('./template/SetDestinationCard.json'); } public onAction(action: IActionArguments | IGetLocationActionArguments): void { const currentTrip = this.state.currentTrip; // if picked a location on the map... if (action.type === 'VivaAction.GetLocation') { currentTrip.DestinationLocation = <ILocation>{ latitude: action.location.latitude, longitude: action.location.longitude }; this.setState({ currentTrip: currentTrip }); } else if (action.type === 'Submit' && action.id === 'save') { // else, check if picked location from dropdown and save it if (action.data.knownDestinationSelection) { currentTrip.DestinationLocation = <ILocation>{ latitude: Number(action.data.knownDestinationSelection.split(',')[0]), longitude: Number(action.data.knownDestinationSelection.split(',')[1]) }; const selectedLocation = LOCATIONS.filter((knownLocation: any) => ( knownLocation.latitude === (currentTrip.DestinationLocation as ILocation).latitude && knownLocation.longitude === (currentTrip.DestinationLocation as ILocation).longitude ))[0]; currentTrip.DestinationName = selectedLocation.title; } this.setState({ currentTrip: currentTrip }); this.quickViewNavigator.pop(); } } }
最後の手順では、保存確認 QuickView をプロジェクトに追加します。
次のコードを 使用 して、 ./src/adaptiveCardExtensions/campusShuttle/quickView/template フォルダーに新しいファイル SaveTripCard.jsonを追加します。
{ "schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.5", "body": [{ "type": "TextBlock", "text": "${title}" }], "actions": [{ "type": "Action.Submit", "id": "close", "title": "Close" }] }
次のコードを使用して、./src/adaptiveCardExtensions/campusShuttle/quickView フォルダーに新しいファイル SaveTrip.tsを追加して、SaveTrip QuickView を実装します。
import { BaseAdaptiveCardView, IActionArguments, ISPFxAdaptiveCard } from '@microsoft/sp-adaptive-card-extension-base'; import { ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState } from '../CampusShuttleAdaptiveCardExtension'; export interface ISaveTripData { title: string; } export class SaveTrip extends BaseAdaptiveCardView< ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState, ISaveTripData > { public get data(): ISaveTripData { return { title: 'Trip saved successfully.' }; } public get template(): ISPFxAdaptiveCard { return require('./template/SaveTripCard.json'); } public onAction(action: IActionArguments): void { if (action.id === 'close') { this.quickViewNavigator.close(); } } }
これら 3 つの新しい QuickView を使用するには、それらを登録する必要があります。
./src/adaptiveCardExtensions/campusShuttle/quickView/index.ts ファイルを開き、新しい QuickView をエクスポートします。
export * from './StartTrip'; export * from './SetOrigin'; // << add export * from './SetDestination'; // << add export * from './SaveTrip'; // << add
./src/adaptiveCardExtensions/campusShuttle/CampusShuttleAdaptiveCardExtension.ts ファイルを開きます。
追加した既存の
import
ステートメントを更新して 、StartTrip QuickView をインポートして、次の 3 つの新しいクイック ビューを参照します。import { StartTrip, SetOrigin, SetDestination, SaveTrip } from './quickView';
CardView と QuickView の ID を宣言する定数を見つけ、新しい QuickView に次の ID を追加します。
export const QUICK_VIEW_SET_ORIGIN_REGISTRY_ID: string = 'CampusShuttle_SetOrigin_QUICK_VIEW'; export const QUICK_VIEW_SET_DESTINATION_REGISTRY_ID: string = 'CampusShuttle_SetDestination_QUICK_VIEW'; export const QUICK_VIEW_SAVE_TRIP_REGISTRY_ID: string = 'CampusShuttle_SaveTrip_QUICK_VIEW';
CampusShuttleAdaptiveCardExtension
クラスのonInit()
メソッド内で、StartTrip QuickView を登録したthis.quickViewNavigator.register()
ステートメントを既存の呼び出しの後に次のコードを追加します。this.quickViewNavigator.register(QUICK_VIEW_SET_ORIGIN_REGISTRY_ID, () => new SetOrigin()); this.quickViewNavigator.register(QUICK_VIEW_SET_DESTINATION_REGISTRY_ID, () => new SetDestination()); this.quickViewNavigator.register(QUICK_VIEW_SAVE_TRIP_REGISTRY_ID, () => new SaveTrip());
最後の手順では、QuickView を既存の StartTrip QuickView に接続します。
./src/adaptiveCardExtensions/campusShuttle/quickView/StartTrip.ts ファイルを見つけて開きます。
CampusShuttleCopilotAdaptiveCardExtension
モジュール内のプロパティ インターフェイスと状態インターフェイスを参照する既存のimport
ステートメントを見つけます。 これを更新して、3 つの新しい QuickView の 3 つの定数をインポートします。import { ICampusShuttleCopilotAdaptiveCardExtensionProps, ICampusShuttleCopilotAdaptiveCardExtensionState, QUICK_VIEW_SET_ORIGIN_REGISTRY_ID, QUICK_VIEW_SET_DESTINATION_REGISTRY_ID, QUICK_VIEW_SAVE_TRIP_REGISTRY_ID } from '../CampusShuttleAdaptiveCardExtension';
onAction()
メソッドのコメント// TODO QuickView originLocation
を次のように置き換えて、SetOrigin QuickView を実装します。this.quickViewNavigator.push(QUICK_VIEW_SET_ORIGIN_REGISTRY_ID);
onAction()
メソッドのコメント// TODO QuickView destinationLocation
を次に置き換えて、SetDestination QuickView を実装します。this.quickViewNavigator.push(QUICK_VIEW_SET_DESTINATION_REGISTRY_ID);
onAction()
メソッドのコメント// TODO QuickView save
を次のように置き換えて、SaveTrip QuickView を実装します。this.quickViewNavigator.push(QUICK_VIEW_SAVE_TRIP_REGISTRY_ID);
これらの呼び出しのたびに、QuickView がナビゲーターに プッシュ されていることに注意してください。 これにより、スタック上の新しい項目を使用して QuickView の再レンダリングがトリガーされます。 以前は、QuickView をスタックからポップしていたリコール。
最後の手順では、旅行が予約されたときに CardView の表示を更新します。
./src/adaptiveCardExtensions/campusShuttle/cardView/CardView.ts ファイルを見つけて開きます。
既存の
import
ステートメント (import { STATUS_AVAILABLE } from '../sp.service';
) を次のコードに置き換えます。import { ILocation, STATUS_AVAILABLE, STATUS_ENROUTE, STATUS_HIRED } from '../sp.service';
cardButtons()
メソッドのswitch
ステートメントを次のコードに更新します。switch (this.state.currentTrip.Status) { case STATUS_AVAILABLE: return [{ title: 'Book a Trip', action: { type: 'QuickView', parameters: { view: QUICK_VIEW_START_TRIP_REGISTRY_ID } } }]; break; case STATUS_ENROUTE: return [ { title: 'View pickup location', action: { type: 'VivaAction.ShowLocation', parameters: { locationCoordinates: { latitude: (this.state.currentTrip.OriginLocation as ILocation).latitude, longitude: (this.state.currentTrip.OriginLocation as ILocation).longitude } } } } ]; break; case STATUS_HIRED: return [ { title: 'View dropoff location', action: { type: 'VivaAction.ShowLocation', parameters: { locationCoordinates: { latitude: (this.state.currentTrip.DestinationLocation as ILocation).latitude, longitude: (this.state.currentTrip.DestinationLocation as ILocation).longitude } } } } ]; break; default: return undefined; break; }
これらの変更により、現在のシャトル ドライバーの状態に応じて、異なるボタンとテキストが条件付きで表示されます。 現在、CardView のアクション
VivaAction.ShowLocation
を使用して、指定した配信元と宛先の場所を表示していることに注意してください。最後に、
data()
メソッドのreturn
ステートメントを次のコードに更新します。return { primaryText: strings.PrimaryText, description: (this.state.currentTrip.Status === STATUS_AVAILABLE) ? `available for hire` : (this.state.currentTrip.Status === STATUS_ENROUTE) ? `Booked - ${STATUS_ENROUTE} to pickup...` : (this.state.currentTrip.DestinationName) ? `Hired - driving passenger to ${this.state.currentTrip.DestinationName}...` : `Hired - driving passenger to destination...`, title: this.properties.title };
これにより、シャトル ドライバーの乗車状態に基づいて条件付きメッセージが変更されることに注意してください。
テスト 旅行作成エクスペリエンス
この時点で、ブラウザーで完全な旅行作成エクスペリエンスをテストできます。
以前にローカル Web サーバーを停止した場合は、コンソールで次のコマンドを実行して再起動します。
gulp serve --nobrowser
SharePoint でホストされているワークベンチに移動して、Campus Shuttle ACE を表示します。
カード サイズが [中] に設定されている場合、ACE は CardView に 1 つのボタンのみを表示します。 ページが編集モードの間にプロパティ ウィンドウを開き、カードのサイズを [大] に変更して、両方のボタンが CardView に表示されるようにします。
次に、ツール バーの右上にある [プレビュー ] ボタンを選択します。
まず、最初の CardView で [ 旅行の予約 ] ボタンを選択します。 これは、以前にテストした [旅行の開始] クイック ビューを表示します。
(1) [マップから旅行の配信元を選択] ボタンを選択して、SetOrigin QuickView を読み込みます。 次に、[ マップ上の場所の選択 ] ボタンを選択します。 ブラウザーに位置情報へのアクセス権を付与していない場合は、アクセスを求めるメッセージが表示されます。 VivaAction.GetLocation アクションを機能させるには、この要求を承認する必要があります。
ブラウザーに位置情報へのアクセスを許可すると、マップを含むダイアログが表示されます。 乗車の乗車場所の場所にマップを中央揃えし、乗車を選択して [ 場所の共有 ] ボタンを選択します。
(2) [旅行先の選択/設定] ボタンを選択して、SetDestination QuickView を読み込みます。 今回は、ドロップダウン ボックスで既知の場所の 1 つを選択し、[ 保存先の保存 ] ボタンを選択します。
最後に、乗車状態を選択して 乗車に向かう途中で 、[ 旅行の保存 ] ボタンを選択します。
旅行が保存された状態で、現在のコンテキストに基づいて CardView にさまざまなボタンとテキストが表示されていることがわかります。
最後に、旅行データが含まれている一覧を参照して、テスト旅行のデータの格納方法を確認します。
キャンパスシャトルACEは旅行の作成に適しています。 最後の 2 つの手順は、ドライバーが乗客をピックアップし、目的地に乗客を運転する途中にあるシナリオを実装することです。
乗客のピックアップに途中で機能を追加する
次に、ドライバーが乗客を迎えに行く途中にある場合のシナリオを実装しましょう。
次のコードを 使用 して、 ./src/adaptiveCardExtensions/campusShuttle/quickView/template フォルダーに新しいファイル UpdateTripCard.jsonを追加します。
{ "schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.5", "body": [ { "type": "TextBlock", "weight": "Bolder", "text": "${title}" } ], "actions": [ { "id": "cancel", "type": "Action.Submit", "title": "Cancel Current Trip" }, { "id": "pickup", "type": "Action.Submit", "title": "Pickup Passenger", "style": "positive" } ] }
次のコードを使用して、./src/adaptiveCardExtensions/campusShuttle/quickView フォルダーに新しいファイル UpdateTrip.tsを追加して、UpdateTrip QuickView を実装します。
import { IActionArguments, ISPFxAdaptiveCard, BaseAdaptiveCardView } from '@microsoft/sp-adaptive-card-extension-base'; import { ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState } from '../CampusShuttleAdaptiveCardExtension'; import { STATUS_HIRED, upsertListItem } from '../sp.service'; export interface IUpdateTripData { title: string; } export class UpdateTrip extends BaseAdaptiveCardView< ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState, IUpdateTripData > { public get data(): IUpdateTripData { return { title: 'Update the existing trip' }; } public get template(): ISPFxAdaptiveCard { return require('./template/UpdateTripCard.json'); } public onAction(action: IActionArguments): void { if (action.type !== 'Submit') { return; } switch (action.id) { case 'cancel': // TODO QuickView cancelTrip break case 'pickup': // update current item status const trip = this.state.currentTrip; trip.Status = STATUS_HIRED; // save to list (async () => { await upsertListItem(this.context, this.properties.listId, trip); })(); // update ACE this.setState({ currentTrip: trip }); this.quickViewNavigator.close(); break default: return; } } }
ドライバーが旅行をキャンセルするか、乗客を引き渡すことによって、旅行を削除したい場合は、プロジェクトに確認手順が必要です。 これを実装するには、両方のケースを動的に処理する単一の確認 QuickView を使用します。
次のコードを 使用 して、 ./src/adaptiveCardExtensions/campusShuttle/quickView/template フォルダーに新しいファイル ConfirmationCard.jsonを追加します。
{ "schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.5", "body": [ { "type": "TextBlock", "text": "${title}", "size": "Large" }, { "type": "TextBlock", "text": "${description}" } ], "actions": [ { "id": "confirm", "type": "Action.Submit", "title": "${title}", "style": "positive" } ] }
確認 QuickView を実装するには、次のコードを使用して、新しいファイル ConfirmationQuickView.ts を ./src/adaptiveCardExtensions/campusShuttle/quickView フォルダーに追加します。
import { IActionArguments, ISPFxAdaptiveCard, BaseAdaptiveCardView } from '@microsoft/sp-adaptive-card-extension-base'; import { ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState } from '../CampusShuttleAdaptiveCardExtension'; import { deleteListItem, STATUS_AVAILABLE } from '../sp.service'; export interface IConfirmationQuickViewData { title: string; description: string; } export class ConfirmationQuickView extends BaseAdaptiveCardView< ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState, IConfirmationQuickViewData > { constructor(private confirmType: 'cancel' | 'complete') { super(); } public get data(): IConfirmationQuickViewData { return { title: `${this.confirmType.substring(0,1).toUpperCase()}${this.confirmType.substring(1,this.confirmType.length)} Trip`, description: `Are you sure you want to ${this.confirmType} the trip?` }; } public get template(): ISPFxAdaptiveCard { return require('./template/ConfirmationCard.json'); } public onAction(action: IActionArguments): void { if (action.type === 'Submit' && action.id === 'confirm') { (async () => { // delete list item await deleteListItem(this.context, this.properties.listId, Number(this.state.currentTrip.Id)); })(); // update state to initial value this.setState({ currentTrip: { Title: this.context.pageContext.user.loginName, Status: STATUS_AVAILABLE } }); // close this.quickViewNavigator.close(); } } }
これら 3 つの新しい QuickView を使用するには、それらを登録する必要があります。
./src/adaptiveCardExtensions/campusShuttle/quickView/index.ts ファイルを開き、新しい QuickView をエクスポートします。
// .. existing export statements export * from './UpdateTrip'; export * from './ConfirmationQuickView';
./src/adaptiveCardExtensions/campusShuttle/CampusShuttleAdaptiveCardExtension.ts ファイルを開きます。
既存の
import
を更新して QuickView をインポートし、新しい QuickView を参照します。import { StartTrip, SetOrigin, SetDestination, SaveTrip, UpdateTrip, // << add ConfirmationQuickView // << add } from './quickView';
CardView と QuickView の ID を宣言する定数を見つけ、新しい QuickView に次の ID を追加します。
export const QUICK_VIEW_CANCEL_TRIP_REGISTRY_ID: string = 'CampusShuttleCopilot_CancelTrip_QUICK_VIEW'; export const QUICK_VIEW_COMPLETE_TRIP_REGISTRY_ID: string = 'CampusShuttleCopilot_CompleteTrip_QUICK_VIEW'; export const QUICK_VIEW_UPDATE_TRIP_REGISTRY_ID: string = 'CampusShuttleCopilot_UpdateTrip_QUICK_VIEW';
最初の 2 つの定数が確認 QuickView を参照しない方法に注目してください。 これは、同じ QuickView の 2 つの実装を作成するためです。
CampusShuttleAdaptiveCardExtension
クラスのonInit()
メソッド内で、StartTrip QuickView を登録したthis.quickViewNavigator.register()
ステートメントを既存の呼び出しの後に次のコードを追加します。this.quickViewNavigator.register(QUICK_VIEW_CANCEL_TRIP_REGISTRY_ID, () => new ConfirmationQuickView('cancel')); this.quickViewNavigator.register(QUICK_VIEW_COMPLETE_TRIP_REGISTRY_ID, () => new ConfirmationQuickView('complete')); this.quickViewNavigator.register(QUICK_VIEW_UPDATE_TRIP_REGISTRY_ID, () => new UpdateTrip());
最後の手順では、QuickView を既存の CardView と QuickView に接続します。
./src/adaptiveCardExtensions/campusShuttle/cardView/CardView.ts ファイルを見つけて開きます。
CampusShuttleCopilotAdaptiveCardExtension
モジュール内のプロパティ インターフェイスと状態インターフェイスを参照する既存のimport
ステートメントを見つけます。 更新プログラムの 3 つの定数をインポートし、新しい QuickView を完了するように更新します。import { ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState, QUICK_VIEW_START_TRIP_REGISTRY_ID, QUICK_VIEW_UPDATE_TRIP_REGISTRY_ID, // << add QUICK_VIEW_COMPLETE_TRIP_REGISTRY_ID // << add } from '../CampusShuttleAdaptiveCardExtension';
cardButton()
アクセサー メソッドで、switch ステートメントを更新して、さらにボタンを追加します。case STATUS_ENROUTE
return
ステートメントに次のボタンを追加します。{ title: 'Update Trip', action: { type: 'QuickView', parameters: { view: QUICK_VIEW_UPDATE_TRIP_REGISTRY_ID } } }
case STATUS_HIRED
return
ステートメントに次のボタンを追加します。{ title: 'Complete Trip', action: { type: 'QuickView', parameters: { view: QUICK_VIEW_COMPLETE_TRIP_REGISTRY_ID } } }
./src/adaptiveCardExtensions/campusShuttle/quickView/UpdateTrip.ts ファイルを見つけて開きます。
CampusShuttleCopilotAdaptiveCardExtension
モジュール内のプロパティ インターフェイスと状態インターフェイスを参照する既存のimport
ステートメントを見つけます。 更新プログラムの 3 つの定数をインポートし、新しい QuickView を完了するように更新します。import { ICampusShuttleAdaptiveCardExtensionProps, ICampusShuttleAdaptiveCardExtensionState, QUICK_VIEW_CANCEL_TRIP_REGISTRY_ID // << add } from '../CampusShuttleAdaptiveCardExtension';
onAction()
メソッドのコメント// TODO QuickView cancelTrip
を次に置き換えて、SetOrigin QuickView を実装します。this.quickViewNavigator.push(QUICK_VIEW_CANCEL_TRIP_REGISTRY_ID);
テスト旅行管理エクスペリエンス
この時点で、ブラウザーで旅行管理エクスペリエンスをテストできます。
以前にローカル Web サーバーを停止した場合は、コンソールで次のコマンドを実行して再起動します。
gulp serve --nobrowser
SharePoint でホストされているワークベンチに移動して Campus Shuttle ACE を表示し、ツール バーの右上にある [プレビュー ] ボタンを選択します。
CardView に [ トリップの更新] ボタンが含まれていることに注目してください。
[ 乗車の更新 ] ボタンを選択すると、乗客をキャンセルまたはピックアップするためのオプションが 2 つあります。
[現在の 旅行のキャンセル ] ボタンを選択すると、ACE の状態がリセットされ、SharePoint リストからドライバーのレコードが削除されます。 [ ピックアップ乗客 ] ボタンを選択すると、ACE 状態と SharePoint リスト アイテムの両方で乗車が更新され、旅行の状態が 途中 から採用済みに変更 されます。
[ 乗車客 ] ボタンを選択します。 CardView コンテキストとボタンが変更され、乗車状態の変更が示されます。
最後に、[旅行の 完了 ] ボタンを選択して確認の QuickView を表示し、[ 旅行の完了 ] ボタンを選択して確認します。 これで旅行が完了します。
この演習では、Viva Connectionsの geo 位置情報機能を使用する [プライマリ テキスト カード] オプションを使用して SPFx ACE を作成しました。