Skip to content

Commit 16f1c46

Browse files
author
Faxbot Agent
committed
PR5.1: Remove provider-ID checks across Admin UI; add dot-path trait helpers and active traits; refactor SetupWizard/ProviderSetupWizard/Scripts/Diagnostics/Inbound to trait-gating; purge active.outbound references
1 parent 5e463c2 commit 16f1c46

File tree

6 files changed

+109
-136
lines changed

6 files changed

+109
-136
lines changed

api/admin_ui/src/components/Diagnostics.tsx

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ function Diagnostics({ client, onNavigate, docsBase }: DiagnosticsProps) {
171171
const theme = useTheme();
172172
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
173173
const isSmallMobile = useMediaQuery(theme.breakpoints.down('sm'));
174-
const { active, registry } = useTraits();
174+
const { outboundTraits, inboundTraits } = useTraits();
175175

176176
// const hrefFor = (topic: string): string | undefined => (anchors[topic] || thirdParty[topic]);
177177

@@ -973,31 +973,20 @@ function Diagnostics({ client, onNavigate, docsBase }: DiagnosticsProps) {
973973
<Stack spacing={2}>
974974
<Box>
975975
<Typography variant="subtitle2" fontWeight={600} sx={{ mb: 1 }}>
976-
Active Providers
976+
Active Providers (traits)
977+
</Typography>
978+
<Typography variant="caption" color="text.secondary">
979+
Displaying traits for the active outbound and inbound providers.
977980
</Typography>
978-
<Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
979-
<Chip
980-
label={`Outbound: ${active?.outbound || 'None'}`}
981-
color="primary"
982-
variant="outlined"
983-
sx={{ borderRadius: 1 }}
984-
/>
985-
<Chip
986-
label={`Inbound: ${active?.inbound || 'None'}`}
987-
color="secondary"
988-
variant="outlined"
989-
sx={{ borderRadius: 1 }}
990-
/>
991-
</Box>
992981
</Box>
993982

994-
{active?.outbound && registry?.[active.outbound]?.traits && (
983+
{outboundTraits && (
995984
<Box>
996985
<Typography variant="subtitle2" fontWeight={600} sx={{ mb: 1 }}>
997986
Outbound Traits
998987
</Typography>
999988
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>
1000-
{Object.entries(registry[active.outbound].traits || {}).map(([key, value]) => (
989+
{Object.entries(outboundTraits || {}).map(([key, value]) => (
1001990
<Chip
1002991
key={key}
1003992
label={`${key}: ${String(value)}`}
@@ -1011,13 +1000,13 @@ function Diagnostics({ client, onNavigate, docsBase }: DiagnosticsProps) {
10111000
</Box>
10121001
)}
10131002

1014-
{active?.inbound && registry?.[active.inbound]?.traits && active.inbound !== active.outbound && (
1003+
{inboundTraits && (
10151004
<Box>
10161005
<Typography variant="subtitle2" fontWeight={600} sx={{ mb: 1 }}>
10171006
Inbound Traits
10181007
</Typography>
10191008
<Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>
1020-
{Object.entries(registry[active.inbound].traits || {}).map(([key, value]) => (
1009+
{Object.entries(inboundTraits || {}).map(([key, value]) => (
10211010
<Chip
10221011
key={key}
10231012
label={`${key}: ${String(value)}`}

api/admin_ui/src/components/PluginConfigDialog.tsx

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -49,57 +49,6 @@ export default function PluginConfigDialog({ open, plugin, initialConfig, onClos
4949
const pid = (plugin?.id || '').toLowerCase();
5050
if (!pid) return null;
5151

52-
if (pid === 'phaxio') {
53-
return (
54-
<Box>
55-
<Alert severity="info" sx={{ mb: 2 }}>
56-
Secrets (API key/secret) are configured in Settings → Backend: Phaxio. This form stores only non‑secret values in the plugin config.
57-
</Alert>
58-
<TextField
59-
label="Callback URL"
60-
fullWidth
61-
size="small"
62-
value={config.callback_url || ''}
63-
onChange={(e) => setConfig({ ...config, callback_url: e.target.value })}
64-
margin="normal"
65-
/>
66-
{help('Example: https://yourdomain.com/phaxio-callback')}
67-
<FormControlLabel
68-
control={<Checkbox checked={!!config.verify_signature} onChange={(e) => setConfig({ ...config, verify_signature: e.target.checked })} />}
69-
label="Verify inbound signatures"
70-
/>
71-
</Box>
72-
);
73-
}
74-
75-
if (pid === 'sinch') {
76-
return (
77-
<Box>
78-
<Alert severity="info" sx={{ mb: 2 }}>
79-
Secrets (API key/secret) are configured in Settings → Backend: Sinch. This form stores only non‑secret values in the plugin config.
80-
</Alert>
81-
<TextField
82-
label="Project ID"
83-
fullWidth
84-
size="small"
85-
value={config.project_id || ''}
86-
onChange={(e) => setConfig({ ...config, project_id: e.target.value })}
87-
margin="normal"
88-
/>
89-
</Box>
90-
);
91-
}
92-
93-
if (pid === 'sip') {
94-
return (
95-
<Box>
96-
<Alert severity="info">
97-
Configure AMI host/port/credentials and Station ID in Settings → Backend: SIP/Asterisk. No additional non‑secret plugin settings are required here.
98-
</Alert>
99-
</Box>
100-
);
101-
}
102-
10352
if (pid === 's3') {
10453
return (
10554
<Box>
@@ -190,4 +139,3 @@ export default function PluginConfigDialog({ open, plugin, initialConfig, onClos
190139
</Dialog>
191140
);
192141
}
193-

api/admin_ui/src/components/ProviderSetupWizard.tsx

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -126,21 +126,27 @@ export default function ProviderSetupWizard({
126126
setError(null);
127127

128128
// Convert config to settings format
129-
const settings: any = {
130-
backend: config.provider,
131-
};
132-
133-
if (config.provider === 'phaxio') {
129+
const settings: any = { backend: config.provider };
130+
// Traits-driven mapping
131+
const t = registry?.[config.provider]?.traits || {};
132+
const methods = (t?.auth?.methods || []) as string[];
133+
const requiresAmi = Boolean(t?.requires_ami);
134+
const basicOnly = Array.isArray(methods) && methods.includes('basic') && !methods.includes('oauth2');
135+
const hasOAuth = Array.isArray(methods) && methods.includes('oauth2');
136+
137+
if (basicOnly) {
134138
settings.phaxio_api_key = config.phaxio_api_key;
135139
settings.phaxio_api_secret = config.phaxio_api_secret;
136140
settings.phaxio_callback_url = config.phaxio_callback_url;
137141
settings.phaxio_verify_signature = config.phaxio_verify_signature;
138-
} else if (config.provider === 'sinch') {
142+
}
143+
if (hasOAuth) {
139144
settings.sinch_project_id = config.sinch_project_id;
140145
settings.sinch_api_key = config.sinch_api_key;
141146
settings.sinch_api_secret = config.sinch_api_secret;
142147
settings.sinch_base_url = config.sinch_base_url;
143-
} else if (config.provider === 'sip') {
148+
}
149+
if (requiresAmi) {
144150
settings.ami_host = config.ami_host;
145151
settings.ami_port = config.ami_port;
146152
settings.ami_username = config.ami_username;
@@ -170,16 +176,31 @@ export default function ProviderSetupWizard({
170176
setError(null);
171177

172178
// Convert config to settings format and save
173-
const settings: any = {
174-
backend: config.provider,
175-
};
176-
177-
// Add provider-specific settings
178-
Object.entries(config).forEach(([key, value]) => {
179-
if (key !== 'provider' && value !== undefined && value !== '') {
180-
settings[key] = value;
181-
}
182-
});
179+
const settings: any = { backend: config.provider };
180+
const t = registry?.[config.provider]?.traits || {};
181+
const methods = (t?.auth?.methods || []) as string[];
182+
const requiresAmi = Boolean(t?.requires_ami);
183+
const basicOnly = Array.isArray(methods) && methods.includes('basic') && !methods.includes('oauth2');
184+
const hasOAuth = Array.isArray(methods) && methods.includes('oauth2');
185+
186+
if (basicOnly) {
187+
settings.phaxio_api_key = config.phaxio_api_key;
188+
settings.phaxio_api_secret = config.phaxio_api_secret;
189+
if (config.public_api_url) settings.public_api_url = config.public_api_url;
190+
}
191+
if (hasOAuth) {
192+
settings.sinch_project_id = config.sinch_project_id;
193+
settings.sinch_api_key = config.sinch_api_key;
194+
settings.sinch_api_secret = config.sinch_api_secret;
195+
if (config.sinch_base_url) settings.sinch_base_url = config.sinch_base_url;
196+
}
197+
if (requiresAmi) {
198+
settings.ami_host = config.ami_host;
199+
settings.ami_port = config.ami_port;
200+
settings.ami_username = config.ami_username;
201+
settings.ami_password = config.ami_password;
202+
settings.fax_station_id = config.fax_station_id;
203+
}
183204

184205
await client.updateSettings(settings);
185206
onComplete();
@@ -295,7 +316,7 @@ export default function ProviderSetupWizard({
295316
</Box>
296317

297318
<Stack spacing={3}>
298-
{config.provider === 'phaxio' && (
319+
{(() => { const t = registry?.[config.provider]?.traits || {}; const m = (t?.auth?.methods||[]) as string[]; return Array.isArray(m) && m.includes('basic') && !m.includes('oauth2'); })() && (
299320
<ResponsiveFormSection
300321
title="Phaxio API Credentials"
301322
subtitle="Get these from your Phaxio console"
@@ -334,7 +355,7 @@ export default function ProviderSetupWizard({
334355
</ResponsiveFormSection>
335356
)}
336357

337-
{config.provider === 'sinch' && (
358+
{(() => { const t = registry?.[config.provider]?.traits || {}; const m = (t?.auth?.methods||[]) as string[]; return Array.isArray(m) && m.includes('oauth2'); })() && (
338359
<ResponsiveFormSection
339360
title="Sinch API Credentials"
340361
subtitle="Get these from your Sinch dashboard"
@@ -374,7 +395,7 @@ export default function ProviderSetupWizard({
374395
</ResponsiveFormSection>
375396
)}
376397

377-
{config.provider === 'sip' && (
398+
{Boolean(registry?.[config.provider]?.traits?.requires_ami) && (
378399
<ResponsiveFormSection
379400
title="Asterisk AMI Configuration"
380401
subtitle="Configure connection to your Asterisk server"

api/admin_ui/src/components/ScriptsTests.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const ConsoleBox: React.FC<{ lines: string[]; loading?: boolean; title?: string
142142
};
143143

144144
const ScriptsTests: React.FC<Props> = ({ client, docsBase }) => {
145-
const { active, registry } = useTraits();
145+
const { outboundTraits } = useTraits();
146146
const [error, setError] = useState<string>('');
147147
const [busyAuth, setBusyAuth] = useState<boolean>(false);
148148
const [busyInbound, setBusyInbound] = useState<boolean>(false);
@@ -554,7 +554,7 @@ const ScriptsTests: React.FC<Props> = ({ client, docsBase }) => {
554554
)}
555555

556556
{/* Show callback URL section when outbound supports status callbacks */}
557-
{Boolean(registry && active?.outbound && registry[active.outbound]?.traits?.status_callback) && (
557+
{Boolean(outboundTraits?.status_callback) && (
558558
<Grid item xs={12} lg={6}>
559559
<ResponsiveFormSection
560560
title="Status Callback URL"

0 commit comments

Comments
 (0)