web ui cost module:

- double click cost cell to enable editing cost values.
- fix tables' height / scrollbar behaviour
This commit is contained in:
myoualid
2024-09-09 01:08:29 +01:00
parent 2d7614622f
commit 98ab5399f2
6 changed files with 108 additions and 124 deletions
@@ -3,6 +3,8 @@
gap: 10px;
margin-bottom: 20px;
border: 1px solid #444;
width: 100%;
justify-content: center;
}
.ribbon-bar .action-button {
@@ -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;
}
@@ -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;
}
@@ -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"]) {
@@ -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();
},
});
}
}
@@ -75,9 +75,6 @@
<button id="toggle-theme" onclick="toggleTheme()">
<i class="fas fa-moon"></i>
</button>
<button id="settings-button">
<i class="fa-solid fa-gear"></i>
</button>
<div id="connected-list-div">
<button id="show-connected-button" onclick="toggleClientList()">
Connected Blenders: