This commit is contained in:
@@ -240,6 +240,7 @@
|
||||
function renderReport(id,title,payload){const el=$(id);if(!el)return;const rows=reportRows(payload);const obj=payload?.summary||payload?.counts||payload||{};const fallback=Object.entries(obj).filter(([,v])=>typeof v==='number').slice(0,8);const entries=rows.length?rows.map(r=>[r.label||r.name||r.stage||r.outcome||r.type||'Metric',r.count??r.total??r.value??0]):fallback;if(!entries.length){el.innerHTML=`<div class="panel-heading"><h3>${title}</h3></div><p class="crm-empty">No ${title.toLowerCase()} data returned.</p>`;return;}el.innerHTML=`<div class="panel-heading"><div><p class="eyebrow">REPORT</p><h3>${title}</h3></div><span class="small-label">API summary</span></div><div class="report-rows">${entries.map(([label,value])=>`<div><span>${esc(crmLabel(label))}</span><strong>${esc(value)}</strong></div>`).join('')}</div><p class="report-note">Tenant-scoped API results. Loading, unavailable, and empty are distinct states.</p>`;}
|
||||
async function loadReports(){[['pipelineReport','pipeline report'],['outcomesReport','outcomes report'],['activityReport','activity report']].forEach(([id,title])=>{const el=$(id);if(el)el.innerHTML=`<div class="detail-loading">Loading ${title}…</div>`;});try{const [pipeline,outcomes,activity]=await Promise.all([jsonRequest('/api/v1/reports/pipeline'),jsonRequest('/api/v1/reports/outcomes'),jsonRequest('/api/v1/reports/activity')]);renderReport('pipelineReport','Pipeline',pipeline);renderReport('outcomesReport','Outcomes',outcomes);renderReport('activityReport','Activity',activity);}catch(error){if(error.message!=='unauthorized')[['pipelineReport','pipeline'],['outcomesReport','outcomes'],['activityReport','activity']].forEach(([id,label])=>{const el=$(id);if(el)el.innerHTML=`<div class="detail-error" role="alert"><strong>Unable to load ${label} report</strong><p>${esc(error.message)}</p></div>`;});}}
|
||||
|
||||
let jobs = [], selectedJobId = null, jobPollTimer = null;
|
||||
const jobStatuses = ['queued','running','succeeded','failed','cancelled'];
|
||||
const jobRole = () => String(currentUser?.role || currentUser?.roles?.[0] || '').toLowerCase();
|
||||
const canManageJobs = () => ['admin','owner','operator','manager'].includes(jobRole()) || Boolean(currentUser?.permissions?.includes?.('jobs:manage'));
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
"healthz"
|
||||
],
|
||||
"integrity": {
|
||||
"config.js": "sha256-6d49ab0825feb44111d960cd8d676e005c4f1a06271265277c0d00458236a441",
|
||||
"app.js": "sha256-450c2041d7a87465e5471e5b96faf9d3c27e973d49cbc9a5bdc19fd42a3ec339",
|
||||
"config.js": "sha256-26e69a9af2abda4ac16d5b7c7eed5d69ad578c7f386af5fa62b42475a7318ea6",
|
||||
"app.js": "sha256-7a2a8c1275f97d4485a2c833cbdb205ac163c5b7f4a52c131484fabfa6a6e29d",
|
||||
"styles.css": "sha256-c1b192a15de735819fbb7ec3cddc9574808ae366a8255b4f690a7a40bc21caba",
|
||||
"index.html": "sha256-b8665be623e6e093e9a2d7532276289ebaeaaa0a905263ac3bbd9a3c595f4120",
|
||||
"index.html": "sha256-83f010d3c68cef9b1f3a5ae8a50960156b52ef342944ef906804266e76220227",
|
||||
"health.html": "sha256-c352a6f37aa24628cfc8d5709a70ff2d94181d192ed5fe00916cca9378a61d81",
|
||||
"error.html": "sha256-f3cc28d2dfc9e8af112d0257c6ee47b9e9146e5da8590a754dd589bf43702aaf",
|
||||
"healthz": "sha256-dc51b8c96c2d745df3bd5590d990230a482fd247123599548e0632fdbf97fc22"
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/* Public, non-secret runtime configuration. Replace this file at deploy time if needed. */
|
||||
window.__PROSPECT_CONFIG__ = Object.freeze({
|
||||
apiBase: '',
|
||||
assetVersion: 'phase-36'
|
||||
assetVersion: 'phase-40'
|
||||
});
|
||||
|
||||
+2
-2
@@ -135,7 +135,7 @@
|
||||
<div class="merge-dialog" id="mergeDialog" hidden role="dialog" aria-modal="true" aria-labelledby="mergeDialogTitle">
|
||||
<div class="merge-dialog-card"><div class="panel-heading"><div><p class="eyebrow">REVIEW REQUIRED</p><h2 id="mergeDialogTitle">Confirm merge</h2></div><button class="icon-button" id="cancelMergeBtn" type="button" aria-label="Close merge confirmation">×</button></div><p id="mergeDialogCopy"></p><div class="merge-warning"><strong>This action is reversible.</strong> The merge will be recorded in history and can be reversed later.</div><p id="mergeDialogMessage" class="form-message" role="alert" aria-live="polite"></p><div class="merge-dialog-actions"><button class="button ghost" id="cancelMergeBtnSecondary" type="button">Cancel</button><button class="button primary" id="confirmMergeBtn" type="button">Confirm merge</button></div></div>
|
||||
</div>
|
||||
<script src="config.js?v=phase-39"></script>
|
||||
<script src="app.js?v=phase-39"></script>
|
||||
<script src="config.js?v=phase-40"></script>
|
||||
<script src="app.js?v=phase-40"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user