@finos/legend-application-studio 28.21.22 → 28.21.24

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 (92) hide show
  1. package/lib/__lib__/LegendStudioDocumentation.d.ts +2 -2
  2. package/lib/__lib__/LegendStudioDocumentation.d.ts.map +1 -1
  3. package/lib/__lib__/LegendStudioDocumentation.js +1 -1
  4. package/lib/__lib__/LegendStudioDocumentation.js.map +1 -1
  5. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.d.ts.map +1 -1
  6. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js +2 -5
  7. package/lib/components/editor/editor-group/data-editor/RelationElementsDataEditor.js.map +1 -1
  8. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.d.ts.map +1 -1
  9. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js +13 -239
  10. package/lib/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.js.map +1 -1
  11. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.d.ts.map +1 -1
  12. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js +17 -3
  13. package/lib/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.js.map +1 -1
  14. package/lib/components/editor/editor-group/ingest-editor/testable/IngestTestableEditor.d.ts +22 -0
  15. package/lib/components/editor/editor-group/ingest-editor/testable/IngestTestableEditor.d.ts.map +1 -0
  16. package/lib/components/editor/editor-group/ingest-editor/testable/IngestTestableEditor.js +134 -0
  17. package/lib/components/editor/editor-group/ingest-editor/testable/IngestTestableEditor.js.map +1 -0
  18. package/lib/components/editor/editor-group/testable/LakehouseTestableEditor.d.ts +89 -0
  19. package/lib/components/editor/editor-group/testable/LakehouseTestableEditor.d.ts.map +1 -0
  20. package/lib/components/editor/editor-group/testable/LakehouseTestableEditor.js +144 -0
  21. package/lib/components/editor/editor-group/testable/LakehouseTestableEditor.js.map +1 -0
  22. package/lib/components/editor/editor-group/testable/TestableSharedComponents.d.ts.map +1 -1
  23. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js +14 -8
  24. package/lib/components/editor/editor-group/testable/TestableSharedComponents.js.map +1 -1
  25. package/lib/components/editor/ingest-definition-editor.css +1 -1
  26. package/lib/components/editor/ingest-definition-editor.css.map +1 -1
  27. package/lib/components/project-reviewer/ProjectReviewer.d.ts.map +1 -1
  28. package/lib/components/project-reviewer/ProjectReviewer.js +2 -1
  29. package/lib/components/project-reviewer/ProjectReviewer.js.map +1 -1
  30. package/lib/components/project-view/ProjectViewer.d.ts.map +1 -1
  31. package/lib/components/project-view/ProjectViewer.js +2 -2
  32. package/lib/components/project-view/ProjectViewer.js.map +1 -1
  33. package/lib/components/showcase/ShowcaseViewer.d.ts.map +1 -1
  34. package/lib/components/showcase/ShowcaseViewer.js +2 -2
  35. package/lib/components/showcase/ShowcaseViewer.js.map +1 -1
  36. package/lib/components/workspace-setup/WorkspaceSetup.d.ts +1 -1
  37. package/lib/components/workspace-setup/WorkspaceSetup.d.ts.map +1 -1
  38. package/lib/components/workspace-setup/WorkspaceSetup.js +98 -43
  39. package/lib/components/workspace-setup/WorkspaceSetup.js.map +1 -1
  40. package/lib/index.css +2 -2
  41. package/lib/index.css.map +1 -1
  42. package/lib/package.json +1 -1
  43. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.d.ts.map +1 -1
  44. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js +1 -2
  45. package/lib/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.js.map +1 -1
  46. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.d.ts.map +1 -1
  47. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js +1 -0
  48. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.js.map +1 -1
  49. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts +8 -30
  50. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.d.ts.map +1 -1
  51. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js +7 -147
  52. package/lib/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.js.map +1 -1
  53. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.d.ts.map +1 -1
  54. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js +32 -28
  55. package/lib/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.js.map +1 -1
  56. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts +8 -0
  57. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.d.ts.map +1 -1
  58. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js +15 -0
  59. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.js.map +1 -1
  60. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.d.ts +86 -0
  61. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.d.ts.map +1 -0
  62. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.js +420 -0
  63. package/lib/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.js.map +1 -0
  64. package/lib/stores/editor/editor-state/element-editor-state/testable/LakehouseTestableUtils.d.ts +62 -0
  65. package/lib/stores/editor/editor-state/element-editor-state/testable/LakehouseTestableUtils.d.ts.map +1 -0
  66. package/lib/stores/editor/editor-state/element-editor-state/testable/LakehouseTestableUtils.js +138 -0
  67. package/lib/stores/editor/editor-state/element-editor-state/testable/LakehouseTestableUtils.js.map +1 -0
  68. package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts +10 -1
  69. package/lib/stores/workspace-setup/WorkspaceSetupStore.d.ts.map +1 -1
  70. package/lib/stores/workspace-setup/WorkspaceSetupStore.js +105 -12
  71. package/lib/stores/workspace-setup/WorkspaceSetupStore.js.map +1 -1
  72. package/package.json +11 -11
  73. package/src/__lib__/LegendStudioDocumentation.ts +1 -1
  74. package/src/components/editor/editor-group/data-editor/RelationElementsDataEditor.tsx +2 -5
  75. package/src/components/editor/editor-group/dataProduct/testable/DataProductTestableEditor.tsx +19 -869
  76. package/src/components/editor/editor-group/ingest-editor/IngestDefinitionEditor.tsx +90 -34
  77. package/src/components/editor/editor-group/ingest-editor/testable/IngestTestableEditor.tsx +418 -0
  78. package/src/components/editor/editor-group/testable/LakehouseTestableEditor.tsx +564 -0
  79. package/src/components/editor/editor-group/testable/TestableSharedComponents.tsx +17 -9
  80. package/src/components/project-reviewer/ProjectReviewer.tsx +2 -0
  81. package/src/components/project-view/ProjectViewer.tsx +2 -1
  82. package/src/components/showcase/ShowcaseViewer.tsx +2 -1
  83. package/src/components/workspace-setup/WorkspaceSetup.tsx +169 -75
  84. package/src/stores/editor/editor-state/element-editor-state/data/EmbeddedDataState.ts +1 -2
  85. package/src/stores/editor/editor-state/element-editor-state/dataProduct/DataProductEditorState.ts +1 -0
  86. package/src/stores/editor/editor-state/element-editor-state/dataProduct/testable/DataProductTestableState.ts +18 -204
  87. package/src/stores/editor/editor-state/element-editor-state/function-activator/testable/FunctionTestableState.ts +41 -36
  88. package/src/stores/editor/editor-state/element-editor-state/ingest/IngestDefinitionEditorState.ts +16 -0
  89. package/src/stores/editor/editor-state/element-editor-state/ingest/IngestTestableState.ts +654 -0
  90. package/src/stores/editor/editor-state/element-editor-state/testable/LakehouseTestableUtils.ts +224 -0
  91. package/src/stores/workspace-setup/WorkspaceSetupStore.ts +125 -8
  92. package/tsconfig.json +4 -0
@@ -24,6 +24,8 @@ import {
24
24
  } from 'react';
25
25
  import { observer, useLocalObservable } from 'mobx-react-lite';
26
26
  import {
27
+ type SelectComponent,
28
+ type InputActionData,
27
29
  clsx,
28
30
  AssistantIcon,
29
31
  compareLabelFn,
@@ -45,7 +47,10 @@ import {
45
47
  LEGEND_STUDIO_ROUTE_PATTERN_TOKEN,
46
48
  } from '../../__lib__/LegendStudioNavigation.js';
47
49
  import { flowResult } from 'mobx';
48
- import { useApplicationNavigationContext } from '@finos/legend-application';
50
+ import {
51
+ DEFAULT_TYPEAHEAD_SEARCH_LIMIT,
52
+ useApplicationNavigationContext,
53
+ } from '@finos/legend-application';
49
54
  import { useParams } from '@finos/legend-application/browser';
50
55
  import { LEGEND_STUDIO_DOCUMENTATION_KEY } from '../../__lib__/LegendStudioDocumentation.js';
51
56
  import { CreateProjectModal } from './CreateProjectModal.js';
@@ -82,6 +87,32 @@ const WorkspaceSetupStoreContext = createContext<
82
87
 
83
88
  export const DEFAULT_WORKSPACE_SOURCE = 'HEAD';
84
89
 
90
+ enum ACTION_KEYS {
91
+ ENTER = 'Enter',
92
+ BACKSPACE = 'Backspace',
93
+ DELETE = 'Delete',
94
+ TAB = 'Tab',
95
+ }
96
+
97
+ const PROJECT_SELECTED_ACTION_KEYS: string[] = [
98
+ ACTION_KEYS.BACKSPACE,
99
+ ACTION_KEYS.DELETE,
100
+ ACTION_KEYS.TAB,
101
+ ];
102
+
103
+ const handleKeyClicked = (
104
+ event: React.KeyboardEvent<HTMLDivElement>,
105
+ inputHasSelection: boolean,
106
+ ): void => {
107
+ if (!inputHasSelection) {
108
+ return;
109
+ }
110
+ if (!PROJECT_SELECTED_ACTION_KEYS.includes(event.key)) {
111
+ event.preventDefault();
112
+ event.stopPropagation();
113
+ }
114
+ };
115
+
85
116
  export const ShowcaseCard: React.FC<{ hideDocumentation?: boolean }> = (
86
117
  props,
87
118
  ) => {
@@ -93,7 +124,7 @@ export const ShowcaseCard: React.FC<{ hideDocumentation?: boolean }> = (
93
124
  cardMedia={undefined}
94
125
  cardName="Showcase Projects"
95
126
  cardContent={
96
- <div className="workspace-setup__content__card__content">
127
+ <>
97
128
  Review showcase projects with sample project code and re-use existing
98
129
  code snippets to quickly build your model.{' '}
99
130
  {!props.hideDocumentation && (
@@ -110,7 +141,7 @@ export const ShowcaseCard: React.FC<{ hideDocumentation?: boolean }> = (
110
141
  .
111
142
  </>
112
143
  )}
113
- </div>
144
+ </>
114
145
  }
115
146
  cardActions={[
116
147
  {
@@ -136,7 +167,7 @@ export const DocumentationCard: React.FC = () => {
136
167
  className="workspace-setup__content__card"
137
168
  cardName="Documentation"
138
169
  cardContent={
139
- <div className="workspace-setup__content__card__content">
170
+ <>
140
171
  Review Studio{' '}
141
172
  <a
142
173
  href={appDocUrl}
@@ -147,7 +178,7 @@ export const DocumentationCard: React.FC = () => {
147
178
  documentation
148
179
  </a>
149
180
  .
150
- </div>
181
+ </>
151
182
  }
152
183
  cardActions={[
153
184
  {
@@ -207,31 +238,31 @@ export const ProductionCard: React.FC = () => {
207
238
  );
208
239
  };
209
240
 
210
- export const SandboxCard: React.FC = () => {
241
+ export const FaqCard: React.FC = () => {
211
242
  const applicationStore = useLegendStudioApplicationStore();
212
- const sandboxDocument = applicationStore.documentationService.getDocEntry(
213
- LEGEND_STUDIO_DOCUMENTATION_KEY.APPLICATION_SANDBOX,
243
+ const faqDocument = applicationStore.documentationService.getDocEntry(
244
+ LEGEND_STUDIO_DOCUMENTATION_KEY.APPLICATION_FAQ,
214
245
  );
215
246
  return (
216
- sandboxDocument?.title &&
217
- sandboxDocument.markdownText &&
218
- sandboxDocument.text && (
247
+ faqDocument?.title &&
248
+ faqDocument.markdownText &&
249
+ faqDocument.text && (
219
250
  <BaseCard
220
251
  className="workspace-setup__content__card"
221
- cardName={sandboxDocument.title}
222
- cardContent={sandboxDocument.markdownText.value}
252
+ cardName={faqDocument.title}
253
+ cardContent={faqDocument.markdownText.value}
223
254
  cardActions={[
224
255
  {
225
- title: sandboxDocument.text,
256
+ title: faqDocument.text,
226
257
  content: (
227
258
  <div className="workspace-setup__content__card__action__icon">
228
259
  <OpenIcon />
229
260
  </div>
230
261
  ),
231
262
  action: () => {
232
- if (sandboxDocument.url) {
263
+ if (faqDocument.url) {
233
264
  applicationStore.navigationService.navigator.visitAddress(
234
- sandboxDocument.url,
265
+ faqDocument.url,
235
266
  );
236
267
  }
237
268
  },
@@ -359,7 +390,11 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
359
390
  const setupStore = useWorkspaceSetupStore();
360
391
  const applicationStore = useLegendStudioApplicationStore();
361
392
  const [projectSearchText, setProjectSearchText] = useState('');
393
+ const [isProjectSelectorMenuOpen, setIsProjectSelectorMenuOpen] =
394
+ useState(false);
362
395
  const goButtonRef = useRef<HTMLButtonElement>(null);
396
+ const projectSelectorRef = useRef<SelectComponent>(null);
397
+ const workspaceSelectorRef = useRef<SelectComponent>(null);
363
398
  //TODO: fix logo loading issue for localhost
364
399
  const logoPath = `${applicationStore.config.baseAddress}favicon.ico`;
365
400
  const toggleAssistant = (): void =>
@@ -369,23 +404,28 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
369
404
  // Build a unified option list: recent projects (that aren't already in the
370
405
  // loaded set) are prepended so users can instantly re-open common work
371
406
  // without waiting for the SDLC search to round-trip.
407
+ const { projects, projectMatchedById } = setupStore.projectSearchResult;
372
408
  const sandboxProject =
373
409
  setupStore.sandboxProject instanceof Project
374
410
  ? setupStore.sandboxProject
375
411
  : undefined;
376
412
  const sandboxProjectId = sandboxProject?.projectId;
377
- const loadedProjectOptions = setupStore.projects
378
- .filter((p) => p.projectId !== sandboxProjectId)
413
+ const loadedProjectOptions = projects
414
+ .filter(
415
+ (p) =>
416
+ p.projectId !== sandboxProjectId &&
417
+ p.projectId !== projectMatchedById?.projectId,
418
+ )
419
+ .slice(0, DEFAULT_TYPEAHEAD_SEARCH_LIMIT)
379
420
  .map(buildProjectOption)
380
421
  .sort(compareLabelFn);
381
- const loadedProjectIds = new Set(
382
- setupStore.projects.map((p) => p.projectId),
383
- );
422
+ const loadedProjectIds = new Set(projects.map((p) => p.projectId));
384
423
  const recentProjectOptions: ProjectOption[] = setupStore.recentProjects
385
424
  .filter(
386
425
  (r) =>
387
426
  !loadedProjectIds.has(r.projectId) &&
388
- r.projectId !== sandboxProjectId,
427
+ r.projectId !== sandboxProjectId &&
428
+ r.projectId !== projectMatchedById?.projectId,
389
429
  )
390
430
  .map((r) => {
391
431
  // Rebuild a real Project from the cached metadata; no synthetic
@@ -399,18 +439,21 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
399
439
  } as PlainObject<Project>);
400
440
  return { label: stub.name, value: stub };
401
441
  });
442
+ const pinnedOptions: ProjectOption[] = [];
443
+ if (projectMatchedById) {
444
+ pinnedOptions.push(buildProjectOption(projectMatchedById));
445
+ }
446
+ // The user's own sandbox project is fetched via a dedicated call
447
+ // (`loadSandboxProject`) and excluded from the main search results, so
448
+ // we surface it here as a labeled option pinned to the top of the list.
449
+ if (sandboxProject) {
450
+ pinnedOptions.push({
451
+ label: `${sandboxProject.name} (sandbox)`,
452
+ value: sandboxProject,
453
+ });
454
+ }
402
455
  const projectOptions: ProjectOption[] = [
403
- // The user's own sandbox project is fetched via a dedicated call
404
- // (`loadSandboxProject`) and excluded from the main search results, so
405
- // we surface it here as a labeled option pinned to the top of the list.
406
- ...(sandboxProject
407
- ? [
408
- {
409
- label: `${sandboxProject.name} (sandbox)`,
410
- value: sandboxProject,
411
- },
412
- ]
413
- : []),
456
+ ...pinnedOptions,
414
457
  ...recentProjectOptions,
415
458
  ...loadedProjectOptions,
416
459
  ];
@@ -422,12 +465,14 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
422
465
  : null;
423
466
 
424
467
  const onProjectChange = (val: ProjectOption | null): void => {
468
+ setProjectSearchText('');
425
469
  if (val) {
426
470
  // If the selection corresponds to a recent that hasn't been loaded
427
471
  // from search yet, fetch the project before switching.
428
472
  const isUnloadedRecent =
429
473
  !loadedProjectIds.has(val.value.projectId) &&
430
- recentProjectIdSet.has(val.value.projectId);
474
+ recentProjectIdSet.has(val.value.projectId) &&
475
+ val.value.projectId !== projectMatchedById?.projectId;
431
476
  if (isUnloadedRecent) {
432
477
  flowResult(setupStore.selectRecentProject(val.value.projectId)).catch(
433
478
  applicationStore.alertUnhandledError,
@@ -439,6 +484,7 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
439
484
  }
440
485
  } else {
441
486
  setupStore.resetProject();
487
+ setTimeout(() => projectSelectorRef.current?.focus(), 0);
442
488
  }
443
489
  };
444
490
  const showCreateProjectModal = (): void =>
@@ -457,12 +503,19 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
457
503
  flowResult(setupStore.loadProjects(input)).catch(
458
504
  applicationStore.alertUnhandledError,
459
505
  );
460
- }, 500),
506
+ }, 250),
461
507
  [applicationStore, setupStore],
462
508
  );
463
- const onProjectSearchTextChange = (value: string): void => {
509
+ const onProjectSearchTextChange = (
510
+ value: string,
511
+ actionChange: InputActionData,
512
+ ): void => {
513
+ if (actionChange.action !== 'input-change' || selectedProjectOption) {
514
+ return;
515
+ }
464
516
  if (value !== projectSearchText) {
465
517
  setProjectSearchText(value);
518
+ setupStore.filterListOnInput(value);
466
519
  debouncedLoadProjects.cancel();
467
520
  debouncedLoadProjects(value);
468
521
  }
@@ -515,9 +568,9 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
515
568
  `Can't edit current workspace as the current project is not configured`,
516
569
  );
517
570
  }
518
- goButtonRef.current?.focus();
519
571
  } else {
520
572
  setupStore.resetWorkspace();
573
+ setTimeout(() => workspaceSelectorRef.current?.focus(), 0);
521
574
  }
522
575
  };
523
576
  const showCreateWorkspaceModal = (): void =>
@@ -561,6 +614,20 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
561
614
  LEGEND_STUDIO_APPLICATION_NAVIGATION_CONTEXT_KEY.SETUP,
562
615
  );
563
616
 
617
+ const sharedSelectorProps = {
618
+ inputClassName: 'workspace-setup__selector__input',
619
+ classNames: {
620
+ placeholder: (): string => 'workspace-setup__selector__placeholder',
621
+ },
622
+ isClearable: true,
623
+ escapeClearsValue: true,
624
+ darkMode:
625
+ !applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled,
626
+ optionCustomization: {
627
+ rowHeight: window.innerHeight * 0.03,
628
+ },
629
+ };
630
+
564
631
  return (
565
632
  <div className="app__page">
566
633
  <div className="workspace-setup">
@@ -616,7 +683,16 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
616
683
  <SearchIcon className="workspace-setup__selector__content__icon--project" />
617
684
  </div>
618
685
  <CustomSelectorInput
619
- className="workspace-setup__selector__content__input"
686
+ {...sharedSelectorProps}
687
+ className={clsx(
688
+ 'workspace-setup__selector__content__input',
689
+ {
690
+ 'workspace-setup__selector--locked': Boolean(
691
+ selectedProjectOption,
692
+ ),
693
+ },
694
+ )}
695
+ inputRef={projectSelectorRef}
620
696
  options={projectOptions}
621
697
  isLoading={
622
698
  setupStore.loadProjectsState.isInProgress ||
@@ -624,28 +700,37 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
624
700
  }
625
701
  onInputChange={onProjectSearchTextChange}
626
702
  inputValue={projectSearchText}
627
- onChange={onProjectChange}
703
+ onKeyDown={(
704
+ event: React.KeyboardEvent<HTMLDivElement>,
705
+ ) =>
706
+ handleKeyClicked(
707
+ event,
708
+ Boolean(selectedProjectOption),
709
+ )
710
+ }
711
+ menuIsOpen={isProjectSelectorMenuOpen}
712
+ onFocus={() => setIsProjectSelectorMenuOpen(true)}
713
+ onMenuOpen={() =>
714
+ setIsProjectSelectorMenuOpen(true)
715
+ }
716
+ onBlur={() => setIsProjectSelectorMenuOpen(false)}
717
+ onChange={(option: ProjectOption | null) => {
718
+ onProjectChange(option);
719
+ setIsProjectSelectorMenuOpen(false);
720
+ }}
628
721
  value={selectedProjectOption}
629
722
  placeholder="Search for project..."
630
- isClearable={true}
631
- escapeClearsValue={true}
632
- darkMode={
633
- !applicationStore.layoutService
634
- .TEMPORARY__isLightColorThemeEnabled
635
- }
723
+ filterOption={(): boolean => true}
636
724
  formatOptionLabel={getProjectOptionLabelFormatter(
637
725
  applicationStore,
638
726
  setupStore.currentProjectConfigurationStatus,
639
727
  )}
640
- optionCustomization={{
641
- rowHeight: window.innerHeight * 0.03,
642
- }}
643
728
  />
644
729
  </div>
645
730
  </div>
646
731
  <div className="workspace-setup__selector">
647
732
  <div className="workspace-setup__selector__header">
648
- Choose an existing workspace
733
+ <span>Choose an existing workspace</span>
649
734
  </div>
650
735
  <div className="workspace-setup__selector__content">
651
736
  <div
@@ -655,15 +740,29 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
655
740
  <GitBranchIcon className="workspace-setup__selector__content__icon--workspace" />
656
741
  </div>
657
742
  <CustomSelectorInput
658
- className="workspace-setup__selector__content__input"
743
+ {...sharedSelectorProps}
744
+ className={clsx(
745
+ 'workspace-setup__selector__content__input',
746
+ {
747
+ 'workspace-setup__selector--locked': Boolean(
748
+ selectedWorkspaceOption,
749
+ ),
750
+ },
751
+ )}
752
+ inputRef={workspaceSelectorRef}
659
753
  options={workspaceOptions}
660
754
  onKeyDown={(
661
755
  event: React.KeyboardEvent<HTMLDivElement>,
662
756
  ) => {
663
- if (event.key === 'Enter') {
757
+ if (event.key === ACTION_KEYS.ENTER) {
664
758
  goButtonRef.current?.focus();
665
759
  handleProceed();
760
+ return;
666
761
  }
762
+ handleKeyClicked(
763
+ event,
764
+ Boolean(selectedWorkspaceOption),
765
+ );
667
766
  }}
668
767
  disabled={
669
768
  !setupStore.currentProject ||
@@ -688,15 +787,6 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
688
787
  ? 'Choose an existing workspace'
689
788
  : 'You have no workspaces. Please create one to proceed...'
690
789
  }
691
- isClearable={true}
692
- escapeClearsValue={true}
693
- darkMode={
694
- !applicationStore.layoutService
695
- .TEMPORARY__isLightColorThemeEnabled
696
- }
697
- optionCustomization={{
698
- rowHeight: window.innerHeight * 0.03,
699
- }}
700
790
  />
701
791
  </div>
702
792
  </div>
@@ -707,7 +797,7 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
707
797
  <button
708
798
  className="workspace-setup__new-workspace-btn"
709
799
  onClick={showCreateWorkspaceModal}
710
- title="Create a Workspace after choosing one project"
800
+ title="Create a workspace after choosing a project"
711
801
  disabled={
712
802
  !setupStore.currentProject ||
713
803
  !setupStore.currentProjectConfigurationStatus
@@ -741,7 +831,7 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
741
831
  OR
742
832
  </DividerWithText>
743
833
  {setupStore.sandboxModal && <SandboxAccessModal />}
744
- <div className="workspace-setup__actions__button">
834
+ <div className="workspace-setup__actions__button workspace-setup__actions__button--projects">
745
835
  <button
746
836
  className="workspace-setup__new-btn btn--dark"
747
837
  onClick={showCreateProjectModal}
@@ -749,17 +839,22 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
749
839
  >
750
840
  Create New Project
751
841
  </button>
752
- {setupStore.sandboxProject === true &&
753
- setupStore.initState.hasCompleted &&
754
- setupStore.supportsCreatingSandboxProject && (
755
- <button
756
- className="workspace-setup__new-btn btn--dark"
757
- onClick={createSandboxProject}
758
- title="Create Sandbox Project"
759
- >
760
- Create Sandbox Project
761
- </button>
762
- )}
842
+ {setupStore.supportsCreatingSandboxProject && (
843
+ <button
844
+ className="workspace-setup__new-btn btn--dark"
845
+ onClick={createSandboxProject}
846
+ title="Create Sandbox Project"
847
+ disabled={
848
+ !setupStore.initState.hasCompleted ||
849
+ setupStore.loadSandboxState.isInProgress ||
850
+ setupStore.createSandboxProjectState
851
+ .isInProgress ||
852
+ setupStore.sandboxProject !== true
853
+ }
854
+ >
855
+ Create Sandbox Project
856
+ </button>
857
+ )}
763
858
  </div>
764
859
  </div>
765
860
  </div>
@@ -767,8 +862,7 @@ export const WorkspaceSetup = withWorkspaceSetupStore(
767
862
  <div className="workspace-setup__content__cards">
768
863
  <RuleEngagementCard />
769
864
  <ShowcaseCard />
770
- {/* The SandboxCard and ProductionCard will appear only if the corresponding documentation entry is added in the config.json file for each realm.*/}
771
- <SandboxCard />
865
+ <FaqCard />
772
866
  <ProductionCard />
773
867
  </div>
774
868
  {/* NOTE: We do this to reset the initial state of the modals */}
@@ -255,8 +255,7 @@ export class RelationElementState {
255
255
  }
256
256
 
257
257
  updateColumn(index: number, name: string): void {
258
- const oldName = this.relationElement.columns[index];
259
- if (oldName && oldName !== name) {
258
+ if (index >= 0 && index < this.relationElement.columns.length) {
260
259
  this.relationElement.columns[index] = name;
261
260
  }
262
261
  }
@@ -1046,6 +1046,7 @@ export class DataProductEditorState extends ElementEditorState {
1046
1046
  }
1047
1047
  this.selectedTab = DATA_PRODUCT_TAB.HOME;
1048
1048
  this.testableState = new DataProductTestableState(this);
1049
+ this.testableState.init();
1049
1050
  }
1050
1051
 
1051
1052
  setDeployOnOpen(value: boolean): void {