adjust file card

This commit is contained in:
Nate Kelley 2025-02-10 12:24:35 -07:00
parent 9fa93deed4
commit 7a1f5418b3
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
6 changed files with 98 additions and 34 deletions

View File

@ -89,5 +89,5 @@ export type BusterChatMessageReasoning_file = {
text: string;
line_number: number;
modified?: boolean; //defaults to true
}; //will be defined if the file has been completed OR on a page refresh
}[]; //will be defined if the file has been completed OR on a page refresh
};

View File

@ -68,6 +68,10 @@ const useStyles = createStyles(({ token, css }) => ({
`,
fileCard: css`
margin-bottom: 4px;
.vertical-divider {
display: none;
}
`,
verticalDivider: css`
transition: opacity 0.2s ease-in-out;

View File

@ -1,9 +1,24 @@
import React from 'react';
import { ReasoningMessageProps } from '../ReasoningMessageSelector';
import { BusterChatMessageReasoning_file } from '@/api/asset_interfaces';
import { AppCodeBlock } from '@/components/text/AppMarkdown/AppCodeBlock';
export const ReasoningMessage_File: React.FC<ReasoningMessageProps> = React.memo(
({ reasoningMessage }) => {
return <div>asdf</div>;
({ reasoningMessage, isCompletedStream, isLastMessageItem }) => {
const { file, file_name, file_type, file_chunk } =
reasoningMessage as BusterChatMessageReasoning_file;
const showLoader = !isCompletedStream && isLastMessageItem;
return (
<AppCodeBlock
title={file_name}
language={'yaml'}
showCopyButton={false}
showLoader={showLoader}>
{file?.map((chunk) => chunk.text).join('\n')}
</AppCodeBlock>
);
}
);

View File

@ -1,4 +1,4 @@
import React, { useCallback, useLayoutEffect, useState } from 'react';
import React, { useLayoutEffect, useState } from 'react';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { AppMaterialIcons } from '../../../icons';
import { createStyles } from 'antd-style';
@ -6,7 +6,6 @@ import { Button } from 'antd';
import darkTheme from 'react-syntax-highlighter/dist/cjs/styles/prism/vsc-dark-plus';
import { Text } from '@/components/text';
import { TextPulseLoader } from '../../..';
import { useAntToken } from '@/styles/useAntToken';
import lightTheme from './light';
import { useMemoizedFn } from 'ahooks';
@ -20,7 +19,9 @@ export const AppCodeBlock: React.FC<{
style?: React.CSSProperties;
showLoader?: boolean;
showCopyButton?: boolean;
}> = React.memo((props) => {
title?: string;
buttons?: React.ReactNode;
}> = React.memo(({ title, buttons, ...props }) => {
const isDarkMode = useBusterStylesContext((state) => state.isDarkMode);
const { children, className = '', language, showLoader, showCopyButton = true, ...rest } = props;
const [style, setStyle] = useState<{
@ -42,17 +43,19 @@ export const AppCodeBlock: React.FC<{
<CodeBlockWrapper
code={code}
isDarkMode={isDarkMode}
language={language || ''}
language={title || language}
showCopyButton={showCopyButton}>
<div className="w-full overflow-x-auto">
<div className="code-wrapper">
{language ? (
<SyntaxHighlighter
{...rest}
showLineNumbers
className={`${className} !p-3 transition ${!style ? 'opacity-100' : '!m-0 !border-none !p-0 opacity-100'}`}
children={code}
language={language}
style={style}
lineNumberStyle={{ color: '#000' }}
/>
) : (
<code {...rest} className={className}>
@ -97,9 +100,10 @@ const CodeBlockWrapper: React.FC<{
children: React.ReactNode;
isDarkMode: boolean;
code: string;
language: string;
language?: string;
showCopyButton: boolean;
}> = React.memo(({ children, code, showCopyButton, language }) => {
buttons?: React.ReactNode;
}> = React.memo(({ children, code, showCopyButton, language, buttons }) => {
const { cx, styles } = useStyles();
const { openSuccessMessage } = useBusterNotifications();
const token = useAntToken();
@ -113,21 +117,24 @@ const CodeBlockWrapper: React.FC<{
<div className={cx(styles.container, 'max-h-fit')}>
<div className={cx(styles.containerHeader, 'flex items-center justify-between')}>
<Text className="pl-2">{language}</Text>
{showCopyButton && (
<Button
style={{
color: token.colorTextSecondary
}}
type="text"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
copyCode();
}}
icon={<AppMaterialIcons icon="content_copy" />}>
Copy
</Button>
)}
<div className="flex items-center space-x-1">
{showCopyButton && (
<Button
style={{
color: token.colorTextSecondary
}}
type="text"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
copyCode();
}}
icon={<AppMaterialIcons icon="content_copy" />}>
Copy
</Button>
)}
{buttons}
</div>
</div>
{children}

View File

@ -1,5 +1,8 @@
import { busterAppStyleConfig } from '@/styles/busterAntDStyleConfig';
import React from 'react';
const token = busterAppStyleConfig.token!;
export default {
'code[class*="language-"]': {
color: '#393A34',
@ -77,7 +80,7 @@ export default {
border: '1px solid #dddddd'
},
comment: {
color: '#008000',
color: token.colorTextTertiary,
fontStyle: 'italic'
},
prolog: {
@ -126,25 +129,25 @@ export default {
color: '#36acaa'
},
atrule: {
color: busterAppStyleConfig.token?.colorPrimary
color: token.colorPrimary
},
keyword: {
color: busterAppStyleConfig.token?.colorPrimary
color: token.colorPrimary
},
'attr-value': {
color: busterAppStyleConfig.token?.colorPrimary
color: token.colorPrimary
},
'.language-autohotkey .token.selector': {
color: busterAppStyleConfig.token?.colorPrimary
color: token.colorPrimary
},
'.language-json .token.boolean': {
color: busterAppStyleConfig.token?.colorPrimary
color: token.colorPrimary
},
'.language-json .token.number': {
color: busterAppStyleConfig.token?.colorPrimary
color: token.colorPrimary
},
'code[class*="language-css"]': {
color: busterAppStyleConfig.token?.colorPrimary
color: token.colorPrimary
},
function: {
color: '#393A34'

View File

@ -5,7 +5,8 @@ import {
type BusterChatMessageRequest,
BusterChatMessage_fileMetadata,
BusterChatMessageReasoning_thought,
BusterChatMessageReasoning_thoughtPill
BusterChatMessageReasoning_thoughtPill,
BusterChatMessageReasoning_file
} from '@/api/asset_interfaces';
import { faker } from '@faker-js/faker';
@ -86,6 +87,37 @@ export const createMockResponseMessageFile = (): BusterChatMessage_file => {
};
};
export const createMockReasoningMessageFile = (): BusterChatMessageReasoning_file => {
return {
id: 'swag',
type: 'file',
file_type: 'metric',
status: 'completed',
file_name: faker.company.name(),
version_number: 1,
version_id: faker.string.uuid(),
file: [
{
text: 'name: my-service\nversion: 1.0.0\ndescription: A sample service',
line_number: 1,
modified: false
},
{
text: 'dependencies:\n - name: redis\n version: 6.2.0\n - name: postgres\n version: 13.4',
line_number: 2
},
{
text: 'ports:\n - 8080\n - 9000\n - 6379',
line_number: 3
},
{
text: 'environment:\n NODE_ENV: production\n LOG_LEVEL: info\n DB_HOST: localhost',
line_number: 4
}
]
};
};
export const MOCK_CHAT: BusterChat = {
id: '0',
title: 'Mock Chat',
@ -95,7 +127,10 @@ export const MOCK_CHAT: BusterChat = {
id: '123',
created_at: '2025-01-01',
request_message: createMockUserMessage(),
reasoning: [...Array.from({ length: 1 }, () => createMockResponseMessageThought())],
reasoning: [
...Array.from({ length: 1 }, () => createMockResponseMessageThought()),
createMockReasoningMessageFile()
],
response_messages: [
createMockResponseMessageText(),
createMockResponseMessageFile(),