mirror of
https://github.com/jambonz/jambonz-webapp.git
synced 2026-07-04 19:21:58 +00:00
some S3 compatible storage systems have a region parameter (#524)
* some S3 compatible storage systems have a region parameter * wip * wip * replace current toastMethod by new toastProvider * wip * fix failing testcase * wip
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { Icons } from "src/components/icons";
|
import { Icons } from "src/components/icons";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
import { useToast } from "../toast/toast-provider";
|
||||||
|
|
||||||
type ClipBoardProps = {
|
type ClipBoardProps = {
|
||||||
id?: string;
|
id?: string;
|
||||||
@@ -13,6 +13,7 @@ type ClipBoardProps = {
|
|||||||
const hasClipboard = typeof navigator.clipboard !== "undefined";
|
const hasClipboard = typeof navigator.clipboard !== "undefined";
|
||||||
|
|
||||||
export const ClipBoard = ({ text, id = "", name = "" }: ClipBoardProps) => {
|
export const ClipBoard = ({ text, id = "", name = "" }: ClipBoardProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
navigator.clipboard
|
navigator.clipboard
|
||||||
.writeText(text)
|
.writeText(text)
|
||||||
|
|||||||
@@ -2,15 +2,18 @@ import React from "react";
|
|||||||
import { H1 } from "@jambonz/ui-kit";
|
import { H1 } from "@jambonz/ui-kit";
|
||||||
|
|
||||||
import { RequireAuth } from "./require-auth";
|
import { RequireAuth } from "./require-auth";
|
||||||
|
import { ToastProvider } from "./toast/toast-provider";
|
||||||
|
|
||||||
/** Wrapper to pass different auth contexts */
|
/** Wrapper to pass different auth contexts */
|
||||||
const RequireAuthTestWrapper = () => {
|
const RequireAuthTestWrapper = () => {
|
||||||
return (
|
return (
|
||||||
<RequireAuth>
|
<ToastProvider>
|
||||||
<div className="auth-div">
|
<RequireAuth>
|
||||||
<H1>Protected Route</H1>
|
<div className="auth-div">
|
||||||
</div>
|
<H1>Protected Route</H1>
|
||||||
</RequireAuth>
|
</div>
|
||||||
|
</RequireAuth>
|
||||||
|
</ToastProvider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ import React, { useEffect } from "react";
|
|||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { useAuth } from "src/router/auth";
|
import { useAuth } from "src/router/auth";
|
||||||
import { toastError } from "src/store";
|
|
||||||
import { ROUTE_LOGIN } from "src/router/routes";
|
import { ROUTE_LOGIN } from "src/router/routes";
|
||||||
import { MSG_MUST_LOGIN } from "src/constants";
|
import { MSG_MUST_LOGIN } from "src/constants";
|
||||||
|
import { useToast } from "./toast/toast-provider";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper component that enforces valid authorization to the app
|
* Wrapper component that enforces valid authorization to the app
|
||||||
*/
|
*/
|
||||||
export const RequireAuth = ({ children }: { children: React.ReactNode }) => {
|
export const RequireAuth = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const { authorized } = useAuth();
|
const { authorized } = useAuth();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
import React, {
|
||||||
|
createContext,
|
||||||
|
useContext,
|
||||||
|
useState,
|
||||||
|
useCallback,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
} from "react";
|
||||||
|
import { Toast } from "./index";
|
||||||
|
import type { IMessage, Toast as ToastProps } from "src/store/types";
|
||||||
|
import { TOAST_TIME } from "src/constants";
|
||||||
|
|
||||||
|
// Define the context type
|
||||||
|
interface ToastContextType {
|
||||||
|
toastSuccess: (message: IMessage) => void;
|
||||||
|
toastError: (message: IMessage) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the context with a default value
|
||||||
|
const ToastContext = createContext<ToastContextType | undefined>(undefined);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provider component that makes toast functionality available to any
|
||||||
|
* nested components that call useToast().
|
||||||
|
*/
|
||||||
|
export const ToastProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||||
|
children,
|
||||||
|
}) => {
|
||||||
|
const [toast, setToast] = useState<ToastProps | null>(null);
|
||||||
|
const timeoutRef = useRef<number | null>(null);
|
||||||
|
|
||||||
|
// Clear any existing toasts and timeouts
|
||||||
|
const clearToast = useCallback(() => {
|
||||||
|
setToast(null);
|
||||||
|
if (timeoutRef.current !== null) {
|
||||||
|
clearTimeout(timeoutRef.current);
|
||||||
|
timeoutRef.current = null;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// Show a toast with the specified type and message
|
||||||
|
const showToast = useCallback(
|
||||||
|
(type: "success" | "error", message: IMessage) => {
|
||||||
|
clearToast();
|
||||||
|
|
||||||
|
setToast({ type, message });
|
||||||
|
|
||||||
|
// Auto-hide after specified time
|
||||||
|
timeoutRef.current = window.setTimeout(() => {
|
||||||
|
setToast(null);
|
||||||
|
}, TOAST_TIME);
|
||||||
|
},
|
||||||
|
[clearToast],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Exposed methods
|
||||||
|
const toastSuccess = useCallback(
|
||||||
|
(message: IMessage) => {
|
||||||
|
showToast("success", message);
|
||||||
|
},
|
||||||
|
[showToast],
|
||||||
|
);
|
||||||
|
|
||||||
|
const toastError = useCallback(
|
||||||
|
(message: IMessage) => {
|
||||||
|
showToast("error", message);
|
||||||
|
},
|
||||||
|
[showToast],
|
||||||
|
);
|
||||||
|
|
||||||
|
// Context value
|
||||||
|
const contextValue = useMemo(
|
||||||
|
() => ({
|
||||||
|
toastSuccess,
|
||||||
|
toastError,
|
||||||
|
}),
|
||||||
|
[toastSuccess, toastError],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ToastContext.Provider value={contextValue}>
|
||||||
|
{children}
|
||||||
|
{toast && <Toast type={toast.type} message={toast.message} />}
|
||||||
|
</ToastContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useToast = () => {
|
||||||
|
const context = useContext(ToastContext);
|
||||||
|
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error("useToast must be used within a ToastProvider");
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
};
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { P, Button } from "@jambonz/ui-kit";
|
import { P, Button } from "@jambonz/ui-kit";
|
||||||
|
|
||||||
import { toastSuccess, toastError } from "src/store";
|
|
||||||
import { useApiData, postApiKey, deleteApiKey } from "src/api";
|
import { useApiData, postApiKey, deleteApiKey } from "src/api";
|
||||||
import { Modal, ModalClose, Obscure, ClipBoard, Section } from "src/components";
|
import { Modal, ModalClose, Obscure, ClipBoard, Section } from "src/components";
|
||||||
import { getHumanDateTime, hasLength } from "src/utils";
|
import { getHumanDateTime, hasLength } from "src/utils";
|
||||||
|
|
||||||
import type { ApiKey, TokenResponse } from "src/api/types";
|
import type { ApiKey, TokenResponse } from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type ApiKeyProps = {
|
type ApiKeyProps = {
|
||||||
path: string;
|
path: string;
|
||||||
@@ -18,6 +18,7 @@ type ApiKeyProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const ApiKeys = ({ path, post, label }: ApiKeyProps) => {
|
export const ApiKeys = ({ path, post, label }: ApiKeyProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const [apiKeys, apiKeysRefetcher] = useApiData<ApiKey[]>(path);
|
const [apiKeys, apiKeysRefetcher] = useApiData<ApiKey[]>(path);
|
||||||
const [deleteKey, setDeleteKey] = useState<ApiKey | null>(null);
|
const [deleteKey, setDeleteKey] = useState<ApiKey | null>(null);
|
||||||
const [addedKey, setAddedKey] = useState<TokenResponse | null>(null);
|
const [addedKey, setAddedKey] = useState<TokenResponse | null>(null);
|
||||||
|
|||||||
@@ -5,12 +5,7 @@ import { Link, useLocation, useNavigate } from "react-router-dom";
|
|||||||
import { Icons, ModalForm } from "src/components";
|
import { Icons, ModalForm } from "src/components";
|
||||||
import { naviTop, naviByo } from "./items";
|
import { naviTop, naviByo } from "./items";
|
||||||
import { UserMe } from "../user-me";
|
import { UserMe } from "../user-me";
|
||||||
import {
|
import { useSelectState, useDispatch } from "src/store";
|
||||||
useSelectState,
|
|
||||||
useDispatch,
|
|
||||||
toastSuccess,
|
|
||||||
toastError,
|
|
||||||
} from "src/store";
|
|
||||||
import {
|
import {
|
||||||
getActiveSP,
|
getActiveSP,
|
||||||
removeAccountFilter,
|
removeAccountFilter,
|
||||||
@@ -26,6 +21,7 @@ import { Scope, UserData } from "src/store/types";
|
|||||||
import { USER_ADMIN } from "src/api/constants";
|
import { USER_ADMIN } from "src/api/constants";
|
||||||
import { ROUTE_LOGIN } from "src/router/routes";
|
import { ROUTE_LOGIN } from "src/router/routes";
|
||||||
import { Lcr } from "src/api/types";
|
import { Lcr } from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type CommonProps = {
|
type CommonProps = {
|
||||||
handleMenu: () => void;
|
handleMenu: () => void;
|
||||||
@@ -67,6 +63,7 @@ export const Navi = ({
|
|||||||
handleMenu,
|
handleMenu,
|
||||||
handleLogout,
|
handleLogout,
|
||||||
}: NaviProps) => {
|
}: NaviProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { useParams } from "react-router-dom";
|
|||||||
|
|
||||||
import { ApiKeys } from "src/containers/internal/api-keys";
|
import { ApiKeys } from "src/containers/internal/api-keys";
|
||||||
import { useApiData } from "src/api";
|
import { useApiData } from "src/api";
|
||||||
import { toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { AccountForm } from "./form";
|
import { AccountForm } from "./form";
|
||||||
|
|
||||||
import type { Account, Application, Limit, TtsCache } from "src/api/types";
|
import type { Account, Application, Limit, TtsCache } from "src/api/types";
|
||||||
@@ -14,8 +14,10 @@ import {
|
|||||||
} from "src/router/routes";
|
} from "src/router/routes";
|
||||||
import { useScopedRedirect } from "src/utils";
|
import { useScopedRedirect } from "src/utils";
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const EditAccount = () => {
|
export const EditAccount = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [data, refetch, error] = useApiData<Account>(
|
const [data, refetch, error] = useApiData<Account>(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef } from "react";
|
|||||||
import { P, Button, ButtonGroup, MS, Icon, H1 } from "@jambonz/ui-kit";
|
import { P, Button, ButtonGroup, MS, Icon, H1 } from "@jambonz/ui-kit";
|
||||||
import { Link, useNavigate, useParams } from "react-router-dom";
|
import { Link, useNavigate, useParams } from "react-router-dom";
|
||||||
|
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
putAccount,
|
putAccount,
|
||||||
postAccount,
|
postAccount,
|
||||||
@@ -75,6 +75,7 @@ import { EditBoard } from "src/components/editboard";
|
|||||||
import { ModalLoader } from "src/components/modal";
|
import { ModalLoader } from "src/components/modal";
|
||||||
import { useAuth } from "src/router/auth";
|
import { useAuth } from "src/router/auth";
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type AccountFormProps = {
|
type AccountFormProps = {
|
||||||
apps?: Application[];
|
apps?: Application[];
|
||||||
@@ -89,6 +90,7 @@ export const AccountForm = ({
|
|||||||
account,
|
account,
|
||||||
ttsCache,
|
ttsCache,
|
||||||
}: AccountFormProps) => {
|
}: AccountFormProps) => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
@@ -289,6 +291,7 @@ export const AccountForm = ({
|
|||||||
endpoint: endpoint,
|
endpoint: endpoint,
|
||||||
access_key_id: bucketAccessKeyId,
|
access_key_id: bucketAccessKeyId,
|
||||||
secret_access_key: bucketSecretAccessKey,
|
secret_access_key: bucketSecretAccessKey,
|
||||||
|
...(bucketRegion && { region: bucketRegion }),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -437,6 +440,9 @@ export const AccountForm = ({
|
|||||||
access_key_id: bucketAccessKeyId || null,
|
access_key_id: bucketAccessKeyId || null,
|
||||||
secret_access_key: bucketSecretAccessKey || null,
|
secret_access_key: bucketSecretAccessKey || null,
|
||||||
...(hasLength(bucketTags) && { tags: bucketTags }),
|
...(hasLength(bucketTags) && { tags: bucketTags }),
|
||||||
|
...(bucketRegion && {
|
||||||
|
region: bucketRegion,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
...(!bucketCredentialChecked && {
|
...(!bucketCredentialChecked && {
|
||||||
@@ -550,6 +556,10 @@ export const AccountForm = ({
|
|||||||
setBucketRegion(tmpBucketRegion);
|
setBucketRegion(tmpBucketRegion);
|
||||||
} else if (account.data.bucket_credential?.region) {
|
} else if (account.data.bucket_credential?.region) {
|
||||||
setBucketRegion(account.data.bucket_credential?.region);
|
setBucketRegion(account.data.bucket_credential?.region);
|
||||||
|
} else if (
|
||||||
|
account.data.bucket_credential?.vendor === BUCKET_VENDOR_S3_COMPATIBLE
|
||||||
|
) {
|
||||||
|
setBucketRegion("");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmpAzureConnectionString) {
|
if (tmpAzureConnectionString) {
|
||||||
@@ -583,9 +593,7 @@ export const AccountForm = ({
|
|||||||
JSON.parse(account.data.bucket_credential?.service_key),
|
JSON.parse(account.data.bucket_credential?.service_key),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
setInitialCheckRecordAllCall(
|
setInitialCheckRecordAllCall(hasValue(account.data.bucket_credential));
|
||||||
hasValue(bucketVendor) && bucketVendor.length !== 0,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}, [account]);
|
}, [account]);
|
||||||
|
|
||||||
@@ -1102,6 +1110,18 @@ export const AccountForm = ({
|
|||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
setBucketVendor(e.target.value);
|
setBucketVendor(e.target.value);
|
||||||
setTmpBucketVendor(e.target.value);
|
setTmpBucketVendor(e.target.value);
|
||||||
|
if (
|
||||||
|
e.target.value === BUCKET_VENDOR_AWS &&
|
||||||
|
!regions?.aws.find((r) => r.value === bucketRegion)
|
||||||
|
) {
|
||||||
|
setBucketRegion("us-east-1");
|
||||||
|
setTmpBucketRegion("us-east-1");
|
||||||
|
} else if (
|
||||||
|
e.target.value === BUCKET_VENDOR_S3_COMPATIBLE
|
||||||
|
) {
|
||||||
|
setBucketRegion("");
|
||||||
|
setTmpBucketRegion("");
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -1122,6 +1142,17 @@ export const AccountForm = ({
|
|||||||
setTmpEndpoint(e.target.value);
|
setTmpEndpoint(e.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<label htmlFor="endpoint">Region (Optional)</label>
|
||||||
|
<input
|
||||||
|
id="aws_compatible_region"
|
||||||
|
type="text"
|
||||||
|
name="aws_compatible_region"
|
||||||
|
value={bucketRegion}
|
||||||
|
onChange={(e) => {
|
||||||
|
setBucketRegion(e.target.value);
|
||||||
|
setTmpBucketRegion(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<label htmlFor="bucket_name">
|
<label htmlFor="bucket_name">
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useServiceProviderData, deleteAccount } from "src/api";
|
|||||||
import { ROUTE_INTERNAL_ACCOUNTS } from "src/router/routes";
|
import { ROUTE_INTERNAL_ACCOUNTS } from "src/router/routes";
|
||||||
import { Section, Icons, Spinner, SearchFilter } from "src/components";
|
import { Section, Icons, Spinner, SearchFilter } from "src/components";
|
||||||
import { DeleteAccount } from "./delete";
|
import { DeleteAccount } from "./delete";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
hasLength,
|
hasLength,
|
||||||
hasValue,
|
hasValue,
|
||||||
@@ -17,8 +17,10 @@ import { USER_ACCOUNT } from "src/api/constants";
|
|||||||
|
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import type { Account } from "src/api/types";
|
import type { Account } from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const Accounts = () => {
|
export const Accounts = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [accounts, refetch] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts, refetch] = useServiceProviderData<Account[]>("Accounts");
|
||||||
const [account, setAccount] = useState<Account | null>(null);
|
const [account, setAccount] = useState<Account | null>(null);
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ import { postSubscriptions, useApiData } from "src/api";
|
|||||||
import { CurrentUserData, Subscription } from "src/api/types";
|
import { CurrentUserData, Subscription } from "src/api/types";
|
||||||
import { Section } from "src/components";
|
import { Section } from "src/components";
|
||||||
import { ROUTE_INTERNAL_ACCOUNTS } from "src/router/routes";
|
import { ROUTE_INTERNAL_ACCOUNTS } from "src/router/routes";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { PaymentMethod } from "@stripe/stripe-js";
|
import { PaymentMethod } from "@stripe/stripe-js";
|
||||||
import { ModalLoader } from "src/components/modal";
|
import { ModalLoader } from "src/components/modal";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const ManagePaymentForm = () => {
|
export const ManagePaymentForm = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const stripe = useStripe();
|
const stripe = useStripe();
|
||||||
const elements = useElements();
|
const elements = useElements();
|
||||||
|
|||||||
@@ -19,10 +19,11 @@ import {
|
|||||||
useStripe,
|
useStripe,
|
||||||
} from "@stripe/react-stripe-js";
|
} from "@stripe/react-stripe-js";
|
||||||
import { PaymentMethod } from "@stripe/stripe-js";
|
import { PaymentMethod } from "@stripe/stripe-js";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
|
||||||
import { ModalLoader } from "src/components/modal";
|
import { ModalLoader } from "src/components/modal";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
const SubscriptionForm = () => {
|
const SubscriptionForm = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const [userData] = useApiData<CurrentUserData>("Users/me");
|
const [userData] = useApiData<CurrentUserData>("Users/me");
|
||||||
const [priceInfo] = useApiData<PriceInfo[]>("/Prices");
|
const [priceInfo] = useApiData<PriceInfo[]>("/Prices");
|
||||||
const [userStripeInfo] = useApiData<StripeCustomerId>("/StripeCustomerId");
|
const [userStripeInfo] = useApiData<StripeCustomerId>("/StripeCustomerId");
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
PER_PAGE_SELECTION,
|
PER_PAGE_SELECTION,
|
||||||
USER_ACCOUNT,
|
USER_ACCOUNT,
|
||||||
} from "src/api/constants";
|
} from "src/api/constants";
|
||||||
import { toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { hasLength, hasValue } from "src/utils";
|
import { hasLength, hasValue } from "src/utils";
|
||||||
import {
|
import {
|
||||||
AccountFilter,
|
AccountFilter,
|
||||||
@@ -27,8 +27,10 @@ import {
|
|||||||
setLocation,
|
setLocation,
|
||||||
} from "src/store/localStore";
|
} from "src/store/localStore";
|
||||||
import AlertDetailItem from "./alert-detail-item";
|
import AlertDetailItem from "./alert-detail-item";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const Alerts = () => {
|
export const Alerts = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
||||||
const [accountSid, setAccountSid] = useState("");
|
const [accountSid, setAccountSid] = useState("");
|
||||||
|
|||||||
@@ -3,15 +3,17 @@ import { H1 } from "@jambonz/ui-kit";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
import { useApiData } from "src/api";
|
import { useApiData } from "src/api";
|
||||||
import { toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { ApplicationForm } from "./form";
|
import { ApplicationForm } from "./form";
|
||||||
|
|
||||||
import type { Application } from "src/api/types";
|
import type { Application } from "src/api/types";
|
||||||
import { useScopedRedirect } from "src/utils/use-scoped-redirect";
|
import { useScopedRedirect } from "src/utils/use-scoped-redirect";
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import { ROUTE_INTERNAL_APPLICATIONS } from "src/router/routes";
|
import { ROUTE_INTERNAL_APPLICATIONS } from "src/router/routes";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const EditApplication = () => {
|
export const EditApplication = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [data, refetch, error] = useApiData<Application>(
|
const [data, refetch, error] = useApiData<Application>(
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useRef, useState } from "react";
|
|||||||
import { Button, ButtonGroup, MS } from "@jambonz/ui-kit";
|
import { Button, ButtonGroup, MS } from "@jambonz/ui-kit";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { ClipBoard, Section, Tooltip } from "src/components";
|
import { ClipBoard, Section, Tooltip } from "src/components";
|
||||||
import {
|
import {
|
||||||
Selector,
|
Selector,
|
||||||
@@ -57,12 +57,14 @@ import { hasLength, isUserAccountScope, useRedirect } from "src/utils";
|
|||||||
import { setAccountFilter, setLocation } from "src/store/localStore";
|
import { setAccountFilter, setLocation } from "src/store/localStore";
|
||||||
import SpeechProviderSelection from "./speech-selection";
|
import SpeechProviderSelection from "./speech-selection";
|
||||||
import ObscureInput from "src/components/obscure-input";
|
import ObscureInput from "src/components/obscure-input";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type ApplicationFormProps = {
|
type ApplicationFormProps = {
|
||||||
application?: UseApiDataMap<Application>;
|
application?: UseApiDataMap<Application>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ApplicationForm = ({ application }: ApplicationFormProps) => {
|
export const ApplicationForm = ({ application }: ApplicationFormProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import {
|
|||||||
SelectFilter,
|
SelectFilter,
|
||||||
} from "src/components";
|
} from "src/components";
|
||||||
import { DeleteApplication } from "./delete";
|
import { DeleteApplication } from "./delete";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { isUserAccountScope, hasLength, hasValue } from "src/utils";
|
import { isUserAccountScope, hasLength, hasValue } from "src/utils";
|
||||||
|
|
||||||
import type { Application, Account } from "src/api/types";
|
import type { Application, Account } from "src/api/types";
|
||||||
@@ -29,8 +29,10 @@ import { ScopedAccess } from "src/components/scoped-access";
|
|||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import { PER_PAGE_SELECTION, USER_ACCOUNT } from "src/api/constants";
|
import { PER_PAGE_SELECTION, USER_ACCOUNT } from "src/api/constants";
|
||||||
import { getAccountFilter, setLocation } from "src/store/localStore";
|
import { getAccountFilter, setLocation } from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const Applications = () => {
|
export const Applications = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
||||||
const [accountSid, setAccountSid] = useState("");
|
const [accountSid, setAccountSid] = useState("");
|
||||||
|
|||||||
@@ -10,7 +10,8 @@ import {
|
|||||||
} from "src/api/types";
|
} from "src/api/types";
|
||||||
import { Selector } from "src/components/forms";
|
import { Selector } from "src/components/forms";
|
||||||
import { SelectorOption } from "src/components/forms/selector";
|
import { SelectorOption } from "src/components/forms/selector";
|
||||||
import { toastError, useSelectState } from "src/store";
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
import { useSelectState } from "src/store";
|
||||||
import { hasLength } from "src/utils";
|
import { hasLength } from "src/utils";
|
||||||
import {
|
import {
|
||||||
ELEVENLABS_LANG_EN,
|
ELEVENLABS_LANG_EN,
|
||||||
@@ -82,6 +83,7 @@ export const SpeechProviderSelection = ({
|
|||||||
sttLabelOptions,
|
sttLabelOptions,
|
||||||
sttLabel: [recogLabel, setRecogLabel],
|
sttLabel: [recogLabel, setRecogLabel],
|
||||||
}: SpeechProviderSelectionProbs) => {
|
}: SpeechProviderSelectionProbs) => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [
|
const [
|
||||||
synthesisSupportedLanguagesAndVoices,
|
synthesisSupportedLanguagesAndVoices,
|
||||||
|
|||||||
@@ -3,15 +3,17 @@ import { H1 } from "@jambonz/ui-kit";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
import { useApiData } from "src/api";
|
import { useApiData } from "src/api";
|
||||||
import { toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { CarrierForm } from "./form";
|
import { CarrierForm } from "./form";
|
||||||
|
|
||||||
import { Carrier, SipGateway, SmppGateway } from "src/api/types";
|
import { Carrier, SipGateway, SmppGateway } from "src/api/types";
|
||||||
import { useScopedRedirect } from "src/utils/use-scoped-redirect";
|
import { useScopedRedirect } from "src/utils/use-scoped-redirect";
|
||||||
import { ROUTE_INTERNAL_CARRIERS } from "src/router/routes";
|
import { ROUTE_INTERNAL_CARRIERS } from "src/router/routes";
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const EditCarrier = () => {
|
export const EditCarrier = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [data, refetch, error] = useApiData<Carrier>(
|
const [data, refetch, error] = useApiData<Carrier>(
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import {
|
|||||||
} from "src/components/forms";
|
} from "src/components/forms";
|
||||||
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
||||||
import { ROUTE_INTERNAL_CARRIERS } from "src/router/routes";
|
import { ROUTE_INTERNAL_CARRIERS } from "src/router/routes";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
checkSelectOptions,
|
checkSelectOptions,
|
||||||
getIpValidationType,
|
getIpValidationType,
|
||||||
@@ -67,6 +67,7 @@ import {
|
|||||||
} from "src/api/types";
|
} from "src/api/types";
|
||||||
import { setAccountFilter, setLocation } from "src/store/localStore";
|
import { setAccountFilter, setLocation } from "src/store/localStore";
|
||||||
import { RegisterStatus } from "./register-status";
|
import { RegisterStatus } from "./register-status";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type CarrierFormProps = {
|
type CarrierFormProps = {
|
||||||
carrier?: UseApiDataMap<Carrier>;
|
carrier?: UseApiDataMap<Carrier>;
|
||||||
@@ -79,6 +80,7 @@ export const CarrierForm = ({
|
|||||||
carrierSipGateways,
|
carrierSipGateways,
|
||||||
carrierSmppGateways,
|
carrierSmppGateways,
|
||||||
}: CarrierFormProps) => {
|
}: CarrierFormProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import {
|
|||||||
useApiData,
|
useApiData,
|
||||||
useServiceProviderData,
|
useServiceProviderData,
|
||||||
} from "src/api";
|
} from "src/api";
|
||||||
import { toastSuccess, toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { ROUTE_INTERNAL_CARRIERS } from "src/router/routes";
|
import { ROUTE_INTERNAL_CARRIERS } from "src/router/routes";
|
||||||
import {
|
import {
|
||||||
AccountFilter,
|
AccountFilter,
|
||||||
@@ -43,8 +43,10 @@ import type {
|
|||||||
} from "src/api/types";
|
} from "src/api/types";
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import { getAccountFilter, setLocation } from "src/store/localStore";
|
import { getAccountFilter, setLocation } from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const Carriers = () => {
|
export const Carriers = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [userData] = useApiData<CurrentUserData>("Users/me");
|
const [userData] = useApiData<CurrentUserData>("Users/me");
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import {
|
|||||||
getPcap,
|
getPcap,
|
||||||
getServiceProviderPcap,
|
getServiceProviderPcap,
|
||||||
} from "src/api";
|
} from "src/api";
|
||||||
import { toastError } from "src/store";
|
|
||||||
|
|
||||||
import type { DownloadedBlob } from "src/api/types";
|
import type { DownloadedBlob } from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type PcapButtonProps = {
|
type PcapButtonProps = {
|
||||||
accountSid: string;
|
accountSid: string;
|
||||||
@@ -21,6 +21,7 @@ export const PcapButton = ({
|
|||||||
serviceProviderSid,
|
serviceProviderSid,
|
||||||
sipCallId,
|
sipCallId,
|
||||||
}: PcapButtonProps) => {
|
}: PcapButtonProps) => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const [pcap, setPcap] = useState<DownloadedBlob>();
|
const [pcap, setPcap] = useState<DownloadedBlob>();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import React, { useEffect } from "react";
|
|||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { useApiData } from "src/api";
|
import { useApiData } from "src/api";
|
||||||
import { Client } from "src/api/types";
|
import { Client } from "src/api/types";
|
||||||
import { toastError } from "src/store";
|
|
||||||
import ClientsForm from "./form";
|
import ClientsForm from "./form";
|
||||||
import { ROUTE_INTERNAL_CLIENTS } from "src/router/routes";
|
import { ROUTE_INTERNAL_CLIENTS } from "src/router/routes";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const ClientsEdit = () => {
|
export const ClientsEdit = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [data, refetch, error] = useApiData<Client>(
|
const [data, refetch, error] = useApiData<Client>(
|
||||||
|
|||||||
@@ -13,16 +13,18 @@ import { Section, Tooltip } from "src/components";
|
|||||||
import { AccountSelect, Message, Passwd } from "src/components/forms";
|
import { AccountSelect, Message, Passwd } from "src/components/forms";
|
||||||
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
||||||
import { ROUTE_INTERNAL_CLIENTS } from "src/router/routes";
|
import { ROUTE_INTERNAL_CLIENTS } from "src/router/routes";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import ClientsDelete from "./delete";
|
import ClientsDelete from "./delete";
|
||||||
import { hasValue } from "src/utils";
|
import { hasValue } from "src/utils";
|
||||||
import { IMessage } from "src/store/types";
|
import { IMessage } from "src/store/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type ClientsFormProps = {
|
type ClientsFormProps = {
|
||||||
client?: UseApiDataMap<Client>;
|
client?: UseApiDataMap<Client>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ClientsForm = ({ client }: ClientsFormProps) => {
|
export const ClientsForm = ({ client }: ClientsFormProps) => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -12,14 +12,16 @@ import {
|
|||||||
Spinner,
|
Spinner,
|
||||||
} from "src/components";
|
} from "src/components";
|
||||||
import { ROUTE_INTERNAL_CLIENTS } from "src/router/routes";
|
import { ROUTE_INTERNAL_CLIENTS } from "src/router/routes";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import { hasLength, hasValue, useFilteredResults } from "src/utils";
|
import { hasLength, hasValue, useFilteredResults } from "src/utils";
|
||||||
import ClientsDelete from "./delete";
|
import ClientsDelete from "./delete";
|
||||||
import { USER_ACCOUNT } from "src/api/constants";
|
import { USER_ACCOUNT } from "src/api/constants";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
import { getAccountFilter } from "src/store/localStore";
|
import { getAccountFilter } from "src/store/localStore";
|
||||||
|
|
||||||
export const Clients = () => {
|
export const Clients = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [userData] = useApiData<CurrentUserData>("Users/me");
|
const [userData] = useApiData<CurrentUserData>("Users/me");
|
||||||
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import Card from "./card";
|
|||||||
import { hasLength } from "src/utils";
|
import { hasLength } from "src/utils";
|
||||||
import update from "immutability-helper";
|
import update from "immutability-helper";
|
||||||
import { deleteLcrRoute } from "src/api";
|
import { deleteLcrRoute } from "src/api";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
|
||||||
import { SelectorOption } from "src/components/forms/selector";
|
import { SelectorOption } from "src/components/forms/selector";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type ContainerProps = {
|
type ContainerProps = {
|
||||||
lcrRoute: [LcrRoute[], React.Dispatch<React.SetStateAction<LcrRoute[]>>];
|
lcrRoute: [LcrRoute[], React.Dispatch<React.SetStateAction<LcrRoute[]>>];
|
||||||
@@ -16,6 +16,7 @@ export const Container = ({
|
|||||||
lcrRoute: [lcrRoutes, setLcrRoutes],
|
lcrRoute: [lcrRoutes, setLcrRoutes],
|
||||||
carrierSelectorOptions,
|
carrierSelectorOptions,
|
||||||
}: ContainerProps) => {
|
}: ContainerProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const moveCard = (dragIndex: number, hoverIndex: number) => {
|
const moveCard = (dragIndex: number, hoverIndex: number) => {
|
||||||
setLcrRoutes((prevCards) =>
|
setLcrRoutes((prevCards) =>
|
||||||
update(prevCards, {
|
update(prevCards, {
|
||||||
|
|||||||
@@ -2,12 +2,7 @@ import React, { useEffect, useMemo, useState } from "react";
|
|||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { Button, ButtonGroup, Icon, MS, MXS } from "@jambonz/ui-kit";
|
import { Button, ButtonGroup, Icon, MS, MXS } from "@jambonz/ui-kit";
|
||||||
import { Icons, Section } from "src/components";
|
import { Icons, Section } from "src/components";
|
||||||
import {
|
import { useDispatch, useSelectState } from "src/store";
|
||||||
toastError,
|
|
||||||
toastSuccess,
|
|
||||||
useDispatch,
|
|
||||||
useSelectState,
|
|
||||||
} from "src/store";
|
|
||||||
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
||||||
import { setLocation } from "src/store/localStore";
|
import { setLocation } from "src/store/localStore";
|
||||||
import { AccountSelect, Message, Selector } from "src/components/forms";
|
import { AccountSelect, Message, Selector } from "src/components/forms";
|
||||||
@@ -35,6 +30,7 @@ import { DndProvider } from "react-dnd";
|
|||||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||||
import Container from "./container";
|
import Container from "./container";
|
||||||
import { hasValue } from "src/utils";
|
import { hasValue } from "src/utils";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type LcrFormProps = {
|
type LcrFormProps = {
|
||||||
lcrDataMap?: UseApiDataMap<Lcr>;
|
lcrDataMap?: UseApiDataMap<Lcr>;
|
||||||
@@ -56,6 +52,7 @@ export const LcrForm = ({ lcrDataMap, lcrRouteDataMap }: LcrFormProps) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import {
|
|||||||
} from "src/components";
|
} from "src/components";
|
||||||
import { ScopedAccess } from "src/components/scoped-access";
|
import { ScopedAccess } from "src/components/scoped-access";
|
||||||
import { ROUTE_INTERNAL_LEST_COST_ROUTING } from "src/router/routes";
|
import { ROUTE_INTERNAL_LEST_COST_ROUTING } from "src/router/routes";
|
||||||
import { toastSuccess, toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
// import { getAccountFilter, setLocation } from "src/store/localStore";
|
// import { getAccountFilter, setLocation } from "src/store/localStore";
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import {
|
import {
|
||||||
@@ -25,8 +25,10 @@ import {
|
|||||||
} from "src/utils";
|
} from "src/utils";
|
||||||
import { USER_ACCOUNT } from "src/api/constants";
|
import { USER_ACCOUNT } from "src/api/constants";
|
||||||
import DeleteLcr from "./delete";
|
import DeleteLcr from "./delete";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const Lcrs = () => {
|
export const Lcrs = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
useScopedRedirect(
|
useScopedRedirect(
|
||||||
Scope.admin,
|
Scope.admin,
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ import { H1 } from "@jambonz/ui-kit";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
import { useApiData } from "src/api";
|
import { useApiData } from "src/api";
|
||||||
import { toastError } from "src/store";
|
|
||||||
import { MsTeamsTenantForm } from "./form";
|
import { MsTeamsTenantForm } from "./form";
|
||||||
|
|
||||||
import type { MSTeamsTenant } from "src/api/types";
|
import type { MSTeamsTenant } from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const EditMsTeamsTenant = () => {
|
export const EditMsTeamsTenant = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const [data, refetch, error] = useApiData<MSTeamsTenant>(
|
const [data, refetch, error] = useApiData<MSTeamsTenant>(
|
||||||
`MicrosoftTeamsTenants/${params.ms_teams_tenant_sid}`,
|
`MicrosoftTeamsTenants/${params.ms_teams_tenant_sid}`,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
ApplicationSelect,
|
ApplicationSelect,
|
||||||
} from "src/components/forms";
|
} from "src/components/forms";
|
||||||
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
import { MSG_REQUIRED_FIELDS } from "src/constants";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
ROUTE_INTERNAL_ACCOUNTS,
|
ROUTE_INTERNAL_ACCOUNTS,
|
||||||
ROUTE_INTERNAL_MS_TEAMS_TENANTS,
|
ROUTE_INTERNAL_MS_TEAMS_TENANTS,
|
||||||
@@ -28,6 +28,7 @@ import type {
|
|||||||
MSTeamsTenant,
|
MSTeamsTenant,
|
||||||
UseApiDataMap,
|
UseApiDataMap,
|
||||||
} from "src/api/types";
|
} from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type MsTeamsTenantFormProps = {
|
type MsTeamsTenantFormProps = {
|
||||||
msTeamsTenant?: UseApiDataMap<MSTeamsTenant>;
|
msTeamsTenant?: UseApiDataMap<MSTeamsTenant>;
|
||||||
@@ -36,6 +37,7 @@ type MsTeamsTenantFormProps = {
|
|||||||
export const MsTeamsTenantForm = ({
|
export const MsTeamsTenantForm = ({
|
||||||
msTeamsTenant,
|
msTeamsTenant,
|
||||||
}: MsTeamsTenantFormProps) => {
|
}: MsTeamsTenantFormProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
withAccessControl,
|
withAccessControl,
|
||||||
useFilteredResults,
|
useFilteredResults,
|
||||||
} from "src/utils";
|
} from "src/utils";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
|
||||||
import {
|
import {
|
||||||
Icons,
|
Icons,
|
||||||
Section,
|
Section,
|
||||||
@@ -29,8 +28,10 @@ import { DeleteMsTeamsTenant } from "./delete";
|
|||||||
|
|
||||||
import type { Account, MSTeamsTenant, Application } from "src/api/types";
|
import type { Account, MSTeamsTenant, Application } from "src/api/types";
|
||||||
import type { ACLGetIMessage } from "src/utils/with-access-control";
|
import type { ACLGetIMessage } from "src/utils/with-access-control";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const MSTeamsTenants = () => {
|
export const MSTeamsTenants = () => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const [msTeamsTenant, setMsTeamsTenant] = useState<MSTeamsTenant | null>(
|
const [msTeamsTenant, setMsTeamsTenant] = useState<MSTeamsTenant | null>(
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ import { H1 } from "@jambonz/ui-kit";
|
|||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
import { useApiData } from "src/api";
|
import { useApiData } from "src/api";
|
||||||
import { toastError } from "src/store";
|
|
||||||
import { PhoneNumberForm } from "./form";
|
import { PhoneNumberForm } from "./form";
|
||||||
|
|
||||||
import type { PhoneNumber } from "src/api/types";
|
import type { PhoneNumber } from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const EditPhoneNumber = () => {
|
export const EditPhoneNumber = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const [data, refetch, error] = useApiData<PhoneNumber>(
|
const [data, refetch, error] = useApiData<PhoneNumber>(
|
||||||
`PhoneNumbers/${params.phone_number_sid}`,
|
`PhoneNumbers/${params.phone_number_sid}`,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import {
|
|||||||
ROUTE_INTERNAL_CARRIERS,
|
ROUTE_INTERNAL_CARRIERS,
|
||||||
ROUTE_INTERNAL_PHONE_NUMBERS,
|
ROUTE_INTERNAL_PHONE_NUMBERS,
|
||||||
} from "src/router/routes";
|
} from "src/router/routes";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
|
||||||
import { hasLength, useRedirect } from "src/utils";
|
import { hasLength, useRedirect } from "src/utils";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
@@ -31,12 +30,14 @@ import type {
|
|||||||
UseApiDataMap,
|
UseApiDataMap,
|
||||||
} from "src/api/types";
|
} from "src/api/types";
|
||||||
import { setAccountFilter, setLocation } from "src/store/localStore";
|
import { setAccountFilter, setLocation } from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type PhoneNumberFormProps = {
|
type PhoneNumberFormProps = {
|
||||||
phoneNumber?: UseApiDataMap<PhoneNumber>;
|
phoneNumber?: UseApiDataMap<PhoneNumber>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PhoneNumberForm = ({ phoneNumber }: PhoneNumberFormProps) => {
|
export const PhoneNumberForm = ({ phoneNumber }: PhoneNumberFormProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
||||||
const [applications] = useServiceProviderData<Application[]>("Applications");
|
const [applications] = useServiceProviderData<Application[]>("Applications");
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
putPhoneNumber,
|
putPhoneNumber,
|
||||||
useServiceProviderData,
|
useServiceProviderData,
|
||||||
} from "src/api";
|
} from "src/api";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
Icons,
|
Icons,
|
||||||
Section,
|
Section,
|
||||||
@@ -32,8 +32,10 @@ import { PER_PAGE_SELECTION, USER_ACCOUNT } from "src/api/constants";
|
|||||||
import { ScopedAccess } from "src/components/scoped-access";
|
import { ScopedAccess } from "src/components/scoped-access";
|
||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import { getAccountFilter, setLocation } from "src/store/localStore";
|
import { getAccountFilter, setLocation } from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const PhoneNumbers = () => {
|
export const PhoneNumbers = () => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { getRecentCallLog } from "src/api";
|
import { getRecentCallLog } from "src/api";
|
||||||
import { RecentCall } from "src/api/types";
|
import { RecentCall } from "src/api/types";
|
||||||
import { Icons, Spinner } from "src/components";
|
import { Icons, Spinner } from "src/components";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
|
||||||
import { hasValue } from "src/utils";
|
import { hasValue } from "src/utils";
|
||||||
import utc from "dayjs/plugin/utc";
|
import utc from "dayjs/plugin/utc";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
|
|
||||||
type CallSystemLogsProps = {
|
type CallSystemLogsProps = {
|
||||||
@@ -29,6 +29,7 @@ const formatLog = (log: string): string => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function CallSystemLogs({ call }: CallSystemLogsProps) {
|
export default function CallSystemLogs({ call }: CallSystemLogsProps) {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const [logs, setLogs] = useState<string[] | null>();
|
const [logs, setLogs] = useState<string[] | null>();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [count, setCount] = useState(0);
|
const [count, setCount] = useState(0);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import {
|
|||||||
PER_PAGE_SELECTION,
|
PER_PAGE_SELECTION,
|
||||||
USER_ACCOUNT,
|
USER_ACCOUNT,
|
||||||
} from "src/api/constants";
|
} from "src/api/constants";
|
||||||
import { toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
Section,
|
Section,
|
||||||
AccountFilter,
|
AccountFilter,
|
||||||
@@ -28,6 +28,7 @@ import {
|
|||||||
getQueryFilter,
|
getQueryFilter,
|
||||||
setLocation,
|
setLocation,
|
||||||
} from "src/store/localStore";
|
} from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
const directionSelection = [
|
const directionSelection = [
|
||||||
{ name: "either", value: "io" },
|
{ name: "either", value: "io" },
|
||||||
@@ -42,6 +43,7 @@ const statusSelection = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const RecentCalls = () => {
|
export const RecentCalls = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
const [accounts] = useServiceProviderData<Account[]>("Accounts");
|
||||||
const [accountSid, setAccountSid] = useState("");
|
const [accountSid, setAccountSid] = useState("");
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
|
|
||||||
import { getPcap } from "src/api";
|
import { getPcap } from "src/api";
|
||||||
import { toastError } from "src/store";
|
|
||||||
|
|
||||||
import type { DownloadedBlob, RecentCall } from "src/api/types";
|
import type { DownloadedBlob, RecentCall } from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type PcapButtonProps = {
|
type PcapButtonProps = {
|
||||||
call: RecentCall;
|
call: RecentCall;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PcapButton = ({ call }: PcapButtonProps) => {
|
export const PcapButton = ({ call }: PcapButtonProps) => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const [pcap, setPcap] = useState<DownloadedBlob | null>(null);
|
const [pcap, setPcap] = useState<DownloadedBlob | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ import {
|
|||||||
getSpansByNameRegex,
|
getSpansByNameRegex,
|
||||||
getSpansFromJaegerRoot,
|
getSpansFromJaegerRoot,
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type PlayerProps = {
|
type PlayerProps = {
|
||||||
call: RecentCall;
|
call: RecentCall;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Player = ({ call }: PlayerProps) => {
|
export const Player = ({ call }: PlayerProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const { recording_url, call_sid } = call;
|
const { recording_url, call_sid } = call;
|
||||||
const url =
|
const url =
|
||||||
recording_url && recording_url.startsWith("http://")
|
recording_url && recording_url.startsWith("http://")
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
SystemInformation,
|
SystemInformation,
|
||||||
TtsCache,
|
TtsCache,
|
||||||
} from "src/api/types";
|
} from "src/api/types";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
|
||||||
import { Selector } from "src/components/forms";
|
import { Selector } from "src/components/forms";
|
||||||
import { hasValue, isvalidIpv4OrCidr } from "src/utils";
|
import { hasValue, isvalidIpv4OrCidr } from "src/utils";
|
||||||
import {
|
import {
|
||||||
@@ -22,8 +21,10 @@ import {
|
|||||||
PASSWORD_MIN,
|
PASSWORD_MIN,
|
||||||
} from "src/api/constants";
|
} from "src/api/constants";
|
||||||
import { Modal } from "src/components";
|
import { Modal } from "src/components";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const AdminSettings = () => {
|
export const AdminSettings = () => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const [passwordSettings, passwordSettingsFetcher] =
|
const [passwordSettings, passwordSettingsFetcher] =
|
||||||
useApiData<PasswordSettings>("PasswordSettings");
|
useApiData<PasswordSettings>("PasswordSettings");
|
||||||
const [systemInformation, systemInformationFetcher] =
|
const [systemInformation, systemInformationFetcher] =
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { P, Button, ButtonGroup } from "@jambonz/ui-kit";
|
import { P, Button, ButtonGroup } from "@jambonz/ui-kit";
|
||||||
|
|
||||||
import { useDispatch, toastSuccess, toastError } from "src/store";
|
import { useDispatch } from "src/store";
|
||||||
import { hasLength } from "src/utils";
|
import { hasLength } from "src/utils";
|
||||||
import {
|
import {
|
||||||
putServiceProvider,
|
putServiceProvider,
|
||||||
@@ -15,6 +15,7 @@ import { Checkzone, LocalLimits } from "src/components/forms";
|
|||||||
import { withSelectState } from "src/utils";
|
import { withSelectState } from "src/utils";
|
||||||
import type { Limit, ServiceProvider } from "src/api/types";
|
import type { Limit, ServiceProvider } from "src/api/types";
|
||||||
import { removeActiveSP } from "src/store/localStore";
|
import { removeActiveSP } from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export type ServiceProviderSettingsProps = {
|
export type ServiceProviderSettingsProps = {
|
||||||
serviceProviders: ServiceProvider[];
|
serviceProviders: ServiceProvider[];
|
||||||
@@ -25,6 +26,7 @@ export const ServiceProviderSettings = ({
|
|||||||
serviceProviders,
|
serviceProviders,
|
||||||
currentServiceProvider,
|
currentServiceProvider,
|
||||||
}: ServiceProviderSettingsProps) => {
|
}: ServiceProviderSettingsProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const [limits, refetchLimits] = useServiceProviderData<Limit[]>("Limits");
|
const [limits, refetchLimits] = useServiceProviderData<Limit[]>("Limits");
|
||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { H1 } from "@jambonz/ui-kit";
|
import { H1 } from "@jambonz/ui-kit";
|
||||||
|
|
||||||
import { useApiData } from "src/api";
|
import { useApiData } from "src/api";
|
||||||
import { toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import { SpeechServiceForm } from "./form";
|
import { SpeechServiceForm } from "./form";
|
||||||
|
|
||||||
import type { SpeechCredential } from "src/api/types";
|
import type { SpeechCredential } from "src/api/types";
|
||||||
@@ -11,6 +11,7 @@ import { useScopedRedirect } from "src/utils/use-scoped-redirect";
|
|||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import { ROUTE_INTERNAL_SPEECH } from "src/router/routes";
|
import { ROUTE_INTERNAL_SPEECH } from "src/router/routes";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const EditSpeechService = () => {
|
export const EditSpeechService = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
@@ -18,6 +19,7 @@ export const EditSpeechService = () => {
|
|||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
const [url, setUrl] = useState("");
|
const [url, setUrl] = useState("");
|
||||||
const [data, refetch, error] = useApiData<SpeechCredential>(url);
|
const [data, refetch, error] = useApiData<SpeechCredential>(url);
|
||||||
|
const { toastError } = useToast();
|
||||||
|
|
||||||
useScopedRedirect(
|
useScopedRedirect(
|
||||||
Scope.account,
|
Scope.account,
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
Checkzone,
|
Checkzone,
|
||||||
Message,
|
Message,
|
||||||
} from "src/components/forms";
|
} from "src/components/forms";
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
deleteGoogleCustomVoice,
|
deleteGoogleCustomVoice,
|
||||||
getGoogleCustomVoices,
|
getGoogleCustomVoices,
|
||||||
@@ -91,12 +91,14 @@ import {
|
|||||||
GOOGLE_CUSTOM_VOICES_REPORTED_USAGE,
|
GOOGLE_CUSTOM_VOICES_REPORTED_USAGE,
|
||||||
VERBIO_STT_MODELS,
|
VERBIO_STT_MODELS,
|
||||||
} from "src/api/constants";
|
} from "src/api/constants";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type SpeechServiceFormProps = {
|
type SpeechServiceFormProps = {
|
||||||
credential?: UseApiDataMap<SpeechCredential>;
|
credential?: UseApiDataMap<SpeechCredential>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
|
export const SpeechServiceForm = ({ credential }: SpeechServiceFormProps) => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Link } from "react-router-dom";
|
|||||||
|
|
||||||
import { USER_ACCOUNT } from "src/api/constants";
|
import { USER_ACCOUNT } from "src/api/constants";
|
||||||
import { AccountFilter, Icons, Section, Spinner } from "src/components";
|
import { AccountFilter, Icons, Section, Spinner } from "src/components";
|
||||||
import { useSelectState, toastError, toastSuccess } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
deleteSpeechService,
|
deleteSpeechService,
|
||||||
useServiceProviderData,
|
useServiceProviderData,
|
||||||
@@ -26,8 +26,10 @@ import { ScopedAccess } from "src/components/scoped-access";
|
|||||||
import { Scope } from "src/store/types";
|
import { Scope } from "src/store/types";
|
||||||
import { getAccountFilter, setLocation } from "src/store/localStore";
|
import { getAccountFilter, setLocation } from "src/store/localStore";
|
||||||
import { VENDOR_CUSTOM } from "src/vendor";
|
import { VENDOR_CUSTOM } from "src/vendor";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const SpeechServices = () => {
|
export const SpeechServices = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const user = useSelectState("user");
|
const user = useSelectState("user");
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
const [apiUrl, setApiUrl] = useState("");
|
const [apiUrl, setApiUrl] = useState("");
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ import { useParams } from "react-router-dom";
|
|||||||
import { UserForm } from "./form";
|
import { UserForm } from "./form";
|
||||||
import { useApiData } from "src/api";
|
import { useApiData } from "src/api";
|
||||||
import { User } from "src/api/types";
|
import { User } from "src/api/types";
|
||||||
import { toastError } from "src/store";
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const EditUser = () => {
|
export const EditUser = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const [data, refetch, error] = useApiData<User>(`Users/${params.user_sid}`);
|
const [data, refetch, error] = useApiData<User>(`Users/${params.user_sid}`);
|
||||||
|
const { toastError } = useToast();
|
||||||
|
|
||||||
/** Handle error toast at top level... */
|
/** Handle error toast at top level... */
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
|
|||||||
import { Button, ButtonGroup, MS } from "@jambonz/ui-kit";
|
import { Button, ButtonGroup, MS } from "@jambonz/ui-kit";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { toastError, toastSuccess, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
import {
|
import {
|
||||||
deleteUser,
|
deleteUser,
|
||||||
postFetch,
|
postFetch,
|
||||||
@@ -38,12 +38,14 @@ import type {
|
|||||||
} from "src/api/types";
|
} from "src/api/types";
|
||||||
import type { IMessage } from "src/store/types";
|
import type { IMessage } from "src/store/types";
|
||||||
import { setAccountFilter, setLocation } from "src/store/localStore";
|
import { setAccountFilter, setLocation } from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type UserFormProps = {
|
type UserFormProps = {
|
||||||
user?: UseApiDataMap<User>;
|
user?: UseApiDataMap<User>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const UserForm = ({ user }: UserFormProps) => {
|
export const UserForm = ({ user }: UserFormProps) => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const { signout } = useAuth();
|
const { signout } = useAuth();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const currentUser = useSelectState("user");
|
const currentUser = useSelectState("user");
|
||||||
|
|||||||
@@ -8,9 +8,10 @@ import { useNavigate } from "react-router-dom";
|
|||||||
import { MSG_SOMETHING_WRONG } from "src/constants";
|
import { MSG_SOMETHING_WRONG } from "src/constants";
|
||||||
|
|
||||||
import { ROUTE_LOGIN } from "src/router/routes";
|
import { ROUTE_LOGIN } from "src/router/routes";
|
||||||
import { toastSuccess } from "src/store";
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const ForgotPassword = () => {
|
export const ForgotPassword = () => {
|
||||||
|
const { toastSuccess } = useToast();
|
||||||
const [message, setMessage] = useState("");
|
const [message, setMessage] = useState("");
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { Button, H1 } from "@jambonz/ui-kit";
|
import { Button, H1 } from "@jambonz/ui-kit";
|
||||||
import { useLocation, Navigate, Link } from "react-router-dom";
|
import { useLocation, Navigate, Link } from "react-router-dom";
|
||||||
|
|
||||||
import { toastError, toastSuccess } from "src/store";
|
|
||||||
import { getToken, parseJwt, useAuth } from "src/router/auth";
|
import { getToken, parseJwt, useAuth } from "src/router/auth";
|
||||||
import {
|
import {
|
||||||
SESS_FLASH_MSG,
|
SESS_FLASH_MSG,
|
||||||
@@ -26,8 +25,10 @@ import { v4 as uuid } from "uuid";
|
|||||||
import { setLocationBeforeOauth, setOauthState } from "src/store/localStore";
|
import { setLocationBeforeOauth, setOauthState } from "src/store/localStore";
|
||||||
import { getGithubOauthUrl, getGoogleOauthUrl } from "./utils";
|
import { getGithubOauthUrl, getGoogleOauthUrl } from "./utils";
|
||||||
import { UserData } from "src/store/types";
|
import { UserData } from "src/store/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const Login = () => {
|
export const Login = () => {
|
||||||
|
const { toastSuccess, toastError } = useToast();
|
||||||
const state = uuid();
|
const state = uuid();
|
||||||
setOauthState(state);
|
setOauthState(state);
|
||||||
setLocationBeforeOauth("/sign-in");
|
setLocationBeforeOauth("/sign-in");
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
BASE_URL,
|
BASE_URL,
|
||||||
} from "src/api/constants";
|
} from "src/api/constants";
|
||||||
import { Spinner } from "src/components";
|
import { Spinner } from "src/components";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
import { setToken } from "src/router/auth";
|
import { setToken } from "src/router/auth";
|
||||||
import {
|
import {
|
||||||
ROUTE_INTERNAL_ACCOUNTS,
|
ROUTE_INTERNAL_ACCOUNTS,
|
||||||
@@ -15,7 +16,6 @@ import {
|
|||||||
ROUTE_REGISTER,
|
ROUTE_REGISTER,
|
||||||
ROUTE_REGISTER_SUB_DOMAIN,
|
ROUTE_REGISTER_SUB_DOMAIN,
|
||||||
} from "src/router/routes";
|
} from "src/router/routes";
|
||||||
import { toastError } from "src/store";
|
|
||||||
import {
|
import {
|
||||||
getLocationBeforeOauth,
|
getLocationBeforeOauth,
|
||||||
getOauthState,
|
getOauthState,
|
||||||
@@ -25,6 +25,7 @@ import {
|
|||||||
} from "src/store/localStore";
|
} from "src/store/localStore";
|
||||||
|
|
||||||
export const OauthCallback = () => {
|
export const OauthCallback = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const queryParams = new URLSearchParams(location.search);
|
const queryParams = new URLSearchParams(location.search);
|
||||||
const code = queryParams.get("code");
|
const code = queryParams.get("code");
|
||||||
const newState = queryParams.get("state");
|
const newState = queryParams.get("state");
|
||||||
|
|||||||
@@ -7,10 +7,11 @@ import { Passwd } from "src/components/forms";
|
|||||||
import { ROUTE_LOGIN, ROUTE_REGISTER_EMAIL_VERIFY } from "src/router/routes";
|
import { ROUTE_LOGIN, ROUTE_REGISTER_EMAIL_VERIFY } from "src/router/routes";
|
||||||
import { generateActivationCode } from "./utils";
|
import { generateActivationCode } from "./utils";
|
||||||
import { setToken } from "src/router/auth";
|
import { setToken } from "src/router/auth";
|
||||||
import { toastError } from "src/store";
|
|
||||||
import { setRootDomain } from "src/store/localStore";
|
import { setRootDomain } from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
export const RegisterEmail = () => {
|
export const RegisterEmail = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const [email, setEmail] = useState("");
|
const [email, setEmail] = useState("");
|
||||||
const [password, setPassword] = useState("");
|
const [password, setPassword] = useState("");
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ import { Button, H1, MS } from "@jambonz/ui-kit";
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { putActivationCode } from "src/api";
|
import { putActivationCode } from "src/api";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
import { getToken, parseJwt } from "src/router/auth";
|
import { getToken, parseJwt } from "src/router/auth";
|
||||||
import {
|
import {
|
||||||
ROUTE_REGISTER_EMAIL,
|
ROUTE_REGISTER_EMAIL,
|
||||||
ROUTE_REGISTER_SUB_DOMAIN,
|
ROUTE_REGISTER_SUB_DOMAIN,
|
||||||
} from "src/router/routes";
|
} from "src/router/routes";
|
||||||
import { toastError } from "src/store";
|
|
||||||
import { UserData } from "src/store/types";
|
import { UserData } from "src/store/types";
|
||||||
|
|
||||||
export const EmailVerify = () => {
|
export const EmailVerify = () => {
|
||||||
|
const { toastError } = useToast();
|
||||||
const [code, setCode] = useState("");
|
const [code, setCode] = useState("");
|
||||||
const userData: UserData = parseJwt(getToken());
|
const userData: UserData = parseJwt(getToken());
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ import React, { useEffect, useState } from "react";
|
|||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { postChangepassword, postSignIn } from "src/api";
|
import { postChangepassword, postSignIn } from "src/api";
|
||||||
import { Message, Passwd } from "src/components/forms";
|
import { Message, Passwd } from "src/components/forms";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
import { setToken } from "src/router/auth";
|
import { setToken } from "src/router/auth";
|
||||||
import { ROUTE_LOGIN } from "src/router/routes";
|
import { ROUTE_LOGIN } from "src/router/routes";
|
||||||
import { toastError, toastSuccess } from "src/store";
|
|
||||||
|
|
||||||
export const ResetPassword = () => {
|
export const ResetPassword = () => {
|
||||||
|
const { toastError, toastSuccess } = useToast();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
const resetId = params.id;
|
const resetId = params.id;
|
||||||
const [newPassword, setNewPassword] = useState("");
|
const [newPassword, setNewPassword] = useState("");
|
||||||
|
|||||||
+10
-7
@@ -7,17 +7,20 @@ import { AuthProvider } from "./router/auth";
|
|||||||
import { Router } from "./router";
|
import { Router } from "./router";
|
||||||
|
|
||||||
import "./styles/index.scss";
|
import "./styles/index.scss";
|
||||||
|
import { ToastProvider } from "./components/toast/toast-provider";
|
||||||
|
|
||||||
const root: Element = document.getElementById("root")!;
|
const root: Element = document.getElementById("root")!;
|
||||||
|
|
||||||
createRoot(root).render(
|
createRoot(root).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<StateProvider>
|
<ToastProvider>
|
||||||
<BrowserRouter>
|
<StateProvider>
|
||||||
<AuthProvider>
|
<BrowserRouter>
|
||||||
<Router />
|
<AuthProvider>
|
||||||
</AuthProvider>
|
<Router />
|
||||||
</BrowserRouter>
|
</AuthProvider>
|
||||||
</StateProvider>
|
</BrowserRouter>
|
||||||
|
</StateProvider>
|
||||||
|
</ToastProvider>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
);
|
);
|
||||||
|
|||||||
+2
-1
@@ -25,12 +25,12 @@ import {
|
|||||||
import type { UserLogin } from "src/api/types";
|
import type { UserLogin } from "src/api/types";
|
||||||
import { ENABLE_HOSTED_SYSTEM, USER_ACCOUNT } from "src/api/constants";
|
import { ENABLE_HOSTED_SYSTEM, USER_ACCOUNT } from "src/api/constants";
|
||||||
import type { UserData } from "src/store/types";
|
import type { UserData } from "src/store/types";
|
||||||
import { toastError } from "src/store";
|
|
||||||
import {
|
import {
|
||||||
clearLocalStorage,
|
clearLocalStorage,
|
||||||
removeLocationBeforeOauth,
|
removeLocationBeforeOauth,
|
||||||
removeOauthState,
|
removeOauthState,
|
||||||
} from "src/store/localStore";
|
} from "src/store/localStore";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
interface SignIn {
|
interface SignIn {
|
||||||
(username: string, password: string): Promise<UserLogin>;
|
(username: string, password: string): Promise<UserLogin>;
|
||||||
@@ -94,6 +94,7 @@ export const parseJwt = (token: string) => {
|
|||||||
* Provider hook that creates auth object and handles state
|
* Provider hook that creates auth object and handles state
|
||||||
*/
|
*/
|
||||||
export const useProvideAuth = (): AuthStateContext => {
|
export const useProvideAuth = (): AuthStateContext => {
|
||||||
|
const { toastError } = useToast();
|
||||||
let token = getToken();
|
let token = getToken();
|
||||||
let userData: UserData;
|
let userData: UserData;
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React, { useReducer, useContext } from "react";
|
import React, { useReducer, useContext } from "react";
|
||||||
|
|
||||||
import { TOAST_TIME } from "src/constants";
|
|
||||||
import {
|
import {
|
||||||
genericAction,
|
genericAction,
|
||||||
userAsyncAction,
|
userAsyncAction,
|
||||||
@@ -11,8 +10,6 @@ import {
|
|||||||
} from "./actions";
|
} from "./actions";
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
IMessage,
|
|
||||||
Toast,
|
|
||||||
State,
|
State,
|
||||||
Action,
|
Action,
|
||||||
MiddleWare,
|
MiddleWare,
|
||||||
@@ -49,22 +46,12 @@ const reducer: React.Reducer<State, Action<keyof State>> = (state, action) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let toastTimeout: number;
|
|
||||||
|
|
||||||
/** Async middlewares */
|
/** Async middlewares */
|
||||||
/** Proxies dispatch to reducer */
|
/** Proxies dispatch to reducer */
|
||||||
const middleware: MiddleWare = (dispatch) => {
|
const middleware: MiddleWare = (dispatch) => {
|
||||||
/** This generic implementation enforces global dispatch type-safety */
|
/** This generic implementation enforces global dispatch type-safety */
|
||||||
return <Type extends keyof State>(action: Action<Type>) => {
|
return <Type extends keyof State>(action: Action<Type>) => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case "toast":
|
|
||||||
if (toastTimeout) {
|
|
||||||
clearTimeout(toastTimeout);
|
|
||||||
}
|
|
||||||
toastTimeout = setTimeout(() => {
|
|
||||||
dispatch({ type: "toast" });
|
|
||||||
}, TOAST_TIME);
|
|
||||||
return dispatch(action);
|
|
||||||
case "user":
|
case "user":
|
||||||
return userAsyncAction().then((payload) => {
|
return userAsyncAction().then((payload) => {
|
||||||
dispatch({ ...action, payload });
|
dispatch({ ...action, payload });
|
||||||
@@ -106,28 +93,6 @@ export const useDispatch = (): GlobalDispatch => {
|
|||||||
return globalDispatch;
|
return globalDispatch;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Toast dispatch helpers to make component code less cumbersome */
|
|
||||||
const toastDispatch = (payload: Toast) => {
|
|
||||||
globalDispatch({
|
|
||||||
type: "toast",
|
|
||||||
payload,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toastError = (msg: IMessage) => {
|
|
||||||
toastDispatch({
|
|
||||||
type: "error",
|
|
||||||
message: msg,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const toastSuccess = (msg: IMessage) => {
|
|
||||||
toastDispatch({
|
|
||||||
type: "success",
|
|
||||||
message: msg,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Wrapper hook for state context */
|
/** Wrapper hook for state context */
|
||||||
export const useStateContext = () => {
|
export const useStateContext = () => {
|
||||||
const { state } = useContext(StateContext);
|
const { state } = useContext(StateContext);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
import { toastError } from "src/store";
|
|
||||||
|
|
||||||
import type { IMessage } from "src/store/types";
|
import type { IMessage } from "src/store/types";
|
||||||
|
|
||||||
@@ -11,6 +10,7 @@ export const useRedirect = <Type>(
|
|||||||
message: IMessage,
|
message: IMessage,
|
||||||
) => {
|
) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { toastError } = useToast();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (collection && !collection.length) {
|
if (collection && !collection.length) {
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import {
|
|||||||
SpeechCredential,
|
SpeechCredential,
|
||||||
User,
|
User,
|
||||||
} from "src/api/types";
|
} from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
import { toastError, useSelectState } from "src/store";
|
import { useSelectState } from "src/store";
|
||||||
|
|
||||||
import { IMessage, Scope, UserData } from "src/store/types";
|
import { IMessage, Scope, UserData } from "src/store/types";
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ export const useScopedRedirect = (
|
|||||||
) => {
|
) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
|
const { toastError } = useToast();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
@@ -47,5 +49,5 @@ export const useScopedRedirect = (
|
|||||||
|
|
||||||
navigate(redirect);
|
navigate(redirect);
|
||||||
}
|
}
|
||||||
}, [user, currentServiceProvider, data]);
|
}, [user, currentServiceProvider, data, toastError]);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,11 +2,12 @@ import React, { useEffect } from "react";
|
|||||||
|
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { toastError, useSelectState, useAccessControl } from "src/store";
|
import { useSelectState, useAccessControl } from "src/store";
|
||||||
import { ROUTE_INTERNAL_SETTINGS } from "src/router/routes";
|
import { ROUTE_INTERNAL_SETTINGS } from "src/router/routes";
|
||||||
|
|
||||||
import type { ACL, IMessage } from "src/store/types";
|
import type { ACL, IMessage } from "src/store/types";
|
||||||
import type { ServiceProvider } from "src/api/types";
|
import type { ServiceProvider } from "src/api/types";
|
||||||
|
import { useToast } from "src/components/toast/toast-provider";
|
||||||
|
|
||||||
type PassthroughProps = {
|
type PassthroughProps = {
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
@@ -22,6 +23,7 @@ export const withAccessControl = (
|
|||||||
) => {
|
) => {
|
||||||
return function WithAccessControl(Component: React.ComponentType) {
|
return function WithAccessControl(Component: React.ComponentType) {
|
||||||
return function ComponentWithAccessControl(props: PassthroughProps) {
|
return function ComponentWithAccessControl(props: PassthroughProps) {
|
||||||
|
const { toastError } = useToast();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const hasPermission = useAccessControl(acl);
|
const hasPermission = useAccessControl(acl);
|
||||||
const currentServiceProvider = useSelectState("currentServiceProvider");
|
const currentServiceProvider = useSelectState("currentServiceProvider");
|
||||||
|
|||||||
Reference in New Issue
Block a user