diff --git a/apps/web/app.js b/apps/web/app.js index bd4682f..3cf5925 100644 --- a/apps/web/app.js +++ b/apps/web/app.js @@ -329,5 +329,16 @@ ['sourceFilter','geographyFilter','categoryFilter','contactStatusFilter','scoreFilter','statusFilter','websiteClassFilter','pipelineFilter'].forEach(id=>$(id)?.addEventListener('change',()=>{page=1;loadData();})); $('interactionForm').addEventListener('submit',saveInteraction);$('suppressionForm').addEventListener('submit',addSuppression);$('aiProviderForm').addEventListener('submit',saveAiProviderSettings);$('aiProvider').addEventListener('change',updateAiProviderForm);$('aiProviderRefreshBtn').addEventListener('click',loadAiProviderSettings);$('testAiProviderBtn').addEventListener('click',testAiProviderConnection);$('crmRefreshBtn').addEventListener('click',()=>{loadCrmPipeline();loadInteractions(selectedId);});$('reportsRefreshBtn').addEventListener('click',loadReports);$('suppressionRefreshBtn').addEventListener('click',loadSuppressions);$('pipelineViewToggle').addEventListener('click',()=>{crmListMode=!crmListMode;$('pipelineViewToggle').textContent=crmListMode?'▦ Board view':'☷ List view';$('pipelineViewToggle').setAttribute('aria-pressed',String(crmListMode));renderPipeline();});$('pipelineBoard').addEventListener('click',e=>{const selectButton=e.target.closest?.('[data-crm-select]');if(selectButton){selectedId=Number(selectButton.dataset.crmSelect);selectProspect(selectedId);loadInteractions(selectedId);$('crmActivity').scrollIntoView({behavior:'smooth',block:'start'});}const stageButton=e.target.closest?.('[data-crm-save-stage]');if(stageButton)saveCrmStage(stageButton.dataset.crmSaveStage);if(e.target.id==='retryCrmBtn')loadCrmPipeline();if(e.target.id==='retryInteractionsBtn'&&selectedId)loadInteractions(selectedId);});$('suppressionState').addEventListener('change',e=>{const input=e.target.closest?.('[data-suppression-id]');if(input){if(input.checked)selectedSuppressionIds.add(String(input.dataset.suppressionId));else selectedSuppressionIds.delete(String(input.dataset.suppressionId));updateSuppressionSelection();}});$('suppressionState').addEventListener('click',e=>{const button=e.target.closest?.('[data-remove-suppression]');if(button)removeSuppression(button.dataset.removeSuppression);if(e.target.id==='retrySuppressionsBtn')loadSuppressions();});$('selectAllSuppressions').addEventListener('change',e=>{suppressions.forEach(item=>e.target.checked?selectedSuppressionIds.add(String(item.id)):selectedSuppressionIds.delete(String(item.id)));renderSuppressions();});$('bulkReviewSuppressionsBtn').addEventListener('click',bulkReviewSuppressions);$('discoveryWorkspace').addEventListener('click',e=>{const action=e.target.closest?.('[data-run-action]');if(action){const run=discoveryRuns.find(item=>String(item.id)===String(selectedDiscoveryRunId));discoveryAction(action.dataset.runAction,run);}}); $('aiProviderForm').addEventListener('submit',saveAiProviderSettings);$('aiProvider').addEventListener('change',updateAiProviderForm);$('aiProviderRefreshBtn').addEventListener('click',loadAiProviderSettings);$('testAiProviderBtn').addEventListener('click',testAiProviderConnection);$('crmRefreshBtn').addEventListener('click',()=>{loadCrmPipeline();loadInteractions(selectedId);});$('reportsRefreshBtn').addEventListener('click',loadReports);$('suppressionRefreshBtn').addEventListener('click',loadSuppressions);$('pipelineViewToggle').addEventListener('click',()=>{crmListMode=!crmListMode;$('pipelineViewToggle').textContent=crmListMode?'▦ Board view':'☷ List view';$('pipelineViewToggle').setAttribute('aria-pressed',String(crmListMode));renderPipeline();});$('pipelineBoard').addEventListener('click',e=>{const selectButton=e.target.closest?.('[data-crm-select]');if(selectButton){selectedId=Number(selectButton.dataset.crmSelect);selectProspect(selectedId);loadInteractions(selectedId);$('crmActivity').scrollIntoView({behavior:'smooth',block:'start'});}const stageButton=e.target.closest?.('[data-crm-save-stage]');if(stageButton)saveCrmStage(stageButton.dataset.crmSaveStage);if(e.target.id==='retryCrmBtn')loadCrmPipeline();if(e.target.id==='retryInteractionsBtn'&&selectedId)loadInteractions(selectedId);});$('suppressionState').addEventListener('change',e=>{const input=e.target.closest?.('[data-suppression-id]');if(input){if(input.checked)selectedSuppressionIds.add(String(input.dataset.suppressionId));else selectedSuppressionIds.delete(String(input.dataset.suppressionId));updateSuppressionSelection();}});$('suppressionState').addEventListener('click',e=>{const button=e.target.closest?.('[data-remove-suppression]');if(button)removeSuppression(button.dataset.removeSuppression);if(e.target.id==='retrySuppressionsBtn')loadSuppressions();});$('selectAllSuppressions').addEventListener('change',e=>{suppressions.forEach(item=>e.target.checked?selectedSuppressionIds.add(String(item.id)):selectedSuppressionIds.delete(String(item.id)));renderSuppressions();});$('bulkReviewSuppressionsBtn').addEventListener('click',bulkReviewSuppressions);$('outreachPolicyRefreshBtn').addEventListener('click',loadProviderPolicy); + const viewMap = {dashboard:'dashboard', explorer:'prospects', add:'add', discoveryWorkspace:'discovery', jobs:'jobs', sources:'sources', crmPipeline:'crm', crmActivity:'crm', crmReports:'crm', suppressionCenter:'settings', outreachSettings:'settings', aiProviderSettings:'settings', scoreRules:'dashboard'}; + function activateView(view) { document.body.dataset.view = view; document.querySelectorAll('.content > section').forEach(section => section.classList.toggle('view-active', viewMap[section.id] === view)); window.scrollTo({top:0, behavior:'smooth'}); } + document.body.dataset.view = 'dashboard'; + const sourceSetup = document.querySelector('.source-config-panel'); + if (sourceSetup) { + const badge = sourceSetup.querySelector('.small-label'); + const copy = sourceSetup.querySelector('.source-setup-copy'); + if (badge) badge.textContent = 'Public and operator-controlled sources'; + if (copy) copy.textContent = 'Register bounded public sources or operator-controlled imports. New sources start disabled and must be tested before use.'; + } + document.querySelectorAll('.sidebar nav a, [data-scroll]').forEach(link => link.addEventListener('click', event => { const target = (link.getAttribute('href') || link.dataset.scroll || '').replace(/^#/, ''); const view = viewMap[target]; if (view) { event.preventDefault(); activateView(view); document.querySelector('.sidebar')?.classList.remove('open'); } })); bootstrap(); })(); diff --git a/apps/web/asset-manifest.json b/apps/web/asset-manifest.json index af79a00..57b6700 100644 --- a/apps/web/asset-manifest.json +++ b/apps/web/asset-manifest.json @@ -1,6 +1,6 @@ { "schema": 1, - "version": "phase-20", + "version": "phase-21", "entrypoints": [ "config.js", "app.js", @@ -13,10 +13,10 @@ "healthz" ], "integrity": { - "config.js": "sha256-12a10f772029a5ee6d813ed9fd61dfc7ff877aa356bf90f65987948cc3274f90", - "app.js": "sha256-eef64a4296ec8dea6802937af88269b9f759de72fb793f706ac05d30549fcec9", - "styles.css": "sha256-ddbb75572a2e80e19a99834a8fb61540e0d94fffe4658429c99116242034183c", - "index.html": "sha256-2cba8095f33d9eaed8d73c33eecb08b82b223448240e9ef0d96de8c836122da8", + "config.js": "sha256-247380b078f895f025229d42c4f680285a237c498c248cd721f32938ec2398d6", + "app.js": "sha256-8927dd32aa1b79eb9cfa5f58e8ab100927dc3a839a1036774540e475c74626dc", + "styles.css": "sha256-a9fd194b001c0de98775bcf5fbba5da676ccfdd607a889eae84bd30a54c15e08", + "index.html": "sha256-5e6310fe37b241adc4b349dabe5067ad60d56453cbec7c4b1f9b767841c597b1", "health.html": "sha256-c352a6f37aa24628cfc8d5709a70ff2d94181d192ed5fe00916cca9378a61d81", "error.html": "sha256-f3cc28d2dfc9e8af112d0257c6ee47b9e9146e5da8590a754dd589bf43702aaf", "healthz": "sha256-dc51b8c96c2d745df3bd5590d990230a482fd247123599548e0632fdbf97fc22" diff --git a/apps/web/config.js b/apps/web/config.js index bccf855..c17c4fe 100644 --- a/apps/web/config.js +++ b/apps/web/config.js @@ -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-20' + assetVersion: 'phase-21' }); diff --git a/apps/web/index.html b/apps/web/index.html index 6c6030b..6c61424 100644 --- a/apps/web/index.html +++ b/apps/web/index.html @@ -130,7 +130,7 @@ - - + + diff --git a/apps/web/styles.css b/apps/web/styles.css index 7b3e347..d3f8382 100644 --- a/apps/web/styles.css +++ b/apps/web/styles.css @@ -256,6 +256,83 @@ footer { display: flex; justify-content: space-between; gap: 16px; margin-top: 3 .ai-provider-admin-state { margin: 14px 0; } .ai-provider-admin-state p { margin: 4px 0 0; } +/* Application views: keep the operator focused on one job at a time. */ +body[data-view="dashboard"] .direct-discovery-section, +body[data-view="dashboard"] #explorer, +body[data-view="dashboard"] .jobs-section, +body[data-view="dashboard"] .sources-section, +body[data-view="dashboard"] .lower-grid, +body[data-view="dashboard"] .crm-section { display: none; } +body[data-view="prospects"] #dashboard, +body[data-view="prospects"] #discoveryWorkspace, +body[data-view="prospects"] .metrics, +body[data-view="prospects"] .score-overview, +body[data-view="prospects"] #scoreRules, +body[data-view="prospects"] .jobs-section, +body[data-view="prospects"] .sources-section, +body[data-view="prospects"] .lower-grid, +body[data-view="prospects"] .crm-section { display: none; } +body[data-view="discovery"] #dashboard, +body[data-view="discovery"] .metrics, +body[data-view="discovery"] .score-overview, +body[data-view="discovery"] #scoreRules, +body[data-view="discovery"] #explorer, +body[data-view="discovery"] .jobs-section, +body[data-view="discovery"] .sources-section, +body[data-view="discovery"] .lower-grid, +body[data-view="discovery"] .crm-section { display: none; } +body[data-view="jobs"] #dashboard, +body[data-view="jobs"] .metrics, +body[data-view="jobs"] .score-overview, +body[data-view="jobs"] #scoreRules, +body[data-view="jobs"] #explorer, +body[data-view="jobs"] #discoveryWorkspace, +body[data-view="jobs"] .sources-section, +body[data-view="jobs"] .lower-grid, +body[data-view="jobs"] .crm-section { display: none; } +body[data-view="sources"] #dashboard, +body[data-view="sources"] .metrics, +body[data-view="sources"] .score-overview, +body[data-view="sources"] #scoreRules, +body[data-view="sources"] #explorer, +body[data-view="sources"] #discoveryWorkspace, +body[data-view="sources"] .jobs-section, +body[data-view="sources"] .lower-grid, +body[data-view="sources"] .crm-section { display: none; } +body[data-view="add"] #dashboard, +body[data-view="add"] .metrics, +body[data-view="add"] .score-overview, +body[data-view="add"] #scoreRules, +body[data-view="add"] #explorer, +body[data-view="add"] #discoveryWorkspace, +body[data-view="add"] .jobs-section, +body[data-view="add"] .sources-section, +body[data-view="add"] .crm-section { display: none; } +body[data-view="crm"] #dashboard, +body[data-view="crm"] .metrics, +body[data-view="crm"] .score-overview, +body[data-view="crm"] #scoreRules, +body[data-view="crm"] #explorer, +body[data-view="crm"] #discoveryWorkspace, +body[data-view="crm"] .jobs-section, +body[data-view="crm"] .sources-section, +body[data-view="crm"] .lower-grid { display: none; } +body[data-view="settings"] #dashboard, +body[data-view="settings"] .metrics, +body[data-view="settings"] .score-overview, +body[data-view="settings"] #scoreRules, +body[data-view="settings"] #explorer, +body[data-view="settings"] #discoveryWorkspace, +body[data-view="settings"] .jobs-section, +body[data-view="settings"] .sources-section, +body[data-view="settings"] .lower-grid, +body[data-view="settings"] #crmPipeline, +body[data-view="settings"] #crmActivity, +body[data-view="settings"] #crmReports { display: none; } +#startDemoJobBtn { display: none !important; } +.view-active { animation: view-enter .18s ease-out; } +@keyframes view-enter { from { opacity: .35; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } } + .sr-only { position: absolute; width: 1px; height: 1px; padding: 0; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; } @media (max-width: 1100px) { .metrics { grid-template-columns: repeat(3, 1fr); } .filters { grid-template-columns: repeat(3, 1fr); } .filters .search-wrap { grid-column: 1 / -1; } .workspace-grid { grid-template-columns: 1fr; } .detail-panel { min-height: 0; } .reports-grid { grid-template-columns: 1fr 1fr; } }