mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-10 08:05:22 +02:00
feat: added vobiz telephony (#65)
* feat: added vobiz telephony * chore: run formatter * chore: add migration * Add tsclient --------- Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
This commit is contained in:
parent
749a0c557f
commit
09897cb5d8
16 changed files with 994 additions and 19 deletions
|
|
@ -6,7 +6,7 @@ import { useForm } from "react-hook-form";
|
|||
import { toast } from "sonner";
|
||||
|
||||
import { getTelephonyConfigurationApiV1OrganizationsTelephonyConfigGet, saveTelephonyConfigurationApiV1OrganizationsTelephonyConfigPost } from "@/client/sdk.gen";
|
||||
import type { TwilioConfigurationRequest, VonageConfigurationRequest } from "@/client/types.gen";
|
||||
import type { TwilioConfigurationRequest, VobizConfigurationRequest,VonageConfigurationRequest } from "@/client/types.gen";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
Card,
|
||||
|
|
@ -37,6 +37,9 @@ interface TelephonyConfigForm {
|
|||
private_key?: string;
|
||||
api_key?: string;
|
||||
api_secret?: string;
|
||||
// Vobiz fields
|
||||
auth_id?: string;
|
||||
vobiz_auth_token?: string;
|
||||
// Common field
|
||||
from_number: string;
|
||||
}
|
||||
|
|
@ -99,6 +102,14 @@ export default function ConfigureTelephonyPage() {
|
|||
if (response.data.vonage.from_numbers?.length > 0) {
|
||||
setValue("from_number", response.data.vonage.from_numbers[0]);
|
||||
}
|
||||
} else if (response.data?.vobiz) {
|
||||
setHasExistingConfig(true);
|
||||
setValue("provider", "vobiz");
|
||||
setValue("auth_id", response.data.vobiz.auth_id);
|
||||
setValue("vobiz_auth_token", response.data.vobiz.auth_token);
|
||||
if (response.data.vobiz.from_numbers?.length > 0) {
|
||||
setValue("from_number", response.data.vobiz.from_numbers[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -116,7 +127,7 @@ export default function ConfigureTelephonyPage() {
|
|||
const accessToken = await getAccessToken();
|
||||
|
||||
// Build the request body based on provider
|
||||
let requestBody: TwilioConfigurationRequest | VonageConfigurationRequest;
|
||||
let requestBody: TwilioConfigurationRequest | VonageConfigurationRequest | VobizConfigurationRequest;
|
||||
|
||||
if (data.provider === "twilio") {
|
||||
requestBody = {
|
||||
|
|
@ -125,7 +136,7 @@ export default function ConfigureTelephonyPage() {
|
|||
account_sid: data.account_sid,
|
||||
auth_token: data.auth_token,
|
||||
} as TwilioConfigurationRequest;
|
||||
} else {
|
||||
} else if (data.provider === "vonage") {
|
||||
requestBody = {
|
||||
provider: data.provider,
|
||||
from_numbers: [data.from_number],
|
||||
|
|
@ -134,6 +145,13 @@ export default function ConfigureTelephonyPage() {
|
|||
api_key: data.api_key || undefined,
|
||||
api_secret: data.api_secret || undefined,
|
||||
} as VonageConfigurationRequest;
|
||||
} else {
|
||||
requestBody = {
|
||||
provider: data.provider,
|
||||
from_numbers: [data.from_number],
|
||||
auth_id: data.auth_id,
|
||||
auth_token: data.vobiz_auth_token,
|
||||
} as VobizConfigurationRequest;
|
||||
}
|
||||
|
||||
const response = await saveTelephonyConfigurationApiV1OrganizationsTelephonyConfigPost({
|
||||
|
|
@ -223,6 +241,7 @@ export default function ConfigureTelephonyPage() {
|
|||
<SelectContent>
|
||||
<SelectItem value="twilio">Twilio</SelectItem>
|
||||
<SelectItem value="vonage">Vonage</SelectItem>
|
||||
<SelectItem value="vobiz">Vobiz</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
{hasExistingConfig && (
|
||||
|
|
@ -381,6 +400,73 @@ export default function ConfigureTelephonyPage() {
|
|||
</>
|
||||
)}
|
||||
|
||||
{/* Vobiz-specific fields */}
|
||||
{selectedProvider === "vobiz" && (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="auth_id">Auth ID</Label>
|
||||
<Input
|
||||
id="auth_id"
|
||||
placeholder="MA_XXXXXXXX"
|
||||
{...register("auth_id", {
|
||||
required: selectedProvider === "vobiz" ? "Auth ID is required" : false,
|
||||
})}
|
||||
/>
|
||||
{errors.auth_id && (
|
||||
<p className="text-sm text-red-500">
|
||||
{errors.auth_id.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="vobiz_auth_token">Auth Token</Label>
|
||||
<Input
|
||||
id="vobiz_auth_token"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
placeholder={
|
||||
hasExistingConfig
|
||||
? "Leave masked to keep existing"
|
||||
: "Enter your auth token"
|
||||
}
|
||||
{...register("vobiz_auth_token", {
|
||||
required: selectedProvider === "vobiz" && !hasExistingConfig
|
||||
? "Auth token is required"
|
||||
: false,
|
||||
})}
|
||||
/>
|
||||
{errors.vobiz_auth_token && (
|
||||
<p className="text-sm text-red-500">
|
||||
{errors.vobiz_auth_token.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="from_number">From Phone Number</Label>
|
||||
<Input
|
||||
id="from_number"
|
||||
autoComplete="tel"
|
||||
placeholder="918071387428 (E.164 without + prefix)"
|
||||
{...register("from_number", {
|
||||
required: "Phone number is required",
|
||||
pattern: {
|
||||
value: /^[1-9]\d{1,14}$/,
|
||||
message:
|
||||
"Enter a valid phone number without + prefix (e.g., 918071387428)",
|
||||
},
|
||||
})}
|
||||
/>
|
||||
{errors.from_number && (
|
||||
<p className="text-sm text-red-500">
|
||||
{errors.from_number.message}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="pt-4">
|
||||
<Button
|
||||
type="submit"
|
||||
|
|
|
|||
|
|
@ -117,8 +117,8 @@ const WorkflowHeader = ({ isDirty, workflowName, rfInstance, onRun, workflowId,
|
|||
});
|
||||
|
||||
// If no configuration exists, show configure dialog
|
||||
// Check if any telephony provider is configured (Twilio or Vonage)
|
||||
if (configResponse.error || (!configResponse.data?.twilio && !configResponse.data?.vonage)) {
|
||||
// Check if any telephony provider is configured (Twilio, Vonage, or Vobiz)
|
||||
if (configResponse.error || (!configResponse.data?.twilio && !configResponse.data?.vonage && !configResponse.data?.vobiz)) {
|
||||
setConfigureDialogOpen(true);
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
|
||||
import { type ClientOptions as DefaultClientOptions, type Config, createClient, createConfig } from '@hey-api/client-fetch';
|
||||
|
||||
import { createClientConfig } from '../lib/apiClient';
|
||||
import type { ClientOptions } from './types.gen';
|
||||
import { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from '@hey-api/client-fetch';
|
||||
import { createClientConfig } from '../lib/apiClient';
|
||||
|
||||
/**
|
||||
* The `createClientConfig()` function will be called on client initialization
|
||||
|
|
@ -17,4 +16,4 @@ export type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> =
|
|||
|
||||
export const client = createClient(createClientConfig(createConfig<ClientOptions>({
|
||||
baseUrl: 'http://127.0.0.1:8000'
|
||||
})));
|
||||
})));
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
// This file is auto-generated by @hey-api/openapi-ts
|
||||
export * from './sdk.gen';
|
||||
export * from './types.gen';
|
||||
export * from './sdk.gen';
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -246,6 +246,8 @@ export type EmbedConfigResponse = {
|
|||
position: string;
|
||||
button_text: string;
|
||||
button_color: string;
|
||||
size: string;
|
||||
auto_start: boolean;
|
||||
};
|
||||
|
||||
export type EmbedTokenRequest = {
|
||||
|
|
@ -451,6 +453,7 @@ export type SuperuserWorkflowRunsListResponse = {
|
|||
export type TelephonyConfigurationResponse = {
|
||||
twilio?: TwilioConfigurationResponse | null;
|
||||
vonage?: VonageConfigurationResponse | null;
|
||||
vobiz?: VobizConfigurationResponse | null;
|
||||
};
|
||||
|
||||
export type TestSessionResponse = {
|
||||
|
|
@ -563,6 +566,35 @@ export type ValidationError = {
|
|||
type: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request schema for Vobiz configuration.
|
||||
*/
|
||||
export type VobizConfigurationRequest = {
|
||||
provider?: string;
|
||||
/**
|
||||
* Vobiz Account ID (e.g., MA_SYQRLN1K)
|
||||
*/
|
||||
auth_id: string;
|
||||
/**
|
||||
* Vobiz Auth Token
|
||||
*/
|
||||
auth_token: string;
|
||||
/**
|
||||
* List of Vobiz phone numbers (E.164 without + prefix)
|
||||
*/
|
||||
from_numbers: Array<string>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Response schema for Vobiz configuration with masked sensitive fields.
|
||||
*/
|
||||
export type VobizConfigurationResponse = {
|
||||
provider: string;
|
||||
auth_id: string;
|
||||
auth_token: string;
|
||||
from_numbers: Array<string>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request schema for Vonage configuration.
|
||||
*/
|
||||
|
|
@ -812,6 +844,64 @@ export type HandleVonageEventsApiV1TelephonyVonageEventsWorkflowRunIdPostRespons
|
|||
200: unknown;
|
||||
};
|
||||
|
||||
export type HandleVobizHangupCallbackApiV1TelephonyVobizHangupCallbackWorkflowRunIdPostData = {
|
||||
body?: never;
|
||||
path: {
|
||||
workflow_run_id: number;
|
||||
};
|
||||
query?: never;
|
||||
url: '/api/v1/telephony/vobiz/hangup-callback/{workflow_run_id}';
|
||||
};
|
||||
|
||||
export type HandleVobizHangupCallbackApiV1TelephonyVobizHangupCallbackWorkflowRunIdPostErrors = {
|
||||
/**
|
||||
* Not found
|
||||
*/
|
||||
404: unknown;
|
||||
/**
|
||||
* Validation Error
|
||||
*/
|
||||
422: HttpValidationError;
|
||||
};
|
||||
|
||||
export type HandleVobizHangupCallbackApiV1TelephonyVobizHangupCallbackWorkflowRunIdPostError = HandleVobizHangupCallbackApiV1TelephonyVobizHangupCallbackWorkflowRunIdPostErrors[keyof HandleVobizHangupCallbackApiV1TelephonyVobizHangupCallbackWorkflowRunIdPostErrors];
|
||||
|
||||
export type HandleVobizHangupCallbackApiV1TelephonyVobizHangupCallbackWorkflowRunIdPostResponses = {
|
||||
/**
|
||||
* Successful Response
|
||||
*/
|
||||
200: unknown;
|
||||
};
|
||||
|
||||
export type HandleVobizRingCallbackApiV1TelephonyVobizRingCallbackWorkflowRunIdPostData = {
|
||||
body?: never;
|
||||
path: {
|
||||
workflow_run_id: number;
|
||||
};
|
||||
query?: never;
|
||||
url: '/api/v1/telephony/vobiz/ring-callback/{workflow_run_id}';
|
||||
};
|
||||
|
||||
export type HandleVobizRingCallbackApiV1TelephonyVobizRingCallbackWorkflowRunIdPostErrors = {
|
||||
/**
|
||||
* Not found
|
||||
*/
|
||||
404: unknown;
|
||||
/**
|
||||
* Validation Error
|
||||
*/
|
||||
422: HttpValidationError;
|
||||
};
|
||||
|
||||
export type HandleVobizRingCallbackApiV1TelephonyVobizRingCallbackWorkflowRunIdPostError = HandleVobizRingCallbackApiV1TelephonyVobizRingCallbackWorkflowRunIdPostErrors[keyof HandleVobizRingCallbackApiV1TelephonyVobizRingCallbackWorkflowRunIdPostErrors];
|
||||
|
||||
export type HandleVobizRingCallbackApiV1TelephonyVobizRingCallbackWorkflowRunIdPostResponses = {
|
||||
/**
|
||||
* Successful Response
|
||||
*/
|
||||
200: unknown;
|
||||
};
|
||||
|
||||
export type OfferApiV1PipecatRtcOfferPostData = {
|
||||
body: RtcOfferRequest;
|
||||
headers?: {
|
||||
|
|
@ -2145,7 +2235,7 @@ export type GetTelephonyConfigurationApiV1OrganizationsTelephonyConfigGetRespons
|
|||
export type GetTelephonyConfigurationApiV1OrganizationsTelephonyConfigGetResponse = GetTelephonyConfigurationApiV1OrganizationsTelephonyConfigGetResponses[keyof GetTelephonyConfigurationApiV1OrganizationsTelephonyConfigGetResponses];
|
||||
|
||||
export type SaveTelephonyConfigurationApiV1OrganizationsTelephonyConfigPostData = {
|
||||
body: TwilioConfigurationRequest | VonageConfigurationRequest;
|
||||
body: TwilioConfigurationRequest | VonageConfigurationRequest | VobizConfigurationRequest;
|
||||
headers?: {
|
||||
authorization?: string | null;
|
||||
};
|
||||
|
|
@ -3184,4 +3274,4 @@ export type HealthApiV1HealthGetResponses = {
|
|||
|
||||
export type ClientOptions = {
|
||||
baseUrl: 'http://127.0.0.1:8000' | (string & {});
|
||||
};
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue