@finos/legend-application 3.0.3 → 4.0.2

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 (176) hide show
  1. package/lib/application/LegendApplication.d.ts +2 -2
  2. package/lib/application/LegendApplication.d.ts.map +1 -1
  3. package/lib/application/LegendApplication.js +4 -4
  4. package/lib/application/LegendApplication.js.map +1 -1
  5. package/lib/application/LegendApplicationPluginManager.d.ts +3 -3
  6. package/lib/application/LegendApplicationPluginManager.d.ts.map +1 -1
  7. package/lib/components/ActionAlert.d.ts +1 -0
  8. package/lib/components/ActionAlert.d.ts.map +1 -1
  9. package/lib/components/ActionAlert.js +2 -2
  10. package/lib/components/ActionAlert.js.map +1 -1
  11. package/lib/components/ApplicationStoreProvider.d.ts +3 -3
  12. package/lib/components/ApplicationStoreProvider.d.ts.map +1 -1
  13. package/lib/components/ApplicationStoreProvider.js +2 -2
  14. package/lib/components/ApplicationStoreProvider.js.map +1 -1
  15. package/lib/components/ApplicationStoreProviderTestUtils.d.ts +5 -5
  16. package/lib/components/ApplicationStoreProviderTestUtils.d.ts.map +1 -1
  17. package/lib/components/ApplicationStoreProviderTestUtils.js +5 -4
  18. package/lib/components/ApplicationStoreProviderTestUtils.js.map +1 -1
  19. package/lib/components/ApplicationTestID.js +1 -1
  20. package/lib/components/ApplicationTestID.js.map +1 -1
  21. package/lib/components/BasicValueSpecificationEditor.d.ts +44 -0
  22. package/lib/components/BasicValueSpecificationEditor.d.ts.map +1 -0
  23. package/lib/components/BasicValueSpecificationEditor.js +276 -0
  24. package/lib/components/BasicValueSpecificationEditor.js.map +1 -0
  25. package/lib/components/BlockingAlert.d.ts +1 -0
  26. package/lib/components/BlockingAlert.d.ts.map +1 -1
  27. package/lib/components/BlockingAlert.js +1 -1
  28. package/lib/components/BlockingAlert.js.map +1 -1
  29. package/lib/components/CustomDatePicker.d.ts +38 -0
  30. package/lib/components/CustomDatePicker.d.ts.map +1 -0
  31. package/lib/components/CustomDatePicker.js +592 -0
  32. package/lib/components/CustomDatePicker.js.map +1 -0
  33. package/lib/components/DocumentationLink.d.ts +1 -1
  34. package/lib/components/DocumentationLink.js +2 -2
  35. package/lib/components/DocumentationLink.js.map +1 -1
  36. package/lib/components/LambdaEditor.d.ts +2 -1
  37. package/lib/components/LambdaEditor.d.ts.map +1 -1
  38. package/lib/components/LambdaEditor.js +3 -3
  39. package/lib/components/LambdaEditor.js.map +1 -1
  40. package/lib/components/LambdaParameterValuesEditor.d.ts +25 -0
  41. package/lib/components/LambdaParameterValuesEditor.d.ts.map +1 -0
  42. package/lib/components/LambdaParameterValuesEditor.js +52 -0
  43. package/lib/components/LambdaParameterValuesEditor.js.map +1 -0
  44. package/lib/components/LegendApplicationComponentFrameworkProvider.d.ts +1 -1
  45. package/lib/components/LegendApplicationComponentFrameworkProvider.js +3 -3
  46. package/lib/components/LegendApplicationComponentFrameworkProvider.js.map +1 -1
  47. package/lib/components/LegendApplicationNavigationContextServiceUtils.d.ts +32 -0
  48. package/lib/components/LegendApplicationNavigationContextServiceUtils.d.ts.map +1 -0
  49. package/lib/components/LegendApplicationNavigationContextServiceUtils.js +57 -0
  50. package/lib/components/LegendApplicationNavigationContextServiceUtils.js.map +1 -0
  51. package/lib/components/NotificationManager.d.ts +1 -0
  52. package/lib/components/NotificationManager.d.ts.map +1 -1
  53. package/lib/components/NotificationManager.js +2 -2
  54. package/lib/components/NotificationManager.js.map +1 -1
  55. package/lib/components/TextInputEditor.d.ts +2 -2
  56. package/lib/components/TextInputEditor.d.ts.map +1 -1
  57. package/lib/components/TextInputEditor.js +2 -2
  58. package/lib/components/TextInputEditor.js.map +1 -1
  59. package/lib/components/{AppHeader.d.ts → VirtualAssistant.d.ts} +5 -5
  60. package/lib/components/VirtualAssistant.d.ts.map +1 -0
  61. package/lib/components/VirtualAssistant.js +171 -0
  62. package/lib/components/VirtualAssistant.js.map +1 -0
  63. package/lib/components/WebApplicationNavigatorProvider.d.ts +2 -2
  64. package/lib/components/WebApplicationNavigatorProvider.d.ts.map +1 -1
  65. package/lib/components/WebApplicationNavigatorProvider.js +1 -1
  66. package/lib/components/WebApplicationNavigatorProvider.js.map +1 -1
  67. package/lib/components/WebApplicationNavigatorProviderTestUtils.d.ts +2 -2
  68. package/lib/components/WebApplicationNavigatorProviderTestUtils.d.ts.map +1 -1
  69. package/lib/components/WebApplicationNavigatorProviderTestUtils.js +3 -2
  70. package/lib/components/WebApplicationNavigatorProviderTestUtils.js.map +1 -1
  71. package/lib/const.js +2 -2
  72. package/lib/const.js.map +1 -1
  73. package/lib/index.css +2 -2
  74. package/lib/index.css.map +1 -1
  75. package/lib/index.d.ts +30 -22
  76. package/lib/index.d.ts.map +1 -1
  77. package/lib/index.js +32 -22
  78. package/lib/index.js.map +1 -1
  79. package/lib/stores/ApplicationEvent.d.ts +9 -7
  80. package/lib/stores/ApplicationEvent.d.ts.map +1 -1
  81. package/lib/stores/ApplicationEvent.js +10 -8
  82. package/lib/stores/ApplicationEvent.js.map +1 -1
  83. package/lib/stores/ApplicationStore.d.ts +15 -9
  84. package/lib/stores/ApplicationStore.d.ts.map +1 -1
  85. package/lib/stores/ApplicationStore.js +26 -21
  86. package/lib/stores/ApplicationStore.js.map +1 -1
  87. package/lib/stores/ApplicationStoreTestUtils.d.ts +3 -3
  88. package/lib/stores/ApplicationStoreTestUtils.d.ts.map +1 -1
  89. package/lib/stores/ApplicationStoreTestUtils.js +2 -2
  90. package/lib/stores/ApplicationStoreTestUtils.js.map +1 -1
  91. package/lib/stores/ApplicationTelemetry.d.ts +1 -1
  92. package/lib/stores/ApplicationTelemetry.d.ts.map +1 -1
  93. package/lib/stores/ApplicationTelemetry.js +2 -2
  94. package/lib/stores/ApplicationTelemetry.js.map +1 -1
  95. package/lib/stores/CJS__Fuse.cjs +35 -0
  96. package/lib/stores/CJS__Fuse.cjs.map +1 -0
  97. package/lib/stores/CJS__Fuse.d.cts +28 -0
  98. package/lib/stores/CJS__Fuse.d.cts.map +1 -0
  99. package/lib/stores/LambdaParameterState.d.ts +59 -0
  100. package/lib/stores/LambdaParameterState.d.ts.map +1 -0
  101. package/lib/stores/LambdaParameterState.js +184 -0
  102. package/lib/stores/LambdaParameterState.js.map +1 -0
  103. package/lib/stores/LegendApplicationAssistantService.d.ts +63 -0
  104. package/lib/stores/LegendApplicationAssistantService.d.ts.map +1 -0
  105. package/lib/stores/LegendApplicationAssistantService.js +167 -0
  106. package/lib/stores/LegendApplicationAssistantService.js.map +1 -0
  107. package/lib/stores/LegendApplicationConfig.d.ts +5 -4
  108. package/lib/stores/LegendApplicationConfig.d.ts.map +1 -1
  109. package/lib/stores/LegendApplicationConfig.js +8 -3
  110. package/lib/stores/LegendApplicationConfig.js.map +1 -1
  111. package/lib/stores/LegendApplicationDocumentationService.d.ts +70 -0
  112. package/lib/stores/LegendApplicationDocumentationService.d.ts.map +1 -0
  113. package/lib/stores/LegendApplicationDocumentationService.js +152 -0
  114. package/lib/stores/LegendApplicationDocumentationService.js.map +1 -0
  115. package/lib/stores/LegendApplicationEventService.d.ts +22 -0
  116. package/lib/stores/LegendApplicationEventService.d.ts.map +1 -0
  117. package/lib/stores/LegendApplicationEventService.js +25 -0
  118. package/lib/stores/LegendApplicationEventService.js.map +1 -0
  119. package/lib/stores/LegendApplicationNavigationContextService.d.ts +74 -0
  120. package/lib/stores/LegendApplicationNavigationContextService.d.ts.map +1 -0
  121. package/lib/stores/LegendApplicationNavigationContextService.js +118 -0
  122. package/lib/stores/LegendApplicationNavigationContextService.js.map +1 -0
  123. package/lib/stores/LegendApplicationPlugin.d.ts +6 -2
  124. package/lib/stores/LegendApplicationPlugin.d.ts.map +1 -1
  125. package/lib/stores/LegendApplicationPlugin.js.map +1 -1
  126. package/lib/stores/PureLanguageSupport.d.ts.map +1 -1
  127. package/lib/stores/PureLanguageSupport.js +8 -2
  128. package/lib/stores/PureLanguageSupport.js.map +1 -1
  129. package/lib/stores/ValueSpecificationModifierHelper.d.ts +27 -0
  130. package/lib/stores/ValueSpecificationModifierHelper.d.ts.map +1 -0
  131. package/lib/stores/ValueSpecificationModifierHelper.js +49 -0
  132. package/lib/stores/ValueSpecificationModifierHelper.js.map +1 -0
  133. package/package.json +24 -18
  134. package/src/application/LegendApplication.tsx +6 -6
  135. package/src/application/LegendApplicationPluginManager.tsx +3 -3
  136. package/src/components/ActionAlert.tsx +2 -2
  137. package/src/components/ApplicationStoreProvider.tsx +4 -4
  138. package/src/components/ApplicationStoreProviderTestUtils.tsx +7 -6
  139. package/src/components/BasicValueSpecificationEditor.tsx +703 -0
  140. package/src/components/BlockingAlert.tsx +1 -1
  141. package/src/components/CustomDatePicker.tsx +1235 -0
  142. package/src/components/DocumentationLink.tsx +2 -2
  143. package/src/components/LambdaEditor.tsx +4 -4
  144. package/src/components/LambdaParameterValuesEditor.tsx +114 -0
  145. package/src/components/LegendApplicationComponentFrameworkProvider.tsx +3 -3
  146. package/src/components/LegendApplicationNavigationContextServiceUtils.tsx +63 -0
  147. package/src/components/NotificationManager.tsx +2 -2
  148. package/src/components/TextInputEditor.tsx +2 -2
  149. package/src/components/VirtualAssistant.tsx +600 -0
  150. package/src/components/WebApplicationNavigatorProvider.tsx +1 -1
  151. package/src/components/WebApplicationNavigatorProviderTestUtils.tsx +3 -2
  152. package/src/index.ts +39 -28
  153. package/src/stores/ApplicationEvent.ts +11 -7
  154. package/src/stores/ApplicationStore.ts +29 -27
  155. package/src/stores/ApplicationStoreTestUtils.ts +4 -4
  156. package/src/stores/ApplicationTelemetry.ts +2 -2
  157. package/src/stores/CJS__Fuse.cts +28 -0
  158. package/src/stores/LambdaParameterState.ts +314 -0
  159. package/src/stores/LegendApplicationAssistantService.ts +218 -0
  160. package/src/stores/LegendApplicationConfig.ts +20 -6
  161. package/src/stores/LegendApplicationDocumentationService.ts +276 -0
  162. package/src/stores/LegendApplicationEventService.ts +32 -0
  163. package/src/stores/LegendApplicationNavigationContextService.ts +131 -0
  164. package/src/stores/LegendApplicationPlugin.ts +10 -2
  165. package/src/stores/PureLanguageSupport.ts +8 -2
  166. package/src/stores/ValueSpecificationModifierHelper.ts +104 -0
  167. package/tsconfig.json +18 -12
  168. package/lib/components/AppHeader.d.ts.map +0 -1
  169. package/lib/components/AppHeader.js +0 -26
  170. package/lib/components/AppHeader.js.map +0 -1
  171. package/lib/stores/LegendApplicationDocumentationRegistry.d.ts +0 -36
  172. package/lib/stores/LegendApplicationDocumentationRegistry.d.ts.map +0 -1
  173. package/lib/stores/LegendApplicationDocumentationRegistry.js +0 -47
  174. package/lib/stores/LegendApplicationDocumentationRegistry.js.map +0 -1
  175. package/src/components/AppHeader.tsx +0 -49
  176. package/src/stores/LegendApplicationDocumentationRegistry.ts +0 -81
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import { action, makeObservable, observable, computed } from 'mobx';
18
+ import type {
19
+ LegendApplicationContextualDocumentationEntry,
20
+ LegendApplicationDocumentationEntry,
21
+ } from './LegendApplicationDocumentationService.js';
22
+ import type { LegendApplicationConfig } from './LegendApplicationConfig.js';
23
+ import type { ApplicationStore } from './ApplicationStore.js';
24
+ import { Fuse } from './CJS__Fuse.cjs';
25
+ import {
26
+ type MarkdownText,
27
+ guaranteeNonEmptyString,
28
+ uuid,
29
+ isNonNullable,
30
+ ActionState,
31
+ } from '@finos/legend-shared';
32
+
33
+ export enum VIRTUAL_ASSISTANT_TAB {
34
+ SEARCH = 'SEARCH',
35
+ CONTEXTUAL_SUPPORT = 'CONTEXTUAL_SUPPORT',
36
+ }
37
+
38
+ export class VirtualAssistantDocumentationEntry {
39
+ uuid = uuid();
40
+ documentationKey: string;
41
+ title: string;
42
+ content?: string | MarkdownText | undefined;
43
+ url?: string | undefined;
44
+ isOpen = false;
45
+
46
+ constructor(docEntry: LegendApplicationDocumentationEntry) {
47
+ makeObservable(this, {
48
+ isOpen: observable,
49
+ setIsOpen: action,
50
+ });
51
+
52
+ this.documentationKey = docEntry._documentationKey;
53
+ this.title = guaranteeNonEmptyString(docEntry.title);
54
+ this.content = docEntry.markdownText ?? docEntry.text;
55
+ this.url = docEntry.url;
56
+ }
57
+
58
+ setIsOpen(val: boolean): void {
59
+ this.isOpen = val;
60
+ }
61
+ }
62
+
63
+ export class VirtualAssistantContextualDocumentationEntry {
64
+ uuid = uuid();
65
+ context: string;
66
+ title?: string | undefined;
67
+ content?: string | MarkdownText | undefined;
68
+ url?: string | undefined;
69
+ related: VirtualAssistantDocumentationEntry[];
70
+
71
+ constructor(
72
+ contextualDocEntry: LegendApplicationContextualDocumentationEntry,
73
+ related: VirtualAssistantDocumentationEntry[],
74
+ ) {
75
+ this.context = contextualDocEntry._context;
76
+ this.title = contextualDocEntry.title;
77
+ this.content = contextualDocEntry.markdownText ?? contextualDocEntry.text;
78
+ this.url = contextualDocEntry.url;
79
+ this.related = related;
80
+ }
81
+ }
82
+
83
+ export class LegendApplicationAssistantService {
84
+ readonly applicationStore: ApplicationStore<LegendApplicationConfig>;
85
+ private readonly searchEngine: Fuse<LegendApplicationDocumentationEntry>;
86
+ isHidden = false;
87
+ isOpen = false;
88
+ selectedTab = VIRTUAL_ASSISTANT_TAB.SEARCH;
89
+
90
+ searchResults: VirtualAssistantDocumentationEntry[] = [];
91
+ searchState = ActionState.create().pass();
92
+ searchText = '';
93
+
94
+ constructor(applicationStore: ApplicationStore<LegendApplicationConfig>) {
95
+ makeObservable(this, {
96
+ isHidden: observable,
97
+ isOpen: observable,
98
+ selectedTab: observable,
99
+ searchText: observable,
100
+ searchResults: observable,
101
+ currentContextualDocumentationEntry: computed,
102
+ setIsHidden: action,
103
+ setIsOpen: action,
104
+ setSelectedTab: action,
105
+ setSearchText: action,
106
+ resetSearch: action,
107
+ search: action,
108
+ });
109
+
110
+ this.applicationStore = applicationStore;
111
+ this.searchEngine = new Fuse(
112
+ this.applicationStore.documentationService.getAllDocEntries().filter(
113
+ (entry) =>
114
+ // NOTE: since we're searching for user-friendly docs, we will discard anything that
115
+ // doesn't come with a title, or does not have any content/url
116
+ entry.title && (entry.url ?? entry.text ?? entry.markdownText),
117
+ ),
118
+ {
119
+ includeScore: true,
120
+ shouldSort: true,
121
+ // Ignore location when computing the search score
122
+ // See https://fusejs.io/concepts/scoring-theory.html
123
+ ignoreLocation: true,
124
+ // This specifies the point the search gives up
125
+ // `0.0` means exact match where `1.0` would match anything
126
+ // We set a relatively low threshold to filter out irrelevant results
127
+ threshold: 0.2,
128
+ keys: [
129
+ {
130
+ // NOTE: for now, we would weight title the most
131
+ name: 'title',
132
+ weight: 4,
133
+ },
134
+ {
135
+ name: 'text',
136
+ weight: 1,
137
+ },
138
+ {
139
+ name: 'markdownText.value',
140
+ weight: 1,
141
+ },
142
+ ],
143
+ },
144
+ );
145
+ }
146
+
147
+ get currentContextualDocumentationEntry():
148
+ | VirtualAssistantContextualDocumentationEntry
149
+ | undefined {
150
+ const currentContextualDocumentationEntry = this.applicationStore
151
+ .navigationContextService.currentContext
152
+ ? this.applicationStore.documentationService.getContextualDocEntry(
153
+ this.applicationStore.navigationContextService.currentContext.value,
154
+ )
155
+ : undefined;
156
+ return currentContextualDocumentationEntry
157
+ ? new VirtualAssistantContextualDocumentationEntry(
158
+ currentContextualDocumentationEntry,
159
+ currentContextualDocumentationEntry.related
160
+ .map((entry) =>
161
+ this.applicationStore.documentationService.getDocEntry(entry),
162
+ )
163
+ .filter(isNonNullable)
164
+ .filter(
165
+ (entry) =>
166
+ // NOTE: since we're searching for user-friendly docs, we will discard anything that
167
+ // doesn't come with a title, or does not have any content/url
168
+ entry.title && (entry.url ?? entry.text ?? entry.markdownText),
169
+ )
170
+ .map((entry) => new VirtualAssistantDocumentationEntry(entry)),
171
+ )
172
+ : undefined;
173
+ }
174
+
175
+ setIsHidden(val: boolean): void {
176
+ this.isHidden = val;
177
+ }
178
+
179
+ hideAssistant(): void {
180
+ this.setIsHidden(true);
181
+ this.setIsOpen(false);
182
+ }
183
+
184
+ toggleAssistant(): void {
185
+ const newVal = !this.isHidden;
186
+ if (newVal) {
187
+ this.hideAssistant();
188
+ } else {
189
+ this.setIsHidden(false);
190
+ }
191
+ }
192
+
193
+ setIsOpen(val: boolean): void {
194
+ this.isOpen = val;
195
+ }
196
+
197
+ setSelectedTab(val: VIRTUAL_ASSISTANT_TAB): void {
198
+ this.selectedTab = val;
199
+ }
200
+
201
+ setSearchText(val: string): void {
202
+ this.searchText = val;
203
+ }
204
+
205
+ resetSearch(): void {
206
+ this.searchText = '';
207
+ this.searchResults = [];
208
+ this.searchState.complete();
209
+ }
210
+
211
+ search(): void {
212
+ this.searchState.inProgress();
213
+ this.searchResults = Array.from(
214
+ this.searchEngine.search(this.searchText).values(),
215
+ ).map((result) => new VirtualAssistantDocumentationEntry(result.item));
216
+ this.searchState.complete();
217
+ }
218
+ }
@@ -17,13 +17,15 @@
17
17
  import {
18
18
  guaranteeNonEmptyString,
19
19
  guaranteeNonNullable,
20
- type PlainObject,
21
20
  } from '@finos/legend-shared';
22
21
  import {
23
22
  type LegendApplicationKeyedDocumentationEntry,
24
- type LegendApplicationDocumentationEntry,
23
+ type LegendApplicationDocumentationEntryConfig,
24
+ type LegendApplicationKeyedContextualDocumentationEntry,
25
+ type LegendApplicationContextualDocumentationEntryConfig,
25
26
  collectKeyedDocumnetationEntriesFromConfig,
26
- } from './LegendApplicationDocumentationRegistry';
27
+ collectKeyedContextualDocumentationEntriesFromConfig,
28
+ } from './LegendApplicationDocumentationService.js';
27
29
 
28
30
  export interface LegendApplicationVersionData {
29
31
  buildTime: string;
@@ -36,7 +38,11 @@ export interface LegendApplicationConfigurationData {
36
38
  env: string;
37
39
  documentation?: {
38
40
  url: string;
39
- entries?: Record<string, PlainObject<LegendApplicationDocumentationEntry>>;
41
+ entries?: Record<string, LegendApplicationDocumentationEntryConfig>;
42
+ contextualEntries?: Record<
43
+ string,
44
+ LegendApplicationContextualDocumentationEntryConfig
45
+ >;
40
46
  };
41
47
  // TODO: when we support vault-like settings
42
48
  // See https://github.com/finos/legend-studio/issues/407
@@ -49,10 +55,14 @@ export abstract class LegendApplicationConfig {
49
55
  readonly baseUrl: string;
50
56
  readonly env: string;
51
57
 
58
+ // documentation
52
59
  readonly documentationUrl: string | undefined;
53
- readonly documentationKeyedEntries: LegendApplicationKeyedDocumentationEntry[] =
60
+ readonly keyedDocumentationEntries: LegendApplicationKeyedDocumentationEntry[] =
61
+ [];
62
+ readonly keyedContextualDocumentationEntries: LegendApplicationKeyedContextualDocumentationEntry[] =
54
63
  [];
55
64
 
65
+ // version
56
66
  readonly appVersion: string;
57
67
  readonly appVersionBuildTime: string;
58
68
  readonly appVersionCommitId: string;
@@ -74,9 +84,13 @@ export abstract class LegendApplicationConfig {
74
84
 
75
85
  // Documentation
76
86
  this.documentationUrl = configData.documentation?.url;
77
- this.documentationKeyedEntries = collectKeyedDocumnetationEntriesFromConfig(
87
+ this.keyedDocumentationEntries = collectKeyedDocumnetationEntriesFromConfig(
78
88
  configData.documentation?.entries ?? {},
79
89
  );
90
+ this.keyedContextualDocumentationEntries =
91
+ collectKeyedContextualDocumentationEntriesFromConfig(
92
+ configData.documentation?.contextualEntries ?? {},
93
+ );
80
94
 
81
95
  // Version
82
96
  this.appVersion = guaranteeNonNullable(
@@ -0,0 +1,276 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import {
18
+ type MarkdownText,
19
+ type PlainObject,
20
+ type Writable,
21
+ SerializationFactory,
22
+ LogEvent,
23
+ uniq,
24
+ guaranteeNonNullable,
25
+ } from '@finos/legend-shared';
26
+ import {
27
+ createModelSchema,
28
+ custom,
29
+ list,
30
+ optional,
31
+ primitive,
32
+ } from 'serializr';
33
+ import { APPLICATION_EVENT } from './ApplicationEvent.js';
34
+ import type { ApplicationStore } from './ApplicationStore.js';
35
+ import type { LegendApplicationConfig } from './LegendApplicationConfig.js';
36
+
37
+ export type LegendApplicationDocumentationEntryConfig = {
38
+ markdownText?: MarkdownText | undefined;
39
+ title?: string | undefined;
40
+ text?: string | undefined;
41
+ url?: string | undefined;
42
+ };
43
+
44
+ export class LegendApplicationDocumentationEntry {
45
+ readonly _documentationKey!: string;
46
+
47
+ markdownText?: MarkdownText | undefined;
48
+ title?: string | undefined;
49
+ text?: string | undefined;
50
+ url?: string | undefined;
51
+
52
+ static readonly serialization = new SerializationFactory(
53
+ createModelSchema(LegendApplicationDocumentationEntry, {
54
+ markdownText: custom(
55
+ (val) => val,
56
+ (val) => (val.value ? val : undefined),
57
+ ),
58
+ title: optional(primitive()),
59
+ text: optional(primitive()),
60
+ url: optional(primitive()),
61
+ }),
62
+ );
63
+
64
+ static create(
65
+ json: PlainObject<LegendApplicationDocumentationEntry>,
66
+ documentationKey: string,
67
+ ): LegendApplicationDocumentationEntry {
68
+ const entry =
69
+ LegendApplicationDocumentationEntry.serialization.fromJson(json);
70
+ (entry as Writable<LegendApplicationDocumentationEntry>)._documentationKey =
71
+ documentationKey;
72
+ return entry;
73
+ }
74
+ }
75
+
76
+ export type LegendApplicationContextualDocumentationEntryConfig =
77
+ LegendApplicationDocumentationEntryConfig & {
78
+ related?: string[];
79
+ };
80
+
81
+ export class LegendApplicationContextualDocumentationEntry {
82
+ readonly _context!: string;
83
+
84
+ markdownText?: MarkdownText | undefined;
85
+ title?: string | undefined;
86
+ text?: string | undefined;
87
+ url?: string | undefined;
88
+ related: string[] = [];
89
+
90
+ static readonly serialization = new SerializationFactory(
91
+ createModelSchema(LegendApplicationContextualDocumentationEntry, {
92
+ markdownText: custom(
93
+ (val) => val,
94
+ (val) => (val.value ? val : undefined),
95
+ ),
96
+ title: optional(primitive()),
97
+ text: optional(primitive()),
98
+ url: optional(primitive()),
99
+ related: list(primitive()),
100
+ }),
101
+ );
102
+
103
+ static create(
104
+ json: PlainObject<LegendApplicationContextualDocumentationEntry>,
105
+ context: string,
106
+ ): LegendApplicationContextualDocumentationEntry {
107
+ const entry =
108
+ LegendApplicationContextualDocumentationEntry.serialization.fromJson(
109
+ json,
110
+ );
111
+ (
112
+ entry as Writable<LegendApplicationContextualDocumentationEntry>
113
+ )._context = context;
114
+ return entry;
115
+ }
116
+ }
117
+
118
+ export interface LegendApplicationKeyedContextualDocumentationEntry {
119
+ key: string;
120
+ content: LegendApplicationContextualDocumentationEntry;
121
+ }
122
+
123
+ export const collectKeyedContextualDocumentationEntriesFromConfig = (
124
+ rawEntries: Record<
125
+ string,
126
+ LegendApplicationContextualDocumentationEntryConfig
127
+ >,
128
+ ): LegendApplicationKeyedContextualDocumentationEntry[] =>
129
+ Object.entries(rawEntries).map((entry) => ({
130
+ key: entry[0],
131
+ content: LegendApplicationContextualDocumentationEntry.create(
132
+ entry[1],
133
+ entry[0],
134
+ ),
135
+ }));
136
+
137
+ export interface LegendApplicationKeyedDocumentationEntry {
138
+ key: string;
139
+ content: LegendApplicationDocumentationEntry;
140
+ }
141
+
142
+ export const collectKeyedDocumnetationEntriesFromConfig = (
143
+ rawEntries: Record<string, LegendApplicationDocumentationEntryConfig>,
144
+ ): LegendApplicationKeyedDocumentationEntry[] =>
145
+ Object.entries(rawEntries).map((entry) => ({
146
+ key: entry[0],
147
+ content: LegendApplicationDocumentationEntry.create(entry[1], entry[0]),
148
+ }));
149
+
150
+ export class LegendApplicationDocumentationService {
151
+ url?: string | undefined;
152
+
153
+ private docRegistry = new Map<string, LegendApplicationDocumentationEntry>();
154
+ private contextualDocRegistry = new Map<
155
+ string,
156
+ LegendApplicationContextualDocumentationEntry
157
+ >();
158
+
159
+ constructor(applicationStore: ApplicationStore<LegendApplicationConfig>) {
160
+ applicationStore.pluginManager
161
+ .getApplicationPlugins()
162
+ .flatMap((plugin) => plugin.getExtraKeyedDocumentationEntries?.() ?? [])
163
+ .forEach((entry) => {
164
+ // Entries specified natively will not override each other. This is to prevent entries from extensions
165
+ // overriding entries from core.
166
+ if (this.hasDocEntry(entry.key)) {
167
+ applicationStore.log.warn(
168
+ LogEvent.create(
169
+ APPLICATION_EVENT.APPLICATION_DOCUMTENTION_LOAD_SKIPPED,
170
+ ),
171
+ entry.key,
172
+ );
173
+ } else {
174
+ this.docRegistry.set(entry.key, entry.content);
175
+ }
176
+ });
177
+ // entries from config will override entries specified natively
178
+ applicationStore.config.keyedDocumentationEntries.forEach((entry) =>
179
+ this.docRegistry.set(entry.key, entry.content),
180
+ );
181
+
182
+ // Contextual Documentation
183
+ applicationStore.pluginManager
184
+ .getApplicationPlugins()
185
+ .flatMap(
186
+ (plugin) =>
187
+ plugin.getExtraKeyedContextualDocumentationEntries?.() ?? [],
188
+ )
189
+ .forEach((entry) => {
190
+ // Entries specified natively will not override each other. This is to prevent entries from extensions
191
+ // overriding entries from core. However, we will merge the list of related doc entries. This allows
192
+ // extensions to broaden related doc entries for certain contexts
193
+ if (this.hasContextualDocEntry(entry.key)) {
194
+ applicationStore.log.warn(
195
+ LogEvent.create(
196
+ APPLICATION_EVENT.APPLICATION_CONTEXTUAL_DOCUMTENTION_LOAD_SKIPPED,
197
+ ),
198
+ entry.key,
199
+ );
200
+ const existingEntry = guaranteeNonNullable(
201
+ this.getContextualDocEntry(entry.key),
202
+ );
203
+ existingEntry.related = uniq([
204
+ ...existingEntry.related,
205
+ ...entry.content.related,
206
+ ]);
207
+ } else {
208
+ this.contextualDocRegistry.set(entry.key, entry.content);
209
+ }
210
+ });
211
+ // entries from config will override entries specified natively
212
+ // however, we will keep merging related doc entries list
213
+ applicationStore.config.keyedContextualDocumentationEntries.forEach(
214
+ (entry) => {
215
+ const existingEntry = this.getContextualDocEntry(entry.key);
216
+ if (existingEntry) {
217
+ entry.content.related = uniq([
218
+ ...existingEntry.related,
219
+ ...entry.content.related,
220
+ ]);
221
+ }
222
+ this.contextualDocRegistry.set(entry.key, entry.content);
223
+ },
224
+ );
225
+ this.url = applicationStore.config.documentationUrl;
226
+ }
227
+
228
+ getDocEntry(key: string): LegendApplicationDocumentationEntry | undefined {
229
+ return this.docRegistry.get(key);
230
+ }
231
+
232
+ hasDocEntry(key: string): boolean {
233
+ return this.docRegistry.has(key);
234
+ }
235
+
236
+ getContextualDocEntry(
237
+ key: string,
238
+ ): LegendApplicationContextualDocumentationEntry | undefined {
239
+ return this.contextualDocRegistry.get(key);
240
+ }
241
+
242
+ hasContextualDocEntry(key: string): boolean {
243
+ return this.contextualDocRegistry.has(key);
244
+ }
245
+
246
+ getAllDocEntries(): LegendApplicationDocumentationEntry[] {
247
+ return Array.from(this.docRegistry.values());
248
+ }
249
+
250
+ publishDocRegistry(): Record<
251
+ string,
252
+ LegendApplicationDocumentationEntryConfig
253
+ > {
254
+ const result: Record<string, LegendApplicationDocumentationEntryConfig> =
255
+ {};
256
+ this.docRegistry.forEach((value, key) => {
257
+ result[key] =
258
+ LegendApplicationDocumentationEntry.serialization.toJson(value);
259
+ });
260
+ return result;
261
+ }
262
+
263
+ publishContextualDocRegistry(): object {
264
+ const result: Record<
265
+ string,
266
+ LegendApplicationContextualDocumentationEntryConfig
267
+ > = {};
268
+ this.contextualDocRegistry.forEach((value, key) => {
269
+ result[key] =
270
+ LegendApplicationContextualDocumentationEntry.serialization.toJson(
271
+ value,
272
+ );
273
+ });
274
+ return result;
275
+ }
276
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Copyright (c) 2020-present, Goldman Sachs
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ import type {
18
+ NotificationEventData,
19
+ EventNotifierPlugin,
20
+ } from '@finos/legend-shared';
21
+
22
+ export class LegendApplicationEventService {
23
+ private notifierPlugins: EventNotifierPlugin[] = [];
24
+
25
+ registerEventNotifierPlugins(plugins: EventNotifierPlugin[]): void {
26
+ this.notifierPlugins = plugins;
27
+ }
28
+
29
+ notify(event: string, data: NotificationEventData): void {
30
+ this.notifierPlugins.forEach((plugin) => plugin.notify(event, data));
31
+ }
32
+ }