Ejercicio: Creación de una ACE de tarjeta de imagen SPFx que muestra el carrusel de imagen

Completado

En este ejercicio, creará una extensión de tarjeta adaptable (ACE) SharePoint Framework (SPFx) con la plantilla tarjeta de imagen que muestra las imágenes tomadas por una de las cámaras del rover de Marte seleccionado.

Requisitos previos

El desarrollo de ACE para Viva Connections requiere un inquilino de Microsoft 365, SharePoint Online y Viva Connections configurar en el inquilino. Use los siguientes recursos para preparar el inquilino:

También necesita las herramientas de desarrollo necesarias instaladas en la estación de trabajo:

Importante

En la mayoría de los casos, instalar la última versión de las siguientes herramientas es la mejor opción. Las versiones enumeradas aquí fueron usadas la última vez que se publicó y se probó este módulo.

Creación del proyecto SPFx

Abra un símbolo del sistema y muévase a una carpeta donde quiera crear el proyecto SPFx. A continuación, ejecute el generador de Yeoman de SharePoint mediante el comando siguiente:

yo @microsoft/sharepoint

Use lo siguiente para completar el símbolo del sistema que se muestra:

  • ¿Cuál es el nombre de la solución?: AceImageViewer
  • ¿Qué tipo de componente del lado cliente se va a crear?: Extensión de tarjeta adaptable
  • ¿Qué plantilla desea usar?: Plantilla de tarjeta de imagen
  • ¿Cuál es el nombre de la extensión de tarjeta adaptable?: AceImageViewer

Después de aprovisionar las carpetas necesarias para el proyecto, el generador instalará todos los paquetes de dependencias ejecutando npm install automáticamente. Cuando NPM complete la descarga de todas las dependencias, abra el proyecto en Visual Studio Code.

Adición de propiedades públicas al componente ACE

El componente ACE que creará en este ejercicio recuperará y mostrará imágenes tomadas por un rover de Marte mediante uno de los puntos de conexión openAPI de la NASA.

Para llamar a la API, tendremos que establecer tres valores:

  • Clave de API
  • el rover de Marte para recuperar fotos
  • el sol de Marte, un día solar en Marte, para recuperar las imágenes de

Todas ellas serán propiedades públicas y configurables para en el componente ACE.

Nota:

Las API abiertas de la NASA admiten el uso de una clave de API de demostración o la creación de una clave de API gratuita. En este ejercicio se supone que usa la clave de demostración.

La clave de demostración tiene límites de velocidad, como el número máximo de solicitudes por dirección IP en una hora y en un día. Si supera los límites de clave de la API de demostración, puede crear una clave vinculada a su dirección de correo electrónico. Para obtener más información, consulte el sitio open API de la NASA.

Para empezar, agregue las propiedades al componente ACE.

  1. Busque la clase ACE en el archivo ./src/adaptiveCardExtensions/aceImageViewer/AceImageViewerAdaptiveCardExtension.ts y ábrala en VS Code.

  2. Busque la IAceImageViewerAdaptiveCardExtensionProps interfaz y actualícela para que contenga las siguientes propiedades:

    export interface IAceImageViewerAdaptiveCardExtensionProps {
      title: string;
      nasa_api_key: string;
      nasa_rover: string;
      mars_sol: number;
    }
    

A continuación, agregue las propiedades al panel de propiedades:

  1. Busque la clase en el archivo ./src/adaptiveCardExtensions/aceImageViewer/AceImageViewerPropertyPane.ts y ábrala en VS Code.

  2. Busque la import instrucción que importa el PropertyPaneTextField método . Agregue una lista al PropertyPaneDropdown método a esta import instrucción.

    import {
      IPropertyPaneConfiguration,
      PropertyPaneTextField,
      PropertyPaneDropdown    // << add
    } from '@microsoft/sp-property-pane';
    
  3. Actualice el método existente getPropertyPaneConfiguration() para aceptar un único parámetro que especifique el rover seleccionado:

    public getPropertyPaneConfiguration(selectedRover: string = 'curiosity'): IPropertyPaneConfiguration { .. }
    
  4. Agregue los campos siguientes a la matriz de groupFields en el objeto devuelto en el getPropertyPaneConfiguration() método :

    PropertyPaneTextField('nasa_api_key', {
      label: 'NASA API key'
    }),
    PropertyPaneDropdown('nasa_rover', {
      label: 'NASA Mars rover',
      options: [
        { index: 0, key: 'curiosity', text: 'Curiosity' },
        { index: 1, key: 'opportunity', text: 'Opportunity' },
        { index: 2, key: 'spirit', text: 'Spirit' }
      ],
      selectedKey: selectedRover
    }),
    PropertyPaneTextField('mars_sol', {
      label: 'Display photos from Mars day (Sol)'
    })
    

Vamos a agregar una pequeña mejora al panel de propiedades: el selector desplegable del rover de Marte debe establecerse de forma predeterminada en el rover seleccionado actualmente. La firma del getPropertyPaneConfiguration() método acepta un parámetro de entrada que se puede usar para establecerlo:

  1. Volver a la AceImageViewerAdaptiveCardExtension clase y busque el getPropertyPaneConfiguration() método . Reemplace la instrucción existente return por lo siguiente:

    return this._deferredPropertyPane?.getPropertyPaneConfiguration(this.properties.nasa_rover);
    

Por último, agregue establecer algunos valores predeterminados para las propiedades cuando se agregue el componente ACE a la página:

  1. Busque la clase ACE en el archivo ./src/adaptiveCardExtensions/aceImageViewer/AceImageViewerAdaptiveCardExtension.manifest.json y ábrala en VS Code.

  2. Agregue las propiedades siguientes a la lista existente de propiedades en el preconfiguredEntries.properties objeto :

    "nasa_api_key": "DEMO_KEY",
    "nasa_rover": "curiosity",
    "nasa_sol": 1000
    

Incorporación del asistente del servicio de API REST de la NASA

Vamos a agregar un servicio al proyecto para controlar toda la lectura de la OPENAPI REST de la NASA.

Cree un nuevo archivo ./src/adaptiveCardExtensions/aceImageViewer/nasa.service.ts en el proyecto y agréguele el código siguiente:

import { AdaptiveCardExtensionContext } from '@microsoft/sp-adaptive-card-extension-base';
import { HttpClient } from '@microsoft/sp-http';

export interface IMarsRoverCamera {
  id: number;
  name: string;
  rover_id: number;
  full_name: string;
}

export interface IMarsRoverVehicle {
  id: number;
  name: string;
  landing_date: Date;
  launch_date: Date;
  status: string;
}

export interface IMarsRoverPhoto {
  id: number;
  sol: number;
  camera: IMarsRoverCamera;
  rover: IMarsRoverVehicle;
  img_src: string;
  earth_date: Date;
}

export const fetchRoverPhotos = async (
  spContext: AdaptiveCardExtensionContext,
  apiKey: string,
  rover: string,
  mars_sol: number): Promise<IMarsRoverPhoto[]> => {
  const results: { photos: IMarsRoverPhoto[] } = await (
    await spContext.httpClient.get(
      `https://api.nasa.gov/mars-photos/api/v1/rovers/${rover}/photos?sol=${mars_sol}&page=1&api_key=${apiKey}`,
      HttpClient.configurations.v1
    )
  ).json();

  return Promise.resolve(results.photos);
}

Actualización del estado del componente ACE

Con las propiedades públicas y el servicio auxiliar creados, ahora vamos a actualizar el estado del componente que se usa para mostrar los datos en el componente.

  1. Busque la clase ACE en el archivo ./src/adaptiveCardExtensions/aceImageViewer/AceImageViewerAdaptiveCardExtension.ts y ábrala en VS Code.

  2. Agregue la siguiente instrucción import después de las instrucciones import existentes:

    import { isEmpty } from '@microsoft/sp-lodash-subset'
    import {
      fetchRoverPhotos,
      IMarsRoverPhoto
    } from './nasa.service';
    
  3. Busque la IAceImageViewerAdaptiveCardExtensionState interfaz y actualícela para que contenga las siguientes propiedades:

    export interface IAceImageViewerAdaptiveCardExtensionState {
      currentIndex: number;
      roverPhotos: IMarsRoverPhoto[];
    }
    
  4. A continuación, actualice el onInit() método de la AceImageViewerAdaptiveCardExtension clase para inicializar estas dos propiedades en valores vacíos:

    this.state = {
      currentIndex: 0,
      roverPhotos: []
    };
    
  5. onInit()En , agregue el código siguiente para recuperar imágenes de la API de la NASA si se establecen las propiedades mínimas. Esto debe colocarse inmediatamente antes de la existente. return Promise.resolve();

    if (!isEmpty(this.properties.nasa_api_key) &&
        !isEmpty(this.properties.nasa_rover) &&
        !isEmpty(this.properties.mars_sol)){
      this.setState({ roverPhotos: await fetchRoverPhotos(
        this.context,
        this.properties.nasa_api_key,
        this.properties.nasa_rover,
        this.properties.mars_sol)
      });
    }
    
  6. La última instrucción usa la await palabra clave , por lo que debe agregar la async palabra clave a la onInit() declaración del método:

    public async onInit(): Promise<void> {
    

Vamos a controlar un escenario más: si el usuario cambia el seleccionado nasa_rover o mars_sol en el panel de propiedades, queremos actualizar las imágenes en el estado . Para ello, agregue el código siguiente a la AceImageViewerAdaptiveCardExtension clase . Se ejecutará cuando cambie una propiedad en el panel de propiedades:

protected onPropertyPaneFieldChanged(propertyPath: string, oldValue: any, newValue: any): void {
  if (propertyPath === 'nasa_rover' && newValue !== oldValue) {
    (async () => {
      this.setState({ roverPhotos: await fetchRoverPhotos(
        this.context,
        this.properties.nasa_api_key,
        newValue,
        this.properties.mars_sol)
      });
    })
  }

  if (propertyPath === 'mars_sol' && newValue !== oldValue) {
    (async () => {
      this.setState({ roverPhotos: await fetchRoverPhotos(
        this.context,
        this.properties.nasa_api_key,
        this.properties.nasa_rover,
        newValue)
      });
    })
  }
}

Actualización de CardView

Ahora que el componente está configurado para obtener fotos de la API REST y almacenarlas en el estado , puede actualizar la representación para mostrar las fotos. Para empezar, actualice CardView.

  1. Busque y abra el archivo ./src/adaptiveCardExtensions/aceImageViewer/cardView/CardView.ts en VS Code.

  2. Agregue una referencia a la IActionArguments interfaz importada desde el @microsoft/sp-adaptive-card-extension-base paquete:

    import {
      BaseImageCardView,
      IImageCardParameters,
      IExternalLinkCardAction,
      IQuickViewCardAction,
      ICardButton,
      IActionArguments  // << add
    } from '@microsoft/sp-adaptive-card-extension-base';
    
  3. A continuación, actualice los botones que se muestran en CardView. CardView puede devolver cero, uno o dos botones. Quiere mostrar dos botones, los botones anterior y siguiente, cuando no esté al principio o al final de la colección de fotos. Para agregarlo, reemplace el contenido del método de descriptor de cardButtons() acceso por el código siguiente:

    const cardButtons: ICardButton[] = [];
    
    if (this.state.currentIndex !== 0) {
      cardButtons.push(<ICardButton>{
        title: '<',
        id: '-1',
        action: {
          type: 'Submit',
          parameters: {}
        }
      });
    }
    if (this.state.currentIndex !== (this.state.roverPhotos.length - 1)) {
      cardButtons.push(<ICardButton>{
        title: '>',
        id: '1',
        action: {
          type: 'Submit',
          parameters: {}
        }
      });
    }
    
    return (cardButtons.length === 0)
      ? undefined
      : (cardButtons.length === 1)
        ? [cardButtons[0]]
        : [cardButtons[0], cardButtons[1]];
    
  4. A continuación, reemplace el contenido del método de descriptor de data() acceso por el código siguiente. Esto devolverá una imagen predeterminada de Marte con algunas instrucciones si no se especifica el rover o mars sol. De lo contrario, mostrará la imagen actual:

    if (!this.properties.nasa_rover || !this.properties.mars_sol) {
      return {
        primaryText: `Select Mars rover and sol to display photos...`,
        imageUrl: 'https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/Tharsis_and_Valles_Marineris_-_Mars_Orbiter_Mission_%2830055660701%29.png/240px-Tharsis_and_Valles_Marineris_-_Mars_Orbiter_Mission_%2830055660701%29.png',
        imageAltText: `Select Mars rover and sol to display photos...`,
        title: this.properties.title
      }
    } else {
      const rover = `${this.properties.nasa_rover.substring(0, 1).toUpperCase()}${this.properties.nasa_rover.substring(1)}`;
      const roverImage = this.state.roverPhotos[this.state.currentIndex];
      if (roverImage) {
        return {
          primaryText: `Photos from the Mars rover ${rover} on sol ${this.properties.mars_sol}`,
          imageUrl: roverImage.img_src,
          imageAltText: `Image ${roverImage.id} taken on ${roverImage.earth_date} from ${rover}'s ${roverImage.camera.full_name} camera.`,
          title: this.properties.title
        };
      } else {
        return {
          primaryText: `Please refresh the page to reload the rover photos`,
          imageUrl: '',
          imageAltText: '',
          title: this.properties.title
        }
      }
    }
    
  5. A continuación, reemplace el contenido del método de descriptor de onCardSelection() acceso por el código siguiente. Esto abrirá nuestro QuickView, que actualizará en un momento, cuando se seleccione la tarjeta.

    return {
      type: 'QuickView',
      parameters: {
        view: QUICK_VIEW_REGISTRY_ID
      }
    };
    
  6. A continuación, implemente el onAction() método agregando el código siguiente a la CardView clase . Esto se ejecutará cada vez que se produzca una acción de envío en la implementación de CardView. Recuerdos en el cardButtons() método , establezca la id propiedad de los botones en un número positivo o negativo para navegar por la matriz de imágenes:

    public onAction(action: IActionArguments): void {
      if (action.type !== 'Submit') { return; }
    
      let currentIndex = this.state.currentIndex;
      this.setState({ currentIndex: currentIndex + Number(action.id) });
    }
    
  7. Por último, comente o quite la siguiente referencia al strings objeto:

    import * as strings from 'AceImageViewerAdaptiveCardExtensionStrings';
    

Actualización de QuickView

El último paso antes de probar el componente ACE es actualizar QuickView. En este escenario, quickview mostrará más detalles sobre la foto actual.

  1. Busque y abra el archivo ./src/adaptiveCardExtensions/aceImageViewer/quickView/QuickView.ts en VS Code.

  2. Agregue la siguiente import instrucción a las importaciones existentes:

    import { IMarsRoverPhoto } from '../nasa.service';
    
  3. Quite la interfaz existente IQuickViewData .

  4. Reemplace todas las referencias restantes a IQuickViewData en la QuickView clase por IMarsRoverPhoto.

  5. Reemplace el contenido del data() método de descriptor de acceso por lo siguiente:

    return this.state.roverPhotos[this.state.currentIndex];
    
  6. Por último, comente o quite la siguiente referencia al strings objeto:

    import * as strings from 'AceImageViewerAdaptiveCardExtensionStrings';
    

Ahora, actualice la plantilla tarjeta adaptable:

  1. Busque y abra el archivo ./src/adaptiveCardExtensions/aceImageViewer/quickView/template/QuickViewTemplate.json en VS Code.

  2. Reemplace el contenido de la plantilla por el código siguiente:

    {
      "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
      "version": "1.5",
      "type": "AdaptiveCard",
      "body": [
        {
          "type": "Image",
          "url": "${img_src}"
        },
        {
          "type": "TextBlock",
          "text": "${rover.name} rover image #${id}",
          "horizontalAlignment": "Center"
        },
        {
          "type": "TextBlock",
          "text": "Photo Details",
          "spacing": "Medium",
          "separator": true,
          "size": "Large",
          "weight": "Bolder"
        },
        {
          "type": "FactSet",
          "facts": [
            {
              "title": "Rover:",
              "value": "${rover.name}"
            },
            {
              "title": "Camera:",
              "value": "${camera.full_name}"
            },
            {
              "title": "Date taken:",
              "value": "${earth_date} (sol ${sol})"
            }
          ]
        }
      ]
    }
    

Prueba de la ACE dinámica

Vamos a probar la ACE para ver nuestro explorador de imágenes.

En la consola, ejecute la siguiente instrucción:

gulp serve --nobrowser

En un explorador, vaya al área de trabajo hospedada de SharePoint en el sitio donde desea probar la ACE. Por ejemplo, si la dirección URL del sitio es https://contoso.sharepoint.com/sites/MSLearningTeam, la dirección URL del área de trabajo hospedada es https://contoso.sharepoint.com/sites/MSLearningTeam/_layouts/15/workbench.aspx.

Seleccione el + icono y, a continuación, seleccione AceImageViewer en el cuadro de herramientas:

Captura de pantalla del cuadro de herramientas de SPFx.

Observe que la experiencia predeterminada del componente es usar la imagen de Marte. Eso se debe a que no tenemos un sol de Marte establecido:

Captura de pantalla de la representación predeterminada de ACE CardView.

Al igual que un elemento web SPFx, puede mantener el mouse sobre el componente ACE y seleccionar el icono de lápiz para abrir el panel de propiedades:

Captura de pantalla de la experiencia de edición de una ACE.

Establezca mars sol en 1000 y cierre el panel de propiedades seleccionando la X en la esquina superior derecha y, a continuación, seleccione el vínculo Vista previa en la esquina superior derecha de la navegación superior de la página para poner la página en modo de presentación.

Use los botones proporcionados en CardView para desplazarse por las imágenes. Se muestra una versión recortada de la imagen en cardview de la tarjeta de imagen.

Captura de pantalla de la imagen seleccionada en CardView.

Con el mouse, seleccione en cualquier lugar de la tarjeta, sin seleccionar ninguno de los botones. QuickView mostrará la foto sin recorte con más detalles sobre cuándo se tomó:

Captura de pantalla de la imagen seleccionada en QuickView.

En este ejercicio, ha creado una extensión de tarjeta adaptable (ACE) SharePoint Framework (SPFx) con la plantilla tarjeta de imagen que muestra imágenes tomadas por una de las cámaras del rover de Marte seleccionado.

Comprobar sus conocimientos

1.

¿Cómo pueden controlar los desarrolladores las acciones enviadas dentro de tarjetas adaptables?

2.

¿Cuál de las siguientes instrucciones sobre el cardButtons() método es incorrecta?

3.

El registro de cardview o QuickView con su navegador de vistas asociado solo es necesario cuando se desea encadenar vistas juntas.