From 28a1ebdf895fe081091443d3823c61db901bb5fb Mon Sep 17 00:00:00 2001 From: Andrej730 Date: Tue, 15 Sep 2026 12:25:59 +0500 Subject: [PATCH] Renormalize line endings in js files --- .../bonsai/bim/data/webui/static/js/demo.js | 292 ++-- .../bim/data/webui/static/js/drawings.js | 734 +++++----- .../bonsai/bim/data/webui/static/js/gantt.js | 1200 ++++++++--------- .../bonsai/bim/data/webui/static/js/index.js | 974 ++++++------- 4 files changed, 1600 insertions(+), 1600 deletions(-) diff --git a/src/bonsai/bonsai/bim/data/webui/static/js/demo.js b/src/bonsai/bonsai/bim/data/webui/static/js/demo.js index b674ab5014..b95de37a89 100644 --- a/src/bonsai/bonsai/bim/data/webui/static/js/demo.js +++ b/src/bonsai/bonsai/bim/data/webui/static/js/demo.js @@ -1,146 +1,146 @@ -// A global variable to hold the WebSocket connection -let socket; - -// Document ready function -// This function is triggered once the DOM is fully loaded. -// It sets the theme for the UI and -// establishes the WebSocket connection by calling connectSocket(). -$(document).ready(function () { - var defaultTheme = "blender"; // Default theme to be applied - var theme = localStorage.getItem("theme") || defaultTheme; // Retrieve the stored theme or use the default - setTheme(theme); // Apply the theme - - connectSocket(); -}); - -// Function to establish WebSocket connection -// This function constructs the WebSocket connection URL using the SOCKET_PORT variable -// and initializes the socket connection. It also registers event handlers to listen -// for various events emitted by the server, such as 'blender_connect', 'blender_disconnect', -// 'theme_data', and 'demo_data'. -function connectSocket() { - const url = "ws://localhost:" + SOCKET_PORT + "/web"; - socket = io(url); - console.log("socket: ", socket); - - // Register socket event handlers - socket.on("blender_connect", handleBlenderConnect); - socket.on("blender_disconnect", handleBlenderDisconnect); - socket.on("theme_data", handleThemeData); - socket.on("demo_data", handleDemoData); -} - -// Function to handle 'blender_connect' event -// This function is triggered when a new Bonsai instance connects to the server. -// The 'blenderId' is a unique identifier assigned by the server to each Bonsai instance. -// It helps distinguish between different instances of Bonsai connected to the server. -// The 'blenderId' is used in various parts of the code to ensure that messages and data -// are correctly associated with the appropriate Bonsai instance. -function handleBlenderConnect(blenderId) { - console.log("blender connected: ", blenderId); -} - -// Function to handle 'blender_disconnect' event -// This function is triggered when a Bonsai instance disconnects from the server. -// The 'blenderId' is used here to log which specific Bonsai instance has disconnected. -function handleBlenderDisconnect(blenderId) { - console.log("blender disconnected: ", blenderId); -} - -// Function to handle 'demo_data' event -// This function processes the demo data received from the server. -// It extracts the message and the Bonsai instance ID ('blenderId'), -// and updates the DOM to display the message. The 'blenderId' is used -// to differentiate between messages from different Bonsai instances. -// If the message for the specific Bonsai instance is already displayed, it updates the content; -// otherwise, it creates a new element to display the message. -function handleDemoData(demoData) { - console.log(demoData); - const message = demoData["data"]["demo_message"]; - const blenderId = demoData["blenderId"]; - const id = "message-" + blenderId; - const messageHeader = $("#" + id); - const messageText = `Bonsai instance with ID: ${blenderId} sent the message: ${message}`; - - if (messageHeader[0] === undefined) { - const newMessageElement = $("

", { id: id }).text(messageText); - $("#message-container").prepend(newMessageElement); - } else { - messageHeader.text(messageText); - messageHeader.prependTo("#message-container"); - } -} - -// Function to send a message to the server -// This function is triggered when the user submits a message. -// It collects the message from the input field, constructs a message object, -// and emits the 'web_operator' event to the server with the message data. -// If 'blenderId' is specified, the message is sent to a specific Bonsai instance. -function sendMessage() { - const inputMessage = $("#input-message").val(); - - const msg = { - sourcePage: "demo", - // blenderId: BlenderId, // specify the target Bonsai instance - operator: { - type: "message", - message: inputMessage, - }, - }; - socket.emit("web_operator", msg); -} - -function handleThemeData(themeData) { - // console.log(themeData); - - function arrayToRgbString(arr) { - const [r, g, b, a] = arr.map((num) => Math.round(num * 255)); - if (a !== undefined) { - return `rgba(${r}, ${g}, ${b}, ${a})`; - } - return `rgb(${r}, ${g}, ${b})`; - } - - function generateCssVariableRule(theme) { - let cssVariables = ":root.blender {\n"; - for (const key in theme) { - const cssVariableName = `--blender-${key.replace(/_/g, "-")}`; - const cssVariableValue = arrayToRgbString(theme[key]); - cssVariables += ` ${cssVariableName}: ${cssVariableValue};\n`; - } - cssVariables += "}"; - return cssVariables; - } - - const cssRule = generateCssVariableRule(themeData.theme); - console.log(cssRule); - - var styleElement = $("#demo-stylesheet")[0]; - if (styleElement) { - var sheet = styleElement.sheet || styleElement.styleSheet; - sheet.insertRule(cssRule, sheet.cssRules.length); - } -} - -function setTheme(theme) { - $("html").removeClass("light dark blender").addClass(theme); - $(":root").css("color-scheme", theme); - if (theme === "light") { - $("#toggle-theme").html(''); - } else if (theme === "dark") { - $("#toggle-theme").html(''); - } else if (theme === "blender") { - $("#toggle-theme").html(''); - } - localStorage.setItem("theme", theme); -} - -function toggleTheme() { - if ($("html").hasClass("light")) { - setTheme("dark"); - } else if ($("html").hasClass("dark")) { - setTheme("blender"); - } else { - setTheme("light"); - } -} +// A global variable to hold the WebSocket connection +let socket; + +// Document ready function +// This function is triggered once the DOM is fully loaded. +// It sets the theme for the UI and +// establishes the WebSocket connection by calling connectSocket(). +$(document).ready(function () { + var defaultTheme = "blender"; // Default theme to be applied + var theme = localStorage.getItem("theme") || defaultTheme; // Retrieve the stored theme or use the default + setTheme(theme); // Apply the theme + + connectSocket(); +}); + +// Function to establish WebSocket connection +// This function constructs the WebSocket connection URL using the SOCKET_PORT variable +// and initializes the socket connection. It also registers event handlers to listen +// for various events emitted by the server, such as 'blender_connect', 'blender_disconnect', +// 'theme_data', and 'demo_data'. +function connectSocket() { + const url = "ws://localhost:" + SOCKET_PORT + "/web"; + socket = io(url); + console.log("socket: ", socket); + + // Register socket event handlers + socket.on("blender_connect", handleBlenderConnect); + socket.on("blender_disconnect", handleBlenderDisconnect); + socket.on("theme_data", handleThemeData); + socket.on("demo_data", handleDemoData); +} + +// Function to handle 'blender_connect' event +// This function is triggered when a new Bonsai instance connects to the server. +// The 'blenderId' is a unique identifier assigned by the server to each Bonsai instance. +// It helps distinguish between different instances of Bonsai connected to the server. +// The 'blenderId' is used in various parts of the code to ensure that messages and data +// are correctly associated with the appropriate Bonsai instance. +function handleBlenderConnect(blenderId) { + console.log("blender connected: ", blenderId); +} + +// Function to handle 'blender_disconnect' event +// This function is triggered when a Bonsai instance disconnects from the server. +// The 'blenderId' is used here to log which specific Bonsai instance has disconnected. +function handleBlenderDisconnect(blenderId) { + console.log("blender disconnected: ", blenderId); +} + +// Function to handle 'demo_data' event +// This function processes the demo data received from the server. +// It extracts the message and the Bonsai instance ID ('blenderId'), +// and updates the DOM to display the message. The 'blenderId' is used +// to differentiate between messages from different Bonsai instances. +// If the message for the specific Bonsai instance is already displayed, it updates the content; +// otherwise, it creates a new element to display the message. +function handleDemoData(demoData) { + console.log(demoData); + const message = demoData["data"]["demo_message"]; + const blenderId = demoData["blenderId"]; + const id = "message-" + blenderId; + const messageHeader = $("#" + id); + const messageText = `Bonsai instance with ID: ${blenderId} sent the message: ${message}`; + + if (messageHeader[0] === undefined) { + const newMessageElement = $("

", { id: id }).text(messageText); + $("#message-container").prepend(newMessageElement); + } else { + messageHeader.text(messageText); + messageHeader.prependTo("#message-container"); + } +} + +// Function to send a message to the server +// This function is triggered when the user submits a message. +// It collects the message from the input field, constructs a message object, +// and emits the 'web_operator' event to the server with the message data. +// If 'blenderId' is specified, the message is sent to a specific Bonsai instance. +function sendMessage() { + const inputMessage = $("#input-message").val(); + + const msg = { + sourcePage: "demo", + // blenderId: BlenderId, // specify the target Bonsai instance + operator: { + type: "message", + message: inputMessage, + }, + }; + socket.emit("web_operator", msg); +} + +function handleThemeData(themeData) { + // console.log(themeData); + + function arrayToRgbString(arr) { + const [r, g, b, a] = arr.map((num) => Math.round(num * 255)); + if (a !== undefined) { + return `rgba(${r}, ${g}, ${b}, ${a})`; + } + return `rgb(${r}, ${g}, ${b})`; + } + + function generateCssVariableRule(theme) { + let cssVariables = ":root.blender {\n"; + for (const key in theme) { + const cssVariableName = `--blender-${key.replace(/_/g, "-")}`; + const cssVariableValue = arrayToRgbString(theme[key]); + cssVariables += ` ${cssVariableName}: ${cssVariableValue};\n`; + } + cssVariables += "}"; + return cssVariables; + } + + const cssRule = generateCssVariableRule(themeData.theme); + console.log(cssRule); + + var styleElement = $("#demo-stylesheet")[0]; + if (styleElement) { + var sheet = styleElement.sheet || styleElement.styleSheet; + sheet.insertRule(cssRule, sheet.cssRules.length); + } +} + +function setTheme(theme) { + $("html").removeClass("light dark blender").addClass(theme); + $(":root").css("color-scheme", theme); + if (theme === "light") { + $("#toggle-theme").html(''); + } else if (theme === "dark") { + $("#toggle-theme").html(''); + } else if (theme === "blender") { + $("#toggle-theme").html(''); + } + localStorage.setItem("theme", theme); +} + +function toggleTheme() { + if ($("html").hasClass("light")) { + setTheme("dark"); + } else if ($("html").hasClass("dark")) { + setTheme("blender"); + } else { + setTheme("light"); + } +} diff --git a/src/bonsai/bonsai/bim/data/webui/static/js/drawings.js b/src/bonsai/bonsai/bim/data/webui/static/js/drawings.js index 1c4052b6fd..01c22efdca 100644 --- a/src/bonsai/bonsai/bim/data/webui/static/js/drawings.js +++ b/src/bonsai/bonsai/bim/data/webui/static/js/drawings.js @@ -1,367 +1,367 @@ -// keeps track of blenders connected -const connectedClients = {}; -const allDrawings = {}; -let socket; - -// Document ready function -$(document).ready(function () { - var defaultTheme = "blender"; - var theme = localStorage.getItem("theme") || defaultTheme; - setTheme(theme); - - $("#dropdown-menu").change(function () { - const blenderId = $(this).attr("id"); - const ifcFile = $(this).val(); - displayDrawingsNames(blenderId, ifcFile); - }); - - connectSocket(); -}); - -// Function to connect to Socket.IO server -function connectSocket() { - const url = "ws://localhost:" + SOCKET_PORT + "/web"; - socket = io(url); - console.log("socket: ", socket); - - // Register socket event handlers - socket.on("blender_connect", handleBlenderConnect); - socket.on("blender_disconnect", handleBlenderDisconnect); - socket.on("connect", handleWebConnect); - socket.on("connected_clients", handleConnectedClients); - //socket.on("default_data", handleDefaultData); - socket.on("theme_data", handleThemeData); - socket.on("drawings_data", handleDrawingsData); - socket.on("svg_data", handleSvgData); -} - -// function used to get drawings data from Bonsai -function handleWebConnect() { - console.log("Handle Web Connect") - getDrawingsData(); -} - -// Function to handle 'blender_connect' event -function handleBlenderConnect(blenderId) { - console.log("blender connected: ", blenderId); - if (!connectedClients.hasOwnProperty(blenderId)) { - connectedClients[blenderId] = { - shown: false, - ifc_file: "", - has_drawings: false, - }; - } - - $("#blender-count").text(function (i, text) { - return parseInt(text, 10) + 1; - }); - - const msg = { - blenderId: blenderId, - sourcePage: "drawings", - operator: { - type: "getDrawings", - }, - }; - socket.emit("web_operator", msg); -} - -// Function to handle 'default_data' event -function handleDefaultData(data) { - const blenderId = data["blenderId"]; - getDrawingsData(blenderId); -} - -// Function to handle 'blender_disconnect' event -function handleBlenderDisconnect(blenderId) { - if (connectedClients.hasOwnProperty(blenderId)) { - delete connectedClients[blenderId]; - removeSelectOption(blenderId); - } - - $("#blender-count").text(function (i, text) { - return parseInt(text, 10) - 1; - }); -} - -function handleConnectedClients(data) { - $("#blender-count").text(data.length); - // console.log(data); - data.forEach(function (id) { - connectedClients[id] = { - shown: false, - ifc_file: "", - has_drawings: false, - }; - }); -} - -function handleThemeData(themeData) { - function arrayToRgbString(arr) { - const [r, g, b, a] = arr.map((num) => Math.round(num * 255)); - if (a !== undefined) { - return `rgba(${r}, ${g}, ${b}, ${a})`; - } - return `rgb(${r}, ${g}, ${b})`; - } - - function generateCssVariableRule(theme) { - let cssVariables = ":root.blender {\n"; - for (const key in theme) { - const cssVariableName = `--blender-${key.replace(/_/g, "-")}`; - const cssVariableValue = arrayToRgbString(theme[key]); - cssVariables += ` ${cssVariableName}: ${cssVariableValue};\n`; - } - cssVariables += "}"; - return cssVariables; - } - - const cssRule = generateCssVariableRule(themeData.theme); - console.log(cssRule); - - var styleElement = $("#drawings-stylesheet")[0]; - if (styleElement) { - var sheet = styleElement.sheet || styleElement.styleSheet; - sheet.insertRule(cssRule, sheet.cssRules.length); - } -} - -function handleDrawingsData(data) { - console.log("Running handleDrawingsData"); - const blenderId = data["blenderId"]; - - console.log(data); - - const filename = data["data"]["ifc_file"]; - const drawings = data["data"]["drawings_data"]["drawings"]; - const sheets = data["data"]["drawings_data"]["sheets"]; - - allDrawings[filename] = { drawings: drawings, sheets: sheets }; - - const hasDrawings = drawings.length > 0 || sheets.length > 0; - - // console.log(connectedClients); - - if (connectedClients.hasOwnProperty(blenderId)) { - if (!connectedClients[blenderId].shown) { - connectedClients[blenderId] = { - shown: true, - ifc_file: filename, - has_drawings: hasDrawings, - }; - addSelectOption(blenderId, filename); - } else { - updateSelectOption(blenderId, filename); - } - } else { - connectedClients[blenderId] = { - shown: true, - ifc_file: filename, - has_drawings: hasDrawings, - }; - addSelectOption(blenderId, filename); - } -} - -function handleSvgData(data) { - const svgContainer = document.getElementById("svg-container"); - svgContainer.innerHTML = ""; - svgContainer.style.backgroundColor = "white"; - - const dom = SVG(svgContainer).svg(data); - const svgElement = dom.node.children[0]; - - // to make the svg not grow outside the svg container - svgElement.setAttribute("width", "100%"); - svgElement.setAttribute("height", "100%"); - svgElement.style.maxWidth = "100%"; - svgElement.style.maxHeight = "100%"; - svgElement.style.width = "100%"; - svgElement.style.height = "100%"; - svgElement.style.boxSizing = "border-box"; // Ensure padding and borders are included in the element's total width and height - - const panZoomControls = svgPanZoom(svgElement, { - zoomEnabled: true, - controlIconsEnabled: true, - fit: true, - center: true, - }); -} - -function addSelectOption(blenderId, filename) { - const filenameOption = $("") - .attr("id", "blender-" + blenderId) - .val(filename) - .text(filename); - $("#dropdown-menu").append(filenameOption); -} - -function updateSelectOption(blenderId, filename) { - $("#blender-" + blenderId).text(filename); - // console.log(blenderId, filename); - console.log($("#dropdown-menu").val()); - - if ($("#dropdown-menu").val() === filename) { - displayDrawingsNames(blenderId, filename); - } -} - -function removeSelectOption(blenderId) { - const filename = $("#blender-" + blenderId).val(); - const selectedOption = $("#dropdown-menu").val(); - - $("#blender-" + blenderId).remove(); - delete allDrawings[filename]; - - if (selectedOption == filename) { - $("#dropdown-menu").val("0"); - - $("#drawings-sub-panel").empty(); - $("#sheets-sub-panel").empty(); - } -} - -function displayDrawingsNames(blenderId, ifcFile) { - drawings = allDrawings[ifcFile].drawings; - sheets = allDrawings[ifcFile].sheets; - - function createSvgNames(text, index, type) { - var label = $("
  • ") - .text(text) - .attr("id", type + "-" + index) - .addClass("svg-name") - .click(function () { - const id = $(this).attr("id").split("-"); - const index = parseInt(id[1]); - const type = id[0]; - const ifcFile = $("#dropdown-menu").val(); - - var path = ""; - - if (type === "drawing") { - path = allDrawings[ifcFile].drawings[index].path; - } else if (type === "sheet") { - path = allDrawings[ifcFile].sheets[index].path; - } - - const msg = { - path: path, - }; - // console.log(msg); - socket.emit("get_svg", msg); - - $("li").removeClass("selected-svg"); - $(this).addClass("selected-svg"); - }); - - if (type === "drawing") $("#drawings-sub-panel").append(label); - else if (type === "sheet") $("#sheets-sub-panel").append(label); - } - - $("#drawings-sub-panel").empty(); - drawings.forEach(function (drawing, index) { - createSvgNames(drawing.name, index, "drawing"); - }); - - $("#sheets-sub-panel").empty(); - sheets.forEach(function (sheet, index) { - createSvgNames(sheet.name, index, "sheet"); - }); -} - -function setTheme(theme) { - $("html").removeClass("light dark blender").addClass(theme); - $(":root").css("color-scheme", theme); - if (theme === "light") { - $("#toggle-theme").html(''); - } else if (theme === "dark") { - $("#toggle-theme").html(''); - } else if (theme === "blender") { - $("#toggle-theme").html(''); - } - localStorage.setItem("theme", theme); -} - -function toggleTheme() { - if ($("html").hasClass("light")) { - setTheme("dark"); - } else if ($("html").hasClass("dark")) { - setTheme("blender"); - } else { - setTheme("light"); - } -} - -function toggleClientList() { - var clientList = $("#client-list"); - - if (clientList.hasClass("show")) { - clientList.removeClass("show"); - return; - } - - clientList.empty(); - var counter = 0; - - $.each(connectedClients, function (id, client) { - counter++; - - const dropdownIcon = $("") - .addClass("fas fa-chevron-down") - .css("margin-left", "0.5rem"); - - const clientDiv = $("
    ") - .addClass("client") - .text(client.ifc_file || "Blender " + counter); - - clientDiv.append(dropdownIcon); - - const clientDetailsDiv = $("
    ").addClass("client-details"); - - if (id) { - const clientId = $("
    ") - .addClass("client-detail") - .text(`Blender ID: ${id}`); - clientDetailsDiv.append(clientId); - } - - if (!client.has_drawings) { - const clientShown = $("
    ") - .addClass("client-detail") - .text("No drawings exist for this IFC File yet"); - clientDetailsDiv.append(clientShown); - } else { - const clientNumbers = $("
    ") - .addClass("client-detail") - .text( - `${allDrawings[client.ifc_file].drawings.length} Drawing(s), - ${allDrawings[client.ifc_file].sheets.length} Sheet(s)` - ); - clientDetailsDiv.append(clientNumbers); - } - - clientDiv.append(clientDetailsDiv); - - clientDiv.on("click", function () { - clientDetailsDiv.toggleClass("show"); - }); - - clientList.append(clientDiv); - }); - clientList.addClass("show"); -} - -function getDrawingsData(blenderId) { - const msg = { - sourcePage: "drawings", - operator: { - type: "getDrawings", - }, - }; - - if (blenderId !== undefined) { - msg.BlenderId = blenderId; - } - - socket.emit("web_operator", msg); -} +// keeps track of blenders connected +const connectedClients = {}; +const allDrawings = {}; +let socket; + +// Document ready function +$(document).ready(function () { + var defaultTheme = "blender"; + var theme = localStorage.getItem("theme") || defaultTheme; + setTheme(theme); + + $("#dropdown-menu").change(function () { + const blenderId = $(this).attr("id"); + const ifcFile = $(this).val(); + displayDrawingsNames(blenderId, ifcFile); + }); + + connectSocket(); +}); + +// Function to connect to Socket.IO server +function connectSocket() { + const url = "ws://localhost:" + SOCKET_PORT + "/web"; + socket = io(url); + console.log("socket: ", socket); + + // Register socket event handlers + socket.on("blender_connect", handleBlenderConnect); + socket.on("blender_disconnect", handleBlenderDisconnect); + socket.on("connect", handleWebConnect); + socket.on("connected_clients", handleConnectedClients); + //socket.on("default_data", handleDefaultData); + socket.on("theme_data", handleThemeData); + socket.on("drawings_data", handleDrawingsData); + socket.on("svg_data", handleSvgData); +} + +// function used to get drawings data from Bonsai +function handleWebConnect() { + console.log("Handle Web Connect") + getDrawingsData(); +} + +// Function to handle 'blender_connect' event +function handleBlenderConnect(blenderId) { + console.log("blender connected: ", blenderId); + if (!connectedClients.hasOwnProperty(blenderId)) { + connectedClients[blenderId] = { + shown: false, + ifc_file: "", + has_drawings: false, + }; + } + + $("#blender-count").text(function (i, text) { + return parseInt(text, 10) + 1; + }); + + const msg = { + blenderId: blenderId, + sourcePage: "drawings", + operator: { + type: "getDrawings", + }, + }; + socket.emit("web_operator", msg); +} + +// Function to handle 'default_data' event +function handleDefaultData(data) { + const blenderId = data["blenderId"]; + getDrawingsData(blenderId); +} + +// Function to handle 'blender_disconnect' event +function handleBlenderDisconnect(blenderId) { + if (connectedClients.hasOwnProperty(blenderId)) { + delete connectedClients[blenderId]; + removeSelectOption(blenderId); + } + + $("#blender-count").text(function (i, text) { + return parseInt(text, 10) - 1; + }); +} + +function handleConnectedClients(data) { + $("#blender-count").text(data.length); + // console.log(data); + data.forEach(function (id) { + connectedClients[id] = { + shown: false, + ifc_file: "", + has_drawings: false, + }; + }); +} + +function handleThemeData(themeData) { + function arrayToRgbString(arr) { + const [r, g, b, a] = arr.map((num) => Math.round(num * 255)); + if (a !== undefined) { + return `rgba(${r}, ${g}, ${b}, ${a})`; + } + return `rgb(${r}, ${g}, ${b})`; + } + + function generateCssVariableRule(theme) { + let cssVariables = ":root.blender {\n"; + for (const key in theme) { + const cssVariableName = `--blender-${key.replace(/_/g, "-")}`; + const cssVariableValue = arrayToRgbString(theme[key]); + cssVariables += ` ${cssVariableName}: ${cssVariableValue};\n`; + } + cssVariables += "}"; + return cssVariables; + } + + const cssRule = generateCssVariableRule(themeData.theme); + console.log(cssRule); + + var styleElement = $("#drawings-stylesheet")[0]; + if (styleElement) { + var sheet = styleElement.sheet || styleElement.styleSheet; + sheet.insertRule(cssRule, sheet.cssRules.length); + } +} + +function handleDrawingsData(data) { + console.log("Running handleDrawingsData"); + const blenderId = data["blenderId"]; + + console.log(data); + + const filename = data["data"]["ifc_file"]; + const drawings = data["data"]["drawings_data"]["drawings"]; + const sheets = data["data"]["drawings_data"]["sheets"]; + + allDrawings[filename] = { drawings: drawings, sheets: sheets }; + + const hasDrawings = drawings.length > 0 || sheets.length > 0; + + // console.log(connectedClients); + + if (connectedClients.hasOwnProperty(blenderId)) { + if (!connectedClients[blenderId].shown) { + connectedClients[blenderId] = { + shown: true, + ifc_file: filename, + has_drawings: hasDrawings, + }; + addSelectOption(blenderId, filename); + } else { + updateSelectOption(blenderId, filename); + } + } else { + connectedClients[blenderId] = { + shown: true, + ifc_file: filename, + has_drawings: hasDrawings, + }; + addSelectOption(blenderId, filename); + } +} + +function handleSvgData(data) { + const svgContainer = document.getElementById("svg-container"); + svgContainer.innerHTML = ""; + svgContainer.style.backgroundColor = "white"; + + const dom = SVG(svgContainer).svg(data); + const svgElement = dom.node.children[0]; + + // to make the svg not grow outside the svg container + svgElement.setAttribute("width", "100%"); + svgElement.setAttribute("height", "100%"); + svgElement.style.maxWidth = "100%"; + svgElement.style.maxHeight = "100%"; + svgElement.style.width = "100%"; + svgElement.style.height = "100%"; + svgElement.style.boxSizing = "border-box"; // Ensure padding and borders are included in the element's total width and height + + const panZoomControls = svgPanZoom(svgElement, { + zoomEnabled: true, + controlIconsEnabled: true, + fit: true, + center: true, + }); +} + +function addSelectOption(blenderId, filename) { + const filenameOption = $("") + .attr("id", "blender-" + blenderId) + .val(filename) + .text(filename); + $("#dropdown-menu").append(filenameOption); +} + +function updateSelectOption(blenderId, filename) { + $("#blender-" + blenderId).text(filename); + // console.log(blenderId, filename); + console.log($("#dropdown-menu").val()); + + if ($("#dropdown-menu").val() === filename) { + displayDrawingsNames(blenderId, filename); + } +} + +function removeSelectOption(blenderId) { + const filename = $("#blender-" + blenderId).val(); + const selectedOption = $("#dropdown-menu").val(); + + $("#blender-" + blenderId).remove(); + delete allDrawings[filename]; + + if (selectedOption == filename) { + $("#dropdown-menu").val("0"); + + $("#drawings-sub-panel").empty(); + $("#sheets-sub-panel").empty(); + } +} + +function displayDrawingsNames(blenderId, ifcFile) { + drawings = allDrawings[ifcFile].drawings; + sheets = allDrawings[ifcFile].sheets; + + function createSvgNames(text, index, type) { + var label = $("
  • ") + .text(text) + .attr("id", type + "-" + index) + .addClass("svg-name") + .click(function () { + const id = $(this).attr("id").split("-"); + const index = parseInt(id[1]); + const type = id[0]; + const ifcFile = $("#dropdown-menu").val(); + + var path = ""; + + if (type === "drawing") { + path = allDrawings[ifcFile].drawings[index].path; + } else if (type === "sheet") { + path = allDrawings[ifcFile].sheets[index].path; + } + + const msg = { + path: path, + }; + // console.log(msg); + socket.emit("get_svg", msg); + + $("li").removeClass("selected-svg"); + $(this).addClass("selected-svg"); + }); + + if (type === "drawing") $("#drawings-sub-panel").append(label); + else if (type === "sheet") $("#sheets-sub-panel").append(label); + } + + $("#drawings-sub-panel").empty(); + drawings.forEach(function (drawing, index) { + createSvgNames(drawing.name, index, "drawing"); + }); + + $("#sheets-sub-panel").empty(); + sheets.forEach(function (sheet, index) { + createSvgNames(sheet.name, index, "sheet"); + }); +} + +function setTheme(theme) { + $("html").removeClass("light dark blender").addClass(theme); + $(":root").css("color-scheme", theme); + if (theme === "light") { + $("#toggle-theme").html(''); + } else if (theme === "dark") { + $("#toggle-theme").html(''); + } else if (theme === "blender") { + $("#toggle-theme").html(''); + } + localStorage.setItem("theme", theme); +} + +function toggleTheme() { + if ($("html").hasClass("light")) { + setTheme("dark"); + } else if ($("html").hasClass("dark")) { + setTheme("blender"); + } else { + setTheme("light"); + } +} + +function toggleClientList() { + var clientList = $("#client-list"); + + if (clientList.hasClass("show")) { + clientList.removeClass("show"); + return; + } + + clientList.empty(); + var counter = 0; + + $.each(connectedClients, function (id, client) { + counter++; + + const dropdownIcon = $("") + .addClass("fas fa-chevron-down") + .css("margin-left", "0.5rem"); + + const clientDiv = $("
    ") + .addClass("client") + .text(client.ifc_file || "Blender " + counter); + + clientDiv.append(dropdownIcon); + + const clientDetailsDiv = $("
    ").addClass("client-details"); + + if (id) { + const clientId = $("
    ") + .addClass("client-detail") + .text(`Blender ID: ${id}`); + clientDetailsDiv.append(clientId); + } + + if (!client.has_drawings) { + const clientShown = $("
    ") + .addClass("client-detail") + .text("No drawings exist for this IFC File yet"); + clientDetailsDiv.append(clientShown); + } else { + const clientNumbers = $("
    ") + .addClass("client-detail") + .text( + `${allDrawings[client.ifc_file].drawings.length} Drawing(s), + ${allDrawings[client.ifc_file].sheets.length} Sheet(s)` + ); + clientDetailsDiv.append(clientNumbers); + } + + clientDiv.append(clientDetailsDiv); + + clientDiv.on("click", function () { + clientDetailsDiv.toggleClass("show"); + }); + + clientList.append(clientDiv); + }); + clientList.addClass("show"); +} + +function getDrawingsData(blenderId) { + const msg = { + sourcePage: "drawings", + operator: { + type: "getDrawings", + }, + }; + + if (blenderId !== undefined) { + msg.BlenderId = blenderId; + } + + socket.emit("web_operator", msg); +} diff --git a/src/bonsai/bonsai/bim/data/webui/static/js/gantt.js b/src/bonsai/bonsai/bim/data/webui/static/js/gantt.js index 630571e63d..598824968d 100644 --- a/src/bonsai/bonsai/bim/data/webui/static/js/gantt.js +++ b/src/bonsai/bonsai/bim/data/webui/static/js/gantt.js @@ -1,600 +1,600 @@ -import { CostUI } from './utilities/costui.js'; - -// keeps track of blenders connected in form of -// shown:bool, workSchedule: {}, ganttTasks: {}, warning: bool -const connectedClients = {}; -let socket; - -// print options -const pageSizes = [ - { value: "210,297", text: "A4 Portrait" }, - { value: "297,210", text: "A4 Landscape" }, - { value: "297,420", text: "A3 Portrait" }, - { value: "420,297", text: "A3 Landscape" }, - { value: "420,594", text: "A2 Portrait" }, - { value: "594,420", text: "A2 Landscape" }, - { value: "594,841", text: "A1 Portrait" }, - { value: "841,594", text: "A1 Landscape" }, - { value: "841,1189", text: "A0 Portrait" }, - { value: "1189,841", text: "A0 Landscape" }, -]; - -// Document ready function -$(document).ready(function () { - var defaultTheme = "blender"; - var theme = localStorage.getItem("theme") || defaultTheme; - setTheme(theme); - - connectSocket(); -}); - -// Function to connect to Socket.IO server -function connectSocket() { - const url = "ws://localhost:" + SOCKET_PORT + "/web"; - socket = io(url); - - // Register socket event handlers - socket.on("blender_connect", handleBlenderConnect); - socket.on("blender_disconnect", handleBlenderDisconnect); - socket.on("connected_clients", handleConnectedClients); - socket.on("connect", handleWebConnect); - socket.on("theme_data", handleThemeData); - socket.on("gantt_data", handleGanttData); - socket.on("default_data", handleDefaultData); - socket.on("work_schedule_info", handleWorkScheduleData); -} - -// function used to get drawings data from Bonsai -function handleWebConnect() { - getWorkScheduleData(); -} - -// Function to handle 'blender_connect' event -function handleBlenderConnect(blenderId) { - if (!connectedClients.hasOwnProperty(blenderId)) { - connectedClients[blenderId] = { - shown: false, - workSchedule: {}, - ganttTasks: {}, - }; - } - - $("#blender-count").text(function (i, text) { - return parseInt(text, 10) + 1; - }); -} - -// Function to handle 'blender_disconnect' event -function handleBlenderDisconnect(blenderId) { - if (connectedClients.hasOwnProperty(blenderId)) { - delete connectedClients[blenderId]; - removeWorkScheduleInfo(blenderId); - removeGanttElement(blenderId); - } - - $("#blender-count").text(function (i, text) { - return parseInt(text, 10) - 1; - }); -} - -function handleConnectedClients(data) { - $("#blender-count").text(data.length); - data.forEach(function (id) { - connectedClients[id] = { - shown: false, - workSchedule: {}, - ganttTasks: {}, - }; - }); -} - -function handleThemeData(themeData) { - function arrayToRgbString(arr) { - const [r, g, b, a] = arr.map((num) => Math.round(num * 255)); - if (a !== undefined) { - return `rgba(${r}, ${g}, ${b}, ${a})`; - } - return `rgb(${r}, ${g}, ${b})`; - } - - function generateCssVariableRule(theme) { - let cssVariables = ":root.blender {\n"; - for (const key in theme) { - const cssVariableName = `--blender-${key.replace(/_/g, "-")}`; - const cssVariableValue = arrayToRgbString(theme[key]); - cssVariables += ` ${cssVariableName}: ${cssVariableValue};\n`; - } - cssVariables += "}"; - return cssVariables; - } - - const cssRule = generateCssVariableRule(themeData.theme); - - var styleElement = $("#gantt-stylesheet")[0]; - if (styleElement) { - var sheet = styleElement.sheet || styleElement.styleSheet; - sheet.insertRule(cssRule, sheet.cssRules.length); - } -} - -function handleWorkScheduleData(data) { - const blenderId = data["blenderId"]; - const workSchedulesMainDiv = $("#work_schedules"); - const workSchedulesDiv = $("
    ").attr("id", "work_schedules-" + blenderId); - workSchedulesMainDiv.append(workSchedulesDiv); - - const workSchedules = data["data"]["work_schedule_info"]; - - workSchedules.forEach((workSchedule) => { - const mainContainer = CostUI.Text( - "Created On: " + new Date(workSchedule.CreationDate).toLocaleDateString(), - "fa-solid fa-pen-nib" - ); - const callback = () => loadWorkSchedule(workSchedule.id); - const card = CostUI.createCard(workSchedule.id, workSchedule.Name,mainContainer, callback); - workSchedulesDiv.append(card); - }); -} - -function handleGanttData(data) { - const blenderId = data["blenderId"]; - - const filename = data["data"]["ifc_file"]; - const ganttTasks = data["data"]["gantt_data"]["tasks"]; - const ganttWorkSched = data["data"]["gantt_data"]["work_schedule"]; - - if (connectedClients.hasOwnProperty(blenderId)) { - if (!connectedClients[blenderId].shown) { - connectedClients[blenderId] = { - shown: true, - ifc_file: filename, - ganttTasks: ganttTasks, - workSchedule: ganttWorkSched, - warning: false, - }; - addGanttElement(blenderId, ganttTasks, ganttWorkSched, filename); - } else { - updateGanttElement(blenderId, ganttTasks, ganttWorkSched, filename); - connectedClients[blenderId].workSchedule = ganttWorkSched; - connectedClients[blenderId].ganttTasks = ganttTasks; - connectedClients[blenderId].warning = false; - } - } else { - connectedClients[blenderId] = { - shown: true, - ifc_file: filename, - ganttTasks: ganttTasks, - workSchedule: ganttWorkSched, - warning: false, - }; - addGanttElement(blenderId, ganttTasks, ganttWorkSched, filename); - } -} - -function handleDefaultData(data) { - const blenderId = data["blenderId"]; - const isDirty = data["data"]["is_dirty"]; - showWarning(blenderId, isDirty); -} - -// Function to add a new gantt with data and filename - -function addGanttElement(blenderId, tasks, workSched, filename) { - function createWorkSchedDiv(blenderId, workSched) { - const workSchedDiv = $("
    ").attr("id", "workSched" + blenderId); - const scheduleTable = $("
    ") - .addClass("no-print table-description") - .attr("id", "workSchedTable-" + blenderId) - .hide(); - - $.each(workSched, (key, value) => { - value = value ? value : "null"; - $("") - .append($("").text(key)) - .append($("").text(value)) - .appendTo(scheduleTable); - }); - - const toggleButton = $("") - .text("Show Schedule Info") - .addClass("btn no-print") - .on("click", function () { - scheduleTable.toggle(); - const buttonText = scheduleTable.is(":visible") - ? "Hide Schedule Info" - : "Show Schedule Info"; - toggleButton.text(buttonText); - }); - - workSchedDiv.append(toggleButton); - workSchedDiv.append(scheduleTable); - - return workSchedDiv; - } - - function createGanttInfoDiv(blenderId, workSched) { - const ganttInfoDiv = $("
    ") - .addClass("gantt-info") - .attr("id", "gantt-info-" + blenderId); - - const scheduleName = $("").text("Schedule: " + workSched.Name); - const createdOn = $("") - .text("Created: " + new Date(workSched.CreationDate).toLocaleDateString()) - .css("float", "right"); - - ganttInfoDiv.append(scheduleName); - ganttInfoDiv.append(createdOn); - - return ganttInfoDiv; - } - - function createGantt(blenderId) { - const ganttDiv = $("
    ") - .addClass("gantt-chart") - .attr("id", "gantt-" + blenderId); - - let g = new JSGantt.GanttChart(ganttDiv[0], "week"); - g.setOptions({ - vCaptionType: "Caption", // Set to Show Caption : None,Caption,Resource,Duration,Complete, - vQuarterColWidth: 36, - vDateTaskDisplayFormat: "day dd month yyyy", // Shown in tool tip box - vDayMajorDateDisplayFormat: "mon yyyy - Week ww", // Set format to dates in the "Major" header of the "Day" view - vWeekMinorDateDisplayFormat: "dd mon", // Set format to display dates in the "Minor" header of the "Week" view - vLang: "en", - vShowTaskInfoLink: 1, // Show link in tool tip (0/1) - vShowEndWeekDate: 0, // Show/Hide the date for the last day of the week in header for daily - vUseSingleCell: 10000, // Set the threshold cell per table row (Helps performance for large data. - vFormatArr: ["Hour", "Day", "Week", "Month", "Quarter"], // vUseSingleCell keeps Hour usable on large charts. - vShowRes: true, // Disable the resource column. - vShowComp: false, // Disable the completion column. - vShowDur: false, // Disable the duration column, because jsgantt doesn't calculate durations the way we want. - vAdditionalHeaders: { - ifcduration: { title: "Duration" }, - resourceUsage: { title: "Resource Usage" }, - }, - vUseToolTip: true, // Disable tooltips. - vTooltipTemplate: generateTooltip, - vTotalHeight: 900, - - vEventsChange: { - taskname: editValue, // if you need to use the this scope, do: editValue.bind(this) - res: editValue, - dur: editValue, - comp: editValue, - start: editValue, - end: editValue, - planstart: editValue, - planend: editValue, - cost: editValue, - additional_category: editValue, - }, - }); - - JSGantt.addJSONTask(g, tasks); - g.setEditable(true); - - connectedClients[blenderId]["gantt"] = g; - - return ganttDiv; - } - - function createPrint(blenderId) { - const printButton = $("