Este artículo es para explicar cómo construir una aplicación en tiempo real muy rápidamente usando AWS Amplify con Angular. Una de las integraciones realizadas dentro del servicio de desarrollo de software a medida y en nuestros equipos de desarrollo dedicados

También te puede interesar: «Página de pago de Stripe usando elementos de Stripe»

¿Qué es AWS Amplify?

De su página web:

AWS Amplify es un conjunto de herramientas y servicios que permite a los desarrolladores web móviles y de front-end crear aplicaciones de pila completa seguras y escalables, impulsadas por AWS.

Requisitos previos:

  • Node.js versión 10 o posterior
  • Cuenta de AWS
  • Angular CLI versión 10 o posterior
  • Comprensión básica de los conceptos de Angular

Crear el esqueleto de la aplicación de chat usando Angular CLI

npx ng new amplify-chat-angular

Creación del proyecto

Para este tutorial, utilizaremos AWS Amplify para impulsar nuestra API, la mensajería en tiempo real y la autenticación en nuestra aplicación Angular.

npm install --save aws-amplify

Luego ejecuta lo siguiente, para inicializar nuestra aplicación Angular como un proyecto Amplify.

amplify init

Se le pedirá que responda a algunas preguntas sobre su proyecto.

Enter a name for the project (amplifychatangular)
# For this tutorial, we'll only use the dev environment
Enter a name for the environment (dev)
# Here, just choose the editor you want to associate with Amplify
Choose your default editor
# Since we're building a Angular app, choose JavaScript and React
Choose the type of app that you're building (javascript)
What JavaScript framework are you using (angular)
# Choose the default options for these
Source directory path (src)
Distribution directory path (build)
Build command (npm run build)
Start command (npm run start)
# Remember the profile you created when you configured AWS Amplify?
# Let's choose that profile in this step
Do you want to use an AWS profile

Después de responder a todas estas preguntas, Amplify debería haber autogenerado un archivo aws-export.js que luego se utiliza para guardar toda la configuración de Amplify.

Ahora sólo queda configurar nuestra aplicación Angular para que utilice AWS Amplify.

Abra src/main.ts y añada las siguientes líneas después de la última declaración de importación.

import Amplify from '@aws-amplify/core';
import awsExports from './aws-exports';


Amplify.configure(awsExports);

Y ya está. Ha configurado con éxito una aplicación Angular para utilizar AWS Amplify.

Configuración de la API y el modelo GraphQL

El siguiente paso sería añadir la API y nuestro modelo. Para este tutorial, vamos a utilizar una API GraphQL así que ejecuta lo siguiente para añadir una API GraphQL de AppSync a nuestra aplicación.

amplify add api

Cuando se le pida, elija las opciones por defecto y la CLI debería abrir un esquema GraphQL que se vería así.

Archivo: amplify/backend/api/amplifychatangular/schema.graphql

type Todo @model {
  id: ID!
  name: String!
  description: String
}

Dado que estamos construyendo una aplicación de chat, un modelo Todo no funciona realmente para nosotros. Así que vamos a cambiar eso.

type Message
  @model
  @key(name: "byChannelID", fields: ["channelID", "createdAt"], queryField: "messagesByChannelID") {
  id: ID!
  channelID: ID!
  author: String!
  body: String!
  createdAt: AWSDateTime
  updatedAt: AWSDateTime
}

Aquí, estamos creando un modelo de Mensaje con los campos id, author (que es el nombre del autor), body, createdAt, y updatedAt.

Explicación:

@key(nombre: «byChannelID», fields: [«channelID», «createdAt»], queryField: «messagesByChannelID»




AWSDateTime



ID
autor
cuerpo
Creamos un nuevo índice para la tabla Messages. Hemos añadido @key que es una directiva GraphQL de AWS Amplify, como @model. Esto básicamente le dice a AppSync que cree una clave secundaria con el nombre de byChannelID. La matriz de campos comprende nuestra nueva clave. El primer campo será siempre la clave hash y el segundo, nuestra clave de ordenación. Por último, el parámetro queryField indica a AppSync que cree una nueva operación de consulta utilizando esta clave recién creada con el valor de queryField como nombre.
AWSDateTime es un tipo escalar proporcionado por AWS AppSync. Básicamente es una cadena con la forma YYYY-MM-DDThh:mm:ss.sssZ. Puede leer más sobre los tipos escalares de AppSync aquí. Esto será establecido automáticamente por AppSync en las mutaciones.
Id. único del mensaje
Nombre del autor
Contenido del mensaje

Guarde, salga y ejecute el siguiente comando para aprovisionar la API en la nube. Una vez más, elija las opciones predeterminadas para los avisos.

amplify push

Esto puede llevar un rato, así que coge una taza de café.

Una vez que esto termine, ¡felicidades! Su API ya está en funcionamiento. Ahora puedes empezar a hacer consultas GraphQL y mutaciones en ella. Es tan fácil que es como hacer trampa, ¿verdad?

Cuando ejecutó amplify push, vio que ocurrían un montón de cosas. Estos registros son comandos de AWS CloudFormation que se ejecutan para aprovisionar la aplicación en AWS, incluida la configuración de AppSync, DynamoDB, la asignación de roles de IAM y algunas otras cosas, cosas que normalmente no querrías tocar como desarrollador móvil o de front-end. La herramienta Amplify CLI las abstrae en un simple comando.

Generador de mutación, consulta y resolución de GraphQL

Amplify debería haber generado automáticamente angulares específicos, Mutación y Consulta automáticamente relevantes para el modelo que hemos creado.

Revisa src/app/API.service.ts para la referencia, usando el servicio API, podremos hacer, createMessage, updateMessage, listMessages, deleteMessages y etc.

También genera suscripciones a graphql en tiempo real, para lo cual no tenemos que hacer ninguna conexión de socket web explícitamente, todo será gestionado por Amplify.

Configuración de la UI

Antes de llegar a la parte buena, configuraremos nuestra interfaz de usuario: una lista de mensajes y una barra de chat– ¡nada demasiado elegante!

Para ello, abra src/app.component.html y añada el siguiente código.

<div id="root">
  <div class="container">
    <div class="messages">
      <div class="messages-scroller">
        <ng-container *ngFor="let message of messages">
          <div [ngClass]="message.author === username ? 'message me' : 'message'">
            {{message.body}}
          </div>
        </ng-container>
      </div>

    </div>
    <div class="chat-bar">
      <div class="form">
        <input #messageInput type="text" name="messageBody" placeholder="Type your message here" value=""
          (keyup.enter)="send($event, messageInput)" />
      </div>
    </div>
  </div>
</div>

A continuación, abra style.scss y sustituya el contenido por el siguiente código para que nuestra vista tenga un aspecto agradable.

/* You can add global styles to this file, and also import other style files */
* {
  box-sizing: border-box;
  font-family: 'Roboto', sans-serif;
}

html, body {
  height: 100%;
  margin: 0;
}

#root {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #f8f8f8;
  height: 100%;
}

.container {
  display: flex;
  flex-direction: column;
  width: 540px;
  height: 680px;
  background: white;
  border-radius: 16px;
  box-shadow: 0 2px 16px rgba(0, 0, 0, 0.0);
}

.messages {
  flex: 1;
  position: relative;
}

.messages-scroller {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: flex;
  flex-direction: column;
  padding: 16px;
  overflow-y: scroll;
}

.message {
  align-self: flex-start;
  margin-top: 4px;
  padding: 8px 12px;
  max-width: 240px;
  background: #f1f0f0;
  border-radius: 16px;
  font-size: 14px;
}

.message.me {
  align-self: flex-end;
  background: #2196F3;
  color: white;
  width: fit-content;
//   margin: 10px;
}

.chat-bar {
  height: 64px;
  border-top: 1px solid #ddd;
}

.chat-bar .form {
  height: 100%;
  padding: 16px;
}

.chat-bar .form input {
  width: 100%;
  height: 32px;
  padding: 8px 16px;
  border: 1px solid #ddd;
  border-radius: 16px;
  outline: none;
}

.chat-bar .form input:focus {
  border: 1px solid #2196F3;
}

/* width */
::-webkit-scrollbar {
  width: 10px;
}

/* Track */
::-webkit-scrollbar-track {
  background: #f1f1f1; 
}
 
/* Handle */
::-webkit-scrollbar-thumb {
  background: #888; 
}

/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
  background: #555; 
}

No hace mucho por ahora, así que vamos a cargar los mensajes que creamos en el artículo anterior y a conectar los manejadores de eventos.

Carga / Envío de mensajes en tiempo real

Querremos cargar los mensajes cuando se cargue nuestro componente de la aplicación, y para ello utilizaremos APIService, y la biblioteca Amplify API.

Abre src/app.component.ts e importa el APIService y el Router e inyéctalos en el constructor.

  constructor(
    private api: APIService,
    private router: Router
  ) { }

Ahora necesitamos crear manejadores de eventos

listMessages => para cargar los mensajes enviados / recibidos anteriormente

enviar => Para enviar el mensaje

onCreateMessage => Escuchar el evento de adición de mensajes en tiempo real

  1. listMessages: Aquí estamos recuperando los mensajes por el ID del canal usando MessagesByChannelId(graphql query), el usuario puede usar el ID dinámico del canal
  listMessages(): void {
    this.api.MessagesByChannelId('1').then((val) => {
      console.log(val);
      this.messages = val.items;
    });
  }

2. enviar: Usaremos este método para enviar el mensaje escrito por el usuario a un canal específico usando CreateMessage graphql Mutation.

  send(event, inputElement: HTMLInputElement): void {
    event.preventDefault();
    event.stopPropagation();
    const input = {
      channelID: '1',
      author: this.username.trim(),
      body: inputElement.value.trim()
    };
    this.api.CreateMessage(input).then((val) => {
      console.log('Send Message Success =>', val);
      inputElement.value = '';
    });
  }

3. onCreateMessage: Utilizaremos la suscripción graphql para escuchar en tiempo real el evento de creación de mensajes. Cada vez que alguien añada un mensaje al canal «1», se activará este evento.

  onCreateMessage(): void {
    this.api.OnCreateMessageListener.subscribe(
      {
        next: (val: any) => {
          console.log(val);
          this.messages.push(val.value.data.onCreateMessage);
        }
      }
    );
  }

El código completo del archivo app.component.ts se encuentra aquí.

El código completo de la aplicación se puede encontrar aquí

Demostración de trabajo

Tecnología Unimedia

En Unimedia Technology contamos con un equipo de desarrolladores de Angular que pueden desarrollar sus cuadros de mando y aplicaciones web más exigentes utilizando las últimas tecnologías de AWS.