@@ -16,20 +16,21 @@ import { getFeatureConfig, withFeatureConsumer, isFeatureEnabled } from '../comm
1616import { withRouterAndRef } from '../common/routing' ;
1717import {
1818 ORIGIN_ACTIVITY_SIDEBAR ,
19+ ORIGIN_BOXAI_SIDEBAR ,
1920 ORIGIN_DETAILS_SIDEBAR ,
2021 ORIGIN_DOCGEN_SIDEBAR ,
2122 ORIGIN_METADATA_SIDEBAR ,
2223 ORIGIN_METADATA_SIDEBAR_REDESIGN ,
2324 ORIGIN_SKILLS_SIDEBAR ,
2425 ORIGIN_VERSIONS_SIDEBAR ,
2526 SIDEBAR_VIEW_ACTIVITY ,
27+ SIDEBAR_VIEW_BOXAI ,
2628 SIDEBAR_VIEW_DETAILS ,
2729 SIDEBAR_VIEW_METADATA ,
2830 SIDEBAR_VIEW_SKILLS ,
2931 SIDEBAR_VIEW_VERSIONS ,
3032 SIDEBAR_VIEW_DOCGEN ,
3133 SIDEBAR_VIEW_METADATA_REDESIGN ,
32- SIDEBAR_VIEW_BOXAI ,
3334} from '../../constants' ;
3435import type { DetailsSidebarProps } from './DetailsSidebar' ;
3536import type { DocGenSidebarProps } from './DocGenSidebar/DocGenSidebar' ;
@@ -59,7 +60,7 @@ type Props = {
5960 getPreview : Function ,
6061 getViewer : Function ,
6162 hasActivity : boolean ,
62- hasBoxAI : boolean ,
63+ hasNativeBoxAISidebar : boolean ,
6364 hasDetails : boolean ,
6465 hasDocGen : boolean ,
6566 hasMetadata : boolean ,
@@ -87,12 +88,13 @@ type ElementRefType = {
8788
8889// TODO: place into code splitting logic
8990const BASE_EVENT_NAME = '_JS_LOADING' ;
90- const MARK_NAME_JS_LOADING_DETAILS = `${ ORIGIN_DETAILS_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
9191const MARK_NAME_JS_LOADING_ACTIVITY = `${ ORIGIN_ACTIVITY_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
92- const MARK_NAME_JS_LOADING_SKILLS = `${ ORIGIN_SKILLS_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
92+ const MARK_NAME_JS_LOADING_BOXAI = `${ ORIGIN_BOXAI_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
93+ const MARK_NAME_JS_LOADING_DETAILS = `${ ORIGIN_DETAILS_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
94+ const MARK_NAME_JS_LOADING_DOCGEN = `${ ORIGIN_DOCGEN_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
9395const MARK_NAME_JS_LOADING_METADATA = `${ ORIGIN_METADATA_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
9496const MARK_NAME_JS_LOADING_METADATA_REDESIGNED = `${ ORIGIN_METADATA_SIDEBAR_REDESIGN } ${ BASE_EVENT_NAME } ` ;
95- const MARK_NAME_JS_LOADING_DOCGEN = `${ ORIGIN_DOCGEN_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
97+ const MARK_NAME_JS_LOADING_SKILLS = `${ ORIGIN_SKILLS_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
9698const MARK_NAME_JS_LOADING_VERSIONS = `${ ORIGIN_VERSIONS_SIDEBAR } ${ BASE_EVENT_NAME } ` ;
9799
98100const URL_TO_FEED_ITEM_TYPE = { annotations : 'annotation' , comments : 'comment' , tasks : 'task' } ;
@@ -106,12 +108,13 @@ const DEFAULT_SIDEBAR_VIEWS = [
106108 SIDEBAR_VIEW_METADATA ,
107109] ;
108110
109- const LoadableDetailsSidebar = SidebarUtils . getAsyncSidebarContent ( SIDEBAR_VIEW_DETAILS , MARK_NAME_JS_LOADING_DETAILS ) ;
110111const LoadableActivitySidebar = SidebarUtils . getAsyncSidebarContent (
111112 SIDEBAR_VIEW_ACTIVITY ,
112113 MARK_NAME_JS_LOADING_ACTIVITY ,
113114) ;
114- const LoadableSkillsSidebar = SidebarUtils . getAsyncSidebarContent ( SIDEBAR_VIEW_SKILLS , MARK_NAME_JS_LOADING_SKILLS ) ;
115+ const LoadableBoxAISidebar = SidebarUtils . getAsyncSidebarContent ( SIDEBAR_VIEW_BOXAI , MARK_NAME_JS_LOADING_BOXAI ) ;
116+ const LoadableDetailsSidebar = SidebarUtils . getAsyncSidebarContent ( SIDEBAR_VIEW_DETAILS , MARK_NAME_JS_LOADING_DETAILS ) ;
117+ const LoadableDocGenSidebar = SidebarUtils . getAsyncSidebarContent ( SIDEBAR_VIEW_DOCGEN , MARK_NAME_JS_LOADING_DOCGEN ) ;
115118const LoadableMetadataSidebar = SidebarUtils . getAsyncSidebarContent (
116119 SIDEBAR_VIEW_METADATA ,
117120 MARK_NAME_JS_LOADING_METADATA ,
@@ -120,7 +123,7 @@ const LoadableMetadataSidebarRedesigned = SidebarUtils.getAsyncSidebarContent(
120123 SIDEBAR_VIEW_METADATA_REDESIGN ,
121124 MARK_NAME_JS_LOADING_METADATA ,
122125) ;
123- const LoadableDocGenSidebar = SidebarUtils . getAsyncSidebarContent ( SIDEBAR_VIEW_DOCGEN , MARK_NAME_JS_LOADING_DOCGEN ) ;
126+ const LoadableSkillsSidebar = SidebarUtils . getAsyncSidebarContent ( SIDEBAR_VIEW_SKILLS , MARK_NAME_JS_LOADING_SKILLS ) ;
124127const LoadableVersionsSidebar = SidebarUtils . getAsyncSidebarContent (
125128 SIDEBAR_VIEW_VERSIONS ,
126129 MARK_NAME_JS_LOADING_VERSIONS ,
@@ -185,6 +188,13 @@ class SidebarPanels extends React.Component<Props, State> {
185188 }
186189 } ;
187190
191+ setBoxAiSidebarCacheValue = (
192+ key : 'agents' | 'encodedSession' | 'questions' | 'shouldShowLandingPage' | 'suggestedQuestions' ,
193+ value : any ,
194+ ) => {
195+ this . boxAiSidebarCache [ key ] = value ;
196+ } ;
197+
188198 getCustomSidebarRef = ( panelId : string ) : ElementRefType => {
189199 if ( ! this . customSidebars . has ( panelId ) ) {
190200 this . customSidebars . set ( panelId , React . createRef ( ) ) ;
@@ -236,27 +246,33 @@ class SidebarPanels extends React.Component<Props, State> {
236246 }
237247 }
238248
239- getPanelOrder = ( customPanels ?: Array < CustomSidebarPanel > , shouldBoxAIBeDefaultPanel : boolean ) : string [ ] => {
240- // No custom panels - return default panels
241- if ( ! customPanels || customPanels . length === 0 ) {
242- return DEFAULT_SIDEBAR_VIEWS ;
249+ getPanelOrder = (
250+ customPanels ?: Array < CustomSidebarPanel > ,
251+ shouldBoxAIBeDefaultPanel : boolean ,
252+ hasNativeBoxAISidebar : boolean ,
253+ ) : string [ ] => {
254+ const customPanelPaths = customPanels ? customPanels . map ( panel => panel . path ) : [ ] ;
255+ const boxAiCustomPanel = customPanels ? customPanels . find ( panel => panel . id === SIDEBAR_VIEW_BOXAI ) : undefined ;
256+ const boxAiPath = boxAiCustomPanel ? boxAiCustomPanel . path : null ;
257+ const nonBoxAIPaths = customPanelPaths . filter ( path => path !== boxAiPath ) ;
258+
259+ if ( hasNativeBoxAISidebar ) {
260+ return shouldBoxAIBeDefaultPanel
261+ ? [ SIDEBAR_VIEW_BOXAI , ...DEFAULT_SIDEBAR_VIEWS , ...nonBoxAIPaths ]
262+ : [ ...DEFAULT_SIDEBAR_VIEWS , SIDEBAR_VIEW_BOXAI , ...nonBoxAIPaths ] ;
243263 }
244264
245- // Separate box-ai custom panel from other custom panels
246- const boxAiCustomPanel = customPanels . find ( panel => panel . id === SIDEBAR_VIEW_BOXAI ) ;
247- const otherCustomPanels = customPanels . filter ( panel => panel . id !== SIDEBAR_VIEW_BOXAI ) ;
248- const otherCustomPanelPaths = otherCustomPanels . map ( panel => panel . path ) ;
249-
250265 if ( boxAiCustomPanel && shouldBoxAIBeDefaultPanel ) {
251- return [ boxAiCustomPanel . path , ...DEFAULT_SIDEBAR_VIEWS , ...otherCustomPanelPaths ] ;
266+ return [ boxAiCustomPanel . path , ...DEFAULT_SIDEBAR_VIEWS , ...nonBoxAIPaths ] ;
252267 }
253268
254- return [ ...DEFAULT_SIDEBAR_VIEWS , ...customPanels . map ( panel => panel . path ) ] ;
269+ return [ ...DEFAULT_SIDEBAR_VIEWS , ...customPanelPaths ] ;
255270 } ;
256271
257272 render ( ) {
258273 const {
259274 activitySidebarProps,
275+ boxAISidebarProps,
260276 customPanels,
261277 currentUser,
262278 currentUserError,
@@ -271,6 +287,7 @@ class SidebarPanels extends React.Component<Props, State> {
271287 getPreview,
272288 getViewer,
273289 hasActivity,
290+ hasNativeBoxAISidebar,
274291 hasDetails,
275292 hasDocGen,
276293 hasMetadata,
@@ -288,20 +305,25 @@ class SidebarPanels extends React.Component<Props, State> {
288305
289306 const isMetadataSidebarRedesignEnabled = isFeatureEnabled ( features , 'metadata.redesign.enabled' ) ;
290307 const isMetadataAiSuggestionsEnabled = isFeatureEnabled ( features , 'metadata.aiSuggestions.enabled' ) ;
291- const { shouldBeDefaultPanel : shouldBoxAIBeDefaultPanel } = getFeatureConfig ( features , 'boxai.sidebar' ) ;
308+ const { shouldBeDefaultPanel : shouldBoxAIBeDefaultPanel , showOnlyNavButton : showOnlyBoxAINavButton } =
309+ getFeatureConfig ( features , 'boxai.sidebar' ) ;
310+
311+ const canShowBoxAISidebarPanel = hasNativeBoxAISidebar && ! showOnlyBoxAINavButton ;
292312
293313 const hasCustomPanels = customPanels && customPanels . length > 0 ;
294314
295- // Build eligibility for custom panels
296315 const customPanelEligibility = { } ;
297316 if ( hasCustomPanels ) {
298317 // $FlowFixMe: customPanels is checked for existence in hasCustomPanels
299- customPanels . forEach ( ( { path, isDisabled } ) => {
300- customPanelEligibility [ path ] = ! isDisabled ;
318+ customPanels . forEach ( ( { id, path, isDisabled } ) => {
319+ const isBoxAICustomPanel = id === SIDEBAR_VIEW_BOXAI ;
320+ const isEligible = isBoxAICustomPanel ? ! hasNativeBoxAISidebar && ! isDisabled : ! isDisabled ;
321+ customPanelEligibility [ path ] = isEligible ;
301322 } ) ;
302323 }
303324
304325 const panelsEligibility = {
326+ [ SIDEBAR_VIEW_BOXAI ] : hasNativeBoxAISidebar ,
305327 [ SIDEBAR_VIEW_DOCGEN ] : hasDocGen ,
306328 [ SIDEBAR_VIEW_SKILLS ] : hasSkills ,
307329 [ SIDEBAR_VIEW_ACTIVITY ] : hasActivity ,
@@ -315,6 +337,7 @@ class SidebarPanels extends React.Component<Props, State> {
315337 if (
316338 ! isOpen ||
317339 ( ! hasActivity &&
340+ ! hasNativeBoxAISidebar &&
318341 ! hasDetails &&
319342 ! hasMetadata &&
320343 ! hasSkills &&
@@ -327,6 +350,30 @@ class SidebarPanels extends React.Component<Props, State> {
327350
328351 return (
329352 < Switch >
353+ { /* Native Box AI route - takes precedence when hasNativeBoxAISidebar is true */ }
354+ { canShowBoxAISidebarPanel && (
355+ < Route
356+ exact
357+ path = { `/${ SIDEBAR_VIEW_BOXAI } ` }
358+ render = { ( ) => {
359+ this . handlePanelRender ( SIDEBAR_VIEW_BOXAI ) ;
360+ return (
361+ < LoadableBoxAISidebar
362+ contentName = { file . name }
363+ elementId = { elementId }
364+ fileExtension = { file . extension }
365+ fileID = { file . id }
366+ hasSidebarInitialized = { isInitialized }
367+ ref = { this . boxAISidebar }
368+ startMarkName = { MARK_NAME_JS_LOADING_BOXAI }
369+ cache = { this . boxAiSidebarCache }
370+ setCacheValue = { this . setBoxAiSidebarCacheValue }
371+ { ...boxAISidebarProps }
372+ />
373+ ) ;
374+ } }
375+ />
376+ ) }
330377 { hasCustomPanels &&
331378 // $FlowFixMe: customPanels is checked for existence in hasCustomPanels
332379 customPanels . map ( customPanel => {
@@ -337,6 +384,11 @@ class SidebarPanels extends React.Component<Props, State> {
337384 isDisabled,
338385 } = customPanel ;
339386
387+ const isBoxAICustomPanel = customPanelId === SIDEBAR_VIEW_BOXAI ;
388+ if ( isBoxAICustomPanel && hasNativeBoxAISidebar ) {
389+ return null ;
390+ }
391+
340392 if ( isDisabled || ! CustomPanelComponent ) {
341393 return null ;
342394 }
@@ -351,7 +403,8 @@ class SidebarPanels extends React.Component<Props, State> {
351403 return CustomPanelComponent ? (
352404 < CustomPanelComponent
353405 elementId = { elementId }
354- key = { file . id }
406+ file = { file }
407+ fileId = { fileId }
355408 fileExtension = { file . extension }
356409 hasSidebarInitialized = { isInitialized }
357410 ref = { this . getCustomSidebarRef ( customPanelId ) }
@@ -524,7 +577,11 @@ class SidebarPanels extends React.Component<Props, State> {
524577 redirect = defaultPanel ;
525578 } else {
526579 // Use panel order to determine redirect
527- const panelOrder = this . getPanelOrder ( customPanels , shouldBoxAIBeDefaultPanel ) ;
580+ const panelOrder = this . getPanelOrder (
581+ customPanels ,
582+ shouldBoxAIBeDefaultPanel ,
583+ hasNativeBoxAISidebar ,
584+ ) ;
528585 const firstEligiblePanel = panelOrder . find ( panel => panelsEligibility [ panel ] ) ;
529586 if ( firstEligiblePanel ) {
530587 redirect = firstEligiblePanel ;
0 commit comments