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:
parent
25cdc4b80d
commit
c2e78180f1
77 changed files with 847 additions and 178 deletions
|
|
@ -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(
|
||||
|
|
|
|||
13
src/frontend/src/assets/langflow_logo_black.svg
Normal file
13
src/frontend/src/assets/langflow_logo_black.svg
Normal 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 |
13
src/frontend/src/assets/langflow_logo_white.svg
Normal file
13
src/frontend/src/assets/langflow_logo_white.svg
Normal 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 |
|
|
@ -266,16 +266,6 @@ export default function StoreCardComponent({
|
|||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
{/* {openPlayground && (
|
||||
<IOModal
|
||||
key={data.id}
|
||||
cleanOnClose={true}
|
||||
open={openPlayground}
|
||||
setOpen={setOpenPlayground}
|
||||
>
|
||||
<></>
|
||||
</IOModal>
|
||||
)} */}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]">
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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?.()}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ export default function LinkComponent({
|
|||
id = "",
|
||||
text,
|
||||
icon,
|
||||
editNode = false,
|
||||
handleOnNewValue,
|
||||
}: InputProps<string, LinkComponentType>): JSX.Element {
|
||||
function handleOpenLink() {
|
||||
if (value) {
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
100
src/frontend/src/components/ui/text-loop.tsx
Normal file
100
src/frontend/src/components/ui/text-loop.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
|
|
@ -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: "/" });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 });
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
import { AccountMenu } from "@/components/core/appHeaderComponent/components/AccountMenu";
|
||||
|
||||
export function CustomAccountMenu() {
|
||||
return <AccountMenu />;
|
||||
}
|
||||
|
||||
export default CustomAccountMenu;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import { DashboardWrapperPage } from "@/pages/DashboardWrapperPage";
|
||||
|
||||
export const CustomDashboardWrapperPage = () => {
|
||||
return <DashboardWrapperPage />;
|
||||
};
|
||||
|
||||
export default CustomDashboardWrapperPage;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import { LangflowCounts } from "@/components/core/appHeaderComponent/components/langflow-counts";
|
||||
|
||||
export function CustomLangflowCounts() {
|
||||
return <LangflowCounts />;
|
||||
}
|
||||
|
||||
export default CustomLangflowCounts;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,3 +1,7 @@
|
|||
import { ProfileIcon } from "@/components/core/appHeaderComponent/components/ProfileIcon";
|
||||
|
||||
export function CustomProfileIcon() {
|
||||
return <></>;
|
||||
return <ProfileIcon />;
|
||||
}
|
||||
|
||||
export default CustomProfileIcon;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
@ -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]"
|
||||
/>
|
||||
),
|
||||
},
|
||||
];
|
||||
};
|
||||
|
|
@ -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;
|
||||
2
src/frontend/src/customization/constants.ts
Normal file
2
src/frontend/src/customization/constants.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
//Langflow Desktop Base URL
|
||||
export const baseURL = "";
|
||||
5
src/frontend/src/customization/custom-App.tsx
Normal file
5
src/frontend/src/customization/custom-App.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import App from "../App";
|
||||
|
||||
export default function CustomApp() {
|
||||
return <App />;
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
21
src/frontend/src/customization/types/updater.ts
Normal file
21
src/frontend/src/customization/types/updater.ts
Normal 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;
|
||||
};
|
||||
13
src/frontend/src/customization/utils/custom-buildUtils.ts
Normal file
13
src/frontend/src/customization/utils/custom-buildUtils.ts
Normal 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`;
|
||||
};
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
export async function customGetAppVersions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
export async function customGetLatestVersion() {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
export const customGetHostProtocol = () => {
|
||||
return {
|
||||
host: window.location.host,
|
||||
protocol: window.location.protocol,
|
||||
};
|
||||
};
|
||||
3
src/frontend/src/customization/utils/custom-mcp-open.ts
Normal file
3
src/frontend/src/customization/utils/custom-mcp-open.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export const customMcpOpen = () => {
|
||||
return "_blank";
|
||||
};
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { BASE_URL_API } from "@/constants/constants";
|
||||
|
||||
export const customPreLoadImageUrl = (imageUrl: string) => {
|
||||
return `${BASE_URL_API}files/profile_pictures/${imageUrl}`;
|
||||
};
|
||||
|
|
@ -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();
|
||||
};
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { useDarkStore } from "@/stores/darkStore";
|
||||
|
||||
export const customRefreshLatestVersion = (version: string) => {
|
||||
const refreshLatestVersion = useDarkStore.getState().refreshLatestVersion;
|
||||
refreshLatestVersion(version);
|
||||
};
|
||||
|
|
@ -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;
|
||||
14
src/frontend/src/customization/utils/custom-routes-store.tsx
Normal file
14
src/frontend/src/customization/utils/custom-routes-store.tsx
Normal 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;
|
||||
4
src/frontend/src/customization/utils/dialog-class.ts
Normal file
4
src/frontend/src/customization/utils/dialog-class.ts
Normal 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",
|
||||
};
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ export default function ChatMessage({
|
|||
<ForwardedIconComponent name={chat.properties.icon} />
|
||||
)
|
||||
) : !ENABLE_DATASTAX_LANGFLOW && !playgroundPage ? (
|
||||
<ProfileIcon />
|
||||
<CustomProfileIcon />
|
||||
) : playgroundPage ? (
|
||||
<ForwardedIconComponent name="User" />
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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="..."`
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
|
|
|
|||
|
|
@ -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 ? (
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}`)),
|
||||
),
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue