@finos/legend-query-builder 4.14.40 → 4.14.43
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/components/explorer/QueryBuilderMilestoningEditor.d.ts +0 -5
- package/lib/components/explorer/QueryBuilderMilestoningEditor.d.ts.map +1 -1
- package/lib/components/explorer/QueryBuilderMilestoningEditor.js +5 -10
- package/lib/components/explorer/QueryBuilderMilestoningEditor.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js +3 -35
- package/lib/components/fetch-structure/QueryBuilderResultModifierPanel.js.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.d.ts.map +1 -1
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js +1 -11
- package/lib/components/fetch-structure/QueryBuilderTDSPanel.js.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.d.ts.map +1 -1
- package/lib/components/filter/QueryBuilderFilterPanel.js +6 -2
- package/lib/components/filter/QueryBuilderFilterPanel.js.map +1 -1
- package/lib/components/shared/BasicValueSpecificationEditor.d.ts +11 -9
- package/lib/components/shared/BasicValueSpecificationEditor.d.ts.map +1 -1
- package/lib/components/shared/BasicValueSpecificationEditor.js +160 -143
- package/lib/components/shared/BasicValueSpecificationEditor.js.map +1 -1
- package/lib/index.css +2 -2
- package/lib/index.css.map +1 -1
- package/lib/package.json +1 -1
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts +0 -1
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.d.ts.map +1 -1
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js +0 -8
- package/lib/stores/fetch-structure/tds/QueryBuilderTDSState.js.map +1 -1
- package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_In.js +2 -2
- package/lib/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_In.js.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.d.ts +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.d.ts.map +1 -1
- package/lib/stores/filter/QueryBuilderFilterState.js +4 -3
- package/lib/stores/filter/QueryBuilderFilterState.js.map +1 -1
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js +2 -2
- package/lib/stores/filter/operators/QueryBuilderFilterOperator_In.js.map +1 -1
- package/lib/stores/milestoning/QueryBuilderMilestoningState.d.ts.map +1 -1
- package/lib/stores/milestoning/QueryBuilderMilestoningState.js +3 -9
- package/lib/stores/milestoning/QueryBuilderMilestoningState.js.map +1 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts +1 -0
- package/lib/stores/shared/ValueSpecificationEditorHelper.d.ts.map +1 -1
- package/lib/stores/shared/ValueSpecificationEditorHelper.js +48 -0
- package/lib/stores/shared/ValueSpecificationEditorHelper.js.map +1 -1
- package/package.json +8 -8
- package/src/components/explorer/QueryBuilderMilestoningEditor.tsx +46 -60
- package/src/components/fetch-structure/QueryBuilderResultModifierPanel.tsx +3 -53
- package/src/components/fetch-structure/QueryBuilderTDSPanel.tsx +19 -116
- package/src/components/filter/QueryBuilderFilterPanel.tsx +13 -5
- package/src/components/shared/BasicValueSpecificationEditor.tsx +299 -285
- package/src/stores/fetch-structure/tds/QueryBuilderTDSState.ts +0 -11
- package/src/stores/fetch-structure/tds/post-filter/operators/QueryBuilderPostFilterOperator_In.ts +2 -2
- package/src/stores/filter/QueryBuilderFilterState.ts +6 -3
- package/src/stores/filter/operators/QueryBuilderFilterOperator_In.ts +2 -2
- package/src/stores/milestoning/QueryBuilderMilestoningState.ts +7 -11
- package/src/stores/shared/ValueSpecificationEditorHelper.ts +63 -0
|
@@ -14,10 +14,14 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH,
|
|
19
|
+
useApplicationStore,
|
|
20
|
+
} from '@finos/legend-application';
|
|
18
21
|
import {
|
|
19
22
|
type TooltipPlacement,
|
|
20
23
|
type InputActionData,
|
|
24
|
+
type SelectActionData,
|
|
21
25
|
Tooltip,
|
|
22
26
|
DollarIcon,
|
|
23
27
|
clsx,
|
|
@@ -29,9 +33,6 @@ import {
|
|
|
29
33
|
SaveIcon,
|
|
30
34
|
PencilIcon,
|
|
31
35
|
DragPreviewLayer,
|
|
32
|
-
FilledWindowMaximizeIcon,
|
|
33
|
-
BasePopover,
|
|
34
|
-
PanelFormSection,
|
|
35
36
|
CalculateIcon,
|
|
36
37
|
InputWithInlineValidation,
|
|
37
38
|
} from '@finos/legend-art';
|
|
@@ -52,7 +53,6 @@ import {
|
|
|
52
53
|
GenericTypeExplicitReference,
|
|
53
54
|
GenericType,
|
|
54
55
|
Enumeration,
|
|
55
|
-
getEnumValue,
|
|
56
56
|
getMultiplicityDescription,
|
|
57
57
|
type ObserverContext,
|
|
58
58
|
matchFunctionName,
|
|
@@ -63,16 +63,16 @@ import {
|
|
|
63
63
|
type GeneratorFn,
|
|
64
64
|
guaranteeNonNullable,
|
|
65
65
|
isNonNullable,
|
|
66
|
-
returnUndefOnError,
|
|
67
|
-
uniq,
|
|
68
|
-
parseCSVString,
|
|
69
66
|
guaranteeIsNumber,
|
|
70
67
|
csvStringify,
|
|
71
68
|
guaranteeType,
|
|
69
|
+
isNonEmptyString,
|
|
70
|
+
parseCSVString,
|
|
71
|
+
uniq,
|
|
72
72
|
} from '@finos/legend-shared';
|
|
73
73
|
import { flowResult } from 'mobx';
|
|
74
74
|
import { observer } from 'mobx-react-lite';
|
|
75
|
-
import {
|
|
75
|
+
import React, {
|
|
76
76
|
forwardRef,
|
|
77
77
|
useEffect,
|
|
78
78
|
useImperativeHandle,
|
|
@@ -91,6 +91,10 @@ import {
|
|
|
91
91
|
} from '../../stores/QueryBuilderValueSpecificationHelper.js';
|
|
92
92
|
import { evaluate } from 'mathjs';
|
|
93
93
|
import { isUsedDateFunctionSupportedInFormMode } from '../../stores/QueryBuilderStateBuilder.js';
|
|
94
|
+
import {
|
|
95
|
+
convertTextToPrimitiveInstanceValue,
|
|
96
|
+
getValueSpecificationStringValue,
|
|
97
|
+
} from '../../stores/shared/ValueSpecificationEditorHelper.js';
|
|
94
98
|
|
|
95
99
|
type TypeCheckOption = {
|
|
96
100
|
expectedType: Type;
|
|
@@ -222,16 +226,7 @@ const StringPrimitiveInstanceValueEditor = observer(
|
|
|
222
226
|
className?: string | undefined;
|
|
223
227
|
setValueSpecification: (val: ValueSpecification) => void;
|
|
224
228
|
resetValue: () => void;
|
|
225
|
-
selectorConfig?:
|
|
226
|
-
| {
|
|
227
|
-
values: string[] | undefined;
|
|
228
|
-
isLoading: boolean;
|
|
229
|
-
reloadValues:
|
|
230
|
-
| DebouncedFunc<(inputValue: string) => GeneratorFn<void>>
|
|
231
|
-
| undefined;
|
|
232
|
-
cleanUpReloadValues?: () => void;
|
|
233
|
-
}
|
|
234
|
-
| undefined;
|
|
229
|
+
selectorConfig?: BasicValueSpecificationEditorSelectorConfig | undefined;
|
|
235
230
|
obseverContext: ObserverContext;
|
|
236
231
|
}
|
|
237
232
|
>(function StringPrimitiveInstanceValueEditor(props, ref) {
|
|
@@ -628,153 +623,287 @@ const stringifyValue = (values: ValueSpecification[]): string => {
|
|
|
628
623
|
]).trim();
|
|
629
624
|
};
|
|
630
625
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
): void => {
|
|
643
|
-
if (value.trim().length === 0) {
|
|
644
|
-
instanceValue_setValues(valueSpecification, [], obseverContext);
|
|
645
|
-
return;
|
|
626
|
+
const getPlaceHolder = (expectedType: Type): string => {
|
|
627
|
+
if (expectedType instanceof PrimitiveType) {
|
|
628
|
+
switch (expectedType.path) {
|
|
629
|
+
case PRIMITIVE_TYPE.DATE:
|
|
630
|
+
case PRIMITIVE_TYPE.STRICTDATE:
|
|
631
|
+
return 'yyyy-mm-dd';
|
|
632
|
+
case PRIMITIVE_TYPE.DATETIME:
|
|
633
|
+
return 'yyyy-mm-ddThh:mm:ss';
|
|
634
|
+
default:
|
|
635
|
+
return 'Add';
|
|
636
|
+
}
|
|
646
637
|
}
|
|
647
|
-
|
|
638
|
+
return 'Add';
|
|
639
|
+
};
|
|
648
640
|
|
|
649
|
-
|
|
641
|
+
interface BasicValueSpecificationEditorSelectorConfig {
|
|
642
|
+
values: string[] | undefined;
|
|
643
|
+
isLoading: boolean;
|
|
644
|
+
reloadValues:
|
|
645
|
+
| DebouncedFunc<(inputValue: string) => GeneratorFn<void>>
|
|
646
|
+
| undefined;
|
|
647
|
+
cleanUpReloadValues?: () => void;
|
|
648
|
+
}
|
|
650
649
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
650
|
+
const PrimitiveCollectionInstanceValueEditor = observer(
|
|
651
|
+
(props: {
|
|
652
|
+
valueSpecification: CollectionInstanceValue;
|
|
653
|
+
expectedType: Type;
|
|
654
|
+
saveEdit: () => void;
|
|
655
|
+
selectorConfig?: BasicValueSpecificationEditorSelectorConfig | undefined;
|
|
656
|
+
observerContext: ObserverContext;
|
|
657
|
+
}) => {
|
|
658
|
+
const {
|
|
659
|
+
valueSpecification,
|
|
660
|
+
expectedType,
|
|
661
|
+
saveEdit,
|
|
662
|
+
selectorConfig,
|
|
663
|
+
observerContext,
|
|
664
|
+
} = props;
|
|
654
665
|
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
666
|
+
// local state and variables
|
|
667
|
+
const applicationStore = useApplicationStore();
|
|
668
|
+
const inputRef = useRef(null);
|
|
669
|
+
const [inputValue, setInputValue] = useState('');
|
|
670
|
+
const [inputValueIsError, setInputValueIsError] = useState(false);
|
|
671
|
+
const [selectedOptions, setSelectedOptions] = useState<
|
|
672
|
+
{ label: string; value: string }[]
|
|
673
|
+
>(
|
|
674
|
+
valueSpecification.values
|
|
675
|
+
.map((valueSpec) => getValueSpecificationStringValue(valueSpec))
|
|
676
|
+
.filter(isNonEmptyString)
|
|
677
|
+
.map((value) => ({
|
|
678
|
+
label: value,
|
|
679
|
+
value,
|
|
680
|
+
})),
|
|
681
|
+
);
|
|
682
|
+
|
|
683
|
+
// typehead search setup
|
|
684
|
+
const isTypeaheadSearchEnabled =
|
|
685
|
+
expectedType === PrimitiveType.STRING && Boolean(selectorConfig);
|
|
686
|
+
const reloadValuesFunc = isTypeaheadSearchEnabled
|
|
687
|
+
? selectorConfig?.reloadValues
|
|
688
|
+
: undefined;
|
|
689
|
+
const cleanUpReloadValuesFunc = isTypeaheadSearchEnabled
|
|
690
|
+
? selectorConfig?.cleanUpReloadValues
|
|
691
|
+
: undefined;
|
|
692
|
+
const isLoading = isTypeaheadSearchEnabled
|
|
693
|
+
? selectorConfig?.isLoading
|
|
694
|
+
: undefined;
|
|
695
|
+
const queryOptions =
|
|
696
|
+
isTypeaheadSearchEnabled && selectorConfig?.values?.length
|
|
697
|
+
? selectorConfig.values.map((e) => ({
|
|
698
|
+
value: e,
|
|
699
|
+
label: e.toString(),
|
|
700
|
+
}))
|
|
701
|
+
: undefined;
|
|
702
|
+
const noMatchMessage =
|
|
703
|
+
isTypeaheadSearchEnabled && isLoading ? 'Loading...' : undefined;
|
|
704
|
+
|
|
705
|
+
// helper functions
|
|
706
|
+
const buildOptionForValueSpec = (
|
|
707
|
+
value: ValueSpecification,
|
|
708
|
+
): { label: string; value: string } => {
|
|
709
|
+
const stringValue = guaranteeNonNullable(
|
|
710
|
+
getValueSpecificationStringValue(value),
|
|
711
|
+
);
|
|
712
|
+
return {
|
|
713
|
+
label: stringValue,
|
|
714
|
+
value: stringValue,
|
|
715
|
+
};
|
|
716
|
+
};
|
|
717
|
+
|
|
718
|
+
const isValueAlreadySelected = (value: string): boolean =>
|
|
719
|
+
selectedOptions.map((option) => option.value).includes(value);
|
|
720
|
+
|
|
721
|
+
/**
|
|
722
|
+
* NOTE: We attempt to be less disruptive here by not throwing errors left and right, instead
|
|
723
|
+
* we simply return null for values which are not valid or parsable. But perhaps, we can consider
|
|
724
|
+
* passing in logger or notifier to give the users some idea of what went wrong instead of ignoring
|
|
725
|
+
* their input.
|
|
726
|
+
*/
|
|
727
|
+
const convertInputValueToValueSpec = (): ValueSpecification | null => {
|
|
728
|
+
const trimmedInputValue = inputValue.trim();
|
|
729
|
+
|
|
730
|
+
if (trimmedInputValue.length) {
|
|
731
|
+
const newValueSpec = convertTextToPrimitiveInstanceValue(
|
|
732
|
+
expectedType,
|
|
733
|
+
trimmedInputValue,
|
|
734
|
+
observerContext,
|
|
735
|
+
);
|
|
736
|
+
|
|
737
|
+
if (
|
|
738
|
+
newValueSpec === null ||
|
|
739
|
+
getValueSpecificationStringValue(newValueSpec) === undefined ||
|
|
740
|
+
isValueAlreadySelected(
|
|
741
|
+
guaranteeNonNullable(
|
|
742
|
+
getValueSpecificationStringValue(newValueSpec),
|
|
743
|
+
),
|
|
744
|
+
)
|
|
745
|
+
) {
|
|
746
|
+
return null;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
return newValueSpec;
|
|
674
750
|
}
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
instanceValue_setValues(
|
|
691
|
-
primitiveInstanceValue,
|
|
692
|
-
[item],
|
|
693
|
-
obseverContext,
|
|
694
|
-
);
|
|
695
|
-
return primitiveInstanceValue;
|
|
696
|
-
})
|
|
697
|
-
.filter(isNonNullable);
|
|
698
|
-
break;
|
|
751
|
+
return null;
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
const addInputValueToSelectedOptions = (): void => {
|
|
755
|
+
const newValueSpec = convertInputValueToValueSpec();
|
|
756
|
+
|
|
757
|
+
if (newValueSpec !== null) {
|
|
758
|
+
setSelectedOptions([
|
|
759
|
+
...selectedOptions,
|
|
760
|
+
buildOptionForValueSpec(newValueSpec),
|
|
761
|
+
]);
|
|
762
|
+
setInputValue('');
|
|
763
|
+
reloadValuesFunc?.cancel();
|
|
764
|
+
} else if (inputValue.trim().length) {
|
|
765
|
+
setInputValueIsError(true);
|
|
699
766
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
[item],
|
|
716
|
-
obseverContext,
|
|
717
|
-
);
|
|
718
|
-
return primitiveInstanceValue;
|
|
719
|
-
})
|
|
720
|
-
.filter(isNonNullable);
|
|
721
|
-
break;
|
|
767
|
+
};
|
|
768
|
+
|
|
769
|
+
// event handlers
|
|
770
|
+
const changeValue = (
|
|
771
|
+
newSelectedOptions: { value: string; label: string }[],
|
|
772
|
+
actionChange: SelectActionData<{ value: string; label: string }>,
|
|
773
|
+
): void => {
|
|
774
|
+
setSelectedOptions(newSelectedOptions);
|
|
775
|
+
if (actionChange.action === 'select-option') {
|
|
776
|
+
setInputValue('');
|
|
777
|
+
} else if (
|
|
778
|
+
actionChange.action === 'remove-value' &&
|
|
779
|
+
actionChange.removedValue.value === inputValue
|
|
780
|
+
) {
|
|
781
|
+
setInputValueIsError(false);
|
|
722
782
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
);
|
|
741
|
-
instanceValue_setValues(
|
|
742
|
-
primitiveInstanceValue,
|
|
743
|
-
[item],
|
|
744
|
-
obseverContext,
|
|
745
|
-
);
|
|
746
|
-
return primitiveInstanceValue;
|
|
747
|
-
})
|
|
748
|
-
.filter(isNonNullable);
|
|
749
|
-
break;
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
const handleInputChange = (
|
|
786
|
+
newInputValue: string,
|
|
787
|
+
actionChange: InputActionData,
|
|
788
|
+
): void => {
|
|
789
|
+
if (actionChange.action === 'input-change') {
|
|
790
|
+
setInputValue(newInputValue);
|
|
791
|
+
setInputValueIsError(false);
|
|
792
|
+
reloadValuesFunc?.cancel();
|
|
793
|
+
const reloadValuesFuncTransformation =
|
|
794
|
+
reloadValuesFunc?.(newInputValue);
|
|
795
|
+
if (reloadValuesFuncTransformation) {
|
|
796
|
+
flowResult(reloadValuesFuncTransformation).catch(
|
|
797
|
+
applicationStore.alertUnhandledError,
|
|
798
|
+
);
|
|
799
|
+
}
|
|
750
800
|
}
|
|
751
|
-
|
|
752
|
-
|
|
801
|
+
if (actionChange.action === 'input-blur') {
|
|
802
|
+
reloadValuesFunc?.cancel();
|
|
803
|
+
cleanUpReloadValuesFunc?.();
|
|
804
|
+
}
|
|
805
|
+
};
|
|
806
|
+
|
|
807
|
+
const updateValueSpecAndSaveEdit = (): void => {
|
|
808
|
+
const newValueSpec = convertInputValueToValueSpec();
|
|
809
|
+
const finalSelectedOptions =
|
|
810
|
+
newValueSpec !== null
|
|
811
|
+
? [...selectedOptions, buildOptionForValueSpec(newValueSpec)]
|
|
812
|
+
: selectedOptions;
|
|
813
|
+
instanceValue_setValues(
|
|
814
|
+
valueSpecification,
|
|
815
|
+
finalSelectedOptions
|
|
816
|
+
.map((option) => option.value)
|
|
817
|
+
.map((value) =>
|
|
818
|
+
convertTextToPrimitiveInstanceValue(
|
|
819
|
+
expectedType,
|
|
820
|
+
value,
|
|
821
|
+
observerContext,
|
|
822
|
+
),
|
|
823
|
+
)
|
|
824
|
+
.filter(isNonNullable),
|
|
825
|
+
observerContext,
|
|
826
|
+
);
|
|
827
|
+
saveEdit();
|
|
828
|
+
};
|
|
829
|
+
|
|
830
|
+
const handleKeyDown = (event: KeyboardEvent): void => {
|
|
831
|
+
if ((event.key === 'Enter' || event.key === ',') && !event.shiftKey) {
|
|
832
|
+
addInputValueToSelectedOptions();
|
|
833
|
+
event.preventDefault();
|
|
834
|
+
}
|
|
835
|
+
};
|
|
836
|
+
|
|
837
|
+
const handlePaste = (event: React.ClipboardEvent<string>): void => {
|
|
838
|
+
const pastedText = event.clipboardData.getData('text');
|
|
839
|
+
const parsedData = parseCSVString(pastedText);
|
|
840
|
+
if (!parsedData) {
|
|
753
841
|
return;
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
)
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
842
|
+
}
|
|
843
|
+
const newValues = uniq(
|
|
844
|
+
uniq(parsedData)
|
|
845
|
+
.map((value) => {
|
|
846
|
+
const newValueSpec = convertTextToPrimitiveInstanceValue(
|
|
847
|
+
expectedType,
|
|
848
|
+
value,
|
|
849
|
+
observerContext,
|
|
850
|
+
);
|
|
851
|
+
return newValueSpec
|
|
852
|
+
? getValueSpecificationStringValue(newValueSpec)
|
|
853
|
+
: null;
|
|
854
|
+
})
|
|
855
|
+
.filter(isNonNullable),
|
|
856
|
+
).filter((value) => !isValueAlreadySelected(value));
|
|
857
|
+
setSelectedOptions([
|
|
858
|
+
...selectedOptions,
|
|
859
|
+
...newValues.map((value) => ({ label: value, value })),
|
|
860
|
+
]);
|
|
861
|
+
event.preventDefault();
|
|
862
|
+
};
|
|
863
|
+
|
|
864
|
+
return (
|
|
865
|
+
<>
|
|
866
|
+
<CustomSelectorInput
|
|
867
|
+
className={clsx('value-spec-editor__primitive-collection-selector', {
|
|
868
|
+
'value-spec-editor__primitive-collection-selector--error':
|
|
869
|
+
inputValueIsError,
|
|
870
|
+
})}
|
|
871
|
+
options={queryOptions}
|
|
872
|
+
inputValue={inputValue}
|
|
873
|
+
isMulti={true}
|
|
874
|
+
menuIsOpen={
|
|
875
|
+
isTypeaheadSearchEnabled &&
|
|
876
|
+
inputValue.length >= DEFAULT_TYPEAHEAD_SEARCH_MINIMUM_SEARCH_LENGTH
|
|
877
|
+
}
|
|
878
|
+
autoFocus={true}
|
|
879
|
+
inputRef={inputRef}
|
|
880
|
+
onChange={changeValue}
|
|
881
|
+
onInputChange={handleInputChange}
|
|
882
|
+
onBlur={() => updateValueSpecAndSaveEdit()}
|
|
883
|
+
onKeyDown={handleKeyDown}
|
|
884
|
+
onPaste={handlePaste}
|
|
885
|
+
value={selectedOptions}
|
|
886
|
+
darkMode={
|
|
887
|
+
!applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
|
|
888
|
+
}
|
|
889
|
+
isLoading={isLoading}
|
|
890
|
+
noMatchMessage={noMatchMessage}
|
|
891
|
+
placeholder={null}
|
|
892
|
+
inputPlaceholder={getPlaceHolder(expectedType)}
|
|
893
|
+
components={{
|
|
894
|
+
DropdownIndicator: null,
|
|
895
|
+
}}
|
|
896
|
+
/>
|
|
897
|
+
<button
|
|
898
|
+
className="value-spec-editor__list-editor__save-button btn--dark"
|
|
899
|
+
onClick={updateValueSpecAndSaveEdit}
|
|
900
|
+
>
|
|
901
|
+
<SaveIcon />
|
|
902
|
+
</button>
|
|
903
|
+
</>
|
|
904
|
+
);
|
|
905
|
+
},
|
|
906
|
+
);
|
|
778
907
|
|
|
779
908
|
const EnumCollectionInstanceValueEditor = observer(
|
|
780
909
|
(props: {
|
|
@@ -853,7 +982,8 @@ const EnumCollectionInstanceValueEditor = observer(
|
|
|
853
982
|
darkMode={
|
|
854
983
|
!applicationStore.layoutService.TEMPORARY__isLightColorThemeEnabled
|
|
855
984
|
}
|
|
856
|
-
placeholder=
|
|
985
|
+
placeholder={null}
|
|
986
|
+
inputPlaceholder="Add"
|
|
857
987
|
autoFocus={true}
|
|
858
988
|
menuIsOpen={true}
|
|
859
989
|
/>
|
|
@@ -870,21 +1000,6 @@ const EnumCollectionInstanceValueEditor = observer(
|
|
|
870
1000
|
|
|
871
1001
|
const COLLECTION_PREVIEW_CHAR_LIMIT = 50;
|
|
872
1002
|
|
|
873
|
-
const getPlaceHolder = (expectedType: Type): string => {
|
|
874
|
-
if (expectedType instanceof PrimitiveType) {
|
|
875
|
-
switch (expectedType.path) {
|
|
876
|
-
case PRIMITIVE_TYPE.DATE:
|
|
877
|
-
case PRIMITIVE_TYPE.STRICTDATE:
|
|
878
|
-
return 'yyyy-mm-dd';
|
|
879
|
-
case PRIMITIVE_TYPE.DATETIME:
|
|
880
|
-
return 'yyyy-mm-ddThh:mm:ss';
|
|
881
|
-
default:
|
|
882
|
-
return '(empty)';
|
|
883
|
-
}
|
|
884
|
-
}
|
|
885
|
-
return '(empty)';
|
|
886
|
-
};
|
|
887
|
-
|
|
888
1003
|
const CollectionValueInstanceValueEditor = observer(
|
|
889
1004
|
(props: {
|
|
890
1005
|
valueSpecification: CollectionInstanceValue;
|
|
@@ -893,6 +1008,7 @@ const CollectionValueInstanceValueEditor = observer(
|
|
|
893
1008
|
className?: string | undefined;
|
|
894
1009
|
resetValue: () => void;
|
|
895
1010
|
setValueSpecification: (val: ValueSpecification) => void;
|
|
1011
|
+
selectorConfig?: BasicValueSpecificationEditorSelectorConfig | undefined;
|
|
896
1012
|
obseverContext: ObserverContext;
|
|
897
1013
|
}) => {
|
|
898
1014
|
const {
|
|
@@ -901,14 +1017,11 @@ const CollectionValueInstanceValueEditor = observer(
|
|
|
901
1017
|
className,
|
|
902
1018
|
resetValue,
|
|
903
1019
|
setValueSpecification,
|
|
1020
|
+
selectorConfig,
|
|
904
1021
|
obseverContext,
|
|
905
1022
|
} = props;
|
|
906
|
-
const inputRef = useRef<HTMLTextAreaElement>(null);
|
|
907
1023
|
|
|
908
|
-
const [text, setText] = useState(stringifyValue(valueSpecification.values));
|
|
909
1024
|
const [editable, setEditable] = useState(false);
|
|
910
|
-
const [showAdvancedEditorPopover, setShowAdvancedEditorPopover] =
|
|
911
|
-
useState(false);
|
|
912
1025
|
const valueText = stringifyValue(valueSpecification.values);
|
|
913
1026
|
const previewText = `List(${
|
|
914
1027
|
valueSpecification.values.length === 0
|
|
@@ -927,78 +1040,13 @@ const CollectionValueInstanceValueEditor = observer(
|
|
|
927
1040
|
const saveEdit = (): void => {
|
|
928
1041
|
if (editable) {
|
|
929
1042
|
setEditable(false);
|
|
930
|
-
setShowAdvancedEditorPopover(false);
|
|
931
1043
|
setValueSpecification(valueSpecification);
|
|
932
1044
|
}
|
|
933
1045
|
};
|
|
934
|
-
const updateValueSpecAndSaveEdit = (): void => {
|
|
935
|
-
if (editable) {
|
|
936
|
-
setCollectionValue(
|
|
937
|
-
valueSpecification,
|
|
938
|
-
expectedType,
|
|
939
|
-
text,
|
|
940
|
-
obseverContext,
|
|
941
|
-
);
|
|
942
|
-
setText(stringifyValue(valueSpecification.values));
|
|
943
|
-
saveEdit();
|
|
944
|
-
}
|
|
945
|
-
};
|
|
946
|
-
|
|
947
|
-
const changeValueTextArea: React.ChangeEventHandler<HTMLTextAreaElement> = (
|
|
948
|
-
event,
|
|
949
|
-
) => {
|
|
950
|
-
setText(event.target.value);
|
|
951
|
-
};
|
|
952
|
-
const expandButtonName = `${valueSpecification.hashCode}ExpandButton`;
|
|
953
|
-
const handleOnBlur: React.FocusEventHandler<HTMLTextAreaElement> = (
|
|
954
|
-
event,
|
|
955
|
-
) => {
|
|
956
|
-
// disable save if target is expand button
|
|
957
|
-
if (
|
|
958
|
-
(event.relatedTarget as HTMLButtonElement | undefined)?.name !==
|
|
959
|
-
expandButtonName
|
|
960
|
-
) {
|
|
961
|
-
updateValueSpecAndSaveEdit();
|
|
962
|
-
}
|
|
963
|
-
};
|
|
964
|
-
|
|
965
|
-
const placeholder = text === '' ? getPlaceHolder(expectedType) : undefined;
|
|
966
|
-
|
|
967
|
-
// focus the input box when edit is enabled
|
|
968
|
-
useEffect(() => {
|
|
969
|
-
if (editable) {
|
|
970
|
-
inputRef.current?.focus();
|
|
971
|
-
}
|
|
972
|
-
}, [editable]);
|
|
973
1046
|
|
|
974
1047
|
if (editable) {
|
|
975
1048
|
return (
|
|
976
1049
|
<>
|
|
977
|
-
{showAdvancedEditorPopover && (
|
|
978
|
-
<BasePopover
|
|
979
|
-
onClose={() => setShowAdvancedEditorPopover(false)}
|
|
980
|
-
open={showAdvancedEditorPopover}
|
|
981
|
-
anchorEl={inputRef.current}
|
|
982
|
-
>
|
|
983
|
-
<textarea
|
|
984
|
-
className="panel__content__form__section__input value-spec-editor__list-editor__textarea"
|
|
985
|
-
spellCheck={false}
|
|
986
|
-
value={text}
|
|
987
|
-
placeholder={placeholder}
|
|
988
|
-
onChange={changeValueTextArea}
|
|
989
|
-
onKeyDown={(event): void => {
|
|
990
|
-
if (event.key === 'Enter' && !event.shiftKey) {
|
|
991
|
-
updateValueSpecAndSaveEdit();
|
|
992
|
-
}
|
|
993
|
-
}}
|
|
994
|
-
/>
|
|
995
|
-
<PanelFormSection>
|
|
996
|
-
<div className="value-spec-editor__list-editor__textarea__description">
|
|
997
|
-
Hit Enter to Apply Change
|
|
998
|
-
</div>
|
|
999
|
-
</PanelFormSection>
|
|
1000
|
-
</BasePopover>
|
|
1001
|
-
)}
|
|
1002
1050
|
<div className={clsx('value-spec-editor', className)}>
|
|
1003
1051
|
{expectedType instanceof Enumeration ? (
|
|
1004
1052
|
<EnumCollectionInstanceValueEditor
|
|
@@ -1007,39 +1055,13 @@ const CollectionValueInstanceValueEditor = observer(
|
|
|
1007
1055
|
saveEdit={saveEdit}
|
|
1008
1056
|
/>
|
|
1009
1057
|
) : (
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
value={text}
|
|
1018
|
-
placeholder={placeholder}
|
|
1019
|
-
onChange={changeValueTextArea}
|
|
1020
|
-
onKeyDown={(event): void => {
|
|
1021
|
-
if (event.key === 'Enter' && !event.shiftKey) {
|
|
1022
|
-
updateValueSpecAndSaveEdit();
|
|
1023
|
-
}
|
|
1024
|
-
}}
|
|
1025
|
-
onBlur={handleOnBlur}
|
|
1026
|
-
/>
|
|
1027
|
-
<button
|
|
1028
|
-
className="value-spec-editor__list-editor__expand-button btn--dark"
|
|
1029
|
-
onClick={() => setShowAdvancedEditorPopover(true)}
|
|
1030
|
-
tabIndex={-1}
|
|
1031
|
-
name={expandButtonName}
|
|
1032
|
-
title="Expand window..."
|
|
1033
|
-
>
|
|
1034
|
-
<FilledWindowMaximizeIcon />
|
|
1035
|
-
</button>
|
|
1036
|
-
<button
|
|
1037
|
-
className="value-spec-editor__list-editor__save-button btn--dark"
|
|
1038
|
-
onClick={saveEdit}
|
|
1039
|
-
>
|
|
1040
|
-
<SaveIcon />
|
|
1041
|
-
</button>
|
|
1042
|
-
</>
|
|
1058
|
+
<PrimitiveCollectionInstanceValueEditor
|
|
1059
|
+
valueSpecification={valueSpecification}
|
|
1060
|
+
expectedType={expectedType}
|
|
1061
|
+
saveEdit={saveEdit}
|
|
1062
|
+
selectorConfig={selectorConfig}
|
|
1063
|
+
observerContext={obseverContext}
|
|
1064
|
+
/>
|
|
1043
1065
|
)}
|
|
1044
1066
|
<button
|
|
1045
1067
|
className="value-spec-editor__reset-btn"
|
|
@@ -1141,16 +1163,7 @@ export const BasicValueSpecificationEditor = forwardRef<
|
|
|
1141
1163
|
setValueSpecification: (val: ValueSpecification) => void;
|
|
1142
1164
|
resetValue: () => void;
|
|
1143
1165
|
isConstant?: boolean;
|
|
1144
|
-
selectorConfig?:
|
|
1145
|
-
| {
|
|
1146
|
-
values: string[] | undefined;
|
|
1147
|
-
isLoading: boolean;
|
|
1148
|
-
reloadValues:
|
|
1149
|
-
| DebouncedFunc<(inputValue: string) => GeneratorFn<void>>
|
|
1150
|
-
| undefined;
|
|
1151
|
-
cleanUpReloadValues?: () => void;
|
|
1152
|
-
}
|
|
1153
|
-
| undefined;
|
|
1166
|
+
selectorConfig?: BasicValueSpecificationEditorSelectorConfig | undefined;
|
|
1154
1167
|
}
|
|
1155
1168
|
>(function BasicValueSpecificationEditor(props, ref) {
|
|
1156
1169
|
const {
|
|
@@ -1249,6 +1262,7 @@ export const BasicValueSpecificationEditor = forwardRef<
|
|
|
1249
1262
|
className={className}
|
|
1250
1263
|
resetValue={resetValue}
|
|
1251
1264
|
setValueSpecification={setValueSpecification}
|
|
1265
|
+
selectorConfig={selectorConfig}
|
|
1252
1266
|
obseverContext={obseverContext}
|
|
1253
1267
|
/>
|
|
1254
1268
|
);
|