1- import { ConsultMessage , User , UserRole } from '@idea2app/data-server' ;
2- import {
3- Avatar ,
4- Button ,
5- Container ,
6- IconButton ,
7- Paper ,
8- TextField ,
9- Tooltip ,
10- Typography ,
11- } from '@mui/material' ;
12- import { marked } from 'marked' ;
1+ import { User } from '@idea2app/data-server' ;
2+ import { Button , Container , IconButton , Paper , TextField , Tooltip } from '@mui/material' ;
133import { observer } from 'mobx-react' ;
144import { ObservedComponent , reaction } from 'mobx-react-helper' ;
155import { compose , JWTProps , jwtVerifier , RouteProps , router } from 'next-ssr-middleware' ;
166import { ChangeEvent , KeyboardEventHandler , type SubmitEvent } from 'react' ;
177import { formToJSON , scrollTo , sleep } from 'web-utility' ;
188
199import { SymbolIcon } from '../../../components/Icon' ;
20- import { FilePreview } from '../../../components/FilePreview' ;
2110import { PageHead } from '../../../components/PageHead' ;
2211import { PasteDropBox , PasteDropEvent } from '../../../components/PasteDropBox' ;
23- import { EvaluationDisplay } from '../../../components/Project/EvaluationDisplay ' ;
12+ import { ChatMessage } from '../../../components/Project/ChatMessage ' ;
2413import { ScrollList } from '../../../components/ScrollList' ;
2514import { SessionBox } from '../../../components/User/SessionBox' ;
2615import fileStore from '../../../models/File' ;
@@ -103,71 +92,8 @@ export default class ProjectEvaluationPage extends ObservedComponent<
10392 for ( const file of currentTarget . files || [ ] ) await this . uploadFile ( file ) ;
10493 } ;
10594
106- renderChatMessage = (
107- { id, content, file, evaluation, prototypes, createdAt, createdBy } : ConsultMessage ,
108- index = 0 ,
109- { length } : ConsultMessage [ ] ,
110- ) => {
111- const { t } = this . observedContext ;
112- const isBot = createdBy . roles . includes ( 3 as UserRole . Robot ) ;
113- const avatarSrc = isBot ? '/robot-avatar.png' : createdBy ?. avatar || '/default-avatar.png' ;
114- const name = isBot ? `${ t ( 'ai_assistant' ) } 🤖` : createdBy ?. name || 'User' ;
115-
116- return (
117- < div
118- key = { id }
119- id = { index + 1 === length ? 'last-message' : undefined }
120- className = { `mb-2 flex w-full ${ isBot ? 'justify-start' : 'justify-end' } ` }
121- >
122- < div
123- className = { `flex max-w-[95%] items-start gap-1 sm:max-w-[80%] ${ isBot ? 'flex-row' : 'flex-row-reverse' } ` }
124- >
125- < Avatar src = { avatarSrc } alt = { name } className = "h-7 w-7 sm:h-8 sm:w-8" />
126- < Paper
127- elevation = { 1 }
128- className = "bg-primary-light text-primary-contrast rounded-[16px_16px_4px_16px] p-1.5 sm:p-2"
129- sx = { {
130- backgroundColor : 'primary.light' ,
131- color : 'primary.contrastText' ,
132- } }
133- >
134- < Typography
135- variant = "caption"
136- display = "block"
137- className = "mb-0.5 text-[0.7rem] opacity-80 sm:text-[0.75rem]"
138- >
139- { name }
140- </ Typography >
141-
142- { file ? (
143- < FilePreview className = "mb-1" path = { file } />
144- ) : (
145- content && (
146- < Typography
147- className = "prose mb-1 text-[0.875rem] sm:text-base"
148- variant = "body2"
149- dangerouslySetInnerHTML = { { __html : marked ( content ) } }
150- />
151- )
152- ) }
153- { evaluation && (
154- < EvaluationDisplay
155- { ...evaluation }
156- projectId = { this . projectId }
157- messageId = { id }
158- prototypes = { prototypes }
159- />
160- ) }
161- { createdAt && (
162- < Typography variant = "caption" className = "text-[0.65rem] opacity-60 sm:text-[0.75rem]" >
163- { new Date ( createdAt ) . toLocaleTimeString ( ) }
164- </ Typography >
165- ) }
166- </ Paper >
167- </ div >
168- </ div >
169- ) ;
170- } ;
95+ handleParseFile = ( messageId : number , text : string ) =>
96+ this . messageStore . updateOne ( { content : text } , messageId ) ;
17197
17298 render ( ) {
17399 const { jwtPayload } = this . props ,
@@ -194,7 +120,15 @@ export default class ProjectEvaluationPage extends ObservedComponent<
194120 filter = { { project : projectId } }
195121 renderList = { allItems => (
196122 < div className = "h-full overflow-y-auto p-1 sm:p-2" >
197- { allItems . map ( this . renderChatMessage ) }
123+ { allItems . map ( ( message , index , { length } ) => (
124+ < div
125+ key = { message . id }
126+ id = { index + 1 === length ? 'last-message' : undefined }
127+ className = "mb-2 flex w-full"
128+ >
129+ < ChatMessage { ...message } onFileParse = { this . handleParseFile } />
130+ </ div >
131+ ) ) }
198132 </ div >
199133 ) }
200134 />
0 commit comments