WEB :: interface loading JSON board

Rafael
jaume-nualart 7 months ago
parent 389db2a580
commit 9d64b495fd
  1. 2
      web-html/dash.html
  2. 320
      web-html/js/dash.js

@ -135,7 +135,7 @@
<div id="templates">Manage board:&nbsp;&nbsp;
<button id="saveDash" class="btn btn-outline-success" onclick="getApiUrls();"><i class="fa fa-upload"></i>Save</button>
&nbsp;&nbsp;
<button id="loadDashList" class="btn btn-outline-success" onclick=""><i class="fa fa-folder-open-o"></i>List</button>
<button id="loadDashList" class="btn btn-outline-success" onclick="loadBoards();"><i class="fa fa-folder-open-o"></i>List</button>
<span class="float-end">Templates:&nbsp;&nbsp;
<button id="button2" class="btn btn-outline-success"><i class="fa fa-map"></i> 33 %</button>
&nbsp;&nbsp;

@ -725,6 +725,104 @@ function do_grid_monthly(myid, month, year, data, apiUrl) {
function do_grid_monthly_one(myid, month, year, data, apiUrl) {
const margin = { top: 60, right: 20, bottom: 20, left: 20 };
const cellSize = 35;
const width = cellSize * 7; // Number of columns (days)
const height = cellSize * 7; // Number of rows (days)
// Create a tooltip element
const tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0)
.style("position", "absolute"); // Set tooltip position to absolute
const svg = d3.select(`#${myid}`)
.append("svg")
.attr("class", "heatmap")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
// Convert data values to numbers
const numericData = data.map(value => parseFloat(value));
// Create a color scale based on numeric data
const colorScale = d3.scaleLinear()
.domain([d3.min(numericData), d3.max(numericData)])
.range(["#0571b0", "#ca0020"]); // Replace with your desired color range
const rect = svg.selectAll("rect")
.data(numericData)
.enter().append("rect")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", (d, i) => ((i + getDayOffset(month, year)) % 7) * cellSize)
.attr("y", (d, i) => Math.floor((i + getDayOffset(month, year)) / 7) * cellSize)
.attr("fill", d => colorScale(d)) // Apply the color scale to data values
.on("mouseover", function (d) {
// Show the tooltip on hover
const [x, y] = d3.mouse(this);
const pageX = x + window.scrollX; // Adjust for horizontal scroll
const pageY = y + window.scrollY; // Adjust for vertical scroll
tooltip
.style("left", (d3.event.pageX + 10) + "px")
.style("top", (d3.event.pageY - 10) + "px")
.style("background-color", "#c3c3c3")
.style("opacity", 1)
.html("Value: " + d.toFixed(2));
})
.on("mouseout", () => {
tooltip.style("opacity", 0);
});
svg.selectAll(".day-number")
.data(numericData)
.enter().append("text")
.attr("class", "day-number")
.attr("x", (d, i) => ((i + getDayOffset(month, year)) % 7) * cellSize + cellSize / 2)
.attr("y", (d, i) => Math.floor((i + getDayOffset(month, year)) / 7) * cellSize + cellSize / 2)
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.text((d, i) => i + 1);
const weekDays = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
svg.selectAll(".weekday")
.data(weekDays)
.enter().append("text")
.attr("class", "weekday")
.attr("x", (d, i) => i * cellSize + cellSize / 2)
.attr("y", -10)
.attr("text-anchor", "middle")
.text((d) => d);
const firstDayOfMonth = new Date(year, month - 1, 1);
const dayOffset = (firstDayOfMonth.getDay() + 6) % 7; // Calculate the day offset for the first day of the month
const monthName = getMonth(month);
svg.append("text")
.attr("class", "year-label")
.attr("x", width)
.attr("y", -30)
.attr("text-anchor", "end")
.text(monthName + ", " + year);
function getDayOffset(month, year) {
const firstDayOfMonth = new Date(year, month - 1, 1);
const dayOffset = (firstDayOfMonth.getDay() + 6) % 7; // Calculate the day offset for the first day of the month
return dayOffset;
}
function getMonth(month) {
const months = [
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
return months[month - 1];
}
}
//--------------------------------
@ -775,8 +873,8 @@ function do_grid_yearly(myid, year, myData) {
// Create a color scale based on the min, max, and range of values
const colorScale = d3.scaleLinear()
.domain([minValue, maxValue])
.range(["#eff3ff", "#08519c"]); // Specify the range of colors
.domain([minValue, maxValue])
.range([0, 1]);
// Create a group for month labels
const monthLabelsGroup = svg.append("g")
@ -810,96 +908,112 @@ function do_grid_yearly(myid, year, myData) {
const x = col * cellWidth + borderWidth;
const y = row * cellHeight + borderWidth;
// Month Label
const monthLabel = monthLabelsGroup.append("text")
.attr("x", x + cellWidth / 2)
.attr("y", y + 20) // Increased vertical position
.attr("font-size", "18")
.attr("text-anchor", "middle")
.text(`${month.name} ${year}`);
// Create a border around the month
const border = svg.append("rect")
.attr("x", x)
.attr("y", y + 30) // Increased vertical position
.attr("width", cellWidth - 2 * borderWidth)
.attr("height", cellHeight - 2 * borderWidth - 30) // Adjusted height to avoid overlap
.attr("fill", "none")
.attr("stroke", "#ffffff") // Border
.attr("stroke-width", borderWidth);
// Calculate the y position for each month label
const monthLabelY = y + 20 + (row * 20); // Add 20px margin top for each row
// Month Label
const monthLabel = monthLabelsGroup.append("text")
.attr("x", x + cellWidth / 2)
.attr("y", monthLabelY)
.attr("font-size", "18")
.attr("text-anchor", "middle")
.text(`${month.name} ${year}`);
// Calendar Days
for (let day = 1; day <= month.days; day++) {
// Get the value for the current day
const value = myData[month.days * i + day - 1]; // Calculate index based on month and day
// Weekday labels
const weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
// Calculate the color based on the value
const color = d3.interpolateViridis(colorScale(value));
for (let w = 0; w < weekdays.length; w++) {
const weekdayLabel = svg.append("text")
.attr("x", x + (w * (cellWidth / 7)) + cellWidth / 14)
.attr("y", y + 55) // Increased vertical position
.attr("font-size", "12")
.attr("text-anchor", "middle")
.text(weekdays[w]);
}
// Calculate the position of the current day
const dayRow = Math.floor((day - 1) / 7);
const dayCol = (day - 1) % 7;
// Calculate the y position for each border rectangle
const borderY = y + 30 + (row * 20); // Add 20px margin top for each row
// Create a border around the month
const border = svg.append("rect")
.attr("x", x)
.attr("y", borderY)
.attr("width", cellWidth - 2 * borderWidth)
.attr("height", cellHeight - 10) // Decreased height to fit the day rectangles
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", borderWidth);
// Calculate the number of weeks in the month
const numWeeks = Math.ceil(month.days / 7);
function getDayOffset(month, year) {
const firstDayOfMonth = new Date(year, month - 1, 1);
const dayOffset = (firstDayOfMonth.getDay() + 6) % 7; // Calculate the day offset for the first day of the month
return dayOffset;
}
// Loop through each week and create the day rectangles
for (let week = 0; week < numWeeks; week++) {
for (let day = 0; day < 7; day++) {
const dayNumber = week * 7 + day + 1; // Calculate the day number
}
// Weekday labels
const weekdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
// Calculate the x and y positions for each day rectangle
const rectX = x + (day * (cellWidth / 7));
const rectY = y + 30 + ((week + 1) * (cellHeight / numWeeks));
// Loop through each month and create the calendar heatmap
for (let i = 0; i < months.length; i++) {
const month = months[i];
// Calculate row and column positions
const row = Math.floor(i / columns);
const col = i % columns;
// Calculate the value index for the current day
const valueIndex = (i * month.days) + (week * 7) + day;
// Starting positions for months
const x = col * cellWidth + borderWidth;
const y = row * cellHeight + borderWidth;
// Get the value for the current day
const value = myData[valueIndex];
// Calculate the color based on the value
const color = colorScale(value);
// Create the day rectangle
const rect = svg.append("rect")
.attr("x", rectX)
.attr("y", rectY)
.attr("width", cellWidth / 7)
.attr("height", cellHeight / numWeeks)
.attr("fill", value ? color : "white") // Set white background for empty values
.attr("stroke", "none")
.on("mouseover", () => handleMouseover(dayNumber, value))
.on("mouseout", () => tooltip.style("opacity", 0));
// Add the day number as text inside the day rectangle
const dayText = svg.append("text")
.attr("x", rectX + (cellWidth / 14))
.attr("y", rectY + (cellHeight / (2 * numWeeks)))
.attr("font-size", "12")
.attr("text-anchor", "middle")
.text(dayNumber);
}
}
// Weekday labels
for (let w = 0; w < weekdays.length; w++) {
const weekdayLabel = svg.append("text")
.attr("x", x + (w * (cellWidth / 7)) + cellWidth / 14)
.attr("y", y + 55) // Increased vertical position
.attr("font-size", "12")
.attr("text-anchor", "middle")
.text(weekdays[w]);
}
}
// Calendar Days
for (let day = 1; day <= month.days; day++) {
// Get the value for the current day
const value = myData[month.days * i + day - 1]; // Calculate index based on month and day
// Calculate the color based on the value
const color = d3.interpolateViridis(colorScale(value));
// Calculate the position of the current day
const dayRow = Math.floor((day - 1) / 7);
const dayCol = (day - 1) % 7;
// Create a rectangle for each day
svg.append("rect")
.attr("x", x + (dayCol * (cellWidth / 7)))
.attr("y", y + 60 + (dayRow * (cellHeight / 6))) // Increased vertical position
.attr("width", cellWidth / 7)
.attr("height", cellHeight / 6)
.attr("fill", color)
.attr("stroke", "#ffffff") // white border
.attr("class", "day")
.on("mouseover", () => {
const dayValue = myData[month.days * i + day - 1]; // Calculate index based on month and day
// Call the handleMouseover function with the correct value
handleMouseover(day, dayValue);
})
.on("mouseout", () => {
tooltip.style("opacity", 0);
})
.append("text") // Add text to display the day number
.attr("x", x + (dayCol * (cellWidth / 7)) + cellWidth / 14)
.attr("y", y + 85 + (dayRow * (cellHeight / 6))) // Increased vertical position
.attr("font-size", "12")
.attr("text-anchor", "middle")
.text(day);
}
}
}
}
function do_grid_yearlyXX(myid, year, myData) {
@ -1133,8 +1247,6 @@ for (let i = 0; i < months.length; i++) {
//--------------------------------
// HORIZON d3 diagram
function do_horizon_row(data, myid, title, myDates) {
var horizonChart = d3.horizonChart()
.height(50)
@ -1215,7 +1327,7 @@ function getApiUrls() {
document.querySelectorAll('#col-left div').forEach(function(element, index) {
var apiUrl = element.getAttribute('apiurl');
var id = element.id;
var order = apiUrlsCenter.length;
var order = apiUrlsLeft.length;
if (apiUrl === 'txt') {
var clone = element.cloneNode(true);
clone.querySelectorAll('span').forEach(function(span) {
@ -1254,7 +1366,7 @@ function getApiUrls() {
var apiUrl = element.getAttribute('apiurl');
var id = element.id;
var text = element.innerHTML.trim(); // Assuming the text is the innerHTML of the element
var order = apiUrlsCenter.length;
var order = apiUrlsRight.length;
if (apiUrl === 'txt') {
var clone = element.cloneNode(true);
clone.querySelectorAll('span').forEach(function(span) {
@ -1272,7 +1384,10 @@ function getApiUrls() {
// Similar modifications for #col-center and #col-right
var result = {
"name": myHouse.xname,
// FIXME : boardName will be entered in the save board form
"boardName" : "my Form name test",
"name": boardName,
"hus": myParam,
"description": myHouse.subtitle,
"col-left": apiUrlsLeft,
"col-center": apiUrlsCenter,
@ -1699,9 +1814,42 @@ var firstOpen = true;
// > makeApiRequiest
// > submit nuttons listener
//function to prepare the tha API request upon a board JSON
function loadBoards(myJSON) {
myJSON = '';
function getFormId(api_url) {return api_url[0].toUpperCase() + api_url.split("/")[1][0].toUpperCase();};
function loadBoards() {
//JAUME
// Test JSON Board:
myJSON = {"name":"Charlie","hus":"Charlie","description":"Lorem <a href=\"#\">Ipsum is</a> simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen.","col-left":[{"order":0,"id":"P-txt-728265","text":"Here a text","api_url":null},{"order":1,"id":"parallel-8001586","text":"","api_url":"parallel/monthly?hus=Charlie&family=MP1_1&type=celsius&year=2020&month=1"}],"col-center":[{"order":0,"id":"G-txt-956767","text":"Here a text","api_url":null},{"order":1,"id":"grid-190619","text":"","api_url":"grid/monthly?hus=Charlie&sensor=Temp_MP1_1_Pos1&type=celsius&year=2023&month=01"}],"col-right":[{"order":0,"id":"H-txt-518613","text":"Here a text","api_url":null},{"order":1,"id":"horizon-986338","text":"","api_url":"horizon/daily?hus=Charlie&family=MP1_1&type=celsius&day=2023-04-12"}]};
var cols = ["col-left", "col-center", "col-right"];
cols.forEach(col => {
if (col.length > 0) {
myJSON[col].forEach(element => {
// Get necessary variables:
var myColumn = col;
var myid = element.id;
var myTitle = element.text;
// Create DIV
createMyDiv(myid, myColumn, myTitle);
// Check if is TXT or Diagram:
if (element.text == "" ) {
cl(element["api_url"]);
var apiUrl = element["api_url"];
var formId = getFormId(apiUrl);
//createParallel(myid, formId, formData);
makeApiRequest(formId, apiUrl, myid);
} else {
var formId = "TXT";
createTXT(myid, element.text);
}
});
}
});
//Prepara the variables:
// formId, apiUrl, myid, myTitle, ...args
@ -1833,25 +1981,13 @@ function makeApiRequest(formId, apiUrl, myid, myTitle, ...args) {
case "HY":
data.sensor_names.forEach(element => {
var dataRow = data[element]
var element1 = [31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.70, 31.70, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.80, 31.70, 31.70, 31.70, 31.70, 31.70, 31.70];
do_horizon_row(dataRow, "#"+myid, element, data.days);
});
break;
}
})
.catch((error) => {
console.error("Fetch error:", error);
});
}
async function createHiddenVauesDiv(myid, dataName, data) {
// final childs for each data var
var mainDiv = document.getElementById(myid);
const childDiv = document.createElement("div");
const lastValueElement = document.createElement("div");
lastValueElement.id = dataName;
var data2 = JSON.stringify(data);
lastValueElement.innerHTML = data2;
}
Loading…
Cancel
Save