Visual enhancements for dark mode, along with search functionality for service requests and installed base
This commit is contained in:
@@ -32,6 +32,12 @@
|
||||
}
|
||||
.opportunities-extension-install-base-status[data-status="ACTIVE"] { color: #17693a; background: #e1f1e5; }
|
||||
.opportunities-extension-install-base-status[data-status="UNSUPPORTED"] { color: #855300; background: #fff0d6; }
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-content,
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-table,
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-table th,
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-table td { color: #f6f4f2; }
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-message { color: #c9c5c1; }
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-message[role="alert"] { color: #ffb4ab; }
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-table th { background: #353331; }
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-table th,
|
||||
.opportunities-extension-modal[data-theme="dark"] .opportunities-extension-install-base-table td { border-color: #484541; }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function createInstallBaseView({ MODAL_ID, createCloseIcon, formatOracleResponseDate, environment }) {
|
||||
function createInstallBaseView({ MODAL_ID, createCloseIcon, formatOracleResponseDate, createSearch, environment }) {
|
||||
const { document } = environment;
|
||||
let active = null;
|
||||
const columns = [
|
||||
@@ -23,6 +23,16 @@ function createInstallBaseView({ MODAL_ID, createCloseIcon, formatOracleResponse
|
||||
if (previous.trigger?.isConnected) previous.trigger.focus();
|
||||
return true;
|
||||
}
|
||||
function formatValue(value, type) {
|
||||
if (value === null || value === undefined || value === "") return "-";
|
||||
if (type === "date") return formatOracleResponseDate(value);
|
||||
if ((type === "amount" || type === "quantity") && Number.isFinite(Number(value))) {
|
||||
return new Intl.NumberFormat("en-US", {
|
||||
minimumFractionDigits: type === "amount" ? 2 : 0, maximumFractionDigits: type === "amount" ? 2 : 4
|
||||
}).format(Number(value));
|
||||
}
|
||||
return String(value).trim();
|
||||
}
|
||||
function createTable(items, loading = false) {
|
||||
const table = element("table", "opportunities-extension-install-base-table");
|
||||
table.setAttribute("aria-label", "Installed base items");
|
||||
@@ -49,14 +59,7 @@ function createInstallBaseView({ MODAL_ID, createCloseIcon, formatOracleResponse
|
||||
cell.append(bar);
|
||||
} else {
|
||||
const value = item[key];
|
||||
const missing = value === null || value === undefined || value === "";
|
||||
let text = missing ? "-" : String(value).trim();
|
||||
if (!missing && type === "date") text = formatOracleResponseDate(value);
|
||||
if (!missing && (type === "amount" || type === "quantity") && Number.isFinite(Number(value))) {
|
||||
text = new Intl.NumberFormat("en-US", {
|
||||
minimumFractionDigits: type === "amount" ? 2 : 0, maximumFractionDigits: type === "amount" ? 2 : 4
|
||||
}).format(Number(value));
|
||||
}
|
||||
const text = formatValue(value, type);
|
||||
if (type === "status") {
|
||||
const badge = element("span", "opportunities-extension-install-base-status", text);
|
||||
badge.dataset.status = text.toUpperCase();
|
||||
@@ -99,27 +102,44 @@ function createInstallBaseView({ MODAL_ID, createCloseIcon, formatOracleResponse
|
||||
content.setAttribute("aria-label", "Installed base results");
|
||||
const status = element("p", "opportunities-extension-install-base-message", "Loading installed base...");
|
||||
status.setAttribute("role", "status");
|
||||
let loadedItems = [], loaded = false, failure = "";
|
||||
const search = createSearch({ label: "Search installed base", onSearch: renderResults,
|
||||
getValues: item => columns.flatMap(([key, , type]) => [item[key], formatValue(item[key], type)]) });
|
||||
const toolbar = element("div", "opportunities-extension-customer-table-toolbar");
|
||||
toolbar.append(search.input);
|
||||
content.append(status, createTable([], true));
|
||||
dialog.append(header, content);
|
||||
dialog.append(header, toolbar, content);
|
||||
modal.append(dialog);
|
||||
overlay.append(modal);
|
||||
active = { modal, trigger };
|
||||
modal.addEventListener("keydown", event => {
|
||||
if (event.key === "Tab") {
|
||||
event.preventDefault();
|
||||
(document.activeElement === close ? content : close).focus();
|
||||
const controls = [close, search.input, content];
|
||||
const index = controls.indexOf(document.activeElement);
|
||||
controls[(index + (event.shiftKey ? -1 : 1) + controls.length) % controls.length].focus();
|
||||
}
|
||||
});
|
||||
close.focus();
|
||||
function renderResults() {
|
||||
if (!loaded || active?.modal !== modal || overlay.hidden) return;
|
||||
const items = failure ? [] : search.filter(loadedItems);
|
||||
content.textContent = "";
|
||||
status.textContent = failure || (loadedItems.length
|
||||
? `${items.length} of ${loadedItems.length} installed base items${items.length ? "" : ". No matching records."}`
|
||||
: "No installed base items found for this customer.");
|
||||
status.setAttribute("role", failure ? "alert" : "status");
|
||||
content.append(status);
|
||||
if (!failure && items.length) content.append(createTable(items));
|
||||
content.scrollTop = 0;
|
||||
}
|
||||
return { render(items, error = "") {
|
||||
// A closed or replaced dialog must never receive a late response.
|
||||
if (active?.modal !== modal || overlay.hidden) return;
|
||||
modal.setAttribute("aria-busy", "false");
|
||||
content.textContent = "";
|
||||
status.textContent = error || (items.length ? `${items.length} installed base items` : "No installed base items found for this customer.");
|
||||
status.setAttribute("role", error ? "alert" : "status");
|
||||
content.append(status);
|
||||
if (!error && items.length) content.append(createTable(items));
|
||||
loadedItems = items; failure = error; loaded = true;
|
||||
search.reset();
|
||||
renderResults();
|
||||
} };
|
||||
}
|
||||
return { openInstallBaseModal, closeInstallBaseModal, createTable };
|
||||
|
||||
Reference in New Issue
Block a user