feat: Replace standard components with customizable versions and add Langflow Desktop support (#7904)

*  (frontend): Add new customization components and hooks for the frontend application. This includes DashboardWrapperPage, McpServerTab, BaseModal, EmptyPageCommunity, FileCard, IOFileInput, IOModal, ProfilePictureChooserComponent, VoiceAssistant, App, router, CustomPreloadImages, useStartConversation, useStartRecording, CustomAudioWorkletProcessor.

*  (frontend): Add new customization components and utilities for NodeStatus, curl code, JS API code, Python API code, and widget code.

*  (frontend): Add new customization components and controllers for the frontend application.

*  (frontend): Add new customization components and controllers for the frontend application.

* add customization folder desktop

*  (AccountMenu): Introduce CustomAccountMenu component to customize the account menu in the app header
🔄 (ProfileIcon): Refactor ProfileIcon component to CustomProfileIcon for customization purposes
🔄 (langflow-counts): Refactor LangflowCounts component to CustomLangflowCounts for customization purposes

* 🔧 Remove unused files related to dialog, langflow, buildUtils, and reactflowUtils components

*  (frontend): Add new images and components for the frontend UI
📝 (frontend): Update custom hooks to have more descriptive names for better clarity and organization

* 🔧 Remove package-lock.json as it is not needed and can be generated dynamically by npm or yarn when installing dependencies

* [autofix.ci] apply automated fixes

* 📝 (frontend): Add custom dialog content component without fixed positioning
🔧 (frontend): Update dialog class utility to improve dialog styling
🔧 (frontend): Update custom build utils for API endpoints
🔧 (frontend): Add custom get access token utility function
🔧 (frontend): Add custom get host protocol utility function
🔧 (frontend): Add custom pre-load image URL utility function
🔧 (frontend): Add custom react flow utility functions
🔧 (frontend): Add custom refresh latest version utility function
🔧 (frontend): Add custom routes for store pages
🔧 (frontend): Add custom routes for store pages components
🔧 (frontend): Update build utils for API endpoints
🔧 (frontend): Update react flow utility functions for downloading flows

*  (custom-routes-store-pages.tsx): Rename customRoutesStorePages to CustomRoutesStorePages for consistency and clarity
 (custom-routes-store.tsx): Rename customRoutesStore to CustomRoutesStore for consistency and clarity
🔧 (routes.tsx): Remove unused import of StoreGuard to clean up the code and improve maintainability
🔧 (routes.tsx): Update imports of customRoutesStore and customRoutesStorePages to use named imports for consistency and clarity

*  (API/index.ts): Add custom functions to fetch app versions and latest version from a custom source
🔧 (feature-flags.ts): Remove ENABLE_LANGFLOW_DESKTOP feature flag as it is no longer needed
📝 (custom-get-app-latest-version.ts): Add custom functions to fetch app versions and latest version from a custom source

* ♻️ (frontend): refactor API controller to export getAppVersions and getLatestVersion functions instead of calling custom functions directly

*  (deploy-dropdown.tsx): Add customMcpOpen function to handle target attribute in CustomLink component
 (sideBarFolderButtons/index.tsx): Add CustomStoreButton component to render a custom store button if ENABLE_DATASTAX_LANGFLOW is false
📝 (custom-store-button.tsx): Create CustomStoreButton component to render a custom store button
📝 (custom-store-sidebar.tsx): Create CustomStoreSidebar component to define custom store sidebar items
📝 (custom-mcp-open.ts): Create customMcpOpen function to return "_blank" for target attribute
📝 (custom-refresh-latest-version.ts): Add useDarkStore import and use it to refresh latest version
📝 (SettingsPage/index.tsx): Import CustomStoreSidebar and use it to populate langflowItems
📝 (ProfilePictureChooserComponent/index.tsx): Import customPreLoadImageUrl and use it to preload images
📝 (use-preload-images.ts): Remove unused import of BASE_URL_API
📝 (use-preload-images.ts): Remove unused constant BASE_URL_API

* 🔧 (LangflowDesktopLogo.png): remove LangflowDesktopLogo.png as it is no longer needed in the project

*  (custom-fetch-error-component.tsx): add CustomFetchErrorComponent to customize error handling in the frontend
🔧 (GenericErrorComponent/index.tsx): replace FetchErrorComponent with CustomFetchErrorComponent for more flexibility and customization in error handling

*  (updater.ts): introduce new types Version and UpdaterStoreType for managing version information and updater modal state in the frontend customization module

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
This commit is contained in:
Cristhian Zanforlin Lousa 2025-05-14 08:11:35 -07:00 committed by GitHub
commit c2e78180f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 847 additions and 178 deletions

View file

@ -1,6 +1,7 @@
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { usePostValidateComponentCode } from "@/controllers/API/queries/nodes/use-post-validate-component-code";
import { CustomNodeStatus } from "@/customization/components/custom-NodeStatus";
import UpdateComponentModal from "@/modals/updateComponentModal";
import { useAlternate } from "@/shared/hooks/use-alternate";
import { FlowStoreType } from "@/types/zustand/flow";
@ -40,7 +41,7 @@ const MemoizedOutputParameter = memo(OutputParameter);
const MemoizedRenderInputParameters = memo(RenderInputParameters);
const MemoizedNodeIcon = memo(NodeIcon);
const MemoizedNodeName = memo(NodeName);
const MemoizedNodeStatus = memo(NodeStatus);
const MemoizedNodeStatus = memo(CustomNodeStatus);
const MemoizedNodeDescription = memo(NodeDescription);
const HiddenOutputsButton = memo(

View file

@ -0,0 +1,13 @@
<svg width="150" height="100" viewBox="0 0 1318 258" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1226.43 123.28C1226.02 123.28 1225.66 123.56 1225.55 123.95C1218.12 150.1 1212.3 170.33 1208.11 184.65C1207.38 187.13 1205.11 188.82 1202.53 188.82H1173.7C1171.14 188.82 1168.88 187.15 1168.14 184.7L1135.81 78.8201C1134.67 75.0801 1137.47 71.3 1141.38 71.3H1163.83C1166.44 71.3 1168.73 73.04 1169.44 75.56L1188.31 143.31C1188.42 143.7 1188.78 143.98 1189.19 143.98C1189.6 143.98 1189.96 143.71 1190.07 143.31C1193.97 129.54 1196.97 119.18 1199.08 112.24L1209.6 75.5201C1210.32 73.0201 1212.6 71.3 1215.19 71.3H1239.98C1242.59 71.3 1244.87 73.03 1245.58 75.54L1264.67 143.31C1264.78 143.7 1265.14 143.98 1265.55 143.98C1265.96 143.98 1266.32 143.71 1266.43 143.31C1274.76 114.15 1281.13 91.57 1285.53 75.58C1286.23 73.05 1288.52 71.3 1291.14 71.3H1311.5C1315.41 71.3 1318.21 75.0801 1317.07 78.8201L1284.75 184.7C1284 187.15 1281.74 188.82 1279.18 188.82H1250.81C1248.23 188.82 1245.96 187.12 1245.23 184.65L1227.34 123.94C1227.23 123.55 1226.87 123.28 1226.46 123.28H1226.43Z" fill="black"/>
<path d="M1133.55 133.4C1133.55 145.21 1131.02 155.48 1125.96 164.22C1121.05 172.96 1114.23 179.63 1105.49 184.23C1096.75 188.83 1086.94 191.13 1076.05 191.13H1072.37C1061.48 191.13 1051.67 188.83 1042.93 184.23C1034.19 179.63 1027.29 172.96 1022.23 164.22C1017.32 155.48 1014.87 145.21 1014.87 133.4V126.73C1014.87 114.92 1017.32 104.65 1022.23 95.91C1027.29 87.17 1034.19 80.5 1042.93 75.9C1051.67 71.3 1061.48 69 1072.37 69H1076.05C1086.93 69 1096.75 71.3 1105.49 75.9C1114.23 80.5 1121.05 87.17 1125.96 95.91C1131.02 104.65 1133.55 114.92 1133.55 126.73V133.4ZM1099.51 120.75C1099.51 111.4 1097.13 104.27 1092.38 99.36C1087.78 94.45 1081.73 92 1074.21 92C1066.69 92 1060.56 94.45 1055.81 99.36C1051.21 104.27 1048.91 111.4 1048.91 120.75V139.38C1048.91 148.73 1051.21 155.86 1055.81 160.77C1060.56 165.68 1066.7 168.13 1074.21 168.13C1081.72 168.13 1087.78 165.68 1092.38 160.77C1097.13 155.86 1099.51 148.73 1099.51 139.38V120.75Z" fill="black"/>
<path d="M949.84 24.89C947.38 24.09 944.49 23.38 941.16 22.78C936.1 21.86 931.65 21.4 927.82 21.4C904.21 21.4 892.4 32.9 892.4 55.9V71.31H884.61C881.4 71.31 878.79 73.91 878.79 77.13V88.02C878.79 91.23 881.39 93.84 884.61 93.84H892.4V183.01C892.4 186.22 895.01 188.83 898.22 188.83H920.16C923.37 188.83 925.98 186.22 925.98 183.01V100.12C925.98 96.91 928.58 94.3 931.8 94.3H947.53C950.74 94.3 953.35 91.7 953.35 88.48V77.12C953.35 73.91 950.74 71.3 947.53 71.3H931.8C928.59 71.3 925.98 68.69 925.98 65.48V57.96C925.98 52.44 927.21 48.76 929.66 46.92C932.27 45.08 935.41 44.16 939.09 44.16C940.78 44.16 943.08 44.47 945.99 45.08C949.69 45.66 953.35 42.9 953.35 39.15V29.98C953.35 27.69 952.01 25.59 949.84 24.88V24.89Z" fill="black"/>
<path d="M995.07 23.24H973.13C969.916 23.24 967.31 25.8457 967.31 29.06V183.01C967.31 186.224 969.916 188.83 973.13 188.83H995.07C998.284 188.83 1000.89 186.224 1000.89 183.01V29.06C1000.89 25.8457 998.284 23.24 995.07 23.24Z" fill="black"/>
<path d="M654.92 75.92C655.97 80.82 662.54 82.36 666.39 79.15C674.49 72.39 684.06 69.01 695.11 69.01C707.07 69.01 716.88 72.23 724.55 78.67C732.37 85.11 736.28 94.46 736.28 106.73V183.01C736.28 186.22 733.68 188.83 730.46 188.83H708.52C705.31 188.83 702.7 186.22 702.7 183.01V114.08C702.7 108.1 700.94 103.19 697.41 99.36C694.04 95.37 689.67 93.38 684.3 93.38C678.32 93.38 673.19 95.68 668.89 100.28C664.6 104.73 662.45 110.17 662.45 116.61V183.01C662.45 186.22 659.84 188.83 656.63 188.83H634.69C631.48 188.83 628.87 186.22 628.87 183.01V77.13C628.87 73.92 631.48 71.31 634.69 71.31H649.23C651.97 71.31 654.35 73.24 654.92 75.92Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M575.88 96.83C579.25 100.05 580.94 104.27 580.94 109.48V111.77L580.92 112.01C580.81 113.29 580.7 114.53 580.7 115.58C580.7 116.53 579.93 117.3 578.98 117.31C562.39 117.38 548.79 118.38 538.17 120.3C527.13 122.29 518.47 126.2 512.18 132.03C506.05 137.7 502.98 145.98 502.98 156.87C502.98 170.21 506.74 179.25 514.25 184.01C521.76 188.76 531.35 191.14 543 191.14C554.65 191.14 564 187.81 572.64 181.14C575.7 178.78 580.7 180.77 580.7 184.64C580.7 186.96 582.58 188.84 584.91 188.84H608.46C611.67 188.84 614.28 186.23 614.28 183.02V106.74C614.28 94.47 610.37 85.12 602.55 78.68C596.44 73.55 589.79 71.53 581.01 70.57C575.71 69.54 569.78 69.02 563.23 69.02H558.4C548.28 69.02 539.31 70.48 531.49 73.39C523.67 76.3 517.54 80.37 513.09 85.58C508.8 90.79 506.65 96.7 506.65 103.29C506.65 105.7 508.87 107.43 511.28 107.43H537.7C538.72 107.43 539.54 106.61 539.54 105.59C539.54 103.75 540.31 101.76 541.84 99.61C543.53 97.46 545.9 95.7 548.97 94.32C552.04 92.79 555.72 92.02 560.01 92.02C567.37 92.02 572.66 93.63 575.88 96.85V96.83ZM574.87 136.25C578.08 136.15 580.7 138.77 580.7 141.98V145.43C580.7 145.71 580.68 145.98 580.64 146.25C580.09 149.64 578.82 152.79 576.8 155.7C574.19 159.69 570.9 162.75 566.91 164.9C562.92 167.05 558.94 168.12 554.95 168.12C549.12 168.12 544.75 167.12 541.84 165.13C539.08 162.98 537.7 159.38 537.7 154.32C537.7 147.88 541.23 143.28 548.28 140.52C554.45 138.03 563.31 136.6 574.87 136.24V136.25Z" fill="black"/>
<path d="M409.44 188.82C406.23 188.82 403.62 186.21 403.62 183V36.87C403.62 33.66 406.23 31.05 409.44 31.05H433.45C436.66 31.05 439.27 33.66 439.27 36.87V153.56C439.27 156.77 441.88 159.38 445.09 159.38H485.44C488.15 159.38 490.51 161.26 491.11 163.9L495.17 181.7C496 185.34 493.23 188.81 489.5 188.81H409.44V188.82Z" fill="black"/>
<path d="M862.6 171.34C856.93 165.21 848.72 162.14 837.99 162.14H797.05C792.14 162.14 788.46 161.3 786.01 159.61C783.71 157.92 782.56 155.55 782.56 152.48C782.56 150.03 783.79 147.8 786.24 145.81C788.85 143.82 792.45 142.82 797.05 142.82H812.92C821.97 142.82 829.94 141.21 836.84 137.99C843.89 134.62 849.33 130.17 853.17 124.65C857 118.98 858.92 112.77 858.92 106.02C858.92 101.87 858.16 97.97 856.66 94.33H863.52C866.73 94.33 869.34 91.72 869.34 88.51V77.62C869.34 74.41 866.74 71.8 863.52 71.8H828.05C827.99 71.78 827.93 71.76 827.87 71.75C822.2 69.91 815.76 68.99 808.55 68.99H804.87C788.46 68.99 775.97 72.44 767.38 79.34C758.95 86.24 754.73 95.13 754.73 106.02C754.73 111.69 756.19 117.06 759.1 122.12C759.9 123.47 760.8 124.76 761.78 125.99C764.89 129.88 763.99 137.1 760.21 140.33C759.08 141.3 758.02 142.36 757.03 143.51C753.35 147.65 751.51 152.56 751.51 158.23C751.51 162.22 752.43 165.9 754.27 169.27C754.47 169.63 754.68 169.99 754.89 170.34C757.31 174.24 756.89 180.5 753.57 183.67C752.16 185.01 750.86 186.5 749.66 188.13C746.44 192.58 744.83 197.56 744.83 203.08C744.83 212.13 747.97 219.18 754.26 224.24C760.7 229.45 768.59 232.06 777.95 232.06H826.48C834.76 232.06 842.27 230.45 849.02 227.23C855.92 224.16 861.36 219.79 865.35 214.12C869.34 208.45 871.33 202.08 871.33 195.03C871.33 185.22 868.42 177.32 862.59 171.34H862.6ZM792.68 93.61C796.51 90.54 801.34 89.01 807.17 89.01C813 89.01 818.06 90.54 821.89 93.61C825.72 96.52 827.64 100.66 827.64 106.03C827.64 111.4 825.72 115.61 821.89 118.68C818.06 121.59 813.15 123.05 807.17 123.05C801.19 123.05 796.51 121.59 792.68 118.68C788.85 115.61 786.93 111.4 786.93 106.03C786.93 100.66 788.85 96.52 792.68 93.61ZM835.92 207.68C833.01 210.13 829.56 211.36 825.57 211.36H786.93C783.56 211.36 780.64 210.21 778.19 207.91C775.74 205.61 774.51 202.93 774.51 199.86C774.51 196.79 775.74 194.11 778.19 191.81C780.64 189.66 783.56 188.59 786.93 188.59H826.95C830.94 188.59 834.16 189.59 836.61 191.58C839.06 193.73 840.29 196.33 840.29 199.4C840.29 202.62 838.83 205.38 835.92 207.68Z" fill="black"/>
<path d="M241.05 136.17H281.58C289.53 136.17 295.97 142.61 295.97 150.56V174.47C295.97 182.42 289.53 188.86 281.58 188.86H246.23C242.41 188.86 238.75 190.38 236.05 193.08L175.39 253.73C172.69 256.43 169.03 257.95 165.21 257.95H136.05C128.25 257.95 121.86 251.73 121.66 243.93L121.03 219.52C120.82 211.43 127.32 204.75 135.42 204.75H160.52C164.34 204.75 168 203.23 170.7 200.53L230.85 140.38C233.55 137.68 237.21 136.16 241.03 136.16L241.05 136.17Z" fill="black"/>
<path d="M120.71 0.0500488H161.24C169.19 0.0500488 175.63 6.49005 175.63 14.44V38.3501C175.63 46.3001 169.19 52.7401 161.24 52.7401H125.89C122.07 52.7401 118.41 54.2601 115.71 56.9601L55.05 117.62C52.35 120.32 48.69 121.84 44.87 121.84H15.71C7.91 121.84 1.52 115.62 1.32 107.82L0.690008 83.41C0.480008 75.3201 6.98001 68.65 15.08 68.65H40.18C44 68.65 47.66 67.13 50.36 64.43L110.51 4.28004C113.21 1.58004 116.87 0.0600433 120.69 0.0600433L120.71 0.0500488Z" fill="black"/>
<path d="M241.05 30.8501H281.58C289.53 30.8501 295.97 37.2901 295.97 45.2401V69.1501C295.97 77.1001 289.53 83.5401 281.58 83.5401H246.23C242.41 83.5401 238.75 85.0601 236.05 87.7601L175.39 148.42C172.69 151.12 169.03 152.64 165.21 152.64H129.78C126.07 152.64 122.5 154.07 119.82 156.64L51.72 221.9C49.04 224.47 45.47 225.9 41.76 225.9H16.94C8.99005 225.9 2.55005 219.45 2.55005 211.51V186.94C2.55005 178.99 8.99005 172.55 16.94 172.55H41.58C45.4 172.55 49.06 171.03 51.76 168.33L116.43 103.66C119.13 100.96 122.79 99.4401 126.61 99.4401H160.52C164.34 99.4401 168 97.9201 170.7 95.2201L230.85 35.0701C233.55 32.3701 237.21 30.8501 241.03 30.8501H241.05Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 9 KiB

View file

@ -0,0 +1,13 @@
<svg width="150" height="100" viewBox="0 0 1318 258" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1226.43 123.28C1226.02 123.28 1225.66 123.56 1225.55 123.95C1218.12 150.1 1212.3 170.33 1208.11 184.65C1207.38 187.13 1205.11 188.82 1202.53 188.82H1173.7C1171.14 188.82 1168.88 187.15 1168.14 184.7L1135.81 78.82C1134.67 75.08 1137.47 71.3 1141.38 71.3H1163.83C1166.44 71.3 1168.73 73.04 1169.44 75.56L1188.31 143.31C1188.42 143.7 1188.78 143.98 1189.19 143.98C1189.6 143.98 1189.96 143.71 1190.07 143.31C1193.97 129.54 1196.97 119.18 1199.08 112.24L1209.6 75.52C1210.32 73.02 1212.6 71.3 1215.19 71.3H1239.98C1242.59 71.3 1244.87 73.03 1245.58 75.54L1264.67 143.31C1264.78 143.7 1265.14 143.98 1265.55 143.98C1265.96 143.98 1266.32 143.71 1266.43 143.31C1274.76 114.15 1281.13 91.57 1285.53 75.58C1286.23 73.05 1288.52 71.3 1291.14 71.3H1311.5C1315.41 71.3 1318.21 75.08 1317.07 78.82L1284.75 184.7C1284 187.15 1281.74 188.82 1279.18 188.82H1250.81C1248.23 188.82 1245.96 187.12 1245.23 184.65L1227.34 123.94C1227.23 123.55 1226.87 123.28 1226.46 123.28H1226.43Z" fill="white"/>
<path d="M1133.55 133.4C1133.55 145.21 1131.02 155.48 1125.96 164.22C1121.05 172.96 1114.23 179.63 1105.49 184.23C1096.75 188.83 1086.94 191.13 1076.05 191.13H1072.37C1061.48 191.13 1051.67 188.83 1042.93 184.23C1034.19 179.63 1027.29 172.96 1022.23 164.22C1017.32 155.48 1014.87 145.21 1014.87 133.4V126.73C1014.87 114.92 1017.32 104.65 1022.23 95.91C1027.29 87.17 1034.19 80.5 1042.93 75.9C1051.67 71.3 1061.48 69 1072.37 69H1076.05C1086.93 69 1096.75 71.3 1105.49 75.9C1114.23 80.5 1121.05 87.17 1125.96 95.91C1131.02 104.65 1133.55 114.92 1133.55 126.73V133.4ZM1099.51 120.75C1099.51 111.4 1097.13 104.27 1092.38 99.36C1087.78 94.45 1081.73 92 1074.21 92C1066.69 92 1060.56 94.45 1055.81 99.36C1051.21 104.27 1048.91 111.4 1048.91 120.75V139.38C1048.91 148.73 1051.21 155.86 1055.81 160.77C1060.56 165.68 1066.7 168.13 1074.21 168.13C1081.72 168.13 1087.78 165.68 1092.38 160.77C1097.13 155.86 1099.51 148.73 1099.51 139.38V120.75Z" fill="white"/>
<path d="M949.84 24.89C947.38 24.09 944.49 23.38 941.16 22.78C936.1 21.86 931.65 21.4 927.82 21.4C904.21 21.4 892.4 32.9 892.4 55.9V71.31H884.61C881.4 71.31 878.79 73.91 878.79 77.13V88.02C878.79 91.23 881.39 93.84 884.61 93.84H892.4V183.01C892.4 186.22 895.01 188.83 898.22 188.83H920.16C923.37 188.83 925.98 186.22 925.98 183.01V100.12C925.98 96.91 928.58 94.3 931.8 94.3H947.53C950.74 94.3 953.35 91.7 953.35 88.48V77.12C953.35 73.91 950.74 71.3 947.53 71.3H931.8C928.59 71.3 925.98 68.69 925.98 65.48V57.96C925.98 52.44 927.21 48.76 929.66 46.92C932.27 45.08 935.41 44.16 939.09 44.16C940.78 44.16 943.08 44.47 945.99 45.08C949.69 45.66 953.35 42.9 953.35 39.15V29.98C953.35 27.69 952.01 25.59 949.84 24.88V24.89Z" fill="white"/>
<path d="M995.07 23.24H973.13C969.916 23.24 967.31 25.8457 967.31 29.06V183.01C967.31 186.224 969.916 188.83 973.13 188.83H995.07C998.284 188.83 1000.89 186.224 1000.89 183.01V29.06C1000.89 25.8457 998.284 23.24 995.07 23.24Z" fill="white"/>
<path d="M654.92 75.92C655.97 80.82 662.54 82.36 666.39 79.15C674.49 72.39 684.06 69.01 695.11 69.01C707.07 69.01 716.88 72.23 724.55 78.67C732.37 85.11 736.28 94.46 736.28 106.73V183.01C736.28 186.22 733.68 188.83 730.46 188.83H708.52C705.31 188.83 702.7 186.22 702.7 183.01V114.08C702.7 108.1 700.94 103.19 697.41 99.36C694.04 95.37 689.67 93.38 684.3 93.38C678.32 93.38 673.19 95.68 668.89 100.28C664.6 104.73 662.45 110.17 662.45 116.61V183.01C662.45 186.22 659.84 188.83 656.63 188.83H634.69C631.48 188.83 628.87 186.22 628.87 183.01V77.13C628.87 73.92 631.48 71.31 634.69 71.31H649.23C651.97 71.31 654.35 73.24 654.92 75.92Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M575.88 96.83C579.25 100.05 580.94 104.27 580.94 109.48V111.77L580.92 112.01C580.81 113.29 580.7 114.53 580.7 115.58C580.7 116.53 579.93 117.3 578.98 117.31C562.39 117.38 548.79 118.38 538.17 120.3C527.13 122.29 518.47 126.2 512.18 132.03C506.05 137.7 502.98 145.98 502.98 156.87C502.98 170.21 506.74 179.25 514.25 184.01C521.76 188.76 531.35 191.14 543 191.14C554.65 191.14 564 187.81 572.64 181.14C575.7 178.78 580.7 180.77 580.7 184.64C580.7 186.96 582.58 188.84 584.91 188.84H608.46C611.67 188.84 614.28 186.23 614.28 183.02V106.74C614.28 94.47 610.37 85.12 602.55 78.68C596.44 73.55 589.79 71.53 581.01 70.57C575.71 69.54 569.78 69.02 563.23 69.02H558.4C548.28 69.02 539.31 70.48 531.49 73.39C523.67 76.3 517.54 80.37 513.09 85.58C508.8 90.79 506.65 96.7 506.65 103.29C506.65 105.7 508.87 107.43 511.28 107.43H537.7C538.72 107.43 539.54 106.61 539.54 105.59C539.54 103.75 540.31 101.76 541.84 99.61C543.53 97.46 545.9 95.7 548.97 94.32C552.04 92.79 555.72 92.02 560.01 92.02C567.37 92.02 572.66 93.63 575.88 96.85V96.83ZM574.87 136.25C578.08 136.15 580.7 138.77 580.7 141.98V145.43C580.7 145.71 580.68 145.98 580.64 146.25C580.09 149.64 578.82 152.79 576.8 155.7C574.19 159.69 570.9 162.75 566.91 164.9C562.92 167.05 558.94 168.12 554.95 168.12C549.12 168.12 544.75 167.12 541.84 165.13C539.08 162.98 537.7 159.38 537.7 154.32C537.7 147.88 541.23 143.28 548.28 140.52C554.45 138.03 563.31 136.6 574.87 136.24V136.25Z" fill="white"/>
<path d="M409.44 188.82C406.23 188.82 403.62 186.21 403.62 183V36.87C403.62 33.66 406.23 31.05 409.44 31.05H433.45C436.66 31.05 439.27 33.66 439.27 36.87V153.56C439.27 156.77 441.88 159.38 445.09 159.38H485.44C488.15 159.38 490.51 161.26 491.11 163.9L495.17 181.7C496 185.34 493.23 188.81 489.5 188.81H409.44V188.82Z" fill="white"/>
<path d="M862.6 171.34C856.93 165.21 848.72 162.14 837.99 162.14H797.05C792.14 162.14 788.46 161.3 786.01 159.61C783.71 157.92 782.56 155.55 782.56 152.48C782.56 150.03 783.79 147.8 786.24 145.81C788.85 143.82 792.45 142.82 797.05 142.82H812.92C821.97 142.82 829.94 141.21 836.84 137.99C843.89 134.62 849.33 130.17 853.17 124.65C857 118.98 858.92 112.77 858.92 106.02C858.92 101.87 858.16 97.97 856.66 94.33H863.52C866.73 94.33 869.34 91.72 869.34 88.51V77.62C869.34 74.41 866.74 71.8 863.52 71.8H828.05C827.99 71.78 827.93 71.76 827.87 71.75C822.2 69.91 815.76 68.99 808.55 68.99H804.87C788.46 68.99 775.97 72.44 767.38 79.34C758.95 86.24 754.73 95.13 754.73 106.02C754.73 111.69 756.19 117.06 759.1 122.12C759.9 123.47 760.8 124.76 761.78 125.99C764.89 129.88 763.99 137.1 760.21 140.33C759.08 141.3 758.02 142.36 757.03 143.51C753.35 147.65 751.51 152.56 751.51 158.23C751.51 162.22 752.43 165.9 754.27 169.27C754.47 169.63 754.68 169.99 754.89 170.34C757.31 174.24 756.89 180.5 753.57 183.67C752.16 185.01 750.86 186.5 749.66 188.13C746.44 192.58 744.83 197.56 744.83 203.08C744.83 212.13 747.97 219.18 754.26 224.24C760.7 229.45 768.59 232.06 777.95 232.06H826.48C834.76 232.06 842.27 230.45 849.02 227.23C855.92 224.16 861.36 219.79 865.35 214.12C869.34 208.45 871.33 202.08 871.33 195.03C871.33 185.22 868.42 177.32 862.59 171.34H862.6ZM792.68 93.61C796.51 90.54 801.34 89.01 807.17 89.01C813 89.01 818.06 90.54 821.89 93.61C825.72 96.52 827.64 100.66 827.64 106.03C827.64 111.4 825.72 115.61 821.89 118.68C818.06 121.59 813.15 123.05 807.17 123.05C801.19 123.05 796.51 121.59 792.68 118.68C788.85 115.61 786.93 111.4 786.93 106.03C786.93 100.66 788.85 96.52 792.68 93.61ZM835.92 207.68C833.01 210.13 829.56 211.36 825.57 211.36H786.93C783.56 211.36 780.64 210.21 778.19 207.91C775.74 205.61 774.51 202.93 774.51 199.86C774.51 196.79 775.74 194.11 778.19 191.81C780.64 189.66 783.56 188.59 786.93 188.59H826.95C830.94 188.59 834.16 189.59 836.61 191.58C839.06 193.73 840.29 196.33 840.29 199.4C840.29 202.62 838.83 205.38 835.92 207.68Z" fill="white"/>
<path d="M241.05 136.17H281.58C289.53 136.17 295.97 142.61 295.97 150.56V174.47C295.97 182.42 289.53 188.86 281.58 188.86H246.23C242.41 188.86 238.75 190.38 236.05 193.08L175.39 253.73C172.69 256.43 169.03 257.95 165.21 257.95H136.05C128.25 257.95 121.86 251.73 121.66 243.93L121.03 219.52C120.82 211.43 127.32 204.75 135.42 204.75H160.52C164.34 204.75 168 203.23 170.7 200.53L230.85 140.38C233.55 137.68 237.21 136.16 241.03 136.16L241.05 136.17Z" fill="white"/>
<path d="M120.71 0.0499878H161.24C169.19 0.0499878 175.63 6.48999 175.63 14.44V38.35C175.63 46.3 169.19 52.74 161.24 52.74H125.89C122.07 52.74 118.41 54.26 115.71 56.96L55.05 117.62C52.35 120.32 48.69 121.84 44.87 121.84H15.71C7.91 121.84 1.52 115.62 1.32 107.82L0.690008 83.41C0.480008 75.32 6.98001 68.65 15.08 68.65H40.18C44 68.65 47.66 67.13 50.36 64.43L110.51 4.27998C113.21 1.57998 116.87 0.0599823 120.69 0.0599823L120.71 0.0499878Z" fill="white"/>
<path d="M241.05 30.85H281.58C289.53 30.85 295.97 37.29 295.97 45.24V69.15C295.97 77.1 289.53 83.54 281.58 83.54H246.23C242.41 83.54 238.75 85.06 236.05 87.76L175.39 148.42C172.69 151.12 169.03 152.64 165.21 152.64H129.78C126.07 152.64 122.5 154.07 119.82 156.64L51.72 221.9C49.04 224.47 45.47 225.9 41.76 225.9H16.94C8.99005 225.9 2.55005 219.45 2.55005 211.51V186.94C2.55005 178.99 8.99005 172.55 16.94 172.55H41.58C45.4 172.55 49.06 171.03 51.76 168.33L116.43 103.66C119.13 100.96 122.79 99.44 126.61 99.44H160.52C164.34 99.44 168 97.92 170.7 95.22L230.85 35.07C233.55 32.37 237.21 30.85 241.03 30.85H241.05Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

View file

@ -266,16 +266,6 @@ export default function StoreCardComponent({
</div>
</CardFooter>
</Card>
{/* {openPlayground && (
<IOModal
key={data.id}
cleanOnClose={true}
open={openPlayground}
setOpen={setOpenPlayground}
>
<></>
</IOModal>
)} */}
</>
);
}

View file

@ -7,6 +7,7 @@ import {
TWITTER_URL,
} from "@/constants/constants";
import { useLogout } from "@/controllers/API/queries/auth";
import { CustomProfileIcon } from "@/customization/components/custom-profile-icon";
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import useAuthStore from "@/stores/authStore";
@ -50,7 +51,7 @@ export const AccountMenu = () => {
className="h-6 w-6 rounded-lg focus-visible:outline-0"
data-testid="user-profile-settings"
>
<ProfileIcon />
<CustomProfileIcon />
</div>
</HeaderMenuToggle>
<HeaderMenuItems position="right" classNameSize="w-[272px]">

View file

@ -5,6 +5,8 @@ import ForwardedIconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { Button } from "@/components/ui/button";
import { Separator } from "@/components/ui/separator";
import CustomAccountMenu from "@/customization/components/custom-AccountMenu";
import CustomLangflowCounts from "@/customization/components/custom-langflow-counts";
import { CustomOrgSelector } from "@/customization/components/custom-org-selector";
import { CustomProductSelector } from "@/customization/components/custom-product-selector";
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
@ -94,7 +96,7 @@ export default function AppHeader(): JSX.Element {
unstyled
className="hidden items-center whitespace-nowrap pr-2 lg:inline"
>
<LangflowCounts />
<CustomLangflowCounts />
</Button>
</>
<AlertDropdown
@ -142,7 +144,7 @@ export default function AppHeader(): JSX.Element {
/>
<div className="flex">
<AccountMenu />
<CustomAccountMenu />
</div>
</div>
</div>

View file

@ -11,6 +11,7 @@ import { Switch } from "@/components/ui/switch";
import { usePatchUpdateFlow } from "@/controllers/API/queries/flows/use-patch-update-flow";
import { CustomLink } from "@/customization/components/custom-link";
import { ENABLE_PUBLISH, ENABLE_WIDGET } from "@/customization/feature-flags";
import { customMcpOpen } from "@/customization/utils/custom-mcp-open";
import ApiModal from "@/modals/apiModal/new-api-modal";
import EmbedModal from "@/modals/EmbedModal/embed-modal";
import useAlertStore from "@/stores/alertStore";
@ -120,7 +121,7 @@ export default function PublishDropdown() {
<CustomLink
className={cn("flex-1")}
to={`/mcp/folder/${folderId}`}
target="_blank"
target={customMcpOpen()}
>
<DropdownMenuItem
className="deploy-dropdown-item group"

View file

@ -1,8 +1,8 @@
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import ShadTooltip from "@/components/common/shadTooltipComponent";
import { PLAYGROUND_BUTTON_NAME } from "@/constants/constants";
import { CustomIOModal } from "@/customization/components/custom-new-modal";
import { ENABLE_PUBLISH } from "@/customization/feature-flags";
import IOModal from "@/modals/IOModal/new-modal";
interface PlaygroundButtonProps {
hasIO: boolean;
@ -50,14 +50,14 @@ const PlaygroundButton = ({
canvasOpen,
}: PlaygroundButtonProps) => {
return hasIO ? (
<IOModal
<CustomIOModal
open={open}
setOpen={setOpen}
disable={!hasIO}
canvasOpen={canvasOpen}
>
<ActiveButton />
</IOModal>
</CustomIOModal>
) : (
<ShadTooltip content="Add a Chat Input or Chat Output to use the playground">
<div>

View file

@ -2,6 +2,7 @@ import IconComponent from "@/components/common/genericIconComponent";
import { GetStartedProgress } from "@/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/get-started-progress";
import { SidebarTrigger } from "@/components/ui/sidebar";
import { useUpdateUser } from "@/controllers/API/queries/auth";
import CustomGetStartedProgress from "@/customization/components/custom-get-started-progress";
import useAuthStore from "@/stores/authStore";
import { Separator } from "@radix-ui/react-separator";
import { useState } from "react";
@ -45,7 +46,7 @@ export const HeaderButtons = ({
<>
{!isDismissedDialog && (
<>
<GetStartedProgress
<CustomGetStartedProgress
userData={userData!}
isGithubStarred={isGithubStarred ?? false}
isDiscordJoined={isDiscordJoined ?? false}

View file

@ -21,6 +21,7 @@ import {
usePostUploadFolders,
} from "@/controllers/API/queries/folders";
import { useGetDownloadFolders } from "@/controllers/API/queries/folders/use-get-download-folders";
import { CustomStoreButton } from "@/customization/components/custom-store-button";
import {
ENABLE_CUSTOM_PARAM,
ENABLE_DATASTAX_LANGFLOW,
@ -490,23 +491,7 @@ const SideBarFoldersButtonsComponent = ({
{ENABLE_FILE_MANAGEMENT && (
<SidebarFooter className="border-t">
<div className="grid w-full items-center gap-2 p-2">
{!ENABLE_DATASTAX_LANGFLOW && (
<div
className="flex w-full items-center"
data-testid="button-store"
>
<SidebarMenuButton
size="md"
className="text-sm"
onClick={() => {
window.open("/store", "_blank");
}}
>
<ForwardedIconComponent name="Store" className="h-4 w-4" />
Store
</SidebarMenuButton>
</div>
)}
{!ENABLE_DATASTAX_LANGFLOW && <CustomStoreButton />}
<SidebarMenuButton
isActive={checkPathFiles}
onClick={() => handleFilesClick?.()}

View file

@ -10,7 +10,7 @@ import { memo, useEffect, useRef, useState } from "react";
import { InputProps } from "../../types";
import HelperTextComponent from "../helperTextComponent";
type ConnectionComponentProps = {
export type ConnectionComponentProps = {
tooltip?: string;
name: string;
helperText?: string;

View file

@ -11,8 +11,6 @@ export default function LinkComponent({
id = "",
text,
icon,
editNode = false,
handleOnNewValue,
}: InputProps<string, LinkComponentType>): JSX.Element {
function handleOpenLink() {
if (value) {

View file

@ -4,10 +4,11 @@ import CodeAreaComponent from "@/components/core/parameterRenderComponent/compon
import SliderComponent from "@/components/core/parameterRenderComponent/components/sliderComponent";
import TabComponent from "@/components/core/parameterRenderComponent/components/tabComponent";
import { TEXT_FIELD_TYPES } from "@/constants/constants";
import CustomConnectionComponent from "@/customization/components/custom-connectionComponent";
import CustomLinkComponent from "@/customization/components/custom-linkComponent";
import { APIClassType, InputFieldType } from "@/types/api";
import { useMemo } from "react";
import ToolsComponent from "./components/ToolsComponent";
import ConnectionComponent from "./components/connectionComponent";
import DictComponent from "./components/dictComponent";
import { EmptyParameterComponent } from "./components/emptyParameterComponent";
import FloatComponent from "./components/floatComponent";
@ -146,7 +147,7 @@ export function ParameterRenderComponent({
);
case "link":
return (
<LinkComponent
<CustomLinkComponent
{...baseInputProps}
icon={templateData.icon}
text={templateData.text}
@ -248,7 +249,7 @@ export function ParameterRenderComponent({
)?.link || "";
return (
<ConnectionComponent
<CustomConnectionComponent
{...baseInputProps}
name={name}
nodeId={nodeId}

View file

@ -26,6 +26,11 @@ export type BaseInputProps<valueType = any> = {
nodeId?: string;
nodeInformationMetadata?: NodeInfoType;
hasRefreshButton?: boolean;
helperMetadata?: any;
options?: any[];
searchCategory?: string[];
buttonMetadata?: { variant?: string; icon?: string };
connectionLink?: string;
};
// Generic type for composing input props

View file

@ -1,9 +1,10 @@
import DialogContentWithouFixed from "@/customization/components/custom-dialog-content-without-fixed";
import { dialogClass } from "@/customization/utils/dialog-class";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { Cross2Icon } from "@radix-ui/react-icons";
import * as React from "react";
import { cn } from "../../utils/utils";
import ShadTooltip from "../common/shadTooltipComponent";
const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger;
@ -26,10 +27,7 @@ const DialogOverlay = React.forwardRef<
>(({ className, ...props }, ref) => (
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"fixed inset-0 bottom-0 left-0 right-0 top-0 z-40 overflow-auto bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
className,
)}
className={cn(dialogClass.dialogContent, className)}
{...props}
/>
));
@ -105,7 +103,6 @@ const DialogContent = React.forwardRef<
);
},
);
DialogContent.displayName = DialogPrimitive.Content.displayName;
const DialogHeader = ({
className,
@ -162,6 +159,7 @@ DialogDescription.displayName = DialogPrimitive.Description.displayName;
export {
Dialog,
DialogContent,
DialogContentWithouFixed,
DialogDescription,
DialogFooter,
DialogHeader,

View file

@ -0,0 +1,100 @@
"use client";
import { cn } from "@/utils/utils";
import {
AnimatePresence,
AnimatePresenceProps,
motion,
Transition,
Variants,
} from "framer-motion";
import { Children, useCallback, useEffect, useRef, useState } from "react";
export type TextLoopProps = {
children: React.ReactNode | React.ReactNode[];
className?: string;
interval?: number;
transition?: Transition;
variants?: Variants;
onIndexChange?: (index: number) => void;
trigger?: boolean;
mode?: AnimatePresenceProps["mode"];
style?: React.CSSProperties;
};
export function TextLoop({
children,
className,
interval = 2,
transition = { duration: 0.3 },
variants,
onIndexChange,
trigger = true,
mode = "popLayout",
style,
}: TextLoopProps) {
const [currentIndex, setCurrentIndex] = useState(0);
const items = Children.toArray(children);
const timerRef = useRef<NodeJS.Timeout>();
const updateIndex = useCallback(() => {
setCurrentIndex((current) => {
const next = (current + 1) % items.length;
onIndexChange?.(next);
return next;
});
}, [items.length, onIndexChange]);
useEffect(() => {
if (!trigger || items.length <= 1) return;
const intervalMs = interval * 1000;
timerRef.current = setInterval(updateIndex, intervalMs);
return () => {
if (timerRef.current) {
clearInterval(timerRef.current);
}
};
}, [trigger, interval, items.length, updateIndex]);
const motionVariants: Variants = {
initial: { y: 20, opacity: 0 },
animate: { y: 0, opacity: 1 },
exit: { y: -20, opacity: 0 },
};
if (items.length === 1) {
return (
<div className={cn("relative inline-block whitespace-nowrap", className)}>
<motion.div
initial="initial"
animate="animate"
transition={transition}
variants={variants || motionVariants}
style={style}
>
{items[0]}
</motion.div>
</div>
);
}
return (
<div className={cn("relative inline-block whitespace-nowrap", className)}>
<AnimatePresence mode={mode} initial={false}>
<motion.div
key={currentIndex}
initial="initial"
animate="animate"
exit="exit"
transition={transition}
variants={variants || motionVariants}
style={style}
>
{items[currentIndex]}
</motion.div>
</AnimatePresence>
</div>
);
}

View file

@ -7,6 +7,7 @@ import {
import { useGetUserData } from "@/controllers/API/queries/auth";
import { useGetGlobalVariablesMutation } from "@/controllers/API/queries/variables/use-get-mutation-global-variables";
import useAuthStore from "@/stores/authStore";
import { setLocalStorage } from "@/utils/local-storage-util";
import { createContext, useEffect, useState } from "react";
import { Cookies } from "react-cookie";
import { useStoreStore } from "../stores/storeStore";
@ -81,7 +82,10 @@ export function AuthProvider({ children }): React.ReactElement {
autoLogin: string,
refreshToken?: string,
) {
cookies.set(LANGFLOW_ACCESS_TOKEN, newAccessToken, { path: "/" });
cookies.set(LANGFLOW_AUTO_LOGIN_OPTION, autoLogin, { path: "/" });
setLocalStorage(LANGFLOW_ACCESS_TOKEN, newAccessToken);
if (refreshToken) {
cookies.set(LANGFLOW_REFRESH_TOKEN, refreshToken, { path: "/" });
}

View file

@ -1,5 +1,7 @@
import { IS_AUTO_LOGIN, LANGFLOW_ACCESS_TOKEN } from "@/constants/constants";
import { IS_AUTO_LOGIN } from "@/constants/constants";
import { baseURL } from "@/customization/constants";
import { useCustomApiHeaders } from "@/customization/hooks/use-custom-api-headers";
import { customGetAccessToken } from "@/customization/utils/custom-get-access-token";
import useAuthStore from "@/stores/authStore";
import { useUtilityStore } from "@/stores/utilityStore";
import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from "axios";
@ -14,7 +16,7 @@ import { useLogout, useRefreshAccessToken } from "./queries/auth";
// Create a new Axios instance
const api: AxiosInstance = axios.create({
baseURL: "",
baseURL: baseURL,
});
const cookies = new Cookies();
@ -41,7 +43,8 @@ function ApiInterceptor() {
useEffect(() => {
const unregister = fetchIntercept.register({
request: function (url, config) {
const accessToken = cookies.get(LANGFLOW_ACCESS_TOKEN);
const accessToken = customGetAccessToken();
if (accessToken && !isAuthorizedURL(config?.url)) {
config.headers["Authorization"] = `Bearer ${accessToken}`;
}
@ -83,7 +86,8 @@ function ApiInterceptor() {
await tryToRenewAccessToken(error);
const accessToken = cookies.get(LANGFLOW_ACCESS_TOKEN);
const accessToken = customGetAccessToken();
if (!accessToken && error?.config?.url?.includes("login")) {
return Promise.reject(error);
}
@ -142,7 +146,7 @@ function ApiInterceptor() {
// Request interceptor to add access token to every request
const requestInterceptor = api.interceptors.request.use(
(config) => {
async (config) => {
const controller = new AbortController();
try {
checkDuplicateRequestAndStoreRequest(config);
@ -152,7 +156,8 @@ function ApiInterceptor() {
console.error(error.message);
}
const accessToken = cookies.get(LANGFLOW_ACCESS_TOKEN);
const accessToken = customGetAccessToken();
if (accessToken && !isAuthorizedURL(config?.url)) {
config.headers["Authorization"] = `Bearer ${accessToken}`;
}
@ -234,7 +239,8 @@ function ApiInterceptor() {
const originalRequest = error.config as AxiosRequestConfig;
try {
const accessToken = cookies.get(LANGFLOW_ACCESS_TOKEN);
const accessToken = customGetAccessToken();
if (!accessToken) {
throw new Error("Access token not found in cookies");
}

View file

@ -1,3 +1,7 @@
import {
customGetAppVersions,
customGetLatestVersion,
} from "@/customization/utils/custom-get-app-latest-version";
import { Edge, Node, ReactFlowJsonObject } from "@xyflow/react";
import { AxiosRequestConfig, AxiosResponse } from "axios";
import { BASE_URL_API } from "../../constants/constants";
@ -32,6 +36,10 @@ export async function getDiscordCount() {
return null;
}
}
export const getAppVersions = customGetAppVersions;
export const getLatestVersion = customGetLatestVersion;
export async function createApiKey(name: string) {
try {
const res = await api.post(`${BASE_URL_API}api_key/`, { name });

View file

@ -1,3 +1,4 @@
import { customRefreshLatestVersion } from "@/customization/utils/custom-refresh-latest-version";
import { useDarkStore } from "@/stores/darkStore";
import { useQueryFunctionType } from "@/types/api";
import { api } from "../../api";
@ -23,9 +24,10 @@ export const useGetVersionQuery: useQueryFunctionType<
const responseFn = async () => {
const { data } = await getVersionFn();
const refreshVersion = useDarkStore.getState().refreshVersion;
const refreshLatestVersion = useDarkStore.getState().refreshLatestVersion;
refreshVersion(data.version);
refreshLatestVersion(data.main_version);
customRefreshLatestVersion(data.main_version);
return data;
};

View file

@ -0,0 +1,7 @@
import { AccountMenu } from "@/components/core/appHeaderComponent/components/AccountMenu";
export function CustomAccountMenu() {
return <AccountMenu />;
}
export default CustomAccountMenu;

View file

@ -0,0 +1,7 @@
import { DashboardWrapperPage } from "@/pages/DashboardWrapperPage";
export const CustomDashboardWrapperPage = () => {
return <DashboardWrapperPage />;
};
export default CustomDashboardWrapperPage;

View file

@ -0,0 +1,7 @@
import McpServerTab from "@/pages/MainPage/pages/homePage/components/McpServerTab";
export const CustomMcpServerTab = ({ folderName }: { folderName: string }) => {
return <McpServerTab folderName={folderName} />;
};
export default CustomMcpServerTab;

View file

@ -0,0 +1,54 @@
import { BuildStatus } from "@/constants/enums";
import NodeStatus from "@/CustomNodes/GenericNode/components/NodeStatus";
import { VertexBuildTypeAPI } from "@/types/api";
import { NodeDataType } from "@/types/flow";
export function CustomNodeStatus({
nodeId,
display_name,
selected,
setBorderColor,
frozen,
showNode,
data,
buildStatus,
dismissAll,
isOutdated,
isUserEdited,
isBreakingChange,
getValidationStatus,
}: {
nodeId: string;
display_name: string;
selected?: boolean;
setBorderColor: (color: string) => void;
frozen?: boolean;
showNode: boolean;
data: NodeDataType;
buildStatus: BuildStatus;
dismissAll: boolean;
isOutdated: boolean;
isUserEdited: boolean;
isBreakingChange: boolean;
getValidationStatus: (data) => VertexBuildTypeAPI | null;
}) {
return (
<NodeStatus
nodeId={nodeId}
display_name={display_name}
selected={selected}
setBorderColor={setBorderColor}
frozen={frozen}
showNode={showNode}
data={data}
buildStatus={buildStatus}
isOutdated={isOutdated}
isUserEdited={isUserEdited}
getValidationStatus={getValidationStatus}
dismissAll={dismissAll}
isBreakingChange={isBreakingChange}
/>
);
}
export default CustomNodeStatus;

View file

@ -0,0 +1,30 @@
import ConnectionComponent, {
ConnectionComponentProps,
} from "@/components/core/parameterRenderComponent/components/connectionComponent";
import { InputProps } from "@/components/core/parameterRenderComponent/types";
const CustomConnectionComponent = ({
tooltip = "",
name,
helperText = "",
helperMetadata = { icon: undefined, variant: "muted-foreground" },
options = [],
searchCategory = [],
buttonMetadata = { variant: "destructive", icon: "unplug" },
connectionLink = "",
...baseInputProps
}: InputProps<any, ConnectionComponentProps>) => {
return (
<ConnectionComponent
{...baseInputProps}
name={name}
helperMetadata={helperMetadata}
options={options}
searchCategory={searchCategory}
buttonMetadata={buttonMetadata}
connectionLink={connectionLink}
/>
);
};
export default CustomConnectionComponent;

View file

@ -0,0 +1,21 @@
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { DialogContent } from "@radix-ui/react-dialog";
import React from "react";
export const DialogContentWithouFixed = React.forwardRef<
React.ElementRef<typeof DialogPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> & {
hideTitle?: boolean;
closeButtonClassName?: string;
}
>(
(
{ className, children, hideTitle = false, closeButtonClassName, ...props },
ref,
) => {
return <></>;
},
);
DialogContent.displayName = DialogPrimitive.Content.displayName;
export default DialogContentWithouFixed;

View file

@ -0,0 +1,10 @@
import { EmptyPageCommunity } from "@/pages/MainPage/pages/empty-page";
export const CustomEmptyPageCommunity = ({
setOpenModal,
}: {
setOpenModal: (open: boolean) => void;
}) => {
return <EmptyPageCommunity setOpenModal={setOpenModal} />;
};
export default CustomEmptyPageCommunity;

View file

@ -0,0 +1,22 @@
import FetchErrorComponent from "@/components/common/fetchErrorComponent";
import { fetchErrorComponentType } from "@/types/components";
export function CustomFetchErrorComponent({
message,
description,
openModal,
setRetry,
isLoadingHealth,
}: fetchErrorComponentType) {
return (
<FetchErrorComponent
message={message}
description={description}
openModal={openModal}
setRetry={setRetry}
isLoadingHealth={isLoadingHealth}
/>
);
}
export default CustomFetchErrorComponent;

View file

@ -0,0 +1,12 @@
import FileCard from "@/modals/IOModal/components/chatView/fileComponent/components/file-card";
import { fileCardPropsType } from "@/types/components";
export function CustomFileCard({
fileName,
path,
fileType,
}: fileCardPropsType) {
return <FileCard fileName={fileName} path={path} fileType={fileType} />;
}
export default CustomFileCard;

View file

@ -0,0 +1,8 @@
import IOFileInput from "@/modals/IOModal/components/IOFieldView/components/file-input";
import { IOFileInputProps } from "@/types/components";
export function CustomIOFileInput({ field, updateValue }: IOFileInputProps) {
return <IOFileInput field={field} updateValue={updateValue} />;
}
export default CustomIOFileInput;

View file

@ -0,0 +1,25 @@
import { GetStartedProgress } from "@/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/get-started-progress";
import { Users } from "@/types/api";
export function CustomGetStartedProgress({
userData,
isGithubStarred,
isDiscordJoined,
handleDismissDialog,
}: {
userData: Users;
isGithubStarred: boolean;
isDiscordJoined: boolean;
handleDismissDialog: () => void;
}) {
return (
<GetStartedProgress
userData={userData}
isGithubStarred={isGithubStarred}
isDiscordJoined={isDiscordJoined}
handleDismissDialog={handleDismissDialog}
/>
);
}
export default CustomGetStartedProgress;

View file

@ -0,0 +1,7 @@
import { LangflowCounts } from "@/components/core/appHeaderComponent/components/langflow-counts";
export function CustomLangflowCounts() {
return <LangflowCounts />;
}
export default CustomLangflowCounts;

View file

@ -0,0 +1,29 @@
import LinkComponent from "@/components/core/parameterRenderComponent/components/linkComponent";
import {
InputProps,
LinkComponentType,
} from "@/components/core/parameterRenderComponent/types";
export function CustomLinkComponent({
value,
disabled = false,
id = "",
text,
icon,
editNode,
handleOnNewValue,
}: InputProps<string, LinkComponentType>) {
return (
<LinkComponent
value={value}
disabled={disabled}
id={id}
text={text}
icon={icon}
editNode={editNode}
handleOnNewValue={handleOnNewValue}
/>
);
}
export default CustomLinkComponent;

View file

@ -0,0 +1,24 @@
import IOModal from "@/modals/IOModal/new-modal";
import { IOModalPropsType } from "@/types/components";
export function CustomIOModal({
children,
open,
setOpen,
disable,
isPlayground,
canvasOpen,
playgroundPage,
}: IOModalPropsType) {
return (
<IOModal
children={children}
open={open}
setOpen={setOpen}
disable={disable}
isPlayground={isPlayground}
canvasOpen={canvasOpen}
playgroundPage={playgroundPage}
/>
);
}

View file

@ -1,3 +1,7 @@
import { ProfileIcon } from "@/components/core/appHeaderComponent/components/ProfileIcon";
export function CustomProfileIcon() {
return <></>;
return <ProfileIcon />;
}
export default CustomProfileIcon;

View file

@ -0,0 +1,20 @@
import ProfilePictureChooserComponent, {
ProfilePictureChooserComponentProps,
} from "@/pages/SettingsPage/pages/GeneralPage/components/ProfilePictureForm/components/profilePictureChooserComponent";
export function CustomProfilePictureChooserComponent({
profilePictures,
loading,
value,
onChange,
}: ProfilePictureChooserComponentProps) {
return (
<ProfilePictureChooserComponent
profilePictures={profilePictures}
loading={loading}
value={value}
onChange={onChange}
/>
);
}
export default CustomProfilePictureChooserComponent;

View file

@ -0,0 +1,21 @@
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import { SidebarMenuButton } from "@/components/ui/sidebar";
export const CustomStoreButton = () => {
return (
<>
<div className="flex w-full items-center" data-testid="button-store">
<SidebarMenuButton
size="md"
className="text-sm"
onClick={() => {
window.open("/store", "_blank");
}}
>
<ForwardedIconComponent name="Store" className="h-4 w-4" />
Store
</SidebarMenuButton>
</div>
</>
);
};

View file

@ -0,0 +1,26 @@
import { ForwardedIconComponent } from "@/components/common/genericIconComponent";
export const CustomStoreSidebar = () => {
return [
{
title: "Langflow API Keys",
href: "/settings/api-keys",
icon: (
<ForwardedIconComponent
name="Key"
className="w-4 flex-shrink-0 justify-start stroke-[1.5]"
/>
),
},
{
title: "Langflow Store",
href: "/settings/store",
icon: (
<ForwardedIconComponent
name="Store"
className="w-4 flex-shrink-0 justify-start stroke-[1.5]"
/>
),
},
];
};

View file

@ -0,0 +1,15 @@
import {
VoiceAssistant,
VoiceAssistantProps,
} from "@/modals/IOModal/components/chatView/chatInput/components/voice-assistant/voice-assistant";
export function CustomVoiceAssistant({
flowId,
setShowAudioInput,
}: VoiceAssistantProps) {
return (
<VoiceAssistant flowId={flowId} setShowAudioInput={setShowAudioInput} />
);
}
export default CustomVoiceAssistant;

View file

@ -0,0 +1,2 @@
//Langflow Desktop Base URL
export const baseURL = "";

View file

@ -0,0 +1,5 @@
import App from "../App";
export default function CustomApp() {
return <App />;
}

View file

@ -0,0 +1,23 @@
import { useStartConversation } from "@/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-start-conversation";
export const customUseStartConversation = (
flowId: string,
wsRef: React.MutableRefObject<WebSocket | null>,
setStatus: (status: string) => void,
startRecording: () => void,
handleWebSocketMessage: (event: MessageEvent) => void,
stopRecording: () => void,
currentSessionId: string,
) => {
return useStartConversation(
flowId,
wsRef,
setStatus,
startRecording,
handleWebSocketMessage,
stopRecording,
currentSessionId,
);
};
export default customUseStartConversation;

View file

@ -0,0 +1,32 @@
import { useStartRecording } from "@/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-start-recording";
import { MutableRefObject } from "react";
export const customUseStartRecording = (
audioContextRef: React.MutableRefObject<AudioContext | null>,
microphoneRef: MutableRefObject<MediaStreamAudioSourceNode | null>,
analyserRef: React.MutableRefObject<AnalyserNode | null>,
wsRef: React.MutableRefObject<WebSocket | null>,
setIsRecording: (isRecording: boolean) => void,
playNextAudioChunk: () => void,
isPlayingRef: React.MutableRefObject<boolean>,
audioQueueRef: MutableRefObject<AudioBuffer[]>,
workletCode: string,
processorRef: MutableRefObject<AudioWorkletNode | null>,
setStatus: (status: string) => void,
) => {
return useStartRecording(
audioContextRef,
microphoneRef,
analyserRef,
wsRef,
setIsRecording,
playNextAudioChunk,
isPlayingRef,
audioQueueRef,
workletCode,
processorRef,
setStatus,
);
};
export default customUseStartRecording;

View file

@ -0,0 +1,21 @@
export type Version = {
name: string;
url: string;
description_section?: {
section?: string;
descriptions?: string[];
}[];
version_oss: string;
is_lf_oss_update?: boolean;
date?: string;
};
export type UpdaterStoreType = {
openUpdaterModal: boolean;
setOpenUpdaterModal: (open: boolean) => void;
latestVersion: Version | null;
versionApp: string | null;
version_oss: string | null;
showVersionChangelog: boolean;
isLatestVersion: boolean;
};

View file

@ -0,0 +1,13 @@
import { BASE_URL_API } from "@/constants/constants";
export const customBuildUrl = (flowId: string, playgroundPage?: boolean) => {
return `${BASE_URL_API}${playgroundPage ? "build_public_tmp" : "build"}/${flowId}/flow`;
};
export const customCancelBuildUrl = (jobId: string) => {
return `${BASE_URL_API}build/${jobId}/cancel`;
};
export const customEventsUrl = (jobId: string) => {
return `${BASE_URL_API}build/${jobId}/events`;
};

View file

@ -0,0 +1,7 @@
import { LANGFLOW_ACCESS_TOKEN } from "@/constants/constants";
import { Cookies } from "react-cookie";
export const customGetAccessToken = () => {
const cookies = new Cookies();
return cookies.get(LANGFLOW_ACCESS_TOKEN);
};

View file

@ -0,0 +1,7 @@
export async function customGetAppVersions() {
return null;
}
export async function customGetLatestVersion() {
return null;
}

View file

@ -0,0 +1,6 @@
export const customGetHostProtocol = () => {
return {
host: window.location.host,
protocol: window.location.protocol,
};
};

View file

@ -0,0 +1,3 @@
export const customMcpOpen = () => {
return "_blank";
};

View file

@ -0,0 +1,5 @@
import { BASE_URL_API } from "@/constants/constants";
export const customPreLoadImageUrl = (imageUrl: string) => {
return `${BASE_URL_API}files/profile_pictures/${imageUrl}`;
};

View file

@ -0,0 +1,14 @@
import { FlowType } from "@/types/flow";
export const customDownloadFlow = (
flow: FlowType,
sortedJsonString: string,
flowName: string,
) => {
const dataUri = `data:text/json;chatset=utf-8,${encodeURIComponent(sortedJsonString)}`;
const downloadLink = document.createElement("a");
downloadLink.href = dataUri;
downloadLink.download = `${flowName || flow.name}.json`;
downloadLink.click();
};

View file

@ -0,0 +1,6 @@
import { useDarkStore } from "@/stores/darkStore";
export const customRefreshLatestVersion = (version: string) => {
const refreshLatestVersion = useDarkStore.getState().refreshLatestVersion;
refreshLatestVersion(version);
};

View file

@ -0,0 +1,29 @@
import { StoreGuard } from "@/components/authorization/storeGuard";
import StoreApiKeyPage from "@/pages/SettingsPage/pages/StoreApiKeyPage";
import StorePage from "@/pages/StorePage";
import { Route } from "react-router-dom";
export const CustomRoutesStorePages = () => {
return (
<>
<Route
path="store"
element={
<StoreGuard>
<StorePage />
</StoreGuard>
}
/>
<Route
path="store/:id/"
element={
<StoreGuard>
<StorePage />
</StoreGuard>
}
/>
</>
);
};
export default CustomRoutesStorePages;

View file

@ -0,0 +1,14 @@
import { StoreGuard } from "@/components/authorization/storeGuard";
import StoreApiKeyPage from "@/pages/SettingsPage/pages/StoreApiKeyPage";
import StorePage from "@/pages/StorePage";
import { Route } from "react-router-dom";
export const CustomRoutesStore = () => {
return (
<>
<Route path="store" element={<StoreApiKeyPage />} />
</>
);
};
export default CustomRoutesStore;

View file

@ -0,0 +1,4 @@
export const dialogClass = {
dialogContent:
"fixed inset-0 bottom-0 left-0 right-0 top-0 z-40 overflow-auto bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
};

View file

@ -9,7 +9,7 @@ import "./App.css";
import "./style/applies.css";
// @ts-ignore
import App from "./App";
import App from "./customization/custom-App";
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement,

View file

@ -1,3 +1,4 @@
import CustomIOFileInput from "@/customization/components/custom-file-input";
import useHandleNewValue from "@/CustomNodes/hooks/use-handle-new-value";
import { AllNodeType } from "@/types/flow";
import { cloneDeep } from "lodash";
@ -91,7 +92,7 @@ export default function IOFieldView({
);
case IOInputTypes.FILE_LOADER:
return (
<IOFileInput
<CustomIOFileInput
field={node.data.node!.template["file_path"]["value"]}
updateValue={(e) => {
if (node) {

View file

@ -7,6 +7,8 @@ import {
usePatchGlobalVariables,
usePostGlobalVariables,
} from "@/controllers/API/queries/variables";
import { customUseStartConversation } from "@/customization/hooks/use-custom-start-conversation";
import { customUseStartRecording } from "@/customization/hooks/use-custom-start-recording";
import useAlertStore from "@/stores/alertStore";
import useFlowStore from "@/stores/flowStore";
import { useGlobalVariablesStore } from "@/stores/globalVariablesStore/globalVariables";
@ -25,11 +27,9 @@ import { useHandleWebsocketMessage } from "./hooks/use-handle-websocket-message"
import { useInitializeAudio } from "./hooks/use-initialize-audio";
import { useInterruptPlayback } from "./hooks/use-interrupt-playback";
import { usePlayNextAudioChunk } from "./hooks/use-play-next-audio-chunk";
import { useStartConversation } from "./hooks/use-start-conversation";
import { useStartRecording } from "./hooks/use-start-recording";
import { useStopRecording } from "./hooks/use-stop-recording";
interface VoiceAssistantProps {
export interface VoiceAssistantProps {
flowId: string;
setShowAudioInput: (value: boolean) => void;
}
@ -133,7 +133,7 @@ export function VoiceAssistant({
};
const startRecording = async () => {
useStartRecording(
customUseStartRecording(
audioContextRef,
microphoneRef,
analyserRef,
@ -187,7 +187,7 @@ export function VoiceAssistant({
};
const startConversation = () => {
useStartConversation(
customUseStartConversation(
flowId,
wsRef,
setStatus,

View file

@ -255,7 +255,7 @@ export default function ChatMessage({
<ForwardedIconComponent name={chat.properties.icon} />
)
) : !ENABLE_DATASTAX_LANGFLOW && !playgroundPage ? (
<ProfileIcon />
<CustomProfileIcon />
) : playgroundPage ? (
<ForwardedIconComponent name="User" />
) : (

View file

@ -1,6 +1,6 @@
import CustomFileCard from "@/customization/components/custom-file-card";
import { useState } from "react";
import ForwardedIconComponent from "../../../../../../components/common/genericIconComponent";
import FileCard from "../../fileComponent/components/file-card";
import formatFileName from "../../fileComponent/utils/format-file-name";
export default function FileCardWrapper({
@ -33,7 +33,7 @@ export default function FileCardWrapper({
{formatFileName(name, 50)}
<ForwardedIconComponent name={show ? "ChevronDown" : "ChevronRight"} />
</span>
<FileCard
<CustomFileCard
showFile={show}
fileName={name}
fileType={type}

View file

@ -1,4 +1,5 @@
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
import { customGetHostProtocol } from "@/customization/utils/custom-get-host-protocol";
import useFlowStore from "@/stores/flowStore";
import { GetCodeType } from "@/types/tweaks";
@ -23,10 +24,11 @@ export function getCurlRunCode({
if (tweaksBuildedObject)
tweaksString = JSON.stringify(tweaksBuildedObject, null, 2);
// show the endpoint name in the curl command if it exists
const { protocol, host } = customGetHostProtocol();
return `curl -X POST \\
"${window.location.protocol}//${window.location.host}/api/v1/run/${
endpointName || flowId
}?stream=false" \\
"${protocol}//${host}/api/v1/run/${endpointName || flowId}?stream=false" \\
-H 'Content-Type: application/json'\\${
!isAuth ? `\n -H 'x-api-key: <your api key>'\\` : ""
}
@ -54,7 +56,8 @@ export function getCurlWebhookCode({
endpointName,
format = "multiline",
}: GetCodeType & { format?: "multiline" | "singleline" }) {
const baseUrl = `${window.location.protocol}//${window.location.host}/api/v1/webhook/${endpointName || flowId}`;
const { protocol, host } = customGetHostProtocol();
const baseUrl = `${protocol}//${host}/api/v1/webhook/${endpointName || flowId}`;
const authHeader = !isAuth ? `-H 'x-api-key: <your api key>'` : "";
if (format === "singleline") {
@ -93,8 +96,7 @@ export function getNewCurlCode({
activeTweaks: boolean;
endpointName: string;
}): string {
const host = window.location.host;
const protocol = window.location.protocol;
const { protocol, host } = customGetHostProtocol();
const apiUrl = `${protocol}//${host}/api/v1/run/${endpointName || flowId}`;
const tweaksString =

View file

@ -1,3 +1,4 @@
import { customGetHostProtocol } from "@/customization/utils/custom-get-host-protocol";
import useFlowStore from "@/stores/flowStore";
import { GetCodeType } from "@/types/tweaks";
@ -24,8 +25,10 @@ export default function getJsApiCode({
const hasChatInput = inputs.some((input) => input.type === "ChatInput");
const hasChatOutput = outputs.some((output) => output.type === "ChatOutput");
const { protocol, host } = customGetHostProtocol();
return `${activeTweaks ? "" : 'let inputValue = ""; // Insert input value here\n\n'}fetch(
"${window.location.protocol}//${window.location.host}/api/v1/run/${endpointName || flowId}?stream=false",
"${protocol}//${host}/api/v1/run/${endpointName || flowId}?stream=false",
{
method: "POST",
headers: {
@ -76,8 +79,7 @@ export function getNewJsApiCode({
activeTweaks: boolean;
endpointName: string;
}): string {
const host = window.location.host;
const protocol = window.location.protocol;
const { protocol, host } = customGetHostProtocol();
const apiUrl = `${protocol}//${host}/api/v1/run/${endpointName || flowId}`;
const tweaksString =

View file

@ -1,3 +1,4 @@
import { customGetHostProtocol } from "@/customization/utils/custom-get-host-protocol";
import { GetCodeType } from "@/types/tweaks";
/**
@ -134,8 +135,7 @@ export function getNewPythonApiCode({
activeTweaks: boolean;
endpointName: string;
}): string {
const host = window.location.host;
const protocol = window.location.protocol;
const { protocol, host } = customGetHostProtocol();
const apiUrl = `${protocol}//${host}/api/v1/run/${endpointName || flowId}`;
const tweaksString =

View file

@ -1,3 +1,4 @@
import { customGetHostProtocol } from "@/customization/utils/custom-get-host-protocol";
import { GetCodeType } from "@/types/tweaks";
/**
@ -20,11 +21,13 @@ export default function getWidgetCode({
build/static/js/bundle.min.js">
</script>`;
const { protocol, host } = customGetHostProtocol();
return `${source}
<langflow-chat
window_title="${flowName}"
flow_id="${flowId}"
host_url="${window.location.protocol}//${window.location.host}"${
host_url="${protocol}//${host}"${
!isAuth
? `
api_key="..."`

View file

@ -4,6 +4,7 @@ import React from "react";
import {
Dialog,
DialogContent,
DialogContentWithouFixed,
DialogDescription,
DialogHeader,
DialogTitle,
@ -196,6 +197,7 @@ interface BaseModalProps {
onSubmit?: () => void;
onEscapeKeyDown?: (e: KeyboardEvent) => void;
closeButtonClassName?: string;
dialogContentWithouFixed?: boolean;
}
function BaseModal({
className,
@ -208,6 +210,7 @@ function BaseModal({
onSubmit,
onEscapeKeyDown,
closeButtonClassName,
dialogContentWithouFixed = false,
}: BaseModalProps) {
const headerChild = React.Children.toArray(children).find(
(child) => (child as React.ReactElement).type === Header,
@ -262,27 +265,51 @@ function BaseModal({
) : (
<Dialog open={open} onOpenChange={setOpen}>
{triggerChild}
<DialogContent
onClick={(e) => e.stopPropagation()}
onOpenAutoFocus={(event) => event.preventDefault()}
onEscapeKeyDown={onEscapeKeyDown}
className={contentClasses}
closeButtonClassName={closeButtonClassName}
>
{onSubmit ? (
<Form.Root
onSubmit={(event) => {
event.preventDefault();
onSubmit();
}}
className={formClasses}
>
{modalContent}
</Form.Root>
) : (
modalContent
)}
</DialogContent>
{dialogContentWithouFixed ? (
<DialogContentWithouFixed
onClick={(e) => e.stopPropagation()}
onOpenAutoFocus={(event) => event.preventDefault()}
onEscapeKeyDown={onEscapeKeyDown}
className={contentClasses}
closeButtonClassName={closeButtonClassName}
>
{onSubmit ? (
<Form.Root
onSubmit={(event) => {
event.preventDefault();
onSubmit();
}}
className={formClasses}
>
{modalContent}
</Form.Root>
) : (
modalContent
)}
</DialogContentWithouFixed>
) : (
<DialogContent
onClick={(e) => e.stopPropagation()}
onOpenAutoFocus={(event) => event.preventDefault()}
onEscapeKeyDown={onEscapeKeyDown}
className={contentClasses}
closeButtonClassName={closeButtonClassName}
>
{onSubmit ? (
<Form.Root
onSubmit={(event) => {
event.preventDefault();
onSubmit();
}}
className={formClasses}
>
{modalContent}
</Form.Root>
) : (
modalContent
)}
</DialogContent>
)}
</Dialog>
)}
</>

View file

@ -1,5 +1,5 @@
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
import { useGenerateToken } from "@/customization/hooks/use-generate-token";
import { useGenerateToken } from "@/customization/hooks/use-custom-generate-token";
import { useEffect, useRef, useState } from "react";
import { COPIED_NOTICE_ALERT } from "../../constants/alerts_constants";
import { createApiKey } from "../../controllers/API";

View file

@ -1,4 +1,3 @@
import FetchErrorComponent from "@/components/common/fetchErrorComponent";
import TimeoutErrorComponent from "@/components/common/timeoutErrorComponent";
import {
FETCH_ERROR_DESCRIPION,
@ -6,18 +5,19 @@ import {
TIMEOUT_ERROR_DESCRIPION,
TIMEOUT_ERROR_MESSAGE,
} from "@/constants/constants";
import CustomFetchErrorComponent from "@/customization/components/custom-fetch-error-component";
export function GenericErrorComponent({ healthCheckTimeout, fetching, retry }) {
switch (healthCheckTimeout) {
case "serverDown":
return (
<FetchErrorComponent
<CustomFetchErrorComponent
description={FETCH_ERROR_DESCRIPION}
message={FETCH_ERROR_MESSAGE}
openModal={true}
setRetry={retry}
isLoadingHealth={fetching}
></FetchErrorComponent>
></CustomFetchErrorComponent>
);
case "timeout":
return (

View file

@ -3,6 +3,7 @@ import CardsWrapComponent from "@/components/core/cardsWrapComponent";
import { IS_MAC } from "@/constants/constants";
import { useGetFolderQuery } from "@/controllers/API/queries/folders/use-get-folder";
import { CustomBanner } from "@/customization/components/custom-banner";
import { CustomMcpServerTab } from "@/customization/components/custom-McpServerTab";
import { ENABLE_DATASTAX_LANGFLOW } from "@/customization/feature-flags";
import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { useFolderStore } from "@/stores/foldersStore";
@ -15,7 +16,6 @@ import ListSkeleton from "../../components/listSkeleton";
import ModalsComponent from "../../components/modalsComponent";
import useFileDrop from "../../hooks/use-on-file-drop";
import EmptyFolder from "../emptyFolder";
import McpServerTab from "./components/McpServerTab";
const HomePage = ({ type }: { type: "flows" | "components" | "mcp" }) => {
const [view, setView] = useState<"grid" | "list">(() => {
@ -211,7 +211,7 @@ const HomePage = ({ type }: { type: "flows" | "components" | "mcp" }) => {
</div>
)
) : flowType === "mcp" ? (
<McpServerTab folderName={folderName} />
<CustomMcpServerTab folderName={folderName} />
) : (flowType === "flows" || flowType === "components") &&
data &&
data.pagination.total > 0 ? (

View file

@ -1,6 +1,7 @@
import SideBarFoldersButtonsComponent from "@/components/core/folderSidebarComponent/components/sideBarFolderButtons";
import { SidebarProvider } from "@/components/ui/sidebar";
import { useDeleteFolders } from "@/controllers/API/queries/folders";
import CustomEmptyPageCommunity from "@/customization/components/custom-empty-page";
import CustomLoader from "@/customization/components/custom-loader";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import useAlertStore from "@/stores/alertStore";
@ -80,9 +81,7 @@ export default function CollectionPage(): JSX.Element {
{flows?.length !== examples?.length || folders?.length > 1 ? (
<Outlet />
) : (
// <EmptyPage setOpenModal={setOpenModal} />
<EmptyPageCommunity setOpenModal={setOpenModal} />
<CustomEmptyPageCommunity setOpenModal={setOpenModal} />
)}
</div>
) : (

View file

@ -1,8 +1,8 @@
import { useGetConfig } from "@/controllers/API/queries/config/use-get-config";
import { useGetFlow } from "@/controllers/API/queries/flows/use-get-flow";
import { CustomIOModal } from "@/customization/components/custom-new-modal";
import { useCustomNavigate } from "@/customization/hooks/use-custom-navigate";
import { track } from "@/customization/utils/analytics";
import IOModal from "@/modals/IOModal/new-modal";
import useFlowStore from "@/stores/flowStore";
import { useUtilityStore } from "@/stores/utilityStore";
import { CookieOptions, getCookie, setCookie } from "@/utils/utils";
@ -93,9 +93,14 @@ export default function PlaygroundPage() {
return (
<div className="flex h-full w-full flex-col items-center justify-center align-middle">
{currentSavedFlow && (
<IOModal open={true} setOpen={() => {}} isPlayground playgroundPage>
<CustomIOModal
open={true}
setOpen={() => {}}
isPlayground
playgroundPage
>
<></>
</IOModal>
</CustomIOModal>
)}
</div>
);

View file

@ -1,5 +1,6 @@
import SideBarButtonsComponent from "@/components/core/sidebarComponent";
import { SidebarProvider } from "@/components/ui/sidebar";
import { CustomStoreSidebar } from "@/customization/components/custom-store-sidebar";
import {
ENABLE_DATASTAX_LANGFLOW,
ENABLE_PROFILE_ICONS,
@ -9,7 +10,6 @@ import { useStoreStore } from "@/stores/storeStore";
import { Outlet } from "react-router-dom";
import ForwardedIconComponent from "../../components/common/genericIconComponent";
import PageLayout from "../../components/common/pageLayout";
export default function SettingsPage(): JSX.Element {
const autoLogin = useAuthStore((state) => state.autoLogin);
const hasStore = useStoreStore((state) => state.hasStore);
@ -71,28 +71,7 @@ export default function SettingsPage(): JSX.Element {
);
if (!ENABLE_DATASTAX_LANGFLOW) {
const langflowItems = [
{
title: "Langflow API Keys",
href: "/settings/api-keys",
icon: (
<ForwardedIconComponent
name="Key"
className="w-4 flex-shrink-0 justify-start stroke-[1.5]"
/>
),
},
{
title: "Langflow Store",
href: "/settings/store",
icon: (
<ForwardedIconComponent
name="Store"
className="w-4 flex-shrink-0 justify-start stroke-[1.5]"
/>
),
},
];
const langflowItems = CustomStoreSidebar();
sidebarNavItems.splice(2, 0, ...langflowItems);
}

View file

@ -1,5 +1,5 @@
import { customPreLoadImageUrl } from "@/customization/utils/custom-pre-load-image-url";
import { useEffect } from "react";
import { BASE_URL_API } from "../../../../../../../../../constants/constants";
const usePreloadImages = (
setImagesLoaded: (value: boolean) => void,
@ -26,9 +26,7 @@ const usePreloadImages = (
Object.keys(profilePictures).flatMap((folder) =>
profilePictures[folder].map((path) =>
imageArray.push(
`${BASE_URL_API}files/profile_pictures/${folder}/${path}`,
),
imageArray.push(customPreLoadImageUrl(`${folder}/${path}`)),
),
);

View file

@ -1,13 +1,13 @@
import { ProfilePicturesQueryResponse } from "@/controllers/API/queries/files";
import { customPreLoadImageUrl } from "@/customization/utils/custom-pre-load-image-url";
import { useEffect, useRef, useState } from "react";
import { Button } from "../../../../../../../../components/ui/button";
import Loading from "../../../../../../../../components/ui/loading";
import { BASE_URL_API } from "../../../../../../../../constants/constants";
import { useDarkStore } from "../../../../../../../../stores/darkStore";
import { cn } from "../../../../../../../../utils/utils";
import usePreloadImages from "./hooks/use-preload-images";
type ProfilePictureChooserComponentProps = {
export type ProfilePictureChooserComponentProps = {
profilePictures?: ProfilePicturesQueryResponse;
loading: boolean;
value: string;
@ -54,9 +54,7 @@ export default function ProfilePictureChooserComponent({
>
<img
key={idx}
src={`${BASE_URL_API}files/profile_pictures/${
folder + "/" + path
}`}
src={customPreLoadImageUrl(`${folder}/${path}`)}
style={{
filter:
value === folder + "/" + path

View file

@ -9,18 +9,19 @@ import { ProtectedAdminRoute } from "./components/authorization/authAdminGuard";
import { ProtectedRoute } from "./components/authorization/authGuard";
import { ProtectedLoginRoute } from "./components/authorization/authLoginGuard";
import { AuthSettingsGuard } from "./components/authorization/authSettingsGuard";
import { StoreGuard } from "./components/authorization/storeGuard";
import ContextWrapper from "./contexts";
import CustomDashboardWrapperPage from "./customization/components/custom-DashboardWrapperPage";
import { CustomNavigate } from "./customization/components/custom-navigate";
import { BASENAME } from "./customization/config-constants";
import {
ENABLE_CUSTOM_PARAM,
ENABLE_FILE_MANAGEMENT,
} from "./customization/feature-flags";
import { CustomRoutesStore } from "./customization/utils/custom-routes-store";
import { CustomRoutesStorePages } from "./customization/utils/custom-routes-store-pages";
import { AppAuthenticatedPage } from "./pages/AppAuthenticatedPage";
import { AppInitPage } from "./pages/AppInitPage";
import { AppWrapperPage } from "./pages/AppWrapperPage";
import { DashboardWrapperPage } from "./pages/DashboardWrapperPage";
import FlowPage from "./pages/FlowPage";
import LoginPage from "./pages/LoginPage";
import FilesPage from "./pages/MainPage/pages/filesPage";
@ -32,8 +33,6 @@ import GeneralPage from "./pages/SettingsPage/pages/GeneralPage";
import GlobalVariablesPage from "./pages/SettingsPage/pages/GlobalVariablesPage";
import MessagesPage from "./pages/SettingsPage/pages/messagesPage";
import ShortcutsPage from "./pages/SettingsPage/pages/ShortcutsPage";
import StoreApiKeyPage from "./pages/SettingsPage/pages/StoreApiKeyPage";
import StorePage from "./pages/StorePage";
import ViewPage from "./pages/ViewPage";
const AdminPage = lazy(() => import("./pages/AdminPage"));
@ -43,6 +42,7 @@ const DeleteAccountPage = lazy(() => import("./pages/DeleteAccountPage"));
const PlaygroundPage = lazy(() => import("./pages/Playground"));
const SignUp = lazy(() => import("./pages/SignUpPage"));
const router = createBrowserRouter(
createRoutesFromElements([
<Route path="/playground/:id/">
@ -74,7 +74,7 @@ const router = createBrowserRouter(
}
>
<Route path="" element={<AppAuthenticatedPage />}>
<Route path="" element={<DashboardWrapperPage />}>
<Route path="" element={<CustomDashboardWrapperPage />}>
<Route path="" element={<CollectionPage />}>
<Route
index
@ -135,24 +135,9 @@ const router = createBrowserRouter(
/>
<Route path="shortcuts" element={<ShortcutsPage />} />
<Route path="messages" element={<MessagesPage />} />
<Route path="store" element={<StoreApiKeyPage />} />
{CustomRoutesStore()}
</Route>
<Route
path="store"
element={
<StoreGuard>
<StorePage />
</StoreGuard>
}
/>
<Route
path="store/:id/"
element={
<StoreGuard>
<StorePage />
</StoreGuard>
}
/>
{CustomRoutesStorePages()}
<Route path="account">
<Route path="delete" element={<DeleteAccountPage />}></Route>
</Route>
@ -166,7 +151,7 @@ const router = createBrowserRouter(
/>
</Route>
<Route path="flow/:id/">
<Route path="" element={<DashboardWrapperPage />}>
<Route path="" element={<CustomDashboardWrapperPage />}>
<Route path="folder/:folderId/" element={<FlowPage />} />
<Route path="" element={<FlowPage />} />
</Route>

View file

@ -5,6 +5,11 @@ import {
POLLING_MESSAGES,
} from "@/constants/constants";
import { performStreamingRequest } from "@/controllers/API/api";
import {
customBuildUrl,
customCancelBuildUrl,
customEventsUrl,
} from "@/customization/utils/custom-buildUtils";
import { useMessagesStore } from "@/stores/messagesStore";
import { Edge, Node } from "@xyflow/react";
import { AxiosError } from "axios";
@ -268,7 +273,7 @@ export async function buildFlowVertices({
}: BuildVerticesParams) {
const inputs = {};
let buildUrl = `${BASE_URL_API}${playgroundPage ? "build_public_tmp" : "build"}/${flowId}/flow`;
let buildUrl = customBuildUrl(flowId, playgroundPage);
const queryParams = new URLSearchParams();
@ -381,7 +386,7 @@ export async function buildFlowVertices({
const { job_id } = await buildResponse.json();
const cancelBuildUrl = `${BASE_URL_API}build/${job_id}/cancel`;
const cancelBuildUrl = customCancelBuildUrl(job_id);
// Get the buildController from flowStore
const buildController = new AbortController();
@ -399,7 +404,7 @@ export async function buildFlowVertices({
});
useFlowStore.getState().setBuildController(buildController);
// Then stream the events
const eventsUrl = `${BASE_URL_API}build/${job_id}/events`;
const eventsUrl = customEventsUrl(job_id);
const buildResults: Array<boolean> = [];
const verticesStartTimeMs: Map<string, number> = new Map();

View file

@ -16,6 +16,7 @@ import {
getRightHandleId,
} from "@/CustomNodes/utils/get-handle-id";
import { INCOMPLETE_LOOP_ERROR_ALERT } from "@/constants/alerts_constants";
import { customDownloadFlow } from "@/customization/utils/custom-reactFlowUtils";
import {
Connection,
Edge,
@ -1792,7 +1793,7 @@ function sortJsonStructure<T>(obj: T): T {
* @param flowName - The name to use for the flow
* @param flowDescription - Optional description for the flow
*/
export function downloadFlow(
export async function downloadFlow(
flow: FlowType,
flowName: string,
flowDescription?: string,
@ -1811,12 +1812,7 @@ export function downloadFlow(
const sortedData = sortJsonStructure(flowData);
const sortedJsonString = JSON.stringify(sortedData, null, 2);
const dataUri = `data:text/json;chatset=utf-8,${encodeURIComponent(sortedJsonString)}`;
const downloadLink = document.createElement("a");
downloadLink.href = dataUri;
downloadLink.download = `${flowName || flow.name}.json`;
downloadLink.click();
customDownloadFlow(flow, sortedJsonString, flowName);
} catch (error) {
console.error("Error downloading flow:", error);
}