@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.
- package/lib/application/LegendApplication.d.ts +2 -2
- package/lib/application/LegendApplication.d.ts.map +1 -1
- package/lib/application/LegendApplication.js +4 -4
- package/lib/application/LegendApplication.js.map +1 -1
- package/lib/application/LegendApplicationPluginManager.d.ts +3 -3
- package/lib/application/LegendApplicationPluginManager.d.ts.map +1 -1
- package/lib/components/ActionAlert.d.ts +1 -0
- package/lib/components/ActionAlert.d.ts.map +1 -1
- package/lib/components/ActionAlert.js +2 -2
- package/lib/components/ActionAlert.js.map +1 -1
- package/lib/components/ApplicationStoreProvider.d.ts +3 -3
- package/lib/components/ApplicationStoreProvider.d.ts.map +1 -1
- package/lib/components/ApplicationStoreProvider.js +2 -2
- package/lib/components/ApplicationStoreProvider.js.map +1 -1
- package/lib/components/ApplicationStoreProviderTestUtils.d.ts +5 -5
- package/lib/components/ApplicationStoreProviderTestUtils.d.ts.map +1 -1
- package/lib/components/ApplicationStoreProviderTestUtils.js +5 -4
- package/lib/components/ApplicationStoreProviderTestUtils.js.map +1 -1
- package/lib/components/ApplicationTestID.js +1 -1
- package/lib/components/ApplicationTestID.js.map +1 -1
- package/lib/components/BasicValueSpecificationEditor.d.ts +44 -0
- package/lib/components/BasicValueSpecificationEditor.d.ts.map +1 -0
- package/lib/components/BasicValueSpecificationEditor.js +276 -0
- package/lib/components/BasicValueSpecificationEditor.js.map +1 -0
- package/lib/components/BlockingAlert.d.ts +1 -0
- package/lib/components/BlockingAlert.d.ts.map +1 -1
- package/lib/components/BlockingAlert.js +1 -1
- package/lib/components/BlockingAlert.js.map +1 -1
- package/lib/components/CustomDatePicker.d.ts +38 -0
- package/lib/components/CustomDatePicker.d.ts.map +1 -0
- package/lib/components/CustomDatePicker.js +592 -0
- package/lib/components/CustomDatePicker.js.map +1 -0
- package/lib/components/DocumentationLink.d.ts +1 -1
- package/lib/components/DocumentationLink.js +2 -2
- package/lib/components/DocumentationLink.js.map +1 -1
- package/lib/components/LambdaEditor.d.ts +2 -1
- package/lib/components/LambdaEditor.d.ts.map +1 -1
- package/lib/components/LambdaEditor.js +3 -3
- package/lib/components/LambdaEditor.js.map +1 -1
- package/lib/components/LambdaParameterValuesEditor.d.ts +25 -0
- package/lib/components/LambdaParameterValuesEditor.d.ts.map +1 -0
- package/lib/components/LambdaParameterValuesEditor.js +52 -0
- package/lib/components/LambdaParameterValuesEditor.js.map +1 -0
- package/lib/components/LegendApplicationComponentFrameworkProvider.d.ts +1 -1
- package/lib/components/LegendApplicationComponentFrameworkProvider.js +3 -3
- package/lib/components/LegendApplicationComponentFrameworkProvider.js.map +1 -1
- package/lib/components/LegendApplicationNavigationContextServiceUtils.d.ts +32 -0
- package/lib/components/LegendApplicationNavigationContextServiceUtils.d.ts.map +1 -0
- package/lib/components/LegendApplicationNavigationContextServiceUtils.js +57 -0
- package/lib/components/LegendApplicationNavigationContextServiceUtils.js.map +1 -0
- package/lib/components/NotificationManager.d.ts +1 -0
- package/lib/components/NotificationManager.d.ts.map +1 -1
- package/lib/components/NotificationManager.js +2 -2
- package/lib/components/NotificationManager.js.map +1 -1
- package/lib/components/TextInputEditor.d.ts +2 -2
- package/lib/components/TextInputEditor.d.ts.map +1 -1
- package/lib/components/TextInputEditor.js +2 -2
- package/lib/components/TextInputEditor.js.map +1 -1
- package/lib/components/{AppHeader.d.ts → VirtualAssistant.d.ts} +5 -5
- package/lib/components/VirtualAssistant.d.ts.map +1 -0
- package/lib/components/VirtualAssistant.js +171 -0
- package/lib/components/VirtualAssistant.js.map +1 -0
- package/lib/components/WebApplicationNavigatorProvider.d.ts +2 -2
- package/lib/components/WebApplicationNavigatorProvider.d.ts.map +1 -1
- package/lib/components/WebApplicationNavigatorProvider.js +1 -1
- package/lib/components/WebApplicationNavigatorProvider.js.map +1 -1
- package/lib/components/WebApplicationNavigatorProviderTestUtils.d.ts +2 -2
- package/lib/components/WebApplicationNavigatorProviderTestUtils.d.ts.map +1 -1
- package/lib/components/WebApplicationNavigatorProviderTestUtils.js +3 -2
- package/lib/components/WebApplicationNavigatorProviderTestUtils.js.map +1 -1
- package/lib/const.js +2 -2
- package/lib/const.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/index.d.ts +30 -22
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +32 -22
- package/lib/index.js.map +1 -1
- package/lib/stores/ApplicationEvent.d.ts +9 -7
- package/lib/stores/ApplicationEvent.d.ts.map +1 -1
- package/lib/stores/ApplicationEvent.js +10 -8
- package/lib/stores/ApplicationEvent.js.map +1 -1
- package/lib/stores/ApplicationStore.d.ts +15 -9
- package/lib/stores/ApplicationStore.d.ts.map +1 -1
- package/lib/stores/ApplicationStore.js +26 -21
- package/lib/stores/ApplicationStore.js.map +1 -1
- package/lib/stores/ApplicationStoreTestUtils.d.ts +3 -3
- package/lib/stores/ApplicationStoreTestUtils.d.ts.map +1 -1
- package/lib/stores/ApplicationStoreTestUtils.js +2 -2
- package/lib/stores/ApplicationStoreTestUtils.js.map +1 -1
- package/lib/stores/ApplicationTelemetry.d.ts +1 -1
- package/lib/stores/ApplicationTelemetry.d.ts.map +1 -1
- package/lib/stores/ApplicationTelemetry.js +2 -2
- package/lib/stores/ApplicationTelemetry.js.map +1 -1
- package/lib/stores/CJS__Fuse.cjs +35 -0
- package/lib/stores/CJS__Fuse.cjs.map +1 -0
- package/lib/stores/CJS__Fuse.d.cts +28 -0
- package/lib/stores/CJS__Fuse.d.cts.map +1 -0
- package/lib/stores/LambdaParameterState.d.ts +59 -0
- package/lib/stores/LambdaParameterState.d.ts.map +1 -0
- package/lib/stores/LambdaParameterState.js +184 -0
- package/lib/stores/LambdaParameterState.js.map +1 -0
- package/lib/stores/LegendApplicationAssistantService.d.ts +63 -0
- package/lib/stores/LegendApplicationAssistantService.d.ts.map +1 -0
- package/lib/stores/LegendApplicationAssistantService.js +167 -0
- package/lib/stores/LegendApplicationAssistantService.js.map +1 -0
- package/lib/stores/LegendApplicationConfig.d.ts +5 -4
- package/lib/stores/LegendApplicationConfig.d.ts.map +1 -1
- package/lib/stores/LegendApplicationConfig.js +8 -3
- package/lib/stores/LegendApplicationConfig.js.map +1 -1
- package/lib/stores/LegendApplicationDocumentationService.d.ts +70 -0
- package/lib/stores/LegendApplicationDocumentationService.d.ts.map +1 -0
- package/lib/stores/LegendApplicationDocumentationService.js +152 -0
- package/lib/stores/LegendApplicationDocumentationService.js.map +1 -0
- package/lib/stores/LegendApplicationEventService.d.ts +22 -0
- package/lib/stores/LegendApplicationEventService.d.ts.map +1 -0
- package/lib/stores/LegendApplicationEventService.js +25 -0
- package/lib/stores/LegendApplicationEventService.js.map +1 -0
- package/lib/stores/LegendApplicationNavigationContextService.d.ts +74 -0
- package/lib/stores/LegendApplicationNavigationContextService.d.ts.map +1 -0
- package/lib/stores/LegendApplicationNavigationContextService.js +118 -0
- package/lib/stores/LegendApplicationNavigationContextService.js.map +1 -0
- package/lib/stores/LegendApplicationPlugin.d.ts +6 -2
- package/lib/stores/LegendApplicationPlugin.d.ts.map +1 -1
- package/lib/stores/LegendApplicationPlugin.js.map +1 -1
- package/lib/stores/PureLanguageSupport.d.ts.map +1 -1
- package/lib/stores/PureLanguageSupport.js +8 -2
- package/lib/stores/PureLanguageSupport.js.map +1 -1
- package/lib/stores/ValueSpecificationModifierHelper.d.ts +27 -0
- package/lib/stores/ValueSpecificationModifierHelper.d.ts.map +1 -0
- package/lib/stores/ValueSpecificationModifierHelper.js +49 -0
- package/lib/stores/ValueSpecificationModifierHelper.js.map +1 -0
- package/package.json +24 -18
- package/src/application/LegendApplication.tsx +6 -6
- package/src/application/LegendApplicationPluginManager.tsx +3 -3
- package/src/components/ActionAlert.tsx +2 -2
- package/src/components/ApplicationStoreProvider.tsx +4 -4
- package/src/components/ApplicationStoreProviderTestUtils.tsx +7 -6
- package/src/components/BasicValueSpecificationEditor.tsx +703 -0
- package/src/components/BlockingAlert.tsx +1 -1
- package/src/components/CustomDatePicker.tsx +1235 -0
- package/src/components/DocumentationLink.tsx +2 -2
- package/src/components/LambdaEditor.tsx +4 -4
- package/src/components/LambdaParameterValuesEditor.tsx +114 -0
- package/src/components/LegendApplicationComponentFrameworkProvider.tsx +3 -3
- package/src/components/LegendApplicationNavigationContextServiceUtils.tsx +63 -0
- package/src/components/NotificationManager.tsx +2 -2
- package/src/components/TextInputEditor.tsx +2 -2
- package/src/components/VirtualAssistant.tsx +600 -0
- package/src/components/WebApplicationNavigatorProvider.tsx +1 -1
- package/src/components/WebApplicationNavigatorProviderTestUtils.tsx +3 -2
- package/src/index.ts +39 -28
- package/src/stores/ApplicationEvent.ts +11 -7
- package/src/stores/ApplicationStore.ts +29 -27
- package/src/stores/ApplicationStoreTestUtils.ts +4 -4
- package/src/stores/ApplicationTelemetry.ts +2 -2
- package/src/stores/CJS__Fuse.cts +28 -0
- package/src/stores/LambdaParameterState.ts +314 -0
- package/src/stores/LegendApplicationAssistantService.ts +218 -0
- package/src/stores/LegendApplicationConfig.ts +20 -6
- package/src/stores/LegendApplicationDocumentationService.ts +276 -0
- package/src/stores/LegendApplicationEventService.ts +32 -0
- package/src/stores/LegendApplicationNavigationContextService.ts +131 -0
- package/src/stores/LegendApplicationPlugin.ts +10 -2
- package/src/stores/PureLanguageSupport.ts +8 -2
- package/src/stores/ValueSpecificationModifierHelper.ts +104 -0
- package/tsconfig.json +18 -12
- package/lib/components/AppHeader.d.ts.map +0 -1
- package/lib/components/AppHeader.js +0 -26
- package/lib/components/AppHeader.js.map +0 -1
- package/lib/stores/LegendApplicationDocumentationRegistry.d.ts +0 -36
- package/lib/stores/LegendApplicationDocumentationRegistry.d.ts.map +0 -1
- package/lib/stores/LegendApplicationDocumentationRegistry.js +0 -47
- package/lib/stores/LegendApplicationDocumentationRegistry.js.map +0 -1
- package/src/components/AppHeader.tsx +0 -49
- package/src/stores/LegendApplicationDocumentationRegistry.ts +0 -81
|
@@ -0,0 +1,703 @@
|
|
|
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 TooltipPlacement,
|
|
19
|
+
Tooltip,
|
|
20
|
+
DollarIcon,
|
|
21
|
+
clsx,
|
|
22
|
+
InfoCircleIcon,
|
|
23
|
+
RefreshIcon,
|
|
24
|
+
CheckSquareIcon,
|
|
25
|
+
SquareIcon,
|
|
26
|
+
CustomSelectorInput,
|
|
27
|
+
SaveIcon,
|
|
28
|
+
PencilIcon,
|
|
29
|
+
} from '@finos/legend-art';
|
|
30
|
+
import {
|
|
31
|
+
type Enum,
|
|
32
|
+
type Type,
|
|
33
|
+
type ValueSpecification,
|
|
34
|
+
type PureModel,
|
|
35
|
+
PrimitiveInstanceValue,
|
|
36
|
+
CollectionInstanceValue,
|
|
37
|
+
EnumValueInstanceValue,
|
|
38
|
+
INTERNAL__PropagatedValue,
|
|
39
|
+
SimpleFunctionExpression,
|
|
40
|
+
VariableExpression,
|
|
41
|
+
EnumValueExplicitReference,
|
|
42
|
+
TYPICAL_MULTIPLICITY_TYPE,
|
|
43
|
+
PrimitiveType,
|
|
44
|
+
PRIMITIVE_TYPE,
|
|
45
|
+
GenericTypeExplicitReference,
|
|
46
|
+
GenericType,
|
|
47
|
+
Enumeration,
|
|
48
|
+
getEnumValue,
|
|
49
|
+
getMultiplicityDescription,
|
|
50
|
+
} from '@finos/legend-graph';
|
|
51
|
+
import {
|
|
52
|
+
guaranteeNonNullable,
|
|
53
|
+
isNonNullable,
|
|
54
|
+
returnUndefOnError,
|
|
55
|
+
uniq,
|
|
56
|
+
} from '@finos/legend-shared';
|
|
57
|
+
import { observer } from 'mobx-react-lite';
|
|
58
|
+
import CSVParser from 'papaparse';
|
|
59
|
+
import { useEffect, useRef, useState } from 'react';
|
|
60
|
+
import {
|
|
61
|
+
instanceValue_changeValue,
|
|
62
|
+
instanceValue_changeValues,
|
|
63
|
+
} from '../stores/ValueSpecificationModifierHelper.js';
|
|
64
|
+
import { CustomDatePicker } from './CustomDatePicker.js';
|
|
65
|
+
|
|
66
|
+
type TypeCheckOption = {
|
|
67
|
+
expectedType: Type;
|
|
68
|
+
/**
|
|
69
|
+
* Indicates if a strict type-matching will happen.
|
|
70
|
+
* Sometimes, auto-boxing allow some rooms to wiggle,
|
|
71
|
+
* for example we can assign a Float to an Integer, a
|
|
72
|
+
* Date to a DateTime. With this flag set to `true`
|
|
73
|
+
* we will not allow this.
|
|
74
|
+
*/
|
|
75
|
+
match?: boolean;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const ParameterInfoTooltip: React.FC<{
|
|
79
|
+
variable: VariableExpression;
|
|
80
|
+
children: React.ReactElement;
|
|
81
|
+
placement?: TooltipPlacement | undefined;
|
|
82
|
+
}> = (props) => {
|
|
83
|
+
const { variable, children, placement } = props;
|
|
84
|
+
const type = variable.genericType?.value.rawType;
|
|
85
|
+
return (
|
|
86
|
+
<Tooltip
|
|
87
|
+
arrow={true}
|
|
88
|
+
{...(placement !== undefined ? { placement } : {})}
|
|
89
|
+
classes={{
|
|
90
|
+
tooltip: 'value-spec-paramater__tooltip',
|
|
91
|
+
arrow: 'value-spec-paramater__tooltip__arrow',
|
|
92
|
+
tooltipPlacementRight: 'value-spec-paramater__tooltip--right',
|
|
93
|
+
}}
|
|
94
|
+
TransitionProps={{
|
|
95
|
+
// disable transition
|
|
96
|
+
// NOTE: somehow, this is the only workaround we have, if for example
|
|
97
|
+
// we set `appear = true`, the tooltip will jump out of position
|
|
98
|
+
timeout: 0,
|
|
99
|
+
}}
|
|
100
|
+
title={
|
|
101
|
+
<div className="value-spec-paramater__tooltip__content">
|
|
102
|
+
<div className="value-spec-paramater__tooltip__item">
|
|
103
|
+
<div className="value-spec-paramater__tooltip__item__label">
|
|
104
|
+
Type
|
|
105
|
+
</div>
|
|
106
|
+
<div className="value-spec-paramater__tooltip__item__value">
|
|
107
|
+
{type?.name ?? ''}
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
<div className="value-spec-paramater__tooltip__item">
|
|
111
|
+
<div className="value-spec-paramater__tooltip__item__label">
|
|
112
|
+
Var Name
|
|
113
|
+
</div>
|
|
114
|
+
<div className="value-spec-paramater__tooltip__item__value">
|
|
115
|
+
{variable.name}
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
<div className="value-spec-paramater__tooltip__item">
|
|
119
|
+
<div className="value-spec-paramater__tooltip__item__label">
|
|
120
|
+
Multiplicity
|
|
121
|
+
</div>
|
|
122
|
+
<div className="value-spec-paramater__tooltip__item__value">
|
|
123
|
+
{getMultiplicityDescription(variable.multiplicity)}
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
}
|
|
128
|
+
>
|
|
129
|
+
{children}
|
|
130
|
+
</Tooltip>
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const VariableExpressionParameterEditor = observer(
|
|
135
|
+
(props: {
|
|
136
|
+
valueSpecification: VariableExpression;
|
|
137
|
+
className?: string | undefined;
|
|
138
|
+
resetValue: () => void;
|
|
139
|
+
}) => {
|
|
140
|
+
const { valueSpecification, className, resetValue } = props;
|
|
141
|
+
const varName = valueSpecification.name;
|
|
142
|
+
return (
|
|
143
|
+
<div className={clsx('value-spec-editor__parameter', className)}>
|
|
144
|
+
<div className="value-spec-editor__parameter__icon">
|
|
145
|
+
<DollarIcon />
|
|
146
|
+
</div>
|
|
147
|
+
<div className="value-spec-editor__parameter__label">
|
|
148
|
+
<div className="value-spec-editor__parameter__text">{varName}</div>
|
|
149
|
+
<ParameterInfoTooltip variable={valueSpecification}>
|
|
150
|
+
<div className="value-spec-editor__parameter__info">
|
|
151
|
+
<InfoCircleIcon />
|
|
152
|
+
</div>
|
|
153
|
+
</ParameterInfoTooltip>
|
|
154
|
+
<button
|
|
155
|
+
className="value-spec-editor__parameter__reset-btn"
|
|
156
|
+
title="Reset"
|
|
157
|
+
onClick={resetValue}
|
|
158
|
+
>
|
|
159
|
+
<RefreshIcon />
|
|
160
|
+
</button>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
);
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
const StringPrimitiveInstanceValueEditor = observer(
|
|
168
|
+
(props: {
|
|
169
|
+
valueSpecification: PrimitiveInstanceValue;
|
|
170
|
+
className?: string | undefined;
|
|
171
|
+
resetValue: () => void;
|
|
172
|
+
}) => {
|
|
173
|
+
const { valueSpecification, className, resetValue } = props;
|
|
174
|
+
const value = valueSpecification.values[0] as string;
|
|
175
|
+
const changeValue: React.ChangeEventHandler<HTMLInputElement> = (event) =>
|
|
176
|
+
instanceValue_changeValue(valueSpecification, event.target.value, 0);
|
|
177
|
+
|
|
178
|
+
return (
|
|
179
|
+
<div className={clsx('value-spec-editor', className)}>
|
|
180
|
+
<input
|
|
181
|
+
className="panel__content__form__section__input value-spec-editor__input"
|
|
182
|
+
spellCheck={false}
|
|
183
|
+
value={value}
|
|
184
|
+
placeholder={value === '' ? '(empty)' : undefined}
|
|
185
|
+
onChange={changeValue}
|
|
186
|
+
/>
|
|
187
|
+
<button
|
|
188
|
+
className="value-spec-editor__reset-btn"
|
|
189
|
+
title="Reset"
|
|
190
|
+
onClick={resetValue}
|
|
191
|
+
>
|
|
192
|
+
<RefreshIcon />
|
|
193
|
+
</button>
|
|
194
|
+
</div>
|
|
195
|
+
);
|
|
196
|
+
},
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const BooleanPrimitiveInstanceValueEditor = observer(
|
|
200
|
+
(props: {
|
|
201
|
+
valueSpecification: PrimitiveInstanceValue;
|
|
202
|
+
className?: string | undefined;
|
|
203
|
+
resetValue: () => void;
|
|
204
|
+
}) => {
|
|
205
|
+
const { valueSpecification, className, resetValue } = props;
|
|
206
|
+
const value = valueSpecification.values[0] as boolean;
|
|
207
|
+
const toggleValue = (): void =>
|
|
208
|
+
instanceValue_changeValue(valueSpecification, !value, 0);
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<div className={clsx('value-spec-editor', className)}>
|
|
212
|
+
<button
|
|
213
|
+
className={clsx('value-spec-editor__toggler__btn', {
|
|
214
|
+
'value-spec-editor__toggler__btn--toggled': value,
|
|
215
|
+
})}
|
|
216
|
+
onClick={toggleValue}
|
|
217
|
+
>
|
|
218
|
+
{value ? <CheckSquareIcon /> : <SquareIcon />}
|
|
219
|
+
</button>
|
|
220
|
+
<button
|
|
221
|
+
className="value-spec-editor__reset-btn"
|
|
222
|
+
title="Reset"
|
|
223
|
+
onClick={resetValue}
|
|
224
|
+
>
|
|
225
|
+
<RefreshIcon />
|
|
226
|
+
</button>
|
|
227
|
+
</div>
|
|
228
|
+
);
|
|
229
|
+
},
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
const NumberPrimitiveInstanceValueEditor = observer(
|
|
233
|
+
(props: {
|
|
234
|
+
valueSpecification: PrimitiveInstanceValue;
|
|
235
|
+
isInteger: boolean;
|
|
236
|
+
className?: string | undefined;
|
|
237
|
+
resetValue: () => void;
|
|
238
|
+
}) => {
|
|
239
|
+
const { valueSpecification, isInteger, className, resetValue } = props;
|
|
240
|
+
const value = valueSpecification.values[0] as number;
|
|
241
|
+
const changeValue: React.ChangeEventHandler<HTMLInputElement> = (event) => {
|
|
242
|
+
let inputVal = isInteger
|
|
243
|
+
? parseInt(event.target.value, 10)
|
|
244
|
+
: parseFloat(event.target.value);
|
|
245
|
+
inputVal = isNaN(inputVal) ? 0 : inputVal;
|
|
246
|
+
instanceValue_changeValue(valueSpecification, inputVal, 0);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
<div className={clsx('value-spec-editor', className)}>
|
|
251
|
+
<input
|
|
252
|
+
className="panel__content__form__section__input value-spec-editor__input"
|
|
253
|
+
spellCheck={false}
|
|
254
|
+
type="number"
|
|
255
|
+
value={value}
|
|
256
|
+
onChange={changeValue}
|
|
257
|
+
/>
|
|
258
|
+
<button
|
|
259
|
+
className="value-spec-editor__reset-btn"
|
|
260
|
+
title="Reset"
|
|
261
|
+
onClick={resetValue}
|
|
262
|
+
>
|
|
263
|
+
<RefreshIcon />
|
|
264
|
+
</button>
|
|
265
|
+
</div>
|
|
266
|
+
);
|
|
267
|
+
},
|
|
268
|
+
);
|
|
269
|
+
|
|
270
|
+
const EnumValueInstanceValueEditor = observer(
|
|
271
|
+
(props: {
|
|
272
|
+
valueSpecification: EnumValueInstanceValue;
|
|
273
|
+
className?: string | undefined;
|
|
274
|
+
resetValue: () => void;
|
|
275
|
+
}) => {
|
|
276
|
+
const { valueSpecification, className, resetValue } = props;
|
|
277
|
+
const enumValueRef = guaranteeNonNullable(valueSpecification.values[0]);
|
|
278
|
+
const enumValue = enumValueRef.value;
|
|
279
|
+
const options = enumValue._OWNER.values.map((value) => ({
|
|
280
|
+
label: value.name,
|
|
281
|
+
value: value,
|
|
282
|
+
}));
|
|
283
|
+
const changeValue = (val: { value: Enum; label: string }): void => {
|
|
284
|
+
instanceValue_changeValue(
|
|
285
|
+
valueSpecification,
|
|
286
|
+
EnumValueExplicitReference.create(val.value),
|
|
287
|
+
0,
|
|
288
|
+
);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
return (
|
|
292
|
+
<div className={clsx('value-spec-editor', className)}>
|
|
293
|
+
<CustomSelectorInput
|
|
294
|
+
className="value-spec-editor__enum-selector"
|
|
295
|
+
options={options}
|
|
296
|
+
onChange={changeValue}
|
|
297
|
+
value={{ value: enumValue, label: enumValue.name }}
|
|
298
|
+
darkMode={true}
|
|
299
|
+
/>
|
|
300
|
+
<button
|
|
301
|
+
className="value-spec-editor__reset-btn"
|
|
302
|
+
title="Reset"
|
|
303
|
+
onClick={resetValue}
|
|
304
|
+
>
|
|
305
|
+
<RefreshIcon />
|
|
306
|
+
</button>
|
|
307
|
+
</div>
|
|
308
|
+
);
|
|
309
|
+
},
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
const stringifyValue = (values: ValueSpecification[]): string => {
|
|
313
|
+
if (values.length === 0) {
|
|
314
|
+
return '';
|
|
315
|
+
}
|
|
316
|
+
return CSVParser.unparse([
|
|
317
|
+
values
|
|
318
|
+
.map((val) => {
|
|
319
|
+
if (val instanceof PrimitiveInstanceValue) {
|
|
320
|
+
return val.values[0];
|
|
321
|
+
} else if (val instanceof EnumValueInstanceValue) {
|
|
322
|
+
return guaranteeNonNullable(val.values[0]).value.name;
|
|
323
|
+
}
|
|
324
|
+
return undefined;
|
|
325
|
+
})
|
|
326
|
+
.filter(isNonNullable),
|
|
327
|
+
]).trim();
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* NOTE: We attempt to be less disruptive here by not throwing errors left and right, instead
|
|
332
|
+
* we silently remove values which are not valid or parsable. But perhaps, we can consider
|
|
333
|
+
* passing in logger or notifier to show give the users some idea of what went wrong instead
|
|
334
|
+
* of silently swallow parts of their inputs like this.
|
|
335
|
+
*/
|
|
336
|
+
const setCollectionValue = (
|
|
337
|
+
valueSpecification: CollectionInstanceValue,
|
|
338
|
+
graph: PureModel,
|
|
339
|
+
expectedType: Type,
|
|
340
|
+
value: string,
|
|
341
|
+
): void => {
|
|
342
|
+
if (value.trim().length === 0) {
|
|
343
|
+
instanceValue_changeValues(valueSpecification, []);
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
const multiplicityOne = graph.getTypicalMultiplicity(
|
|
347
|
+
TYPICAL_MULTIPLICITY_TYPE.ONE,
|
|
348
|
+
);
|
|
349
|
+
let result: unknown[] = [];
|
|
350
|
+
const parseResult = CSVParser.parse<string[]>(value.trim(), {
|
|
351
|
+
delimiter: ',',
|
|
352
|
+
});
|
|
353
|
+
const parseData = parseResult.data[0] as string[]; // only take the first line
|
|
354
|
+
if (parseResult.errors.length) {
|
|
355
|
+
if (
|
|
356
|
+
parseResult.errors[0] &&
|
|
357
|
+
parseResult.errors[0].code === 'UndetectableDelimiter' &&
|
|
358
|
+
parseResult.errors[0].type === 'Delimiter' &&
|
|
359
|
+
parseResult.data.length === 1
|
|
360
|
+
) {
|
|
361
|
+
// NOTE: this happens when the user only put one item in the value input
|
|
362
|
+
// we can go the other way by ensure the input has a comma but this is arguably neater
|
|
363
|
+
// as it tinkers with the parser
|
|
364
|
+
} else {
|
|
365
|
+
// there were some parsing error, escape
|
|
366
|
+
// NOTE: ideally, we could show a warning here
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
} else if (expectedType instanceof PrimitiveType) {
|
|
370
|
+
switch (expectedType.path) {
|
|
371
|
+
case PRIMITIVE_TYPE.STRING: {
|
|
372
|
+
result = uniq(parseData)
|
|
373
|
+
.map((item): PrimitiveInstanceValue | undefined => {
|
|
374
|
+
const primitiveInstanceValue = new PrimitiveInstanceValue(
|
|
375
|
+
GenericTypeExplicitReference.create(
|
|
376
|
+
new GenericType(expectedType),
|
|
377
|
+
),
|
|
378
|
+
multiplicityOne,
|
|
379
|
+
);
|
|
380
|
+
primitiveInstanceValue.values = [item.toString()];
|
|
381
|
+
return primitiveInstanceValue;
|
|
382
|
+
})
|
|
383
|
+
.filter(isNonNullable);
|
|
384
|
+
break;
|
|
385
|
+
}
|
|
386
|
+
case PRIMITIVE_TYPE.NUMBER:
|
|
387
|
+
case PRIMITIVE_TYPE.FLOAT:
|
|
388
|
+
case PRIMITIVE_TYPE.DECIMAL:
|
|
389
|
+
case PRIMITIVE_TYPE.INTEGER: {
|
|
390
|
+
result = uniq(
|
|
391
|
+
parseData
|
|
392
|
+
.filter((val) => !isNaN(Number(val)))
|
|
393
|
+
.map((val) => Number(val)),
|
|
394
|
+
)
|
|
395
|
+
.map((item): PrimitiveInstanceValue | undefined => {
|
|
396
|
+
const primitiveInstanceValue = new PrimitiveInstanceValue(
|
|
397
|
+
GenericTypeExplicitReference.create(
|
|
398
|
+
new GenericType(expectedType),
|
|
399
|
+
),
|
|
400
|
+
multiplicityOne,
|
|
401
|
+
);
|
|
402
|
+
primitiveInstanceValue.values = [item];
|
|
403
|
+
return primitiveInstanceValue;
|
|
404
|
+
})
|
|
405
|
+
.filter(isNonNullable);
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
default:
|
|
409
|
+
// unsupported expected type, just escape
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
} else if (expectedType instanceof Enumeration) {
|
|
413
|
+
result = uniq(parseData.map((item) => item.trim()))
|
|
414
|
+
.map((item): EnumValueInstanceValue | undefined => {
|
|
415
|
+
const _enum = returnUndefOnError(() =>
|
|
416
|
+
getEnumValue(expectedType, item),
|
|
417
|
+
);
|
|
418
|
+
if (!_enum) {
|
|
419
|
+
return undefined;
|
|
420
|
+
}
|
|
421
|
+
const enumValueInstanceValue = new EnumValueInstanceValue(
|
|
422
|
+
GenericTypeExplicitReference.create(new GenericType(expectedType)),
|
|
423
|
+
multiplicityOne,
|
|
424
|
+
);
|
|
425
|
+
enumValueInstanceValue.values = [
|
|
426
|
+
EnumValueExplicitReference.create(_enum),
|
|
427
|
+
];
|
|
428
|
+
return enumValueInstanceValue;
|
|
429
|
+
})
|
|
430
|
+
.filter(isNonNullable);
|
|
431
|
+
}
|
|
432
|
+
instanceValue_changeValues(valueSpecification, result);
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
const COLLECTION_PREVIEW_CHAR_LIMIT = 50;
|
|
436
|
+
|
|
437
|
+
const CollectionValueInstanceValueEditor = observer(
|
|
438
|
+
(props: {
|
|
439
|
+
valueSpecification: CollectionInstanceValue;
|
|
440
|
+
graph: PureModel;
|
|
441
|
+
expectedType: Type;
|
|
442
|
+
className?: string | undefined;
|
|
443
|
+
resetValue: () => void;
|
|
444
|
+
}) => {
|
|
445
|
+
const { valueSpecification, graph, expectedType, className, resetValue } =
|
|
446
|
+
props;
|
|
447
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
448
|
+
const [text, setText] = useState(stringifyValue(valueSpecification.values));
|
|
449
|
+
const [editable, setEditable] = useState(false);
|
|
450
|
+
const valueText = stringifyValue(valueSpecification.values);
|
|
451
|
+
const previewText = `List(${
|
|
452
|
+
valueSpecification.values.length === 0
|
|
453
|
+
? 'empty'
|
|
454
|
+
: valueSpecification.values.length
|
|
455
|
+
})${
|
|
456
|
+
valueSpecification.values.length === 0
|
|
457
|
+
? ''
|
|
458
|
+
: `: ${
|
|
459
|
+
valueText.length > COLLECTION_PREVIEW_CHAR_LIMIT
|
|
460
|
+
? `${valueText.substring(0, COLLECTION_PREVIEW_CHAR_LIMIT)}...`
|
|
461
|
+
: valueText
|
|
462
|
+
}`
|
|
463
|
+
}`;
|
|
464
|
+
const enableEdit = (): void => setEditable(true);
|
|
465
|
+
const saveEdit = (): void => {
|
|
466
|
+
setEditable(false);
|
|
467
|
+
setCollectionValue(valueSpecification, graph, expectedType, text);
|
|
468
|
+
setText(stringifyValue(valueSpecification.values));
|
|
469
|
+
};
|
|
470
|
+
const changeValue: React.ChangeEventHandler<HTMLInputElement> = (event) =>
|
|
471
|
+
setText(event.target.value);
|
|
472
|
+
|
|
473
|
+
// focus the input box when edit is enabled
|
|
474
|
+
useEffect(() => {
|
|
475
|
+
if (editable) {
|
|
476
|
+
inputRef.current?.focus();
|
|
477
|
+
}
|
|
478
|
+
}, [editable]);
|
|
479
|
+
|
|
480
|
+
if (editable) {
|
|
481
|
+
return (
|
|
482
|
+
<div className={clsx('value-spec-editor', className)}>
|
|
483
|
+
<input
|
|
484
|
+
ref={inputRef}
|
|
485
|
+
className="panel__content__form__section__input value-spec-editor__input"
|
|
486
|
+
spellCheck={false}
|
|
487
|
+
value={text}
|
|
488
|
+
placeholder={text === '' ? '(empty)' : undefined}
|
|
489
|
+
onChange={changeValue}
|
|
490
|
+
/>
|
|
491
|
+
<button
|
|
492
|
+
className="value-spec-editor__list-editor__save-button btn--dark"
|
|
493
|
+
onClick={saveEdit}
|
|
494
|
+
>
|
|
495
|
+
<SaveIcon />
|
|
496
|
+
</button>
|
|
497
|
+
<button
|
|
498
|
+
className="value-spec-editor__reset-btn"
|
|
499
|
+
title="Reset"
|
|
500
|
+
onClick={resetValue}
|
|
501
|
+
>
|
|
502
|
+
<RefreshIcon />
|
|
503
|
+
</button>
|
|
504
|
+
</div>
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
return (
|
|
508
|
+
<div
|
|
509
|
+
className={clsx('value-spec-editor', className)}
|
|
510
|
+
onClick={enableEdit}
|
|
511
|
+
title="Click to edit"
|
|
512
|
+
>
|
|
513
|
+
<input
|
|
514
|
+
className="value-spec-editor__list-editor__preview"
|
|
515
|
+
spellCheck={false}
|
|
516
|
+
value={previewText}
|
|
517
|
+
disabled={true}
|
|
518
|
+
/>
|
|
519
|
+
<button className="value-spec-editor__list-editor__edit-icon">
|
|
520
|
+
<PencilIcon />
|
|
521
|
+
</button>
|
|
522
|
+
</div>
|
|
523
|
+
);
|
|
524
|
+
},
|
|
525
|
+
);
|
|
526
|
+
|
|
527
|
+
const UnsupportedValueSpecificationEditor: React.FC = () => (
|
|
528
|
+
<div className="value-spec-editor--unsupported">unsupported</div>
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
const DateInstanceValueEditor = observer(
|
|
532
|
+
(props: {
|
|
533
|
+
valueSpecification: PrimitiveInstanceValue | SimpleFunctionExpression;
|
|
534
|
+
graph: PureModel;
|
|
535
|
+
typeCheckOption: TypeCheckOption;
|
|
536
|
+
className?: string | undefined;
|
|
537
|
+
updateValue: (val: ValueSpecification) => void;
|
|
538
|
+
resetValue: () => void;
|
|
539
|
+
}) => {
|
|
540
|
+
const {
|
|
541
|
+
valueSpecification,
|
|
542
|
+
updateValue,
|
|
543
|
+
graph,
|
|
544
|
+
typeCheckOption,
|
|
545
|
+
resetValue,
|
|
546
|
+
} = props;
|
|
547
|
+
|
|
548
|
+
return (
|
|
549
|
+
<div className="value-spec-editor">
|
|
550
|
+
<CustomDatePicker
|
|
551
|
+
valueSpecification={valueSpecification}
|
|
552
|
+
graph={graph}
|
|
553
|
+
typeCheckOption={typeCheckOption}
|
|
554
|
+
updateValue={updateValue}
|
|
555
|
+
/>
|
|
556
|
+
<button
|
|
557
|
+
className="value-spec-editor__reset-btn"
|
|
558
|
+
title="Reset"
|
|
559
|
+
onClick={resetValue}
|
|
560
|
+
>
|
|
561
|
+
<RefreshIcon />
|
|
562
|
+
</button>
|
|
563
|
+
</div>
|
|
564
|
+
);
|
|
565
|
+
},
|
|
566
|
+
);
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* TODO we should pass in the props `setValueSpecification` and `resetValueSpecification`. Reset
|
|
570
|
+
* should be part of this editor. Also through here we can call `observe_` accordingly.
|
|
571
|
+
*
|
|
572
|
+
* See https://github.com/finos/legend-studio/pull/1021
|
|
573
|
+
*/
|
|
574
|
+
export const BasicValueSpecificationEditor: React.FC<{
|
|
575
|
+
valueSpecification: ValueSpecification;
|
|
576
|
+
graph: PureModel;
|
|
577
|
+
typeCheckOption: TypeCheckOption;
|
|
578
|
+
className?: string | undefined;
|
|
579
|
+
updateValue: (val: ValueSpecification) => void;
|
|
580
|
+
resetValue: () => void;
|
|
581
|
+
}> = (props) => {
|
|
582
|
+
const {
|
|
583
|
+
className,
|
|
584
|
+
valueSpecification,
|
|
585
|
+
graph,
|
|
586
|
+
typeCheckOption,
|
|
587
|
+
updateValue,
|
|
588
|
+
resetValue,
|
|
589
|
+
} = props;
|
|
590
|
+
if (valueSpecification instanceof PrimitiveInstanceValue) {
|
|
591
|
+
const _type = valueSpecification.genericType.value.rawType;
|
|
592
|
+
switch (_type.path) {
|
|
593
|
+
case PRIMITIVE_TYPE.STRING:
|
|
594
|
+
return (
|
|
595
|
+
<StringPrimitiveInstanceValueEditor
|
|
596
|
+
valueSpecification={valueSpecification}
|
|
597
|
+
className={className}
|
|
598
|
+
resetValue={resetValue}
|
|
599
|
+
/>
|
|
600
|
+
);
|
|
601
|
+
case PRIMITIVE_TYPE.BOOLEAN:
|
|
602
|
+
return (
|
|
603
|
+
<BooleanPrimitiveInstanceValueEditor
|
|
604
|
+
valueSpecification={valueSpecification}
|
|
605
|
+
className={className}
|
|
606
|
+
resetValue={resetValue}
|
|
607
|
+
/>
|
|
608
|
+
);
|
|
609
|
+
case PRIMITIVE_TYPE.NUMBER:
|
|
610
|
+
case PRIMITIVE_TYPE.FLOAT:
|
|
611
|
+
case PRIMITIVE_TYPE.DECIMAL:
|
|
612
|
+
case PRIMITIVE_TYPE.INTEGER:
|
|
613
|
+
return (
|
|
614
|
+
<NumberPrimitiveInstanceValueEditor
|
|
615
|
+
valueSpecification={valueSpecification}
|
|
616
|
+
isInteger={_type.path === PRIMITIVE_TYPE.INTEGER}
|
|
617
|
+
className={className}
|
|
618
|
+
resetValue={resetValue}
|
|
619
|
+
/>
|
|
620
|
+
);
|
|
621
|
+
case PRIMITIVE_TYPE.DATE:
|
|
622
|
+
case PRIMITIVE_TYPE.STRICTDATE:
|
|
623
|
+
case PRIMITIVE_TYPE.DATETIME:
|
|
624
|
+
case PRIMITIVE_TYPE.LATESTDATE:
|
|
625
|
+
return (
|
|
626
|
+
<DateInstanceValueEditor
|
|
627
|
+
valueSpecification={valueSpecification}
|
|
628
|
+
graph={graph}
|
|
629
|
+
typeCheckOption={typeCheckOption}
|
|
630
|
+
className={className}
|
|
631
|
+
updateValue={updateValue}
|
|
632
|
+
resetValue={resetValue}
|
|
633
|
+
/>
|
|
634
|
+
);
|
|
635
|
+
default:
|
|
636
|
+
return <UnsupportedValueSpecificationEditor />;
|
|
637
|
+
}
|
|
638
|
+
} else if (valueSpecification instanceof EnumValueInstanceValue) {
|
|
639
|
+
return (
|
|
640
|
+
<EnumValueInstanceValueEditor
|
|
641
|
+
valueSpecification={valueSpecification}
|
|
642
|
+
className={className}
|
|
643
|
+
resetValue={resetValue}
|
|
644
|
+
/>
|
|
645
|
+
);
|
|
646
|
+
} else if (
|
|
647
|
+
valueSpecification instanceof CollectionInstanceValue &&
|
|
648
|
+
valueSpecification.genericType
|
|
649
|
+
) {
|
|
650
|
+
// NOTE: since when we fill in the arguments, `[]` (or `nullish` value in Pure)
|
|
651
|
+
// is used for parameters we don't handle, we should not attempt to support empty collection
|
|
652
|
+
// without generic type here as that is equivalent to `[]`
|
|
653
|
+
return (
|
|
654
|
+
<CollectionValueInstanceValueEditor
|
|
655
|
+
valueSpecification={valueSpecification}
|
|
656
|
+
graph={graph}
|
|
657
|
+
expectedType={typeCheckOption.expectedType}
|
|
658
|
+
className={className}
|
|
659
|
+
resetValue={resetValue}
|
|
660
|
+
/>
|
|
661
|
+
);
|
|
662
|
+
}
|
|
663
|
+
// property expression
|
|
664
|
+
else if (valueSpecification instanceof VariableExpression) {
|
|
665
|
+
return (
|
|
666
|
+
<VariableExpressionParameterEditor
|
|
667
|
+
valueSpecification={valueSpecification}
|
|
668
|
+
className={className}
|
|
669
|
+
resetValue={resetValue}
|
|
670
|
+
/>
|
|
671
|
+
);
|
|
672
|
+
} else if (valueSpecification instanceof INTERNAL__PropagatedValue) {
|
|
673
|
+
return (
|
|
674
|
+
<BasicValueSpecificationEditor
|
|
675
|
+
valueSpecification={valueSpecification.getValue()}
|
|
676
|
+
graph={graph}
|
|
677
|
+
typeCheckOption={typeCheckOption}
|
|
678
|
+
updateValue={updateValue}
|
|
679
|
+
resetValue={resetValue}
|
|
680
|
+
/>
|
|
681
|
+
);
|
|
682
|
+
} else if (
|
|
683
|
+
valueSpecification instanceof SimpleFunctionExpression &&
|
|
684
|
+
[
|
|
685
|
+
PRIMITIVE_TYPE.DATE.toString(),
|
|
686
|
+
PRIMITIVE_TYPE.STRICTDATE.toString(),
|
|
687
|
+
PRIMITIVE_TYPE.DATETIME.toString(),
|
|
688
|
+
PRIMITIVE_TYPE.LATESTDATE.toString(),
|
|
689
|
+
].includes(typeCheckOption.expectedType.path)
|
|
690
|
+
) {
|
|
691
|
+
return (
|
|
692
|
+
<DateInstanceValueEditor
|
|
693
|
+
valueSpecification={valueSpecification}
|
|
694
|
+
graph={graph}
|
|
695
|
+
typeCheckOption={typeCheckOption}
|
|
696
|
+
className={className}
|
|
697
|
+
updateValue={updateValue}
|
|
698
|
+
resetValue={resetValue}
|
|
699
|
+
/>
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
return <UnsupportedValueSpecificationEditor />;
|
|
703
|
+
};
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
import { observer } from 'mobx-react-lite';
|
|
18
18
|
import { PanelLoadingIndicator, Dialog } from '@finos/legend-art';
|
|
19
19
|
import { noop } from '@finos/legend-shared';
|
|
20
|
-
import { useApplicationStore } from './ApplicationStoreProvider';
|
|
20
|
+
import { useApplicationStore } from './ApplicationStoreProvider.js';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* The users of this need to justify their use case because blocking app disrupts the UX flow.
|