refactor: added analytics track and custom parameter support (#3617)
* Added analytics track * Changed post add user to just use the function * Added tracking in various components * Added custom parameter support * Added centered footer
This commit is contained in:
parent
32d51b69e8
commit
9102c6272f
11 changed files with 111 additions and 18 deletions
|
|
@ -1,16 +1,16 @@
|
||||||
import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
|
import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
|
||||||
import { ParameterRenderComponent } from "@/components/parameterRenderComponent";
|
|
||||||
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
|
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
|
||||||
import { ReactNode, useEffect, useRef, useState } from "react";
|
import {
|
||||||
|
CustomParameterComponent,
|
||||||
|
getCustomParameterTitle,
|
||||||
|
} from "@/customization/components/custom-parameter";
|
||||||
|
import { useEffect, useRef } from "react";
|
||||||
import { default as IconComponent } from "../../../../components/genericIconComponent";
|
import { default as IconComponent } from "../../../../components/genericIconComponent";
|
||||||
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||||
import { LANGFLOW_SUPPORTED_TYPES } from "../../../../constants/constants";
|
import { LANGFLOW_SUPPORTED_TYPES } from "../../../../constants/constants";
|
||||||
import useFlowStore from "../../../../stores/flowStore";
|
import useFlowStore from "../../../../stores/flowStore";
|
||||||
import { useTypesStore } from "../../../../stores/typesStore";
|
import { useTypesStore } from "../../../../stores/typesStore";
|
||||||
import {
|
import { NodeInputFieldComponentType } from "../../../../types/components";
|
||||||
NodeInputFieldComponentType,
|
|
||||||
ParameterComponentType,
|
|
||||||
} from "../../../../types/components";
|
|
||||||
import { scapedJSONStringfy } from "../../../../utils/reactflowUtils";
|
import { scapedJSONStringfy } from "../../../../utils/reactflowUtils";
|
||||||
import useFetchDataOnMount from "../../../hooks/use-fetch-data-on-mount";
|
import useFetchDataOnMount from "../../../hooks/use-fetch-data-on-mount";
|
||||||
import useHandleOnNewValue from "../../../hooks/use-handle-new-value";
|
import useHandleOnNewValue from "../../../hooks/use-handle-new-value";
|
||||||
|
|
@ -105,11 +105,21 @@ export default function NodeInputField({
|
||||||
<div className="flex w-full items-center truncate text-sm">
|
<div className="flex w-full items-center truncate text-sm">
|
||||||
{proxy ? (
|
{proxy ? (
|
||||||
<ShadTooltip content={<span>{proxy.id}</span>}>
|
<ShadTooltip content={<span>{proxy.id}</span>}>
|
||||||
{<span>{title}</span>}
|
{
|
||||||
|
<span>
|
||||||
|
{getCustomParameterTitle({ title, nodeId: data.id })}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
</ShadTooltip>
|
</ShadTooltip>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<span>{<span>{title}</span>}</span>
|
<span>
|
||||||
|
{
|
||||||
|
<span>
|
||||||
|
{getCustomParameterTitle({ title, nodeId: data.id })}
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<span className={(required ? "ml-2 " : "") + "text-status-red"}>
|
<span className={(required ? "ml-2 " : "") + "text-status-red"}>
|
||||||
|
|
@ -133,7 +143,7 @@ export default function NodeInputField({
|
||||||
{displayHandle && Handle}
|
{displayHandle && Handle}
|
||||||
{data.node?.template[name] !== undefined && (
|
{data.node?.template[name] !== undefined && (
|
||||||
<div className="mt-2 w-full">
|
<div className="mt-2 w-full">
|
||||||
<ParameterRenderComponent
|
<CustomParameterComponent
|
||||||
handleOnNewValue={handleOnNewValue}
|
handleOnNewValue={handleOnNewValue}
|
||||||
name={name}
|
name={name}
|
||||||
nodeId={data.id}
|
nodeId={data.id}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { track } from "@/customization/utils/analytics";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Control } from "react-hook-form";
|
import { Control } from "react-hook-form";
|
||||||
import IOModal from "../../modals/IOModal";
|
import IOModal from "../../modals/IOModal";
|
||||||
|
|
@ -137,6 +138,7 @@ export default function CollectionCardComponent({
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
track("Playground Button Clicked", { flowId: data.id });
|
||||||
setLoadingPlayground(true);
|
setLoadingPlayground(true);
|
||||||
const flow = getFlowById(data.id);
|
const flow = getFlowById(data.id);
|
||||||
if (flow) {
|
if (flow) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { ENABLE_API } from "@/customization/feature-flags";
|
import { ENABLE_API } from "@/customization/feature-flags";
|
||||||
|
import { track } from "@/customization/utils/analytics";
|
||||||
import { Transition } from "@headlessui/react";
|
import { Transition } from "@headlessui/react";
|
||||||
import { useMemo, useState } from "react";
|
import { useEffect, useMemo, useState } from "react";
|
||||||
import { useHotkeys } from "react-hotkeys-hook";
|
import { useHotkeys } from "react-hotkeys-hook";
|
||||||
import IOModal from "../../modals/IOModal";
|
import IOModal from "../../modals/IOModal";
|
||||||
import ApiModal from "../../modals/apiModal";
|
import ApiModal from "../../modals/apiModal";
|
||||||
|
|
@ -48,6 +49,12 @@ export default function FlowToolbar(): JSX.Element {
|
||||||
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
const hasApiKey = useStoreStore((state) => state.hasApiKey);
|
||||||
const currentFlow = useFlowStore((state) => state.currentFlow);
|
const currentFlow = useFlowStore((state) => state.currentFlow);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
track("Playground Button Clicked");
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
const ModalMemo = useMemo(
|
const ModalMemo = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<ShareModal
|
<ShareModal
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,7 @@ export const useAddUser: useMutationFunctionType<undefined, UserInputType> = (
|
||||||
|
|
||||||
const mutation: UseMutationResult<Array<Users>, any, UserInputType> = mutate(
|
const mutation: UseMutationResult<Array<Users>, any, UserInputType> = mutate(
|
||||||
["useAddUser"],
|
["useAddUser"],
|
||||||
async (payload: UserInputType) => {
|
addUserFunction,
|
||||||
const res = await addUserFunction(payload);
|
|
||||||
return res;
|
|
||||||
},
|
|
||||||
options,
|
options,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { ParameterRenderComponent } from "@/components/parameterRenderComponent";
|
||||||
|
import { handleOnNewValueType } from "@/CustomNodes/hooks/use-handle-new-value";
|
||||||
|
import { APIClassType, InputFieldType } from "@/types/api";
|
||||||
|
|
||||||
|
export function CustomParameterComponent({
|
||||||
|
handleOnNewValue,
|
||||||
|
name,
|
||||||
|
nodeId,
|
||||||
|
templateData,
|
||||||
|
templateValue,
|
||||||
|
editNode,
|
||||||
|
handleNodeClass,
|
||||||
|
nodeClass,
|
||||||
|
disabled,
|
||||||
|
}: {
|
||||||
|
handleOnNewValue: handleOnNewValueType;
|
||||||
|
name: string;
|
||||||
|
nodeId: string;
|
||||||
|
templateData: Partial<InputFieldType>;
|
||||||
|
templateValue: any;
|
||||||
|
editNode: boolean;
|
||||||
|
handleNodeClass: (value: any, code?: string, type?: string) => void;
|
||||||
|
nodeClass: APIClassType;
|
||||||
|
disabled: boolean;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<ParameterRenderComponent
|
||||||
|
handleOnNewValue={handleOnNewValue}
|
||||||
|
name={name}
|
||||||
|
nodeId={nodeId}
|
||||||
|
templateData={templateData}
|
||||||
|
templateValue={templateValue}
|
||||||
|
editNode={editNode}
|
||||||
|
handleNodeClass={handleNodeClass}
|
||||||
|
nodeClass={nodeClass}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getCustomParameterTitle({
|
||||||
|
title,
|
||||||
|
nodeId,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
nodeId: string;
|
||||||
|
}) {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
7
src/frontend/src/customization/utils/analytics.ts
Normal file
7
src/frontend/src/customization/utils/analytics.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export const track = async (
|
||||||
|
name: string,
|
||||||
|
properties: Record<string, any> = {},
|
||||||
|
id: string = "",
|
||||||
|
): Promise<void> => {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
@ -89,9 +89,16 @@ const Footer: React.FC<{
|
||||||
onClick?: () => void;
|
onClick?: () => void;
|
||||||
};
|
};
|
||||||
close?: boolean;
|
close?: boolean;
|
||||||
}> = ({ children, submit, close }) => {
|
centered?: boolean;
|
||||||
|
}> = ({ children, submit, close, centered }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-shrink-0 flex-row-reverse">
|
<div
|
||||||
|
className={
|
||||||
|
centered
|
||||||
|
? "flex flex-shrink-0 justify-center"
|
||||||
|
: "flex flex-shrink-0 flex-row-reverse"
|
||||||
|
}
|
||||||
|
>
|
||||||
{submit ? (
|
{submit ? (
|
||||||
<div className="flex w-full items-center justify-between">
|
<div className="flex w-full items-center justify-between">
|
||||||
{children ?? <div />}
|
{children ?? <div />}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import LoadingComponent from "@/components/loadingComponent";
|
import LoadingComponent from "@/components/loadingComponent";
|
||||||
import { useGetBuildsQuery } from "@/controllers/API/queries/_builds";
|
import { useGetBuildsQuery } from "@/controllers/API/queries/_builds";
|
||||||
|
import { track } from "@/customization/utils/analytics";
|
||||||
import useAutoSaveFlow from "@/hooks/flows/use-autosave-flow";
|
import useAutoSaveFlow from "@/hooks/flows/use-autosave-flow";
|
||||||
import useUploadFlow from "@/hooks/flows/use-upload-flow";
|
import useUploadFlow from "@/hooks/flows/use-upload-flow";
|
||||||
import _, { cloneDeep } from "lodash";
|
import _, { cloneDeep } from "lodash";
|
||||||
|
|
@ -334,6 +335,8 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
||||||
event.dataTransfer.getData("nodedata"),
|
event.dataTransfer.getData("nodedata"),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
track(`Component Added: ${data.node?.display_name}`);
|
||||||
|
|
||||||
const newId = getNodeId(data.type);
|
const newId = getNodeId(data.type);
|
||||||
|
|
||||||
const newNode: NodeType = {
|
const newNode: NodeType = {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import FolderSidebarNav from "@/components/folderSidebarComponent";
|
import FolderSidebarNav from "@/components/folderSidebarComponent";
|
||||||
import { useDeleteFolders } from "@/controllers/API/queries/folders";
|
import { useDeleteFolders } from "@/controllers/API/queries/folders";
|
||||||
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
|
import { track } from "@/customization/utils/analytics";
|
||||||
import useAlertStore from "@/stores/alertStore";
|
import useAlertStore from "@/stores/alertStore";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Outlet, useLocation } from "react-router-dom";
|
import { Outlet, useLocation } from "react-router-dom";
|
||||||
|
|
@ -65,7 +66,10 @@ export default function HomePage(): JSX.Element {
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<DropdownButton
|
<DropdownButton
|
||||||
firstButtonName="New Project"
|
firstButtonName="New Project"
|
||||||
onFirstBtnClick={() => setOpenModal(true)}
|
onFirstBtnClick={() => {
|
||||||
|
setOpenModal(true);
|
||||||
|
track("New Project Button Clicked");
|
||||||
|
}}
|
||||||
options={dropdownOptions}
|
options={dropdownOptions}
|
||||||
plusButton={true}
|
plusButton={true}
|
||||||
dropdownOptions={false}
|
dropdownOptions={false}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
import { useGetRefreshFlows } from "@/controllers/API/queries/flows/use-get-refresh-flows";
|
||||||
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
import { useGetGlobalVariables } from "@/controllers/API/queries/variables";
|
||||||
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
|
import { track } from "@/customization/utils/analytics";
|
||||||
import { useStoreStore } from "@/stores/storeStore";
|
import { useStoreStore } from "@/stores/storeStore";
|
||||||
import { useTypesStore } from "@/stores/typesStore";
|
import { useTypesStore } from "@/stores/typesStore";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
@ -57,6 +58,10 @@ export default function PlaygroundPage() {
|
||||||
awaitgetTypes();
|
awaitgetTypes();
|
||||||
}, [id, flows, validApiKey]);
|
}, [id, flows, validApiKey]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (id) track("Playground Page Loaded", { flowId: id });
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full flex-col items-center justify-center align-middle">
|
<div className="flex h-full w-full flex-col items-center justify-center align-middle">
|
||||||
{currentSavedFlow && (
|
{currentSavedFlow && (
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { useAddUser } from "@/controllers/API/queries/auth";
|
import { useAddUser } from "@/controllers/API/queries/auth";
|
||||||
import { CustomLink } from "@/customization/components/custom-link";
|
import { CustomLink } from "@/customization/components/custom-link";
|
||||||
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
|
||||||
|
import { track } from "@/customization/utils/analytics";
|
||||||
import * as Form from "@radix-ui/react-form";
|
import * as Form from "@radix-ui/react-form";
|
||||||
import { FormEvent, useEffect, useState } from "react";
|
import { FormEvent, useEffect, useState } from "react";
|
||||||
import InputComponent from "../../components/inputComponent";
|
import InputComponent from "../../components/inputComponent";
|
||||||
|
|
@ -52,7 +53,8 @@ export default function SignUp(): JSX.Element {
|
||||||
};
|
};
|
||||||
|
|
||||||
mutateAddUser(newUser, {
|
mutateAddUser(newUser, {
|
||||||
onSuccess: () => {
|
onSuccess: (user) => {
|
||||||
|
track("User Signed Up", user);
|
||||||
setSuccessData({
|
setSuccessData({
|
||||||
title: SIGN_UP_SUCCESS,
|
title: SIGN_UP_SUCCESS,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue