Pular para o conteúdo principal

Implementação de tabelas e gráficos

Antes de Começar

Antes de começar este tutorial certifique-se que sabe criar Formulários, Campos, Relações e Serviços Web Rest onde aprofundamos mais cada explicação, caso não o saiba visite as respetivas ligações:

É também aconselhável que, antes de começar este tutorial, se certifique que tem noções básicas em JavaScript, React.js e HTML.

Introdução

Neste tutorial iremos explicar como desenvolver uma aplicação simples que envolve a criação de formulários, relações entre os mesmos, serviços, tabelas e gráficos que apresentam os dados do serviço utilizando uma biblioteca denominada de React ChartJS 2 (que necessita também da dependência Chart.js), tudo isto criado em JavaScript, React.js e HTML.

Produto Final

Se seguir todos os passos descritos neste tutorial, a sua aplicação irá ficar semelhante à apresentada na seguinte imagem:

implementaçaotabelasgraficos1.png

Primeiro Passo

O primeiro passo será criar os formulários, as respectivas relações e popular com alguns dados, segue-se uma imagem referente à estrutura dos formulários e campos utilizados neste tutorial: implementaçaotabelasgraficos2.png

Nota: Não é necessário criar o campo de id porque o Netuno o cria automaticamente após a criação da tabela.

Vamos analisar o template da dashboard do Netuno. Para tal basta dirigir-se ao seguinte diretório:

/apps/minhaapp/server/templates/dashboard.html

Vamos agora analisar o código apresentado a seguir, este código será utilizado mais tarde como referência para se injetarem os componentes da Tabela e do Gráfico.

<div id="app-dashboard"></div>

Segundo Passo

Agora iremos criar os serviços que irão ser utilizados para popular os dados da tabela e do gráfico. Para criar os ficheiros dirija-se ao seguinte diretório e crie primeiro um ficheiro denominado de registos.js (o nome do ficheiro é este para efeitos de exemplo)

/apps/minhaapp/server/services/

Segue-se o código criado para tal efeito, em que são selecionados todos os trabalhadores e as respetivas horas de entrada e horas de saída e é efetuada uma soma das mesmas apresentando o total de horas por trabalhador.

// Para realizar uma query simples utilizamos _db.query() que é uma função Netuno
var registos = _db.query('SELECT DISTINCT trabalhador.nome, SUM(DATEDIFF(HOUR, registo.hora_entrada, registo.hora_saida)) AS total FROM registo INNER JOIN trabalhador ON registo.trabalhador_id = trabalhador.id GROUP BY trabalhador.nome ORDER BY total ASC');

// Inicializar a variável para que esta possa receber valores
var registosProcessados = _val.init();

// Iteração por todos os registos para receber cada trabalhador, a data e as horas respectivas
if (registos) {

for (var i = 0; i < registos.size(); i++){

var registo = registos.get(i);

var item = _val.init()
.set("trabalhador", registo.getString("nome"))
.set("trabalhadorHoras", registo.getInt("total"))

registosProcessados.push(item);
}
}

// Visualizar no ecrã os valores
_out.json(registosProcessados);

A seguir crie um ficheiro chamado calc-hours.js no directório:

/apps/minhaapp/server/services/

Este serviço incrementa horas na data atual para encontrar o resultado final.

var values = _val.init()

var date = new Date()
date.setHours(date.getHours() + _req.getInt('hours'))

values.set("date", _date_format.date().format(date))
values.set("time", _date_format.time().format(date))


_out.json(values)

Terceiro Passo

Antes de começar a desenvolver em React.js certifique-se que executou o comando npm install no diretório /apps/minhaapp/ui e que após a sua conclusão executou o comando npm run watch para compilar as suas alterações.

Para poder utilizar a biblioteca React Chartjs 2 execute também o comando npm install react-chartjs-2 chart.js --save

Criação das classes em React.js que permitirão imprimir no ecrã a tabela e o gráfico com os dados dos serviços. Para tal efeito iremos criar duas pastas:

  • Table
  • ChartBar

Estas devem ser criadas no seguinte diretório:

/apps/minhaapp/ui/src/components/

Quarto Passo

Iremos agora criar o componente responsável pela tabela no diretório Table, o ficheiro index.jsx da seguinte forma:

import React, { Component } from 'react';

import styles from './index.less';

export default class Table extends Component {

constructor(props) {
super(props);
this.state = {
tableData: {}
}
}

static getDerivedStateFromProps(nextProps, prevState){
if (nextProps.tableData) {
return {
tableData: nextProps.tableData
}
}
return null;
}

render() {

const tableFinalData = this.state.tableData.map((registo, i) =>
<tr key={i}>
<td>{registo.trabalhador}</td><td>{registo.trabalhadorHoras}</td>
</tr>
);

return (
<table className={ styles.table }>
<thead>
<tr>
<th>Trabalhador</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{tableFinalData}
</tbody>
</table>
)
}
}

Iremos agora criar um ficheiro de estilos para a tabela no diretório Table, o ficheiro index.less da seguinte forma:

.table {
width: 100%;
padding-top: 15px;
padding-left: 15px;
th, td {
padding: 5px;
border: 1px solid black;
text-align: center;
}
}

Quinto Passo

Iremos agora criar o componente responsável pelo gráfico no diretório ChartBar, o ficheiro index.jsx da seguinte forma:

import React, { Component } from 'react';
import { Bar } from 'react-chartjs-2';

export default class ChartBar extends Component {

constructor(props) {

super(props);
this.state = {
chartData: {}
}
}

static getDerivedStateFromProps(nextProps, prevState){

if (nextProps.chartData) {

// Receção e processamento dos dados
let colors = [
'rgb(255, 99, 132)',
'rgb(255, 159, 64)',
'rgb(255, 205, 86)',
'rgb(75, 192, 192)',
'rgb(54, 162, 235)',
'rgb(153, 102, 255)',
'rgb(201, 203, 207)'
]

let labels = [];
let values = [];
let chartDataValues = {
labels: [],
datasets: [
{
label: "Horas",
data: [],
backgroundColor: []
}
]
};

for (const i in nextProps.chartData) {
labels.push(nextProps.chartData[i].trabalhador);
values.push(nextProps.chartData[i].trabalhadorHoras);
chartDataValues.datasets[0].backgroundColor[i] = colors[i];
}

chartDataValues.labels = labels;
chartDataValues.datasets[0].data = values;

return {chartData: chartDataValues};
}
return null;
}

render() {
return (

<Bar
data={this.state.chartData}
options={{
title: {
display: this.props.displayTitle
},
legend: {
display: this.props.displayLegend,
position: this.props.legendPosition
},
scales: {
yAxes: [{
display: true,
ticks: {
suggestedMin: 0,
}
}]
}
}}
/>
)
}
}

Sexto Passo

Iremos agora editar o container responsável por processar os dados dos serviços, o DashboardContainer.

Este container permitirá a passagem dos dados para a tabela e para o gráfico,e também possibilita renderizar os dois componentes anteriormente explicados.

Este container está no seguinte diretório:

/apps/minhaapp/ui/src/containers/DashboardContainer/

O ficheiro a editar é o index.jsx da seguinte forma:

import React, { Component } from "react";
import Table from "../../components/Table/index.jsx";
import ChartBar from "../../components/ChartBar/index.jsx";

import styles from './index.less';

export default class DashboardContainer extends Component {
constructor(props) {
super(props);
this.state = {
tableData: [],
chartData: {}
};

this.input = React.createRef();
this.result = React.createRef();
this.handleChange = this.handleChange.bind(this);
}

// Chamada aos dados para a tabela e gráfico serem criadas
componentDidMount() {
this.getRecords();
}

handleChange(event) {
if (isNaN(event.target.value)) {
this.setState({ calc_hours: parseInt(this.state.calc_hours) });
return;
}
let self = this;
fetch('/services/calc-hours.netuno?hours='+ event.target.value, {
credentials: 'include'
}).then((response) => {
return response.json();
}).then((json) => {
self.result.current.innerText = json.date +' '+ json.time;
});
this.setState({ calc_hours: event.target.value });
}

// Criação da chamada ao serviço registos.netuno
getRecords() {
let that = this;
fetch('/services/registos.netuno', {
credentials: 'include'
}).then((response) => {
return response.json();
}).then((json) => {
if (!json.length) {
return;
} else {
// Adição dos dados à tabela e gráfico
that.setState({ tableData: json, chartData: json });
}
});
}

render() {
return (
<div className="my-dashboard">
<div className="row">
<div className="col-lg-6">
<div className="panel panel-default">
<div className={styles.panelBackground}>
<h3 className="panel-title">Tabela</h3>
</div>
<div className="panel-body">
<Table tableData={this.state.tableData} />
</div>
</div>
</div>
<div className="col-lg-6">
<div className="panel panel-default">
<div className={styles.panelBackground}>
<h3 className="panel-title">Gráfico</h3>
</div>
<div className="panel-body">

<ChartBar chartData={this.state.chartData} displayLegend="false" legendPosition="top" />

</div>
</div>
</div>
</div>
</div>
);
}
}

Iremos agora editar o ficheiro de estilos do dashboard do netuno no diretório DashboardContainer, o ficheiro index.less da seguinte forma:

.panelBackground{
background-color: #3f54ba;
padding: 10px 15px;
color: white;
}

Sétimo Passo

Agora para concluir basta compilar o código dos componentes e do container, para isso execute o comando npm run watch no diretório /apps/minhaapp/ui

E é tudo para este tutorial!

Caso tenha alguma questão não hesite em contactar-nos através dos meios apresentados no fim da página.

Bom desenvolvimento!