diff --git a/src/bonsai/bonsai/bim/data/webui/static/css/components/headerBar.css b/src/bonsai/bonsai/bim/data/webui/static/css/components/headerBar.css index d5767af2ef..4c431f407b 100644 --- a/src/bonsai/bonsai/bim/data/webui/static/css/components/headerBar.css +++ b/src/bonsai/bonsai/bim/data/webui/static/css/components/headerBar.css @@ -3,6 +3,8 @@ gap: 10px; margin-bottom: 20px; border: 1px solid #444; + width: 100%; + justify-content: center; } .ribbon-bar .action-button { diff --git a/src/bonsai/bonsai/bim/data/webui/static/css/cost.css b/src/bonsai/bonsai/bim/data/webui/static/css/cost.css index 557c42822c..bf2a85a9df 100644 --- a/src/bonsai/bonsai/bim/data/webui/static/css/cost.css +++ b/src/bonsai/bonsai/bim/data/webui/static/css/cost.css @@ -11,45 +11,55 @@ --scrollbar-track-color: #f1f1f1; --scrollbar-thumb-color: #888; --scrollbar-thumb-hover-color: #555; + --padding-small: 5px; + --padding-medium: 10px; } body { margin: 0; padding: 0; box-sizing: border-box; } + .form-header { display: flex; justify-content: flex-start; align-items: center; margin-bottom: 10px; - background-color: var(--background-color); - padding: 10px; - font-size: var(--fontSize); + background-color: #323936; + padding: var(--padding-medium); + font-size: large; + border-bottom: 1px solid #ddd; + border-radius: 6px 6px 0 0; } -span { +.floating-form span { + padding: var(--padding-small); margin-left: var(--margin-small); } .floating-form { width: 50vw; - height: 50vh; max-height: 80vh; position: absolute; background-color: var(--background-color); border: 1px solid black; z-index: 9999; cursor: move; - padding: 20px; user-select: none; - overflow-y: auto; - overflow-x: hidden; + resize: both; } .floating-form table tr { margin-bottom: 10px; } + +.form-container { + padding: var(--padding-medium); + overflow-y: auto; + overflow-x: hidden; +} + .action-button { background-color: var(--button-background); border: none; @@ -128,32 +138,37 @@ body { overflow-x: auto; overflow-y: auto; position: relative; + border: 1px solid #ddd; } .floating-form .table-container { - height: 50%; - max-height: 50%; + max-height: 70%; } #cost-items { max-height: calc(100vh - var(--margin-small)); } -/* if id starts with cost-values-form */ [id^="cost-values-form"] table { /* fixed */ max-height: 50%; table-layout: fixed; } + +[id^="selected-products"] .form-container { + height: 50vh; +} + table { width: 100%; height: 100%; border-collapse: collapse; user-select: none; font-size: var(--fontSize); - -webkit-font-smoothing: antialiased; /* Improve font rendering */ - -moz-osx-font-smoothing: grayscale; /* Improve font rendering */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + border: 1px solid #ddd; } thead { @@ -161,7 +176,6 @@ thead { top: 0; z-index: 1; background-color: #727272; - font-size: large; } tbody { @@ -172,13 +186,9 @@ tbody { td, th { - padding: 0; - margin: 0; border-left: 1px solid #ddd; border-right: 1px solid #ddd; text-align: center; - border-bottom: 0; - border-top: 0; } th { @@ -189,7 +199,6 @@ td { align-items: center; } -/* first td of a row, must be flex */ td:first-child { display: flex; align-items: center; @@ -223,7 +232,7 @@ select { margin-left: 0.5em; margin-right: 0.5em; font-size: var(--fontSize); - min-width: 50px; /* Minimum width to prevent it from becoming too small */ + min-width: 50px; } input:focus { @@ -258,7 +267,6 @@ input:focus { text-align: center; } -/* Responsive Styles */ @media (max-width: 768px) { table { font-size: 12px; @@ -295,3 +303,9 @@ input:focus { form table { max-height: 50%; } + + +.subtotal-row { + background-color: var(--button-hover-background); + font-weight: bold; +} \ No newline at end of file diff --git a/src/bonsai/bonsai/bim/data/webui/static/css/shared.css b/src/bonsai/bonsai/bim/data/webui/static/css/shared.css index 21c6c2c519..92fd10bda0 100644 --- a/src/bonsai/bonsai/bim/data/webui/static/css/shared.css +++ b/src/bonsai/bonsai/bim/data/webui/static/css/shared.css @@ -51,7 +51,7 @@ --border-color: #222; } -*:not(td, tr, td, .gmain) { +*:not(td, tr, td, th, button, .gmain) { border-radius: var(--border-radius) !important; } diff --git a/src/bonsai/bonsai/bim/data/webui/static/js/cost.js b/src/bonsai/bonsai/bim/data/webui/static/js/cost.js index 3866fadf39..22fca33d5a 100644 --- a/src/bonsai/bonsai/bim/data/webui/static/js/cost.js +++ b/src/bonsai/bonsai/bim/data/webui/static/js/cost.js @@ -11,21 +11,7 @@ $(document).ready(function () { setTheme(theme); connectSocket(); - CostUI.addSettingsMenu(); - CostUI.addRibbonButton({ - text: "Hide Schedules", - icon: "fa-regular fa-eye-slash", - callback: (button) => { - CostUI.toggleSchedulesContainer(button); - }, - }); - CostUI.addRibbonButton({ - text: "Settings", - icon: "fas fa-cog", - callback: (button) => { - CostUI.toggleSettingsMenu(button); - }, - }); + CostUI.createRibbon(); }); function connectSocket() { @@ -54,9 +40,15 @@ function handleSelectedProducts(data) { const formId = "selected-products-" + costItemId; const form = CostUI.Form({ id: formId, - name: "Selected Products", - icon: "fa-solid fa-cart-shopping", + name: "Edit Product Assignments for: " + CostUI.getCostItemName(costItemId), + icon: "fa-solid fa-box", }); + const numberOfProducts = CostUI.Text( + "Selection basket : " + products.length + " products", + "fa-solid fa-cart-shopping", + "large" + ); + form.appendChild(numberOfProducts); CostUI.highlightElement(costItemId); const selectedProductsTable = CostUI.createProductTable({ form, @@ -68,11 +60,12 @@ function handleSelectedProducts(data) { getSelectedProducts: getSelectedProducts, }, }); + if (assigned_products.length > 0) { const assignedProductsText = CostUI.Text( "Assigned Products", - "fa-solid fa-box", - "x-large" + "fa-solid fa-solid fa-paperclip", + "large" ); form.appendChild(assignedProductsText); const assignmentsTable = CostUI.createAssignmentsTable({ @@ -339,7 +332,6 @@ function handleCostSchedulesData(data) { "Predefined Type: " + costSchedule.PredefinedType, "fa-solid fa-paperclip" ); - // simplyfying the date const updatedDate = new Date(costSchedule.UpdateDate).toLocaleDateString(); const updatedOn = CostUI.Text( "Updated On: " + updatedDate, @@ -363,7 +355,6 @@ function handleCostSchedulesData(data) { } function handleCostItemsData(data) { - console.log(data); const cards = document.querySelectorAll("[id^='schedule-']"); cards.forEach((card) => { if (card.id === "schedule-" + data.data["cost_items"]["cost_schedule_id"]) { diff --git a/src/bonsai/bonsai/bim/data/webui/static/js/utilities/costui.js b/src/bonsai/bonsai/bim/data/webui/static/js/utilities/costui.js index 4fdfb5c575..a3f6c76882 100644 --- a/src/bonsai/bonsai/bim/data/webui/static/js/utilities/costui.js +++ b/src/bonsai/bonsai/bim/data/webui/static/js/utilities/costui.js @@ -182,7 +182,6 @@ export class CostUI { getSelectedProducts.hasListener = true; } - // Function to get column names from the table header function getColumnNames(tableId) { const table = document.getElementById(tableId); const headerRow = table.querySelector("thead tr"); @@ -191,7 +190,6 @@ export class CostUI { ); } - // Add double-click event listener document .getElementById("cost-items") .addEventListener("dblclick", function (event) { @@ -202,36 +200,12 @@ export class CostUI { targetCell ); const costItemId = parseInt(targetRow.getAttribute("id")); - const cellContent = targetCell.textContent; + const columnName = getColumnNames("cost-items")[columnIndex]; - // Get column names from the table header - const columnNames = getColumnNames("cost-items"); - const cellName = columnNames[columnIndex]; - - console.log("Column Name: ", cellName); - console.log("Content: ", cellContent); - - // Implement different behaviors based on the column index - switch (columnIndex) { - case 0: - // Behavior for the first column - callbacks.firstColumnDoubleClick - ? callbacks.firstColumnDoubleClick(costItemId) - : null; - break; - case 1: - // Behavior for the second column - callbacks.secondColumnDoubleClick - ? callbacks.secondColumnDoubleClick(costItemId) - : null; - break; - // Add more cases as needed for other columns - default: - // Default behavior - callbacks.defaultDoubleClick - ? callbacks.defaultDoubleClick(costItemId) - : null; - break; + if (columnName === "Cost") { + callbacks.enableEditingCostValues + ? callbacks.enableEditingCostValues(costItemId) + : null; } } }); @@ -345,21 +319,24 @@ export class CostUI { form.appendChild(typeSelect); const submitButton = document.createElement("button"); - submitButton.type = "submit"; submitButton.textContent = "Add"; submitButton.classList.add("action-button"); form.appendChild(submitButton); - form.addEventListener("submit", function (event) { - event.preventDefault(); - const formData = new FormData(form); - const data = {}; - formData.forEach((value, key) => { - data[key] = value; + document + .getElementById("add-cost-schedule-form") + .addEventListener("submit", function (event) { + event.preventDefault(); + const formData = new FormData( + document.getElementById("add-cost-schedule-form") + ); + const data = {}; + formData.forEach((value, key) => { + data[key] = value; + }); + addCostSchedule(data.name, data["Predefined Type"]); + document.getElementById("add-cost-schedule-form").remove(); }); - addCostSchedule(data.name, data["Predefined Type"]); - form.remove(); - }); }); } @@ -1012,19 +989,20 @@ export class CostUI { } static Form({ id, name, icon = "fa-solid fa-file", shouldHide = false }) { - let form; if (document.getElementById(id)) { - form = document.getElementById(id); - } else { - form = document.createElement("form"); - form.id = id; - form.classList.add("floating-form"); - form.style.position = "absolute"; - form.style.top = "50%"; - form.style.left = "50%"; - form.style.transform = "translate(-50%, -50%)"; + const formContainer = document + .getElementById(id) + .querySelector(".form-container"); + formContainer.innerHTML = ""; + return formContainer; } - + const form = document.createElement("form"); + form.id = id; + form.classList.add("floating-form"); + form.style.position = "absolute"; + form.style.top = "50%"; + form.style.left = "50%"; + form.style.transform = "translate(-50%, -50%)"; const header = CostUI.createHeader(name, icon); let closeButton; if (shouldHide) { @@ -1035,8 +1013,12 @@ export class CostUI { form.appendChild(header); form.appendChild(closeButton); CostUI.makeFormDraggable(form); + + const formContainer = document.createElement("div"); + formContainer.classList.add("form-container"); + form.appendChild(formContainer); document.body.appendChild(form); - return form; + return formContainer; } static makeFormDraggable(form) { let pos1 = 0, @@ -1154,7 +1136,6 @@ export class CostUI { Object.entries(qto).forEach(([key, value]) => { if (key !== "id") { const cell = document.createElement("td"); - // check if value is a number cell.textContent = parseFloat(value).toFixed(2); row.appendChild(cell); } @@ -1254,7 +1235,7 @@ export class CostUI { }); } - subtotalRow.style.fontWeight = "bold"; + subtotalRow.classList.add("subtotal-row"); return subtotalRow; } @@ -1489,9 +1470,6 @@ export class CostUI { } static addSettingsMenu() { - if (document.getElementById("settings-menu")) { - return document.getElementById("settings-menu"); - } const settingsMenu = CostUI.Form({ id: "settings-menu", name: "Settings", @@ -1503,14 +1481,7 @@ export class CostUI { const tableFontSize = CostUI.createFontSizePicker(); settingsMenu.appendChild(picker); settingsMenu.appendChild(tableFontSize); - - settingsMenu.style.display = "none"; - const settingsButton = document.getElementById("settings-button"); - settingsButton.addEventListener("click", function () { - settingsMenu.style.display = "block"; - }); - - // Apply saved settings on page load + document.getElementById("settings-menu").style.display = "none"; CostUI.applySavedSettings(); } @@ -1570,7 +1541,6 @@ export class CostUI { } static applySavedSettings() { - console.log("Applying saved settings"); const savedFontSize = localStorage.getItem("tableFontSize"); if (savedFontSize) { CostUI.applyFontSizeToAllTables(savedFontSize); @@ -1599,7 +1569,7 @@ export class CostUI { const button = document.createElement("button"); button.classList.add("action-button", ...icon.split(" ")); - button.dataset.tooltip = text; // Use dataset to set the tooltip attribute + button.dataset.tooltip = text; button.addEventListener("click", () => callback(button)); @@ -1641,20 +1611,30 @@ export class CostUI { return document.getElementById("settings-menu"); } - static toggleSettingsMenu(button) { + static toggleSettingsMenu() { const settingsMenu = CostUI.getSettingsMenu(); - const isHidden = settingsMenu.style.display === "none"; - - if (isHidden) { + if (settingsMenu.style.display === "none") { settingsMenu.style.display = "block"; - button.classList.remove("fa-gear"); - button.classList.add("fa-times"); - button.dataset.tooltip = "Close Settings"; } else { settingsMenu.style.display = "none"; - button.classList.remove("fa-times"); - button.classList.add("fa-gear"); - button.dataset.tooltip = "Open Settings"; } } + + static createRibbon() { + CostUI.addSettingsMenu(); + CostUI.addRibbonButton({ + text: "Hide Schedules", + icon: "fa-regular fa-eye-slash", + callback: (button) => { + CostUI.toggleSchedulesContainer(button); + }, + }); + CostUI.addRibbonButton({ + text: "Settings", + icon: "fas fa-cog", + callback: () => { + CostUI.toggleSettingsMenu(); + }, + }); + } } diff --git a/src/bonsai/bonsai/bim/data/webui/templates/costing.html b/src/bonsai/bonsai/bim/data/webui/templates/costing.html index cdc6d3947c..3e607757af 100644 --- a/src/bonsai/bonsai/bim/data/webui/templates/costing.html +++ b/src/bonsai/bonsai/bim/data/webui/templates/costing.html @@ -75,9 +75,6 @@ -