| Line 2068... |
Line 2068... |
| 2068 |
<div class="brand">
|
2068 |
<div class="brand">
|
| 2069 |
<div class="crumb"><a href="/indent/today_po_rbm">← Today PO / RBM</a> · Sales · Indent</div>
|
2069 |
<div class="crumb"><a href="/indent/today_po_rbm">← Today PO / RBM</a> · Sales · Indent</div>
|
| 2070 |
<h1>RBM DRR Dashboard <span class="live"><i></i>Live</span></h1>
|
2070 |
<h1>RBM DRR Dashboard <span class="live"><i></i>Live</span></h1>
|
| 2071 |
</div>
|
2071 |
</div>
|
| 2072 |
<div class="hd-right">
|
2072 |
<div class="hd-right">
|
| - |
|
2073 |
<select id="rdrrTypeSelect" class="ctl" style="min-width:120px;height:38px;padding:8px 12px" title="Filter type">
|
| - |
|
2074 |
<option value="RBM" selected>RBM</option>
|
| - |
|
2075 |
<option value="SALES">Sales</option>
|
| - |
|
2076 |
</select>
|
| 2073 |
<select id="rdrrRbmFilter" class="ctl" style="min-width:220px;height:38px;padding:8px 12px">
|
2077 |
<select id="rdrrLevelSelect" class="ctl" style="min-width:140px;height:38px;padding:8px 12px;display:none"
|
| - |
|
2078 |
title="Sales level">
|
| - |
|
2079 |
<option value="">Select level</option>
|
| - |
|
2080 |
<option value="ASM">ASM (L1)</option>
|
| - |
|
2081 |
<option value="CM">CM (L2)</option>
|
| - |
|
2082 |
<option value="DM">DM (L3)</option>
|
| - |
|
2083 |
<option value="BM">BM (L4)</option>
|
| - |
|
2084 |
<option value="RSM">RSM (L5)</option>
|
| - |
|
2085 |
<option value="NSM">NSM (L6)</option>
|
| - |
|
2086 |
</select>
|
| - |
|
2087 |
<select id="rdrrPersonSelect" class="ctl" style="min-width:230px;height:38px;padding:8px 12px" title="Person">
|
| 2074 |
<option value="">All RBMs</option>
|
2088 |
<option value="">All RBMs</option>
|
| 2075 |
</select>
|
2089 |
</select>
|
| 2076 |
<input class="ctl" id="rdrrPeriod" type="text" placeholder="Select date range"/>
|
2090 |
<input class="ctl" id="rdrrPeriod" type="text" placeholder="Select date range"/>
|
| 2077 |
<button class="btn-r" id="rdrrApply">Apply</button>
|
2091 |
<button class="btn-r" id="rdrrApply">Apply</button>
|
| 2078 |
</div>
|
2092 |
</div>
|
| Line 2408... |
Line 2422... |
| 2408 |
if (p) {
|
2422 |
if (p) {
|
| 2409 |
startDate = p.startDate.format("YYYY-MM-DD");
|
2423 |
startDate = p.startDate.format("YYYY-MM-DD");
|
| 2410 |
endDate = p.endDate.format("YYYY-MM-DD");
|
2424 |
endDate = p.endDate.format("YYYY-MM-DD");
|
| 2411 |
}
|
2425 |
}
|
| 2412 |
load();
|
2426 |
load();
|
| - |
|
2427 |
// If a Sales filter is currently active, re-fetch its data for the new range.
|
| - |
|
2428 |
if (CURRENT_SALES_AUTH_ID) {
|
| - |
|
2429 |
$.ajax({
|
| - |
|
2430 |
url: "/rbm-drr/sales-data",
|
| - |
|
2431 |
type: "GET",
|
| - |
|
2432 |
data: {startDate: startDate, endDate: endDate},
|
| - |
|
2433 |
dataType: "json",
|
| - |
|
2434 |
success: function (payload) {
|
| - |
|
2435 |
SALES_PAYLOAD = payload;
|
| - |
|
2436 |
renderFiltered();
|
| - |
|
2437 |
},
|
| - |
|
2438 |
error: function () {
|
| - |
|
2439 |
SALES_PAYLOAD = {rows: []};
|
| - |
|
2440 |
renderFiltered();
|
| - |
|
2441 |
}
|
| - |
|
2442 |
});
|
| - |
|
2443 |
}
|
| 2413 |
});
|
2444 |
});
|
| 2414 |
|
2445 |
|
| 2415 |
function load() {
|
2446 |
function load() {
|
| 2416 |
$("#rdrrTableWrap").html('<div class="loading"><div class="spinner"></div>Loading…</div>');
|
2447 |
$("#rdrrTableWrap").html('<div class="loading"><div class="spinner"></div>Loading…</div>');
|
| 2417 |
$("#rdrrAgingWrap").html('<div class="loading"><div class="spinner"></div>Loading…</div>');
|
2448 |
$("#rdrrAgingWrap").html('<div class="loading"><div class="spinner"></div>Loading…</div>');
|
| Line 2575... |
Line 2606... |
| 2575 |
}
|
2606 |
}
|
| 2576 |
|
2607 |
|
| 2577 |
// Cached latest payload so the "Target Status by RBM" modal can render
|
2608 |
// Cached latest payload so the "Target Status by RBM" modal can render
|
| 2578 |
// without a re-fetch when the KPI card is clicked.
|
2609 |
// without a re-fetch when the KPI card is clicked.
|
| 2579 |
var LAST_PAYLOAD = null;
|
2610 |
var LAST_PAYLOAD = null;
|
| - |
|
2611 |
var SALES_PAYLOAD = null; // fetched on-demand from /rbm-drr/sales-data
|
| - |
|
2612 |
var CURRENT_SALES_AUTH_ID = null; // when set, renderFiltered() uses SALES_PAYLOAD
|
| - |
|
2613 |
// Set of RBM authIds allowed by the current filter. null = no filter (show all).
|
| 2580 |
var CURRENT_FILTER_AUTH_ID = ""; // "" = all RBMs
|
2614 |
var CURRENT_FILTER_AUTH_IDS = null;
|
| 2581 |
|
2615 |
|
| 2582 |
function render(data) {
|
2616 |
function render(data) {
|
| 2583 |
LAST_PAYLOAD = data;
|
2617 |
LAST_PAYLOAD = data;
|
| 2584 |
populateRbmFilter(data.rows || []);
|
- |
|
| 2585 |
renderFiltered();
|
2618 |
renderFiltered();
|
| 2586 |
}
|
2619 |
}
|
| 2587 |
|
2620 |
|
| 2588 |
// Build the dropdown options from the fetched rows (unique RBM names).
|
2621 |
// Renders KPIs + grid from the appropriate payload:
|
| 2589 |
// Preserves current selection if the RBM still exists in the new dataset.
|
2622 |
// - Sales filter active → SALES_PAYLOAD filtered to selected sales person (rows are sales × warehouse)
|
| 2590 |
function populateRbmFilter(rows) {
|
- |
|
| 2591 |
var seen = {};
|
- |
|
| 2592 |
var options = [];
|
- |
|
| 2593 |
rows.forEach(function (r) {
|
- |
|
| 2594 |
if (!seen[r.authId]) {
|
- |
|
| 2595 |
seen[r.authId] = true;
|
- |
|
| 2596 |
options.push({id: r.authId, name: r.rbmName});
|
- |
|
| 2597 |
}
|
- |
|
| 2598 |
});
|
- |
|
| 2599 |
options.sort(function (a, b) {
|
- |
|
| 2600 |
return (a.name || "").localeCompare(b.name || "");
|
- |
|
| 2601 |
});
|
- |
|
| 2602 |
var sel = $("#rdrrRbmFilter");
|
- |
|
| 2603 |
var prev = sel.val() || "";
|
- |
|
| 2604 |
var html = '<option value="">All RBMs (' + options.length + ')</option>';
|
- |
|
| 2605 |
options.forEach(function (o) {
|
- |
|
| 2606 |
html += '<option value="' + o.id + '">' + escapeHtml(o.name || "Unknown") + '</option>';
|
- |
|
| 2607 |
});
|
- |
|
| 2608 |
sel.html(html);
|
- |
|
| 2609 |
// Restore prior selection if still valid; otherwise reset.
|
- |
|
| 2610 |
if (prev && seen[prev]) sel.val(prev); else CURRENT_FILTER_AUTH_ID = "";
|
- |
|
| 2611 |
}
|
- |
|
| 2612 |
|
- |
|
| 2613 |
// Renders KPIs + grid from LAST_PAYLOAD filtered by CURRENT_FILTER_AUTH_ID.
|
2623 |
// - RBM filter or no filter → LAST_PAYLOAD filtered by CURRENT_FILTER_AUTH_IDS (rows are RBM × warehouse)
|
| 2614 |
function renderFiltered() {
|
2624 |
function renderFiltered() {
|
| - |
|
2625 |
if (CURRENT_SALES_AUTH_ID && SALES_PAYLOAD) {
|
| - |
|
2626 |
var salesRows = (SALES_PAYLOAD.rows || []).filter(function (r) {
|
| - |
|
2627 |
return String(r.salesAuthId) === String(CURRENT_SALES_AUTH_ID);
|
| - |
|
2628 |
}).map(function (r) {
|
| - |
|
2629 |
// Normalise sales row into the same shape the RBM grid renderer expects.
|
| - |
|
2630 |
return {
|
| - |
|
2631 |
authId: r.salesAuthId, warehouseId: r.warehouseId,
|
| - |
|
2632 |
rbmName: r.salesName + (r.role ? " (" + r.role + ")" : ""),
|
| - |
|
2633 |
warehouseName: r.warehouseName,
|
| - |
|
2634 |
totalAch: r.totalAch, totalTgt: r.totalTgt,
|
| - |
|
2635 |
hidAch: r.hidAch, hidTgt: r.hidTgt,
|
| - |
|
2636 |
fastAch: r.fastAch, fastTgt: r.fastTgt,
|
| - |
|
2637 |
runAch: r.runAch, runTgt: r.runTgt,
|
| - |
|
2638 |
slowAch: r.slowAch, slowTgt: r.slowTgt,
|
| - |
|
2639 |
otherAch: r.otherAch, otherTgt: r.otherTgt
|
| - |
|
2640 |
};
|
| - |
|
2641 |
});
|
| - |
|
2642 |
renderRowsAsGrid(salesRows, true);
|
| - |
|
2643 |
return;
|
| - |
|
2644 |
}
|
| 2615 |
if (!LAST_PAYLOAD) return;
|
2645 |
if (!LAST_PAYLOAD) return;
|
| 2616 |
var allRows = LAST_PAYLOAD.rows || [];
|
2646 |
var allRows = LAST_PAYLOAD.rows || [];
|
| 2617 |
var rows = CURRENT_FILTER_AUTH_ID
|
2647 |
var rows = CURRENT_FILTER_AUTH_IDS
|
| 2618 |
? allRows.filter(function (r) {
|
2648 |
? allRows.filter(function (r) {
|
| 2619 |
return String(r.authId) === String(CURRENT_FILTER_AUTH_ID);
|
2649 |
return CURRENT_FILTER_AUTH_IDS[String(r.authId)];
|
| 2620 |
})
|
2650 |
})
|
| 2621 |
: allRows;
|
2651 |
: allRows;
|
| - |
|
2652 |
renderRowsAsGrid(rows, false);
|
| - |
|
2653 |
}
|
| - |
|
2654 |
|
| - |
|
2655 |
// Extracted from renderFiltered() so both RBM-source and Sales-source paths share it.
|
| - |
|
2656 |
function renderRowsAsGrid(rows, isSalesView) {
|
| 2622 |
|
2657 |
|
| 2623 |
// Recompute totals from the filtered subset. Cheaper + correct vs using server totals.
|
2658 |
// Recompute totals from the filtered subset. Cheaper + correct vs using server totals.
|
| 2624 |
var t = {
|
2659 |
var t = {
|
| 2625 |
totalAch: 0, totalTgt: 0, hidAch: 0, hidTgt: 0, fastAch: 0, fastTgt: 0,
|
2660 |
totalAch: 0, totalTgt: 0, hidAch: 0, hidTgt: 0, fastAch: 0, fastTgt: 0,
|
| 2626 |
runAch: 0, runTgt: 0, slowAch: 0, slowTgt: 0, otherAch: 0, otherTgt: 0,
|
2661 |
runAch: 0, runTgt: 0, slowAch: 0, slowTgt: 0, otherAch: 0, otherTgt: 0,
|
| Line 2648... |
Line 2683... |
| 2648 |
$("#rdrrKpiPct").html(pk.cls === "na" ? '<span class="u">n/a</span>' :
|
2683 |
$("#rdrrKpiPct").html(pk.cls === "na" ? '<span class="u">n/a</span>' :
|
| 2649 |
'<span class="pct ' + pk.cls + '">' + pk.text + '</span>');
|
2684 |
'<span class="pct ' + pk.cls + '">' + pk.text + '</span>');
|
| 2650 |
$("#rdrrKpiTop").html((t.rbmsAtOrAbove100 || 0) + ' <span class="u">/ ' + (t.rbmRowCount || 0) + '</span>');
|
2685 |
$("#rdrrKpiTop").html((t.rbmsAtOrAbove100 || 0) + ' <span class="u">/ ' + (t.rbmRowCount || 0) + '</span>');
|
| 2651 |
|
2686 |
|
| 2652 |
if (rows.length === 0) {
|
2687 |
if (rows.length === 0) {
|
| - |
|
2688 |
var emptyMsg;
|
| - |
|
2689 |
if (isSalesView) {
|
| 2653 |
$("#rdrrTableWrap").html('<div class="empty"><div class="ei">📭</div>' +
|
2690 |
emptyMsg = 'No Sales target/achievement rows for this person in the range. Has the pushSalesTargets cron run today?';
|
| - |
|
2691 |
} else if (CURRENT_FILTER_AUTH_IDS) {
|
| 2654 |
(CURRENT_FILTER_AUTH_ID ? 'This RBM has no rows in the current range.' : 'No RBM rows in this range.') +
|
2692 |
emptyMsg = 'No RBM rows in this range for the selected filter.';
|
| 2655 |
'</div>');
|
2693 |
} else {
|
| - |
|
2694 |
emptyMsg = 'No RBM rows in this range.';
|
| - |
|
2695 |
}
|
| - |
|
2696 |
$("#rdrrTableWrap").html('<div class="empty"><div class="ei">📭</div>' + emptyMsg + '</div>');
|
| 2656 |
return;
|
2697 |
return;
|
| 2657 |
}
|
2698 |
}
|
| 2658 |
|
2699 |
|
| 2659 |
var buckets = [
|
2700 |
var buckets = [
|
| 2660 |
{key: "hid", label: "HID"},
|
2701 |
{key: "hid", label: "HID"},
|
| Line 2939... |
Line 2980... |
| 2939 |
|
2980 |
|
| 2940 |
function openStatusModal() {
|
2981 |
function openStatusModal() {
|
| 2941 |
if (!LAST_PAYLOAD) return;
|
2982 |
if (!LAST_PAYLOAD) return;
|
| 2942 |
// Respect the RBM filter so the modal matches what's on screen.
|
2983 |
// Respect the RBM filter so the modal matches what's on screen.
|
| 2943 |
var rows = (LAST_PAYLOAD.rows || []).filter(function (r) {
|
2984 |
var rows = (LAST_PAYLOAD.rows || []).filter(function (r) {
|
| 2944 |
return !CURRENT_FILTER_AUTH_ID || String(r.authId) === String(CURRENT_FILTER_AUTH_ID);
|
2985 |
return !CURRENT_FILTER_AUTH_IDS || CURRENT_FILTER_AUTH_IDS[String(r.authId)];
|
| 2945 |
});
|
2986 |
});
|
| 2946 |
var achieved = [], pending = [];
|
2987 |
var achieved = [], pending = [];
|
| 2947 |
rows.forEach(function (r) {
|
2988 |
rows.forEach(function (r) {
|
| 2948 |
if (!r.totalTgt || r.totalTgt <= 0) return;
|
2989 |
if (!r.totalTgt || r.totalTgt <= 0) return;
|
| 2949 |
var pct = (r.totalAch / r.totalTgt) * 100;
|
2990 |
var pct = (r.totalAch / r.totalTgt) * 100;
|
| Line 3210... |
Line 3251... |
| 3210 |
});
|
3251 |
});
|
| 3211 |
$("#rdrrCallDrawerBack").on("click", function (e) {
|
3252 |
$("#rdrrCallDrawerBack").on("click", function (e) {
|
| 3212 |
if (e.target === this) $(this).removeClass("show");
|
3253 |
if (e.target === this) $(this).removeClass("show");
|
| 3213 |
});
|
3254 |
});
|
| 3214 |
|
3255 |
|
| - |
|
3256 |
// ------------------------- cascading filter (Type → [Level] → Person) -------------------------
|
| - |
|
3257 |
// Flow:
|
| - |
|
3258 |
// Type = RBM → Person dropdown = all RBMs. Pick one to filter to that RBM.
|
| - |
|
3259 |
// Type = SALES → Level dropdown appears (ASM/CM/DM/BM/RSM/NSM). Pick a level
|
| - |
|
3260 |
// → Person dropdown = active people at that level. Pick a person
|
| - |
|
3261 |
// → fetches /rbm-drr/sales-data and shows that person's aggregated rows.
|
| - |
|
3262 |
// One backend call caches both the RBM list and the Sales list.
|
| - |
|
3263 |
var ALL_RBMS = []; // [{authId, name}, ...]
|
| - |
|
3264 |
var ALL_SALES_BY_ROLE = {}; // {ASM: [...], CM: [...], ...}
|
| - |
|
3265 |
|
| - |
|
3266 |
function loadFilterOptions() {
|
| - |
|
3267 |
$.ajax({
|
| - |
|
3268 |
url: "/rbm-drr/all-sales", type: "GET", dataType: "json",
|
| - |
|
3269 |
success: function (payload) {
|
| - |
|
3270 |
ALL_RBMS = (payload && payload.rbms) || [];
|
| - |
|
3271 |
ALL_SALES_BY_ROLE = {};
|
| - |
|
3272 |
((payload && payload.sales) || []).forEach(function (s) {
|
| - |
|
3273 |
(ALL_SALES_BY_ROLE[s.role] = ALL_SALES_BY_ROLE[s.role] || []).push(s);
|
| - |
|
3274 |
});
|
| - |
|
3275 |
repopulatePersonForCurrentType();
|
| - |
|
3276 |
}
|
| - |
|
3277 |
});
|
| - |
|
3278 |
}
|
| - |
|
3279 |
|
| 3215 |
// RBM filter — re-render KPIs + grid from the cached payload (no re-fetch).
|
3280 |
// Refill the Person dropdown based on current Type (+ Level if Sales).
|
| - |
|
3281 |
function repopulatePersonForCurrentType() {
|
| - |
|
3282 |
var type = $("#rdrrTypeSelect").val();
|
| - |
|
3283 |
var personSel = $("#rdrrPersonSelect");
|
| - |
|
3284 |
if (type === "RBM") {
|
| - |
|
3285 |
var html = '<option value="">All RBMs (' + ALL_RBMS.length + ')</option>';
|
| - |
|
3286 |
ALL_RBMS.forEach(function (r) {
|
| - |
|
3287 |
html += '<option value="' + r.authId + '">' + escapeHtml(r.name || "Unknown") + '</option>';
|
| - |
|
3288 |
});
|
| - |
|
3289 |
personSel.html(html).prop("disabled", false);
|
| - |
|
3290 |
return;
|
| - |
|
3291 |
}
|
| - |
|
3292 |
// SALES
|
| - |
|
3293 |
var level = $("#rdrrLevelSelect").val();
|
| - |
|
3294 |
if (!level) {
|
| - |
|
3295 |
personSel.html('<option value="">Pick a level first</option>').prop("disabled", true);
|
| - |
|
3296 |
return;
|
| - |
|
3297 |
}
|
| - |
|
3298 |
var list = ALL_SALES_BY_ROLE[level] || [];
|
| - |
|
3299 |
var salesHtml = '<option value="">All ' + escapeHtml(level) + 's (' + list.length + ')</option>';
|
| - |
|
3300 |
list.forEach(function (s) {
|
| - |
|
3301 |
salesHtml += '<option value="' + s.authId + '">' + escapeHtml(s.name || "Unknown") + '</option>';
|
| - |
|
3302 |
});
|
| - |
|
3303 |
personSel.html(salesHtml).prop("disabled", false);
|
| - |
|
3304 |
}
|
| - |
|
3305 |
|
| - |
|
3306 |
// Type toggles: show/hide Level; reset filter state; refresh Person options.
|
| 3216 |
$("#rdrrRbmFilter").on("change", function () {
|
3307 |
$("#rdrrTypeSelect").on("change", function () {
|
| - |
|
3308 |
var type = $(this).val();
|
| - |
|
3309 |
if (type === "SALES") {
|
| - |
|
3310 |
$("#rdrrLevelSelect").css("display", "").val("");
|
| - |
|
3311 |
} else {
|
| - |
|
3312 |
$("#rdrrLevelSelect").css("display", "none").val("");
|
| - |
|
3313 |
}
|
| - |
|
3314 |
// Clear all filter state whenever the type changes.
|
| - |
|
3315 |
CURRENT_FILTER_AUTH_IDS = null;
|
| - |
|
3316 |
CURRENT_SALES_AUTH_ID = null;
|
| - |
|
3317 |
SALES_PAYLOAD = null;
|
| - |
|
3318 |
repopulatePersonForCurrentType();
|
| - |
|
3319 |
renderFiltered();
|
| - |
|
3320 |
});
|
| - |
|
3321 |
|
| - |
|
3322 |
$("#rdrrLevelSelect").on("change", function () {
|
| - |
|
3323 |
// New level → clear Sales filter state and repopulate Person.
|
| 3217 |
CURRENT_FILTER_AUTH_ID = $(this).val() || "";
|
3324 |
CURRENT_FILTER_AUTH_IDS = null;
|
| - |
|
3325 |
CURRENT_SALES_AUTH_ID = null;
|
| - |
|
3326 |
SALES_PAYLOAD = null;
|
| - |
|
3327 |
repopulatePersonForCurrentType();
|
| 3218 |
renderFiltered();
|
3328 |
renderFiltered();
|
| 3219 |
});
|
3329 |
});
|
| 3220 |
|
3330 |
|
| - |
|
3331 |
$("#rdrrPersonSelect").on("change", function () {
|
| - |
|
3332 |
var authId = $(this).val();
|
| - |
|
3333 |
var type = $("#rdrrTypeSelect").val();
|
| - |
|
3334 |
|
| - |
|
3335 |
if (type === "RBM") {
|
| - |
|
3336 |
// RBM filter (single authId) — no server round trip needed.
|
| - |
|
3337 |
CURRENT_SALES_AUTH_ID = null;
|
| - |
|
3338 |
SALES_PAYLOAD = null;
|
| - |
|
3339 |
if (!authId) {
|
| - |
|
3340 |
CURRENT_FILTER_AUTH_IDS = null;
|
| - |
|
3341 |
} else {
|
| - |
|
3342 |
var single = {};
|
| - |
|
3343 |
single[String(authId)] = true;
|
| - |
|
3344 |
CURRENT_FILTER_AUTH_IDS = single;
|
| - |
|
3345 |
}
|
| - |
|
3346 |
renderFiltered();
|
| - |
|
3347 |
return;
|
| - |
|
3348 |
}
|
| - |
|
3349 |
|
| - |
|
3350 |
// SALES type
|
| - |
|
3351 |
CURRENT_FILTER_AUTH_IDS = null;
|
| - |
|
3352 |
if (!authId) {
|
| - |
|
3353 |
// "All <role>s" — no filter (show everyone in the DRR grid, RBM view).
|
| - |
|
3354 |
CURRENT_SALES_AUTH_ID = null;
|
| - |
|
3355 |
SALES_PAYLOAD = null;
|
| - |
|
3356 |
renderFiltered();
|
| - |
|
3357 |
return;
|
| - |
|
3358 |
}
|
| - |
|
3359 |
// Pick a specific Sales person → fetch that person's aggregated data.
|
| - |
|
3360 |
CURRENT_SALES_AUTH_ID = authId;
|
| - |
|
3361 |
$("#rdrrTableWrap").html('<div class="loading"><div class="spinner"></div>Loading…</div>');
|
| - |
|
3362 |
$.ajax({
|
| - |
|
3363 |
url: "/rbm-drr/sales-data", type: "GET",
|
| - |
|
3364 |
data: {startDate: startDate, endDate: endDate}, dataType: "json",
|
| - |
|
3365 |
success: function (payload) {
|
| - |
|
3366 |
SALES_PAYLOAD = payload;
|
| - |
|
3367 |
renderFiltered();
|
| - |
|
3368 |
},
|
| - |
|
3369 |
error: function () {
|
| - |
|
3370 |
SALES_PAYLOAD = {rows: []};
|
| - |
|
3371 |
renderFiltered();
|
| - |
|
3372 |
}
|
| - |
|
3373 |
});
|
| - |
|
3374 |
});
|
| - |
|
3375 |
|
| 3221 |
// initial load
|
3376 |
// initial load
|
| - |
|
3377 |
loadFilterOptions();
|
| 3222 |
load();
|
3378 |
load();
|
| 3223 |
loadPurchaseMilestones();
|
3379 |
loadPurchaseMilestones();
|
| 3224 |
loadPerformanceDashboard();
|
3380 |
loadPerformanceDashboard();
|
| 3225 |
loadCallTargetIframe();
|
3381 |
loadCallTargetIframe();
|
| 3226 |
})();
|
3382 |
})();
|