diff --git a/backend/modules/brain/entity/integration_brain.py b/backend/modules/brain/entity/integration_brain.py index 0af7e2a0b..96bef6038 100644 --- a/backend/modules/brain/entity/integration_brain.py +++ b/backend/modules/brain/entity/integration_brain.py @@ -10,6 +10,15 @@ class IntegrationType(str, Enum): SYNC = "sync" DOC = "doc" +class IntegrationBrainTag(str, Enum): + NEW = "new" + RECOMMENDED = "recommended" + MOST_POPULAR = "most_popular" + PREMIUM = "premium" + COMING_SOON = "coming_soon" + COMMUNITY = "community" + DEPRECATED = "deprecated" + class IntegrationDescriptionEntity(BaseModel): id: UUID @@ -17,8 +26,11 @@ class IntegrationDescriptionEntity(BaseModel): integration_logo_url: Optional[str] = None connection_settings: Optional[dict] = None integration_type: IntegrationType + tags: Optional[list[IntegrationBrainTag]] = [] + information: Optional[str] = None description: str max_files: int + allow_model_change: bool class IntegrationEntity(BaseModel): diff --git a/frontend/app/studio/[brainId]/BrainManagementTabs/components/SettingsTab/SettingsTab.tsx b/frontend/app/studio/[brainId]/BrainManagementTabs/components/SettingsTab/SettingsTab.tsx index d6ec7836a..25a08c799 100644 --- a/frontend/app/studio/[brainId]/BrainManagementTabs/components/SettingsTab/SettingsTab.tsx +++ b/frontend/app/studio/[brainId]/BrainManagementTabs/components/SettingsTab/SettingsTab.tsx @@ -59,7 +59,7 @@ export const SettingsTabContent = ({
- {brain?.brain_type === "doc" && ( + {brain?.integration_description?.allow_model_change && (
; + connection_settings: string; integration_type: "custom" | "sync"; description: string; max_files: number; + tags: IntegrationBrainTag[]; + information: string; }; export type UpdateBrainInput = Partial; diff --git a/frontend/lib/api/brain/utils/mapBackendMinimalBrainToMinimalBrain.ts b/frontend/lib/api/brain/utils/mapBackendMinimalBrainToMinimalBrain.ts index 7f809b848..10a5b35e0 100644 --- a/frontend/lib/api/brain/utils/mapBackendMinimalBrainToMinimalBrain.ts +++ b/frontend/lib/api/brain/utils/mapBackendMinimalBrainToMinimalBrain.ts @@ -14,4 +14,5 @@ export const mapBackendMinimalBrainToMinimalBrain = ( description: backendMinimalBrain.description, integration_logo_url: backendMinimalBrain.integration_logo_url, max_files: backendMinimalBrain.max_files, + allow_model_change: backendMinimalBrain.allow_model_change, }); diff --git a/frontend/lib/components/AddBrainModal/AddBrainModal.tsx b/frontend/lib/components/AddBrainModal/AddBrainModal.tsx index 354fa4080..ce7e21675 100644 --- a/frontend/lib/components/AddBrainModal/AddBrainModal.tsx +++ b/frontend/lib/components/AddBrainModal/AddBrainModal.tsx @@ -19,7 +19,7 @@ export const AddBrainModal = (): JSX.Element => { const { isBrainCreationModalOpened, setIsBrainCreationModalOpened, - setCurrentIntegrationBrain, + setCurrentSelectedBrain, } = useBrainCreationContext(); const defaultValues: CreateBrainProps = { @@ -33,7 +33,7 @@ export const AddBrainModal = (): JSX.Element => { }); useEffect(() => { - setCurrentIntegrationBrain(undefined); + setCurrentSelectedBrain(undefined); }, [isBrainCreationModalOpened]); return ( diff --git a/frontend/lib/components/AddBrainModal/brainCreation-provider.tsx b/frontend/lib/components/AddBrainModal/brainCreation-provider.tsx index c32e2e8c0..ca092f86e 100644 --- a/frontend/lib/components/AddBrainModal/brainCreation-provider.tsx +++ b/frontend/lib/components/AddBrainModal/brainCreation-provider.tsx @@ -7,8 +7,8 @@ interface BrainCreationContextProps { setIsBrainCreationModalOpened: React.Dispatch>; creating: boolean; setCreating: React.Dispatch>; - currentIntegrationBrain: IntegrationBrains | undefined; - setCurrentIntegrationBrain: React.Dispatch< + currentSelectedBrain: IntegrationBrains | undefined; + setCurrentSelectedBrain: React.Dispatch< React.SetStateAction >; } @@ -24,7 +24,7 @@ export const BrainCreationProvider = ({ }): JSX.Element => { const [isBrainCreationModalOpened, setIsBrainCreationModalOpened] = useState(false); - const [currentIntegrationBrain, setCurrentIntegrationBrain] = + const [currentSelectedBrain, setCurrentSelectedBrain] = useState(); const [creating, setCreating] = useState(false); @@ -35,8 +35,8 @@ export const BrainCreationProvider = ({ setIsBrainCreationModalOpened, creating, setCreating, - currentIntegrationBrain, - setCurrentIntegrationBrain, + currentSelectedBrain, + setCurrentSelectedBrain, }} > {children} diff --git a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainCatalogue/BrainCatalogue.module.scss b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainCatalogue/BrainCatalogue.module.scss new file mode 100644 index 000000000..8be97d3ab --- /dev/null +++ b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainCatalogue/BrainCatalogue.module.scss @@ -0,0 +1,60 @@ +@use "@/styles/Colors.module.scss"; +@use "@/styles/Radius.module.scss"; +@use "@/styles/ScreenSizes.module.scss"; +@use "@/styles/Spacings.module.scss"; +@use "@/styles/Typography.module.scss"; + +.cards_wrapper { + width: 100%; + height: 100%; + display: flex; + flex-direction: column; + gap: Spacings.$spacing05; + + .title { + @include Typography.H2; + } + + .brains_grid { + display: flex; + gap: Spacings.$spacing03; + flex-wrap: wrap; + + .brain_card_container { + display: flex; + flex-direction: column; + gap: Spacings.$spacing02; + + .tag_wrapper { + height: 2rem; + } + + .brain_card_wrapper { + display: flex; + flex-direction: column; + align-items: center; + border-radius: Radius.$normal; + gap: Spacings.$spacing03; + padding: Spacings.$spacing04; + width: fit-content; + cursor: pointer; + width: 120px; + + .brain_title { + font-size: Typography.$medium; + font-weight: 500; + } + + &:hover, + &.selected { + border-color: Colors.$primary; + background-color: Colors.$primary-lightest; + + .brain_title { + color: Colors.$primary; + } + } + } + } + } +} diff --git a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/CustomBrainList/CustomBrainList.tsx b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainCatalogue/BrainCatalogue.tsx similarity index 53% rename from frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/CustomBrainList/CustomBrainList.tsx rename to frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainCatalogue/BrainCatalogue.tsx index 7dc18f41b..54a87e625 100644 --- a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/CustomBrainList/CustomBrainList.tsx +++ b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainCatalogue/BrainCatalogue.tsx @@ -1,38 +1,49 @@ +import { capitalCase } from "change-case"; import Image from "next/image"; import { IntegrationBrains } from "@/lib/api/brain/types"; import { MessageInfoBox } from "@/lib/components/ui/MessageInfoBox/MessageInfoBox"; +import { Tag } from "@/lib/components/ui/Tag/Tag"; import Tooltip from "@/lib/components/ui/Tooltip/Tooltip"; -import styles from "./CustomBrainList.module.scss"; +import styles from "./BrainCatalogue.module.scss"; import { useBrainCreationContext } from "../../../brainCreation-provider"; -export const CustomBrainList = ({ - customBrainList, +export const BrainCatalogue = ({ + brains, + next, }: { - customBrainList: IntegrationBrains[]; + brains: IntegrationBrains[]; + next: () => void; }): JSX.Element => { - const { setCurrentIntegrationBrain, currentIntegrationBrain } = + const { setCurrentSelectedBrain, currentSelectedBrain } = useBrainCreationContext(); return (
- More custom brains are coming! + + A Brain is a specialized AI tool designed to interact with specific + use cases or data sources. + - Choose a custom brain -
- {customBrainList.map((brain) => { + Choose a brain type +
+ {brains.map((brain) => { return (
setCurrentIntegrationBrain(brain)} + className={styles.brain_card_container} + onClick={() => { + next(); + setCurrentSelectedBrain(brain); + }} >
{brain.integration_name} +
+ {brain.tags[0] && ( + + )} +
diff --git a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelection/BrainTypeSelection.module.scss b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelection/BrainTypeSelection.module.scss deleted file mode 100644 index 35b16ed5d..000000000 --- a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelection/BrainTypeSelection.module.scss +++ /dev/null @@ -1,48 +0,0 @@ -@use "@/styles/Colors.module.scss"; -@use "@/styles/Radius.module.scss"; -@use "@/styles/Spacings.module.scss"; -@use "@/styles/Typography.module.scss"; - -.brain_type_wrapper { - display: flex; - flex-direction: column; - gap: Spacings.$spacing05; - padding: Spacings.$spacing05; - border-radius: Radius.$big; - cursor: pointer; - border: 1px solid Colors.$lightest-black; - - &.disabled { - pointer-events: none; - background-color: Colors.$lightest-grey; - opacity: 0.6; - } - - .first_line_wrapper { - display: flex; - gap: Spacings.$spacing03; - align-items: center; - - .name { - @include Typography.H3; - } - } - - .description { - color: Colors.$dark-grey; - } - - &:hover, - &.selected { - border-color: Colors.$primary; - background-color: Colors.$primary-lightest; - - .name { - color: Colors.$primary; - } - - .description { - color: Colors.$black; - } - } -} diff --git a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelection/BrainTypeSelection.tsx b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelection/BrainTypeSelection.tsx deleted file mode 100644 index 2a85d8dfa..000000000 --- a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelection/BrainTypeSelection.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { useState } from "react"; - -import { BrainType } from "@/lib/components/AddBrainModal/types/types"; -import Icon from "@/lib/components/ui/Icon/Icon"; - -import styles from "./BrainTypeSelection.module.scss"; - -export const BrainTypeSelection = ({ - brainType, - onClick, - selected, -}: { - brainType: BrainType; - onClick: () => void; - selected: boolean; -}): JSX.Element => { - const [isHovered, setIsHovered] = useState(false); - - return ( -
setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} - onClick={onClick} - > -
- - {brainType.name} -
- {brainType.description} -
- ); -}; diff --git a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelectionStep.tsx b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelectionStep.tsx index cf2caee92..184149376 100644 --- a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelectionStep.tsx +++ b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/BrainTypeSelectionStep.tsx @@ -1,66 +1,34 @@ import { useEffect, useState } from "react"; +import { useFormContext } from "react-hook-form"; import { IntegrationBrains } from "@/lib/api/brain/types"; import { useBrainApi } from "@/lib/api/brain/useBrainApi"; -import { BrainType } from "@/lib/components/AddBrainModal/types/types"; -import QuivrButton from "@/lib/components/ui/QuivrButton/QuivrButton"; -import { BrainTypeSelection } from "./BrainTypeSelection/BrainTypeSelection"; +import { BrainCatalogue } from "./BrainCatalogue/BrainCatalogue"; import styles from "./BrainTypeSelectionStep.module.scss"; -import { CustomBrainList } from "./CustomBrainList/CustomBrainList"; -import { useBrainCreationContext } from "../../brainCreation-provider"; import { useBrainCreationSteps } from "../../hooks/useBrainCreationSteps"; +import { CreateBrainProps } from "../../types/types"; export const BrainTypeSelectionStep = (): JSX.Element => { - const [selectedIndex, setSelectedIndex] = useState(-1); - const [customBrainsCatalogueOpened, setCustomBrainsCatalogueOpened] = - useState(false); - const [customBrains, setCustomBrains] = useState([]); + const [brains, setBrains] = useState([]); const { goToNextStep, currentStepIndex } = useBrainCreationSteps(); const { getIntegrationBrains } = useBrainApi(); - const { currentIntegrationBrain } = useBrainCreationContext(); + const { setValue } = useFormContext(); useEffect(() => { getIntegrationBrains() .then((response) => { - setCustomBrains( - response.filter((brain) => brain.integration_type === "custom") - ); + setBrains(response); }) .catch((error) => { console.error(error); }); + + setValue("name", ""); + setValue("description", ""); }, []); - const brainTypes: BrainType[] = [ - { - name: "Core Brain", - description: "Upload documents or website links to feed your brain.", - iconName: "feed", - }, - { - name: "Custom Brain", - description: - "Explore your databases, converse with your APIs, and much more!", - iconName: "custom", - onClick: () => { - setCustomBrainsCatalogueOpened(true); - }, - }, - { - name: "Sync Brain - Coming soon!", - description: - "Connect to your tools and applications to interact with your data.", - iconName: "software", - disabled: true, - }, - ]; - - const next = (): void => { - goToNextStep(); - }; - if (currentStepIndex !== 0) { return <>; } @@ -68,54 +36,7 @@ export const BrainTypeSelectionStep = (): JSX.Element => { return (
- {customBrainsCatalogueOpened ? ( - - ) : ( - <> - Choose a type of brain - {brainTypes.map((brainType, index) => ( -
- { - setSelectedIndex(index); - if (brainType.onClick) { - brainType.onClick(); - } - }} - /> -
- ))} - - )} -
-
- {customBrainsCatalogueOpened && ( - { - setCustomBrainsCatalogueOpened(false); - setSelectedIndex(-1); - }} - /> - )} - next()} - disabled={ - selectedIndex === -1 || - (!!customBrainsCatalogueOpened && !currentIntegrationBrain) - } - /> +
); diff --git a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/CustomBrainList/CustomBrainList.module.scss b/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/CustomBrainList/CustomBrainList.module.scss deleted file mode 100644 index e5b697d43..000000000 --- a/frontend/lib/components/AddBrainModal/components/BrainTypeSelectionStep/CustomBrainList/CustomBrainList.module.scss +++ /dev/null @@ -1,44 +0,0 @@ -@use "@/styles/Colors.module.scss"; -@use "@/styles/Radius.module.scss"; -@use "@/styles/ScreenSizes.module.scss"; -@use "@/styles/Spacings.module.scss"; -@use "@/styles/Typography.module.scss"; - -.cards_wrapper { - width: 100%; - height: 100%; - display: flex; - flex-direction: column; - gap: Spacings.$spacing05; - - .title { - @include Typography.H2; - } - - .brain_card_wrapper { - display: flex; - flex-direction: column; - align-items: center; - border-radius: Radius.$normal; - gap: Spacings.$spacing03; - padding: Spacings.$spacing04; - border: 1px solid Colors.$lightest-black; - width: fit-content; - cursor: pointer; - width: 100px; - - .brain_title { - font-size: Typography.$small; - } - - &:hover, - &.selected { - border-color: Colors.$primary; - background-color: Colors.$primary-lightest; - - .brain_title { - color: Colors.$primary; - } - } - } -} diff --git a/frontend/lib/components/AddBrainModal/components/CreateBrainStep/CreateBrainStep.module.scss b/frontend/lib/components/AddBrainModal/components/CreateBrainStep/CreateBrainStep.module.scss index 27814da17..fdfc3ebe4 100644 --- a/frontend/lib/components/AddBrainModal/components/CreateBrainStep/CreateBrainStep.module.scss +++ b/frontend/lib/components/AddBrainModal/components/CreateBrainStep/CreateBrainStep.module.scss @@ -12,6 +12,12 @@ @include Typography.H2; } + .settings_wrapper { + display: flex; + flex-direction: column; + gap: Spacings.$spacing05; + } + .message_info_box_wrapper { align-self: center; display: flex; diff --git a/frontend/lib/components/AddBrainModal/components/CreateBrainStep/CreateBrainStep.tsx b/frontend/lib/components/AddBrainModal/components/CreateBrainStep/CreateBrainStep.tsx index a387d8730..ca3c1c9a3 100644 --- a/frontend/lib/components/AddBrainModal/components/CreateBrainStep/CreateBrainStep.tsx +++ b/frontend/lib/components/AddBrainModal/components/CreateBrainStep/CreateBrainStep.tsx @@ -1,6 +1,10 @@ +import { capitalCase } from "change-case"; +import { useEffect, useState } from "react"; + import { KnowledgeToFeed } from "@/app/chat/[chatId]/components/ActionsBar/components"; import { MessageInfoBox } from "@/lib/components/ui/MessageInfoBox/MessageInfoBox"; import QuivrButton from "@/lib/components/ui/QuivrButton/QuivrButton"; +import { TextInput } from "@/lib/components/ui/TextInput/TextInput"; import styles from "./CreateBrainStep.module.scss"; import { useBrainCreationApi } from "./hooks/useBrainCreationApi"; @@ -10,9 +14,29 @@ import { useBrainCreationSteps } from "../../hooks/useBrainCreationSteps"; export const CreateBrainStep = (): JSX.Element => { const { currentStepIndex, goToPreviousStep } = useBrainCreationSteps(); - const { createBrain } = useBrainCreationApi(); - const { creating, setCreating, currentIntegrationBrain } = + const { createBrain, fields, setFields } = useBrainCreationApi(); + const { creating, setCreating, currentSelectedBrain } = useBrainCreationContext(); + const [createBrainStepIndex, setCreateBrainStepIndex] = useState(0); + + useEffect(() => { + if (currentSelectedBrain?.connection_settings) { + const newFields = Object.entries( + currentSelectedBrain.connection_settings + ).map(([key, type]) => { + return { name: key, type, value: "" }; + }); + setFields(newFields); + } + + setCreateBrainStepIndex(Number(!currentSelectedBrain?.connection_settings)); + }, [currentSelectedBrain?.connection_settings]); + + const handleInputChange = (name: string, value: string) => { + setFields( + fields.map((field) => (field.name === name ? { ...field, value } : field)) + ); + }; const previous = (): void => { goToPreviousStep(); @@ -29,28 +53,48 @@ export const CreateBrainStep = (): JSX.Element => { return (
- {!currentIntegrationBrain ? ( + {!createBrainStepIndex && ( +
+ + {currentSelectedBrain?.information} + + {fields.map(({ name, value }) => ( + + handleInputChange(name, inputValue) + } + label={capitalCase(name)} + /> + ))} +
+ )} + {!!currentSelectedBrain?.max_files && !!createBrainStepIndex && (
Feed your brain
- ) : ( -
- -
- Click on - - to finish your brain creation. -
-
-
)} + {!currentSelectedBrain?.max_files && + !currentSelectedBrain?.connection_settings && ( +
+ +
+ Click on + + to finish your brain creation. +
+
+
+ )} +
{ iconName="chevronLeft" onClick={previous} /> - + {(!currentSelectedBrain?.max_files && !createBrainStepIndex) || + createBrainStepIndex ? ( + + ) : ( + setCreateBrainStepIndex(1)} + isLoading={creating} + /> + )}
); diff --git a/frontend/lib/components/AddBrainModal/components/CreateBrainStep/hooks/useBrainCreationApi.ts b/frontend/lib/components/AddBrainModal/components/CreateBrainStep/hooks/useBrainCreationApi.ts index e21e75e17..fb80a4c1c 100644 --- a/frontend/lib/components/AddBrainModal/components/CreateBrainStep/hooks/useBrainCreationApi.ts +++ b/frontend/lib/components/AddBrainModal/components/CreateBrainStep/hooks/useBrainCreationApi.ts @@ -1,5 +1,6 @@ import { useMutation, useQueryClient } from "@tanstack/react-query"; import { UUID } from "crypto"; +import { useState } from "react"; import { useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; @@ -24,11 +25,11 @@ export const useBrainCreationApi = () => { const { setKnowledgeToFeed } = useKnowledgeToFeedContext(); const { createBrain: createBrainApi, setCurrentBrainId } = useBrainContext(); const { crawlWebsiteHandler, uploadFileHandler } = useKnowledgeToFeedInput(); - const { - setIsBrainCreationModalOpened, - setCreating, - currentIntegrationBrain, - } = useBrainCreationContext(); + const { setIsBrainCreationModalOpened, setCreating, currentSelectedBrain } = + useBrainCreationContext(); + const [fields, setFields] = useState< + { name: string; type: string; value: string }[] + >([]); const handleFeedBrain = async (brainId: UUID): Promise => { const uploadPromises = files.map((file) => @@ -44,15 +45,19 @@ export const useBrainCreationApi = () => { const { name, description } = getValues(); let integrationSettings: IntegrationSettings | undefined = undefined; - if (currentIntegrationBrain) { + if (currentSelectedBrain) { integrationSettings = { - integration_id: currentIntegrationBrain.id, - settings: {}, + integration_id: currentSelectedBrain.id, + settings: fields.reduce((acc, field) => { + acc[field.name] = field.value; + + return acc; + }, {} as { [key: string]: string }), }; } const createdBrainId = await createBrainApi({ - brain_type: currentIntegrationBrain ? "integration" : "doc", + brain_type: currentSelectedBrain ? "integration" : "doc", name, description, integration: integrationSettings, @@ -98,5 +103,7 @@ export const useBrainCreationApi = () => { return { createBrain: mutate, isBrainCreationPending, + fields, + setFields, }; }; diff --git a/frontend/lib/components/AddBrainModal/hooks/useBrainCreationSteps.ts b/frontend/lib/components/AddBrainModal/hooks/useBrainCreationSteps.ts index a2b179b01..ee0b145d4 100644 --- a/frontend/lib/components/AddBrainModal/hooks/useBrainCreationSteps.ts +++ b/frontend/lib/components/AddBrainModal/hooks/useBrainCreationSteps.ts @@ -1,3 +1,4 @@ +import { useEffect } from "react"; import { useFormContext } from "react-hook-form"; import { useTranslation } from "react-i18next"; @@ -6,9 +7,12 @@ import { Step, } from "@/lib/components/AddBrainModal/types/types"; +import { useBrainCreationContext } from "../brainCreation-provider"; + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export const useBrainCreationSteps = () => { const { t } = useTranslation("brain"); + const { isBrainCreationModalOpened } = useBrainCreationContext(); const steps: Step[] = [ { @@ -30,6 +34,10 @@ export const useBrainCreationSteps = () => { (step) => step.value === currentStep ); + useEffect(() => { + goToFirstStep(); + }, [isBrainCreationModalOpened]); + const goToNextStep = () => { if (currentStepIndex === -1 || currentStepIndex === steps.length - 1) { return; @@ -48,6 +56,10 @@ export const useBrainCreationSteps = () => { return setValue("brainCreationStep", previousStep.value); }; + const goToFirstStep = () => { + return setValue("brainCreationStep", steps[0].value); + }; + return { currentStep, steps, diff --git a/frontend/lib/components/ui/Tag/Tag.module.scss b/frontend/lib/components/ui/Tag/Tag.module.scss new file mode 100644 index 000000000..052eeb9dc --- /dev/null +++ b/frontend/lib/components/ui/Tag/Tag.module.scss @@ -0,0 +1,20 @@ +@use "@/styles/Colors.module.scss"; +@use "@/styles/Radius.module.scss"; +@use "@/styles/Spacings.module.scss"; +@use "@/styles/Typography.module.scss"; + +.tag_wrapper { + padding: Spacings.$spacing01; + padding-inline: Spacings.$spacing03; + border-radius: Radius.$big; + width: fit-content; + font-size: Typography.$tiny; + + &.primary { + background-color: Colors.$primary-light; + } + + &.gold { + background-color: Colors.$gold; + } +} diff --git a/frontend/lib/components/ui/Tag/Tag.tsx b/frontend/lib/components/ui/Tag/Tag.tsx new file mode 100644 index 000000000..4d465042c --- /dev/null +++ b/frontend/lib/components/ui/Tag/Tag.tsx @@ -0,0 +1,16 @@ +import { Color } from "@/lib/types/Colors"; + +import styles from "./Tag.module.scss"; + +interface TagProps { + name: string; + color: Color; +} + +export const Tag = (props: TagProps): JSX.Element => { + return ( +
+ {props.name} +
+ ); +}; diff --git a/frontend/lib/context/BrainProvider/types.ts b/frontend/lib/context/BrainProvider/types.ts index 5e462c4f8..2b20a54af 100644 --- a/frontend/lib/context/BrainProvider/types.ts +++ b/frontend/lib/context/BrainProvider/types.ts @@ -18,6 +18,7 @@ export type IntegrationDescription = { integration_name: string; integration_type: "custom" | "sync"; max_files: number; + allow_model_change: boolean; }; export type Brain = { @@ -45,6 +46,7 @@ export type MinimalBrainForUser = { description: string; integration_logo_url?: string; max_files: number; + allow_model_change: boolean; }; //TODO: rename rights to role in Backend and use MinimalBrainForUser instead of BackendMinimalBrainForUser diff --git a/supabase/migrations/20240305225452_tags-integration.sql b/supabase/migrations/20240305225452_tags-integration.sql new file mode 100644 index 000000000..c30ef962a --- /dev/null +++ b/supabase/migrations/20240305225452_tags-integration.sql @@ -0,0 +1,7 @@ +create type "public"."brain_tags" as enum ('new', 'recommended', 'most_popular', 'premium', 'coming_soon', 'community', 'deprecated'); + +alter table "public"."integrations" add column "information" text; + +alter table "public"."integrations" add column "tags" brain_tags[]; + + diff --git a/supabase/migrations/20240306013910_allow_model_change.sql b/supabase/migrations/20240306013910_allow_model_change.sql new file mode 100644 index 000000000..21ef8afe0 --- /dev/null +++ b/supabase/migrations/20240306013910_allow_model_change.sql @@ -0,0 +1,3 @@ +alter table "public"."integrations" add column "allow_model_change" boolean not null default true; + +