connection integration list and blocks

This commit is contained in:
Abhimanyu Yadav
2025-05-26 00:25:30 +05:30
parent 6f1c522ea3
commit 0361ea4aa4
30 changed files with 60 additions and 59 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -32,13 +32,14 @@ const Integration: IntegrationComponent = ({
)}
{...rest}
>
<div className="relative h-[2.625rem] w-[2.625rem] rounded-[0.5rem] bg-white">
<div className="relative h-[2.625rem] w-[2.625rem] overflow-hidden rounded-[0.5rem] bg-white">
{icon_url && (
// TODO : handle fallback
<Image
src={icon_url}
alt="integration-icon"
fill
className="w-full object-contain group-disabled:opacity-50"
className="w-full rounded-[0.5rem] object-contain group-disabled:opacity-50"
/>
)}
</div>

View File

@@ -1,6 +1,6 @@
"use client";
import { Block } from "@/lib/autogpt-server-api";
import { Block, CredentialsProviderName } from "@/lib/autogpt-server-api";
import { createContext, ReactNode, useContext, useState } from "react";
interface BaseSearchItem {
@@ -82,8 +82,10 @@ export interface Filters {
interface BlockMenuContextType {
defaultState: DefaultStateType;
setDefaultState: React.Dispatch<React.SetStateAction<DefaultStateType>>;
integration: string;
setIntegration: React.Dispatch<React.SetStateAction<string>>;
integration: CredentialsProviderName | null;
setIntegration: React.Dispatch<
React.SetStateAction<CredentialsProviderName | null>
>;
searchQuery: string;
setSearchQuery: React.Dispatch<React.SetStateAction<string>>;
filters: Filters;
@@ -120,7 +122,8 @@ export function BlockMenuStateProvider({
}: BlockMenuStateProviderProps) {
const [defaultState, setDefaultState] =
useState<DefaultStateType>("suggestion");
const [integration, setIntegration] = useState("");
const [integration, setIntegration] =
useState<CredentialsProviderName | null>(null);
const [searchQuery, setSearchQuery] = useState("");
const [filters, setFilters] = useState<Filters>({
categories: {

View File

@@ -43,7 +43,7 @@ const BlockMenuSidebar: React.FC = ({}) => {
type: "integrations",
number: 24,
onClick: () => {
setIntegration("");
setIntegration(null);
setDefaultState("integrations");
},
},

View File

@@ -6,36 +6,28 @@ import {
integrationsListData,
} from "../../testing_data";
import { useBlockMenuContext } from "../block-menu-provider";
export interface IntegrationBlockData {
title: string;
description: string;
icon_url: string;
}
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import { Block } from "@/lib/autogpt-server-api";
const IntegrationBlocks: React.FC = ({}) => {
const { integration, setIntegration } = useBlockMenuContext();
const [blocks, setBlocks] = useState<IntegrationBlockData[]>([]);
const { integration, setIntegration, addNode } = useBlockMenuContext();
const [blocks, setBlocks] = useState<Block[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
// TEMPORARY FETCHING
useEffect(() => {
if (integration) {
setIsLoading(true);
setTimeout(() => {
const foundBlocks = integrationBlocksData[integration] || [];
setBlocks(foundBlocks);
setIsLoading(false);
}, 800);
}
}, [integration]);
const api = useBackendAPI();
const getBlockCount = (): number => {
const integrationData = integrationsListData.find(
(item) => item.title === integration,
);
return integrationData?.number_of_blocks || 0;
};
useEffect(() => {
const fetchBlocks = async () => {
if (integration) {
setIsLoading(true);
const response = await api.getBuilderBlocks({ provider: integration });
setBlocks(response.blocks);
setIsLoading(false);
}
};
fetchBlocks();
}, [api, integration]);
return (
<div className="space-y-2.5">
@@ -45,7 +37,7 @@ const IntegrationBlocks: React.FC = ({}) => {
variant={"link"}
className="p-0 font-sans text-sm font-medium leading-[1.375rem] text-zinc-800"
onClick={() => {
setIntegration("");
setIntegration(null);
}}
>
Integrations
@@ -58,7 +50,7 @@ const IntegrationBlocks: React.FC = ({}) => {
</p>
</div>
<span className="flex h-[1.375rem] w-[1.6875rem] items-center justify-center rounded-[1.25rem] bg-[#f0f0f0] p-1.5 font-sans text-sm leading-[1.375rem] text-zinc-500 group-disabled:text-zinc-400">
{getBlockCount()}
{blocks.length}
</span>
</div>
@@ -75,9 +67,17 @@ const IntegrationBlocks: React.FC = ({}) => {
{blocks.map((block, index) => (
<IntegrationBlock
key={index}
title={block.title}
title={block.name}
description={block.description}
icon_url={block.icon_url}
icon_url={`/integrations/${integration}.png`}
onClick={() => {
addNode(
block.id,
block.name,
block.hardcodedValues || {},
block,
);
}}
/>
))}
</div>

View File

@@ -1,28 +1,23 @@
import React, { useState, useEffect } from "react";
import Integration from "../Integration";
import { integrationsListData } from "../../testing_data";
import { useBlockMenuContext } from "../block-menu-provider";
export interface IntegrationData {
title: string;
icon_url: string;
description: string;
number_of_blocks: number;
}
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import { Provider } from "@/lib/autogpt-server-api";
const IntegrationList: React.FC = ({}) => {
const { setIntegration } = useBlockMenuContext();
const [integrations, setIntegrations] = useState<IntegrationData[]>([]);
const [integrations, setIntegrations] = useState<Provider[]>([]);
const [isLoading, setIsLoading] = useState<boolean>(true);
// TEMPORARY FETCHING
const api = useBackendAPI();
useEffect(() => {
const fetchIntegrations = async () => {
setIsLoading(true);
try {
await new Promise((resolve) => setTimeout(resolve, 1000));
setIntegrations(integrationsListData);
// Some integrations are missing, like twitter or todoist or more
const providers = await api.getProviders();
setIntegrations(providers.providers);
} catch (error) {
console.error("Failed to fetch integrations:", error);
} finally {
@@ -31,7 +26,7 @@ const IntegrationList: React.FC = ({}) => {
};
fetchIntegrations();
}, []);
}, [api]);
if (isLoading) {
return (
@@ -50,11 +45,11 @@ const IntegrationList: React.FC = ({}) => {
{integrations.map((integration, index) => (
<Integration
key={index}
title={integration.title}
icon_url={integration.icon_url}
title={integration.name}
icon_url={`/integrations/${integration.name}.png`}
description={integration.description}
number_of_blocks={integration.number_of_blocks}
onClick={() => setIntegration(integration.title)}
number_of_blocks={integration.integration_count}
onClick={() => setIntegration(integration.name)}
/>
))}
</div>

View File

@@ -8,7 +8,7 @@ const IntegrationsContent: React.FC = () => {
return (
<div className="scrollbar-thumb-rounded h-full overflow-y-auto pt-4 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-zinc-200">
<div className="w-full px-4 pb-4">
{integration == "" ? <IntegrationList /> : <IntegrationBlocks />}
{!integration ? <IntegrationList /> : <IntegrationBlocks />}
</div>
</div>
);

View File

@@ -3,7 +3,10 @@ import SearchHistoryChip from "../SearchHistoryChip";
import IntegrationChip from "../IntegrationChip";
import Block from "../Block";
import { useBlockMenuContext } from "../block-menu-provider";
import { SuggestionsResponse } from "@/lib/autogpt-server-api";
import {
CredentialsProviderName,
SuggestionsResponse,
} from "@/lib/autogpt-server-api";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
const SuggestionContent: React.FC = () => {
@@ -16,7 +19,6 @@ const SuggestionContent: React.FC = () => {
const api = useBackendAPI();
// TEMPORARY FETCHING
useEffect(() => {
const fetchSuggestions = async () => {
try {
@@ -33,7 +35,7 @@ const SuggestionContent: React.FC = () => {
};
fetchSuggestions();
}, []);
}, [api]);
return (
<div className="scrollbar-thumb-rounded h-full overflow-y-auto pt-4 scrollbar-thin scrollbar-track-transparent scrollbar-thumb-zinc-200">
@@ -78,7 +80,7 @@ const SuggestionContent: React.FC = () => {
name={provider}
onClick={() => {
setDefaultState("integrations");
setIntegration(provider);
setIntegration(provider as CredentialsProviderName);
}}
/>
))