@finos/legend-application-studio 28.19.72 → 28.19.74

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 (22) hide show
  1. package/lib/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.d.ts.map +1 -1
  2. package/lib/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.js +26 -338
  3. package/lib/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.js.map +1 -1
  4. package/lib/index.css +2 -2
  5. package/lib/index.css.map +1 -1
  6. package/lib/package.json +1 -1
  7. package/lib/stores/editor/EditorGraphState.d.ts.map +1 -1
  8. package/lib/stores/editor/EditorGraphState.js +1 -7
  9. package/lib/stores/editor/EditorGraphState.js.map +1 -1
  10. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.d.ts +0 -2
  11. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.d.ts.map +1 -1
  12. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js +0 -19
  13. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js.map +1 -1
  14. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.d.ts +1 -16
  15. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.d.ts.map +1 -1
  16. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.js +1 -112
  17. package/lib/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.js.map +1 -1
  18. package/package.json +5 -5
  19. package/src/components/editor/editor-group/project-configuration-editor/ProjectDependencyEditor.tsx +53 -599
  20. package/src/stores/editor/EditorGraphState.ts +4 -11
  21. package/src/stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.ts +0 -26
  22. package/src/stores/editor/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.ts +1 -178
@@ -61,10 +61,7 @@ import {
61
61
  type StoreProjectData,
62
62
  SNAPSHOT_VERSION_ALIAS,
63
63
  } from '@finos/legend-server-depot';
64
- import {
65
- type ProjectDependency,
66
- type ProjectDependencyExclusion,
67
- } from '@finos/legend-server-sdlc';
64
+ import type { ProjectDependency } from '@finos/legend-server-sdlc';
68
65
  import {
69
66
  ActionState,
70
67
  assertErrorThrown,
@@ -77,7 +74,7 @@ import {
77
74
  import { generateGAVCoordinates } from '@finos/legend-storage';
78
75
  import { flowResult } from 'mobx';
79
76
  import { observer } from 'mobx-react-lite';
80
- import { forwardRef, useCallback, useEffect, useRef, useState } from 'react';
77
+ import { forwardRef, useEffect, useRef, useState } from 'react';
81
78
  import { ProjectConfigurationEditorState } from '../../../../stores/editor/editor-state/project-configuration-editor-state/ProjectConfigurationEditorState.js';
82
79
  import {
83
80
  type ProjectDependencyConflictTreeNodeData,
@@ -253,117 +250,9 @@ const DependencyTreeNodeContainer: React.FC<
253
250
  >
254
251
  > = (props) => {
255
252
  const { node, level, stepPaddingInRem, onNodeSelect } = props;
256
- const editorStore = useEditorStore();
257
- const dependencyEditorState =
258
- editorStore.projectConfigurationEditorState.projectDependencyEditorState;
259
-
260
253
  const isExpandable = Boolean(node.childrenIds?.length);
261
254
  const selectNode = (): void => onNodeSelect?.(node);
262
255
  const value = node.value;
263
-
264
- const isExcluded = (): boolean => {
265
- const coordinate = generateGAVCoordinates(
266
- value.groupId,
267
- value.artifactId,
268
- undefined,
269
- );
270
-
271
- const treeData = dependencyEditorState.dependencyTreeData;
272
- if (!treeData) {
273
- return false;
274
- }
275
-
276
- const findRootNodeForCurrentNode = (nodeId: string): string | null => {
277
- if (treeData.rootIds.indexOf(nodeId) !== -1) {
278
- return nodeId;
279
- }
280
-
281
- const findInSubtree = (rootId: string, searchId: string): boolean => {
282
- const rootNode = treeData.nodes.get(rootId);
283
- if (!rootNode) {
284
- return false;
285
- }
286
- const visited: { [key: string]: boolean } = {};
287
- const queue = [rootId];
288
-
289
- while (queue.length > 0) {
290
- const currentId = queue.shift();
291
- if (!currentId || visited[currentId]) {
292
- continue;
293
- }
294
-
295
- visited[currentId] = true;
296
-
297
- if (currentId === searchId) {
298
- return true;
299
- }
300
-
301
- const currentNode = treeData.nodes.get(currentId);
302
- if (currentNode?.childrenIds) {
303
- for (let i = 0; i < currentNode.childrenIds.length; i++) {
304
- queue.push(guaranteeNonNullable(currentNode.childrenIds[i]));
305
- }
306
- }
307
- }
308
- return false;
309
- };
310
-
311
- for (let i = 0; i < treeData.rootIds.length; i++) {
312
- const rootId = guaranteeNonNullable(treeData.rootIds[i]);
313
- if (findInSubtree(rootId, nodeId)) {
314
- return rootId;
315
- }
316
- }
317
-
318
- return null;
319
- };
320
-
321
- const rootNodeId = findRootNodeForCurrentNode(node.id);
322
- if (!rootNodeId) {
323
- return false;
324
- }
325
-
326
- const rootNode = treeData.nodes.get(rootNodeId);
327
- if (!rootNode) {
328
- return false;
329
- }
330
-
331
- const currentProjectConfiguration =
332
- editorStore.projectConfigurationEditorState.currentProjectConfiguration;
333
- const rootCoordinate = `${rootNode.value.groupId}:${rootNode.value.artifactId}`;
334
-
335
- for (
336
- let i = 0;
337
- i < currentProjectConfiguration.projectDependencies.length;
338
- i++
339
- ) {
340
- const projectDep = guaranteeNonNullable(
341
- currentProjectConfiguration.projectDependencies[i],
342
- );
343
- const projectDepCoordinate = generateGAVCoordinates(
344
- guaranteeNonNullable(projectDep.groupId),
345
- guaranteeNonNullable(projectDep.artifactId),
346
- undefined,
347
- );
348
-
349
- if (projectDepCoordinate === rootCoordinate) {
350
- const exclusions = dependencyEditorState.getExclusions(
351
- projectDep.projectId,
352
- );
353
-
354
- for (let j = 0; j < exclusions.length; j++) {
355
- if (guaranteeNonNullable(exclusions[j]).coordinate === coordinate) {
356
- return true;
357
- }
358
- }
359
- break;
360
- }
361
- }
362
-
363
- return false;
364
- };
365
-
366
- const nodeIsExcluded = isExcluded();
367
256
  const nodeExpandIcon = isExpandable ? (
368
257
  node.isOpen ? (
369
258
  <ChevronDownIcon />
@@ -388,10 +277,6 @@ const DependencyTreeNodeContainer: React.FC<
388
277
  'project-dependency-explorer-tree__node__container--selected':
389
278
  node.isSelected,
390
279
  },
391
- {
392
- 'project-dependency-explorer-tree__node__container--excluded':
393
- nodeIsExcluded,
394
- },
395
280
  )}
396
281
  style={{
397
282
  paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 1)}rem`,
@@ -404,27 +289,15 @@ const DependencyTreeNodeContainer: React.FC<
404
289
  </div>
405
290
  </div>
406
291
  <button
407
- className={clsx(
408
- 'tree-view__node__label project-dependency-explorer-tree__node__label',
409
- {
410
- 'project-dependency-explorer-tree__node__label--excluded':
411
- nodeIsExcluded,
412
- },
413
- )}
292
+ className="tree-view__node__label project-dependency-explorer-tree__node__label"
414
293
  tabIndex={-1}
415
- title={nodeIsExcluded ? `${value.id} (EXCLUDED)` : value.id}
294
+ title={value.id}
416
295
  >
417
296
  {value.artifactId}
418
297
  </button>
419
298
  <div className="project-dependency-explorer-tree__node__version">
420
299
  <button
421
- className={clsx(
422
- 'project-dependency-explorer-tree__node__version-btn',
423
- {
424
- 'project-dependency-explorer-tree__node__version-btn--excluded':
425
- nodeIsExcluded,
426
- },
427
- )}
300
+ className="project-dependency-explorer-tree__node__version-btn"
428
301
  title={value.versionId}
429
302
  tabIndex={-1}
430
303
  >
@@ -491,114 +364,8 @@ const ConflictTreeNodeContainer: React.FC<
491
364
  >
492
365
  > = (props) => {
493
366
  const { node, level, stepPaddingInRem, onNodeSelect } = props;
494
- const editorStore = useEditorStore();
495
- const dependencyEditorState =
496
- editorStore.projectConfigurationEditorState.projectDependencyEditorState;
497
-
498
367
  const isExpandable = Boolean(node.childrenIds?.length);
499
368
  const selectNode = (): void => onNodeSelect?.(node);
500
-
501
- const isExcluded = (): boolean => {
502
- if (!(node instanceof ProjectDependencyTreeNodeData)) {
503
- return false;
504
- }
505
-
506
- const value = node.value;
507
- const coordinate = `${value.groupId}:${value.artifactId}`;
508
-
509
- const treeData = dependencyEditorState.dependencyTreeData;
510
- if (!treeData) {
511
- return false;
512
- }
513
-
514
- const findRootNodeForCurrentNode = (nodeId: string): string | null => {
515
- if (treeData.rootIds.indexOf(nodeId) !== -1) {
516
- return nodeId;
517
- }
518
-
519
- const findInSubtree = (rootId: string, searchId: string): boolean => {
520
- const rootNode = treeData.nodes.get(rootId);
521
- if (!rootNode) {
522
- return false;
523
- }
524
- const visited: { [key: string]: boolean } = {};
525
- const queue = [rootId];
526
-
527
- while (queue.length > 0) {
528
- const currentId = queue.shift();
529
- if (!currentId || visited[currentId]) {
530
- continue;
531
- }
532
- visited[currentId] = true;
533
-
534
- if (currentId === searchId) {
535
- return true;
536
- }
537
-
538
- const currentNode = treeData.nodes.get(currentId);
539
- if (currentNode?.childrenIds) {
540
- for (let i = 0; i < currentNode.childrenIds.length; i++) {
541
- queue.push(guaranteeNonNullable(currentNode.childrenIds[i]));
542
- }
543
- }
544
- }
545
- return false;
546
- };
547
-
548
- for (let i = 0; i < treeData.rootIds.length; i++) {
549
- const rootId = guaranteeNonNullable(treeData.rootIds[i]);
550
- if (findInSubtree(rootId, nodeId)) {
551
- return rootId;
552
- }
553
- }
554
-
555
- return null;
556
- };
557
-
558
- const rootNodeId = findRootNodeForCurrentNode(node.id);
559
- if (!rootNodeId) {
560
- return false;
561
- }
562
-
563
- const rootNode = treeData.nodes.get(rootNodeId);
564
- if (!rootNode) {
565
- return false;
566
- }
567
-
568
- const currentProjectConfiguration =
569
- editorStore.projectConfigurationEditorState.currentProjectConfiguration;
570
- const rootCoordinate = `${rootNode.value.groupId}:${rootNode.value.artifactId}`;
571
-
572
- for (
573
- let i = 0;
574
- i < currentProjectConfiguration.projectDependencies.length;
575
- i++
576
- ) {
577
- const projectDep = guaranteeNonNullable(
578
- currentProjectConfiguration.projectDependencies[i],
579
- );
580
- const projectDepCoordinate = generateGAVCoordinates(
581
- guaranteeNonNullable(projectDep.groupId),
582
- guaranteeNonNullable(projectDep.artifactId),
583
- undefined,
584
- );
585
-
586
- if (projectDepCoordinate === rootCoordinate) {
587
- const exclusions = dependencyEditorState.getExclusions(
588
- projectDep.projectId,
589
- );
590
-
591
- for (let j = 0; j < exclusions.length; j++) {
592
- if (guaranteeNonNullable(exclusions[j]).coordinate === coordinate) {
593
- return true;
594
- }
595
- }
596
- break;
597
- }
598
- }
599
-
600
- return false;
601
- };
602
369
  const nodeExpandIcon = isExpandable ? (
603
370
  node.isOpen ? (
604
371
  <ChevronDownIcon />
@@ -623,10 +390,6 @@ const ConflictTreeNodeContainer: React.FC<
623
390
  'project-dependency-explorer-tree__node__container--selected':
624
391
  node.isSelected,
625
392
  },
626
- {
627
- 'project-dependency-explorer-tree__node__container--excluded':
628
- isExcluded(),
629
- },
630
393
  )}
631
394
  style={{
632
395
  paddingLeft: `${(level - 1) * (stepPaddingInRem ?? 1)}rem`,
@@ -658,35 +421,17 @@ const ConflictTreeNodeContainer: React.FC<
658
421
  )}
659
422
  </div>
660
423
  <button
661
- className={clsx(
662
- 'tree-view__node__label project-dependency-explorer-tree__node__label',
663
- {
664
- 'project-dependency-explorer-tree__node__label--excluded':
665
- isExcluded(),
666
- },
667
- )}
424
+ className="tree-view__node__label project-dependency-explorer-tree__node__label"
668
425
  tabIndex={-1}
669
- title={
670
- isExcluded() ? `${node.description} (EXCLUDED)` : node.description
671
- }
426
+ title={node.description}
672
427
  >
673
428
  {node.label}
674
429
  </button>
675
430
  {node instanceof ProjectDependencyTreeNodeData && (
676
431
  <div className="project-dependency-explorer-tree__node__version">
677
432
  <button
678
- className={clsx(
679
- 'project-dependency-explorer-tree__node__version-btn',
680
- {
681
- 'project-dependency-explorer-tree__node__version-btn--excluded':
682
- isExcluded(),
683
- },
684
- )}
685
- title={
686
- isExcluded()
687
- ? `${node.value.versionId} (EXCLUDED)`
688
- : node.value.versionId
689
- }
433
+ className="project-dependency-explorer-tree__node__version-btn"
434
+ title={node.value.versionId}
690
435
  tabIndex={-1}
691
436
  >
692
437
  {node.value.versionId}
@@ -1002,267 +747,6 @@ const ProjectDependencyReportModal = observer(
1002
747
  },
1003
748
  );
1004
749
 
1005
- interface TransitiveDependencyOption {
1006
- label: string;
1007
- value: string;
1008
- groupId: string;
1009
- artifactId: string;
1010
- }
1011
-
1012
- const ProjectDependencyInlineExclusionsSelector = observer(
1013
- (props: { projectDependency: ProjectDependency; isReadOnly: boolean }) => {
1014
- const { projectDependency, isReadOnly } = props;
1015
- const editorStore = useEditorStore();
1016
- const applicationStore = useApplicationStore();
1017
- const dependencyEditorState =
1018
- editorStore.projectConfigurationEditorState.projectDependencyEditorState;
1019
- const [selectedTransitiveDependency, setSelectedTransitiveDependency] =
1020
- useState<TransitiveDependencyOption | null>(null);
1021
- const [transitiveDependencyOptions, setTransitiveDependencyOptions] =
1022
- useState<TransitiveDependencyOption[]>([]);
1023
-
1024
- const getTransitiveDependencies =
1025
- useCallback((): TransitiveDependencyOption[] => {
1026
- const dependencyReport = dependencyEditorState.dependencyReport;
1027
- if (!dependencyReport?.graph) {
1028
- return [];
1029
- }
1030
-
1031
- const transitiveDeps: { [key: string]: TransitiveDependencyOption } =
1032
- {};
1033
- const existingExclusionCoordinates =
1034
- dependencyEditorState.getExclusionCoordinates(
1035
- projectDependency.projectId,
1036
- );
1037
-
1038
- const visitedNodes: { [key: string]: boolean } = {};
1039
- const traverseNode = (nodeId: string) => {
1040
- if (visitedNodes[nodeId]) {
1041
- return;
1042
- }
1043
- visitedNodes[nodeId] = true;
1044
-
1045
- const node = dependencyReport.graph.nodes.get(nodeId);
1046
- if (node?.dependencies) {
1047
- for (let i = 0; i < node.dependencies.length; i++) {
1048
- const dep = node.dependencies[i];
1049
- if (!dep?.groupId || !dep.artifactId) {
1050
- continue;
1051
- }
1052
- const coordinate = generateGAVCoordinates(
1053
- dep.groupId,
1054
- dep.artifactId,
1055
- undefined,
1056
- );
1057
-
1058
- if (
1059
- existingExclusionCoordinates.indexOf(coordinate) === -1 &&
1060
- coordinate !==
1061
- `${projectDependency.groupId}:${projectDependency.artifactId}`
1062
- ) {
1063
- transitiveDeps[coordinate] = {
1064
- label: generateGAVCoordinates(
1065
- dep.groupId,
1066
- dep.artifactId,
1067
- undefined,
1068
- ),
1069
- value: coordinate,
1070
- groupId: dep.groupId,
1071
- artifactId: dep.artifactId,
1072
- };
1073
- }
1074
-
1075
- traverseNode(dep.id);
1076
- }
1077
- }
1078
- };
1079
-
1080
- const rootNodeId = generateGAVCoordinates(
1081
- guaranteeNonNullable(projectDependency.groupId),
1082
- guaranteeNonNullable(projectDependency.artifactId),
1083
- guaranteeNonNullable(projectDependency.versionId),
1084
- );
1085
- traverseNode(rootNodeId);
1086
-
1087
- const transitiveDepsArray: TransitiveDependencyOption[] = [];
1088
- for (const coordinate in transitiveDeps) {
1089
- if (
1090
- Object.prototype.hasOwnProperty.call(transitiveDeps, coordinate)
1091
- ) {
1092
- if (!transitiveDeps[coordinate]) {
1093
- continue;
1094
- } else {
1095
- transitiveDepsArray.push(transitiveDeps[coordinate]);
1096
- }
1097
- }
1098
- }
1099
-
1100
- return transitiveDepsArray.sort((a, b) =>
1101
- a.label.localeCompare(b.label),
1102
- );
1103
- }, [
1104
- dependencyEditorState,
1105
- projectDependency.projectId,
1106
- projectDependency.groupId,
1107
- projectDependency.artifactId,
1108
- projectDependency.versionId,
1109
- ]);
1110
-
1111
- useEffect(() => {
1112
- setTransitiveDependencyOptions(getTransitiveDependencies());
1113
- }, [
1114
- dependencyEditorState.dependencyReport,
1115
- projectDependency.projectId,
1116
- getTransitiveDependencies,
1117
- ]);
1118
-
1119
- const addExclusionFromDropdown = (
1120
- option: TransitiveDependencyOption | null,
1121
- ): void => {
1122
- if (!option) {
1123
- return;
1124
- }
1125
-
1126
- try {
1127
- dependencyEditorState.addExclusionByCoordinate(
1128
- projectDependency.projectId,
1129
- option.value,
1130
- );
1131
- setSelectedTransitiveDependency(null);
1132
- setTransitiveDependencyOptions(getTransitiveDependencies());
1133
- flowResult(dependencyEditorState.fetchDependencyReport())
1134
- .then(() => {
1135
- setTransitiveDependencyOptions(getTransitiveDependencies());
1136
- })
1137
- .catch(applicationStore.alertUnhandledError);
1138
-
1139
- applicationStore.notificationService.notifySuccess(
1140
- `Exclusion added: ${option.value}`,
1141
- );
1142
- } catch (error) {
1143
- assertErrorThrown(error);
1144
- applicationStore.notificationService.notifyError(
1145
- `Failed to add exclusion: ${error.message}`,
1146
- );
1147
- }
1148
- };
1149
-
1150
- if (isReadOnly) {
1151
- return null;
1152
- }
1153
-
1154
- return (
1155
- <div className="project-dependency-exclusions-selector">
1156
- <CustomSelectorInput
1157
- className="project-dependency-exclusions-selector__dropdown"
1158
- placeholder="Add exclusion..."
1159
- options={transitiveDependencyOptions}
1160
- onChange={addExclusionFromDropdown}
1161
- value={selectedTransitiveDependency}
1162
- isClearable={true}
1163
- escapeClearsValue={true}
1164
- disabled={transitiveDependencyOptions.length === 0}
1165
- darkMode={
1166
- !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
1167
- }
1168
- />
1169
- </div>
1170
- );
1171
- },
1172
- );
1173
-
1174
- const ProjectDependencyExclusionsList = observer(
1175
- (props: { projectDependency: ProjectDependency; isReadOnly: boolean }) => {
1176
- const { projectDependency, isReadOnly } = props;
1177
- const editorStore = useEditorStore();
1178
- const applicationStore = useApplicationStore();
1179
- const dependencyEditorState =
1180
- editorStore.projectConfigurationEditorState.projectDependencyEditorState;
1181
- const [, setForceUpdate] = useState(0);
1182
- const exclusions = dependencyEditorState.getExclusions(
1183
- projectDependency.projectId,
1184
- );
1185
-
1186
- useEffect(() => {
1187
- setForceUpdate((prev) => prev + 1);
1188
- }, [
1189
- dependencyEditorState.dependencyReport,
1190
- projectDependency.projectId,
1191
- dependencyEditorState,
1192
- ]);
1193
-
1194
- useEffect(() => {
1195
- const interval = setInterval(() => {
1196
- const currentExclusions = dependencyEditorState.getExclusions(
1197
- projectDependency.projectId,
1198
- );
1199
- if (currentExclusions.length !== exclusions.length) {
1200
- setForceUpdate((prev) => prev + 1);
1201
- }
1202
- }, 1000);
1203
-
1204
- return () => clearInterval(interval);
1205
- }, [exclusions.length, dependencyEditorState, projectDependency.projectId]);
1206
-
1207
- const removeExclusion = (exclusion: ProjectDependencyExclusion): void => {
1208
- try {
1209
- dependencyEditorState.removeExclusion(
1210
- projectDependency.projectId,
1211
- exclusion,
1212
- );
1213
-
1214
- flowResult(dependencyEditorState.fetchDependencyReport()).catch(
1215
- applicationStore.alertUnhandledError,
1216
- );
1217
-
1218
- applicationStore.notificationService.notifySuccess(
1219
- `Exclusion removed: ${exclusion.coordinate}`,
1220
- );
1221
- } catch (error) {
1222
- assertErrorThrown(error);
1223
- applicationStore.notificationService.notifyError(
1224
- `Failed to remove exclusion: ${error.message}`,
1225
- );
1226
- }
1227
- };
1228
-
1229
- if (exclusions.length === 0) {
1230
- return null;
1231
- }
1232
-
1233
- return (
1234
- <div className="project-dependency-exclusions-list">
1235
- <div className="project-dependency-exclusions-list__header">
1236
- <div className="project-dependency-exclusions-list__title">
1237
- Exclusions ({exclusions.length})
1238
- </div>
1239
- </div>
1240
- <div className="project-dependency-exclusions-list__items">
1241
- {exclusions.map((exclusion) => (
1242
- <div
1243
- key={exclusion.coordinate}
1244
- className="project-dependency-exclusions-list__item"
1245
- >
1246
- <div className="project-dependency-exclusions-list__item__coordinate">
1247
- {exclusion.coordinate}
1248
- </div>
1249
- {!isReadOnly && (
1250
- <button
1251
- className="project-dependency-exclusions-list__item__remove-btn btn--dark btn--caution"
1252
- onClick={() => removeExclusion(exclusion)}
1253
- title="Remove exclusion"
1254
- >
1255
- <TimesIcon />
1256
- </button>
1257
- )}
1258
- </div>
1259
- ))}
1260
- </div>
1261
- </div>
1262
- );
1263
- },
1264
- );
1265
-
1266
750
  const ProjectVersionDependencyEditor = observer(
1267
751
  (props: {
1268
752
  projectDependency: ProjectDependency;
@@ -1270,6 +754,7 @@ const ProjectVersionDependencyEditor = observer(
1270
754
  isReadOnly: boolean;
1271
755
  projects: Map<string, StoreProjectData>;
1272
756
  }) => {
757
+ // init
1273
758
  const { projectDependency, deleteValue, isReadOnly, projects } = props;
1274
759
  const projectDependencyData = projects.get(projectDependency.projectId);
1275
760
  const editorStore = useEditorStore();
@@ -1291,14 +776,12 @@ const ProjectVersionDependencyEditor = observer(
1291
776
  const projectDisabled =
1292
777
  !configState.associatedProjectsAndVersionsFetched ||
1293
778
  configState.isReadOnly;
1294
- const projectsArray: StoreProjectData[] = [];
1295
- configState.projects.forEach((project: StoreProjectData) => {
1296
- projectsArray.push(project);
1297
- });
1298
- const projectsOptions = projectsArray
779
+ const projectsOptions = Array.from(configState.projects.values())
1299
780
  .map(buildProjectOption)
1300
781
  .sort(compareLabelFn);
1301
- const onProjectSelectionChange = (val: ProjectOption | null): void => {
782
+ const onProjectSelectionChange = async (
783
+ val: ProjectOption | null,
784
+ ): Promise<void> => {
1302
785
  if (
1303
786
  (val !== null || selectedProjectOption !== null) &&
1304
787
  (!val ||
@@ -1310,36 +793,26 @@ const ProjectVersionDependencyEditor = observer(
1310
793
  if (val) {
1311
794
  try {
1312
795
  fetchSelectedProjectVersionsStatus.inProgress();
1313
- editorStore.depotServerClient
1314
- .getVersions(
1315
- guaranteeNonNullable(projectDependency.groupId),
1316
- guaranteeNonNullable(projectDependency.artifactId),
1317
- true,
1318
- )
1319
- .then((_versions) => {
1320
- configState.versions.set(val.value.coordinates, _versions);
1321
- if (_versions.length) {
1322
- projectDependency.setVersionId(
1323
- guaranteeNonNullable(_versions[_versions.length - 1]),
1324
- );
1325
- flowResult(
1326
- dependencyEditorState.fetchDependencyReport(),
1327
- ).catch(applicationStore.alertUnhandledError);
1328
- } else {
1329
- projectDependency.setVersionId('');
1330
- }
1331
- fetchSelectedProjectVersionsStatus.reset();
1332
- })
1333
- .catch((error) => {
1334
- assertErrorThrown(error);
1335
- editorStore.applicationStore.notificationService.notifyError(
1336
- error,
1337
- );
1338
- fetchSelectedProjectVersionsStatus.reset();
1339
- });
796
+ const _versions = await editorStore.depotServerClient.getVersions(
797
+ guaranteeNonNullable(projectDependency.groupId),
798
+ guaranteeNonNullable(projectDependency.artifactId),
799
+ true,
800
+ );
801
+ configState.versions.set(val.value.coordinates, _versions);
802
+ if (_versions.length) {
803
+ projectDependency.setVersionId(
804
+ guaranteeNonNullable(_versions[_versions.length - 1]),
805
+ );
806
+ flowResult(dependencyEditorState.fetchDependencyReport()).catch(
807
+ applicationStore.alertUnhandledError,
808
+ );
809
+ } else {
810
+ projectDependency.setVersionId('');
811
+ }
1340
812
  } catch (error) {
1341
813
  assertErrorThrown(error);
1342
814
  editorStore.applicationStore.notificationService.notifyError(error);
815
+ } finally {
1343
816
  fetchSelectedProjectVersionsStatus.reset();
1344
817
  }
1345
818
  }
@@ -1347,26 +820,19 @@ const ProjectVersionDependencyEditor = observer(
1347
820
  };
1348
821
  // version
1349
822
  const version = projectDependency.versionId;
1350
- const sortedVersions = versions
1351
- .slice()
1352
- .sort((v1, v2) => compareSemVerVersions(v2, v1));
1353
- const versionOptions = sortedVersions.map((v) => {
1354
- if (v === MASTER_SNAPSHOT_ALIAS) {
1355
- return { value: v, label: SNAPSHOT_VERSION_ALIAS };
1356
- }
1357
- return { value: v, label: v };
1358
- });
1359
- let selectedVersionOption: VersionOption | null = null;
1360
- for (let i = 0; i < versionOptions.length; i++) {
1361
- if (guaranteeNonNullable(versionOptions[i]).value === version) {
1362
- selectedVersionOption = guaranteeNonNullable(versionOptions[i]);
1363
- break;
1364
- }
1365
- }
823
+ const versionOptions = versions
824
+ .toSorted((v1, v2) => compareSemVerVersions(v2, v1))
825
+ .map((v) => {
826
+ if (v === MASTER_SNAPSHOT_ALIAS) {
827
+ return { value: v, label: SNAPSHOT_VERSION_ALIAS };
828
+ }
829
+ return { value: v, label: v };
830
+ });
831
+ const selectedVersionOption: VersionOption | null =
832
+ versionOptions.find((v) => v.value === version) ?? null;
1366
833
  const versionDisabled =
1367
- !guaranteeNonNullable(versions.length) ||
1368
- !guaranteeNonNullable(projectDependency.projectId.length) ||
1369
- !guaranteeNonNullable(configState.associatedProjectsAndVersionsFetched) ||
834
+ Boolean(!versions.length || !projectDependency.projectId.length) ||
835
+ !configState.associatedProjectsAndVersionsFetched ||
1370
836
  isReadOnly;
1371
837
 
1372
838
  const onVersionSelectionChange = (val: VersionOption | null): void => {
@@ -1435,7 +901,9 @@ const ProjectVersionDependencyEditor = observer(
1435
901
  isClearable={true}
1436
902
  escapeClearsValue={true}
1437
903
  onChange={(val: ProjectOption | null) => {
1438
- onProjectSelectionChange(val);
904
+ onProjectSelectionChange(val).catch(
905
+ applicationStore.alertUnhandledError,
906
+ );
1439
907
  }}
1440
908
  value={selectedProjectOption}
1441
909
  isLoading={configState.fetchingProjectVersionsState.isInProgress}
@@ -1467,13 +935,6 @@ const ProjectVersionDependencyEditor = observer(
1467
935
  !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
1468
936
  }
1469
937
  />
1470
- {selectedProject && selectedVersionOption && (
1471
- <ProjectDependencyInlineExclusionsSelector
1472
- projectDependency={projectDependency}
1473
- isReadOnly={isReadOnly}
1474
- />
1475
- )}
1476
-
1477
938
  <ControlledDropdownMenu
1478
939
  className="project-dependency-editor__visit-project-btn__dropdown-trigger btn--medium"
1479
940
  content={
@@ -1552,20 +1013,13 @@ export const ProjectDependencyEditor = observer(() => {
1552
1013
  <ProjectDependencyActions dependencyEditorState={dependencyEditorState} />
1553
1014
  {currentProjectConfiguration.projectDependencies.map(
1554
1015
  (projectDependency) => (
1555
- <div key={projectDependency._UUID}>
1556
- <ProjectVersionDependencyEditor
1557
- projectDependency={projectDependency}
1558
- deleteValue={deleteProjectDependency(projectDependency)}
1559
- isReadOnly={isReadOnly}
1560
- projects={configState.projects}
1561
- />
1562
- {/* Indented exclusions list */}
1563
- <ProjectDependencyExclusionsList
1564
- key={`${projectDependency.projectId}-exclusions`}
1565
- projectDependency={projectDependency}
1566
- isReadOnly={isReadOnly}
1567
- />
1568
- </div>
1016
+ <ProjectVersionDependencyEditor
1017
+ key={projectDependency._UUID}
1018
+ projectDependency={projectDependency}
1019
+ deleteValue={deleteProjectDependency(projectDependency)}
1020
+ isReadOnly={isReadOnly}
1021
+ projects={configState.projects}
1022
+ />
1569
1023
  ),
1570
1024
  )}
1571
1025
  {dependencyEditorState.reportTab && (