@finos/legend-application-studio 22.1.5 → 22.2.0

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 (95) hide show
  1. package/lib/components/DSL_ExternalFormat_LegendStudioApplicationPlugin.d.ts +3 -1
  2. package/lib/components/DSL_ExternalFormat_LegendStudioApplicationPlugin.d.ts.map +1 -1
  3. package/lib/components/DSL_ExternalFormat_LegendStudioApplicationPlugin.js +15 -3
  4. package/lib/components/DSL_ExternalFormat_LegendStudioApplicationPlugin.js.map +1 -1
  5. package/lib/components/editor/edit-panel/GrammarTextEditor.d.ts.map +1 -1
  6. package/lib/components/editor/edit-panel/GrammarTextEditor.js +8 -0
  7. package/lib/components/editor/edit-panel/GrammarTextEditor.js.map +1 -1
  8. package/lib/components/editor/edit-panel/external-format-editor/DSL_ExternalFormat_ExternalFormatConnectionEditor.d.ts +1 -0
  9. package/lib/components/editor/edit-panel/external-format-editor/DSL_ExternalFormat_ExternalFormatConnectionEditor.d.ts.map +1 -1
  10. package/lib/components/editor/edit-panel/external-format-editor/DSL_ExternalFormat_ExternalFormatConnectionEditor.js +4 -0
  11. package/lib/components/editor/edit-panel/external-format-editor/DSL_ExternalFormat_ExternalFormatConnectionEditor.js.map +1 -1
  12. package/lib/components/editor/edit-panel/project-configuration-editor/ProjectDependencyEditor.d.ts.map +1 -1
  13. package/lib/components/editor/edit-panel/project-configuration-editor/ProjectDependencyEditor.js +155 -59
  14. package/lib/components/editor/edit-panel/project-configuration-editor/ProjectDependencyEditor.js.map +1 -1
  15. package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
  16. package/lib/components/editor/side-bar/CreateNewElementModal.js +28 -23
  17. package/lib/components/editor/side-bar/CreateNewElementModal.js.map +1 -1
  18. package/lib/components/editor/side-bar/Explorer.d.ts.map +1 -1
  19. package/lib/components/editor/side-bar/Explorer.js +1 -0
  20. package/lib/components/editor/side-bar/Explorer.js.map +1 -1
  21. package/lib/components/editor/side-bar/LocalChanges.d.ts.map +1 -1
  22. package/lib/components/editor/side-bar/LocalChanges.js +16 -3
  23. package/lib/components/editor/side-bar/LocalChanges.js.map +1 -1
  24. package/lib/index.css +2 -2
  25. package/lib/index.css.map +1 -1
  26. package/lib/package.json +3 -3
  27. package/lib/stores/ChangeDetectionState.d.ts +3 -0
  28. package/lib/stores/ChangeDetectionState.d.ts.map +1 -1
  29. package/lib/stores/ChangeDetectionState.js +68 -1
  30. package/lib/stores/ChangeDetectionState.js.map +1 -1
  31. package/lib/stores/DSL_Mapping_LegendStudioApplicationPlugin_Extension.d.ts +15 -1
  32. package/lib/stores/DSL_Mapping_LegendStudioApplicationPlugin_Extension.d.ts.map +1 -1
  33. package/lib/stores/EditorGraphState.d.ts +9 -1
  34. package/lib/stores/EditorGraphState.d.ts.map +1 -1
  35. package/lib/stores/EditorGraphState.js +220 -38
  36. package/lib/stores/EditorGraphState.js.map +1 -1
  37. package/lib/stores/EditorStore.d.ts +2 -1
  38. package/lib/stores/EditorStore.d.ts.map +1 -1
  39. package/lib/stores/EditorStore.js +14 -2
  40. package/lib/stores/EditorStore.js.map +1 -1
  41. package/lib/stores/EditorTabManagerState.d.ts +3 -10
  42. package/lib/stores/EditorTabManagerState.d.ts.map +1 -1
  43. package/lib/stores/EditorTabManagerState.js +33 -37
  44. package/lib/stores/EditorTabManagerState.js.map +1 -1
  45. package/lib/stores/ExplorerTreeState.d.ts +2 -0
  46. package/lib/stores/ExplorerTreeState.d.ts.map +1 -1
  47. package/lib/stores/ExplorerTreeState.js +53 -0
  48. package/lib/stores/ExplorerTreeState.js.map +1 -1
  49. package/lib/stores/LegendStudioRouter.d.ts +1 -1
  50. package/lib/stores/LegendStudioRouter.d.ts.map +1 -1
  51. package/lib/stores/LegendStudioRouter.js.map +1 -1
  52. package/lib/stores/editor/NewElementState.d.ts +14 -9
  53. package/lib/stores/editor/NewElementState.d.ts.map +1 -1
  54. package/lib/stores/editor/NewElementState.js +38 -19
  55. package/lib/stores/editor/NewElementState.js.map +1 -1
  56. package/lib/stores/editor-state/FileGenerationViewerState.d.ts +1 -0
  57. package/lib/stores/editor-state/FileGenerationViewerState.d.ts.map +1 -1
  58. package/lib/stores/editor-state/FileGenerationViewerState.js +4 -0
  59. package/lib/stores/editor-state/FileGenerationViewerState.js.map +1 -1
  60. package/lib/stores/editor-state/GraphGenerationState.d.ts.map +1 -1
  61. package/lib/stores/editor-state/GraphGenerationState.js +4 -1
  62. package/lib/stores/editor-state/GraphGenerationState.js.map +1 -1
  63. package/lib/stores/editor-state/element-editor-state/ElementEditorState.d.ts +1 -0
  64. package/lib/stores/editor-state/element-editor-state/ElementEditorState.d.ts.map +1 -1
  65. package/lib/stores/editor-state/element-editor-state/ElementEditorState.js +4 -0
  66. package/lib/stores/editor-state/element-editor-state/ElementEditorState.js.map +1 -1
  67. package/lib/stores/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.d.ts +46 -13
  68. package/lib/stores/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.d.ts.map +1 -1
  69. package/lib/stores/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.js +176 -23
  70. package/lib/stores/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.js.map +1 -1
  71. package/lib/stores/sidebar-state/LocalChangesState.d.ts +14 -2
  72. package/lib/stores/sidebar-state/LocalChangesState.d.ts.map +1 -1
  73. package/lib/stores/sidebar-state/LocalChangesState.js +206 -30
  74. package/lib/stores/sidebar-state/LocalChangesState.js.map +1 -1
  75. package/package.json +12 -12
  76. package/src/components/DSL_ExternalFormat_LegendStudioApplicationPlugin.tsx +17 -3
  77. package/src/components/editor/edit-panel/GrammarTextEditor.tsx +14 -0
  78. package/src/components/editor/edit-panel/external-format-editor/DSL_ExternalFormat_ExternalFormatConnectionEditor.tsx +5 -0
  79. package/src/components/editor/edit-panel/project-configuration-editor/ProjectDependencyEditor.tsx +430 -169
  80. package/src/components/editor/side-bar/CreateNewElementModal.tsx +50 -43
  81. package/src/components/editor/side-bar/Explorer.tsx +1 -0
  82. package/src/components/editor/side-bar/LocalChanges.tsx +16 -6
  83. package/src/stores/ChangeDetectionState.ts +119 -0
  84. package/src/stores/DSL_Mapping_LegendStudioApplicationPlugin_Extension.ts +19 -1
  85. package/src/stores/EditorGraphState.ts +321 -44
  86. package/src/stores/EditorStore.ts +22 -2
  87. package/src/stores/EditorTabManagerState.ts +55 -37
  88. package/src/stores/ExplorerTreeState.ts +118 -0
  89. package/src/stores/LegendStudioRouter.ts +1 -1
  90. package/src/stores/editor/NewElementState.ts +57 -28
  91. package/src/stores/editor-state/FileGenerationViewerState.ts +5 -0
  92. package/src/stores/editor-state/GraphGenerationState.ts +9 -0
  93. package/src/stores/editor-state/element-editor-state/ElementEditorState.ts +5 -0
  94. package/src/stores/editor-state/project-configuration-editor-state/ProjectDependencyEditorState.ts +259 -34
  95. package/src/stores/sidebar-state/LocalChangesState.ts +338 -62
@@ -174,7 +174,7 @@ class PatchLoaderState {
174
174
  }
175
175
  }
176
176
 
177
- export class LocalChangesState {
177
+ export abstract class LocalChangesState {
178
178
  readonly editorStore: EditorStore;
179
179
  readonly sdlcState: EditorSDLCState;
180
180
  readonly workspaceSyncState: WorkspaceSyncState;
@@ -186,7 +186,6 @@ export class LocalChangesState {
186
186
  constructor(editorStore: EditorStore, sdlcState: EditorSDLCState) {
187
187
  makeObservable(this, {
188
188
  hasUnpushedChanges: computed,
189
- openPotentialWorkspacePullConflict: action,
190
189
  refreshWorkspaceSyncStatus: flow,
191
190
  refreshLocalChanges: flow,
192
191
  pushLocalChanges: flow,
@@ -245,6 +244,78 @@ export class LocalChangesState {
245
244
  }
246
245
  }
247
246
 
247
+ *refreshWorkspaceSyncStatus(): GeneratorFn<void> {
248
+ try {
249
+ this.refreshWorkspaceSyncStatusState.inProgress();
250
+ const currentRemoteRevision =
251
+ this.sdlcState.activeRemoteWorkspaceRevision;
252
+ yield flowResult(
253
+ this.sdlcState.fetchRemoteWorkspaceRevision(
254
+ this.sdlcState.activeProject.projectId,
255
+ this.sdlcState.activeWorkspace,
256
+ ),
257
+ );
258
+ if (
259
+ currentRemoteRevision.id !==
260
+ this.sdlcState.activeRemoteWorkspaceRevision.id
261
+ ) {
262
+ if (this.sdlcState.isWorkspaceOutOfSync) {
263
+ this.editorStore.localChangesState.workspaceSyncState.fetchIncomingRevisions();
264
+ const remoteWorkspaceEntities =
265
+ (yield this.editorStore.sdlcServerClient.getEntitiesByRevision(
266
+ this.sdlcState.activeProject.projectId,
267
+ this.sdlcState.activeWorkspace,
268
+ this.sdlcState.activeRemoteWorkspaceRevision.id,
269
+ )) as Entity[];
270
+ this.editorStore.changeDetectionState.workspaceRemoteLatestRevisionState.setEntities(
271
+ remoteWorkspaceEntities,
272
+ );
273
+ yield flowResult(
274
+ this.editorStore.changeDetectionState.workspaceRemoteLatestRevisionState.buildEntityHashesIndex(
275
+ remoteWorkspaceEntities,
276
+ LogEvent.create(
277
+ CHANGE_DETECTION_EVENT.CHANGE_DETECTION_LOCAL_HASHES_INDEX_BUILT,
278
+ ),
279
+ ),
280
+ );
281
+ yield flowResult(
282
+ this.editorStore.changeDetectionState.computeAggregatedWorkspaceRemoteChanges(),
283
+ );
284
+ } else {
285
+ this.editorStore.changeDetectionState.workspaceRemoteLatestRevisionState.setEntities(
286
+ [],
287
+ );
288
+ this.editorStore.changeDetectionState.setPotentialWorkspacePullConflicts(
289
+ [],
290
+ );
291
+ this.editorStore.changeDetectionState.setAggregatedWorkspaceRemoteChanges(
292
+ [],
293
+ );
294
+ }
295
+ }
296
+ } catch (error) {
297
+ assertErrorThrown(error);
298
+ this.editorStore.applicationStore.log.error(
299
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
300
+ error,
301
+ );
302
+ } finally {
303
+ this.refreshWorkspaceSyncStatusState.complete();
304
+ }
305
+ }
306
+
307
+ abstract refreshLocalChanges(): GeneratorFn<void>;
308
+
309
+ abstract pushLocalChanges(pushMessage?: string): GeneratorFn<void>;
310
+ }
311
+
312
+ export class FormLocalChangesState extends LocalChangesState {
313
+ constructor(editorStore: EditorStore, sdlcState: EditorSDLCState) {
314
+ super(editorStore, sdlcState);
315
+ makeObservable(this, {
316
+ openPotentialWorkspacePullConflict: action,
317
+ });
318
+ }
248
319
  openLocalChange(diff: EntityDiff): void {
249
320
  const fromEntityGetter = (
250
321
  entityPath: string | undefined,
@@ -428,66 +499,6 @@ export class LocalChangesState {
428
499
  }
429
500
  }
430
501
 
431
- *refreshWorkspaceSyncStatus(): GeneratorFn<void> {
432
- try {
433
- this.refreshWorkspaceSyncStatusState.inProgress();
434
- const currentRemoteRevision =
435
- this.sdlcState.activeRemoteWorkspaceRevision;
436
- yield flowResult(
437
- this.sdlcState.fetchRemoteWorkspaceRevision(
438
- this.sdlcState.activeProject.projectId,
439
- this.sdlcState.activeWorkspace,
440
- ),
441
- );
442
- if (
443
- currentRemoteRevision.id !==
444
- this.sdlcState.activeRemoteWorkspaceRevision.id
445
- ) {
446
- if (this.sdlcState.isWorkspaceOutOfSync) {
447
- this.editorStore.localChangesState.workspaceSyncState.fetchIncomingRevisions();
448
- const remoteWorkspaceEntities =
449
- (yield this.editorStore.sdlcServerClient.getEntitiesByRevision(
450
- this.sdlcState.activeProject.projectId,
451
- this.sdlcState.activeWorkspace,
452
- this.sdlcState.activeRemoteWorkspaceRevision.id,
453
- )) as Entity[];
454
- this.editorStore.changeDetectionState.workspaceRemoteLatestRevisionState.setEntities(
455
- remoteWorkspaceEntities,
456
- );
457
- yield flowResult(
458
- this.editorStore.changeDetectionState.workspaceRemoteLatestRevisionState.buildEntityHashesIndex(
459
- remoteWorkspaceEntities,
460
- LogEvent.create(
461
- CHANGE_DETECTION_EVENT.CHANGE_DETECTION_LOCAL_HASHES_INDEX_BUILT,
462
- ),
463
- ),
464
- );
465
- yield flowResult(
466
- this.editorStore.changeDetectionState.computeAggregatedWorkspaceRemoteChanges(),
467
- );
468
- } else {
469
- this.editorStore.changeDetectionState.workspaceRemoteLatestRevisionState.setEntities(
470
- [],
471
- );
472
- this.editorStore.changeDetectionState.setPotentialWorkspacePullConflicts(
473
- [],
474
- );
475
- this.editorStore.changeDetectionState.setAggregatedWorkspaceRemoteChanges(
476
- [],
477
- );
478
- }
479
- }
480
- } catch (error) {
481
- assertErrorThrown(error);
482
- this.editorStore.applicationStore.log.error(
483
- LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
484
- error,
485
- );
486
- } finally {
487
- this.refreshWorkspaceSyncStatusState.complete();
488
- }
489
- }
490
-
491
502
  *pushLocalChanges(pushMessage?: string): GeneratorFn<void> {
492
503
  if (
493
504
  this.pushChangesState.isInProgress ||
@@ -578,6 +589,7 @@ export class LocalChangesState {
578
589
  }
579
590
  const currentHashesIndex =
580
591
  this.editorStore.changeDetectionState.snapshotLocalEntityHashesIndex();
592
+
581
593
  try {
582
594
  const nullableRevisionChange =
583
595
  (yield this.editorStore.sdlcServerClient.performEntityChanges(
@@ -613,7 +625,9 @@ export class LocalChangesState {
613
625
  );
614
626
 
615
627
  // ======= (RE)START CHANGE DETECTION =======
628
+
616
629
  this.editorStore.changeDetectionState.stop();
630
+
617
631
  try {
618
632
  /**
619
633
  * Here we try to rebuild local hash index. If failed, we will use local hash index, but for veracity, it's best to use entities
@@ -693,6 +707,268 @@ export class LocalChangesState {
693
707
  true,
694
708
  ),
695
709
  ]);
710
+
711
+ this.editorStore.applicationStore.log.info(
712
+ LogEvent.create(CHANGE_DETECTION_EVENT.CHANGE_DETECTION_RESTARTED),
713
+ Date.now() - syncFinishedTime,
714
+ 'ms',
715
+ );
716
+ // ======= FINISHED (RE)START CHANGE DETECTION =======
717
+ } catch (error) {
718
+ assertErrorThrown(error);
719
+ this.editorStore.applicationStore.log.error(
720
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
721
+ error,
722
+ );
723
+ if (
724
+ error instanceof NetworkClientError &&
725
+ error.response.status === HttpStatus.CONFLICT
726
+ ) {
727
+ // NOTE: a confict here indicates that the reference revision ID sent along with update call
728
+ // does not match the HEAD of the workspace, therefore, we need to prompt user to refresh the application
729
+ this.editorStore.applicationStore.notifyWarning(
730
+ 'Syncing failed. Current workspace revision is not the latest. Please backup your work and refresh the application',
731
+ );
732
+ // TODO: maybe we should do more here, e.g. prompt the user to download the patch, but that is for later
733
+ } else {
734
+ this.editorStore.applicationStore.notifyError(error);
735
+ }
736
+ } finally {
737
+ this.pushChangesState.complete();
738
+ }
739
+ }
740
+ }
741
+
742
+ export class TextLocalChangesState extends LocalChangesState {
743
+ localChanges: EntityChange[] = [];
744
+
745
+ constructor(editorStore: EditorStore, sdlcState: EditorSDLCState) {
746
+ super(editorStore, sdlcState);
747
+ makeObservable(this, {
748
+ setLocalChanges: action,
749
+ });
750
+ }
751
+
752
+ setLocalChanges(val: EntityChange[]): void {
753
+ this.localChanges = val;
754
+ }
755
+
756
+ *refreshLocalChanges(): GeneratorFn<void> {
757
+ const startTime = Date.now();
758
+ this.refreshLocalChangesDetectorState.inProgress();
759
+ try {
760
+ // ======= (RE)START CHANGE DETECTION =======
761
+ yield Promise.all([
762
+ this.sdlcState.buildWorkspaceLatestRevisionEntityHashesIndex(),
763
+ this.editorStore.changeDetectionState.preComputeGraphElementHashes(),
764
+ ]);
765
+ this.editorStore.changeDetectionState.computeLocalChangesInTextMode(
766
+ this.editorStore.changeDetectionState.workspaceLocalLatestRevisionState
767
+ .entities,
768
+ );
769
+ this.editorStore.applicationStore.log.info(
770
+ LogEvent.create(CHANGE_DETECTION_EVENT.CHANGE_DETECTION_RESTARTED),
771
+ Date.now() - startTime,
772
+ 'ms',
773
+ );
774
+ // ======= FINISHED (RE)START CHANGE DETECTION =======
775
+ } catch (error) {
776
+ assertErrorThrown(error);
777
+ this.editorStore.applicationStore.log.error(
778
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
779
+ error,
780
+ );
781
+ this.editorStore.applicationStore.notifyError(error);
782
+ this.sdlcState.handleChangeDetectionRefreshIssue(error);
783
+ } finally {
784
+ this.refreshLocalChangesDetectorState.complete();
785
+ }
786
+ }
787
+
788
+ *pushLocalChanges(pushMessage?: string): GeneratorFn<void> {
789
+ if (
790
+ this.pushChangesState.isInProgress ||
791
+ this.editorStore.workspaceUpdaterState.isUpdatingWorkspace
792
+ ) {
793
+ return;
794
+ }
795
+
796
+ this.pushChangesState.inProgress();
797
+ const startTime = Date.now();
798
+ if (!this.localChanges.length) {
799
+ this.pushChangesState.complete();
800
+ return;
801
+ }
802
+ yield flowResult(
803
+ this.sdlcState.fetchRemoteWorkspaceRevision(
804
+ this.sdlcState.activeProject.projectId,
805
+ this.sdlcState.activeWorkspace,
806
+ ),
807
+ );
808
+ if (this.sdlcState.isWorkspaceOutOfSync) {
809
+ // ensure changes have been computed for latest remote version
810
+ const remoteWorkspaceEntities =
811
+ (yield this.editorStore.sdlcServerClient.getEntitiesByRevision(
812
+ this.sdlcState.activeProject.projectId,
813
+ this.sdlcState.activeWorkspace,
814
+ this.sdlcState.activeRemoteWorkspaceRevision.id,
815
+ )) as Entity[];
816
+ this.editorStore.changeDetectionState.workspaceRemoteLatestRevisionState.setEntities(
817
+ remoteWorkspaceEntities,
818
+ );
819
+ yield flowResult(
820
+ this.editorStore.changeDetectionState.workspaceRemoteLatestRevisionState.buildEntityHashesIndex(
821
+ remoteWorkspaceEntities,
822
+ LogEvent.create(
823
+ CHANGE_DETECTION_EVENT.CHANGE_DETECTION_LOCAL_HASHES_INDEX_BUILT,
824
+ ),
825
+ ),
826
+ );
827
+ yield flowResult(
828
+ this.editorStore.changeDetectionState.computeAggregatedWorkspaceRemoteChanges(),
829
+ );
830
+ this.editorStore.applicationStore.setActionAlertInfo({
831
+ message: 'Local workspace is out-of-sync',
832
+ prompt: 'Please pull remote changes before pushing your local changes',
833
+ type: ActionAlertType.CAUTION,
834
+ actions: [
835
+ {
836
+ label: 'Pull remote changes',
837
+ type: ActionAlertActionType.STANDARD,
838
+ default: true,
839
+ handler: (): void => {
840
+ this.editorStore.setActiveActivity(ACTIVITY_MODE.LOCAL_CHANGES);
841
+ flowResult(
842
+ this.editorStore.localChangesState.workspaceSyncState.pullChanges(),
843
+ ).catch(this.editorStore.applicationStore.alertUnhandledError);
844
+ },
845
+ },
846
+ {
847
+ label: 'Cancel',
848
+ type: ActionAlertActionType.PROCEED_WITH_CAUTION,
849
+ },
850
+ ],
851
+ });
852
+ this.pushChangesState.complete();
853
+ return;
854
+ }
855
+ const currentHashesIndex =
856
+ this.editorStore.changeDetectionState.workspaceLocalLatestRevisionState
857
+ .currentEntityHashesIndex;
858
+ try {
859
+ const nullableRevisionChange =
860
+ (yield this.editorStore.sdlcServerClient.performEntityChanges(
861
+ this.sdlcState.activeProject.projectId,
862
+ this.sdlcState.activeWorkspace,
863
+ {
864
+ message:
865
+ pushMessage ??
866
+ `pushed new changes from ${
867
+ this.editorStore.applicationStore.config.appName
868
+ } [potentially affected ${
869
+ this.localChanges.length === 1
870
+ ? '1 entity'
871
+ : `${this.localChanges.length} entities`
872
+ }]`,
873
+ entityChanges: this.localChanges,
874
+ revisionId: this.sdlcState.activeRevision.id,
875
+ },
876
+ )) as PlainObject<Revision> | undefined;
877
+ const revisionChange = guaranteeNonNullable(
878
+ nullableRevisionChange,
879
+ `Can't push an empty change set. This may be due to an error with change detection`,
880
+ );
881
+ const latestRevision = Revision.serialization.fromJson(revisionChange);
882
+ this.sdlcState.setCurrentRevision(latestRevision); // update current revision to the latest
883
+ this.sdlcState.setWorkspaceLatestRevision(latestRevision);
884
+ const syncFinishedTime = Date.now();
885
+
886
+ this.editorStore.applicationStore.log.info(
887
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.WORKSPACE_LOCAL_CHANGES_PUSHED),
888
+ syncFinishedTime - startTime,
889
+ 'ms',
890
+ );
891
+ this.localChanges = [];
892
+
893
+ // ======= (RE)START CHANGE DETECTION =======
894
+ try {
895
+ /**
896
+ * Here we try to rebuild local hash index. If failed, we will use local hash index, but for veracity, it's best to use entities
897
+ * coming from the server.
898
+ */
899
+ const entities =
900
+ (yield this.editorStore.sdlcServerClient.getEntitiesByRevision(
901
+ this.sdlcState.activeProject.projectId,
902
+ this.sdlcState.activeWorkspace,
903
+ latestRevision.id,
904
+ )) as Entity[];
905
+ this.editorStore.changeDetectionState.workspaceLocalLatestRevisionState.setEntities(
906
+ entities,
907
+ );
908
+ yield flowResult(
909
+ this.editorStore.changeDetectionState.workspaceLocalLatestRevisionState.buildEntityHashesIndex(
910
+ entities,
911
+ LogEvent.create(
912
+ CHANGE_DETECTION_EVENT.CHANGE_DETECTION_LOCAL_HASHES_INDEX_BUILT,
913
+ ),
914
+ ),
915
+ );
916
+ this.editorStore.tabManagerState.refreshCurrentEntityDiffViewer();
917
+ } catch (error) {
918
+ assertErrorThrown(error);
919
+ /**
920
+ * NOTE: there is a known problem with the SDLC server where if we try to fetch the entities right after syncing, there is a chance
921
+ * that we get entities from the older commit (i.e. potentially some caching issue). As such, to account for this case, we will
922
+ * not try to get entities for the workspace HEAD, but for the revision returned from the syncing call (i.e. this must be the latest revision)
923
+ * if we get a 404, we will do a refresh and warn user about this. Otherwise, if we get other types of error, we will assume this is a network
924
+ * failure and use local workspace hashes index
925
+ */
926
+ if (error instanceof NetworkClientError) {
927
+ if (error.response.status === HttpStatus.NOT_FOUND) {
928
+ this.editorStore.applicationStore.log.error(
929
+ LogEvent.create(LEGEND_STUDIO_APP_EVENT.SDLC_MANAGER_FAILURE),
930
+ `Can't fetch entities for the latest workspace revision immediately after syncing`,
931
+ error,
932
+ );
933
+ }
934
+ this.editorStore.applicationStore.setActionAlertInfo({
935
+ message: `Change detection engine failed to build hashes index for workspace after syncing`,
936
+ prompt:
937
+ 'To fix this, you can either try to keep refreshing local changes until success or trust and reuse current workspace hashes index',
938
+ type: ActionAlertType.CAUTION,
939
+ actions: [
940
+ {
941
+ label: 'Use local hashes index',
942
+ type: ActionAlertActionType.PROCEED_WITH_CAUTION,
943
+ handler: (): void => {
944
+ this.editorStore.changeDetectionState.workspaceLocalLatestRevisionState.setEntityHashesIndex(
945
+ currentHashesIndex,
946
+ );
947
+ this.editorStore.changeDetectionState.workspaceLocalLatestRevisionState.setIsBuildingEntityHashesIndex(
948
+ false,
949
+ );
950
+ },
951
+ },
952
+ {
953
+ label: 'Refresh changes',
954
+ type: ActionAlertActionType.STANDARD,
955
+ default: true,
956
+ handler: this.editorStore.applicationStore.guardUnhandledError(
957
+ () => flowResult(this.refreshLocalChanges()),
958
+ ),
959
+ },
960
+ ],
961
+ });
962
+ } else {
963
+ throw error;
964
+ }
965
+ }
966
+ // compute the changes in text mode
967
+ this.editorStore.changeDetectionState.computeLocalChangesInTextMode(
968
+ this.editorStore.changeDetectionState.workspaceLocalLatestRevisionState
969
+ .entities,
970
+ );
971
+
696
972
  this.editorStore.applicationStore.log.info(
697
973
  LogEvent.create(CHANGE_DETECTION_EVENT.CHANGE_DETECTION_RESTARTED),
698
974
  Date.now() - syncFinishedTime,