diff --git a/.env b/.env index 08d4da9..848b1ae 100644 --- a/.env +++ b/.env @@ -29,4 +29,6 @@ ## ignore some specific speech vendors, defined by ADDITIONAL_SPEECH_VENDORS constant # VITE_APP_DISABLE_ADDITIONAL_SPEECH_VENDORS=true ## AWS region for enabling Recent Call Feature server logs -#VITE_APP_AWS_REGION=us-west-2 \ No newline at end of file +#VITE_APP_AWS_REGION=us-west-2 +## enable lazy loading for phone numbers (improves performance when managing large quantities) +# VITE_APP_ENABLE_PHONE_NUMBER_LAZY_LOAD=true \ No newline at end of file diff --git a/src/api/constants.ts b/src/api/constants.ts index f10fcac..3574fb4 100644 --- a/src/api/constants.ts +++ b/src/api/constants.ts @@ -33,6 +33,7 @@ interface JambonzWindowObject { STRIPE_PUBLISHABLE_KEY: string; DISABLE_ADDITIONAL_SPEECH_VENDORS: string; AWS_REGION: string; + ENABLE_PHONE_NUMBER_LAZY_LOAD: string; } declare global { @@ -91,6 +92,10 @@ export const DISABLE_ADDITIONAL_SPEECH_VENDORS: boolean = export const AWS_REGION: string = window.JAMBONZ?.AWS_REGION || import.meta.env.VITE_APP_AWS_REGION; +export const ENABLE_PHONE_NUMBER_LAZY_LOAD: boolean = + window.JAMBONZ?.ENABLE_PHONE_NUMBER_LAZY_LOAD === "true" || + JSON.parse(import.meta.env.VITE_APP_ENABLE_PHONE_NUMBER_LAZY_LOAD || "false"); + export const DEFAULT_SERVICE_PROVIDER_SID: string = window.JAMBONZ?.DEFAULT_SERVICE_PROVIDER_SID || import.meta.env.VITE_APP_DEFAULT_SERVICE_PROVIDER_SID; diff --git a/src/api/index.ts b/src/api/index.ts index bfb3b78..cec58f3 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -96,6 +96,7 @@ import type { GoogleCustomVoicesQuery, SpeechSupportedLanguagesAndVoices, AppEnv, + PhoneNumberQuery, } from "./types"; import { Availability, StatusCodes } from "./types"; import { JaegerRoot } from "./jaeger-types"; @@ -899,6 +900,12 @@ export const getPrice = () => { return getFetch(API_PRICE); }; +export const getPhoneNumbers = (query: Partial) => { + const qryStr = getQuery>(query); + + return getFetch(`${API_PHONE_NUMBERS}?${qryStr}`); +}; + export const getSpeechSupportedLanguagesAndVoices = ( sid: string | undefined, vendor: string, diff --git a/src/api/types.ts b/src/api/types.ts index 60cf929..48a7e7e 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -562,6 +562,11 @@ export interface PageQuery { days?: number; } +export interface PhoneNumberQuery extends PageQuery { + account_sid?: string; + filter?: string; +} + export interface CallQuery extends PageQuery { direction?: string; answered?: string; diff --git a/src/containers/internal/views/phone-numbers/index.tsx b/src/containers/internal/views/phone-numbers/index.tsx index e648c2d..037bbb8 100644 --- a/src/containers/internal/views/phone-numbers/index.tsx +++ b/src/containers/internal/views/phone-numbers/index.tsx @@ -4,6 +4,7 @@ import { Link } from "react-router-dom"; import { deletePhoneNumber, + getPhoneNumbers, putPhoneNumber, useServiceProviderData, } from "src/api"; @@ -30,7 +31,7 @@ import { import { DeletePhoneNumber } from "./delete"; import type { Account, PhoneNumber, Carrier, Application } from "src/api/types"; -import { USER_ACCOUNT } from "src/api/constants"; +import { ENABLE_PHONE_NUMBER_LAZY_LOAD, USER_ACCOUNT } from "src/api/constants"; import { ScopedAccess } from "src/components/scoped-access"; import { Scope } from "src/store/types"; import { getAccountFilter, setLocation } from "src/store/localStore"; @@ -41,8 +42,7 @@ export const PhoneNumbers = () => { const [applications] = useServiceProviderData("Applications"); const [carriers] = useServiceProviderData("VoipCarriers"); const [phoneNumber, setPhoneNumber] = useState(null); - const [phoneNumbers, refetch] = - useServiceProviderData("PhoneNumbers"); + const [phoneNumbers, setPhoneNumbers] = useState(null); const [selectedPhoneNumbers, setSelectedPhoneNumbers] = useState< PhoneNumber[] >([]); @@ -59,12 +59,30 @@ export const PhoneNumbers = () => { (phn) => !accountSid || phn.account_sid === accountSid, ) : []; - }, [accountSid, phoneNumbers]); + }, [phoneNumbers, ...[!ENABLE_PHONE_NUMBER_LAZY_LOAD && accountSid]]); - const filteredPhoneNumbers = useFilteredResults( - filter, - phoneNumbersFiltered, - ); + const filteredPhoneNumbers = !ENABLE_PHONE_NUMBER_LAZY_LOAD + ? useFilteredResults(filter, phoneNumbersFiltered) + : phoneNumbersFiltered; + + const refetch = () => { + getPhoneNumbers( + !ENABLE_PHONE_NUMBER_LAZY_LOAD + ? {} + : { + ...(accountSid && { account_sid: accountSid }), + ...(filter && { filter }), + }, + ) + .then(({ json }) => { + if (json) { + setPhoneNumbers(json); + } + }) + .catch((error) => { + toastError(error.msg); + }); + }; const handleMassEdit = () => { Promise.all( @@ -114,6 +132,15 @@ export const PhoneNumbers = () => { } }, [user]); + useEffect(() => { + if (ENABLE_PHONE_NUMBER_LAZY_LOAD) { + setPhoneNumbers([]); + return; + } + + refetch(); + }, []); + return ( <>
@@ -141,6 +168,19 @@ export const PhoneNumbers = () => { defaultOption /> + {ENABLE_PHONE_NUMBER_LAZY_LOAD && ( + + + + )}