From 49c18ebd2635580e358bc7a6ab9bc2f0aef425a7 Mon Sep 17 00:00:00 2001 From: Hoan Luu Huu <110280845+xquanluu@users.noreply.github.com> Date: Tue, 4 Apr 2023 00:21:26 +0700 Subject: [PATCH] feat: carrier register status (#226) * feat: carrier register status * fix: typo issue * update PcapButton * is active for voice gateway to true * fix: download pcap * fix: download pcap --- src/api/constants.ts | 6 +- src/api/index.ts | 19 ++++++ src/api/types.ts | 8 +++ .../internal/views/carriers/form.tsx | 10 +++ .../internal/views/carriers/index.tsx | 21 ++++++ .../internal/views/carriers/pcap.tsx | 64 +++++++++++++++++++ .../views/carriers/register-status.tsx | 53 +++++++++++++++ 7 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 src/containers/internal/views/carriers/pcap.tsx create mode 100644 src/containers/internal/views/carriers/register-status.tsx diff --git a/src/api/constants.ts b/src/api/constants.ts index 62d9ac8..55e01d7 100644 --- a/src/api/constants.ts +++ b/src/api/constants.ts @@ -59,7 +59,7 @@ export const DEFAULT_SIP_GATEWAY: SipGateway = { ipv4: "", port: 5060, netmask: 32, - is_active: false, + is_active: true, inbound: 1, outbound: 0, }; @@ -187,6 +187,10 @@ export const CRED_OK = "ok"; export const CRED_FAIL = "fail"; export const CRED_NOT_TESTED = "not tested"; +/** Voip Carrier Register result status values */ +export const CARRIER_REG_OK = "ok"; +export const CARRIER_REG_FAIL = "fail"; + /** API base paths */ export const API_LOGIN = `${API_BASE_URL}/login`; export const API_LOGOUT = `${API_BASE_URL}/logout`; diff --git a/src/api/index.ts b/src/api/index.ts index c096c93..25fbed7 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -550,6 +550,25 @@ export const getPcap = (sid: string, sipCallId: string) => { ); }; +export const getServiceProviderRecentCall = ( + sid: string, + sipCallId: string +) => { + return getFetch( + import.meta.env.DEV + ? `${DEV_BASE_URL}/ServiceProviders/${sid}/RecentCalls/${sipCallId}` + : `${API_SERVICE_PROVIDERS}/${sid}/RecentCalls/${sipCallId}` + ); +}; + +export const getServiceProviderPcap = (sid: string, sipCallId: string) => { + return getBlob( + import.meta.env.DEV + ? `${DEV_BASE_URL}/ServiceProviders/${sid}/RecentCalls/${sipCallId}/pcap` + : `${API_SERVICE_PROVIDERS}/${sid}/RecentCalls/${sipCallId}/pcap` + ); +}; + export const getAlerts = (sid: string, query: Partial) => { const qryStr = getQuery>(query); diff --git a/src/api/types.ts b/src/api/types.ts index c47459f..ef9c55b 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -324,6 +324,13 @@ export interface Alert { detail: string; } +export interface CarrierRegisterStatus { + status: null | string; + reason: null | string; + cseq: null | string; + callId: null | string; +} + export interface Carrier { voip_carrier_sid: string; name: string; @@ -349,6 +356,7 @@ export interface Carrier { smpp_inbound_system_id: null | string; smpp_inbound_password: null | string; smpp_enquire_link_interval: number; + register_status: CarrierRegisterStatus; } export interface PredefinedCarrier extends Carrier { diff --git a/src/containers/internal/views/carriers/form.tsx b/src/containers/internal/views/carriers/form.tsx index e5515e1..b8b18b9 100644 --- a/src/containers/internal/views/carriers/form.tsx +++ b/src/containers/internal/views/carriers/form.tsx @@ -60,6 +60,7 @@ import type { Application, } from "src/api/types"; import { setAccountFilter, setLocation } from "src/store/localStore"; +import { RegisterStatus } from "./register-status"; type CarrierFormProps = { carrier?: UseApiDataMap; @@ -619,6 +620,15 @@ export const CarrierForm = ({
{MSG_REQUIRED_FIELDS}
+ {carrier && + carrier.data && + Boolean(carrier.data.requires_register) && + carrier.data.register_status && ( +
+
Register status
+ +
+ )}
diff --git a/src/containers/internal/views/carriers/index.tsx b/src/containers/internal/views/carriers/index.tsx index 031e4ae..8267726 100644 --- a/src/containers/internal/views/carriers/index.tsx +++ b/src/containers/internal/views/carriers/index.tsx @@ -29,6 +29,7 @@ import { import { API_SIP_GATEWAY, API_SMPP_GATEWAY, + CARRIER_REG_OK, USER_ACCOUNT, } from "src/api/constants"; import { DeleteCarrier } from "./delete"; @@ -197,6 +198,26 @@ export const Carriers = () => { {carrier.is_active ? "Active" : "Inactive"}
+ {Boolean(carrier.requires_register) && ( +
+ {carrier.register_status.status === CARRIER_REG_OK ? ( + + ) : ( + + )} + + {carrier.register_status.status === CARRIER_REG_OK + ? "Registered" + : "Unregistered"} + +
+ )} diff --git a/src/containers/internal/views/carriers/pcap.tsx b/src/containers/internal/views/carriers/pcap.tsx new file mode 100644 index 0000000..1b60f7d --- /dev/null +++ b/src/containers/internal/views/carriers/pcap.tsx @@ -0,0 +1,64 @@ +import React, { useEffect, useState } from "react"; + +import { + getRecentCall, + getServiceProviderRecentCall, + getPcap, + getServiceProviderPcap, +} from "src/api"; +import { toastError } from "src/store"; + +import type { Pcap } from "src/api/types"; + +type PcapButtonProps = { + accountSid: string; + serviceProviderSid: string; + sipCallId: string; +}; + +export const PcapButton = ({ + accountSid, + serviceProviderSid, + sipCallId, +}: PcapButtonProps) => { + const [pcap, setPcap] = useState(); + + useEffect(() => { + const p = accountSid + ? getRecentCall(accountSid, sipCallId) + : getServiceProviderRecentCall(serviceProviderSid, sipCallId); + p.then(({ json }) => { + if (json.total > 0) { + const p1 = accountSid + ? getPcap(accountSid, sipCallId) + : getServiceProviderPcap(serviceProviderSid, sipCallId); + p1.then(({ blob }) => { + if (blob) { + setPcap({ + data_url: URL.createObjectURL(blob), + file_name: `callid-${sipCallId}.pcap`, + }); + } + }).catch((error) => { + toastError(error.msg); + }); + } + }).catch((error) => { + toastError(error.msg); + }); + }, []); + + if (pcap) { + return ( + + Download pcap + + ); + } + + return null; +}; diff --git a/src/containers/internal/views/carriers/register-status.tsx b/src/containers/internal/views/carriers/register-status.tsx new file mode 100644 index 0000000..0d97088 --- /dev/null +++ b/src/containers/internal/views/carriers/register-status.tsx @@ -0,0 +1,53 @@ +import React from "react"; +import { Carrier } from "src/api/types"; +import { Icons } from "src/components"; +import { CARRIER_REG_OK } from "src/api/constants"; +import { MS } from "@jambonz/ui-kit"; +import { PcapButton } from "./pcap"; + +type CarrierProps = { + carrier: Carrier; +}; + +export const RegisterStatus = ({ carrier }: CarrierProps) => { + const renderStatus = () => { + return ( +
+ {carrier.register_status.status === CARRIER_REG_OK ? ( + + ) : ( + + )} + + {carrier.register_status.status + ? `Status ${carrier.register_status.status}` + : "Not Started"} + +
+ ); + }; + + return ( +
+ {renderStatus()} + + Reason:{" "} + {carrier.register_status.reason || "Not Started"} + + +
+ ); +};