@csn_chile/table_status
Version:
test new data structure
397 lines (372 loc) • 13.1 kB
JavaScript
import moment from 'moment';
import {
gauge_tpl,
fuel_gauge_tpl,
time_tpl,
load_template,
give_values,
tpl_gauge_opts,
tpl_time_opts,
tpl_dop_opts,
} from './templates';
import { createGauge, createFuelGauge, createTwoCircles, loadChart } from './charts';
import { gaugeCharts, fuelGaugeCharts, twoCirclesCharts } from './charts';
/*
Función para obtener el la última hoja del árbol
*/
function get_last_element(data, list) {
/*
obtener el ultimo valor
dentro del dato json
dada una lista de keys, para
extraer dentro del arbol
*/
let result = data;
for (let index in list) {
let elem = list[index];
if (result.hasOwnProperty(elem)) {
result = result[elem];
} else {
result = '';
}
}
return result;
}
// encontrar la posición
function findPosition(list, text) {
for (let e in list) {
let elem = list[e];
if (elem.textContent == text) {
return e;
}
}
}
// añadir fila a tabla
function add_row2table(table, table_head, key_name, data,
position, css_id_class, other_opts) {
/*
key_name = {
[CODIGO]: ['station'],
[NOMBRE]: ['name'],
[BATERIA]: ['batt_cap'],
[MEMORIA]: ['remaining_mem'],
[ULTIMO_DATO]: ['timestamp'],
[TPO_OFFLINE]: ['time_connected'],
[DOP]: ['dop'],
};
*/
// obtener la lista de encabezados
// tomados de table_head
let headers = table_head.getElementsByTagName('tr')[0].getElementsByTagName('th');
// insertar fila en posición n
let row = table.insertRow(position);
// en las opciones si tiene row_click, añadir callback
if (other_opts.hasOwnProperty('row_click')){
const callback=other_opts['row_click'].callback;
const args=other_opts['row_click'].args;
callback(data, row, ...args);
}
// se añade atributo css a cada fila
Object.entries(css_id_class).forEach((key, value) => {
row.setAttribute(...key);
});
// a la lista de clases de cada fila, añadir otras clases
row.classList.add(other_opts['paired_class']);
// codigo :: se debería añadir codigo a opts antes de llamar la fn?
let code = other_opts['code'];
let template = other_opts['tpl'];
let with_tpl = other_opts['with_tpl'];
let width = other_opts.size.w;
let height = other_opts.size.h;
// se itera en cada header, que es una lista
// item es un index
for (let item=0; item < headers.length; item++) {
/// obtener el texto
let item_name = headers[item].textContent;
// obtener el ultimo elemento o valor dado el dato
let elem = get_last_element(data, key_name[item_name]);
// insertar celda <td> en fila <tr>
let cell = row.insertCell(item);
// ultimo nombre de key_name[item]
let last_name = key_name[item_name].slice(-1)[0];
// asignar atributo de clase con last_name a cell
cell.setAttribute('class', last_name);
let extra_params = {};
// si el item name está en with_tpl
if (item_name in with_tpl) {
switch (with_tpl[item_name]['tipo']) {
case 'gauge':
let tpl_opts_json = tpl_gauge_opts(code + '_' + last_name, width, height);
let inner_html = give_values(template['gauge'], tpl_opts_json);
// look for class gauge_status--->svg-->id
//
cell.innerHTML = inner_html;
let svg = cell.getElementsByTagName('svg')[0];
let id_svg = svg.id;
// code, type:last_name, id_svg,
// create chart
// here->other_opts['chart_opts'][column]
let gauge_params = other_opts['chart_opts'][item_name];
let chart_map = other_opts['charts']['liquid_gauge'];
// load _chart
extra_params={};
if (data.hasOwnProperty('equipment_data')){
extra_params = data['equipment_data']['opts'][item_name];}
let gp = Object.assign(gauge_params, extra_params);
let new_gauge = createGauge(id_svg, gp, 1);
loadChart(code, last_name, id_svg, new_gauge, chart_map);
break;
case 'fuel_gauge':
let tpl_fuel_opts_json = tpl_time_opts(code + '_TO', width, height);
let inner_fuel_html = give_values(template['fuel_gauge'], tpl_fuel_opts_json);
cell.innerHTML = inner_fuel_html;
let svg_fuel = cell.getElementsByTagName('svg')[0];
let id_svg_fuel = svg_fuel.id;
// code, type:last_name, id_svg,
// create chart
// here->other_opts['chart_opts'][column]
let fuel_gauge_params = other_opts['chart_opts'][item_name];
// join with data--->
extra_params={};
if (data.hasOwnProperty('equipment_data')){
extra_params = data['equipment_data']['opts'][item_name];}
let fgp = Object.assign(fuel_gauge_params, extra_params);
//
let new_fuel_gauge = createFuelGauge(id_svg_fuel, fgp);
let fuel_chart_map = other_opts['charts']['fuel_gauge'];
// load _chart
loadChart(code, last_name, id_svg_fuel, new_fuel_gauge, fuel_chart_map);
new_fuel_gauge.redraw(100);
break;
case 'datetime':
let tpl_time_opts_json = tpl_time_opts(code);
let inner_time_html = give_values(template['datetime'], tpl_time_opts_json);
cell.innerHTML = inner_time_html;
break;
case 'dop':
let tpl_dop_opts_json = tpl_dop_opts(code);
let inner_dop_html = give_values(template['dop'], tpl_dop_opts_json);
cell.innerHTML = inner_dop_html;
let svg_dop = cell.getElementsByTagName('svg')[0];
let id_svg_dop = svg_dop.id;
let dop_params = other_opts['chart_opts'][item_name];
let dop_map = other_opts['charts']['dop'];
// load _chart
// generate opts object
let dgp = Object.assign(dop_params, extra_params);
dgp['code'] = code;
let new_dop = createTwoCircles(id_svg_dop, dgp);
let dop_chart_map = other_opts['charts']['dop'];
loadChart(code, last_name, id_svg_dop, new_dop, dop_chart_map);
new_dop.init();
//
//load_chart(code, last_name, id_svg_dop, new_fuel_gauge, fuel_chart_map);
break;
}
} else {
cell.innerHTML = elem;
}
}
}
function print(...value) {
console.log(...value);
}
export function oddOrEven(x) {
return ( x & 1 ) ? "odd" : "even";
}
function complete_table(table_name, key_name, data_list, table_map, other_opts) {
/*
table_name : string id de nombre de tabla, carga tabla en este id
key_name : json de campos con su lista de keys para extraer de datos
data_list : lista de datos para completar tabla
table_map : json de campos con posicion en columna
other_opts : json opciones especiales
*/
let table = document.getElementById(table_name).getElementsByTagName('tbody')[0];
let table_head = document.getElementById(table_name).getElementsByTagName('thead')[0];
//let table_head=thead.getElementsByTagName("tr")[0].getElementsByTagName("th");
let class_style = 'status_row';
let css_id_class = { class: class_style };
// read template
let tpl_path = other_opts['tpl_path'];
let tpl_file = load_template(tpl_path);
other_opts['tpl'] = tpl_file;
for (let data_pos in data_list) {
let position = parseInt(data_pos);
// dato de cada estacion
let data = data_list[data_pos];
let code = data['station'];
let id_style = code + '_row';
css_id_class['id'] = id_style;
let class_name=oddOrEven(data_pos);
other_opts['paired_class'] = class_name;
table_map[code] = position;
other_opts['code'] = code;
other_opts['paired_class']=class_name;
// hacer join de datos opts de data y other_opts
add_row2table(table, table_head, key_name, data, position, css_id_class, other_opts);
}
}
function update_gauge_value(cell, id_css, code, item, value) {
// if id_css==value
let cell_value = cell.getElementsByClassName(id_css)[0];
if (id_css == 'gauge_status') {
let gauge = gaugeCharts[code][item]['object_chart'];
gauge.update(value);
} else {
cell_value.innerHTML = value;
}
}
function update_fuel_gauge_value(cell, id_css, code, item, value) {
// if id_css==value
let cell_value = cell.getElementsByClassName(id_css)[0];
if (id_css == 'gauge_time_on') {
let gauge = fuelGaugeCharts[code]["time_connected"]['object_chart'];
gauge.redraw(value * 0.3);
} else {
cell_value.innerHTML = value;
}
}
function update_dop_value(cell, id_css, code, item, value) {
let dop = twoCirclesCharts[code][item]['object_chart'];
dop.update2(value);
}
function update_table(data_gen, table_name, headers, table_map, column_map, other_opts) {
/*
data_gen:
{
"id": 1581259,
"installation_ep": 8,
"dt_gen": "2020-05-13T17:10:44.085262+00:00",
"batt_cap": 100,
"remaining_mem": 201.7378,
"pdop": 1.8245403767,
"hdop": 0.8082436323000001,
"vdop": 1.6357536316,
"tdop": 1.4518325329000001,
"time_connected": 10,
"station": "TRPD",
"name": "Torpederas",
"timestamp": 1589389844.085262,
"dop": 2.3316872195462683,
"get_absolute_url": "/status_unidad/item/id=1581259",
"identify": [
1581259,
"TRPD",
"2020-05-13T17:10:44.085262+00:00"
],
"origin": "dj_channels"
}
*/
let table = document.getElementById(table_name).getElementsByTagName('tbody')[0];
// valor string codigo de estacion
let code = data_gen['station'];
// with_tpl : json que indicta tipo de template
let with_tpl = other_opts['with_tpl'];
// si existe en table_map el campo
// table_map es un json que se llena al
// construir la tabla con estaciones
// campo: posicion
if (table_map.hasOwnProperty(code)) {
// obtener la posicion
// de fila
let row_position = table_map[code];
// iterar, por cada columna del encabezado
for (let column in headers) {
// obtener la lista de items de esa columna
// headers :: key_name_json -> array[a,b,c]
// en esta columna se recibe un dato que se ubica
// en la última posicion del dato entrante
// siendo un diccionario
let item_list = headers[column];
// obtener la posición numerica de la columna
let column_position = column_map[column];
// obtener el valor ultimod el dato entrante
// dada la item list
let value = get_last_element(data_gen, item_list);
// obtener la celda que corresponde
// dada la fila y la columna
let cell = table.rows[row_position].cells[column_position];
// si value existe y cell existe,
// asignamos el valor al widget en cell
if (value && cell) {
// item_name -> , with_tpl, template (NO), cell
if (column in with_tpl) {
// si la key columna está en with_tpl
/*set value innerHTML on #id value*/
// extraer las settings para esa columna
let settings = with_tpl[column];
// actualizar de todas maneras
// la aguja del delta tiempo
update_gauge_value(cell, 'value', code, item_list[item_list.length - 1], value);
// para cada caso dentro de setttings tipo
// activa un grafico
switch (settings['tipo']) {
case 'gauge':
update_gauge_value(cell, 'gauge_status', code, item_list[item_list.length - 1], value);
break;
case 'fuel_gauge':
update_fuel_gauge_value(cell, 'gauge_time_on', code, item_list[item_list.length - 1], value);
break;
case 'datetime':
let cell_value = cell.getElementsByClassName('datetime')[0];
let date_cell = document.getElementById('column-date');
let dt = new Date(value * 1000);
cell_value.innerHTML = moment(dt).format('DD/MM HH:mm:ss');
date_cell.innerHTML = moment(dt).format('DD/MM/YYYY');
break;
case 'dop':
let dop_data = {PDOP:data_gen.pdop,TDOP:data_gen.tdop};
update_dop_value(cell, 'update_dop', code, item_list[item_list.length - 1], dop_data);
break;
}
}
else {
cell.innerHTML = value;
}
}
}
}
}
function deltatime(last_time, row, position, code) {
let now = new Date().getTime();
let ts = last_time;
if (ts) {
let delta = now / 1000 - parseInt(ts);
let nf = Intl.NumberFormat();
//row.cells[position+1].innerHTML=nf.format(delta);
let cell = row.cells[position + 1];
update_fuel_gauge_value(cell, 'gauge_time_on', code, 'to', delta);
// rescue gauge
return delta;
}
}
function update_field(table_name, field, callback, callback_args, table_map, column_map) {
let table = document.getElementById(table_name).getElementsByTagName('tbody')[0];
let field_index = column_map[field];
for (let value in table_map) {
// obtener valor en campo
let index = table_map[value];
let row = table.rows[index];
if (row.cells[field_index]) {
// let field_value = row.cells[field_index].textContent
let field_value = row.cells[field_index].getElementsByClassName("value")[0].textContent;
let result = callback(field_value, row, field_index, value, ...callback_args);
}
}
}
/*
Define client for use in node
*/
export {
get_last_element,
findPosition,
add_row2table,
print,
complete_table,
update_gauge_value,
update_fuel_gauge_value,
update_table,
deltatime,
update_field,
};