Esercizio - Creare un'ace SPFx con funzionalità di geolocalizzazione

Completato

In questo esercizio si creerà un'estensione per schede adattive (ACE) SharePoint Framework (SPFx) con il modello Scheda di testo primaria che usa le funzionalità di posizione geografica in Viva Connections.

Lo scenario che si implementerà è una versione semplice di un servizio navetta del campus che consente alle persone di passare da un edificio all'altro. L'ACE è per il sub di una navetta. L'autista userà l'ACE per prenotare un viaggio e indicare che è sulla strada per prendere un passeggero o consegnare un passeggero a destinazione.

Prerequisiti

Lo sviluppo di ACL per Viva Connections richiede un tenant di Microsoft 365, SharePoint Online e Viva Connections configurato nel tenant. Usare le risorse seguenti per preparare il tenant:

Sono necessari anche gli strumenti di sviluppo necessari installati nella workstation:

Importante

Nella maggior parte dei casi, è consigliabile l'installazione dell'ultima versione di tali strumenti. Le versioni qui elencate sono state utilizzate durante la pubblicazione di questo modulo e quando è stato testato per l'ultima volta.

Creare un elenco di SharePoint per archiviare i dati

Il primo passaggio consiste nel creare un nuovo elenco di SharePoint per archiviare i dati per ogni driver dello shuttle del campus.

In un browser passare al sito di SharePoint in cui si vuole testare il progetto che si creerà in questo esercizio.

Selezionare New (Nuovo ) e quindi List (Elenco ) dalle opzioni disponibili:

Screenshot della nuova esperienza di elenco.

Nella finestra di dialogo Crea un elenco selezionare Elenco vuoto.

Impostare il nome dell'elenco su Campus Shuttle e selezionare Crea.

Quando il browser viene aggiornato per visualizzare il nuovo elenco, aggiungere alcune colonne all'elenco. Selezionare Aggiungi colonna, selezionare Testo e quindi selezionare il pulsante Avanti . Nel pannello Crea colonna immettere i valori seguenti e selezionare Salva:

  • Nome: OriginLocation
  • Tipo: singola riga di testo

Ripetere questo processo usando i valori seguenti per aggiungere altre colonne all'elenco:

  • Colonna:
    • Nome: DestinationName
    • Tipo: singola riga di testo
  • Colonna:
    • Nome: DestinationLocation
    • Tipo: singola riga di testo
  • Colonna:
    • Nome: Stato
    • Tipo: Scelta
    • Scelte:
      • assoldato
      • en route
      • disponibile

Con list per archiviare i dati per l'ACE, è ora possibile creare il progetto.

Creare e preparare il progetto SPFx

Aprire un prompt dei comandi, passare a una cartella in cui si vuole creare il progetto SPFx. Eseguire il generatore Yeoman di SharePoint tramite il seguente comando:

yo @microsoft/sharepoint

Usare quanto segue per completare la richiesta visualizzata:

  • Qual è il nome della soluzione?: AceCampusShuttle
  • Quale tipo di componente lato client creare?: Estensione scheda adattiva
  • Quale modello si vuole usare?: Modello di testo primario
  • Qual è il nome dell'estensione della scheda adattiva?: Campus Shuttle

Dopo il provisioning delle cartelle necessarie per il progetto, il generatore installerà tutti i pacchetti di dipendenze eseguendo automaticamente l'installazione di npm . Dopo che npm ha completato il download di tutte le dipendenze, aprire il progetto in Visual Studio Code.

Aggiungere dati di esempio

L'ACE che si creerà consentirà al driver dello shuttle di scegliere una destinazione da un elenco o selezionare un punto su una mappa.

Creare un nuovo file ./src/adaptiveCardExtensions/campusShuttle/assets/campus_locations.json nel progetto e aggiungere una matrice per gli oggetti location. Ogni posizione deve avere una proprietà name, latitude e longitudine . In alternativa, è possibile incollare il codice JSON seguente nel file che contiene alcune posizioni dell'Università della Florida a Gainesville, in Florida, Stati Uniti.

[
  { "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 }
]

Aggiungere l'helper del servizio API REST di SharePoint

Aggiungere quindi un servizio REST di SharePoint al progetto per gestire tutte le operazioni di lettura e scrittura nell'elenco di SharePoint creato per archiviare i dati del driver shuttle.

Creare un nuovo file ./src/adaptiveCardExtensions/campusShuttle/sp.service.ts nel progetto e aggiungervi il codice seguente:

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' }
    }
  );
}

Questo servizio esporta gli elementi seguenti che verranno usati in tutto il progetto:

  • Tre costanti () per le opzioni di stato:
    • STATUS_AVAILABLE
    • STATUS_ENROUTE
    • STATUS_HIRED
  • fetchListItem(): questo metodo recupera il record del driver attualmente connesso (se presente).
  • upsertListItem(): questo metodo crea un nuovo record del driver o ne aggiorna uno esistente.
  • deleteListItem(): questo metodo elimina un record del driver quando è più lungo in un viaggio.

Inizializzare il progetto

Ora che il progetto ha aggiunto alcune dipendenze di base, è ora possibile implementare l'inizializzazione di alcune funzionalità di base quando l'ACE viene caricato per la prima volta nella pagina. Ciò comporta la configurazione dello stato dell'ace e l'abilitazione dell'utente per impostare l'ID dell'elenco che contiene i dettagli della corsa del driver.

Aggiornare l'ace per consentire all'utente di impostare l'ID elenco di SharePoint

Individuare la classe ACE nel file ./src/adaptiveCardExtensions/campusShuttle/CampusShuttleAdaptiveCardExtension.ts e aprirla in VS Code.

Individuare l'interfaccia ICampusShuttleAdaptiveCardExtensionProps e aggiungere la listId proprietà per archiviare l'ID dell'elenco di SharePoint che contiene i record di stato del driver:

export interface ICampusShuttleAdaptiveCardExtensionProps {
  title: string;
  listId: string;
}

Individuare e aprire il file ./src/adaptiveCardExtensions/campusShuttle/CampusShuttlePropertyPane.ts. Aggiungere un nuovo PropertyPaneTextField elemento alla groupFields matrice per aggiungere all'utente un'opzione per impostare l'ID dell'elenco che contiene i record di stato del driver:

groupFields: [
  PropertyPaneTextField('title', {
    label: strings.TitleFieldLabel
  }),
  PropertyPaneTextField('listId', {
    label: 'List ID (GUID)'
  })
]

Tornare infine al file CampusShuttleAdaptiveCardExtension.ts e aggiungere il metodo seguente alla CampusShuttleAdaptiveCardExtension classe . Il runtime SPFx genera questo evento quando cambia il valore di una proprietà nel riquadro delle proprietà. Si vuole che l'ACE usi una modifica nell'ID dell'elenco per tentare di inizializzare lo stato dell'ACE se viene trovato un record del driver:

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 }); }
      })();
    }
  }
}

Aggiornare lo stato ace e la visualizzazione scheda iniziale

Aggiungere l'istruzione seguente import dopo le istruzioni esistenti import nel file:

import {
  IListItem,
  fetchListItem,
  STATUS_AVAILABLE
} from './sp.service';

Individuare l'interfaccia ICampusShuttleAdaptiveCardExtensionState di stato e aggiungere la proprietà currentTrip come illustrato nel codice seguente:

export interface ICampusShuttleAdaptiveCardExtensionState {
  currentTrip: IListItem;
}

Inizializzare la proprietà di stato nel metodo esistente onInit() . Sostituire l'oggetto esistente this.state = { }; con il codice seguente per impostare lo stato di un viaggio segnaposto per il driver corrente:

this.state = {
  currentTrip: {
    Title: this.context.pageContext.user.loginName,
    Status: STATUS_AVAILABLE
  }
};

Aggiungere quindi il codice seguente al onInit() metodo , immediatamente prima dell'istruzione return Promise.resolve(); per recuperare il record di viaggio del driver corrente dall'elenco SharePoint. Se viene trovato un viaggio corrispondente, aggiorna lo stato dell'ace a questo viaggio, sovrascrivendo il viaggio predefinito vuoto creato durante l'inizializzazione dello stato.

if (this.properties.listId) {
  const trip = await fetchListItem(this.context, this.properties.listId);
  if (trip) { this.setState({ currentTrip: trip }); }
}

Questo codice usa la await parola chiave ma la firma del onInit() metodo, mentre restituisce , Promisenon ha la parola chiave obbligatoria async . Aggiornare la dichiarazione del onInit() metodo per includere questa parola chiave:

public async onInit(): Promise<void> { .. }

Rimuovere il controllo QuickView esistente e aggiornare il controllo CardView iniziale

L'ultimo passaggio prima di testare l'ace consiste nel rimuovere l'oggetto QuickView corrente. Successivamente, verranno aggiunti più nuovi quickview all'ace.

Per iniziare, rimuovere le righe seguenti dal file CampusShuttleAdaptiveCardExtension.ts :

  1. Rimuovere l'istruzione seguente import :

    import { QuickView } from './quickView/QuickView';
    
  2. Rimuovere la export dichiarazione dell'ID QuickView:

    export const QUICK_VIEW_REGISTRY_ID: string = 'CampusShuttle_QUICK_VIEW';
    
  3. Nel metodo della CampusShuttleAdaptiveCardExtensiononInit() classe rimuovere l'istruzione seguente che registra QuickView:

    this.quickViewNavigator.register(QUICK_VIEW_REGISTRY_ID, () => new QuickView());
    
  4. Eliminare i file seguenti dal progetto:

    • ./src/adaptiveCardExtensions/campusShuttle/quickView/template/QuickViewTemplate.json
    • ./src/adaptiveCardExtensions/campusShuttle/quickView/QuickView.ts

Individuare e aprire quindi CardView: ./src/adaptiveCardExtensions/campusShuttle/cardView/CardView.ts e apportare le modifiche seguenti:

  1. Individuare l'istruzione esistente import che fa riferimento ai valori dal @microsoft/sp-adaptive-card-extension-base pacchetto e rimuovere i riferimenti seguenti:

    • IExternalLinkCardAction
    • IQuickViewCardAction
  2. Individuare l'istruzione esistente import che fa riferimento ai valori del CampusShuttleAdaptiveCardExtension modulo e rimuovere il riferimento alla QUICK_VIEW_REGISTRY_ID costante.

  3. Aggiungere l'importistruzione seguenteimport dopo le istruzioni esistenti:

    import { STATUS_AVAILABLE } from '../sp.service';
    
  4. Sostituire il contenuto del membro della cardButtons() funzione di accesso con l'istruzione seguente switch . Questa istruzione switch verrà aggiornata durante questo esercizio durante l'aggiunta di nuove funzionalità all'ACE:

public get cardButtons(): [ICardButton] | [ICardButton, ICardButton] | undefined {
  switch (this.state.currentTrip.Status) {
    default:
      return undefined;
      break;
  }
}
  1. Aggiornare il membro della data() funzione di accesso per restituire le proprietà che verranno utilizzate per la scheda corrente:
public get data(): IPrimaryTextCardParameters {
  return {
    primaryText: strings.PrimaryText,
    description: (this.state.currentTrip.Status === STATUS_AVAILABLE)
      ? `available for hire`
      : `TODO`,
    title: this.properties.title
  };
}
  1. Rimuovere il membro della funzione di accesso esistente onCardSelection() perché il controllo CardView non contiene più pulsanti.

Testare l'ACE

A questo punto si è pronti per testare lo stato iniziale dell'ace.

Nella console eseguire l'istruzione seguente:

gulp serve --nobrowser

In un browser passare al workbench ospitato in SharePoint nello stesso sito in cui è stato creato l'elenco per archiviare i record dei driver. Ad esempio, se l'URL dell'elenco è https://contoso.sharepoint.com/sites/MSLearningTeam/Lists/Campus%20Shuttle/AllItems.aspx, l'URL per il workbench ospitato è https://contoso.sharepoint.com/sites/MSLearningTeam/_layouts/15/workbench.aspx.

Selezionare l'icona + e quindi il Campus Shuttle dalla casella degli strumenti:

Screenshot della casella degli strumenti SPFx.

Passare il mouse sul componente ACE e selezionare l'icona a matita per aprire il riquadro delle proprietà:

Screenshot dell'esperienza di modifica per un'ace.

Immettere l'ID dell'elenco SharePoint nella casella di testo ID elenco , quindi chiudere il riquadro delle proprietà selezionando l'icona X nell'angolo in alto a destra.

Consiglio

È possibile ottenere l'ID di un elenco dall'URL della pagina delle impostazioni dell'elenco.

Passare prima all'elenco e quindi selezionare l'icona a ingranaggio nella barra della suite, quindi selezionare il collegamento Impostazioni elenco .

La stringa di query della pagina delle impostazioni elenco contiene una proprietà List , ad List=%7B93f11b8b-6201-4199-b263-3ca78408a73b%7Desempio . Si tratta di una stringa con codifica URL che contiene guid racchiusi tra {}. Rimuovere il prefisso e %7D il %7B suffisso per ottenere l'ID dell'elenco. Ad esempio, questo ID elenco è 93f11b8b-6201-4199-b263-3ca78408a73b.

Screenshot di come ottenere la pagina delle impostazioni dell'elenco.

Non si noterà una modifica nel rendering dell'ace perché non sono ancora presenti record nell'elenco.

A questo punto, il progetto minimo funziona. È possibile iniziare ad aggiungere interattività all'ace con QuickViews.

Aggiungere la possibilità di creare viaggi con QuickViews

A questo momento si implementerà la funzionalità per consentire all'utente corrente di aggiungere un nuovo viaggio usando l'ACE. Quando creano un viaggio, devono impostare tre elementi:

  • posizione di origine/inizio per il viaggio
  • località di destinazione per il viaggio
  • se il conducente dello shuttle è in viaggio per prendere un passeggero dal luogo di origine, o ha prelevato il passeggero e sulla strada per la destinazione

Per implementarlo, si creeranno più QuickView e si userà la funzionalità di posizione geografica degli ACL in Viva Connections.

Creare il controllo QuickView StartTrip

Per iniziare, creare un nuovo file StartTripCard.json nella cartella ./src/adaptiveCardExtensions/campusShuttle/quickView/template e aggiungervi il codice JSON seguente. In questo modo viene impostato il contenuto di QuickView usando una scheda adattiva.

{
  "$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"
    }
  ]
}

Creare quindi il file StartTrip.ts nella cartella ./src/adaptiveCardExtensions/campusShuttle/quickView . Questo file conterrà la classe che implementa QuickView.

Aggiungere il codice seguente al file:

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
        })();
      }
    }
  }

}

La StartTrip classe in questo file contiene tre membri:

  • data(): questo membro della funzione di accesso restituisce un oggetto al motore di rendering della scheda adattiva che verrà usato per associare le proprietà alla scheda adattiva usata per implementare QuickView.
  • template(): questo membro della funzione di accesso restituisce un oggetto JSON che contiene la definizione della scheda adattiva.
  • onAction(): questo metodo viene chiamato quando si verificano determinate azioni nella scheda adattiva. A questo punto, il codice salva semplicemente il valore del tipo di viaggio (in corso | dinoleggio) e contiene i segnaposto per altre schede QuickView che verranno aggiunte al progetto.

Per semplificare il riferimento ai controlli QuickView che il progetto conterrà, aggiungere un nuovo file index.ts alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView con il codice seguente:

export * from './StartTrip';

Registrare e fare riferimento a StartTrip QuickView

Per usarlo, è necessario registrarlo con lo strumento di navigazione QuickView dell'ACE. Aprire il file ./src/adaptiveCardExtensions/campusShuttle/CampusShuttleAdaptiveCardExtension.ts .

Aggiungere l'istruzione seguente import dopo le istruzioni import esistenti per importare il nuovo controllo QuickView creato:

import {
  StartTrip
} from './quickView';

Individuare la costante immediatamente prima della dichiarazione di CampusShuttleAdaptiveCardExtension classe e aggiungere la dichiarazione seguente:

export const QUICK_VIEW_START_TRIP_REGISTRY_ID: string = 'CampusShuttle_StartTrip_QUICK_VIEW';

Successivamente, nel CampusShuttleAdaptiveCardExtension metodo della onInit() classe individuare la riga seguente:

this.cardNavigator.register(CARD_VIEW_REGISTRY_ID, () => new CardView());

Aggiungere la riga seguente per registrare Il controllo QuickView StartTrip con lo strumento di navigazione QuickView.

this.quickViewNavigator.register(QUICK_VIEW_START_TRIP_REGISTRY_ID, () => new StartTrip());

Aggiungere StartTrip QuickView a CardView

L'ultimo passaggio consiste nell'aggiungere QuickView a CardView per usarlo. Individuare e aprire il file seguente in VS Code: ./src/adaptiveCardExtensions/campusShuttle/cardView/CardView.ts

Individuare l'istruzione import che importa la proprietà e l'interfaccia di stato dal file che contiene la dichiarazione della classe ACE. Aggiungere la costante aggiunta che contiene l'ID di StartTrip QuickView:

import {
  ICampusShuttleAdaptiveCardExtensionProps,
  ICampusShuttleAdaptiveCardExtensionState,
  QUICK_VIEW_START_TRIP_REGISTRY_ID   // << add this
} from '../CampusShuttleAdaptiveCardExtension';

Nell'istruzione della cardButtons() funzione di accesso aggiungere case quindi l'istruzione prima dell'oggetto switch esistente default per visualizzare un pulsante per prenotare un viaggio quando è disponibile lo stato del driver corrente:

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;
}

Testare l'ACE per verificare che QuickView funzioni. Se il server Web locale è stato arrestato in precedenza, riavviarlo eseguendo quanto segue nella console:

gulp serve --nobrowser

Passare al workbench ospitato in SharePoint per visualizzare l'ACE Campus Shuttle:

Screenshot dell'ACE di cui è stato eseguito il rendering in modalità di modifica.

Si noti il pulsante Prenota un viaggio su CardView. Testarlo selezionando il collegamento Anteprima nella sezione in alto a destra del riquadro di spostamento superiore. Questa pagina passerà dalla modalità di modifica alla modalità di visualizzazione in cui è possibile selezionare il pulsante:

Screenshot dell'ace di cui è stato eseguito il rendering in modalità di anteprima o visualizzazione.

A questo punto è possibile implementare la funzionalità di StartTrip QuickView.

Aggiungere funzionalità a StartTrip QuickView

A questo punto si aggiungeranno tre QuickView che verranno usati da StartTrip QuickView. Uno gestisce l'impostazione della posizione di origine del viaggio, un altro gestisce la selezione o l'impostazione della destinazione per il viaggio e l'ultimo funge da avviso di conferma quando si salva il viaggio.

  • Aggiungere un nuovo file SetOriginCard.json alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView/template con il codice seguente:

    {
      "$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
          }
        }
      ]
    }
    

    Si noti che la singola azione in questa scheda adattiva è impostata sul tipo VivaAction.GetLocation. Verrà richiesto all'utente di selezionare una posizione dal dispositivo e restituire le coordinate.

  • Implementare SetOrigin QuickView aggiungendo un nuovo file SetOrigin.ts alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView con il codice seguente:

    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();
        }
      }
    }
    

    Si noti che questo codice, all'interno del onAction() gestore eventi, ottiene la posizione selezionata quando VivaAction.GetLocation viene inviato dalla scheda adattiva. Imposta la posizione selezionata nel viaggio e aggiorna l'oggetto trip nello stato dell'ACE. L'ultima chiamata a this.quickViewNavigator.pop() rimuove questo controllo QuickView dallo stack QuickView, che attiva un nuovo rendering del controllo QuickView successivo nello stack.

Implementare ora un controllo QuickView simile per l'impostazione del percorso di destinazione:

  • Aggiungere un nuovo file SetDestinationCard.json alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView/template con il codice seguente:

    {
      "$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"
        }
      ]
    }
    

    Questa scheda adattiva è simile a quella usata per la posizione di origine nel modo in cui consente all'utente di selezionare una posizione sulla mappa o di selezionarla da un elenco di posizioni predefinite. Queste posizioni predefinite si trovano nel file ./src/adaptiveCardExtensions/campusShuttle/assets/campus_locations.json .

    La scheda adattiva contiene anche un altro pulsante di azione di invio. A differenza dell'origine impostata QuickView, questo pulsante verrà usato per chiudere il controllo QuickView di destinazione impostato perché l'utente dispone di due opzioni per la selezione di una destinazione di viaggio.

  • Implementare SetDestination QuickView aggiungendo un nuovo file SetDestination.ts alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView con il codice seguente:

    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();
        }
      }
    
    }
    

L'ultimo passaggio consiste nell'aggiungere un controllo QuickView di conferma del salvataggio al progetto:

  • Aggiungere un nuovo file SaveTripCard.json alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView/template con il codice seguente:

    {
      "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"
      }]
    }
    
  • Implementare SaveTrip QuickView aggiungendo un nuovo file SaveTrip.ts alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView con il codice seguente:

    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();
        }
      }
    }
    

Per usare questi tre nuovi QuickView, è necessario registrarli:

  1. Aprire il file ./src/adaptiveCardExtensions/campusShuttle/quickView/index.ts ed esportare i nuovi QuickView:

    export * from './StartTrip';
    export * from './SetOrigin';      // << add
    export * from './SetDestination'; // << add
    export * from './SaveTrip';       // << add
    
  2. Aprire il file ./src/adaptiveCardExtensions/campusShuttle/CampusShuttleAdaptiveCardExtension.ts .

    1. Aggiornare l'istruzione esistente import aggiunta per importare Il controllo QuickView StartTrip per fare riferimento ai tre nuovi QuickView:

      import {
        StartTrip,
        SetOrigin,
        SetDestination,
        SaveTrip
      } from './quickView';
      
    2. Individuare le costanti che dichiarano gli ID di CardView e QuickView e aggiungere gli ID seguenti per i nuovi QuickView:

      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';
      
    3. All'interno del onInit() metodo nella CampusShuttleAdaptiveCardExtension classe aggiungere il codice seguente dopo la chiamata esistente all'istruzione this.quickViewNavigator.register() che ha registrato StartTrip QuickView:

      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());
      

L'ultimo passaggio consiste nel collegare i controlli QuickView all'oggetto QuickView StartTrip esistente.

  1. Individuare e aprire il file ./src/adaptiveCardExtensions/campusShuttle/quickView/StartTrip.ts .

  2. Individuare l'istruzione esistente import che fa riferimento alle interfacce di proprietà e stato nel CampusShuttleCopilotAdaptiveCardExtension modulo. Aggiornarlo per importare le tre costanti per i tre nuovi QuickView:

    import {
      ICampusShuttleCopilotAdaptiveCardExtensionProps,
      ICampusShuttleCopilotAdaptiveCardExtensionState,
      QUICK_VIEW_SET_ORIGIN_REGISTRY_ID,
      QUICK_VIEW_SET_DESTINATION_REGISTRY_ID,
      QUICK_VIEW_SAVE_TRIP_REGISTRY_ID
    } from '../CampusShuttleAdaptiveCardExtension';
    
  3. Implementare SetOrigin QuickView sostituendo il commento // TODO QuickView originLocation nel onAction() metodo con quanto segue:

    this.quickViewNavigator.push(QUICK_VIEW_SET_ORIGIN_REGISTRY_ID);
    
  4. Implementare SetDestination QuickView sostituendo il commento // TODO QuickView destinationLocation nel onAction() metodo con quanto segue:

    this.quickViewNavigator.push(QUICK_VIEW_SET_DESTINATION_REGISTRY_ID);
    
  5. Implementare SaveTrip QuickView sostituendo il commento // TODO QuickView save nel onAction() metodo con quanto segue:

    this.quickViewNavigator.push(QUICK_VIEW_SAVE_TRIP_REGISTRY_ID);
    

Si noti che ognuna di queste chiamate esegue il push di un controllo QuickView nello strumento di navigazione. In questo modo viene attivato un nuovo rendering di QuickView usando il nuovo elemento nello stack. Richiamo che in precedenza, si stavano spuntando QuickView dallo stack.

L'ultimo passaggio consiste nell'aggiornare la visualizzazione CardView quando è stato prenotato un viaggio.

  1. Individuare e aprire il file ./src/adaptiveCardExtensions/campusShuttle/cardView/CardView.ts .

  2. Sostituire l'istruzione esistente import , import { STATUS_AVAILABLE } from '../sp.service';, con il codice seguente:

    import {
      ILocation,
      STATUS_AVAILABLE,
      STATUS_ENROUTE,
      STATUS_HIRED
    } from '../sp.service';
    
  3. Aggiornare l'istruzione switch nel cardButtons() metodo al codice seguente.

    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;
    }
    

    Queste modifiche visualizzeranno in modo condizionale pulsanti e testo diversi a seconda dello stato del driver dello shuttle corrente. Si noti che ora si usa l'azione VivaAction.ShowLocation di CardView per visualizzare le posizioni di origine e di destinazione specificate.

  4. Aggiornare infine l'istruzione return nel data() metodo al codice seguente.

    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
    };
    

    Si noti che questo modificherà il messaggio condizionale in base allo stato del viaggio del conducente dello shuttle.

Esperienza di creazione del viaggio di test

A questo punto è possibile testare l'esperienza di creazione completa del viaggio nel browser.

Se il server Web locale è stato arrestato in precedenza, riavviarlo eseguendo quanto segue nella console:

gulp serve --nobrowser

Passare al workbench ospitato in SharePoint per visualizzare l'ACE di Campus Shuttle.

Gli ACL visualizzeranno un solo pulsante in CardView quando la dimensione della scheda è impostata su Media. Mentre la pagina è in modalità di modifica, aprire il riquadro delle proprietà e impostare la dimensione della scheda su Grande in modo che entrambi i pulsanti vengano visualizzati in CardView.

Selezionare quindi il pulsante Anteprima in alto a destra della barra degli strumenti.

Per iniziare, selezionare il pulsante Prenota un viaggio nel controllo CardView iniziale. Viene visualizzato il controllo QuickView Avvia un viaggio testato in precedenza.

Selezionare il pulsante (1) Selezionare l'origine del viaggio dalla mappa per caricare SetOrigin QuickView. Selezionare ora il pulsante Seleziona posizione sulla mappa . Se non hai concesso l'accesso al browser alla tua posizione, ti verrà richiesto di farlo. È necessario approvare questa richiesta affinché l'azione VivaAction.GetLocation funzioni:

Screenshot della richiesta del browser per concedere l'accesso alla posizione.

Dopo aver concesso al browser l'accesso alla posizione, verrà visualizzata una finestra di dialogo con una mappa. Centrare la mappa sulla posizione per il luogo di ritiro per il viaggio, selezionare il ritiro e selezionare il pulsante Condividi posizione .

Screenshot che seleziona la posizione di origine per il ritiro del viaggio.

Selezionare il pulsante (2) Selezionare/impostare la destinazione del viaggio per caricare SetDestination QuickView.Select the (2) Select/set trip destination button to load the SetDestination QuickView. Questa volta selezionare una delle posizioni note nella casella a discesa e selezionare il pulsante Salva percorso di destinazione .

Screenshot che seleziona il percorso di destinazione per il viaggio.

Infine, selezionare lo stato del viaggio per il ritiro e selezionare il pulsante Salva viaggio .

Screenshot che mostra il controllo QuickView di conferma del salvataggio.

Dopo aver salvato il viaggio, si noti che CardView visualizza ora pulsanti e testo diversi in base al contesto corrente.

Screenshot di CardView quando l'autista è in viaggio verso un ritiro di viaggio.

Infine, passare all'elenco che contiene i dati del viaggio per vedere come vengono archiviati i dati per il test trip:

Screenshot del viaggio nell'elenco di SharePoint.

Il Campus Shuttle ACE è in buona forma per la creazione del viaggio. Gli ultimi due passaggi riguardano l'implementazione degli scenari in cui il conducente è in viaggio per prendere un passeggero e guidare il passeggero verso la destinazione.

Aggiungere funzionalità durante il viaggio verso il ritiro dei passeggeri

A questo punto si implementerà lo scenario in cui il conducente è in viaggio per prendere un passeggero.

  • Aggiungere un nuovo file UpdateTripCard.json alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView/template con il codice seguente:

    {
      "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"
        }
      ]
    }
    
  • Implementare UpdateTrip QuickView aggiungendo un nuovo file UpdateTrip.ts alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView con il codice seguente:

    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;
        }
      }
    
    }
    

Il nostro progetto richiede un passaggio di conferma se il conducente vuole eliminare un viaggio, annullandolo o consegnando un passeggero. Per implementare questa operazione, si userà un'unica visualizzazione rapida di conferma che gestirà in modo dinamico entrambi i casi.

  • Aggiungere un nuovo file ConfirmationCard.json alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView/template con il codice seguente:

    {
      "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"
        }
      ]
    }
    
  • Implementare il controllo QuickView di conferma aggiungendo un nuovo file ConfirmationQuickView.ts alla cartella ./src/adaptiveCardExtensions/campusShuttle/quickView con il codice seguente:

    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();
        }
      }
    }
    

Per usare questi tre nuovi QuickView, è necessario registrarli:

  1. Aprire il file ./src/adaptiveCardExtensions/campusShuttle/quickView/index.ts ed esportare i nuovi QuickView:

    // .. existing export statements
    export * from './UpdateTrip';
    export * from './ConfirmationQuickView';
    
  2. Aprire il file ./src/adaptiveCardExtensions/campusShuttle/CampusShuttleAdaptiveCardExtension.ts .

    1. Aggiornare l'oggetto esistente import per importare gli oggetti QuickView per fare riferimento ai nuovi controlli QuickView:

      import {
        StartTrip,
        SetOrigin,
        SetDestination,
        SaveTrip,
        UpdateTrip,            // << add
        ConfirmationQuickView  // << add
      } from './quickView';
      
    2. Individuare le costanti che dichiarano gli ID di CardView e QuickView e aggiungere gli ID seguenti per i nuovi QuickView:

      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';
      

      Si noti che le prime due costanti non fanno riferimento al controllo QuickView di conferma? Questo perché verranno create due implementazioni dello stesso controllo QuickView.

    3. All'interno del onInit() metodo nella CampusShuttleAdaptiveCardExtension classe aggiungere il codice seguente dopo la chiamata esistente all'istruzione this.quickViewNavigator.register() che ha registrato StartTrip QuickView:

      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());
      

The last step is to wire up the QuickViews to the existing CardView and QuickViews.

  1. Individuare e aprire il file ./src/adaptiveCardExtensions/campusShuttle/cardView/CardView.ts .

    1. Individuare l'istruzione esistente import che fa riferimento alle interfacce di proprietà e stato nel CampusShuttleCopilotAdaptiveCardExtension modulo. Aggiornarlo per importare le tre costanti per l'aggiornamento e completare i nuovi 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';
      
    2. Nel metodo della cardButton() funzione di accesso aggiornare l'istruzione switch per aggiungere altri pulsanti:

      1. Aggiungere il pulsante seguente all'istruzione case STATUS_ENROUTEreturn :

        {
          title: 'Update Trip',
          action: {
            type: 'QuickView',
            parameters: { view: QUICK_VIEW_UPDATE_TRIP_REGISTRY_ID }
          }
        }
        
      2. Aggiungere il pulsante seguente all'istruzione case STATUS_HIREDreturn :

        {
          title: 'Complete Trip',
          action: {
            type: 'QuickView',
            parameters: { view: QUICK_VIEW_COMPLETE_TRIP_REGISTRY_ID }
          }
        }
        
  2. Individuare e aprire il file ./src/adaptiveCardExtensions/campusShuttle/quickView/UpdateTrip.ts .

    1. Individuare l'istruzione esistente import che fa riferimento alle interfacce di proprietà e stato nel CampusShuttleCopilotAdaptiveCardExtension modulo. Aggiornarlo per importare le tre costanti per l'aggiornamento e completare i nuovi QuickView:

      import {
        ICampusShuttleAdaptiveCardExtensionProps,
        ICampusShuttleAdaptiveCardExtensionState,
        QUICK_VIEW_CANCEL_TRIP_REGISTRY_ID    // << add
      } from '../CampusShuttleAdaptiveCardExtension';
      
  3. Implementare SetOrigin QuickView sostituendo il commento // TODO QuickView cancelTrip nel onAction() metodo con quanto segue:

    this.quickViewNavigator.push(QUICK_VIEW_CANCEL_TRIP_REGISTRY_ID);
    

Esperienza di gestione dei test trip

A questo punto è possibile testare l'esperienza di gestione dei viaggi nel browser.

Se il server Web locale è stato arrestato in precedenza, riavviarlo eseguendo quanto segue nella console:

gulp serve --nobrowser

Passare al workbench ospitato in SharePoint per visualizzare l'ACE Campus Shuttle e selezionare il pulsante Anteprima in alto a destra della barra degli strumenti.

Si noti che CardView contiene ora un pulsante Update Trip .

Screenshot dell'oggetto CardView aggiornato.

Selezionare il pulsante Update Trip (Aggiorna viaggio ) e notare che sono disponibili due opzioni per annullare o ritirare un passeggero.

Screenshot di UpdateTrip QuickView.

Se si seleziona il pulsante Annulla viaggio corrente , lo stato ace verrà reimpostato ed eliminato il record del driver dall'elenco di SharePoint. Se si seleziona il pulsante Pick-Passenger , il viaggio verrà aggiornato, sia nello stato ACE che nella voce di elenco di SharePoint, per modificare lo stato del viaggio da in viaggio a noleggio.

Selezionare il pulsante Pickup Passenger (Pick Passenger ). Si noti che il contesto e i pulsanti di CardView cambiano per indicare la modifica allo stato del viaggio:

Screenshot di CardView quando il driver porta il passeggero a destinazione.

Infine, selezionare il pulsante Completa viaggio per visualizzare la visualizzazione rapida di conferma, quindi selezionare il pulsante Completa viaggio per confermare. Questo completerà il viaggio.

Screenshot del controllo QuickView di conferma.

In questo esercizio è stata creata un'ace SPFx con l'opzione Scheda di testo primaria che usa le funzionalità di posizione geografica in Viva Connections.

Verifica delle conoscenze

1.

In che modo gli sviluppatori possono rendere dinamici CardView e QuickView con dati contestuali?

2.

Quando si usa l'azione VivaConnections.SelectMedia, in che modo gli sviluppatori salvano le immagini selezionate in una raccolta documenti di SharePoint?

3.

Per impostare la posizione nell'azione VivaLocation.ShowLocation, gli sviluppatori possono fornire le coordinate GPS come latitudine e longitudine o l'indirizzo della posizione.