mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-26 02:07:36 +00:00
enable displaying schedule of rates - web ui ref #5369
This commit is contained in:
@@ -11,6 +11,7 @@ export class CostUI {
|
|||||||
table ? table.parentElement.remove() : null;
|
table ? table.parentElement.remove() : null;
|
||||||
}
|
}
|
||||||
static createCostTable({ costSchedule, currency, callbacks }) {
|
static createCostTable({ costSchedule, currency, callbacks }) {
|
||||||
|
const isScheduleOfRates = costSchedule.PredefinedType === "SCHEDULEOFRATES";
|
||||||
let tableWrapper;
|
let tableWrapper;
|
||||||
const id = costSchedule.id;
|
const id = costSchedule.id;
|
||||||
if (CostUI.isCostScheduleLoaded(id)) {
|
if (CostUI.isCostScheduleLoaded(id)) {
|
||||||
@@ -50,6 +51,11 @@ export class CostUI {
|
|||||||
"Total Cost (" + currency + ")",
|
"Total Cost (" + currency + ")",
|
||||||
"Actions",
|
"Actions",
|
||||||
];
|
];
|
||||||
|
if (isScheduleOfRates) {
|
||||||
|
columnHeaders.splice(2, 1);
|
||||||
|
columnHeaders[3] = "Rate (" + currency + ")";
|
||||||
|
columnHeaders[4] = "Total Rate (" + currency + ")";
|
||||||
|
}
|
||||||
const thead = document.createElement("thead");
|
const thead = document.createElement("thead");
|
||||||
const tr = document.createElement("tr");
|
const tr = document.createElement("tr");
|
||||||
thead.appendChild(tr);
|
thead.appendChild(tr);
|
||||||
@@ -80,7 +86,7 @@ export class CostUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static deleteCostItem(costItemId) {
|
static deleteCostItem(costItemId) {
|
||||||
const costItemRow = document.getElementById(costItemId);
|
const costItemRow = CostUI.getCostItemRow(costItemId);
|
||||||
let expandedState = JSON.parse(localStorage.getItem("expandedState")) || {};
|
let expandedState = JSON.parse(localStorage.getItem("expandedState")) || {};
|
||||||
expandedState = CostUI.deleteCostItemRow(costItemRow, expandedState);
|
expandedState = CostUI.deleteCostItemRow(costItemRow, expandedState);
|
||||||
localStorage.setItem("expandedState", JSON.stringify(expandedState));
|
localStorage.setItem("expandedState", JSON.stringify(expandedState));
|
||||||
@@ -149,18 +155,6 @@ export class CostUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (deleteCostItemButton && !deleteCostItemButton.hasListener) {
|
|
||||||
// deleteCostItemButton.addEventListener("click", function () {
|
|
||||||
// const targetRow = document.getElementById("context-menu").targetRow;
|
|
||||||
// if (targetRow) {
|
|
||||||
// const costItemId = parseInt(targetRow.getAttribute("id"));
|
|
||||||
// CostUI.deleteCostItem(costItemId, callbacks.deleteCostItem);
|
|
||||||
// }
|
|
||||||
// document.getElementById("context-menu").style.display = "none";
|
|
||||||
// });
|
|
||||||
// deleteCostItemButton.hasListener = true;
|
|
||||||
// }
|
|
||||||
|
|
||||||
handleButtonClick(deleteCostItemButton, callbacks.deleteCostItem);
|
handleButtonClick(deleteCostItemButton, callbacks.deleteCostItem);
|
||||||
handleButtonClick(duplicateButton, callbacks.duplicateCostItem);
|
handleButtonClick(duplicateButton, callbacks.duplicateCostItem);
|
||||||
handleButtonClick(getSelectedProducts, callbacks.enableEditingQuantities);
|
handleButtonClick(getSelectedProducts, callbacks.enableEditingQuantities);
|
||||||
@@ -187,10 +181,13 @@ export class CostUI {
|
|||||||
const columnIndex = Array.from(targetRow.children).indexOf(
|
const columnIndex = Array.from(targetRow.children).indexOf(
|
||||||
targetCell
|
targetCell
|
||||||
);
|
);
|
||||||
|
const tableId = targetRow.parentElement.parentElement.id;
|
||||||
const costItemId = parseInt(targetRow.getAttribute("id"));
|
const costItemId = parseInt(targetRow.getAttribute("id"));
|
||||||
const columnName = getColumnNames("cost-items")[columnIndex];
|
const columnName = getColumnNames(tableId)[columnIndex];
|
||||||
|
if (
|
||||||
if (columnName.includes("Cost") && !columnName.includes("Total")) {
|
(columnName.includes("Cost") || columnName.includes("Rate")) &&
|
||||||
|
!columnName.includes("Total")
|
||||||
|
) {
|
||||||
callbacks.enableEditingCostValues
|
callbacks.enableEditingCostValues
|
||||||
? callbacks.enableEditingCostValues(costItemId)
|
? callbacks.enableEditingCostValues(costItemId)
|
||||||
: null;
|
: null;
|
||||||
@@ -374,47 +371,51 @@ export class CostUI {
|
|||||||
addSummaryCostItemButton.textContent = "Add Summary Cost Item";
|
addSummaryCostItemButton.textContent = "Add Summary Cost Item";
|
||||||
addSummaryCostItemButton.addEventListener("click", function () {
|
addSummaryCostItemButton.addEventListener("click", function () {
|
||||||
callbacks.addSummaryCostItem
|
callbacks.addSummaryCostItem
|
||||||
? callbacks.addSummaryCostItem(costScheduleId)
|
? callbacks.addSummaryCostItem(costSchedule.id)
|
||||||
: null;
|
: null;
|
||||||
});
|
});
|
||||||
td.appendChild(addSummaryCostItemButton);
|
td.appendChild(addSummaryCostItemButton);
|
||||||
addSummaryCostItemButton.classList.add("action-button");
|
addSummaryCostItemButton.classList.add("action-button");
|
||||||
} else {
|
} else {
|
||||||
CostUI.createCostTree(
|
CostUI.createCostTree({
|
||||||
costSchedule["cost_items"],
|
costItems: costSchedule["cost_items"],
|
||||||
tbody,
|
container: tbody,
|
||||||
0,
|
nestingLevel: 0,
|
||||||
null,
|
parentID: null,
|
||||||
callbacks
|
callbacks: callbacks,
|
||||||
);
|
isScheduleOfRates: costSchedule.PredefinedType === "SCHEDULEOFRATES",
|
||||||
|
});
|
||||||
CostUI.applyExpandedState();
|
CostUI.applyExpandedState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static createCostTree(
|
static createCostTree({
|
||||||
costItems,
|
costItems,
|
||||||
container,
|
container,
|
||||||
nestingLevel = 0,
|
nestingLevel,
|
||||||
parentID = null,
|
parentID,
|
||||||
callbacks = {}
|
callbacks,
|
||||||
) {
|
isScheduleOfRates = false,
|
||||||
|
}) {
|
||||||
costItems.forEach((costItem) => {
|
costItems.forEach((costItem) => {
|
||||||
const row = CostUI.addCostItemRow(
|
const row = CostUI.addCostItemRow(
|
||||||
costItem,
|
costItem,
|
||||||
nestingLevel,
|
nestingLevel,
|
||||||
parentID,
|
parentID,
|
||||||
|
isScheduleOfRates,
|
||||||
callbacks
|
callbacks
|
||||||
);
|
);
|
||||||
container.appendChild(row);
|
container.appendChild(row);
|
||||||
|
|
||||||
if (costItem.IsNestedBy && costItem.IsNestedBy.length > 0) {
|
if (costItem.IsNestedBy && costItem.IsNestedBy.length > 0) {
|
||||||
CostUI.createCostTree(
|
CostUI.createCostTree({
|
||||||
costItem.IsNestedBy,
|
costItems: costItem.IsNestedBy,
|
||||||
container,
|
container: container,
|
||||||
nestingLevel + 1,
|
nestingLevel: nestingLevel + 1,
|
||||||
costItem.id,
|
parentID: costItem.id,
|
||||||
callbacks
|
isScheduleOfRates: isScheduleOfRates,
|
||||||
);
|
callbacks: callbacks,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -429,18 +430,32 @@ export class CostUI {
|
|||||||
.replace(/,/g, " ");
|
.replace(/,/g, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
static addCostItemRow(costItem, nestingLevel, parentID, callbacks = {}) {
|
static addCostItemRow(
|
||||||
|
costItem,
|
||||||
|
nestingLevel,
|
||||||
|
parentID,
|
||||||
|
isScheduleOfRates,
|
||||||
|
callbacks = {}
|
||||||
|
) {
|
||||||
const totalQuantity = costItem.TotalCostQuantity
|
const totalQuantity = costItem.TotalCostQuantity
|
||||||
? CostUI.format_number(costItem.TotalCostQuantity)
|
? CostUI.format_number(costItem.TotalCostQuantity)
|
||||||
: "-";
|
: "-";
|
||||||
const appliedValue = costItem.TotalAppliedValue
|
let appliedValue = costItem.TotalAppliedValue
|
||||||
? CostUI.format_number(costItem.TotalAppliedValue)
|
? CostUI.format_number(costItem.TotalAppliedValue)
|
||||||
: "-";
|
: "-";
|
||||||
|
const unitBasisValue = costItem.UnitBasisValueComponent
|
||||||
|
? CostUI.format_number(costItem.UnitBasisValueComponent)
|
||||||
|
: null;
|
||||||
|
if (isScheduleOfRates && unitBasisValue) {
|
||||||
|
appliedValue = appliedValue + " / " + unitBasisValue;
|
||||||
|
}
|
||||||
const row = CostUI.createCostItemRow(costItem, nestingLevel, parentID);
|
const row = CostUI.createCostItemRow(costItem, nestingLevel, parentID);
|
||||||
const identification = costItem.Identification
|
const identification = costItem.Identification
|
||||||
? costItem.Identification
|
? costItem.Identification
|
||||||
: "XXX";
|
: "XXX";
|
||||||
const idCell = CostUI.createTableCell(identification);
|
const idCell = CostUI.createTableCell(identification);
|
||||||
|
row.appendChild(idCell);
|
||||||
|
|
||||||
const expandButton = CostUI.createExpandButton(costItem);
|
const expandButton = CostUI.createExpandButton(costItem);
|
||||||
const nameCell = CostUI.createNameCell(
|
const nameCell = CostUI.createNameCell(
|
||||||
costItem,
|
costItem,
|
||||||
@@ -448,33 +463,43 @@ export class CostUI {
|
|||||||
expandButton,
|
expandButton,
|
||||||
callbacks
|
callbacks
|
||||||
);
|
);
|
||||||
const totalCostQuantityCell = CostUI.createTableCell(totalQuantity);
|
row.appendChild(nameCell);
|
||||||
totalCostQuantityCell.classList.add("clickable-cell");
|
|
||||||
const unitSymbolCell = CostUI.createTableCell(costItem.UnitSymbol);
|
if (isScheduleOfRates) {
|
||||||
|
const unitBasisUnitSymbol = costItem.UnitBasisUnitSymbol
|
||||||
|
? costItem.UnitBasisUnitSymbol
|
||||||
|
: "-";
|
||||||
|
const unitBasisUnitSymbolCell =
|
||||||
|
CostUI.createTableCell(unitBasisUnitSymbol);
|
||||||
|
row.appendChild(unitBasisUnitSymbolCell);
|
||||||
|
} else {
|
||||||
|
const totalCostQuantityCell = CostUI.createTableCell(totalQuantity);
|
||||||
|
row.appendChild(totalCostQuantityCell);
|
||||||
|
totalCostQuantityCell.classList.add("clickable-cell");
|
||||||
|
const unitSymbolCell = CostUI.createTableCell(costItem.UnitSymbol);
|
||||||
|
row.appendChild(unitSymbolCell);
|
||||||
|
}
|
||||||
|
|
||||||
const totalAppliedValueCell = CostUI.createCostCell(appliedValue);
|
const totalAppliedValueCell = CostUI.createCostCell(appliedValue);
|
||||||
totalAppliedValueCell.classList.add("clickable-cell");
|
totalAppliedValueCell.classList.add("clickable-cell");
|
||||||
|
row.appendChild(totalAppliedValueCell);
|
||||||
|
|
||||||
const totalCostCell = CostUI.createTotalCostCell(
|
const totalCostCell = CostUI.createTotalCostCell(
|
||||||
costItem,
|
costItem,
|
||||||
|
isScheduleOfRates,
|
||||||
callbacks.addSumCostValue
|
callbacks.addSumCostValue
|
||||||
);
|
);
|
||||||
const actionsCell = CostUI.costItemActions(costItem, callbacks);
|
|
||||||
|
|
||||||
actionsCell.classList.add("actions-column");
|
|
||||||
|
|
||||||
row.appendChild(idCell);
|
|
||||||
row.appendChild(nameCell);
|
|
||||||
row.appendChild(totalCostQuantityCell);
|
|
||||||
row.appendChild(unitSymbolCell);
|
|
||||||
row.appendChild(totalAppliedValueCell);
|
|
||||||
row.appendChild(totalCostCell);
|
row.appendChild(totalCostCell);
|
||||||
|
|
||||||
|
const actionsCell = CostUI.costItemActions(costItem, callbacks);
|
||||||
|
actionsCell.classList.add("actions-column");
|
||||||
row.appendChild(actionsCell);
|
row.appendChild(actionsCell);
|
||||||
|
|
||||||
row.get_id = function () {
|
row.get_id = function () {
|
||||||
return this.getAttribute("id");
|
return this.getAttribute("id");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
row.isRate = isScheduleOfRates;
|
||||||
row.get_parent = function () {
|
row.get_parent = function () {
|
||||||
const parentId = this.getAttribute("parent-id");
|
const parentId = this.getAttribute("parent-id");
|
||||||
return parentId ? document.getElementById(parentId) : null;
|
return parentId ? document.getElementById(parentId) : null;
|
||||||
@@ -657,10 +682,13 @@ export class CostUI {
|
|||||||
return CostUI.createTableCell(appliedValue);
|
return CostUI.createTableCell(appliedValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
static createTotalCostCell(costItem, callback) {
|
static createTotalCostCell(costItem, isScheduleOfRates, callback) {
|
||||||
const totalCostCell = document.createElement("td");
|
const totalCostCell = document.createElement("td");
|
||||||
const totalCost = CostUI.format_number(costItem.TotalCost);
|
const totalCost = CostUI.format_number(costItem.TotalCost);
|
||||||
totalCostCell.textContent = totalCost;
|
totalCostCell.textContent = totalCost;
|
||||||
|
if (isScheduleOfRates) {
|
||||||
|
return totalCostCell;
|
||||||
|
}
|
||||||
if (costItem.IsSum) {
|
if (costItem.IsSum) {
|
||||||
totalCostCell.textContent = totalCost + " *";
|
totalCostCell.textContent = totalCost + " *";
|
||||||
} else if (!costItem.TotalCost) {
|
} else if (!costItem.TotalCost) {
|
||||||
@@ -835,9 +863,13 @@ export class CostUI {
|
|||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getCostItemRow(costItemId) {
|
||||||
|
return document.getElementById(costItemId);
|
||||||
|
}
|
||||||
|
|
||||||
static getRowNameCell(costItemId) {
|
static getRowNameCell(costItemId) {
|
||||||
return document.getElementById(costItemId)
|
return CostUI.getCostItemRow(costItemId)
|
||||||
? document.getElementById(costItemId).querySelector("td input")
|
? CostUI.getCostItemRow(costItemId).querySelector("td input")
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,6 +881,10 @@ export class CostUI {
|
|||||||
|
|
||||||
static createCostValuesForm({ costItemId, costValues, callbacks }) {
|
static createCostValuesForm({ costItemId, costValues, callbacks }) {
|
||||||
const formId = "cost-values-form-" + costItemId;
|
const formId = "cost-values-form-" + costItemId;
|
||||||
|
|
||||||
|
const costItemRow = CostUI.getCostItemRow(costItemId);
|
||||||
|
const isRate = costItemRow.isRate;
|
||||||
|
|
||||||
let existingForm = document.getElementById(formId);
|
let existingForm = document.getElementById(formId);
|
||||||
if (existingForm) {
|
if (existingForm) {
|
||||||
existingForm.remove();
|
existingForm.remove();
|
||||||
@@ -861,22 +897,41 @@ export class CostUI {
|
|||||||
id: formId,
|
id: formId,
|
||||||
name: formName,
|
name: formName,
|
||||||
});
|
});
|
||||||
|
let headers;
|
||||||
|
if (isRate) {
|
||||||
|
headers = [
|
||||||
|
"Type",
|
||||||
|
"Category",
|
||||||
|
"Value",
|
||||||
|
"Unit Symbol",
|
||||||
|
"Unit Component",
|
||||||
|
"",
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
headers = ["Type", "Category", "Value", ""];
|
||||||
|
}
|
||||||
|
|
||||||
const { tableContainer, table } = CostUI.addTable({
|
const { tableContainer, table } = CostUI.addTable({
|
||||||
headers: ["Type", "Category", "Value", ""],
|
headers: headers,
|
||||||
className: "cost-values-table",
|
className: "cost-values-table",
|
||||||
id: "cost-values-table-" + costItemId,
|
id: "cost-values-table-" + costItemId,
|
||||||
});
|
});
|
||||||
|
|
||||||
costValues.forEach((costValue) => {
|
costValues.forEach((costValue) => {
|
||||||
const tr = CostUI.createCostvaluesRow(costItemId, costValue, callbacks);
|
costValue.isRate = isRate;
|
||||||
|
const tr = CostUI.createCostvaluesRow({
|
||||||
|
costItemId,
|
||||||
|
costValue,
|
||||||
|
costValueCallbacks: callbacks,
|
||||||
|
});
|
||||||
table.appendChild(tr);
|
table.appendChild(tr);
|
||||||
});
|
});
|
||||||
|
|
||||||
const addButton = CostUI.createAddCostValueButton(costItemId, callbacks);
|
|
||||||
|
|
||||||
form.appendChild(tableContainer);
|
form.appendChild(tableContainer);
|
||||||
form.appendChild(addButton);
|
if (!isRate) {
|
||||||
|
//TODO: IMPLEMENT ADDING COST VALUES FOR COST RATES
|
||||||
|
const addButton = CostUI.createAddCostValueButton(costItemId, callbacks);
|
||||||
|
form.appendChild(addButton);
|
||||||
|
}
|
||||||
return form;
|
return form;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -889,17 +944,35 @@ export class CostUI {
|
|||||||
if (!table) {
|
if (!table) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const tr = CostUI.createCostvaluesRow(
|
const costItemRow = CostUI.getCostItemRow(costItemId);
|
||||||
costItemId,
|
const isRate = costItemRow.isRate;
|
||||||
{
|
let newData;
|
||||||
|
if (isRate) {
|
||||||
|
newData = {
|
||||||
category: "",
|
category: "",
|
||||||
name: "",
|
name: "",
|
||||||
applied_value: 0,
|
applied_value: 0,
|
||||||
id: costValueId,
|
id: costValueId,
|
||||||
parent: costItemId,
|
parent: costItemId,
|
||||||
},
|
unit_data: {
|
||||||
costValueCallbacks
|
unit_symbol: "",
|
||||||
);
|
value_component: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
newData = {
|
||||||
|
category: "",
|
||||||
|
name: "",
|
||||||
|
applied_value: 0,
|
||||||
|
id: costValueId,
|
||||||
|
parent: costItemId,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const tr = CostUI.createCostvaluesRow({
|
||||||
|
costItemId,
|
||||||
|
costValue: newData,
|
||||||
|
costValueCallbacks,
|
||||||
|
});
|
||||||
table.appendChild(tr);
|
table.appendChild(tr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -933,35 +1006,54 @@ export class CostUI {
|
|||||||
return { tableContainer: div, table: table };
|
return { tableContainer: div, table: table };
|
||||||
}
|
}
|
||||||
|
|
||||||
static createCostvaluesRow(costItemId, costValue, costValueCallbacks) {
|
static createCostvaluesRow({ costItemId, costValue, costValueCallbacks }) {
|
||||||
function cleanLabel(value) {
|
|
||||||
return value.replace(/[^0-9.]/g, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (document.getElementById(costValue.id)) {
|
if (document.getElementById(costValue.id)) {
|
||||||
return document.getElementById(costValue.id);
|
return document.getElementById(costValue.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tr = document.createElement("tr");
|
const tr = document.createElement("tr");
|
||||||
tr.isCostValue = true;
|
|
||||||
tr.parent = costItemId;
|
tr.parent = costItemId;
|
||||||
tr.id = costValue.id;
|
tr.id = costValue.id;
|
||||||
|
|
||||||
let costType = "FIXED";
|
const costType = CostUI.determineCostType(costValue);
|
||||||
if (costValue.category === "*") {
|
const { dropdown, typeCell } = CostUI.createTypeCell(
|
||||||
costType = "SUM";
|
tr,
|
||||||
} else if (costValue.category && costValue.category !== "*") {
|
costType,
|
||||||
costType = "CATEGORY";
|
costItemId,
|
||||||
} else if (costValue.applied_value) {
|
costValue,
|
||||||
costType = "FIXED";
|
costValueCallbacks
|
||||||
|
);
|
||||||
|
tr.appendChild(typeCell);
|
||||||
|
|
||||||
|
const categoryCell = CostUI.createTableInput(
|
||||||
|
"text",
|
||||||
|
"category",
|
||||||
|
costValue.category
|
||||||
|
);
|
||||||
|
tr.appendChild(categoryCell);
|
||||||
|
|
||||||
|
const value = CostUI.determineValue(costValue);
|
||||||
|
const valueCell1 = CostUI.createTableInput("number", "value", value);
|
||||||
|
tr.appendChild(valueCell1);
|
||||||
|
let unitSymbolCell;
|
||||||
|
let unitComponentCell;
|
||||||
|
if (costValue.isRate) {
|
||||||
|
unitSymbolCell = CostUI.Text(costValue.unit_data.unit_symbol); //TODO CostUI.createTableInput("text", "unit_symbol", costValue.unit_data.unit_symbol);
|
||||||
|
tr.appendChild(unitSymbolCell);
|
||||||
|
unitComponentCell = CostUI.createTableInput(
|
||||||
|
"number",
|
||||||
|
"unit_value_component",
|
||||||
|
costValue.unit_data.value_component
|
||||||
|
);
|
||||||
|
tr.appendChild(unitComponentCell);
|
||||||
}
|
}
|
||||||
const options = ["FIXED", "CATEGORY", "SUM"];
|
|
||||||
const typeCell = document.createElement("td");
|
CostUI.addValueChangeListeners(
|
||||||
const dropdown = CostUI.createTableDropdown({
|
tr,
|
||||||
name: "type",
|
costItemId,
|
||||||
options: options,
|
costValue,
|
||||||
defaultValue: costType,
|
costValueCallbacks
|
||||||
});
|
);
|
||||||
typeCell.appendChild(dropdown);
|
|
||||||
dropdown.addEventListener("change", function () {
|
dropdown.addEventListener("change", function () {
|
||||||
const selectedType = this.value;
|
const selectedType = this.value;
|
||||||
CostUI.updateRowBasedOnType(selectedType, categoryCell, valueCell1);
|
CostUI.updateRowBasedOnType(selectedType, categoryCell, valueCell1);
|
||||||
@@ -986,62 +1078,139 @@ export class CostUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
tr.appendChild(typeCell);
|
|
||||||
|
|
||||||
const categoryCell = CostUI.createTableInput(
|
const deleteCell = CostUI.createDeleteCell(
|
||||||
"text",
|
costItemId,
|
||||||
"category",
|
costValue,
|
||||||
costValue.category
|
costValueCallbacks,
|
||||||
|
tr
|
||||||
);
|
);
|
||||||
tr.appendChild(categoryCell);
|
tr.appendChild(deleteCell);
|
||||||
|
|
||||||
let value;
|
CostUI.updateRowBasedOnType(costType, categoryCell, valueCell1);
|
||||||
|
return tr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static determineCostType(costValue) {
|
||||||
|
if (costValue.category === "*") {
|
||||||
|
return "SUM";
|
||||||
|
} else if (costValue.category && costValue.category !== "*") {
|
||||||
|
return "CATEGORY";
|
||||||
|
} else if (costValue.applied_value) {
|
||||||
|
return "FIXED";
|
||||||
|
}
|
||||||
|
return "FIXED";
|
||||||
|
}
|
||||||
|
|
||||||
|
static createTypeCell(costType, costItemId, costValue, costValueCallbacks) {
|
||||||
|
const options = ["FIXED", "CATEGORY", "SUM"];
|
||||||
|
const typeCell = document.createElement("td");
|
||||||
|
const dropdown = CostUI.createTableDropdown({
|
||||||
|
name: "type",
|
||||||
|
options: options,
|
||||||
|
defaultValue: costType,
|
||||||
|
});
|
||||||
|
typeCell.appendChild(dropdown);
|
||||||
|
|
||||||
|
return { dropdown, typeCell };
|
||||||
|
}
|
||||||
|
|
||||||
|
static determineValue(costValue) {
|
||||||
|
function cleanLabel(value) {
|
||||||
|
return value.replace(/[^0-9.]/g, "");
|
||||||
|
}
|
||||||
|
|
||||||
if (costValue.category === "*") {
|
if (costValue.category === "*") {
|
||||||
value = cleanLabel(costValue.label);
|
return cleanLabel(costValue.label);
|
||||||
} else {
|
} else {
|
||||||
value = costValue.applied_value;
|
return costValue.applied_value;
|
||||||
}
|
}
|
||||||
const valueCell1 = CostUI.createTableInput("number", "value", value);
|
}
|
||||||
tr.appendChild(valueCell1);
|
|
||||||
|
|
||||||
const inputValue = valueCell1.querySelector("input");
|
static getCostValueData({
|
||||||
|
typeCell,
|
||||||
|
categoryCell,
|
||||||
|
valueCell1,
|
||||||
|
componentCell,
|
||||||
|
}) {
|
||||||
|
const costType = typeCell.value;
|
||||||
|
const costCategory = categoryCell ? categoryCell.value : null;
|
||||||
|
const appliedValue = parseFloat(valueCell1.value);
|
||||||
|
const unitBasisValue = componentCell
|
||||||
|
? parseFloat(componentCell.value)
|
||||||
|
: null;
|
||||||
|
return { costType, costCategory, appliedValue, unitBasisValue };
|
||||||
|
}
|
||||||
|
|
||||||
|
static addValueChangeListeners(
|
||||||
|
tr,
|
||||||
|
costItemId,
|
||||||
|
costValue,
|
||||||
|
costValueCallbacks
|
||||||
|
) {
|
||||||
function handleCostValueChange(costItemId) {
|
function handleCostValueChange(costItemId) {
|
||||||
const costValueData = {
|
let costValueData = CostUI.getCostValueData({
|
||||||
costType: typeCell.querySelector("select").value,
|
typeCell,
|
||||||
costCategory: categoryCell.querySelector("input").value,
|
categoryCell,
|
||||||
appliedValue: parseFloat(this.value),
|
valueCell1,
|
||||||
|
componentCell,
|
||||||
|
});
|
||||||
|
costValueData = {
|
||||||
|
...costValueData,
|
||||||
id: costValue.id,
|
id: costValue.id,
|
||||||
costItemId: costItemId,
|
costItemId: costItemId,
|
||||||
};
|
};
|
||||||
|
if (costValueData.unitBasisValue) {
|
||||||
|
costValueData.unitComponent = costValue.unit_data.unit_component;
|
||||||
|
}
|
||||||
if (costValueCallbacks.editCostValues) {
|
if (costValueCallbacks.editCostValues) {
|
||||||
costValueCallbacks.editCostValues(costItemId, [costValueData]);
|
costValueCallbacks.editCostValues(costItemId, [costValueData]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inputValue.addEventListener(
|
const typeCell = tr.querySelector("td select[name='type']");
|
||||||
|
const categoryCell = tr.querySelector("td input[name='category']");
|
||||||
|
const valueCell1 = tr.querySelector("td input[name='value']");
|
||||||
|
const componentCell = tr.querySelector(
|
||||||
|
"td input[name='unit_value_component']"
|
||||||
|
);
|
||||||
|
valueCell1.addEventListener(
|
||||||
"change",
|
"change",
|
||||||
handleCostValueChange.bind(inputValue, costItemId)
|
handleCostValueChange.bind(valueCell1, costItemId)
|
||||||
);
|
);
|
||||||
|
|
||||||
inputValue.addEventListener("keydown", function (event) {
|
valueCell1.addEventListener("keydown", function (event) {
|
||||||
if (event.key === "Enter") {
|
if (event.key === "Enter") {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
handleCostValueChange.call(this, costItemId);
|
handleCostValueChange.call(this, costItemId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (componentCell) {
|
||||||
|
componentCell.addEventListener(
|
||||||
|
"change",
|
||||||
|
handleCostValueChange.bind(componentCell, costItemId)
|
||||||
|
);
|
||||||
|
componentCell.addEventListener("keydown", function (event) {
|
||||||
|
if (event.key === "Enter") {
|
||||||
|
event.preventDefault();
|
||||||
|
handleCostValueChange.call(this, costItemId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static createDeleteCell(costItemId, costValue, costValueCallbacks, tr) {
|
||||||
const deleteCell = document.createElement("td");
|
const deleteCell = document.createElement("td");
|
||||||
tr.appendChild(deleteCell);
|
const deleteButton = CostUI.createButton("Delete", "fa-solid fa-trash");
|
||||||
const dleteButton = CostUI.createButton("Delete", "fa-solid fa-trash");
|
|
||||||
dleteButton.addEventListener("click", function () {
|
deleteButton.addEventListener("click", function () {
|
||||||
costValueCallbacks.deleteCostValue(costItemId, costValue.id);
|
costValueCallbacks.deleteCostValue(costItemId, costValue.id);
|
||||||
tr.remove();
|
tr.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
deleteCell.appendChild(dleteButton);
|
deleteCell.appendChild(deleteButton);
|
||||||
CostUI.updateRowBasedOnType(costType, categoryCell, valueCell1);
|
return deleteCell;
|
||||||
return tr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static updateRowBasedOnType(type, categoryCell, valueCell1) {
|
static updateRowBasedOnType(type, categoryCell, valueCell1) {
|
||||||
@@ -1126,7 +1295,7 @@ export class CostUI {
|
|||||||
const costItemId = form.id.split("-").pop();
|
const costItemId = form.id.split("-").pop();
|
||||||
CostUI.unhighlightElement(costItemId);
|
CostUI.unhighlightElement(costItemId);
|
||||||
};
|
};
|
||||||
closeButton = CostUI.createCloseButton(callback); // Pass the function reference without invoking it
|
closeButton = CostUI.createCloseButton(callback);
|
||||||
}
|
}
|
||||||
form.appendChild(header);
|
form.appendChild(header);
|
||||||
form.appendChild(closeButton);
|
form.appendChild(closeButton);
|
||||||
|
|||||||
@@ -391,8 +391,8 @@ class Web(bonsai.core.tool.Web):
|
|||||||
cls.load_cost_schedule_web_ui(cost_schedule)
|
cls.load_cost_schedule_web_ui(cost_schedule)
|
||||||
if operator_data["type"] == "deleteCostItem":
|
if operator_data["type"] == "deleteCostItem":
|
||||||
cost_item = tool.Ifc.get().by_id(operator_data["costItemId"])
|
cost_item = tool.Ifc.get().by_id(operator_data["costItemId"])
|
||||||
tool.Ifc.run("cost.remove_cost_item", cost_item=cost_item)
|
|
||||||
cost_schedule = tool.Cost.get_cost_schedule(cost_item=cost_item)
|
cost_schedule = tool.Cost.get_cost_schedule(cost_item=cost_item)
|
||||||
|
tool.Ifc.run("cost.remove_cost_item", cost_item=cost_item)
|
||||||
cls.load_cost_schedule_web_ui(cost_schedule)
|
cls.load_cost_schedule_web_ui(cost_schedule)
|
||||||
if operator_data["type"] == "duplicateCostItem":
|
if operator_data["type"] == "duplicateCostItem":
|
||||||
cost_item = tool.Ifc.get().by_id(operator_data["costItemId"])
|
cost_item = tool.Ifc.get().by_id(operator_data["costItemId"])
|
||||||
@@ -439,6 +439,7 @@ class Web(bonsai.core.tool.Web):
|
|||||||
cost_schedule = tool.Cost.get_cost_schedule(cost_item=cost_item)
|
cost_schedule = tool.Cost.get_cost_schedule(cost_item=cost_item)
|
||||||
for value_data in operator_data["costValues"] or []:
|
for value_data in operator_data["costValues"] or []:
|
||||||
value = ifc_file.by_id(value_data["id"])
|
value = ifc_file.by_id(value_data["id"])
|
||||||
|
attributes = {}
|
||||||
if value_data["costType"] == "FIXED":
|
if value_data["costType"] == "FIXED":
|
||||||
attributes = {"AppliedValue": value_data["appliedValue"], "Category": None}
|
attributes = {"AppliedValue": value_data["appliedValue"], "Category": None}
|
||||||
elif value_data["costType"] == "CATEGORY":
|
elif value_data["costType"] == "CATEGORY":
|
||||||
@@ -448,6 +449,11 @@ class Web(bonsai.core.tool.Web):
|
|||||||
}
|
}
|
||||||
elif value_data["costType"] == "SUM":
|
elif value_data["costType"] == "SUM":
|
||||||
attributes = {"Category": "*"}
|
attributes = {"Category": "*"}
|
||||||
|
if value_data["unitBasisValue"]:
|
||||||
|
attributes["UnitBasis"] = {
|
||||||
|
"ValueComponent": value_data["unitBasisValue"],
|
||||||
|
"UnitComponent": ifc_file.by_id(value_data["unitComponent"]),
|
||||||
|
}
|
||||||
ifcopenshell.api.cost.edit_cost_value(file=ifc_file, cost_value=value, attributes=attributes)
|
ifcopenshell.api.cost.edit_cost_value(file=ifc_file, cost_value=value, attributes=attributes)
|
||||||
cls.load_cost_schedule_web_ui(cost_schedule)
|
cls.load_cost_schedule_web_ui(cost_schedule)
|
||||||
if operator_data["type"] == "addProductAssignments":
|
if operator_data["type"] == "addProductAssignments":
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from typing import Optional, Union, Literal, Generator, Any
|
|||||||
import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper
|
import ifcopenshell.ifcopenshell_wrapper as ifcopenshell_wrapper
|
||||||
from ifcopenshell.util.doc import get_predefined_type_doc
|
from ifcopenshell.util.doc import get_predefined_type_doc
|
||||||
from ifcopenshell.util.element import get_psets
|
from ifcopenshell.util.element import get_psets
|
||||||
|
from ifcopenshell.util.unit import get_unit_symbol
|
||||||
arithmetic_operator_symbols = {"ADD": "+", "DIVIDE": "/", "MULTIPLY": "*", "SUBTRACT": "-"}
|
arithmetic_operator_symbols = {"ADD": "+", "DIVIDE": "/", "MULTIPLY": "*", "SUBTRACT": "-"}
|
||||||
symbol_arithmetic_operators = {"+": "ADD", "/": "DIVIDE", "*": "MULTIPLY", "-": "SUBTRACT"}
|
symbol_arithmetic_operators = {"+": "ADD", "/": "DIVIDE", "*": "MULTIPLY", "-": "SUBTRACT"}
|
||||||
FILTER_BY_TYPE = Literal["PRODUCT", "RESOURCE", "PROCESS"]
|
FILTER_BY_TYPE = Literal["PRODUCT", "RESOURCE", "PROCESS"]
|
||||||
@@ -255,6 +255,13 @@ def get_cost_values(cost_item: ifcopenshell.entity_instance) -> list[dict[str, s
|
|||||||
for cost_value in cost_item.CostValues or []:
|
for cost_value in cost_item.CostValues or []:
|
||||||
label = "{0:.2f}".format(calculate_applied_value(cost_item, cost_value))
|
label = "{0:.2f}".format(calculate_applied_value(cost_item, cost_value))
|
||||||
label += " = {}".format(serialise_cost_value(cost_value))
|
label += " = {}".format(serialise_cost_value(cost_value))
|
||||||
|
unit_data = {"value_component": None, "unit_component": None, "unit_symbol": ""}
|
||||||
|
if cost_value.UnitBasis:
|
||||||
|
data = cost_value.UnitBasis.get_info()
|
||||||
|
unit_data["value_component"] = data["ValueComponent"].wrappedValue
|
||||||
|
unit_data["unit_component"] = data["UnitComponent"].id()
|
||||||
|
unit_data["unit_symbol"] = get_unit_symbol(cost_value.UnitBasis.UnitComponent)
|
||||||
|
|
||||||
results.append(
|
results.append(
|
||||||
{
|
{
|
||||||
"id": cost_value.id(),
|
"id": cost_value.id(),
|
||||||
@@ -264,9 +271,9 @@ def get_cost_values(cost_item: ifcopenshell.entity_instance) -> list[dict[str, s
|
|||||||
"applied_value": (
|
"applied_value": (
|
||||||
get_primitive_applied_value(cost_value.AppliedValue) if cost_value.AppliedValue else None
|
get_primitive_applied_value(cost_value.AppliedValue) if cost_value.AppliedValue else None
|
||||||
),
|
),
|
||||||
|
"unit_data": unit_data,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
print(results)
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user