feat: add customization components (#7419)
* ✨ (webhookFieldComponent): Add support for ENABLE_DATASTAX_LANGFLOW feature flag to conditionally show generate token button 🐛 (use-get-config): Set default value for webhook polling interval if not provided in data ♻️ (custom-secret-key-modal-button): Refactor to pass modal props as a separate object to improve readability and maintainability 🔧 (use-generate-token): Add new file for generating token function 🔧 (secretKeyModal): Refactor to use generate token function based on ENABLE_DATASTAX_LANGFLOW flag and separate modal props into a dedicated interface * ✨ (constants.ts): add default polling interval and timeout constants for better code readability and maintainability ♻️ (use-get-config.ts): refactor to use the newly added default constants for polling interval and timeout to improve code consistency and reduce duplication * 🐛 (typescript_test.yml): update the maximum shard count calculation to be 25 instead of 10 to improve test distribution and efficiency * ⚙️ (typescript_test.yml): adjust optimal shard count calculation to ensure a maximum of 10 shards for test execution ♻️ (index.tsx): refactor modalConfigProps assignment to handle cases where modalProps is null or undefined --------- Co-authored-by: Mike Fortman <michael.fortman@datastax.com>
This commit is contained in:
parent
59f74e894f
commit
f4a07fac69
6 changed files with 83 additions and 23 deletions
|
|
@ -1,7 +1,8 @@
|
||||||
import { AuthContext } from "@/contexts/authContext";
|
import { AuthContext } from "@/contexts/authContext";
|
||||||
import { useGetBuildsMutation } from "@/controllers/API/queries/_builds/use-get-builds-polling-mutation";
|
import { useGetBuildsMutation } from "@/controllers/API/queries/_builds/use-get-builds-polling-mutation";
|
||||||
import SecretKeyModalButton from "@/customization/components/custom-secret-key-modal-button";
|
import SecretKeyModalButton from "@/customization/components/custom-secret-key-modal-button";
|
||||||
import useFlowStore from "@/stores/flowStore";
|
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
|
||||||
|
import { getModalPropsApiKey } from "@/customization/utils/get-modal-props";
|
||||||
import { useContext, useEffect, useRef, useState } from "react";
|
import { useContext, useEffect, useRef, useState } from "react";
|
||||||
import { InputProps, TextAreaComponentType } from "../../types";
|
import { InputProps, TextAreaComponentType } from "../../types";
|
||||||
import CopyFieldAreaComponent from "../copyFieldAreaComponent";
|
import CopyFieldAreaComponent from "../copyFieldAreaComponent";
|
||||||
|
|
@ -19,14 +20,21 @@ export default function WebhookFieldComponent({
|
||||||
const [userId, setUserId] = useState("");
|
const [userId, setUserId] = useState("");
|
||||||
const { mutate: getBuildsMutation } = useGetBuildsMutation();
|
const { mutate: getBuildsMutation } = useGetBuildsMutation();
|
||||||
const hasInitialized = useRef(false);
|
const hasInitialized = useRef(false);
|
||||||
|
const modalProps = getModalPropsApiKey();
|
||||||
|
|
||||||
const isBackendUrl = nodeInformationMetadata?.variableName === "endpoint";
|
const isBackendUrl = nodeInformationMetadata?.variableName === "endpoint";
|
||||||
const isCurlWebhook = nodeInformationMetadata?.variableName === "curl";
|
const isCurlWebhook = nodeInformationMetadata?.variableName === "curl";
|
||||||
const isAuth = nodeInformationMetadata?.isAuth;
|
const isAuth = nodeInformationMetadata?.isAuth;
|
||||||
const showGenerateToken = isBackendUrl && !editNode && !isAuth;
|
const showGenerateToken =
|
||||||
|
(isBackendUrl && !editNode && !isAuth) ||
|
||||||
|
(ENABLE_DATASTAX_LANGFLOW && !editNode);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!editNode && isBackendUrl && !hasInitialized.current) {
|
const getBuilds =
|
||||||
|
(!editNode && isBackendUrl && !hasInitialized.current) ||
|
||||||
|
(ENABLE_DATASTAX_LANGFLOW && !editNode);
|
||||||
|
|
||||||
|
if (getBuilds) {
|
||||||
hasInitialized.current = true;
|
hasInitialized.current = true;
|
||||||
getBuildsMutation({
|
getBuildsMutation({
|
||||||
flowId: nodeInformationMetadata?.flowId!,
|
flowId: nodeInformationMetadata?.flowId!,
|
||||||
|
|
@ -69,7 +77,7 @@ export default function WebhookFieldComponent({
|
||||||
|
|
||||||
{showGenerateToken && (
|
{showGenerateToken && (
|
||||||
<div>
|
<div>
|
||||||
<SecretKeyModalButton userId={userId} />
|
<SecretKeyModalButton userId={userId} modalProps={modalProps} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1062,3 +1062,6 @@ export const OPENAI_VOICES = [
|
||||||
{ name: "shimmer", value: "shimmer" },
|
{ name: "shimmer", value: "shimmer" },
|
||||||
{ name: "verse", value: "verse" },
|
{ name: "verse", value: "verse" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const DEFAULT_POLLING_INTERVAL = 5000;
|
||||||
|
export const DEFAULT_TIMEOUT = 30000;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
import {
|
||||||
|
DEFAULT_POLLING_INTERVAL,
|
||||||
|
DEFAULT_TIMEOUT,
|
||||||
|
} from "@/constants/constants";
|
||||||
import { EventDeliveryType } from "@/constants/enums";
|
import { EventDeliveryType } from "@/constants/enums";
|
||||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||||
import { useUtilityStore } from "@/stores/utilityStore";
|
import { useUtilityStore } from "@/stores/utilityStore";
|
||||||
|
|
@ -44,7 +48,7 @@ export const useGetConfig: useQueryFunctionType<undefined, ConfigResponse> = (
|
||||||
if (data) {
|
if (data) {
|
||||||
const timeoutInMilliseconds = data.frontend_timeout
|
const timeoutInMilliseconds = data.frontend_timeout
|
||||||
? data.frontend_timeout * 1000
|
? data.frontend_timeout * 1000
|
||||||
: 30000;
|
: DEFAULT_TIMEOUT;
|
||||||
axios.defaults.baseURL = "";
|
axios.defaults.baseURL = "";
|
||||||
axios.defaults.timeout = timeoutInMilliseconds;
|
axios.defaults.timeout = timeoutInMilliseconds;
|
||||||
setAutoSaving(data.auto_saving);
|
setAutoSaving(data.auto_saving);
|
||||||
|
|
@ -52,7 +56,9 @@ export const useGetConfig: useQueryFunctionType<undefined, ConfigResponse> = (
|
||||||
setHealthCheckMaxRetries(data.health_check_max_retries);
|
setHealthCheckMaxRetries(data.health_check_max_retries);
|
||||||
setMaxFileSizeUpload(data.max_file_size_upload);
|
setMaxFileSizeUpload(data.max_file_size_upload);
|
||||||
setFeatureFlags(data.feature_flags);
|
setFeatureFlags(data.feature_flags);
|
||||||
setWebhookPollingInterval(data.webhook_polling_interval);
|
setWebhookPollingInterval(
|
||||||
|
data.webhook_polling_interval ?? DEFAULT_POLLING_INTERVAL,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,11 @@ import { getModalPropsApiKey } from "@/pages/SettingsPage/pages/ApiKeysPage/help
|
||||||
|
|
||||||
export const SecretKeyModalButton = ({
|
export const SecretKeyModalButton = ({
|
||||||
userId,
|
userId,
|
||||||
|
modalProps,
|
||||||
}: {
|
}: {
|
||||||
userId: string;
|
userId: string;
|
||||||
|
modalProps;
|
||||||
}): JSX.Element => {
|
}): JSX.Element => {
|
||||||
const modalProps = getModalPropsApiKey();
|
|
||||||
|
|
||||||
return <></>;
|
return <></>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
export const useGenerateToken = (): any => {
|
||||||
|
const tokenFunction = (() => {
|
||||||
|
return "token";
|
||||||
|
}) as any;
|
||||||
|
tokenFunction.token = "token";
|
||||||
|
return tokenFunction;
|
||||||
|
};
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import * as Form from "@radix-ui/react-form";
|
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
|
||||||
import { Label } from "@radix-ui/react-form";
|
import { useGenerateToken } from "@/customization/hooks/use-generate-token";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { Input } from "../../components/ui/input";
|
|
||||||
import { COPIED_NOTICE_ALERT } from "../../constants/alerts_constants";
|
import { COPIED_NOTICE_ALERT } from "../../constants/alerts_constants";
|
||||||
import { createApiKey } from "../../controllers/API";
|
import { createApiKey } from "../../controllers/API";
|
||||||
import useAlertStore from "../../stores/alertStore";
|
import useAlertStore from "../../stores/alertStore";
|
||||||
|
|
@ -11,9 +10,21 @@ import { ContentRenderKey } from "./components/content-render";
|
||||||
import { FormKeyRender } from "./components/form-key-render";
|
import { FormKeyRender } from "./components/form-key-render";
|
||||||
import { HeaderRender } from "./components/header-render";
|
import { HeaderRender } from "./components/header-render";
|
||||||
|
|
||||||
interface ModalProps {
|
// Add this interface for the modal props
|
||||||
generatedKeyMessage?: React.ReactNode;
|
interface ModalConfigProps {
|
||||||
|
title?: string;
|
||||||
description?: React.ReactNode;
|
description?: React.ReactNode;
|
||||||
|
inputLabel?: React.ReactNode;
|
||||||
|
inputPlaceholder?: string;
|
||||||
|
buttonText?: string;
|
||||||
|
generatedKeyMessage?: React.ReactNode;
|
||||||
|
showIcon?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SecretKeyModalProps {
|
||||||
|
userId?: string;
|
||||||
|
size?: string;
|
||||||
|
modalProps?: ModalConfigProps;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function SecretKeyModal({
|
export default function SecretKeyModal({
|
||||||
|
|
@ -21,7 +32,7 @@ export default function SecretKeyModal({
|
||||||
data,
|
data,
|
||||||
onCloseModal,
|
onCloseModal,
|
||||||
modalProps,
|
modalProps,
|
||||||
}: ApiKeyType & { modalProps?: ModalProps }) {
|
}: ApiKeyType & { modalProps: SecretKeyModalProps }) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [apiKeyName, setApiKeyName] = useState(data?.apikeyname ?? "");
|
const [apiKeyName, setApiKeyName] = useState(data?.apikeyname ?? "");
|
||||||
const [apiKeyValue, setApiKeyValue] = useState("");
|
const [apiKeyValue, setApiKeyValue] = useState("");
|
||||||
|
|
@ -29,6 +40,8 @@ export default function SecretKeyModal({
|
||||||
const [textCopied, setTextCopied] = useState(true);
|
const [textCopied, setTextCopied] = useState(true);
|
||||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
const generateToken = useGenerateToken();
|
||||||
|
const modalConfigProps = modalProps?.modalProps ?? modalProps;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) {
|
if (open) {
|
||||||
|
|
@ -68,14 +81,33 @@ export default function SecretKeyModal({
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSubmitForm() {
|
async function handleSubmitForm() {
|
||||||
|
if (apiKeyValue) setOpen(false);
|
||||||
|
if (ENABLE_DATASTAX_LANGFLOW) {
|
||||||
|
handleDataStaxKey();
|
||||||
|
} else {
|
||||||
|
handleOSSKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDataStaxKey = async () => {
|
||||||
|
try {
|
||||||
|
const { token } = await generateToken();
|
||||||
|
setApiKeyValue(token);
|
||||||
|
setRenderKey(true);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error generating token:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOSSKey = () => {
|
||||||
if (!renderKey) {
|
if (!renderKey) {
|
||||||
setRenderKey(true);
|
setRenderKey(true);
|
||||||
handleAddNewKey();
|
handleAddNewKey();
|
||||||
} else {
|
} else {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseModal
|
<BaseModal
|
||||||
|
|
@ -89,30 +121,32 @@ export default function SecretKeyModal({
|
||||||
clampDescription={3}
|
clampDescription={3}
|
||||||
description={
|
description={
|
||||||
renderKey ? (
|
renderKey ? (
|
||||||
<>{modalProps?.generatedKeyMessage}</>
|
<>{modalConfigProps?.generatedKeyMessage}</>
|
||||||
) : (
|
) : (
|
||||||
<>{modalProps?.description}</>
|
<>{modalConfigProps?.description}</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<HeaderRender
|
<HeaderRender
|
||||||
title={modalProps?.title}
|
title={modalConfigProps?.title}
|
||||||
showIcon={modalProps?.showIcon}
|
showIcon={modalConfigProps?.showIcon}
|
||||||
/>
|
/>
|
||||||
</BaseModal.Header>
|
</BaseModal.Header>
|
||||||
<BaseModal.Content>
|
<BaseModal.Content>
|
||||||
{renderKey ? (
|
{renderKey ? (
|
||||||
<ContentRenderKey
|
<ContentRenderKey
|
||||||
inputLabel={String(modalProps?.inputLabel ?? "")}
|
inputLabel={String(modalConfigProps?.inputLabel ?? "")}
|
||||||
inputRef={inputRef}
|
inputRef={inputRef}
|
||||||
apiKeyValue={apiKeyValue}
|
apiKeyValue={apiKeyValue}
|
||||||
handleCopyClick={handleCopyClick}
|
handleCopyClick={handleCopyClick}
|
||||||
textCopied={textCopied}
|
textCopied={textCopied}
|
||||||
renderKey={renderKey}
|
renderKey={renderKey}
|
||||||
/>
|
/>
|
||||||
|
) : ENABLE_DATASTAX_LANGFLOW ? (
|
||||||
|
<></>
|
||||||
) : (
|
) : (
|
||||||
<FormKeyRender
|
<FormKeyRender
|
||||||
modalProps={modalProps}
|
modalProps={modalConfigProps}
|
||||||
apiKeyName={apiKeyName}
|
apiKeyName={apiKeyName}
|
||||||
inputRef={inputRef}
|
inputRef={inputRef}
|
||||||
setApiKeyName={setApiKeyName}
|
setApiKeyName={setApiKeyName}
|
||||||
|
|
@ -120,7 +154,9 @@ export default function SecretKeyModal({
|
||||||
)}
|
)}
|
||||||
</BaseModal.Content>
|
</BaseModal.Content>
|
||||||
<BaseModal.Footer
|
<BaseModal.Footer
|
||||||
submit={{ label: renderKey ? "Done" : (modalProps?.buttonText ?? "") }}
|
submit={{
|
||||||
|
label: renderKey ? "Done" : (modalConfigProps?.buttonText ?? ""),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</BaseModal>
|
</BaseModal>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue