F I N
This commit is contained in:
@@ -28,10 +28,10 @@
|
||||
"GET_SENSOR_VALUES": "/groups/:groupId/devices/:deviceId/sensors/:sensorId/values",
|
||||
|
||||
"GET_ACTUATORS": "/groups/:groupId/devices/:deviceId/actuators",
|
||||
"GET_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id",
|
||||
"GET_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuatorId",
|
||||
"POST_ACTUATORS": "/groups/:groupId/devices/:deviceId/actuators",
|
||||
"PUT_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id",
|
||||
"GET_ACTUATOR_STATUS": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id/status",
|
||||
"PUT_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuatorId",
|
||||
"GET_ACTUATOR_STATUS": "/groups/:groupId/devices/:deviceId/actuators/:actuatorId/status",
|
||||
|
||||
"VIEW_LATEST_VALUES": "/v_latest_values",
|
||||
"VIEW_POLLUTION_MAP": "/v_pollution_map",
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
"GET_SENSOR_VALUES": "/groups/:groupId/devices/:deviceId/sensors/:sensorId/values",
|
||||
|
||||
"GET_ACTUATORS": "/groups/:groupId/devices/:deviceId/actuators",
|
||||
"GET_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id",
|
||||
"GET_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuatorId",
|
||||
"POST_ACTUATORS": "/groups/:groupId/devices/:deviceId/actuators",
|
||||
"PUT_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id",
|
||||
"GET_ACTUATOR_STATUS": "/groups/:groupId/devices/:deviceId/actuators/:actuator_id/status",
|
||||
"PUT_ACTUATOR_BY_ID": "/groups/:groupId/devices/:deviceId/actuators/:actuatorId",
|
||||
"GET_ACTUATOR_STATUS": "/groups/:groupId/devices/:deviceId/actuators/:actuatorId/status",
|
||||
|
||||
"VIEW_LATEST_VALUES": "/v_latest_values",
|
||||
"VIEW_POLLUTION_MAP": "/v_pollution_map",
|
||||
|
||||
Binary file not shown.
@@ -41,7 +41,7 @@ const Card = ({
|
||||
const cardContent = (
|
||||
<div
|
||||
ref={cardRef}
|
||||
className={`card p-3 w-100 ${theme} ${className ?? ""}`}
|
||||
className={`card p-3 w-100 h-100 ${theme} ${className ?? ""}`}
|
||||
style={styleMode === "override" ? style : {}}
|
||||
>
|
||||
<h3 className="text-center">
|
||||
@@ -49,18 +49,24 @@ const Card = ({
|
||||
{shortTitle}
|
||||
</h3>
|
||||
|
||||
<div className="card-content">
|
||||
{marquee ? (
|
||||
<marquee>
|
||||
<p className="card-text text-center">{children}</p>
|
||||
</marquee>
|
||||
) : text ? (
|
||||
<p className="card-text text-center">{children}</p>
|
||||
) : (
|
||||
<div className="my-2">{children}</div>
|
||||
)}
|
||||
|
||||
</div>
|
||||
{marquee && (
|
||||
<div className="contenedor-con-efecto card-content rounded-4 h-100 d-flex align-items-center justify-content-center" style={{ backgroundColor: "black"}}>
|
||||
<marquee scrollamount="30">
|
||||
<p className="card-text text-center m-0">{children}</p>
|
||||
</marquee>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!marquee && (
|
||||
<div className="card-content h-100" >
|
||||
{text ? (
|
||||
<p className="card-text text-center">{children}</p>
|
||||
) : (
|
||||
<>{children}</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{status && <span className="status text-center mt-2">{status}</span>}
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
}
|
||||
|
||||
.card.light > span.status {
|
||||
background: #E0E0E0;
|
||||
background: #D0D0D0;
|
||||
color: #505050;
|
||||
}
|
||||
|
||||
.card.dark {
|
||||
@@ -27,6 +28,7 @@
|
||||
|
||||
.card.dark > span.status {
|
||||
background: #505050;
|
||||
color: #D0D0D0;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
@@ -48,12 +50,20 @@
|
||||
|
||||
.card.led marquee > p.card-text {
|
||||
font-family: "LEDBOARD" !important;
|
||||
color: rgb(38, 60, 229) !important;
|
||||
font-size: 2.5em !important;
|
||||
color: #263ce5 !important;
|
||||
font-size: 6em !important;
|
||||
text-transform: uppercase !important;
|
||||
letter-spacing: 1px !important;
|
||||
}
|
||||
|
||||
.contenedor-con-efecto {
|
||||
background-color: #000; /* Fondo oscuro, similar al de la imagen */
|
||||
background-image: radial-gradient(#313131aa 3px, transparent 0.5px); /* Puntos muy sutiles, casi invisibles */
|
||||
background-size: 8px 8px; /* Controla la separación de los puntos */
|
||||
/* Ajusta estos valores para cambiar el tamaño y la densidad de los puntos */
|
||||
/* Los colores de los puntos pueden ser un azul muy oscuro, casi negro, o el mismo negro del fondo para un efecto muy sutil. */
|
||||
}
|
||||
|
||||
p.card-text {
|
||||
font-size: 2.2em;
|
||||
font-weight: 600;
|
||||
|
||||
@@ -9,10 +9,9 @@ import { useEffect, useState } from "react";
|
||||
import { DataProvider } from "@/context/DataContext";
|
||||
|
||||
import { MapContainer, TileLayer, Marker } from 'react-leaflet';
|
||||
import L, { map } from 'leaflet';
|
||||
import L from 'leaflet';
|
||||
import 'leaflet/dist/leaflet.css';
|
||||
import PropTypes from 'prop-types';
|
||||
import { text } from "@fortawesome/fontawesome-svg-core";
|
||||
|
||||
// Icono de marcador por defecto (porque Leaflet no lo carga bien en algunos setups)
|
||||
const markerIcon = new L.Icon({
|
||||
@@ -24,13 +23,15 @@ const markerIcon = new L.Icon({
|
||||
|
||||
const MiniMap = ({ lat, lon }) => (
|
||||
<MapContainer
|
||||
|
||||
center={[lat, lon]}
|
||||
zoom={15}
|
||||
scrollWheelZoom={false}
|
||||
dragging={false}
|
||||
doubleClickZoom={false}
|
||||
zoomControl={false}
|
||||
style={{ height: '150px', width: '100%', borderRadius: '10px' }}
|
||||
className="rounded-4"
|
||||
style={{ height: '180px', width: '100%'}}
|
||||
>
|
||||
<TileLayer url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" />
|
||||
<Marker position={[lat, lon]} icon={markerIcon} />
|
||||
@@ -65,9 +66,11 @@ const GroupViewContent = () => {
|
||||
const { data, dataLoading, dataError, getData } = useDataContext();
|
||||
const { groupId } = useParams();
|
||||
const [latestData, setLatestData] = useState({});
|
||||
const [actuatorStatus, setActuatorStatus] = useState({});
|
||||
|
||||
const { config } = useConfig(); // lo pillamos por si acaso
|
||||
const latestValuesUrl = config.appConfig.endpoints.LOGIC_URL + config.appConfig.endpoints.GET_DEVICE_LATEST_VALUES;
|
||||
const actuatorStatusUrl = config.appConfig.endpoints.LOGIC_URL + config.appConfig.endpoints.GET_ACTUATOR_STATUS;
|
||||
|
||||
useEffect(() => {
|
||||
if (!data || data.length === 0) return;
|
||||
@@ -94,6 +97,52 @@ const GroupViewContent = () => {
|
||||
fetchLatestData();
|
||||
}, [data, groupId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!data || data.length === 0) return;
|
||||
|
||||
const fetchActuatorStatus = async () => {
|
||||
const statusByDevice = {};
|
||||
|
||||
await Promise.all(data.map(async device => {
|
||||
const actuatorListUrl = config.appConfig.endpoints.DATA_URL +
|
||||
config.appConfig.endpoints.GET_ACTUATORS
|
||||
.replace(':groupId', groupId)
|
||||
.replace(':deviceId', device.deviceId);
|
||||
|
||||
try {
|
||||
const response = await getData(actuatorListUrl);
|
||||
const actuators = Array.isArray(response?.data) ? response.data : [];
|
||||
|
||||
const statuses = await Promise.all(
|
||||
actuators.map(async (actuator) => {
|
||||
const statusUrl = actuatorStatusUrl
|
||||
.replace(':groupId', groupId)
|
||||
.replace(':deviceId', device.deviceId)
|
||||
.replace(':actuatorId', actuator.actuatorId);
|
||||
|
||||
try {
|
||||
const status = await getData(statusUrl); // { status: ... }
|
||||
return { actuatorId: actuator.actuatorId, status };
|
||||
} catch (err) {
|
||||
console.error(`Error al obtener status del actuator ${actuator.actuatorId}:`, err);
|
||||
return { actuatorId: actuator.actuatorId, status: null };
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
statusByDevice[device.deviceId] = statuses;
|
||||
} catch (err) {
|
||||
console.error(`Error al obtener actuadores de ${device.deviceId}:`, err);
|
||||
statusByDevice[device.deviceId] = [];
|
||||
}
|
||||
}));
|
||||
|
||||
setActuatorStatus(statusByDevice);
|
||||
};
|
||||
|
||||
fetchActuatorStatus();
|
||||
}, [data, groupId]);
|
||||
|
||||
if (dataLoading) return <p className="text-center my-5"><LoadingIcon /></p>;
|
||||
if (dataError) return <p className="text-center my-5">Error al cargar datos: {dataError}</p>;
|
||||
|
||||
@@ -104,13 +153,19 @@ const GroupViewContent = () => {
|
||||
const gpsSensor = latest?.data[0];
|
||||
const mapPreview = <MiniMap lat={gpsSensor?.lat} lon={gpsSensor?.lon} />;
|
||||
|
||||
const actuatorById = actuatorStatus[device.deviceId] || [];
|
||||
const firstStatus = actuatorById.length > 0 ? actuatorById[0].status : null;
|
||||
|
||||
return {
|
||||
title: device.deviceName,
|
||||
status: `ID: ${device.deviceId}`,
|
||||
link: gpsSensor != undefined,
|
||||
text: gpsSensor == undefined,
|
||||
marquee: gpsSensor == undefined,
|
||||
content: gpsSensor == undefined ? "TODO TIPO DE VEHICULOS" : mapPreview,
|
||||
|
||||
content: gpsSensor == undefined
|
||||
? (firstStatus?.data?.actuatorStatus || 'Sin estado')
|
||||
: mapPreview,
|
||||
to: `/groups/${groupId}/devices/${device.deviceId}`,
|
||||
className: `col-12 col-md-6 col-lg-4 ${gpsSensor == undefined ? "led" : ""}`,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user