diff --git a/apps/server/utils/configs/levanion_configs.py b/apps/server/utils/configs/levanion_configs.py
index 52cb44b51..ee7631acf 100644
--- a/apps/server/utils/configs/levanion_configs.py
+++ b/apps/server/utils/configs/levanion_configs.py
@@ -5,7 +5,7 @@
"agent": "Agent",
"team": "Team",
"datasource": "Data sources",
- "models": "Models",
+ "models": "Model",
"discovery": "Discovery",
"chat": "Multi-Agent",
"toolkits": "Toolkits",
diff --git a/apps/ui/src/components/ChatSwitcher/ChatSwitcher.tsx b/apps/ui/src/components/ChatSwitcher/ChatSwitcher.tsx
index 2ca658cc0..9a73d2ea1 100644
--- a/apps/ui/src/components/ChatSwitcher/ChatSwitcher.tsx
+++ b/apps/ui/src/components/ChatSwitcher/ChatSwitcher.tsx
@@ -197,6 +197,16 @@ const StyledRoot = styled.div<{ collapsed: boolean; theme: DefaultTheme }>`
background: rgba(255, 255, 255, 0.1);
}
`};
+
+ ::-webkit-scrollbar {
+ display: none;
+ }
+
+ /* Hide scrollbar for IE, Edge add Firefox */
+ {
+ -ms-overflow-style: none;
+ scrollbar-width: none; /* Firefox */
+ }
`
// const StyledRoot = styled.div<{ collapsed: boolean; theme: DefaultTheme }>`
// position: absolute;
diff --git a/apps/ui/src/components/ChatSwitcher/useChatSwitcher.ts b/apps/ui/src/components/ChatSwitcher/useChatSwitcher.ts
index ea2746463..c3502e5f4 100644
--- a/apps/ui/src/components/ChatSwitcher/useChatSwitcher.ts
+++ b/apps/ui/src/components/ChatSwitcher/useChatSwitcher.ts
@@ -10,7 +10,7 @@ export const useChatSwitcher = () => {
useEffect(() => {
const handleResize = () => {
// Check the window width and update the state accordingly
- setShowSwitcher(window.innerWidth >= 1000) // Adjust the breakpoint as needed
+ setShowSwitcher(window.innerWidth >= 900) // Adjust the breakpoint as needed
}
// Set the initial state on component mount
diff --git a/apps/ui/src/components/ImportFile/ImportFile.tsx b/apps/ui/src/components/ImportFile/ImportFile.tsx
index 5fc19ba05..719735bd9 100644
--- a/apps/ui/src/components/ImportFile/ImportFile.tsx
+++ b/apps/ui/src/components/ImportFile/ImportFile.tsx
@@ -1,32 +1,36 @@
import { useEffect } from 'react'
import styled from 'styled-components'
-import ReviewImport, { StyledButtonContainer } from './ReviewImport'
+import ImportFileTable from './ImportFileTable'
import useImportFile from './useImportFile'
import Button from '@l3-lib/ui-core/dist/Button'
+import Typography from '@l3-lib/ui-core/dist/Typography'
+import MenuButton from '@l3-lib/ui-core/dist/MenuButton'
+
import UploadButton from 'components/UploadButton'
-import { ButtonTertiary } from 'components/Button/Button'
+import { ButtonPrimary, ButtonTertiary } from 'components/Button/Button'
import { useDownloadTemplate } from './useDownloadTemplate'
import { t } from 'i18next'
+import TypographySecondary from 'components/Typography/Secondary'
+import { StyledMenuButtonsWrapper } from 'pages/Agents/AgentView/components/AgentViewDetailBox'
+
const ImportFile = ({ setFieldValue, value = '' }: { setFieldValue: any; value?: string }) => {
const {
- step,
parsedData,
- setStep,
- handleUploadJson,
+ setParsedData,
+ handleFileFormat,
handleConvertJson,
- handleUploadCsv,
handleConvertCSVtoJSON,
fileIsLoading,
} = useImportFile({
setFieldValue: setFieldValue,
})
- const { handleDownloadTemplate } = useDownloadTemplate()
+ const { handleDownloadTemplate, handleDownloadTemplateCSV } = useDownloadTemplate()
useEffect(() => {
if (value.length > 0) {
@@ -41,9 +45,11 @@ const ImportFile = ({ setFieldValue, value = '' }: { setFieldValue: any; value?:
})
.then(data => {
if (fileUrl.endsWith('.json')) {
- handleConvertJson(data)
+ const { data: convertedData } = handleConvertJson(data)
+ setParsedData(convertedData)
} else if (fileUrl.endsWith('.csv')) {
- handleConvertCSVtoJSON(data)
+ const { data: convertedData } = handleConvertCSVtoJSON(data)
+ setParsedData(convertedData)
}
})
.catch(error => {
@@ -52,39 +58,52 @@ const ImportFile = ({ setFieldValue, value = '' }: { setFieldValue: any; value?:
}
}, [value])
- function renderTabs(tabIndex: number) {
- switch (tabIndex) {
- case 0:
- return (
-
-
- {t('download-template')}
-
+ return (
+ <>
+
+
+ (
+
+ )}
+ closeDialogOnContentClick={false}
+ zIndex={2}
+ >
+
+
+ {t('download-json')}
+
+
+ {t('download-csv')}
+
+
+
-
+ {parsedData?.length === 0 && (
-
- )
-
- case 1:
- return (
- <>
-
- >
- )
-
- default:
- return <>Error..!>
- }
- }
-
- return (
- <>
- {renderTabs(step)}
+ )}
+ {parsedData?.length > 0 && (
+ {
+ setParsedData([])
+ setFieldValue('fine_tuning_file_url', '')
+ }}
+ size={Button.sizes.SMALL}
+ >
+ {t('start-over')}
+
+ )}
+
+ {parsedData?.length > 0 && }
+
>
)
}
@@ -94,4 +113,18 @@ export default ImportFile
export const StyledFormSection = styled.div<{ columns?: string }>`
width: 100%;
height: 100%;
+ overflow: auto;
+
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+`
+
+const StyledButtonContainer = styled.div`
+ display: flex;
+ align-items: center;
+ gap: 5px;
+`
+const StyledMenuButton = styled(MenuButton)`
+ width: 140px;
`
diff --git a/apps/ui/src/components/ImportFile/ImportFileTable.tsx b/apps/ui/src/components/ImportFile/ImportFileTable.tsx
new file mode 100644
index 000000000..0511930f1
--- /dev/null
+++ b/apps/ui/src/components/ImportFile/ImportFileTable.tsx
@@ -0,0 +1,57 @@
+import React from 'react'
+
+import styled from 'styled-components'
+
+import Table from 'components/Table'
+
+const ImportFileTable = ({ data }: { data: any[] }) => {
+ const columns = [
+ {
+ Header: 'System',
+ accessor: 'System',
+ minWidth: 75,
+ },
+ {
+ Header: 'User',
+ accessor: 'User',
+ minWidth: 75,
+ },
+ {
+ Header: 'Assistant',
+ accessor: 'Assistant',
+ minWidth: 75,
+ },
+ ]
+ const renderTable = React.useMemo(
+ () => (
+ <>
+
+ >
+ ),
+ [data],
+ )
+
+ return (
+ <>
+
+ {renderTable}
+
+ >
+ )
+}
+
+export default ImportFileTable
+
+const StyledTableWrapper = styled.div`
+ height: 100%;
+ width: 100%;
+`
+
+const StyledContentWrapper = styled.div`
+ width: 100%;
+ overflow: auto;
+
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+`
diff --git a/apps/ui/src/components/ImportFile/ReviewImport.tsx b/apps/ui/src/components/ImportFile/ReviewImport.tsx
deleted file mode 100644
index f053d2acc..000000000
--- a/apps/ui/src/components/ImportFile/ReviewImport.tsx
+++ /dev/null
@@ -1,142 +0,0 @@
-import React from 'react'
-// import { CustomTable } from 'oldComponents/atoms/CustomTable'
-import useReviewImport from './useReviewImport'
-import { FormikProvider } from 'formik'
-import Dropdown from '@l3-lib/ui-core/dist/Dropdown'
-
-import styled from 'styled-components'
-
-import Button from '@l3-lib/ui-core/dist/Button'
-
-import Table from 'components/Table'
-import { ButtonPrimary, ButtonTertiary } from 'components/Button/Button'
-import { t } from 'i18next'
-import { useDownloadTemplate } from './useDownloadTemplate'
-
-const ReviewImport = ({ data, setStep: startOver }: { data: any[]; setStep: any }) => {
- const { handleDownloadTemplate } = useDownloadTemplate()
-
- const { formik, step, response, setStep } = useReviewImport(data)
-
- const columns = [
- {
- Header: 'System',
- accessor: 'System',
- minWidth: 75,
- },
- {
- Header: 'User',
- accessor: 'User',
- minWidth: 75,
- },
- {
- Header: 'Assistant',
- accessor: 'Assistant',
- minWidth: 75,
- },
- ]
- const renderTable = React.useMemo(
- () => (
- <>
-
- >
- ),
- [data],
- )
-
- return (
- <>
- {!response ? (
- <>
-
-
-
-
- {t('download-template')}
-
- {/*
- Save
- */}
- startOver(0)} size={Button.sizes.SMALL}>
- {t('start-over')}
-
-
- {/*
- {keys.map((item: any, index: number) => (
-
- ))}
- */}
- {renderTable}
-
-
- >
- ) : (
- <>
-
-
-
-
-
-
-
- Total imported: {response.total_imported}
- Total not imported: {response?.not_imported.length}
-
-
-
- {/* */}
-
-
- >
- )}
- >
- )
-}
-
-export default ReviewImport
-
-const StyledTableWrapper = styled.div`
- height: 100%;
- width: 100%;
-`
-
-const StyledHeaderWrapper = styled.div`
- width: 100%;
- position: sticky;
- padding: 20px 0;
- top: -20px;
-`
-const StyledHeaderContainer = styled.div<{ itemLength?: number }>`
- display: grid;
- grid-auto-flow: column;
- align-items: center;
- grid-template-columns: ${p => p.itemLength && `repeat(${p.itemLength}, 150px)`};
- grid-column-gap: 16px;
- width: 100%;
- margin-right: 50px;
-
- background: red;
-`
-const StyledContentWrapper = styled.div`
- width: 100%;
- overflow: auto;
-
- display: flex;
- flex-direction: column;
- gap: 10px;
-`
-
-export const StyledButtonContainer = styled.div`
- display: flex;
- align-items: center;
- gap: 5px;
-`
diff --git a/apps/ui/src/components/ImportFile/useDownloadTemplate.ts b/apps/ui/src/components/ImportFile/useDownloadTemplate.ts
index 38e90565a..9204883ed 100644
--- a/apps/ui/src/components/ImportFile/useDownloadTemplate.ts
+++ b/apps/ui/src/components/ImportFile/useDownloadTemplate.ts
@@ -25,5 +25,31 @@ export const useDownloadTemplate = () => {
document.body.removeChild(a)
}
- return { handleDownloadTemplate }
+ const handleDownloadTemplateCSV = () => {
+ const csvRows = []
+
+ // Headers
+ const headers = Object.keys(templateData[0])
+ csvRows.push(headers.join(','))
+
+ // Values
+ templateData.forEach((row: any) => {
+ const values = headers.map(header => {
+ return `"${row[header] || ''}"`
+ })
+ csvRows.push(values.join(','))
+ })
+
+ // Join rows
+ const csvContent = csvRows.join('\n')
+ const encodedUri = encodeURI(`data:text/csv;charset=utf-8,${csvContent}`)
+
+ const link = document.createElement('a')
+ link.setAttribute('href', encodedUri)
+ link.setAttribute('download', 'templateData.csv')
+ document.body.appendChild(link) // Required for Firefox
+ link.click()
+ }
+
+ return { handleDownloadTemplate, handleDownloadTemplateCSV }
}
diff --git a/apps/ui/src/components/ImportFile/useImportFile.ts b/apps/ui/src/components/ImportFile/useImportFile.ts
index dabd9d298..e3640a68b 100644
--- a/apps/ui/src/components/ImportFile/useImportFile.ts
+++ b/apps/ui/src/components/ImportFile/useImportFile.ts
@@ -6,12 +6,45 @@ import Papa from 'papaparse'
const useImportFile = ({ setFieldValue }: { setFieldValue: any }) => {
const { setToast } = useContext(ToastContext)
- const [step, setStep] = React.useState(0)
const [fileIsLoading, setFileIsLoading] = React.useState(false)
const [parsedData, setParsedData] = React.useState([])
const { uploadFile } = useUploadFile()
+ const validateJSON = (content: any) => {
+ const data = JSON.parse(content)
+
+ if (
+ Array.isArray(data) &&
+ data.every(
+ obj =>
+ typeof obj === 'object' &&
+ 'System' in obj &&
+ 'User' in obj &&
+ 'Assistant' in obj &&
+ Object.keys(obj).length === 3,
+ )
+ ) {
+ return true
+ } else {
+ return false
+ }
+ }
+
+ const validateCSV = (content: any) => {
+ const lines = content.split('\n')
+ const headers = lines[0].split(',').map((header: any) => header.trim())
+
+ if (
+ headers.length === 3 &&
+ headers.every((header: any) => ['System', 'User', 'Assistant'].includes(header))
+ ) {
+ return true
+ } else {
+ return false
+ }
+ }
+
const handleConvertJson = (data: any) => {
const dataArray = JSON.parse(data)
const convertedData = dataArray.map((item: any) => ({
@@ -19,8 +52,8 @@ const useImportFile = ({ setFieldValue }: { setFieldValue: any }) => {
User: item.User,
Assistant: item.Assistant,
}))
- setParsedData(convertedData)
- setStep(1)
+
+ return { data: convertedData }
}
const handleConvertCSVtoJSON = (csvString: string) => {
@@ -29,11 +62,11 @@ const useImportFile = ({ setFieldValue }: { setFieldValue: any }) => {
skipEmptyLines: true, // Skip empty lines in CSV
})
- setParsedData(data)
- setStep(1)
+ return { data }
}
- const handleUploadFile = async (files: any) => {
+ const handleUploadFile = async (files: any, data: any) => {
+ setFileIsLoading(true)
const promises = []
for (const file of files) {
@@ -52,60 +85,60 @@ const useImportFile = ({ setFieldValue }: { setFieldValue: any }) => {
const uploadedFiles = await Promise.all(promises)
setFieldValue('fine_tuning_file_url', uploadedFiles?.[0].url)
- }
+ setFileIsLoading(false)
- const handleUploadJson = async (event: any) => {
- const { files } = event.target
- const file = files[0]
-
- if (file.type !== 'application/json')
- return setToast({
- message: 'File must be JSON!',
- type: 'negative',
- open: true,
- })
-
- handleUploadFile(files)
-
- const reader = new FileReader()
-
- reader.onload = (event: any) => {
- const data = event.target.result
-
- handleConvertJson(data)
- }
- reader.readAsText(file)
+ setParsedData(data)
}
- const handleUploadCsv = async (event: any) => {
+ const handleFileFormat = async (event: any) => {
const { files } = event.target
const file = files[0]
- if (file.type !== 'text/csv')
+ if (file.type !== 'text/csv' && file.type !== 'application/json')
return setToast({
- message: 'File must be CSV!',
+ message: 'File must be CSV or JSON format!',
type: 'negative',
open: true,
})
- handleUploadFile(files)
-
const reader = new FileReader()
-
- reader.onload = (event: any) => {
- const csvString = event.target.result
- handleConvertCSVtoJSON(csvString)
+ reader.onload = async (event: any) => {
+ const fileData = event.target.result
+
+ if (file.type === 'text/csv') {
+ const isValid = validateCSV(fileData)
+ if (isValid) {
+ const { data } = handleConvertCSVtoJSON(fileData)
+ await handleUploadFile(files, data)
+ } else {
+ return setToast({
+ message: 'Data Fields are incorrect!',
+ type: 'negative',
+ open: true,
+ })
+ }
+ } else if (file.type === 'application/json') {
+ const isValid = validateJSON(fileData)
+ if (isValid) {
+ const { data } = handleConvertJson(fileData)
+ await handleUploadFile(files, data)
+ } else {
+ return setToast({
+ message: 'Data Fields are incorrect!',
+ type: 'negative',
+ open: true,
+ })
+ }
+ }
}
reader.readAsText(file)
}
return {
- handleUploadCsv,
- handleUploadJson,
- step,
+ handleFileFormat,
parsedData,
- setStep,
+ setParsedData,
handleConvertJson,
handleConvertCSVtoJSON,
fileIsLoading,
diff --git a/apps/ui/src/components/ImportFile/useReviewImport.ts b/apps/ui/src/components/ImportFile/useReviewImport.ts
deleted file mode 100644
index 817f7d666..000000000
--- a/apps/ui/src/components/ImportFile/useReviewImport.ts
+++ /dev/null
@@ -1,191 +0,0 @@
-import React from 'react'
-import { useFormik } from 'formik'
-import * as yup from 'yup'
-import { useGetDownloadUrl } from 'services'
-
-import useSnackbarAlert from 'hooks/useSnackbar'
-
-import { useTranslation } from 'react-i18next'
-
-const field_names = [
- { label: 'System', value: 'system' },
- { label: 'User', value: 'user' },
- { label: 'Assistant', value: 'assistant' },
-]
-
-const csv_keys = ['System', 'User', 'Assistant']
-
-const generateValidationSchema = (keys: string[]) => {
- const obj: any = {}
- // eslint-disable-next-line array-callback-return
- keys.map(item => {
- obj[item] = yup.string().required(`Required!`)
- })
-
- return yup.object().shape({
- ...obj,
- })
-}
-
-const useReviewImport = (data: any) => {
- const { t } = useTranslation()
- const { setSnackbar } = useSnackbarAlert()
-
- const [keys, setKeys] = React.useState([])
- const [custom_field_keys, setCustomFieldKeys] = React.useState([])
- const [validationSchema, setValidationSchema] = React.useState(null)
- const [step, setStep] = React.useState(0)
- const [response, setResponse] = React.useState(null)
- const [file_options, setFileOptions] = React.useState([])
-
- const { data: template } = useGetDownloadUrl('template/Template_asset.csv')
-
- // console.log('template:;', template)
-
- const formik = useFormik({
- initialValues: {},
- // validationSchema: validationSchema,
- enableReinitialize: true,
- onSubmit: values => handleSubmit(values),
- })
-
- React.useEffect(() => {
- if (data && data.length) {
- const object: any = {}
- let keys_from_csv: string[] = []
- let custom_keys: any = []
- let f_options: any = []
-
- // eslint-disable-next-line array-callback-return
- Object.keys(data[0]).map((key, index) => {
- if (key === csv_keys[index]) {
- object[field_names[index].value] = field_names[index].value
- keys_from_csv = [...keys_from_csv, field_names[index].value]
- f_options = [...f_options, { key: field_names[index].value, label: key }]
- } else {
- keys_from_csv = [...keys_from_csv, key.toLowerCase().replaceAll(' ', '_')]
- object[key.toLowerCase().replaceAll(' ', '_')] = ''
- custom_keys = [
- ...custom_keys,
- {
- label: key,
- value: key.toLowerCase().replaceAll(' ', '_'),
- },
- ]
-
- f_options = [
- ...f_options,
- { key: key.toLowerCase().replaceAll(' ', '_'), label: key, is_custom_field: true },
- ]
- }
- })
-
- const validationSchema = generateValidationSchema(keys_from_csv)
-
- formik.setValues(object)
- setKeys(keys_from_csv)
- setCustomFieldKeys(custom_keys)
- setValidationSchema(validationSchema)
- setFileOptions(f_options)
- }
- }, [data])
-
- const handleSubmit = async function (values: any) {
- try {
- const new_array = data.map((item: any) => {
- const obj: any = { custom_props: [] }
-
- // eslint-disable-next-line array-callback-return
- keys.map((key: any) => {
- const option: any = field_names.find(i => i.value === key)
-
- obj[key] = option?.label ? item[option.label] : null
-
- // if (key === 'price') {
- // obj.price = parseFloat(item[option.label])
- // }
-
- // if (key === 'token_id') {
- // obj.token_id = parseInt(item[option.label])
- // }
-
- // if (key === 'properties' && item[option.label]) {
- // obj.properties = item[option.label].split(',')
- // }
-
- // if (key === 'number_of_copies') {
- // obj.supply = parseInt(item[option.label])
- // delete obj.number_of_copies
- // }
- })
-
- // for (const key in values) {
- // if (values[key] === 'custom_field') {
- // const cf = custom_field_keys.find((i: any) => i.value === key)
- // obj.custom_props = [...obj.custom_props, { [key]: item[cf.label] }]
- // }
-
- // if (values[key] === 'custom_field' || values[key] === 'no_import') {
- // delete obj[key]
- // }
- // }
-
- return obj
- })
- // if (!collection) return
- // const gameId = collection?.game_id || ''
- // const collectionId = collection?.id || ''
- // const result = await insertAssetsService(
- // { input: new_array, file_options },
- // gameId,
- // collectionId,
- // )
-
- // if (result.success) {
- // setSnackbar({
- // message: t('import-was-successfully'),
- // variant: 'success',
- // })
- // setResponse(result)
- // }
- } catch (error) {
- setSnackbar({ message: t('failed-to-import'), variant: 'error' })
- }
- }
-
- // const { config } = columnConfig({ keys: Object.keys(data[0]) })
-
- const options = field_names.map(i => ({
- ...i,
- ...(Object.values(formik.values)
- .filter(n => n !== 'custom_field' && n !== 'no_import')
- .includes(i.value)
- ? { isDisabled: true }
- : {}),
- }))
-
- React.useEffect(() => {
- if (!formik.isSubmitting) return
- if (Object.keys(formik.errors).length > 0) {
- setSnackbar({ message: t('please-fill-out-required-fields!'), variant: 'error' })
- // const error = document.getElementsByName(Object.keys(formik.errors)[0])[0]
- // if (error) {
- // error.scrollIntoView()
- // console.log(error)
- // }
- }
- }, [formik])
-
- return {
- // columnConfig: config,
- formik,
- keys,
- options: options,
- csv_keys,
- step,
- response,
- setStep,
- }
-}
-
-export default useReviewImport
diff --git a/apps/ui/src/i18n/locales/en.json b/apps/ui/src/i18n/locales/en.json
index be37abf5c..106352541 100644
--- a/apps/ui/src/i18n/locales/en.json
+++ b/apps/ui/src/i18n/locales/en.json
@@ -14,6 +14,8 @@
"add-agent": "Add $t(agent)",
"add-team": "Add $t(team)",
"add-datasource": "Add $t(datasource)",
+ "add-contact": "Add $t(contact)",
+ "add-group": "Add $t(group)",
"add-member": "Add member",
"add-fine-tuning": "Add Fine-Tuning",
"advanced-options": "Advanced Options",
@@ -54,6 +56,7 @@
"brand": "Brand",
"beta": "Beta",
"cancel": "Cancel",
+ "contact": "Contact",
"cannot-update-password": "Cannot update password",
"chargers": "Chargers",
"chat": "Chat",
@@ -112,6 +115,8 @@
"done": "Done",
"dont-have-account": "Don't have an account?",
"download-template": "Download Template",
+ "download-json": "JSON",
+ "download-csv": "CSV",
"edit-agent": "Edit $t(agent)",
"edit-api-keys": "Edit API keys",
"edit-team": "Edit $t(team)",
@@ -144,6 +149,7 @@
"game-successfully-deleted": "Game successfully deleted",
"game-delete-failed": "Game delete failed",
"github": "Github",
+ "group": "Group",
"goals": "Goal",
"goal": "1 Goal",
"greeting": "Greeting",
@@ -287,6 +293,7 @@
"update": "Update",
"upload-csv": "Upload CSV",
"upload-json": "Upload JSON",
+ "upload-file": "Upload file",
"update-password": "Update password",
"user-successfully-deleted": "User successfully deleted",
"user-delete-failed": "User delete failed",
diff --git a/apps/ui/src/modals/AIChatModal/components/ChatMembers/ChatMembers.tsx b/apps/ui/src/modals/AIChatModal/components/ChatMembers/ChatMembers.tsx
index d181c60b9..a79a9f1b1 100644
--- a/apps/ui/src/modals/AIChatModal/components/ChatMembers/ChatMembers.tsx
+++ b/apps/ui/src/modals/AIChatModal/components/ChatMembers/ChatMembers.tsx
@@ -22,6 +22,7 @@ import {
StyledEditIcon,
StyledEyeOpenIcon,
} from 'pages/TeamOfAgents/TeamOfAgentsCard/TeamOfAgentsCard'
+import { StyledTabListSpan, StyledTabListWrapper } from 'styles/tabStyles.css'
const ChatMembers = ({
agentById,
@@ -50,16 +51,16 @@ const ChatMembers = ({
return (
-
+
setActiveTab(0)}>
- {t('info')}
+ {t('info')}
setActiveTab(1)}>
- {t('members')}
+ {t('members')}
-
+
@@ -128,16 +129,16 @@ const ChatMembers = ({
if (teamOfAgents) {
return (
-
+
setActiveTab(0)}>
- {t('info')}
+ {t('info')}
setActiveTab(1)}>
- {t('members')}
+ {t('members')}
-
+
@@ -260,10 +261,3 @@ const StyledIconButtonWrapper = styled.div`
display: flex;
align-items: center;
`
-const StyledDiv = styled.div`
- border: ${({ theme }) => theme.body.secondaryBorder};
- border-radius: 20px;
-`
-const StyledSpan = styled.span`
- color: ${({ theme }) => theme.body.textColorPrimary};
-`
diff --git a/apps/ui/src/pages/Agents/AgentView/components/AgentViewDetailBox.tsx b/apps/ui/src/pages/Agents/AgentView/components/AgentViewDetailBox.tsx
index 1fa52a0db..e85efee2e 100644
--- a/apps/ui/src/pages/Agents/AgentView/components/AgentViewDetailBox.tsx
+++ b/apps/ui/src/pages/Agents/AgentView/components/AgentViewDetailBox.tsx
@@ -25,6 +25,7 @@ import MenuButton from '@l3-lib/ui-core/dist/MenuButton'
import MenuDots from '@l3-lib/ui-core/dist/icons/MenuDots'
import { useAgents } from 'pages/Agents/useAgents'
import { useGetAccountModule } from 'utils/useGetAccountModule'
+import { useModelsService } from 'services'
type AgentViewDetailBoxProps = {
agentData: any
@@ -42,15 +43,23 @@ const AgentVIewDetailBox = ({ agentData }: AgentViewDetailBoxProps) => {
const { deleteAgentHandler } = useAgents()
const navigate = useNavigate()
+
const { closeModal, openModal } = useModal()
+ const { data: models } = useModelsService()
+
const { agent, configs } = agentData
+
const { name, description, role, creator, is_template } = agent
- const { model_version, model_provider, temperature } = configs
+ const { model, temperature } = configs
const isCreator = user?.id === agent?.created_by
+ const agentModel = models
+ ?.filter((modelData: any) => modelData.id === model)
+ .map((model: any) => model.name)
+
const handleEdit = () => {
closeModal('agent-view-modal')
navigate(`/agents/${agent?.id}/edit-agent`)
@@ -65,7 +74,7 @@ const AgentVIewDetailBox = ({ agentData }: AgentViewDetailBoxProps) => {
openModal({ name: 'schedule-run-modal', data: { id: chatId || agent.id, type: 'agent' } })
}
-
+ console.log(model)
return (
@@ -147,9 +156,7 @@ const AgentVIewDetailBox = ({ agentData }: AgentViewDetailBoxProps) => {
{role && }
- {model_provider && }
-
- {model_version && }
+ {agentModel?.length > 0 && }
{temperature && }
@@ -209,7 +216,7 @@ export const StyledMenuButtonsWrapper = styled.div`
backdrop-filter: blur(100px);
padding: 10px;
border-radius: 10px;
- width: 200px;
+
min-width: fit-content;
display: flex;
diff --git a/apps/ui/src/pages/Agents/Agents.tsx b/apps/ui/src/pages/Agents/Agents.tsx
index 75313e374..bf33fcb58 100644
--- a/apps/ui/src/pages/Agents/Agents.tsx
+++ b/apps/ui/src/pages/Agents/Agents.tsx
@@ -100,12 +100,12 @@ export const StyledCardsWrapper = styled.div`
flex-wrap: wrap;
gap: 16px;
- max-width: 1055px;
+ /* max-width: 1055px; */
width: 100%;
max-height: calc(100vh - 325px);
height: 100%;
overflow-y: auto;
- padding: 5px;
+ padding: 5px 35px;
`
const StyledMainHeaderWrapper = styled.div`
display: flex;
diff --git a/apps/ui/src/pages/Models/FineTuning/FineTunings.tsx b/apps/ui/src/pages/Models/FineTuning/FineTunings.tsx
index 4f6a11a03..f0a46bf67 100644
--- a/apps/ui/src/pages/Models/FineTuning/FineTunings.tsx
+++ b/apps/ui/src/pages/Models/FineTuning/FineTunings.tsx
@@ -5,7 +5,6 @@ import ComponentsWrapper from 'components/ComponentsWrapper/ComponentsWrapper'
import { useTranslation } from 'react-i18next'
import {
StyledHeaderGroup,
- StyledSectionDescription,
StyledSectionTitle,
StyledSectionWrapper,
} from 'pages/Home/homeStyle.css'
@@ -17,7 +16,6 @@ import IconButton from '@l3-lib/ui-core/dist/IconButton'
import { useNavigate } from 'react-router-dom'
-import { StyledCardsWrapper } from 'pages/Agents/Agents'
import { useFineTuning } from './useFineTuning'
import { useFineTuningForm } from './FineTuningForm/useFineTuningForm'
@@ -26,6 +24,7 @@ import {
StyledDeleteIcon,
StyledEditIcon,
} from 'pages/TeamOfAgents/TeamOfAgentsCard/TeamOfAgentsCard'
+import { StyledTableWrapper } from 'plugins/contact/pages/Contact/Contacts'
const FineTunings = () => {
const { t } = useTranslation()
@@ -44,21 +43,23 @@ const FineTunings = () => {
{
Header: 'Name',
accessor: 'name',
+ width: 500,
},
{
Header: 'Model',
accessor: 'model',
+ width: 370,
},
{
Header: 'Status',
accessor: 'status',
- width: 250,
+ width: 100,
},
{
Header: 'Actions',
accessor: 'id',
- width: 250,
+ width: 100,
Cell: ({ cell }: any) => {
return (
@@ -90,8 +91,10 @@ const FineTunings = () => {
id: fineTuning.id,
name: fineTuning.name,
status: fineTuning.status,
- model: modelOptions?.filter((model: any) => model.value === fineTuning?.model_id).length > 0 ?
- modelOptions?.filter((model: any) => model.value === fineTuning?.model_id)?.[0].label: '',
+ model:
+ modelOptions?.filter((model: any) => model.value === fineTuning?.model_id).length > 0
+ ? modelOptions?.filter((model: any) => model.value === fineTuning?.model_id)?.[0].label
+ : '',
})) || []
return (
@@ -107,9 +110,9 @@ const FineTunings = () => {
-
+
-
+
)
diff --git a/apps/ui/src/pages/Models/Models.tsx b/apps/ui/src/pages/Models/Models.tsx
index 78269a116..ef7a31c2f 100644
--- a/apps/ui/src/pages/Models/Models.tsx
+++ b/apps/ui/src/pages/Models/Models.tsx
@@ -15,48 +15,78 @@ import { StyledCardsWrapper } from 'pages/Agents/Agents'
import FineTunings from './FineTuning/FineTunings'
-import { StyledRoot } from 'pages/Discover/Discover'
+import Tab from '@l3-lib/ui-core/dist/Tab'
+import TabList from '@l3-lib/ui-core/dist/TabList'
+import TabPanel from '@l3-lib/ui-core/dist/TabPanel'
+import TabPanels from '@l3-lib/ui-core/dist/TabPanels'
+import TabsContext from '@l3-lib/ui-core/dist/TabsContext'
+
+import { useState } from 'react'
+import { StyledTabListSpan, StyledTabListWrapper, StyledTabRootWrapper } from 'styles/tabStyles.css'
const Models = ({ isPublic }: { isPublic?: boolean }) => {
const { t } = useTranslation()
+ const [activeTab, setActiveTab] = useState(0)
+
const { data: models } = useModelsService()
return (
-
-
-
-
-
-
- {`${t('model')}`}
- {t('model-description')}
-
-
-
-
-
- {models
- ?.filter(model => !model.is_fine_tuned)
- ?.map((model, index: number) => {
- const logo = MODEL_PROVIDER_LOGOS.find(logo => logo.provider === model.provider)
- const logoSrc = logo?.logoSrc || ''
-
- return (
-
- )
- })}
-
-
-
-
+
+
+
+ setActiveTab(0)}>
+ {t('fine-tuning')}
+
+ setActiveTab(1)}>
+ {`${t('model')}s`}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {`${t('model')}s`}
+ {t('model-description')}
+
+
+
+
+
+ {models
+ ?.filter(model => !model.is_fine_tuned)
+ ?.map((model, index: number) => {
+ const logo = MODEL_PROVIDER_LOGOS.find(
+ logo => logo.provider === model.provider,
+ )
+ const logoSrc = logo?.logoSrc || ''
+
+ return (
+
+ )
+ })}
+
+
+
+
+
+
+
)
}
diff --git a/apps/ui/src/pages/Navigation/MainNavigation.tsx b/apps/ui/src/pages/Navigation/MainNavigation.tsx
index 4498bfb2c..47ff0b10f 100644
--- a/apps/ui/src/pages/Navigation/MainNavigation.tsx
+++ b/apps/ui/src/pages/Navigation/MainNavigation.tsx
@@ -100,7 +100,6 @@ const MainNavigation = () => {
Agents
*/}
-
{isContact && (
{
>
)}
- {isGroup && (
+ {/* {isGroup && (
onHandleClick('/groups')}>
- )}
+ )} */}
{isDatasource && (
{
onHandleClick('/models')}>
@@ -179,7 +178,6 @@ const MainNavigation = () => {
)}
-
{isDiscover && (
{
const navigate = useNavigate()
@@ -58,10 +66,12 @@ const Contacts = () => {
{
Header: 'Name',
accessor: 'name',
+ width: 225,
},
{
Header: 'Phone',
accessor: 'phone',
+ width: 200,
Cell: ({ cell }: any) => {
return (
@@ -109,11 +119,12 @@ const Contacts = () => {
{
Header: 'Email',
accessor: 'email',
+ width: 200,
},
{
Header: 'Group',
accessor: 'group_id',
-
+ width: 100,
Cell: ({ cell }: any) => {
return (
@@ -127,11 +138,12 @@ const Contacts = () => {
{
Header: 'Description',
accessor: 'description',
+ width: 250,
},
{
Header: 'Actions',
accessor: 'id',
- maxWidth: 100,
+ width: 100,
Cell: ({ cell }: any) => {
return (
@@ -158,28 +170,53 @@ const Contacts = () => {
[],
)
+ const [activeTab, setActiveTab] = useState(0)
+
return (
-
-
-
- Contacts
- {/*
- Here is your datasource, a collection of databases, APIs, files, and more.
- */}
-
-
- navigate('/contacts/create-contact')} size={'small'}>
- Add Contact
-
-
-
-
-
-
-
-
-
-
+
+
+
+ setActiveTab(0)}>
+ {`${t('contact')}s`}
+
+ setActiveTab(1)}>
+ {`${t('group')}s`}
+
+
+
+
+
+
+
+
+
+
+ {`${t('contact')}s`}
+
+
+ navigate('/contacts/create-contact')}
+ size={'small'}
+ >
+ {t('add-contact')}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
)
}
@@ -223,4 +260,6 @@ export const StyledTableWrapper = styled.div`
width: 100%;
height: 100%;
padding: 0 15px;
+ overflow: auto;
+ max-height: calc(100vh - 325px);
`
diff --git a/apps/ui/src/plugins/contact/pages/Group/Groups.tsx b/apps/ui/src/plugins/contact/pages/Group/Groups.tsx
index 6bcc5a0a4..92337825d 100644
--- a/apps/ui/src/plugins/contact/pages/Group/Groups.tsx
+++ b/apps/ui/src/plugins/contact/pages/Group/Groups.tsx
@@ -21,6 +21,7 @@ import {
import styled from 'styled-components'
import Table from 'components/Table'
import { StyledTableWrapper } from '../Contact/Contacts'
+import { t } from 'i18next'
const Groups = () => {
const { groups, deleteGroupHandler } = useGroups()
@@ -39,17 +40,17 @@ const Groups = () => {
{
Header: 'Name',
accessor: 'name',
- width: 400,
+ width: 485,
},
{
Header: 'Description',
accessor: 'description',
- width: 400,
+ width: 485,
},
{
Header: 'Actions',
accessor: 'id',
- width: 300,
+ width: 100,
Cell: ({ cell }: any) => {
return (
@@ -80,14 +81,14 @@ const Groups = () => {
- Groups
+ {`${t('group')}s`}
{/*
Here is your datasource, a collection of databases, APIs, files, and more.
*/}
navigate('/groups/create-group')} size={'small'}>
- Add Group
+ {t('add-group')}
@@ -106,4 +107,5 @@ export default Groups
export const StyledTableButtons = styled.div`
display: flex;
align-items: center;
+ height: 100%;
`
diff --git a/apps/ui/src/routes/ChatRouteLayout.tsx b/apps/ui/src/routes/ChatRouteLayout.tsx
index 4f39520f2..97413e89f 100644
--- a/apps/ui/src/routes/ChatRouteLayout.tsx
+++ b/apps/ui/src/routes/ChatRouteLayout.tsx
@@ -42,6 +42,8 @@ const ChatRouteLayout = () => {
const [showChats, setShowChats] = useState(true)
const [showInfo, setShowInfo] = useState(false)
+ const [isSmallScreen, setIsSmallScreen] = useState(false)
+
const outlet = useOutlet()
const { agentsData, deleteAgentHandler, agentsLoading } = useAgents()
const {
@@ -100,9 +102,25 @@ const ChatRouteLayout = () => {
}
}, [expand])
- if (!user && !chatId) return
+ useEffect(() => {
+ // Function to update the 'show' state based on screen width
+ const handleResize = () => {
+ setIsSmallScreen(window.innerWidth < 1600 && window.innerWidth > 1050)
+ }
+
+ // Initial setup
+ handleResize()
+
+ // Listen for window resize events
+ window.addEventListener('resize', handleResize)
+
+ // Clean up the event listener when the component unmounts
+ return () => {
+ window.removeEventListener('resize', handleResize)
+ }
+ }, [])
- const hasChat = !!chatId
+ if (!user && !chatId) return
return (
@@ -116,6 +134,7 @@ const ChatRouteLayout = () => {
)}
{expand && !showInfo && location.pathname.includes('/chat') && (
setShowInfo(true)}
onMouseEnter={() => setShowInfo(true)}
@@ -133,8 +152,8 @@ const ChatRouteLayout = () => {
{user && (
{teamModule?.list && (
<>
@@ -310,7 +329,10 @@ const StyledContainer = styled.div`
position: relative;
`
-const StyledLeftColumn = styled.div<{ right?: boolean; isHidden?: boolean; hasChat: boolean }>`
+const StyledLeftColumn = styled.div<{
+ isHidden?: boolean
+ isSmallScreen: boolean
+}>`
/* background: ${({ theme }) => theme.body.cardBgColor}; */
border-right: ${({ theme }) =>
location.pathname.includes('/chat') ? theme.body.secondaryBorder : 'none'};
@@ -332,7 +354,7 @@ const StyledLeftColumn = styled.div<{ right?: boolean; isHidden?: boolean; hasCh
padding-left: 120px;
height: 100%;
- min-width: 450px;
+ min-width: 475px;
max-height: calc(100vh - 185px);
@@ -345,8 +367,16 @@ const StyledLeftColumn = styled.div<{ right?: boolean; isHidden?: boolean; hasCh
overflow: hidden;
cursor: pointer;
`}
+ ${props =>
+ props.isSmallScreen &&
+ css`
+ margin-left: 0;
+ overflow: auto;
+ cursor: pointer;
+ position: static;
+ `}
`
-const StyledRightColumn = styled.div<{ isHidden?: boolean }>`
+const StyledRightColumn = styled.div<{ isHidden: boolean }>`
position: absolute;
right: 0;
z-index: 10000;
@@ -399,7 +429,7 @@ const StyledOutletWrapper = styled.div`
margin-left: 450px;
max-width: 1500px;
`
-const StyledShowButton = styled.div<{ isRight?: boolean }>`
+const StyledShowButton = styled.div<{ isRight?: boolean; isSmallScreen?: boolean }>`
height: 100vh;
width: calc(30% - 120px);
@@ -415,6 +445,11 @@ const StyledShowButton = styled.div<{ isRight?: boolean }>`
right: 0;
margin-left: auto;
`}
+ ${props =>
+ props.isSmallScreen &&
+ css`
+ width: calc(15% - 150px);
+ `}
`
const StyledMiddleArea = styled.div`
height: 100%;
diff --git a/apps/ui/src/styles/tabStyles.css.ts b/apps/ui/src/styles/tabStyles.css.ts
new file mode 100644
index 000000000..339d194b8
--- /dev/null
+++ b/apps/ui/src/styles/tabStyles.css.ts
@@ -0,0 +1,20 @@
+import styled from 'styled-components'
+
+export const StyledTabRootWrapper = styled.div`
+ display: flex;
+ flex-direction: column;
+
+ width: 100%;
+
+ gap: 20px;
+`
+
+export const StyledTabListWrapper = styled.div`
+ border: ${({ theme }) => theme.body.secondaryBorder};
+ border-radius: 30px;
+ width: fit-content;
+ margin: 0 auto;
+`
+export const StyledTabListSpan = styled.span`
+ color: ${({ theme }) => theme.body.textColorPrimary};
+`