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
This commit is contained in:
Hoan Luu Huu
2023-04-04 00:21:26 +07:00
committed by GitHub
parent aba8b2be3a
commit 49c18ebd26
7 changed files with 180 additions and 1 deletions
+5 -1
View File
@@ -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`;
+19
View File
@@ -550,6 +550,25 @@ export const getPcap = (sid: string, sipCallId: string) => {
);
};
export const getServiceProviderRecentCall = (
sid: string,
sipCallId: string
) => {
return getFetch<TotalResponse>(
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<PageQuery>) => {
const qryStr = getQuery<Partial<PageQuery>>(query);
+8
View File
@@ -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 {
@@ -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<Carrier>;
@@ -619,6 +620,15 @@ export const CarrierForm = ({
<fieldset>
<MS>{MSG_REQUIRED_FIELDS}</MS>
</fieldset>
{carrier &&
carrier.data &&
Boolean(carrier.data.requires_register) &&
carrier.data.register_status && (
<fieldset>
<div className="m med">Register status</div>
<RegisterStatus carrier={carrier.data} />
</fieldset>
)}
<fieldset>
<div className="multi">
<div className="inp">
@@ -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 = () => {
<span>{carrier.is_active ? "Active" : "Inactive"}</span>
</div>
</div>
{Boolean(carrier.requires_register) && (
<div
className={`i txt--${
carrier.register_status.status === CARRIER_REG_OK
? "teal"
: "jam"
}`}
>
{carrier.register_status.status === CARRIER_REG_OK ? (
<Icons.CheckCircle />
) : (
<Icons.XCircle />
)}
<span>
{carrier.register_status.status === CARRIER_REG_OK
? "Registered"
: "Unregistered"}
</span>
</div>
)}
<Gateways carrier={carrier} />
</div>
</div>
@@ -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<Pcap>();
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 (
<a
href={pcap.data_url}
download={pcap.file_name}
className="btn btn--small pcap"
>
Download pcap
</a>
);
}
return null;
};
@@ -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 (
<div
className={`i txt--${
carrier.register_status.status
? carrier.register_status.status === CARRIER_REG_OK
? "teal"
: "jam"
: "jean"
}`}
title={carrier.register_status.reason || "Not Started"}
>
{carrier.register_status.status === CARRIER_REG_OK ? (
<Icons.CheckCircle />
) : (
<Icons.XCircle />
)}
<span>
{carrier.register_status.status
? `Status ${carrier.register_status.status}`
: "Not Started"}
</span>
</div>
);
};
return (
<details className={carrier.register_status.status || "not-tested"}>
<summary>{renderStatus()}</summary>
<MS>
<strong>Reason:</strong>{" "}
{carrier.register_status.reason || "Not Started"}
</MS>
<PcapButton
accountSid={carrier.account_sid || ""}
serviceProviderSid={carrier.service_provider_sid}
sipCallId={carrier.register_status.callId || ""}
/>
</details>
);
};