General source code refactoring
This commit is contained in:
176
src/features/opportunities/table.js
Normal file
176
src/features/opportunities/table.js
Normal file
@@ -0,0 +1,176 @@
|
||||
function createOpportunitiesTable({
|
||||
ACCOUNT_DETAIL_URL,
|
||||
OPPORTUNITIES_COLUMNS,
|
||||
OPPORTUNITIES_TABLE_ID,
|
||||
OPPORTUNITY_DETAIL_URL,
|
||||
createCloudConsumptionButton,
|
||||
createCopyOpportunityButton,
|
||||
createDetailLink,
|
||||
createProductsCountButton,
|
||||
createProductsDetailRow,
|
||||
createStageBadge,
|
||||
createStatusBadge,
|
||||
displayOpportunityValue,
|
||||
getNestedValue,
|
||||
getSortedOpportunities,
|
||||
opportunitiesTableState,
|
||||
productsContentState,
|
||||
renderCustomerFilter,
|
||||
renderOwnerFilter,
|
||||
renderStageDashboard,
|
||||
resetCustomerFilter,
|
||||
resetOwnerFilter,
|
||||
environment
|
||||
}) {
|
||||
const { document } = environment;
|
||||
function setOpportunitiesTableState(nextState) {
|
||||
if (nextState.status === "ready" && Array.isArray(nextState.items)) {
|
||||
resetCustomerFilter(nextState.items);
|
||||
resetOwnerFilter(nextState.items);
|
||||
}
|
||||
|
||||
opportunitiesTableState.opportunitiesTableState = {
|
||||
...opportunitiesTableState.opportunitiesTableState,
|
||||
...nextState,
|
||||
sortKey: nextState.items ? "" : opportunitiesTableState.opportunitiesTableState.sortKey,
|
||||
sortDirection: nextState.items ? "ascending" : opportunitiesTableState.opportunitiesTableState.sortDirection
|
||||
};
|
||||
renderOpportunitiesTable();
|
||||
renderCustomerFilter();
|
||||
renderOwnerFilter();
|
||||
}
|
||||
|
||||
function renderOpportunitiesTable() {
|
||||
const table = document.getElementById(OPPORTUNITIES_TABLE_ID);
|
||||
|
||||
if (!table) {
|
||||
return;
|
||||
}
|
||||
|
||||
table.textContent = "";
|
||||
table.setAttribute("aria-busy", opportunitiesTableState.opportunitiesTableState.status === "loading" ? "true" : "false");
|
||||
|
||||
const caption = document.createElement("caption");
|
||||
caption.className = "opportunities-extension-visually-hidden";
|
||||
caption.textContent = "Opportunities";
|
||||
|
||||
const tableHead = document.createElement("thead");
|
||||
const headerRow = document.createElement("tr");
|
||||
|
||||
OPPORTUNITIES_COLUMNS.forEach((column) => {
|
||||
const header = document.createElement("th");
|
||||
const isSorted = opportunitiesTableState.opportunitiesTableState.sortKey === column.key;
|
||||
header.scope = "col";
|
||||
|
||||
if (column.sortable === false) {
|
||||
const label = document.createElement("span");
|
||||
label.className = "opportunities-extension-table-header-label";
|
||||
label.textContent = column.label;
|
||||
header.append(label);
|
||||
} else {
|
||||
header.setAttribute("aria-sort", isSorted ? opportunitiesTableState.opportunitiesTableState.sortDirection : "none");
|
||||
|
||||
const sortButton = document.createElement("button");
|
||||
sortButton.type = "button";
|
||||
sortButton.className = "opportunities-extension-sort-button";
|
||||
sortButton.setAttribute("data-sort-direction", isSorted ? opportunitiesTableState.opportunitiesTableState.sortDirection : "none");
|
||||
sortButton.setAttribute("aria-label", `Sort by ${column.label}${isSorted ? `, ${opportunitiesTableState.opportunitiesTableState.sortDirection}` : ""}`);
|
||||
sortButton.textContent = column.label;
|
||||
sortButton.addEventListener("click", () => sortOpportunitiesBy(column.key));
|
||||
header.append(sortButton);
|
||||
}
|
||||
|
||||
headerRow.append(header);
|
||||
});
|
||||
|
||||
tableHead.append(headerRow);
|
||||
|
||||
const tableBody = document.createElement("tbody");
|
||||
const items = getSortedOpportunities();
|
||||
renderStageDashboard(items);
|
||||
|
||||
if (opportunitiesTableState.opportunitiesTableState.status === "loading" || opportunitiesTableState.opportunitiesTableState.status === "error" || opportunitiesTableState.opportunitiesTableState.status === "empty" || (opportunitiesTableState.opportunitiesTableState.status === "ready" && items.length === 0)) {
|
||||
const row = document.createElement("tr");
|
||||
const cell = document.createElement("td");
|
||||
cell.className = "opportunities-extension-table-status";
|
||||
cell.colSpan = OPPORTUNITIES_COLUMNS.length;
|
||||
cell.textContent = opportunitiesTableState.opportunitiesTableState.message || "No opportunities found.";
|
||||
row.append(cell);
|
||||
tableBody.append(row);
|
||||
} else {
|
||||
items.forEach((item) => {
|
||||
const row = document.createElement("tr");
|
||||
|
||||
OPPORTUNITIES_COLUMNS.forEach((column) => {
|
||||
const cell = document.createElement("td");
|
||||
|
||||
if (column.key === "stage") {
|
||||
cell.append(createStageBadge(column.display(item)));
|
||||
} else if (column.key === "status") {
|
||||
cell.append(createStatusBadge(column.display(item)));
|
||||
} else if (column.key === "actions") {
|
||||
const actionsContent = document.createElement("span");
|
||||
actionsContent.className = "opportunities-extension-actions-content";
|
||||
const productsResult = productsContentState.opptyProductsByNumber.get(String(item.OptyNumber));
|
||||
|
||||
if (productsResult) {
|
||||
actionsContent.append(createProductsCountButton(item.OptyNumber, productsResult));
|
||||
}
|
||||
|
||||
actionsContent.append(createCloudConsumptionButton(item));
|
||||
cell.append(actionsContent);
|
||||
} else if (column.key === "name" || column.key === "optyNumber") {
|
||||
const opportunityLink = createDetailLink(
|
||||
column.display(item),
|
||||
item.OptyNumber ? `${OPPORTUNITY_DETAIL_URL}${encodeURIComponent(item.OptyNumber)}` : ""
|
||||
);
|
||||
|
||||
if (column.key === "name" && item.OptyNumber) {
|
||||
const nameCellContent = document.createElement("span");
|
||||
nameCellContent.className = "opportunities-extension-name-content";
|
||||
nameCellContent.append(opportunityLink);
|
||||
cell.append(nameCellContent);
|
||||
} else if (column.key === "optyNumber" && item.OptyNumber) {
|
||||
const opportunityCellContent = document.createElement("span");
|
||||
opportunityCellContent.className = "opportunities-extension-opty-number-content";
|
||||
opportunityCellContent.append(opportunityLink, createCopyOpportunityButton(item.OptyNumber));
|
||||
cell.append(opportunityCellContent);
|
||||
} else {
|
||||
cell.append(opportunityLink);
|
||||
}
|
||||
} else if (column.key === "customer") {
|
||||
cell.append(createDetailLink(
|
||||
column.display(item),
|
||||
getNestedValue(item, ["CustomerAccount", "PartyId"])
|
||||
? `${ACCOUNT_DETAIL_URL}${encodeURIComponent(getNestedValue(item, ["CustomerAccount", "PartyId"]))}`
|
||||
: ""
|
||||
));
|
||||
} else {
|
||||
cell.textContent = displayOpportunityValue(column, item);
|
||||
}
|
||||
|
||||
row.append(cell);
|
||||
});
|
||||
|
||||
tableBody.append(row);
|
||||
|
||||
if (item.OptyNumber && productsContentState.expandedProductOptyNumbers.has(String(item.OptyNumber))) {
|
||||
tableBody.append(createProductsDetailRow(item));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
table.append(caption, tableHead, tableBody);
|
||||
}
|
||||
|
||||
function sortOpportunitiesBy(key) {
|
||||
const isSameColumn = opportunitiesTableState.opportunitiesTableState.sortKey === key;
|
||||
opportunitiesTableState.opportunitiesTableState.sortKey = key;
|
||||
opportunitiesTableState.opportunitiesTableState.sortDirection = isSameColumn && opportunitiesTableState.opportunitiesTableState.sortDirection === "ascending"
|
||||
? "descending"
|
||||
: "ascending";
|
||||
renderOpportunitiesTable();
|
||||
}
|
||||
|
||||
return { setOpportunitiesTableState, renderOpportunitiesTable, sortOpportunitiesBy };
|
||||
}
|
||||
Reference in New Issue
Block a user