Skip to content

Commit b3afcd8

Browse files
DanilaRubleuskiDanila Rubleuski
and
Danila Rubleuski
authored
feat(boxai-sidebar): Pass isStopResponseEnabled prop to BoxAiContentAnswers (#3808)
* feat(boxai-sidebar): Pass isStopResponseEnabled prop * feat(boxai-sidebar): PR fix --------- Co-authored-by: Danila Rubleuski <[email protected]>
1 parent d679d60 commit b3afcd8

File tree

2 files changed

+73
-64
lines changed

2 files changed

+73
-64
lines changed

src/elements/content-sidebar/BoxAISidebar.tsx

+49-41
Original file line numberDiff line numberDiff line change
@@ -13,69 +13,74 @@ import { DOCUMENT_SUGGESTED_QUESTIONS, SPREADSHEET_FILE_EXTENSIONS } from '../co
1313
import messages from '../common/content-answers/messages';
1414

1515
export interface BoxAISidebarContextValues {
16-
cache: { encodedSession?: string | null, questions?: QuestionType[] },
17-
contentName: string,
18-
elementId: string,
19-
recordAction: (params: RecordActionType) => void,
20-
setCacheValue: (key: 'encodedSession' | 'questions', value: string | null | QuestionType[]) => void,
21-
userInfo: { name: string, avatarUrl: string },
22-
};
16+
cache: { encodedSession?: string | null; questions?: QuestionType[] };
17+
contentName: string;
18+
elementId: string;
19+
isStopResponseEnabled: boolean;
20+
recordAction: (params: RecordActionType) => void;
21+
setCacheValue: (key: 'encodedSession' | 'questions', value: string | null | QuestionType[]) => void;
22+
userInfo: { name: string; avatarUrl: string };
23+
}
2324

2425
export const BoxAISidebarContext = React.createContext<BoxAISidebarContextValues>({
2526
cache: null,
2627
contentName: '',
2728
elementId: '',
29+
isStopResponseEnabled: false,
2830
recordAction: noop,
2931
setCacheValue: noop,
30-
userInfo: { name: '', avatarUrl: ''},
32+
userInfo: { name: '', avatarUrl: '' },
3133
});
3234

3335
export interface BoxAISidebarProps {
34-
contentName: string,
35-
cache: { encodedSession?: string | null, questions?: QuestionType[] },
36-
createSessionRequest: (payload: Record<string, unknown>, itemID: string) => Promise<unknown>,
37-
elementId: string,
36+
contentName: string;
37+
cache: { encodedSession?: string | null; questions?: QuestionType[] };
38+
createSessionRequest: (payload: Record<string, unknown>, itemID: string) => Promise<unknown>;
39+
elementId: string;
3840
fetchTimeout: Record<string, unknown>;
39-
fileExtension: string,
40-
fileID: string,
41-
getAgentConfig: (payload: Record<string, unknown>) => Promise<unknown>,
42-
getAIStudioAgents: () => Promise<unknown>,
43-
getAnswer: (payload: Record<string, unknown>,
41+
fileExtension: string;
42+
fileID: string;
43+
getAgentConfig: (payload: Record<string, unknown>) => Promise<unknown>;
44+
getAIStudioAgents: () => Promise<unknown>;
45+
getAnswer: (
46+
payload: Record<string, unknown>,
4447
itemID?: string,
4548
itemIDs?: Array<string>,
46-
state?: Record<string, unknown> ) => Promise<unknown>,
49+
state?: Record<string, unknown>,
50+
) => Promise<unknown>;
4751
getAnswerStreaming: (
4852
payload: Record<string, unknown>,
4953
itemID?: string,
5054
itemIDs?: Array<string>,
5155
abortController?: AbortController,
5256
state?: Record<string, unknown>,
53-
) => Promise<unknown>,
54-
getSuggestedQuestions: (itemID: string) => Promise<unknown> | null,
55-
hostAppName: string,
56-
isAgentSelectorEnabled: boolean,
57-
isAIStudioAgentSelectorEnabled: boolean,
58-
isCitationsEnabled: boolean,
59-
isDebugModeEnabled: boolean,
60-
isIntelligentQueryMode: boolean,
61-
isMarkdownEnabled: boolean,
62-
isResetChatEnabled: boolean,
63-
isStopResponseEnabled: boolean,
64-
isStreamingEnabled: boolean,
65-
userInfo: { name: '', avatarUrl: ''},
66-
recordAction: (params: RecordActionType) => void,
67-
setCacheValue: (key: 'encodedSession' | 'questions', value: string | null | QuestionType[]) => void,
57+
) => Promise<unknown>;
58+
getSuggestedQuestions: (itemID: string) => Promise<unknown> | null;
59+
hostAppName: string;
60+
isAgentSelectorEnabled: boolean;
61+
isAIStudioAgentSelectorEnabled: boolean;
62+
isCitationsEnabled: boolean;
63+
isDebugModeEnabled: boolean;
64+
isIntelligentQueryMode: boolean;
65+
isMarkdownEnabled: boolean;
66+
isResetChatEnabled: boolean;
67+
isStopResponseEnabled?: boolean;
68+
isStreamingEnabled: boolean;
69+
userInfo: { name: ''; avatarUrl: '' };
70+
recordAction: (params: RecordActionType) => void;
71+
setCacheValue: (key: 'encodedSession' | 'questions', value: string | null | QuestionType[]) => void;
6872
}
6973

7074
const BoxAISidebar = (props: BoxAISidebarProps) => {
7175
const {
7276
cache,
7377
contentName,
74-
elementId,
78+
elementId,
7579
fileExtension,
7680
fileID,
7781
getSuggestedQuestions,
7882
isIntelligentQueryMode,
83+
isStopResponseEnabled,
7984
recordAction,
8085
setCacheValue,
8186
userInfo,
@@ -84,9 +89,9 @@ const BoxAISidebar = (props: BoxAISidebarProps) => {
8489
const { questions } = cache;
8590
const { formatMessage } = useIntl();
8691
let questionsWithoutInProgress = questions;
87-
if (questions.length > 0 && !questions[questions.length -1].isCompleted) {
92+
if (questions.length > 0 && !questions[questions.length - 1].isCompleted) {
8893
// pass only fully completed questions to not show loading indicator of question where we canceled API request
89-
questionsWithoutInProgress = questionsWithoutInProgress.slice(0,-1);
94+
questionsWithoutInProgress = questionsWithoutInProgress.slice(0, -1);
9095
}
9196

9297
const localizedQuestions = DOCUMENT_SUGGESTED_QUESTIONS.map(question => ({
@@ -107,19 +112,22 @@ const BoxAISidebar = (props: BoxAISidebarProps) => {
107112
return (
108113
// BoxAISidebarContent is using withApiWrapper that is not passing all provided props,
109114
// that's why we need to use provider to pass other props
110-
<BoxAISidebarContext.Provider value={{cache, contentName, elementId, setCacheValue, recordAction, userInfo}}>
115+
<BoxAISidebarContext.Provider
116+
value={{ cache, contentName, elementId, isStopResponseEnabled, setCacheValue, recordAction, userInfo }}
117+
>
111118
<BoxAISidebarContent
119+
isStopResponseEnabled={isStopResponseEnabled}
112120
itemID={fileID}
113121
itemIDs={[fileID]}
114-
restoredQuestions={questionsWithoutInProgress}
122+
restoredQuestions={questionsWithoutInProgress}
115123
restoredSession={cache.encodedSession}
116-
suggestedQuestions={getSuggestedQuestions === null? localizedQuestions : []}
124+
suggestedQuestions={getSuggestedQuestions === null ? localizedQuestions : []}
117125
warningNotice={spreadsheetNotice}
118126
warningNoticeAriaLabel={formatMessage(messages.welcomeMessageSpreadsheetNoticeAriaLabel)}
119-
{...rest}
127+
{...rest}
120128
/>
121129
</BoxAISidebarContext.Provider>
122130
);
123-
}
131+
};
124132

125133
export default BoxAISidebar;

src/elements/content-sidebar/BoxAISidebarContent.tsx

+24-23
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { AgentsProvider, BoxAiAgentSelectorWithApi } from '@box/box-ai-agent-sel
99
import { IconButton, Text } from '@box/blueprint-web';
1010
import { Trash } from '@box/blueprint-web-assets/icons/Line';
1111
// @ts-expect-error - TS2305 - Module '"@box/box-ai-content-answers"' has no exported member 'ApiWrapperProps'.
12-
import { BoxAiContentAnswers, withApiWrapper, type ApiWrapperProps } from '@box/box-ai-content-answers'
12+
import { BoxAiContentAnswers, withApiWrapper, type ApiWrapperProps } from '@box/box-ai-content-answers';
1313
import SidebarContent from './SidebarContent';
1414
import { withAPIContext } from '../common/api-context';
1515
import { withErrorBoundary } from '../common/error-boundary';
@@ -24,28 +24,28 @@ import sidebarMessages from './messages';
2424

2525
import './BoxAISidebar.scss';
2626

27-
2827
const MARK_NAME_JS_READY: string = `${ORIGIN_BOXAI_SIDEBAR}_${EVENT_JS_READY}`;
2928

3029
mark(MARK_NAME_JS_READY);
31-
30+
3231
function BoxAISidebarContent(props: ApiWrapperProps) {
33-
const {
34-
createSession,
35-
encodedSession,
36-
onClearAction,
32+
const {
33+
createSession,
34+
encodedSession,
35+
onClearAction,
3736
getAIStudioAgents,
3837
hostAppName,
39-
isAIStudioAgentSelectorEnabled,
38+
isAIStudioAgentSelectorEnabled,
4039
isResetChatEnabled,
41-
onSelectAgent,
40+
onSelectAgent,
4241
questions,
43-
sendQuestion,
44-
stopQuestion,
45-
...rest
42+
sendQuestion,
43+
stopQuestion,
44+
...rest
4645
} = props;
4746
const { formatMessage } = useIntl();
48-
const { cache, contentName, elementId, recordAction, setCacheValue, userInfo } = React.useContext(BoxAISidebarContext);
47+
const { cache, contentName, elementId, isStopResponseEnabled, recordAction, setCacheValue, userInfo } =
48+
React.useContext(BoxAISidebarContext);
4949
const { questions: cacheQuestions } = cache;
5050

5151
if (cache.encodedSession !== encodedSession) {
@@ -61,15 +61,15 @@ function BoxAISidebarContent(props: ApiWrapperProps) {
6161
createSession();
6262
}
6363

64-
if (cacheQuestions.length > 0 && cacheQuestions[cacheQuestions.length-1].isCompleted === false) {
64+
if (cacheQuestions.length > 0 && cacheQuestions[cacheQuestions.length - 1].isCompleted === false) {
6565
// if we have cache with question that is not completed resend it to trigger an API
66-
sendQuestion({prompt: cacheQuestions[cacheQuestions.length-1].prompt});
66+
sendQuestion({ prompt: cacheQuestions[cacheQuestions.length - 1].prompt });
6767
}
6868

6969
return () => {
7070
// stop API request on unmount (e.g. during switching to another tab)
7171
stopQuestion();
72-
}
72+
};
7373
// eslint-disable-next-line react-hooks/exhaustive-deps
7474
}, []);
7575

@@ -79,7 +79,7 @@ function BoxAISidebarContent(props: ApiWrapperProps) {
7979
<Text as="h3" className="bcs-title">
8080
{formatMessage(messages.sidebarBoxAITitle)}
8181
</Text>
82-
{isAIStudioAgentSelectorEnabled &&
82+
{isAIStudioAgentSelectorEnabled && (
8383
<BoxAiAgentSelectorWithApi
8484
fetcher={getAIStudioAgents}
8585
hostAppName={hostAppName}
@@ -89,28 +89,28 @@ function BoxAISidebarContent(props: ApiWrapperProps) {
8989
// @ts-ignore variant will be available in higher version
9090
variant="sidebar"
9191
/>
92-
}
92+
)}
9393
</div>
9494
);
9595
};
9696

9797
const renderActions = () => (
9898
<>
99-
{ renderBoxAISidebarTitle() }
100-
{ isResetChatEnabled &&
99+
{renderBoxAISidebarTitle()}
100+
{isResetChatEnabled && (
101101
<IconButton
102102
aria-label={formatMessage(sidebarMessages.boxAISidebarClear)}
103103
icon={Trash}
104104
onClick={onClearAction}
105105
size="x-small"
106106
/>
107-
}
107+
)}
108108
</>
109109
);
110110

111111
return (
112112
<AgentsProvider>
113-
<SidebarContent
113+
<SidebarContent
114114
actions={renderActions()}
115115
className="bcs-BoxAISidebar"
116116
elementId={elementId}
@@ -123,13 +123,14 @@ function BoxAISidebarContent(props: ApiWrapperProps) {
123123
contentType={formatMessage(messages.sidebarBoxAIContent)}
124124
hostAppName={hostAppName}
125125
isAIStudioAgentSelectorEnabled={isAIStudioAgentSelectorEnabled}
126+
isStopResponseEnabled={isStopResponseEnabled}
126127
questions={questions}
127128
stopQuestion={stopQuestion}
128129
submitQuestion={sendQuestion}
129130
userInfo={userInfo}
130131
variant="sidebar"
131132
recordAction={recordAction}
132-
{...rest}
133+
{...rest}
133134
/>
134135
</div>
135136
</SidebarContent>

0 commit comments

Comments
 (0)