email: single-mailbox enroll field on Email Capture panel — v0.1.0:60
Adds a "Test with a single mailbox first" input (pre-filled with the admin's own address) + Enroll this mailbox button calling the enroll-one endpoint, so capture can be tried on one mailbox before enrolling the whole domain. runAction now sends an optional JSON body. Enroll-all stays. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+31
-5
@@ -9955,6 +9955,7 @@
|
|||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState('');
|
const [error, setError] = useState('');
|
||||||
const [busy, setBusy] = useState('');
|
const [busy, setBusy] = useState('');
|
||||||
|
const [oneEmail, setOneEmail] = useState(() => user?.email || '');
|
||||||
|
|
||||||
const load = useCallback(async () => {
|
const load = useCallback(async () => {
|
||||||
let s;
|
let s;
|
||||||
@@ -9991,12 +9992,14 @@
|
|||||||
return () => { cancelled = true; };
|
return () => { cancelled = true; };
|
||||||
}, [load]);
|
}, [load]);
|
||||||
|
|
||||||
const runAction = async (key, endpoint, successMsg, confirmMsg) => {
|
const runAction = async (key, endpoint, successMsg, confirmMsg, body) => {
|
||||||
if (busy) return;
|
if (busy) return;
|
||||||
if (confirmMsg && !window.confirm(confirmMsg)) return;
|
if (confirmMsg && !window.confirm(confirmMsg)) return;
|
||||||
try {
|
try {
|
||||||
setBusy(key);
|
setBusy(key);
|
||||||
const res = await api(endpoint, { method: 'POST' }, token);
|
const opts = { method: 'POST' };
|
||||||
|
if (body) opts.body = JSON.stringify(body);
|
||||||
|
const res = await api(endpoint, opts, token);
|
||||||
onShowToast(typeof successMsg === 'function' ? successMsg(res) : successMsg, 'success');
|
onShowToast(typeof successMsg === 'function' ? successMsg(res) : successMsg, 'success');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
onShowToast(getErrorMessage(err, 'Action failed'), 'error');
|
onShowToast(getErrorMessage(err, 'Action failed'), 'error');
|
||||||
@@ -10060,12 +10063,35 @@
|
|||||||
{isAdmin && (
|
{isAdmin && (
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<div className="section-title">Actions</div>
|
<div className="section-title">Actions</div>
|
||||||
<div className="index-action-buttons">
|
<div className="index-action-hint" style={{ marginTop: 0, marginBottom: '8px' }}>
|
||||||
|
Test with a single mailbox first:
|
||||||
|
</div>
|
||||||
|
<div className="index-action-buttons" style={{ alignItems: 'center', marginBottom: '16px' }}>
|
||||||
|
<input
|
||||||
|
className="text-input"
|
||||||
|
type="email"
|
||||||
|
placeholder="name@ten31.xyz"
|
||||||
|
value={oneEmail}
|
||||||
|
onChange={(e) => setOneEmail(e.target.value)}
|
||||||
|
style={{ maxWidth: '260px' }}
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
onClick={() => runAction('enroll', '/api/email/accounts/enroll-all', (r) => `Enrolled ${r?.count ?? 0} mailbox(es)`, 'Enroll all Ten31 mailboxes for capture? This connects each active @ten31.xyz user’s Gmail via the service account. Domain-wide delegation must already be authorized in Google Workspace admin.')}
|
onClick={() => {
|
||||||
|
const addr = (oneEmail || '').trim();
|
||||||
|
if (!addr) { onShowToast('Enter a mailbox address', 'error'); return; }
|
||||||
|
runAction('enroll-one', '/api/email/accounts/enroll', (r) => `Enrolled ${r?.email || addr}`, `Enroll just ${addr} for capture?`, { email: addr });
|
||||||
|
}}
|
||||||
disabled={!enabled || !!busy}
|
disabled={!enabled || !!busy}
|
||||||
>
|
>
|
||||||
{busy === 'enroll' ? 'Enrolling…' : 'Enroll Ten31 mailboxes'}
|
{busy === 'enroll-one' ? 'Enrolling…' : 'Enroll this mailbox'}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="index-action-buttons">
|
||||||
|
<button
|
||||||
|
onClick={() => runAction('enroll', '/api/email/accounts/enroll-all', (r) => `Enrolled ${r?.count ?? 0} mailbox(es)`, 'Enroll ALL Ten31 mailboxes for capture? This connects every active @ten31.xyz user’s Gmail via the service account. Domain-wide delegation must already be authorized in Google Workspace admin.')}
|
||||||
|
disabled={!enabled || !!busy}
|
||||||
|
>
|
||||||
|
{busy === 'enroll' ? 'Enrolling…' : 'Enroll all Ten31 mailboxes'}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => runAction('sync', '/api/email/sync/run-now', 'Sync started')}
|
onClick={() => runAction('sync', '/api/email/sync/run-now', 'Sync started')}
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ export const PACKAGE_TITLE = 'Ten31 Database'
|
|||||||
// * 0.1.0:56 (Thesis Workshop redesign: edit/choose/delete + approve-as-current)
|
// * 0.1.0:56 (Thesis Workshop redesign: edit/choose/delete + approve-as-current)
|
||||||
// * 0.1.0:57 (redaction fix: magnitude regex no longer eats the word after an amount)
|
// * 0.1.0:57 (redaction fix: magnitude regex no longer eats the word after an amount)
|
||||||
// * 0.1.0:58 (seed 5 Architect positioning framings into the Workshop as candidate options)
|
// * 0.1.0:58 (seed 5 Architect positioning framings into the Workshop as candidate options)
|
||||||
// * Current: 0.1.0:59 (Email Capture admin panel + matched email into the grounding corpus)
|
// * 0.1.0:59 (Email Capture admin panel + matched email into the grounding corpus)
|
||||||
export const PACKAGE_VERSION = '0.1.0:59'
|
// * Current: 0.1.0:60 (Email Capture: single-mailbox enroll field for testing)
|
||||||
|
export const PACKAGE_VERSION = '0.1.0:60'
|
||||||
|
|
||||||
export const DATA_MOUNT_PATH = '/data'
|
export const DATA_MOUNT_PATH = '/data'
|
||||||
export const WEB_PORT = 8080
|
export const WEB_PORT = 8080
|
||||||
|
|||||||
@@ -20,8 +20,9 @@ import { v_0_1_0_56 } from './v0.1.0.56'
|
|||||||
import { v_0_1_0_57 } from './v0.1.0.57'
|
import { v_0_1_0_57 } from './v0.1.0.57'
|
||||||
import { v_0_1_0_58 } from './v0.1.0.58'
|
import { v_0_1_0_58 } from './v0.1.0.58'
|
||||||
import { v_0_1_0_59 } from './v0.1.0.59'
|
import { v_0_1_0_59 } from './v0.1.0.59'
|
||||||
|
import { v_0_1_0_60 } from './v0.1.0.60'
|
||||||
|
|
||||||
export const versionGraph = VersionGraph.of({
|
export const versionGraph = VersionGraph.of({
|
||||||
current: v_0_1_0_59,
|
current: v_0_1_0_60,
|
||||||
other: [v_0_1_0_39, v_0_1_0_40, v_0_1_0_41, v_0_1_0_42, v_0_1_0_43, v_0_1_0_44, v_0_1_0_45, v_0_1_0_46, v_0_1_0_47, v_0_1_0_48, v_0_1_0_49, v_0_1_0_50, v_0_1_0_51, v_0_1_0_52, v_0_1_0_53, v_0_1_0_54, v_0_1_0_55, v_0_1_0_56, v_0_1_0_57, v_0_1_0_58],
|
other: [v_0_1_0_39, v_0_1_0_40, v_0_1_0_41, v_0_1_0_42, v_0_1_0_43, v_0_1_0_44, v_0_1_0_45, v_0_1_0_46, v_0_1_0_47, v_0_1_0_48, v_0_1_0_49, v_0_1_0_50, v_0_1_0_51, v_0_1_0_52, v_0_1_0_53, v_0_1_0_54, v_0_1_0_55, v_0_1_0_56, v_0_1_0_57, v_0_1_0_58, v_0_1_0_59],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { VersionInfo } from '@start9labs/start-sdk'
|
||||||
|
|
||||||
|
// Email Capture: add a single-mailbox enroll field (pre-filled with the admin's own
|
||||||
|
// address) so an admin can test capture on one mailbox before enrolling the whole
|
||||||
|
// domain. Calls the existing enroll-one endpoint; the enroll-all button stays. No
|
||||||
|
// schema migration.
|
||||||
|
export const v_0_1_0_60 = VersionInfo.of({
|
||||||
|
version: '0.1.0:60',
|
||||||
|
releaseNotes: {
|
||||||
|
en_US: [
|
||||||
|
'Email Capture: you can now enroll a single mailbox (pre-filled with your own address)',
|
||||||
|
'to test capture before turning it on for the whole team. The enroll-all option stays.',
|
||||||
|
].join(' '),
|
||||||
|
},
|
||||||
|
migrations: { up: async () => {}, down: async () => {} },
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user