En este tutorial descubrirá como crear una aplicación de punta a punta de React.js que funciona como un panel de instrumentos que muestra datos de ventas que se almacenan en una base de datos Cloudant. Vea cómo utilizar LoopBack 4 para exponer APIs de REST para conectarse a la base de datos de Cloudant de modo que el panel de instrumentos del frontend pueda llamar a las APIs.
Visión general
En este tutorial hay dos partes principales:
- Parte 1: Utilice LoopBack para crear las APIs que se conectan a Cloudant: Vea cómo se crea una aplicación de LoopBack
lb4-sales-analytics
que se conecta a una base de datos de Cloudant. - Parte 2: Cree la aplicación de React que hace llamadas a las APIs de REST que usted creó en la Parte 1: Descubra cómo se crea una aplicación de un panel de instrumentos,
lb4-sales-react-app
, con React.js.
Requisitos Previos
Para completar los pasos de este tutorial, es necesario:
- Instalar Node.js 8.9+ y LoopBack 4 CLI.
- Revisar el conjunto de interfaces de línea de comando LoopBack que le ayudarán a crear más fácilmente los artefactos LoopBack.
- Obtener el código para la parte 1 y la parte 2 para que pueda seguir los ejemplos de este tutorial.
Parte 1: Utilice LoopBack para crear las APIs que se conectan a Cloudant
En esta sección crearemos una aplicación de LoopBack que genera API que hablan con la base de datos de Cloudant.
Paso 1. Cree una aplicación de LoopBack 4
Genere una aplicación de LoopBack 4 llamada lb4-sales-analytics
ejecutando el comando generador de aplicaciones: lb4 app
.
$ lb4 app lb4-sales-analytics
? Project description: lb4-sales-analytics
? Project root directory: lb4-sales-analytics
? Application class name: Lb4SalesAnalyticsApplication
? Select features to enable in the project (Press <space> to select, <a> to toggle all, <i> to invert selectio
n)Enable tslint, Enable prettier, Enable mocha, Enable loopbackBuild, Enable vscode, Enable docker, Enable rep
ositories, Enable services
...
Application lb4-sales-analytics was created in lb4-sales-analytics.
Next steps:
$ cd lb4-sales-analytics
$ npm start
Consejo: Si usted va a usar todos los valores predeterminados, es posible acelerar el proceso de generación mediante la opción
--yes
; En este caso, quedaría así:lb4 app your-app-name --yes
.
Paso 2. Cree el modelo de ventas
El modelo ´Sales´ representa cada pedido de ventas, que tendrá las siguientes propiedades:
- id: el id del pedido de ventas
- description: la descripción del pedido de ventas
- date: la fecha en la que se hace el pedido de ventas
- country: el país desde el que se hace el pedido de ventas
- total: importe del pedido de ventas
Ejecute el comando lb4 model
para generar el modelo.
$ lb4 model
? Model class name: Sales
? Please select the model base class Entity (A persisted model with an ID)
? Allow additional (free-form) properties? No
Let's add a property to Sales
Enter an empty property name when done
? Enter the property name: id
? Property type: number
? Is id the ID property? Sí
? Is it required?: No
? Default value [leave blank for none]:
Let's add another property to Sales
Enter an empty property name when done
? Enter the property name: description
? Property type: string
? Is it required?: No
? Default value [leave blank for none]:
Let's add another property to Sales
Enter an empty property name when done
? Enter the property name: date
? Property type: date
? Is it required?: Yes
? Default value [leave blank for none]:
Let's add another property to Sales
Enter an empty property name when done
? Enter the property name: country
? Property type: string
? Is it required?: Yes
? Default value [leave blank for none]:
Let's add another property to Sales
Enter an empty property name when done
? Enter the property name: total
? Property type: number
? Is it required?: Yes
? Default value [leave blank for none]:
Let's add another property to Sales
Enter an empty property name when done
? Enter the property name:
create src/models/sales.model.ts
update src/models/index.ts
Model Sales was created in src/models/
Paso 3. Añada un origen de datos
Ahora, vamos a crear un origen de datos que se conecta a una base de datos de Cloudant. Este ejemplo utilizar la imagen Couchdb de Docker, para que usted pueda ejecutar la base de datos localmente. El repositorio de conectores de LoopBack Cloudant contiene scripts de utilidades que sirven para descargar y ejecutar la imagen del Docker. Vea las instrucciones. También, es posible utilizar el servicio de Cloudant de IBM Cloud.
Ejecute el comando generador de orígenes de datos lb4 datasource
para crear el origen de datos.
$ lb4 datasource
? Datasource name: cloudant
? Select the connector for cloudant: IBM Cloudant DB (supported by StrongLoop)
? Connection String url to override other settings (eg: https://username:password@host): http://admin:pass@localhost:8080/lb4-sales
? database:
? username:
? password: [hidden]
? Specify the model name to document mapping, defaults to `loopback__model__name`:
create src/datasources/cloudant.datasource.json
create src/datasources/cloudant.datasource.ts
...
Datasource cloudant was created in src/datasources/
Este origen de datos configura el conector LoopBack Cloudant. Si usted tiene el URL de la conexión, es posible ignorar el resto de los ajustes, como los de la base de datos, el nombre de usuario y la contraseña.
De forma predeterminada, las APIs de REST solo pueden devolver un máximo de 25 instancias. Para modificar eso, es posible añadir la propiedad globalLimit
al cloudant.datasource.json
de la siguiente manera:
{
"name": "cloudant",
"connector": "cloudant",
"url": "http://admin:pass@localhost:8080",
"database": "lb4-sales",
"username": "",
"password": "",
"modelIndex": "",
"globalLimit": 1000
}
Si tienes planes para desplegar la aplicación de LoopBack en IBM Cloud y para utilizar el servicio de Cloudant, vaya a la página Desplegar en documentos de IBM Cloud para vincular la aplicación al servicio, para que las credenciales del servicio de Cloudant no se expongan en la aplicación de LoopBack.
Paso 4. Cree un repositorio
El comando generador de repositorios lb4 repository
crea una clase Repository
que vincula el origen de datos y el modelo:
$ lb4 repository
? Please select the datasource CloudantDatasource
? Select the model(s) you want to generate a repository Sales
? Please select the repository base class DefaultCrudRepository (Legacy juggler bridge)
create src/repositories/sales.repository.ts
update src/repositories/index.ts
Repository SalesRepository was created in src/repositories/
Paso 5. Cree un controlador
Finalmente, cree el controlador que se encarga del ciclo de vida solicitud-respuesta de su API.
$ lb4 controller
? Controller class name: Sales
? What kind of controller would you like to generate? REST Controller with CRUD functions
? What is the name of the model to use with this CRUD repository? Ventas
? What is the name of your CRUD repository? SalesRepository
? What is the name of ID property? id
? What is the type of your ID? número
? What is the base HTTP path name of the CRUD operations? /sales
create src/controllers/sales.controller.ts
update src/controllers/index.ts
Controller Sales was created in src/controllers/
Además de las operaciones CRUD que se generaron, usted tiene que añadir dos puntos finales más:
GET /sales/analytics/{country}/{year}/{month}
: Obtiene el número de ventas por país para el rango de fechas AAAA/MMGET /sales/analytics/{country}/{year}
: Número de ventas por país de un año
En src/controllers/sales.controller.ts
, añada los siguientes dos métodos que corresponden a los puntos finales nuevos:
@get('/sales/analytics/{country}/{year}/{month}', {
responses: {
'200': {
description: 'Number of sales by country in a date YYYY/MM range.',
content: {'application/json': {schema: CountSchema}},
},
},
})
async analyticsMonthAndYear(
@param.path.string('country') country: string,
@param.path.number('year') year: number,
@param.path.number('month') month: number,
): Promise<number> {
const filter = {
where: {
country,
date: {
between: [
new Date(year, month - 1).toISOString(),
new Date(year, month).toISOString(),
] as [string, string],
},
},
};
const res = await this.salesRepository.find(filter);
return res.length;
}
@get('/sales/analytics/{country}/{year}', {
responses: {
'200': {
description: 'Number of sales by country for a year.',
content: {'application/json': {schema: CountSchema}},
},
},
})
async analyticsYear(
@param.path.string('country') country: string,
@param.path.number('year') year: number,
): Promise<number> {
const filter = {
where: {
country,
date: {
between: [
new Date(year, 0).toISOString(),
new Date(year + 1, 0).toISOString(),
] as [string, string],
},
},
};
const res = await this.salesRepository.find(filter);
return res.length;
}
Paso 6. Cambie el puerto al 3001
El puerto que se utiliza de forma predeterminada en la aplicación LoopBack es el 3000. Como la aplicación de React que usted va a crear utilizará el mismo puerto, es necesario modificar la aplicación LoopBack para que utilice el puerto 3001.
Vaya a index.js. En config
cambie el número de puerto del 3000 al 3001, de esta manera:
const config = {
rest: {
port: +(process.env.PORT || 3001),
host: process.env.HOST,
openApiSpec: {
// useful when used with OpenAPI-to-GraphQL to locate your application
setServersFromRequest: true,
},
},
};
Pruebe su API
Ahora, su aplicación está lista para ejecutarse. Utilice npm start
para lanzarla.
$ npm start
Server is running at http://[::1]:3001
Try http://[::1]:3001/ping
Abra un navegador y vaya al URL: http://localhost:3001
La especificación de OpenAPI para las APIs de REST está en http://localhost:3001/openapi.json. Pruebe sus APIs en API Explorer: http://localhost:3001/explorer.
Es posible probarlo yendo a GET /sales/count
o a cualquier punto final, y haciendo clic en el botón Try it out.
Opcional: Inicialice la base de datos
Para inicializar una base de datos, vamos a insertar algunos datos aleatorios cuando se inicia la aplicación. Podemos usar el soporte del ciclo de vida de LoopBack.
Ejecute el comando generador del observador el ciclo de vida: lb4 observer
.
$ lb4 observer
? Observer name: AddData
? Observer group: AddDataGroup
create src/observers/add-data.observer.ts
update src/observers/index.ts
Observer AddData was created in src/observers/
En AddDataObserver
, hay dos métodos generados: start()
y stop()
. Para añadir algunos datos durante el inicio de la aplicación, llame a Repository.create()
.
Primero, obtendremos el SalesRepository
que creamos anteriormente.
Añada el constructor de la siguiente manera:
constructor(
@repository('SalesRepository') private salesRepo: SalesRepository,
) {}
Asegúrese de que añade las siguientes importaciones:
//import the repository decorator
import {repository} from '@loopback/repository';
//import the Sales and SalesRepository in my LB app
import {SalesRepository} from '../repositories';
import {Sales} from '../models';
En el método start()
, cree una instancia de Sales
y añádala a la base de datos por medio del método Repository.create()
.
async start(): Promise<void> {
let count: number = (await this.salesRepo.count()).count;
if (count !== 0) return;
//create an instance of Sales to be inserted into the database
let salesData = new Sales({
description: 'this is a sample data',
date: '2019-01-01',
country: 'Canada',
total: 100,
});
this.salesRepo.create(salesData);
}
Lea esta publicación de blog para obtener más información acerca de la generación de instancias aleatorias de Sales
.
Nota: El código para generar varias instancias se puede encontrar en
src/observers/add-data.observer.ts
.
Ahora que ha visto cómo se crean las APIs que extraen datos de Cloudant por medio de LoopBack, veamos cómo se crea en el panel de instrumentos donde se puede ver esta información.
Parte 2. Cree el panel de instrumentos con React.js
En esta sección, le mostramos los pasos para crear con React un panel de instrumentos que llama a las APIs de REST creadas por la aplicación LoopBack que usted creó en la Parte 1 para obtener los datos. Si usted es principiante en React, le convendría seguir este tutorial que cubre la forma en que usamos esta tecnología.
Después de construir todo, la aplicación se parecerá a esto:
En este panel de instrumentos hay tres componentes:
- Una barra de herramientas en la parte superior de la página
- Una sección de visión general que contiene cuadrículas con algunos puntos de datos
- Una sección de un gráfico de ventas que muestra el número de ventas realizadas durante los últimos meses para varios países
Paso 1: Cree una aplicación de React.js
Ejecute este comando:
$ npx create-react-app lb4-sales-react-app
Paso 2: Cree el panel de instrumentos
En la carpeta src
, cree un archivo llamado Dashboard.js
. Vea el código en src/Dashboard.js
en nuestra aplicación previamente creada.
Como es posible ver en el método render()
, hay tres componentes principales:
- Una barra de herramientas con el texto «LoopBack Dashboard»
- Una sección de visión general con el componente
CenteredGrid
que crearemos - Una sección de ventas con el componente
SimpleLineChart
que crearemos
Paso 3: Cree CenteredGrid para la sección de visión general
Cree un archivo llamado CenteredGrid.js
y vea su código en src/CenteredGrid.js
, en nuestra aplicación previamente creada. Vamos a crear dos cuadrículas, una para el número total de ventas y otra para los ingresos totales por ventas. Se conectan a los dos puntos finales /sales/count
y /sales
que usted creó antes con LoopBack 4.
Como existen algunos valores que se usan de forma habitual en los tres componentes que estamos creando, cree un archivo llamado config.js
con el siguiente contenido:
const baseUrl = 'http://localhost:3001';
const availableCountries = ['US', 'Canada', 'Germany', 'France', 'Mexico'];
export {baseUrl, availableCountries};
En CenteredGrid.js
, inicialice el estado del componente en el constructor de la siguiente manera:
this.state = {
totalNumberOfSales: 0,
totalRevenueOfSales: 0,
};
Añada el método componentDidMount()
del ciclo de vida, para que se realice una llamada a las APIs de REST cuando se represente el componente, y luego actualice su estado con los datos:
Compruebe los métodos del ciclo de vida de React.
async componentDidMount() {
const [ totalNumberOfSales, totalRevenueOfSales ] = await Promise.all([
fetch(`${baseUrl}/sales/count`).then(res => res.json()).catch(err => err),
fetch(`${baseUrl}/sales`).then(res => res.json()).catch(err => err)
]);
this.setState({
totalNumberOfSales: totalNumberOfSales.count || 0,
totalRevenueOfSales: Array.isArray(totalRevenueOfSales) ?
totalRevenueOfSales.reduce((sum, curr) => sum + curr.total, 0) : 0,
});
}
Finalmente, modificaremos la función render()
de la siguiente manera:
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<Grid container spacing={24}>
<Grid item xs={6}>
<Paper className={classes.paper}>
<h3>Total Number Of Sales</h3>
{ this.state.totalNumberOfSales }
</Paper>
</Grid>
<Grid item xs={6}>
<Paper className={classes.paper}>
<h3>Total Revenue From Sales</h3>
${ this.state.totalRevenueOfSales }
</Paper>
</Grid>
</Grid>
</div>
);
}
Paso 4: Cree SimpleLineChart para la sección ´Sales´
En esta sección nos hacen falta dos valores para construir el gráfico:
- Eje-x:
dates
(año, mes y la etiqueta del gráfico) - Eje-y: el
graphData
de las ventas
Vamos a crear un archivo llamado SimpleLineChart.js
, y vamos a inicializar el estado del componente en el constructor con las dos variables:
Observe que el periodo temporal del gráfico está determinado por la variable CALC_PERIOD_IN_MONTHS
constructor() {
super();
this.state = {
graphData: [],
dates: []
};
const MONTHS_IN_TEXT = ['JAN', 'FEB', 'MAR','APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
const currentYear = new Date().getUTCFullYear();
const currentMonth = new Date().getUTCMonth();
for (let i = 0; i < CALC_PERIOD_IN_MONTHS; i++) {
const date = new Date(currentYear, currentMonth - 12 + i, 1);
this.state.dates[i] = {
label: MONTHS_IN_TEXT[date.getUTCMonth()],
year: date.getUTCFullYear(),
month: date.getUTCMonth(),
};
}
}
Eche un vistazo a la función componentDidMount()
para saber cómo se obtienen los datos de ventas por país.
Resumen
Este tutorial muestra el escenario de principio a fin para tener una aplicación frontend que habla con una base de datos por medio de una aplicación de LoopBack. En la Parte 1, creamos una aplicación de LoopBack que se conecta a una bases de datos de Cloudant para obtener los datos de las ventas. La aplicación de React que creamos en la Parte 2 para mostrar los datos en un panel de instrumentos utiliza las APIs de REST que se ¬¬exponen en esta aplicación de LoopBack.
Aviso
El contenido aquí presentado fue traducido de la página IBM Developer US. Puede revisar el contenido original en este link.