box-ui-elements 23.4.0-beta.36 → 23.4.0-beta.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/explorer.css +1 -1
  2. package/dist/explorer.js +1 -1
  3. package/dist/preview.css +1 -1
  4. package/dist/preview.js +1 -1
  5. package/dist/sidebar.css +1 -1
  6. package/dist/sidebar.js +1 -1
  7. package/es/common/types/metadata.js.flow +5 -4
  8. package/es/common/types/metadata.js.map +1 -1
  9. package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js +43 -22
  10. package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js.map +1 -1
  11. package/es/elements/content-preview/PreviewNavigation.js +0 -2
  12. package/es/elements/content-preview/PreviewNavigation.js.flow +0 -2
  13. package/es/elements/content-preview/PreviewNavigation.js.map +1 -1
  14. package/es/elements/content-sidebar/versions/VersionsSidebarContainer.js +29 -7
  15. package/es/elements/content-sidebar/versions/VersionsSidebarContainer.js.flow +44 -5
  16. package/es/elements/content-sidebar/versions/VersionsSidebarContainer.js.map +1 -1
  17. package/es/elements/content-sidebar/withSidebarAnnotations.js +141 -35
  18. package/es/elements/content-sidebar/withSidebarAnnotations.js.flow +199 -37
  19. package/es/elements/content-sidebar/withSidebarAnnotations.js.map +1 -1
  20. package/es/features/metadata-instance-editor/CascadePolicy.js +6 -3
  21. package/es/features/metadata-instance-editor/CascadePolicy.js.flow +8 -2
  22. package/es/features/metadata-instance-editor/CascadePolicy.js.map +1 -1
  23. package/es/features/metadata-instance-editor/Instance.js +1 -0
  24. package/es/features/metadata-instance-editor/Instance.js.flow +1 -0
  25. package/es/features/metadata-instance-editor/Instance.js.map +1 -1
  26. package/es/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.d.ts +1 -1
  27. package/i18n/bn-IN.js +1 -1
  28. package/i18n/bn-IN.properties +4 -0
  29. package/i18n/da-DK.js +1 -1
  30. package/i18n/da-DK.properties +4 -0
  31. package/i18n/de-DE.js +1 -1
  32. package/i18n/de-DE.properties +4 -0
  33. package/i18n/en-AU.js +1 -1
  34. package/i18n/en-AU.properties +4 -0
  35. package/i18n/en-CA.js +1 -1
  36. package/i18n/en-CA.properties +4 -0
  37. package/i18n/en-GB.js +1 -1
  38. package/i18n/en-GB.properties +4 -0
  39. package/i18n/es-419.js +1 -1
  40. package/i18n/es-419.properties +4 -0
  41. package/i18n/es-ES.js +1 -1
  42. package/i18n/es-ES.properties +4 -0
  43. package/i18n/fi-FI.js +1 -1
  44. package/i18n/fi-FI.properties +4 -0
  45. package/i18n/fr-CA.js +1 -1
  46. package/i18n/fr-CA.properties +4 -0
  47. package/i18n/fr-FR.js +1 -1
  48. package/i18n/fr-FR.properties +4 -0
  49. package/i18n/hi-IN.js +1 -1
  50. package/i18n/hi-IN.properties +4 -0
  51. package/i18n/it-IT.js +1 -1
  52. package/i18n/it-IT.properties +4 -0
  53. package/i18n/ja-JP.js +1 -1
  54. package/i18n/ja-JP.properties +4 -0
  55. package/i18n/ko-KR.js +1 -1
  56. package/i18n/ko-KR.properties +4 -0
  57. package/i18n/nb-NO.js +1 -1
  58. package/i18n/nb-NO.properties +4 -0
  59. package/i18n/nl-NL.js +1 -1
  60. package/i18n/nl-NL.properties +4 -0
  61. package/i18n/pl-PL.js +1 -1
  62. package/i18n/pl-PL.properties +4 -0
  63. package/i18n/pt-BR.js +1 -1
  64. package/i18n/pt-BR.properties +4 -0
  65. package/i18n/ru-RU.js +1 -1
  66. package/i18n/ru-RU.properties +4 -0
  67. package/i18n/sv-SE.js +1 -1
  68. package/i18n/sv-SE.properties +4 -0
  69. package/i18n/tr-TR.js +1 -1
  70. package/i18n/tr-TR.properties +4 -0
  71. package/i18n/zh-CN.js +1 -1
  72. package/i18n/zh-CN.properties +4 -0
  73. package/i18n/zh-TW.js +1 -1
  74. package/i18n/zh-TW.properties +4 -0
  75. package/package.json +3 -3
  76. package/src/common/types/metadata.js +5 -4
  77. package/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx +47 -31
  78. package/src/elements/content-preview/PreviewNavigation.js +0 -2
  79. package/src/elements/content-preview/__tests__/PreviewNavigation.test.js +12 -12
  80. package/src/elements/content-sidebar/__tests__/withSidebarAnnotations.rtl.test.js +1152 -0
  81. package/src/elements/content-sidebar/versions/VersionsSidebarContainer.js +44 -5
  82. package/src/elements/content-sidebar/versions/__tests__/VersionsSidebarContainer.test.js +200 -43
  83. package/src/elements/content-sidebar/versions/__tests__/__snapshots__/VersionsSidebarContainer.test.js.snap +2 -2
  84. package/src/elements/content-sidebar/withSidebarAnnotations.js +199 -37
  85. package/src/features/metadata-instance-editor/CascadePolicy.js +8 -2
  86. package/src/features/metadata-instance-editor/Instance.js +1 -0
  87. package/src/features/metadata-instance-editor/__tests__/CascadePolicy.test.js +45 -0
  88. package/src/elements/content-sidebar/__tests__/withSidebarAnnotations.test.js +0 -626
@@ -10,25 +10,70 @@ import noop from 'lodash/noop';
10
10
  import { matchPath } from 'react-router-dom';
11
11
  import { FEED_ITEM_TYPE_VERSION } from '../../constants';
12
12
  import { getBadUserError } from '../../utils/error';
13
+ import { ViewType, FeedEntryType } from '../common/types/SidebarNavigation';
13
14
  export default function withSidebarAnnotations(WrappedComponent) {
14
15
  class WithSidebarAnnotations extends React.Component {
15
16
  constructor(props) {
16
17
  super(props);
17
18
  _defineProperty(this, "sidebarPanels", /*#__PURE__*/React.createRef());
19
+ _defineProperty(this, "getInternalNavigationMatch", navigation => {
20
+ if (!('activeFeedEntryType' in navigation) || navigation.activeFeedEntryType !== FeedEntryType.ANNOTATIONS || !navigation.fileVersionId) {
21
+ return null;
22
+ }
23
+
24
+ // Only include annotationId if it's defined (mirrors router behavior where missing optional params are omitted)
25
+ const params = navigation.activeFeedEntryId !== undefined ? {
26
+ fileVersionId: navigation.fileVersionId,
27
+ annotationId: navigation.activeFeedEntryId
28
+ } : {
29
+ fileVersionId: navigation.fileVersionId
30
+ };
31
+ return {
32
+ params
33
+ };
34
+ });
35
+ _defineProperty(this, "getInternalAnnotationsNavigation", (fileVersionId, annotationId) => {
36
+ if (!fileVersionId) {
37
+ return {
38
+ sidebar: ViewType.ACTIVITY
39
+ };
40
+ }
41
+ return {
42
+ sidebar: ViewType.ACTIVITY,
43
+ activeFeedEntryType: FeedEntryType.ANNOTATIONS,
44
+ activeFeedEntryId: annotationId || undefined,
45
+ fileVersionId
46
+ };
47
+ });
18
48
  _defineProperty(this, "redirectDeeplinkedAnnotation", () => {
19
49
  const {
20
50
  file,
21
51
  getAnnotationsPath,
22
52
  getAnnotationsMatchPath,
23
53
  history,
24
- location
54
+ internalSidebarNavigation,
55
+ internalSidebarNavigationHandler,
56
+ location,
57
+ routerDisabled
25
58
  } = this.props;
26
- const match = getAnnotationsMatchPath(location);
27
- const annotationId = getProp(match, 'params.annotationId');
28
59
  const currentFileVersionId = getProp(file, 'file_version.id');
29
- const fileVersionId = getProp(match, 'params.fileVersionId');
30
- if (fileVersionId && fileVersionId !== currentFileVersionId) {
31
- history.replace(getAnnotationsPath(currentFileVersionId, annotationId));
60
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
61
+ // Use internal navigation when router is disabled
62
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
63
+ const annotationId = getProp(match, 'params.annotationId');
64
+ const fileVersionId = getProp(match, 'params.fileVersionId');
65
+ if (fileVersionId && fileVersionId !== currentFileVersionId) {
66
+ const correctedNavigation = this.getInternalAnnotationsNavigation(currentFileVersionId, annotationId);
67
+ internalSidebarNavigationHandler(correctedNavigation, true);
68
+ }
69
+ } else {
70
+ // Use router-based navigation
71
+ const match = getAnnotationsMatchPath(location);
72
+ const annotationId = getProp(match, 'params.annotationId');
73
+ const fileVersionId = getProp(match, 'params.fileVersionId');
74
+ if (fileVersionId && fileVersionId !== currentFileVersionId) {
75
+ history.replace(getAnnotationsPath(currentFileVersionId, annotationId));
76
+ }
32
77
  }
33
78
  });
34
79
  _defineProperty(this, "updateActiveAnnotation", () => {
@@ -41,21 +86,38 @@ export default function withSidebarAnnotations(WrappedComponent) {
41
86
  getAnnotationsMatchPath,
42
87
  getAnnotationsPath,
43
88
  history,
44
- location
89
+ internalSidebarNavigation,
90
+ internalSidebarNavigationHandler,
91
+ location,
92
+ routerDisabled
45
93
  } = this.props;
46
- const match = getAnnotationsMatchPath(location);
47
94
  const currentFileVersionId = getProp(file, 'file_version.id');
48
95
  const defaultFileVersionId = activeAnnotationFileVersionId || currentFileVersionId;
49
- const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
50
- const newLocationState = activeAnnotationId ? {
51
- open: true
52
- } : location.state;
96
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
97
+ // Use internal navigation when router is disabled
98
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
99
+ const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
100
+ const newNavigationState = activeAnnotationId ? {
101
+ open: true
102
+ } : {};
53
103
 
54
- // Update the location pathname and open state if transitioning to an active annotation id, force the sidebar open
55
- history.push({
56
- pathname: getAnnotationsPath(fileVersionId, activeAnnotationId),
57
- state: newLocationState
58
- });
104
+ // Update the navigation and open state if transitioning to an active annotation id, force the sidebar open
105
+ const updatedNavigation = _objectSpread(_objectSpread({}, this.getInternalAnnotationsNavigation(fileVersionId, activeAnnotationId)), newNavigationState);
106
+ internalSidebarNavigationHandler(updatedNavigation);
107
+ } else {
108
+ // Use router-based navigation
109
+ const match = getAnnotationsMatchPath(location);
110
+ const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
111
+ const newLocationState = activeAnnotationId ? {
112
+ open: true
113
+ } : location.state;
114
+
115
+ // Update the location pathname and open state if transitioning to an active annotation id, force the sidebar open
116
+ history.push({
117
+ pathname: getAnnotationsPath(fileVersionId, activeAnnotationId),
118
+ state: newLocationState
119
+ });
120
+ }
59
121
  });
60
122
  _defineProperty(this, "updateActiveVersion", () => {
61
123
  const {
@@ -65,34 +127,63 @@ export default function withSidebarAnnotations(WrappedComponent) {
65
127
  getAnnotationsMatchPath,
66
128
  getAnnotationsPath,
67
129
  history,
130
+ internalSidebarNavigation,
131
+ internalSidebarNavigationHandler,
68
132
  location,
69
- onVersionChange
133
+ onVersionChange,
134
+ routerDisabled
70
135
  } = this.props;
71
136
  const feedAPI = api.getFeedAPI(false);
72
- const match = getAnnotationsMatchPath(location);
73
137
  const currentFileVersionId = getProp(file, 'file_version.id');
74
- const fileVersionId = getProp(match, 'params.fileVersionId');
75
138
  const {
76
139
  items: feedItems = []
77
140
  } = feedAPI.getCachedItems(fileId) || {};
78
- const version = feedItems.filter(item => item.type === FEED_ITEM_TYPE_VERSION).find(item => item.id === fileVersionId);
79
- if (version) {
80
- onVersionChange(version, {
81
- currentVersionId: currentFileVersionId,
82
- updateVersionToCurrent: () => history.push(getAnnotationsPath(currentFileVersionId))
83
- });
141
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
142
+ // Use internal navigation when router is disabled
143
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
144
+ const fileVersionId = getProp(match, 'params.fileVersionId');
145
+ const version = feedItems.filter(item => item.type === FEED_ITEM_TYPE_VERSION).find(item => item.id === fileVersionId);
146
+ if (version) {
147
+ onVersionChange(version, {
148
+ currentVersionId: currentFileVersionId,
149
+ updateVersionToCurrent: () => {
150
+ const currentVersionNavigation = this.getInternalAnnotationsNavigation(currentFileVersionId);
151
+ internalSidebarNavigationHandler(currentVersionNavigation);
152
+ }
153
+ });
154
+ }
155
+ } else {
156
+ // Use router-based navigation
157
+ const match = getAnnotationsMatchPath(location);
158
+ const fileVersionId = getProp(match, 'params.fileVersionId');
159
+ const version = feedItems.filter(item => item.type === FEED_ITEM_TYPE_VERSION).find(item => item.id === fileVersionId);
160
+ if (version) {
161
+ onVersionChange(version, {
162
+ currentVersionId: currentFileVersionId,
163
+ updateVersionToCurrent: () => history.push(getAnnotationsPath(currentFileVersionId))
164
+ });
165
+ }
84
166
  }
85
167
  });
86
168
  _defineProperty(this, "refreshActivitySidebar", () => {
87
169
  const {
170
+ internalSidebarNavigation,
88
171
  isOpen,
89
- location
172
+ location,
173
+ routerDisabled
90
174
  } = this.props;
91
- const pathname = getProp(location, 'pathname', '');
92
- const isActivity = matchPath(pathname, '/activity');
93
175
  const {
94
176
  current
95
177
  } = this.sidebarPanels;
178
+ let isActivity = false;
179
+ if (routerDisabled && internalSidebarNavigation) {
180
+ // Check if current navigation is pointing to activity sidebar
181
+ isActivity = internalSidebarNavigation.sidebar === ViewType.ACTIVITY;
182
+ } else {
183
+ // Use router-based check
184
+ const pathname = getProp(location, 'pathname', '');
185
+ isActivity = !!matchPath(pathname, '/activity');
186
+ }
96
187
 
97
188
  // If the activity sidebar is currently open, then force it to refresh with the updated data
98
189
  if (current && isActivity && isOpen) {
@@ -106,12 +197,15 @@ export default function withSidebarAnnotations(WrappedComponent) {
106
197
  annotatorState,
107
198
  fileId,
108
199
  getAnnotationsMatchPath,
200
+ internalSidebarNavigation,
109
201
  location,
110
- onVersionChange
202
+ onVersionChange,
203
+ routerDisabled
111
204
  } = this.props;
112
205
  const {
113
206
  annotatorState: prevAnnotatorState,
114
207
  fileId: prevFileId,
208
+ internalSidebarNavigation: prevInternalSidebarNavigation,
115
209
  location: prevLocation
116
210
  } = prevProps;
117
211
  const {
@@ -123,13 +217,25 @@ export default function withSidebarAnnotations(WrappedComponent) {
123
217
  activeAnnotationId: prevActiveAnnotationId,
124
218
  annotation: prevAnnotation
125
219
  } = prevAnnotatorState;
126
- const match = getAnnotationsMatchPath(location);
127
- const prevMatch = getAnnotationsMatchPath(prevLocation);
128
- const fileVersionId = getProp(match, 'params.fileVersionId');
129
- const hasActiveAnnotationChanged = prevActiveAnnotationId !== activeAnnotationId;
220
+ let fileVersionId;
221
+ let prevFileVersionId;
222
+ let match;
223
+ if (routerDisabled && internalSidebarNavigation) {
224
+ // Use internal navigation when router is disabled
225
+ match = this.getInternalNavigationMatch(internalSidebarNavigation);
226
+ const prevMatch = prevInternalSidebarNavigation ? this.getInternalNavigationMatch(prevInternalSidebarNavigation) : null;
227
+ fileVersionId = getProp(match, 'params.fileVersionId');
228
+ prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
229
+ } else {
230
+ // Use router-based navigation
231
+ match = getAnnotationsMatchPath(location);
232
+ const prevMatch = getAnnotationsMatchPath(prevLocation);
233
+ fileVersionId = getProp(match, 'params.fileVersionId');
234
+ prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
235
+ }
130
236
  const isAnnotationsPath = !!match;
131
237
  const isTransitioningToAnnotationPath = activeAnnotationId && !isAnnotationsPath;
132
- const prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
238
+ const hasActiveAnnotationChanged = prevActiveAnnotationId !== activeAnnotationId;
133
239
  if (action === 'reply_create_start' || action === 'reply_create_end') {
134
240
  this.addAnnotationReply();
135
241
  }
@@ -7,14 +7,23 @@ import { FEED_ITEM_TYPE_VERSION } from '../../constants';
7
7
  import { getBadUserError } from '../../utils/error';
8
8
  import type { WithAnnotatorContextProps } from '../common/annotator-context';
9
9
  import type { BoxItem, User } from '../../common/types/core';
10
+ import {
11
+ ViewType,
12
+ FeedEntryType,
13
+ type InternalSidebarNavigation,
14
+ type InternalSidebarNavigationHandler,
15
+ } from '../common/types/SidebarNavigation';
10
16
 
11
17
  type Props = {
12
18
  ...ContextRouter,
13
19
  currentUser?: User,
14
20
  file: BoxItem,
15
21
  fileId: string,
22
+ internalSidebarNavigation?: InternalSidebarNavigation,
23
+ internalSidebarNavigationHandler?: InternalSidebarNavigationHandler,
16
24
  isOpen: boolean,
17
25
  onVersionChange: Function,
26
+ routerDisabled?: boolean,
18
27
  } & WithAnnotatorContextProps;
19
28
 
20
29
  type SidebarPanelsRefType = {
@@ -44,31 +53,130 @@ export default function withSidebarAnnotations(
44
53
  this.redirectDeeplinkedAnnotation();
45
54
  }
46
55
 
56
+ getInternalNavigationMatch = (
57
+ navigation: InternalSidebarNavigation,
58
+ ): { params: { annotationId?: string, fileVersionId: string } } | null => {
59
+ if (
60
+ !('activeFeedEntryType' in navigation) ||
61
+ navigation.activeFeedEntryType !== FeedEntryType.ANNOTATIONS ||
62
+ !navigation.fileVersionId
63
+ ) {
64
+ return null;
65
+ }
66
+
67
+ // Only include annotationId if it's defined (mirrors router behavior where missing optional params are omitted)
68
+ const params =
69
+ navigation.activeFeedEntryId !== undefined
70
+ ? {
71
+ fileVersionId: navigation.fileVersionId,
72
+ annotationId: navigation.activeFeedEntryId,
73
+ }
74
+ : {
75
+ fileVersionId: navigation.fileVersionId,
76
+ };
77
+
78
+ return { params };
79
+ };
80
+
81
+ getInternalAnnotationsNavigation = (
82
+ fileVersionId?: string,
83
+ annotationId?: string | null,
84
+ ): InternalSidebarNavigation => {
85
+ if (!fileVersionId) {
86
+ return { sidebar: ViewType.ACTIVITY };
87
+ }
88
+
89
+ return {
90
+ sidebar: ViewType.ACTIVITY,
91
+ activeFeedEntryType: FeedEntryType.ANNOTATIONS,
92
+ activeFeedEntryId: annotationId || undefined,
93
+ fileVersionId,
94
+ };
95
+ };
96
+
47
97
  redirectDeeplinkedAnnotation = () => {
48
- const { file, getAnnotationsPath, getAnnotationsMatchPath, history, location } = this.props;
49
- const match = getAnnotationsMatchPath(location);
50
- const annotationId = getProp(match, 'params.annotationId');
98
+ const {
99
+ file,
100
+ getAnnotationsPath,
101
+ getAnnotationsMatchPath,
102
+ history,
103
+ internalSidebarNavigation,
104
+ internalSidebarNavigationHandler,
105
+ location,
106
+ routerDisabled,
107
+ } = this.props;
108
+
51
109
  const currentFileVersionId = getProp(file, 'file_version.id');
52
- const fileVersionId = getProp(match, 'params.fileVersionId');
53
110
 
54
- if (fileVersionId && fileVersionId !== currentFileVersionId) {
55
- history.replace(getAnnotationsPath(currentFileVersionId, annotationId));
111
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
112
+ // Use internal navigation when router is disabled
113
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
114
+ const annotationId = getProp(match, 'params.annotationId');
115
+ const fileVersionId = getProp(match, 'params.fileVersionId');
116
+
117
+ if (fileVersionId && fileVersionId !== currentFileVersionId) {
118
+ const correctedNavigation = this.getInternalAnnotationsNavigation(
119
+ currentFileVersionId,
120
+ annotationId,
121
+ );
122
+ internalSidebarNavigationHandler(correctedNavigation, true);
123
+ }
124
+ } else {
125
+ // Use router-based navigation
126
+ const match = getAnnotationsMatchPath(location);
127
+ const annotationId = getProp(match, 'params.annotationId');
128
+ const fileVersionId = getProp(match, 'params.fileVersionId');
129
+
130
+ if (fileVersionId && fileVersionId !== currentFileVersionId) {
131
+ history.replace(getAnnotationsPath(currentFileVersionId, annotationId));
132
+ }
56
133
  }
57
134
  };
58
135
 
59
136
  componentDidUpdate(prevProps: Props) {
60
- const { annotatorState, fileId, getAnnotationsMatchPath, location, onVersionChange }: Props = this.props;
61
- const { annotatorState: prevAnnotatorState, fileId: prevFileId, location: prevLocation }: Props = prevProps;
137
+ const {
138
+ annotatorState,
139
+ fileId,
140
+ getAnnotationsMatchPath,
141
+ internalSidebarNavigation,
142
+ location,
143
+ onVersionChange,
144
+ routerDisabled,
145
+ }: Props = this.props;
146
+ const {
147
+ annotatorState: prevAnnotatorState,
148
+ fileId: prevFileId,
149
+ internalSidebarNavigation: prevInternalSidebarNavigation,
150
+ location: prevLocation,
151
+ }: Props = prevProps;
62
152
  const { action, activeAnnotationId, annotation } = annotatorState;
63
153
  const { activeAnnotationId: prevActiveAnnotationId, annotation: prevAnnotation } = prevAnnotatorState;
64
154
 
65
- const match = getAnnotationsMatchPath(location);
66
- const prevMatch = getAnnotationsMatchPath(prevLocation);
67
- const fileVersionId = getProp(match, 'params.fileVersionId');
68
- const hasActiveAnnotationChanged = prevActiveAnnotationId !== activeAnnotationId;
155
+ let fileVersionId;
156
+ let prevFileVersionId;
157
+ let match;
158
+
159
+ if (routerDisabled && internalSidebarNavigation) {
160
+ // Use internal navigation when router is disabled
161
+ match = this.getInternalNavigationMatch(internalSidebarNavigation);
162
+ const prevMatch = prevInternalSidebarNavigation
163
+ ? this.getInternalNavigationMatch(prevInternalSidebarNavigation)
164
+ : null;
165
+
166
+ fileVersionId = getProp(match, 'params.fileVersionId');
167
+ prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
168
+ } else {
169
+ // Use router-based navigation
170
+ match = getAnnotationsMatchPath(location);
171
+ const prevMatch = getAnnotationsMatchPath(prevLocation);
172
+
173
+ fileVersionId = getProp(match, 'params.fileVersionId');
174
+ prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
175
+ }
176
+
69
177
  const isAnnotationsPath = !!match;
70
178
  const isTransitioningToAnnotationPath = activeAnnotationId && !isAnnotationsPath;
71
- const prevFileVersionId = getProp(prevMatch, 'params.fileVersionId');
179
+ const hasActiveAnnotationChanged = prevActiveAnnotationId !== activeAnnotationId;
72
180
 
73
181
  if (action === 'reply_create_start' || action === 'reply_create_end') {
74
182
  this.addAnnotationReply();
@@ -275,19 +383,39 @@ export default function withSidebarAnnotations(
275
383
  getAnnotationsMatchPath,
276
384
  getAnnotationsPath,
277
385
  history,
386
+ internalSidebarNavigation,
387
+ internalSidebarNavigationHandler,
278
388
  location,
389
+ routerDisabled,
279
390
  } = this.props;
280
- const match = getAnnotationsMatchPath(location);
391
+
281
392
  const currentFileVersionId = getProp(file, 'file_version.id');
282
393
  const defaultFileVersionId = activeAnnotationFileVersionId || currentFileVersionId;
283
- const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
284
- const newLocationState = activeAnnotationId ? { open: true } : location.state;
285
-
286
- // Update the location pathname and open state if transitioning to an active annotation id, force the sidebar open
287
- history.push({
288
- pathname: getAnnotationsPath(fileVersionId, activeAnnotationId),
289
- state: newLocationState,
290
- });
394
+
395
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
396
+ // Use internal navigation when router is disabled
397
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
398
+ const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
399
+ const newNavigationState = activeAnnotationId ? { open: true } : {};
400
+
401
+ // Update the navigation and open state if transitioning to an active annotation id, force the sidebar open
402
+ const updatedNavigation = {
403
+ ...this.getInternalAnnotationsNavigation(fileVersionId, activeAnnotationId),
404
+ ...newNavigationState,
405
+ };
406
+ internalSidebarNavigationHandler(updatedNavigation);
407
+ } else {
408
+ // Use router-based navigation
409
+ const match = getAnnotationsMatchPath(location);
410
+ const fileVersionId = getProp(match, 'params.fileVersionId', defaultFileVersionId);
411
+ const newLocationState = activeAnnotationId ? { open: true } : location.state;
412
+
413
+ // Update the location pathname and open state if transitioning to an active annotation id, force the sidebar open
414
+ history.push({
415
+ pathname: getAnnotationsPath(fileVersionId, activeAnnotationId),
416
+ state: newLocationState,
417
+ });
418
+ }
291
419
  };
292
420
 
293
421
  updateActiveVersion = () => {
@@ -298,33 +426,67 @@ export default function withSidebarAnnotations(
298
426
  getAnnotationsMatchPath,
299
427
  getAnnotationsPath,
300
428
  history,
429
+ internalSidebarNavigation,
430
+ internalSidebarNavigationHandler,
301
431
  location,
302
432
  onVersionChange,
433
+ routerDisabled,
303
434
  } = this.props;
435
+
304
436
  const feedAPI = api.getFeedAPI(false);
305
- const match = getAnnotationsMatchPath(location);
306
437
  const currentFileVersionId = getProp(file, 'file_version.id');
307
- const fileVersionId = getProp(match, 'params.fileVersionId');
308
438
  const { items: feedItems = [] } = feedAPI.getCachedItems(fileId) || {};
309
- const version = feedItems
310
- .filter(item => item.type === FEED_ITEM_TYPE_VERSION)
311
- .find(item => item.id === fileVersionId);
312
-
313
- if (version) {
314
- onVersionChange(version, {
315
- currentVersionId: currentFileVersionId,
316
- updateVersionToCurrent: () => history.push(getAnnotationsPath(currentFileVersionId)),
317
- });
439
+
440
+ if (routerDisabled && internalSidebarNavigation && internalSidebarNavigationHandler) {
441
+ // Use internal navigation when router is disabled
442
+ const match = this.getInternalNavigationMatch(internalSidebarNavigation);
443
+ const fileVersionId = getProp(match, 'params.fileVersionId');
444
+ const version = feedItems
445
+ .filter(item => item.type === FEED_ITEM_TYPE_VERSION)
446
+ .find(item => item.id === fileVersionId);
447
+
448
+ if (version) {
449
+ onVersionChange(version, {
450
+ currentVersionId: currentFileVersionId,
451
+ updateVersionToCurrent: () => {
452
+ const currentVersionNavigation =
453
+ this.getInternalAnnotationsNavigation(currentFileVersionId);
454
+ internalSidebarNavigationHandler(currentVersionNavigation);
455
+ },
456
+ });
457
+ }
458
+ } else {
459
+ // Use router-based navigation
460
+ const match = getAnnotationsMatchPath(location);
461
+ const fileVersionId = getProp(match, 'params.fileVersionId');
462
+ const version = feedItems
463
+ .filter(item => item.type === FEED_ITEM_TYPE_VERSION)
464
+ .find(item => item.id === fileVersionId);
465
+
466
+ if (version) {
467
+ onVersionChange(version, {
468
+ currentVersionId: currentFileVersionId,
469
+ updateVersionToCurrent: () => history.push(getAnnotationsPath(currentFileVersionId)),
470
+ });
471
+ }
318
472
  }
319
473
  };
320
474
 
321
475
  refreshActivitySidebar = () => {
322
- const { isOpen, location } = this.props;
323
-
324
- const pathname = getProp(location, 'pathname', '');
325
- const isActivity = matchPath(pathname, '/activity');
476
+ const { internalSidebarNavigation, isOpen, location, routerDisabled } = this.props;
326
477
  const { current } = this.sidebarPanels;
327
478
 
479
+ let isActivity = false;
480
+
481
+ if (routerDisabled && internalSidebarNavigation) {
482
+ // Check if current navigation is pointing to activity sidebar
483
+ isActivity = internalSidebarNavigation.sidebar === ViewType.ACTIVITY;
484
+ } else {
485
+ // Use router-based check
486
+ const pathname = getProp(location, 'pathname', '');
487
+ isActivity = !!matchPath(pathname, '/activity');
488
+ }
489
+
328
490
  // If the activity sidebar is currently open, then force it to refresh with the updated data
329
491
  if (current && isActivity && isOpen) {
330
492
  current.refresh(false);