Add temporary admin contacts-census diagnostic (v0.1.0:105)
A throwaway, admin-only diagnostic for the deferred contacts <-> fundraising_contacts consolidation: GET /api/admin/contacts-census + a Settings -> Admin "Run census" button report the A/B/C populations (linked / contacts-only / pill-only) plus the communications/opportunities repointing surface. Counts only, no PII -- mirrors backend/scripts/contacts_census.sql so the numbers can be read off the box without a shell. All pieces are tagged TEMPORARY; delete the endpoint + route + button after the census is captured. No schema change. 45/45 tests, render-smoke green.
This commit is contained in:
@@ -10699,6 +10699,31 @@
|
||||
);
|
||||
};
|
||||
|
||||
// TEMPORARY (v0.1.0:105) — DELETE AFTER the contacts<->fundraising_contacts census.
|
||||
// Admin button that runs GET /api/admin/contacts-census and shows the counts (no PII), so the
|
||||
// A/B/C populations can be read off the box without shell access. Remove with the endpoint.
|
||||
const ContactsCensus = ({ token }) => {
|
||||
const [data, setData] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const run = async () => {
|
||||
setLoading(true);
|
||||
try { const r = await api('/api/admin/contacts-census', {}, token); setData(r.data || {}); }
|
||||
catch (err) { setData({ error: getErrorMessage(err, 'failed') }); }
|
||||
finally { setLoading(false); }
|
||||
};
|
||||
return (
|
||||
<div style={{ marginBottom: '20px', borderBottom: '1px solid var(--border)', paddingBottom: '16px' }}>
|
||||
<div style={{ fontWeight: 600, marginBottom: '8px' }}>Contacts census <span style={{ fontSize: '11px', color: 'var(--text-muted)', fontWeight: 400 }}>(temporary — sizes the contacts ↔ grid consolidation)</span></div>
|
||||
<button type="button" className="button-secondary" onClick={run} disabled={loading} style={{ marginBottom: '10px' }}>
|
||||
{loading ? <Spinner /> : 'Run census'}
|
||||
</button>
|
||||
{data && (
|
||||
<pre style={{ fontSize: '12px', color: 'var(--text-secondary)', background: 'var(--bg-input)', border: '1px solid var(--border)', borderRadius: '8px', padding: '10px', overflowX: 'auto', margin: 0 }}>{JSON.stringify(data, null, 2)}</pre>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SettingsPage = ({ token, onShowToast, user, onOpenAirtableImport }) => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [inviteForm, setInviteForm] = useState({
|
||||
@@ -11698,6 +11723,8 @@
|
||||
|
||||
<PurgeDeletedData token={token} onShowToast={onShowToast} />
|
||||
|
||||
<ContactsCensus token={token} />{/* TEMPORARY — remove after the consolidation census */}
|
||||
|
||||
<div>
|
||||
<div style={{ fontWeight: 600, marginBottom: '10px' }}>Fundraising State Ops</div>
|
||||
<div style={{ marginBottom: '12px', padding: '10px', border: '1px solid var(--border)', borderRadius: '8px' }}>
|
||||
|
||||
Reference in New Issue
Block a user