Skip to content

Commit

Permalink
Refactor AssistantDetail component and enhance CodeEditor functionality
Browse files Browse the repository at this point in the history
- Replaced BasicInfo and KnowledgeFiles components with General and Files components for improved modularity.
- Introduced a new Script component and updated the layout to include Functions, enhancing the assistant's capabilities.
- Enhanced CodeEditor with a responsive layout and added resize observer for better usability.
- Updated styles for improved visual consistency and user experience across the assistant detail interface.

These changes contribute to a more organized and user-friendly assistant detail interface, improving overall usability.
  • Loading branch information
trheyi committed Dec 28, 2024
1 parent 75f5870 commit 7ff624d
Show file tree
Hide file tree
Showing 10 changed files with 501 additions and 201 deletions.
12 changes: 9 additions & 3 deletions packages/xgen/components/edit/CodeEditor/index.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
.editor {
width: 100%;
height: 100%;
position: relative;
}

._local {
border-radius: var(--radius) !important;
overflow: hidden;
}
width: 100%;
height: 100%;
}
71 changes: 43 additions & 28 deletions packages/xgen/components/edit/CodeEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { useEffect, useMemo, useRef, useState } from 'react'
import Editor from 'react-monaco-editor'

import { Item } from '@/components'
import { useGlobal } from '@/context/app'
import vars from '@/styles/preset/vars'

import styles from './index.less'

import type { Component } from '@/types'

import yaml from 'js-yaml'
import type { EditorDidMount, monaco } from 'react-monaco-editor'
import { message } from 'antd'
Expand Down Expand Up @@ -78,6 +74,23 @@ const Custom = window.$app.memo((props: ICustom) => {
setValue(props.value)
}, [props.value])

useEffect(() => {
const resizeObserver = new ResizeObserver(() => {
if (ref.current) {
ref.current.layout()
}
})

const container = document.querySelector(`.${styles.editor}`)
if (container) {
resizeObserver.observe(container)
}

return () => {
resizeObserver.disconnect()
}
}, [])

const onChange = (v: any) => {
if (!props.onChange) return
props.onChange(v)
Expand Down Expand Up @@ -121,30 +134,32 @@ const Custom = window.$app.memo((props: ICustom) => {
}

return (
<Editor
className={styles._local}
width='100%'
height={height}
language={language}
theme={theme}
options={{
readOnly: props.disabled,
wordWrap: 'on',
formatOnPaste: true,
formatOnType: true,
renderLineHighlight: 'none',
smoothScrolling: true,
padding: { top: 15 },
lineNumbersMinChars: 3,
minimap: { enabled: false },
lineNumbers: props.hideLineNumbers ? 'off' : 'on',
scrollbar: { verticalScrollbarSize: 8, horizontalSliderSize: 8, useShadows: false }
}}
value={value}
onChange={onChange}
editorDidMount={editorDidMount}
editorWillUnmount={editorWillUnmount}
></Editor>
<div className={styles.editor}>
<Editor
className={styles._local}
width='100%'
height={height}
language={language}
theme={theme}
options={{
readOnly: props.disabled,
wordWrap: 'on',
formatOnPaste: true,
formatOnType: true,
renderLineHighlight: 'none',
smoothScrolling: true,
padding: { top: 15 },
lineNumbersMinChars: 3,
minimap: { enabled: false },
lineNumbers: props.hideLineNumbers ? 'off' : 'on',
scrollbar: { verticalScrollbarSize: 8, horizontalSliderSize: 8, useShadows: false }
}}
value={value}
onChange={onChange}
editorDidMount={editorDidMount}
editorWillUnmount={editorWillUnmount}
/>
</div>
)
})

Expand Down
28 changes: 17 additions & 11 deletions packages/xgen/pages/assistants/detail/$.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import type { Assistant } from '@/layouts/components/Neo/components/AIChat/Card'
import type { UploadChangeParam } from 'antd/es/upload'
import type { UploadFile } from 'antd/es/upload/interface'
import Tag from '@/layouts/components/Neo/components/AIChat/Tag'
import BasicInfo from './components/BasicInfo'
import KnowledgeFiles from './components/KnowledgeFiles'
import General from './components/General'
import Files from './components/Files'
import Workflow from './components/Workflow'
import CodeEditor from './components/CodeEditor'
import Script from './components/Script'
import Functions from './components/Functions'
import styles from './index.less'

const AssistantDetail = () => {
Expand Down Expand Up @@ -108,24 +109,29 @@ const AssistantDetail = () => {

const items = [
{
key: 'basic',
label: 'Basic Info',
children: <BasicInfo form={form} />
key: 'general',
label: 'General',
children: <General form={form} />
},
{
key: 'files',
label: 'Knowledge Files',
children: <KnowledgeFiles files={files} onFilesChange={setFiles} />
label: 'Files',
children: <Files files={files} onFilesChange={setFiles} />
},
{
key: 'workflow',
label: 'Workflow',
children: <Workflow />
},
{
key: 'code',
label: 'Code',
children: <CodeEditor code={code} onChange={setCode} />
key: 'functions',
label: 'Functions',
children: <Functions />
},
{
key: 'script',
label: 'Script',
children: <Script code={code} onChange={setCode} />
}
]

Expand Down
117 changes: 117 additions & 0 deletions packages/xgen/pages/assistants/detail/components/Files.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { useState } from 'react'
import { Table, Button, Upload, Space, Typography } from 'antd'
import { UploadOutlined, DeleteOutlined } from '@ant-design/icons'
import type { UploadFile } from 'antd/es/upload/interface'
import styles from '../index.less'

const { Title } = Typography

interface FilesProps {
files: UploadFile[]
onFilesChange: (files: UploadFile[]) => void
}

// Generate 100 test files
const fileTypes = [
{ ext: 'json', type: 'application/json' },
{ ext: 'yaml', type: 'application/yaml' },
{ ext: 'md', type: 'text/markdown' },
{ ext: 'js', type: 'application/javascript' },
{ ext: 'py', type: 'text/x-python' },
{ ext: 'ts', type: 'application/typescript' }
]

const testFiles: UploadFile[] = Array.from({ length: 100 }, (_, index) => {
const fileType = fileTypes[index % fileTypes.length]
return {
uid: String(index + 1),
name: `file_${index + 1}.${fileType.ext}`,
size: Math.floor(Math.random() * 1024 * 1024 * 5), // Random size up to 5MB
type: fileType.type,
status: 'done'
}
})

export default function Files({ files: propFiles, onFilesChange }: FilesProps) {
const [files, setFiles] = useState<UploadFile[]>(testFiles)

const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
ellipsis: true
},
{
title: 'Size',
dataIndex: 'size',
key: 'size',
width: 120,
render: (size: number) => {
if (size < 1024) {
return `${size} B`
} else if (size < 1024 * 1024) {
return `${(size / 1024).toFixed(1)} KB`
} else {
return `${(size / (1024 * 1024)).toFixed(1)} MB`
}
}
},
{
title: 'Action',
key: 'action',
width: 80,
render: (_: any, record: UploadFile) => (
<Button
type='text'
icon={<DeleteOutlined />}
onClick={() => handleRemove(record)}
style={{ color: 'var(--color_text_grey)' }}
/>
)
}
]

const handleRemove = (file: UploadFile) => {
const newFiles = files.filter((item) => item.uid !== file.uid)
setFiles(newFiles)
onFilesChange(newFiles)
}

const handleUpload = (info: any) => {
const newFiles = [...files, ...info.fileList]
setFiles(newFiles)
onFilesChange(newFiles)
}

return (
<div className={styles.files}>
<div className={styles.filesHeader}>
<Title level={5} style={{ margin: 0, fontWeight: 500 }}>
Assistant Files
</Title>
<Upload
multiple
fileList={[]}
beforeUpload={() => false}
onChange={handleUpload}
showUploadList={false}
>
<Button type='primary' icon={<UploadOutlined />}>
Upload
</Button>
</Upload>
</div>
<div className={styles.filesTable}>
<Table
dataSource={files}
columns={columns}
pagination={false}
rowKey='uid'
size='middle'
scroll={{ y: 'calc(100vh - 64px - 24px - 48px - 48px - 48px - 72px)' }}
/>
</div>
</div>
)
}
81 changes: 81 additions & 0 deletions packages/xgen/pages/assistants/detail/components/Functions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { useState } from 'react'
import Editor from 'react-monaco-editor'
import { useGlobal } from '@/context/app'
import vars from '@/styles/preset/vars'
import styles from '../index.less'

const defaultFunctions = {
functions: [
{
name: 'example_function',
description: 'An example function',
parameters: {
type: 'object',
properties: {
param1: {
type: 'string',
description: 'First parameter'
},
param2: {
type: 'number',
description: 'Second parameter'
}
},
required: ['param1']
}
}
]
}

export default function Functions() {
const [value, setValue] = useState(JSON.stringify(defaultFunctions, null, 2))
const global = useGlobal()
const theme = global.theme === 'dark' ? 'x-dark' : 'x-light'

const editorDidMount = (editor: any, monaco: any) => {
monaco.editor.defineTheme('x-dark', {
base: 'vs-dark',
inherit: true,
rules: [],
colors: {
'editor.background': vars[global.theme].color_bg_nav
}
})

monaco.editor.defineTheme('x-light', {
base: 'vs',
inherit: true,
rules: [],
colors: {
'editor.background': vars[global.theme].color_bg_nav
}
})

monaco.editor.setTheme(theme)
}

return (
<div className={styles.functions}>
<Editor
width='100%'
height='100%'
language='json'
theme={theme}
value={value}
onChange={setValue}
editorDidMount={editorDidMount}
options={{
wordWrap: 'on',
formatOnPaste: true,
formatOnType: true,
renderLineHighlight: 'none',
smoothScrolling: true,
padding: { top: 15 },
lineNumbersMinChars: 3,
minimap: { enabled: false },
scrollbar: { verticalScrollbarSize: 8, horizontalSliderSize: 8, useShadows: false }
}}
/>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import styles from '../index.less'
const { TextArea } = Input
const { Option } = Select

interface BasicInfoProps {
form: any
interface GeneralProps {
form: FormInstance
}

export default function BasicInfo({ form }: { form: FormInstance }) {
export default function General({ form }: GeneralProps) {
return (
<Form
form={form}
Expand Down
Loading

0 comments on commit 7ff624d

Please sign in to comment.