@finos/legend-application-studio 13.0.3 → 13.1.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 (170) hide show
  1. package/lib/components/editor/command/project-search.css +1 -1
  2. package/lib/components/editor/command/project-search.css.map +1 -1
  3. package/lib/components/editor/command-center/ProjectSearchCommand.d.ts.map +1 -1
  4. package/lib/components/editor/command-center/ProjectSearchCommand.js +11 -3
  5. package/lib/components/editor/command-center/ProjectSearchCommand.js.map +1 -1
  6. package/lib/components/editor/edit-panel/FunctionEditor.d.ts.map +1 -1
  7. package/lib/components/editor/edit-panel/FunctionEditor.js +41 -34
  8. package/lib/components/editor/edit-panel/FunctionEditor.js.map +1 -1
  9. package/lib/components/editor/edit-panel/GenerationSpecificationEditor.d.ts.map +1 -1
  10. package/lib/components/editor/edit-panel/GenerationSpecificationEditor.js +35 -54
  11. package/lib/components/editor/edit-panel/GenerationSpecificationEditor.js.map +1 -1
  12. package/lib/components/editor/edit-panel/GrammarTextEditor.d.ts.map +1 -1
  13. package/lib/components/editor/edit-panel/GrammarTextEditor.js +2 -2
  14. package/lib/components/editor/edit-panel/GrammarTextEditor.js.map +1 -1
  15. package/lib/components/editor/edit-panel/RuntimeEditor.d.ts.map +1 -1
  16. package/lib/components/editor/edit-panel/RuntimeEditor.js +11 -20
  17. package/lib/components/editor/edit-panel/RuntimeEditor.js.map +1 -1
  18. package/lib/components/editor/edit-panel/data-editor/DataElementEditor.d.ts.map +1 -1
  19. package/lib/components/editor/edit-panel/data-editor/DataElementEditor.js +4 -8
  20. package/lib/components/editor/edit-panel/data-editor/DataElementEditor.js.map +1 -1
  21. package/lib/components/editor/edit-panel/data-editor/RelationalCSVDataEditor.js +1 -1
  22. package/lib/components/editor/edit-panel/data-editor/RelationalCSVDataEditor.js.map +1 -1
  23. package/lib/components/editor/edit-panel/element-generation-editor/FileGenerationEditor.d.ts.map +1 -1
  24. package/lib/components/editor/edit-panel/element-generation-editor/FileGenerationEditor.js +3 -7
  25. package/lib/components/editor/edit-panel/element-generation-editor/FileGenerationEditor.js.map +1 -1
  26. package/lib/components/editor/edit-panel/external-format-editor/BindingElementEditor.d.ts.map +1 -1
  27. package/lib/components/editor/edit-panel/external-format-editor/BindingElementEditor.js +2 -2
  28. package/lib/components/editor/edit-panel/external-format-editor/BindingElementEditor.js.map +1 -1
  29. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.js +1 -1
  30. package/lib/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.js.map +1 -1
  31. package/lib/components/editor/edit-panel/mapping-editor/EnumerationMappingEditor.d.ts.map +1 -1
  32. package/lib/components/editor/edit-panel/mapping-editor/EnumerationMappingEditor.js +2 -9
  33. package/lib/components/editor/edit-panel/mapping-editor/EnumerationMappingEditor.js.map +1 -1
  34. package/lib/components/editor/edit-panel/mapping-editor/FlatDataPropertyMappingEditor.d.ts.map +1 -1
  35. package/lib/components/editor/edit-panel/mapping-editor/FlatDataPropertyMappingEditor.js +3 -4
  36. package/lib/components/editor/edit-panel/mapping-editor/FlatDataPropertyMappingEditor.js.map +1 -1
  37. package/lib/components/editor/edit-panel/mapping-editor/InstanceSetImplementationEditor.d.ts.map +1 -1
  38. package/lib/components/editor/edit-panel/mapping-editor/InstanceSetImplementationEditor.js +3 -10
  39. package/lib/components/editor/edit-panel/mapping-editor/InstanceSetImplementationEditor.js.map +1 -1
  40. package/lib/components/editor/edit-panel/mapping-editor/MappingExecutionBuilder.d.ts.map +1 -1
  41. package/lib/components/editor/edit-panel/mapping-editor/MappingExecutionBuilder.js +4 -10
  42. package/lib/components/editor/edit-panel/mapping-editor/MappingExecutionBuilder.js.map +1 -1
  43. package/lib/components/editor/edit-panel/mapping-editor/MappingExplorer.js +7 -9
  44. package/lib/components/editor/edit-panel/mapping-editor/MappingExplorer.js.map +1 -1
  45. package/lib/components/editor/edit-panel/mapping-editor/MappingTestEditor.d.ts.map +1 -1
  46. package/lib/components/editor/edit-panel/mapping-editor/MappingTestEditor.js +3 -6
  47. package/lib/components/editor/edit-panel/mapping-editor/MappingTestEditor.js.map +1 -1
  48. package/lib/components/editor/edit-panel/mapping-editor/MappingTestsExplorer.d.ts.map +1 -1
  49. package/lib/components/editor/edit-panel/mapping-editor/MappingTestsExplorer.js +7 -8
  50. package/lib/components/editor/edit-panel/mapping-editor/MappingTestsExplorer.js.map +1 -1
  51. package/lib/components/editor/edit-panel/mapping-editor/NewMappingElementModal.d.ts.map +1 -1
  52. package/lib/components/editor/edit-panel/mapping-editor/NewMappingElementModal.js +1 -3
  53. package/lib/components/editor/edit-panel/mapping-editor/NewMappingElementModal.js.map +1 -1
  54. package/lib/components/editor/edit-panel/mapping-editor/OperationSetImplementationEditor.d.ts.map +1 -1
  55. package/lib/components/editor/edit-panel/mapping-editor/OperationSetImplementationEditor.js +5 -7
  56. package/lib/components/editor/edit-panel/mapping-editor/OperationSetImplementationEditor.js.map +1 -1
  57. package/lib/components/editor/edit-panel/mapping-editor/PurePropertyMappingEditor.d.ts.map +1 -1
  58. package/lib/components/editor/edit-panel/mapping-editor/PurePropertyMappingEditor.js +3 -4
  59. package/lib/components/editor/edit-panel/mapping-editor/PurePropertyMappingEditor.js.map +1 -1
  60. package/lib/components/editor/edit-panel/mapping-editor/relational/RelationalPropertyMappingEditor.d.ts.map +1 -1
  61. package/lib/components/editor/edit-panel/mapping-editor/relational/RelationalPropertyMappingEditor.js +1 -1
  62. package/lib/components/editor/edit-panel/mapping-editor/relational/RelationalPropertyMappingEditor.js.map +1 -1
  63. package/lib/components/editor/edit-panel/service-editor/ServiceExecutionEditor.d.ts.map +1 -1
  64. package/lib/components/editor/edit-panel/service-editor/ServiceExecutionEditor.js +3 -5
  65. package/lib/components/editor/edit-panel/service-editor/ServiceExecutionEditor.js.map +1 -1
  66. package/lib/components/editor/edit-panel/service-editor/testable/ServiceTestableEditor.js +1 -1
  67. package/lib/components/editor/edit-panel/service-editor/testable/ServiceTestableEditor.js.map +1 -1
  68. package/lib/components/editor/edit-panel/uml-editor/AssociationEditor.d.ts.map +1 -1
  69. package/lib/components/editor/edit-panel/uml-editor/AssociationEditor.js +4 -8
  70. package/lib/components/editor/edit-panel/uml-editor/AssociationEditor.js.map +1 -1
  71. package/lib/components/editor/edit-panel/uml-editor/ClassEditor.d.ts.map +1 -1
  72. package/lib/components/editor/edit-panel/uml-editor/ClassEditor.js +156 -62
  73. package/lib/components/editor/edit-panel/uml-editor/ClassEditor.js.map +1 -1
  74. package/lib/components/editor/edit-panel/uml-editor/EnumerationEditor.d.ts.map +1 -1
  75. package/lib/components/editor/edit-panel/uml-editor/EnumerationEditor.js +39 -21
  76. package/lib/components/editor/edit-panel/uml-editor/EnumerationEditor.js.map +1 -1
  77. package/lib/components/editor/edit-panel/uml-editor/ProfileEditor.d.ts.map +1 -1
  78. package/lib/components/editor/edit-panel/uml-editor/ProfileEditor.js +62 -9
  79. package/lib/components/editor/edit-panel/uml-editor/ProfileEditor.js.map +1 -1
  80. package/lib/components/editor/edit-panel/uml-editor/PropertyEditor.d.ts.map +1 -1
  81. package/lib/components/editor/edit-panel/uml-editor/PropertyEditor.js +4 -8
  82. package/lib/components/editor/edit-panel/uml-editor/PropertyEditor.js.map +1 -1
  83. package/lib/components/editor/edit-panel/uml-editor/StereotypeSelector.d.ts +7 -1
  84. package/lib/components/editor/edit-panel/uml-editor/StereotypeSelector.d.ts.map +1 -1
  85. package/lib/components/editor/edit-panel/uml-editor/StereotypeSelector.js +33 -5
  86. package/lib/components/editor/edit-panel/uml-editor/StereotypeSelector.js.map +1 -1
  87. package/lib/components/editor/edit-panel/uml-editor/TaggedValueEditor.d.ts +7 -1
  88. package/lib/components/editor/edit-panel/uml-editor/TaggedValueEditor.d.ts.map +1 -1
  89. package/lib/components/editor/edit-panel/uml-editor/TaggedValueEditor.js +35 -7
  90. package/lib/components/editor/edit-panel/uml-editor/TaggedValueEditor.js.map +1 -1
  91. package/lib/components/editor/side-bar/CreateNewElementModal.d.ts.map +1 -1
  92. package/lib/components/editor/side-bar/CreateNewElementModal.js +2 -3
  93. package/lib/components/editor/side-bar/CreateNewElementModal.js.map +1 -1
  94. package/lib/components/editor/side-bar/Explorer.d.ts.map +1 -1
  95. package/lib/components/editor/side-bar/Explorer.js +8 -9
  96. package/lib/components/editor/side-bar/Explorer.js.map +1 -1
  97. package/lib/components/shared/StudioLambdaEditor.d.ts +1 -0
  98. package/lib/components/shared/StudioLambdaEditor.d.ts.map +1 -1
  99. package/lib/components/shared/StudioLambdaEditor.js +2 -2
  100. package/lib/components/shared/StudioLambdaEditor.js.map +1 -1
  101. package/lib/index.css +2 -2
  102. package/lib/index.css.map +1 -1
  103. package/lib/package.json +5 -5
  104. package/lib/stores/EditorStore.d.ts.map +1 -1
  105. package/lib/stores/EditorStore.js +7 -7
  106. package/lib/stores/EditorStore.js.map +1 -1
  107. package/lib/stores/editor/NewElementState.d.ts.map +1 -1
  108. package/lib/stores/editor/NewElementState.js +8 -2
  109. package/lib/stores/editor/NewElementState.js.map +1 -1
  110. package/lib/stores/editor-state/GenerationSpecificationEditorState.d.ts +0 -2
  111. package/lib/stores/editor-state/GenerationSpecificationEditorState.d.ts.map +1 -1
  112. package/lib/stores/editor-state/GenerationSpecificationEditorState.js +1 -8
  113. package/lib/stores/editor-state/GenerationSpecificationEditorState.js.map +1 -1
  114. package/lib/stores/editor-state/element-editor-state/ElementEditorState.d.ts.map +1 -1
  115. package/lib/stores/editor-state/element-editor-state/ElementEditorState.js +2 -4
  116. package/lib/stores/editor-state/element-editor-state/ElementEditorState.js.map +1 -1
  117. package/lib/stores/editor-state/element-editor-state/mapping/MappingEditorState.js +1 -1
  118. package/lib/stores/editor-state/element-editor-state/mapping/MappingEditorState.js.map +1 -1
  119. package/lib/stores/editor-state/element-editor-state/mapping/MappingExecutionState.js +1 -1
  120. package/lib/stores/editor-state/element-editor-state/mapping/MappingExecutionState.js.map +1 -1
  121. package/lib/stores/graphModifier/DomainGraphModifierHelper.d.ts +10 -0
  122. package/lib/stores/graphModifier/DomainGraphModifierHelper.d.ts.map +1 -1
  123. package/lib/stores/graphModifier/DomainGraphModifierHelper.js +31 -1
  124. package/lib/stores/graphModifier/DomainGraphModifierHelper.js.map +1 -1
  125. package/lib/stores/shared/DnDUtil.d.ts +1 -2
  126. package/lib/stores/shared/DnDUtil.d.ts.map +1 -1
  127. package/lib/stores/shared/DnDUtil.js +0 -2
  128. package/lib/stores/shared/DnDUtil.js.map +1 -1
  129. package/package.json +13 -13
  130. package/src/components/editor/command-center/ProjectSearchCommand.tsx +13 -2
  131. package/src/components/editor/edit-panel/FunctionEditor.tsx +220 -152
  132. package/src/components/editor/edit-panel/GenerationSpecificationEditor.tsx +154 -184
  133. package/src/components/editor/edit-panel/GrammarTextEditor.tsx +4 -5
  134. package/src/components/editor/edit-panel/RuntimeEditor.tsx +89 -90
  135. package/src/components/editor/edit-panel/data-editor/DataElementEditor.tsx +57 -40
  136. package/src/components/editor/edit-panel/data-editor/RelationalCSVDataEditor.tsx +1 -1
  137. package/src/components/editor/edit-panel/element-generation-editor/FileGenerationEditor.tsx +50 -45
  138. package/src/components/editor/edit-panel/external-format-editor/BindingElementEditor.tsx +36 -32
  139. package/src/components/editor/edit-panel/external-format-editor/SchemaSetElementEditor.tsx +1 -1
  140. package/src/components/editor/edit-panel/mapping-editor/EnumerationMappingEditor.tsx +46 -41
  141. package/src/components/editor/edit-panel/mapping-editor/FlatDataPropertyMappingEditor.tsx +9 -7
  142. package/src/components/editor/edit-panel/mapping-editor/InstanceSetImplementationEditor.tsx +18 -21
  143. package/src/components/editor/edit-panel/mapping-editor/MappingExecutionBuilder.tsx +39 -29
  144. package/src/components/editor/edit-panel/mapping-editor/MappingExplorer.tsx +39 -39
  145. package/src/components/editor/edit-panel/mapping-editor/MappingTestEditor.tsx +23 -15
  146. package/src/components/editor/edit-panel/mapping-editor/MappingTestsExplorer.tsx +40 -38
  147. package/src/components/editor/edit-panel/mapping-editor/NewMappingElementModal.tsx +1 -3
  148. package/src/components/editor/edit-panel/mapping-editor/OperationSetImplementationEditor.tsx +48 -45
  149. package/src/components/editor/edit-panel/mapping-editor/PurePropertyMappingEditor.tsx +12 -8
  150. package/src/components/editor/edit-panel/mapping-editor/relational/RelationalPropertyMappingEditor.tsx +2 -3
  151. package/src/components/editor/edit-panel/service-editor/ServiceExecutionEditor.tsx +75 -72
  152. package/src/components/editor/edit-panel/service-editor/testable/ServiceTestableEditor.tsx +1 -1
  153. package/src/components/editor/edit-panel/uml-editor/AssociationEditor.tsx +55 -38
  154. package/src/components/editor/edit-panel/uml-editor/ClassEditor.tsx +812 -504
  155. package/src/components/editor/edit-panel/uml-editor/EnumerationEditor.tsx +209 -113
  156. package/src/components/editor/edit-panel/uml-editor/ProfileEditor.tsx +184 -52
  157. package/src/components/editor/edit-panel/uml-editor/PropertyEditor.tsx +62 -39
  158. package/src/components/editor/edit-panel/uml-editor/StereotypeSelector.tsx +137 -52
  159. package/src/components/editor/edit-panel/uml-editor/TaggedValueEditor.tsx +171 -88
  160. package/src/components/editor/side-bar/CreateNewElementModal.tsx +2 -1
  161. package/src/components/editor/side-bar/Explorer.tsx +11 -15
  162. package/src/components/shared/StudioLambdaEditor.tsx +3 -0
  163. package/src/stores/EditorStore.ts +7 -6
  164. package/src/stores/editor/NewElementState.ts +8 -2
  165. package/src/stores/editor-state/GenerationSpecificationEditorState.ts +1 -15
  166. package/src/stores/editor-state/element-editor-state/ElementEditorState.ts +2 -3
  167. package/src/stores/editor-state/element-editor-state/mapping/MappingEditorState.ts +1 -1
  168. package/src/stores/editor-state/element-editor-state/mapping/MappingExecutionState.ts +1 -1
  169. package/src/stores/graphModifier/DomainGraphModifierHelper.ts +92 -0
  170. package/src/stores/shared/DnDUtil.ts +0 -2
@@ -14,13 +14,17 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { useState } from 'react';
17
+ import { useCallback, useRef, useState } from 'react';
18
18
  import { observer } from 'mobx-react-lite';
19
19
  import {
20
20
  CustomSelectorInput,
21
21
  createFilter,
22
22
  TimesIcon,
23
23
  ArrowCircleRightIcon,
24
+ PanelEntryDragHandle,
25
+ PanelEntryDropZonePlaceholder,
26
+ DragPreviewLayer,
27
+ useDragPreviewLayer,
24
28
  } from '@finos/legend-art';
25
29
  import { useEditorStore } from '../../EditorStoreProvider.js';
26
30
  import {
@@ -28,24 +32,54 @@ import {
28
32
  type StereotypeReference,
29
33
  type Stereotype,
30
34
  isStubbed_PackageableElement,
35
+ type AnnotatedElement,
31
36
  } from '@finos/legend-graph';
32
- import { stereotypeReference_setValue } from '../../../../stores/graphModifier/DomainGraphModifierHelper.js';
37
+ import {
38
+ annotatedElement_swapStereotypes,
39
+ stereotypeReference_setValue,
40
+ } from '../../../../stores/graphModifier/DomainGraphModifierHelper.js';
33
41
  import type { PackageableElementOption } from '@finos/legend-application';
42
+ import { useDrop, useDrag } from 'react-dnd';
34
43
 
35
44
  interface StereotypeOption {
36
45
  label: string;
37
46
  value: Stereotype;
38
47
  }
39
48
 
49
+ export const STEREOTYPE_DND_TYPE = 'STEREOTYPE';
50
+ export type StereotypeDragSource = {
51
+ stereotype: StereotypeReference;
52
+ };
53
+
54
+ export const StereotypeDragPreviewLayer: React.FC = () => (
55
+ <DragPreviewLayer
56
+ labelGetter={(item: StereotypeDragSource): string =>
57
+ isStubbed_PackageableElement(item.stereotype.ownerReference.value)
58
+ ? '(unknown)'
59
+ : `${item.stereotype.ownerReference.value.name}.${item.stereotype.value.value}`
60
+ }
61
+ types={[STEREOTYPE_DND_TYPE]}
62
+ />
63
+ );
64
+
40
65
  export const StereotypeSelector = observer(
41
66
  (props: {
67
+ annotatedElement: AnnotatedElement;
42
68
  stereotype: StereotypeReference;
43
69
  deleteStereotype: () => void;
44
70
  isReadOnly: boolean;
45
71
  darkTheme?: boolean;
46
72
  }) => {
47
- const { stereotype, deleteStereotype, isReadOnly, darkTheme } = props;
73
+ const ref = useRef<HTMLDivElement>(null);
74
+ const {
75
+ annotatedElement,
76
+ stereotype,
77
+ deleteStereotype,
78
+ isReadOnly,
79
+ darkTheme,
80
+ } = props;
48
81
  const editorStore = useEditorStore();
82
+
49
83
  // Profile
50
84
  const profileOptions = editorStore.profileOptions.filter(
51
85
  (p) => p.value.p_stereotypes.length,
@@ -59,6 +93,7 @@ export const StereotypeSelector = observer(
59
93
  const [selectedProfile, setSelectedProfile] = useState<
60
94
  PackageableElementOption<Profile>
61
95
  >({ value: stereotype.value._OWNER, label: stereotype.value._OWNER.name });
96
+
62
97
  const changeProfile = (val: PackageableElementOption<Profile>): void => {
63
98
  if (val.value.p_stereotypes.length) {
64
99
  setSelectedProfile(val);
@@ -86,56 +121,106 @@ export const StereotypeSelector = observer(
86
121
  };
87
122
  const updateStereotype = (val: StereotypeOption): void =>
88
123
  stereotypeReference_setValue(stereotype, val.value);
124
+
125
+ // Drag and Drop
126
+ const handleHover = useCallback(
127
+ (item: StereotypeDragSource): void => {
128
+ const draggingProperty = item.stereotype;
129
+ const hoveredProperty = stereotype;
130
+ annotatedElement_swapStereotypes(
131
+ annotatedElement,
132
+ draggingProperty,
133
+ hoveredProperty,
134
+ );
135
+ },
136
+ [annotatedElement, stereotype],
137
+ );
138
+
139
+ const [{ isBeingDraggedStereotype }, dropConnector] = useDrop<
140
+ StereotypeDragSource,
141
+ void,
142
+ { isBeingDraggedStereotype: StereotypeReference | undefined }
143
+ >(
144
+ () => ({
145
+ accept: [STEREOTYPE_DND_TYPE],
146
+ hover: (item) => handleHover(item),
147
+ collect: (monitor) => ({
148
+ isBeingDraggedStereotype:
149
+ monitor.getItem<StereotypeDragSource | null>()?.stereotype,
150
+ }),
151
+ }),
152
+ [handleHover],
153
+ );
154
+ const isBeingDragged = stereotype === isBeingDraggedStereotype;
155
+
156
+ const [, dragConnector, dragPreviewConnector] =
157
+ useDrag<StereotypeDragSource>(
158
+ () => ({
159
+ type: STEREOTYPE_DND_TYPE,
160
+ item: () => ({
161
+ stereotype: stereotype,
162
+ }),
163
+ }),
164
+ [stereotype],
165
+ );
166
+ dragConnector(dropConnector(ref));
167
+ useDragPreviewLayer(dragPreviewConnector);
168
+
89
169
  return (
90
- <div className="stereotype-selector">
91
- <div
92
- className={`stereotype-selector__profile ${
93
- darkTheme ? 'stereotype-selector-dark-theme' : ''
94
- }`}
95
- >
96
- <CustomSelectorInput
97
- className="stereotype-selector__profile__selector"
98
- disabled={isReadOnly}
99
- options={profileOptions}
100
- onChange={changeProfile}
101
- value={selectedProfile}
102
- placeholder={'Choose a profile'}
103
- filterOption={filterOption}
104
- darkMode={Boolean(darkTheme)}
105
- />
106
- <button
107
- className={`stereotype-selector__profile__visit-btn ${
108
- darkTheme ? 'stereotype-selector-dark-theme' : ''
109
- }`}
110
- disabled={isStubbed_PackageableElement(stereotype.value._OWNER)}
111
- onClick={visitProfile}
112
- tabIndex={-1}
113
- title={'Visit profile'}
114
- >
115
- <ArrowCircleRightIcon />
116
- </button>
117
- </div>
118
- <CustomSelectorInput
119
- className="stereotype-selector__stereotype"
120
- disabled={isReadOnly}
121
- options={stereotypeOptions}
122
- onChange={updateStereotype}
123
- value={selectedStereotype}
124
- placeholder={'Choose a stereotype'}
125
- filterOption={stereotypeFilterOption}
126
- darkMode={darkTheme ?? false}
127
- />
128
- {!isReadOnly && (
129
- <button
130
- className="uml-element-editor__remove-btn"
131
- disabled={isReadOnly}
132
- onClick={deleteStereotype}
133
- tabIndex={-1}
134
- title={'Remove'}
135
- >
136
- <TimesIcon />
137
- </button>
138
- )}
170
+ <div ref={ref} className="stereotype-selector__container">
171
+ <PanelEntryDropZonePlaceholder showPlaceholder={isBeingDragged}>
172
+ <div className="stereotype-selector">
173
+ <PanelEntryDragHandle />
174
+ <div
175
+ className={`stereotype-selector__profile ${
176
+ darkTheme ? 'stereotype-selector-dark-theme' : ''
177
+ } stereotype-selector__profile`}
178
+ >
179
+ <CustomSelectorInput
180
+ className="stereotype-selector__profile__selector"
181
+ disabled={isReadOnly}
182
+ options={profileOptions}
183
+ onChange={changeProfile}
184
+ value={selectedProfile}
185
+ placeholder={'Choose a profile'}
186
+ filterOption={filterOption}
187
+ darkMode={Boolean(darkTheme)}
188
+ />
189
+ <button
190
+ className={`stereotype-selector__profile__visit-btn ${
191
+ darkTheme ? 'stereotype-selector-dark-theme' : ''
192
+ }`}
193
+ disabled={isStubbed_PackageableElement(stereotype.value._OWNER)}
194
+ onClick={visitProfile}
195
+ tabIndex={-1}
196
+ title={'Visit profile'}
197
+ >
198
+ <ArrowCircleRightIcon />
199
+ </button>
200
+ </div>
201
+ <CustomSelectorInput
202
+ className="stereotype-selector__stereotype"
203
+ disabled={isReadOnly}
204
+ options={stereotypeOptions}
205
+ onChange={updateStereotype}
206
+ value={selectedStereotype}
207
+ placeholder={'Choose a stereotype'}
208
+ filterOption={stereotypeFilterOption}
209
+ darkMode={darkTheme ?? false}
210
+ />
211
+ {!isReadOnly && (
212
+ <button
213
+ className="uml-element-editor__remove-btn"
214
+ disabled={isReadOnly}
215
+ onClick={deleteStereotype}
216
+ tabIndex={-1}
217
+ title={'Remove'}
218
+ >
219
+ <TimesIcon />
220
+ </button>
221
+ )}
222
+ </div>
223
+ </PanelEntryDropZonePlaceholder>
139
224
  </div>
140
225
  );
141
226
  },
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import { useState } from 'react';
17
+ import { useCallback, useRef, useState } from 'react';
18
18
  import { observer } from 'mobx-react-lite';
19
19
  import {
20
20
  clsx,
@@ -24,6 +24,10 @@ import {
24
24
  TimesIcon,
25
25
  ArrowCircleRightIcon,
26
26
  LongArrowAltUpIcon,
27
+ PanelEntryDragHandle,
28
+ PanelEntryDropZonePlaceholder,
29
+ DragPreviewLayer,
30
+ useDragPreviewLayer,
27
31
  } from '@finos/legend-art';
28
32
  import { useEditorStore } from '../../EditorStoreProvider.js';
29
33
  import {
@@ -31,26 +35,53 @@ import {
31
35
  type Tag,
32
36
  type Profile,
33
37
  isStubbed_PackageableElement,
38
+ type AnnotatedElement,
34
39
  } from '@finos/legend-graph';
35
40
  import {
36
41
  taggedValue_setValue,
37
42
  taggedValue_setTag,
43
+ annotatedElement_swapTaggedValues,
38
44
  } from '../../../../stores/graphModifier/DomainGraphModifierHelper.js';
39
45
  import type { PackageableElementOption } from '@finos/legend-application';
46
+ import { useDrop, useDrag } from 'react-dnd';
40
47
 
41
48
  interface TagOption {
42
49
  label: string;
43
50
  value: Tag;
44
51
  }
45
52
 
53
+ export const TAGGED_VALUE_DND_TYPE = 'TAGGED_VALUE';
54
+ export type TaggedValueDragSource = {
55
+ taggedValue: TaggedValue;
56
+ };
57
+
58
+ export const TaggedValueDragPreviewLayer: React.FC = () => (
59
+ <DragPreviewLayer
60
+ labelGetter={(item: TaggedValueDragSource): string =>
61
+ isStubbed_PackageableElement(item.taggedValue.tag.ownerReference.value)
62
+ ? '(unknown)'
63
+ : `${item.taggedValue.tag.ownerReference.value.name}.${item.taggedValue.tag.value.value}`
64
+ }
65
+ types={[TAGGED_VALUE_DND_TYPE]}
66
+ />
67
+ );
68
+
46
69
  export const TaggedValueEditor = observer(
47
70
  (props: {
71
+ annotatedElement: AnnotatedElement;
48
72
  taggedValue: TaggedValue;
49
73
  deleteValue: () => void;
50
74
  isReadOnly: boolean;
51
75
  darkTheme?: boolean;
52
76
  }) => {
53
- const { taggedValue, deleteValue, isReadOnly, darkTheme } = props;
77
+ const ref = useRef<HTMLDivElement>(null);
78
+ const {
79
+ annotatedElement,
80
+ taggedValue,
81
+ deleteValue,
82
+ isReadOnly,
83
+ darkTheme,
84
+ } = props;
54
85
  const editorStore = useEditorStore();
55
86
  // Name
56
87
  const changeValue: React.ChangeEventHandler<
@@ -101,98 +132,150 @@ export const TaggedValueEditor = observer(
101
132
  const [isExpanded, setIsExpanded] = useState(false);
102
133
  const toggleExpandedMode = (): void => setIsExpanded(!isExpanded);
103
134
 
135
+ // Drag and Drop
136
+ const handleHover = useCallback(
137
+ (item: TaggedValueDragSource) => {
138
+ const draggingProperty = item.taggedValue;
139
+ const hoveredProperty = taggedValue;
140
+ annotatedElement_swapTaggedValues(
141
+ annotatedElement,
142
+ draggingProperty,
143
+ hoveredProperty,
144
+ );
145
+ },
146
+ [annotatedElement, taggedValue],
147
+ );
148
+
149
+ const [{ isBeingDraggedTaggedValue }, dropConnector] = useDrop<
150
+ TaggedValueDragSource,
151
+ void,
152
+ { isBeingDraggedTaggedValue: TaggedValue | undefined }
153
+ >(
154
+ () => ({
155
+ accept: [TAGGED_VALUE_DND_TYPE],
156
+ hover: (item) => handleHover(item),
157
+ collect: (monitor) => ({
158
+ isBeingDraggedTaggedValue:
159
+ monitor.getItem<TaggedValueDragSource | null>()?.taggedValue,
160
+ }),
161
+ }),
162
+ [handleHover],
163
+ );
164
+ const isBeingDragged = taggedValue === isBeingDraggedTaggedValue;
165
+
166
+ const [, dragConnector, dragPreviewConnector] =
167
+ useDrag<TaggedValueDragSource>(
168
+ () => ({
169
+ type: TAGGED_VALUE_DND_TYPE,
170
+ item: () => ({
171
+ taggedValue: taggedValue,
172
+ }),
173
+ }),
174
+ [taggedValue],
175
+ );
176
+ dragConnector(dropConnector(ref));
177
+ useDragPreviewLayer(dragPreviewConnector);
178
+
104
179
  return (
105
- <div className="tagged-value-editor">
106
- <div
107
- className={`tagged-value-editor__profile ${
108
- darkTheme ? 'tagged-value-editor-dark-theme' : ''
109
- }`}
180
+ <div ref={ref} className="tagged-value-editor__container">
181
+ <PanelEntryDropZonePlaceholder
182
+ showPlaceholder={isBeingDragged}
183
+ className="tagged-value-editor__dnd__placeholder"
110
184
  >
111
- <CustomSelectorInput
112
- className="tagged-value-editor__profile__selector"
113
- disabled={isReadOnly}
114
- options={profileOptions}
115
- onChange={changeProfile}
116
- value={selectedProfile}
117
- placeholder={'Choose a profile'}
118
- filterOption={profileFilterOption}
119
- darkMode={darkTheme ?? false}
120
- />
121
- <button
122
- className={`tagged-value-editor__profile__visit-btn ${
123
- darkTheme ? 'tagged-value-editor-dark-theme' : ''
124
- }`}
125
- disabled={isStubbed_PackageableElement(
126
- taggedValue.tag.value._OWNER,
127
- )}
128
- onClick={visitProfile}
129
- tabIndex={-1}
130
- title={'Visit profile'}
131
- >
132
- <ArrowCircleRightIcon />
133
- </button>
134
- </div>
135
- <CustomSelectorInput
136
- className="tagged-value-editor__tag"
137
- disabled={isReadOnly}
138
- options={tagOptions}
139
- onChange={changeTag}
140
- value={selectedTag}
141
- placeholder={'Choose a tag'}
142
- filterOption={tagFilterOption}
143
- darkMode={Boolean(darkTheme)}
144
- />
145
- {!isReadOnly && (
146
- <button
147
- className="uml-element-editor__remove-btn"
148
- disabled={isReadOnly}
149
- onClick={deleteValue}
150
- tabIndex={-1}
151
- title={'Remove'}
152
- >
153
- <TimesIcon />
154
- </button>
155
- )}
156
- <div
157
- className={clsx('tagged-value-editor__value', {
158
- 'tagged-value-editor__value__expanded': isExpanded,
159
- })}
160
- >
161
- {isExpanded && (
162
- <textarea
163
- className={`tagged-value-editor__value__input ${
185
+ <div className="tagged-value-editor">
186
+ <PanelEntryDragHandle />
187
+ <div
188
+ className={`tagged-value-editor__profile ${
164
189
  darkTheme ? 'tagged-value-editor-dark-theme' : ''
165
190
  }`}
166
- spellCheck={false}
191
+ >
192
+ <CustomSelectorInput
193
+ className="tagged-value-editor__profile__selector"
194
+ disabled={isReadOnly}
195
+ options={profileOptions}
196
+ onChange={changeProfile}
197
+ value={selectedProfile}
198
+ placeholder={'Choose a profile'}
199
+ filterOption={profileFilterOption}
200
+ darkMode={darkTheme ?? false}
201
+ />
202
+ <button
203
+ className={`tagged-value-editor__profile__visit-btn ${
204
+ darkTheme ? 'tagged-value-editor-dark-theme' : ''
205
+ }`}
206
+ disabled={isStubbed_PackageableElement(
207
+ taggedValue.tag.value._OWNER,
208
+ )}
209
+ onClick={visitProfile}
210
+ tabIndex={-1}
211
+ title={'Visit profile'}
212
+ >
213
+ <ArrowCircleRightIcon />
214
+ </button>
215
+ </div>
216
+ <CustomSelectorInput
217
+ className="tagged-value-editor__tag"
167
218
  disabled={isReadOnly}
168
- value={taggedValue.value}
169
- onChange={changeValue}
170
- placeholder={`Value`}
219
+ options={tagOptions}
220
+ onChange={changeTag}
221
+ value={selectedTag}
222
+ placeholder={'Choose a tag'}
223
+ filterOption={tagFilterOption}
224
+ darkMode={Boolean(darkTheme)}
171
225
  />
172
- )}
173
- {!isExpanded && (
174
- <input
175
- className={`tagged-value-editor__value__input ${
176
- darkTheme ? 'tagged-value-editor-dark-theme' : ''
177
- }`}
178
- spellCheck={false}
179
- disabled={isReadOnly}
180
- value={taggedValue.value}
181
- onChange={changeValue}
182
- placeholder={`Value`}
183
- />
184
- )}
185
- <button
186
- className={`tagged-value-editor__value__expand-btn ${
187
- darkTheme ? 'tagged-value-editor-dark-theme' : ''
188
- }`}
189
- onClick={toggleExpandedMode}
190
- tabIndex={-1}
191
- title={'Expand/Collapse'}
192
- >
193
- {isExpanded ? <LongArrowAltUpIcon /> : <MoreVerticalIcon />}
194
- </button>
195
- </div>
226
+ {!isReadOnly && (
227
+ <button
228
+ className="uml-element-editor__remove-btn"
229
+ disabled={isReadOnly}
230
+ onClick={deleteValue}
231
+ tabIndex={-1}
232
+ title={'Remove'}
233
+ >
234
+ <TimesIcon />
235
+ </button>
236
+ )}
237
+ <div
238
+ className={clsx('tagged-value-editor__value', {
239
+ 'tagged-value-editor__value__expanded': isExpanded,
240
+ })}
241
+ >
242
+ {isExpanded && (
243
+ <textarea
244
+ className={`tagged-value-editor__value__input ${
245
+ darkTheme ? 'tagged-value-editor-dark-theme' : ''
246
+ }`}
247
+ spellCheck={false}
248
+ disabled={isReadOnly}
249
+ value={taggedValue.value}
250
+ onChange={changeValue}
251
+ placeholder={`Value`}
252
+ />
253
+ )}
254
+ {!isExpanded && (
255
+ <input
256
+ className={`tagged-value-editor__value__input ${
257
+ darkTheme ? 'tagged-value-editor-dark-theme' : ''
258
+ }`}
259
+ spellCheck={false}
260
+ disabled={isReadOnly}
261
+ value={taggedValue.value}
262
+ onChange={changeValue}
263
+ placeholder={`Value`}
264
+ />
265
+ )}
266
+ <button
267
+ className={`tagged-value-editor__value__expand-btn ${
268
+ darkTheme ? 'tagged-value-editor-dark-theme' : ''
269
+ }`}
270
+ onClick={toggleExpandedMode}
271
+ tabIndex={-1}
272
+ title={'Expand/Collapse'}
273
+ >
274
+ {isExpanded ? <LongArrowAltUpIcon /> : <MoreVerticalIcon />}
275
+ </button>
276
+ </div>
277
+ </div>
278
+ </PanelEntryDropZonePlaceholder>
196
279
  </div>
197
280
  );
198
281
  },
@@ -252,7 +252,6 @@ const NewPureModelConnectionDriverEditor = observer(
252
252
  darkMode={true}
253
253
  formatOptionLabel={getPackageableElementOptionFormatter({
254
254
  darkMode: true,
255
- graphManagerState: editorStore.graphManagerState,
256
255
  })}
257
256
  />
258
257
  </div>
@@ -369,6 +368,7 @@ const NewFileGenerationDriverEditor = observer(() => {
369
368
  options={options}
370
369
  onChange={onTypeSelectionChange}
371
370
  value={newConnectionDriver.typeOption}
371
+ darkMode={true}
372
372
  />
373
373
  </div>
374
374
  );
@@ -490,6 +490,7 @@ export const CreateNewElementModal = observer(() => {
490
490
  onChange={handleTypeChange}
491
491
  value={selectedTypeOption}
492
492
  isClearable={false}
493
+ darkMode={true}
493
494
  />
494
495
  )}
495
496
  <input
@@ -71,6 +71,10 @@ import {
71
71
  Package,
72
72
  isValidFullPath,
73
73
  isValidPath,
74
+ isGeneratedElement,
75
+ isSystemElement,
76
+ isDependencyElement,
77
+ isElementReadOnly,
74
78
  } from '@finos/legend-graph';
75
79
  import { useApplicationStore } from '@finos/legend-application';
76
80
  import { PACKAGEABLE_ELEMENT_TYPE } from '../../../stores/shared/ModelUtil.js';
@@ -365,15 +369,11 @@ const PackageTreeNodeContainer = observer(
365
369
  <ChevronRightIcon />
366
370
  );
367
371
 
368
- const iconPackageColor = editorStore.graphManagerState.isGeneratedElement(
369
- node.packageableElement,
370
- )
372
+ const iconPackageColor = isGeneratedElement(node.packageableElement)
371
373
  ? 'color--generated'
372
- : editorStore.graphManagerState.isSystemElement(node.packageableElement)
374
+ : isSystemElement(node.packageableElement)
373
375
  ? 'color--system'
374
- : editorStore.graphManagerState.isDependencyElement(
375
- node.packageableElement,
376
- )
376
+ : isDependencyElement(node.packageableElement)
377
377
  ? 'color--dependency'
378
378
  : '';
379
379
 
@@ -688,12 +688,6 @@ const ProjectExplorerActionPanel = observer((props: { disabled: boolean }) => {
688
688
  });
689
689
  editorStore.explorerTreeState.setTreeData({ ...treeData });
690
690
  };
691
-
692
- const isImmutablePackageTreeNode = (node: PackageTreeNodeData): boolean =>
693
- editorStore.graphManagerState.isGeneratedElement(node.packageableElement) ||
694
- editorStore.graphManagerState.isSystemElement(node.packageableElement) ||
695
- editorStore.graphManagerState.isDependencyElement(node.packageableElement);
696
-
697
691
  const showModelLoader = (): void =>
698
692
  editorStore.openState(editorStore.modelLoaderState);
699
693
 
@@ -713,7 +707,8 @@ const ProjectExplorerActionPanel = observer((props: { disabled: boolean }) => {
713
707
  disabled={
714
708
  disabled ||
715
709
  isInGrammarMode ||
716
- (selectedTreeNode && isImmutablePackageTreeNode(selectedTreeNode))
710
+ (selectedTreeNode &&
711
+ isElementReadOnly(selectedTreeNode.packageableElement))
717
712
  }
718
713
  content={<ExplorerDropdownMenu />}
719
714
  menuProps={{
@@ -727,7 +722,8 @@ const ProjectExplorerActionPanel = observer((props: { disabled: boolean }) => {
727
722
  disabled={
728
723
  disabled ||
729
724
  isInGrammarMode ||
730
- (selectedTreeNode && isImmutablePackageTreeNode(selectedTreeNode))
725
+ (selectedTreeNode &&
726
+ isElementReadOnly(selectedTreeNode.packageableElement))
731
727
  }
732
728
  className="panel__header__action"
733
729
  tabIndex={-1}
@@ -46,6 +46,7 @@ export const StudioLambdaEditor = observer(
46
46
  disablePopUp?: boolean | undefined;
47
47
  useBaseTextEditorSettings?: boolean | undefined;
48
48
  hideErrorBar?: boolean | undefined;
49
+ onEditorFocusEventHandler?: (() => void) | undefined;
49
50
  }) => {
50
51
  const {
51
52
  className,
@@ -60,6 +61,7 @@ export const StudioLambdaEditor = observer(
60
61
  disablePopUp,
61
62
  useBaseTextEditorSettings,
62
63
  hideErrorBar,
64
+ onEditorFocusEventHandler,
63
65
  } = props;
64
66
  const applicationStore = useApplicationStore();
65
67
  const editorStore = useEditorStore();
@@ -134,6 +136,7 @@ export const StudioLambdaEditor = observer(
134
136
  useBaseTextEditorSettings={useBaseTextEditorSettings}
135
137
  hideErrorBar={hideErrorBar}
136
138
  onKeyDownEventHandlers={onKeyDownEventHandlers}
139
+ onEditorFocusEventHandler={onEditorFocusEventHandler}
137
140
  />
138
141
  );
139
142
  },