add special field for Carriers in env vars (#561)

* add special field for Carriers in env vars

* wip

* wip
This commit is contained in:
Hoan Luu Huu
2025-09-05 19:04:24 +07:00
committed by GitHub
parent f7f4a2e7b1
commit 6836a99635
3 changed files with 96 additions and 22 deletions
+9 -1
View File
@@ -1,4 +1,10 @@
import type { Language, Model, Vendor, VoiceLanguage } from "src/vendor/types"; import type {
JambonzResourceOptions,
Language,
Model,
Vendor,
VoiceLanguage,
} from "src/vendor/types";
/** Simple types */ /** Simple types */
@@ -825,6 +831,8 @@ export interface AppEnvProperty {
obscure?: boolean; obscure?: boolean;
uiHint?: "input" | "textarea" | "filepicker"; uiHint?: "input" | "textarea" | "filepicker";
enum?: string[]; enum?: string[];
jambonzResource?: "carriers";
jambonzResourceOptions?: JambonzResourceOptions[];
} }
export interface AppEnv { export interface AppEnv {
@@ -25,6 +25,7 @@ import {
useServiceProviderData, useServiceProviderData,
useApiData, useApiData,
getAppEnvSchema, getAppEnvSchema,
getSPVoipCarriers,
} from "src/api"; } from "src/api";
import { import {
ROUTE_INTERNAL_ACCOUNTS, ROUTE_INTERNAL_ACCOUNTS,
@@ -588,6 +589,51 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
setFallbackSpeechRecognizerLabel(tmp); setFallbackSpeechRecognizerLabel(tmp);
}; };
const fetchAppEnvJambonzResources = async (appEnv: AppEnv) => {
if (appEnv) {
const promises = Object.entries(appEnv).map(async ([key, value]) => {
const { jambonzResource } = value;
switch (jambonzResource) {
case "carriers":
const carriers = await getSPVoipCarriers(
currentServiceProvider?.service_provider_sid || "",
{
page: 1,
page_size: 10000,
...(user?.account_sid && {
account_sid: user.account_sid,
}),
},
);
if (carriers.json.total) {
return {
key,
jambonzResourceOptions: carriers.json.data.map((carrier) => ({
name: carrier.name,
value: carrier.name,
})),
};
}
break;
default:
break;
}
return { key, jambonzResourceOptions: null };
});
const results = await Promise.all(promises);
// Merge the results back into appEnv
results.forEach(({ key, jambonzResourceOptions }) => {
if (jambonzResourceOptions) {
appEnv[key].jambonzResourceOptions = jambonzResourceOptions;
}
});
}
return appEnv;
};
useEffect(() => { useEffect(() => {
if (callWebhook && callWebhook.url) { if (callWebhook && callWebhook.url) {
// Clear any existing timeout to prevent multiple requests // Clear any existing timeout to prevent multiple requests
@@ -599,19 +645,26 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
appEnvTimeoutRef.current = setTimeout(() => { appEnvTimeoutRef.current = setTimeout(() => {
getAppEnvSchema(callWebhook.url) getAppEnvSchema(callWebhook.url)
.then(({ json }) => { .then(({ json }) => {
setAppEnv(json); // fetch app env jambonz_resource
const defaultEnvVars = Object.keys(json).reduce((acc, key) => { fetchAppEnvJambonzResources(json).then((updatedEnv) => {
const value = json[key]; setAppEnv(updatedEnv);
if (value?.default) { const defaultEnvVars = Object.keys(updatedEnv).reduce(
return { ...acc, [key]: value.default }; (acc, key) => {
} const value = updatedEnv[key];
return acc; if (value?.default) {
}, {}); return { ...acc, [key]: value.default };
}
return acc;
},
{},
);
setEnvVars((prev) => ({ setEnvVars((prev) => ({
...defaultEnvVars, ...defaultEnvVars,
...(prev || {}), ...(prev || {}),
})); }));
});
// Default value
}) })
.catch((error) => { .catch((error) => {
setMessage(error.msg); setMessage(error.msg);
@@ -873,9 +926,13 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
}; };
const isDropdown = const isDropdown =
webhook.webhookEnv![key].type === "string" && (webhook.webhookEnv![key].type === "string" &&
(webhook.webhookEnv![key].enum?.length || 0) > (webhook.webhookEnv![key].enum?.length ||
0; 0) > 0) ||
hasLength(
webhook.webhookEnv![key]
.jambonzResourceOptions,
);
const textAreaSpecificProps = { const textAreaSpecificProps = {
rows: 6, rows: 6,
@@ -888,15 +945,19 @@ export const ApplicationForm = ({ application }: ApplicationFormProps) => {
? ObscureInput ? ObscureInput
: webhook.webhookEnv![key].uiHint || "input"; : webhook.webhookEnv![key].uiHint || "input";
if (isDropdown) { if (isDropdown) {
const options =
webhook.webhookEnv![key]
.jambonzResourceOptions ||
webhook.webhookEnv![key].enum!.map(
(option) => ({
name: option,
value: option,
}),
);
return ( return (
<Selector <Selector
{...commonProps} {...commonProps}
options={webhook.webhookEnv![ options={options}
key
].enum!.map((option) => ({
name: option,
value: option,
}))}
/> />
); );
} }
+5
View File
@@ -34,6 +34,11 @@ export interface LabelOptions {
value: string; value: string;
} }
export interface JambonzResourceOptions {
name: string;
value: string;
}
export interface Region { export interface Region {
name: string; name: string;
value: string; value: string;