diff --git a/.changeset/afraid-flies-attack.md b/.changeset/afraid-flies-attack.md new file mode 100644 index 00000000000..826ff47e99c --- /dev/null +++ b/.changeset/afraid-flies-attack.md @@ -0,0 +1,5 @@ +--- +'@finos/legend-query-builder': patch +--- + +Stop defaulting values to derived property/filter/post-filter panel diff --git a/packages/legend-query-builder/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx b/packages/legend-query-builder/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx index 8ebe3c5022b..561cd9fc0ea 100644 --- a/packages/legend-query-builder/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx +++ b/packages/legend-query-builder/src/components/fetch-structure/QueryBuilderPostFilterPanel.tsx @@ -46,12 +46,14 @@ import { MoreVerticalIcon, MenuContentItemIcon, MenuContentItemLabel, + ExclamationTriangleIcon, } from '@finos/legend-art'; import { type ValueSpecification, Class, Enumeration, PrimitiveType, + InstanceValue, } from '@finos/legend-graph'; import { assertErrorThrown, @@ -82,7 +84,10 @@ import { } from '../../stores/fetch-structure/tds/projection/QueryBuilderProjectionColumnState.js'; import type { QueryBuilderState } from '../../stores/QueryBuilderState.js'; import { QUERY_BUILDER_TEST_ID } from '../../__lib__/QueryBuilderTesting.js'; -import { isTypeCompatibleForAssignment } from '../../stores/QueryBuilderValueSpecificationHelper.js'; +import { + isTypeCompatibleForAssignment, + isValidInstanceValue, +} from '../../stores/QueryBuilderValueSpecificationHelper.js'; import { QUERY_BUILDER_GROUP_OPERATION } from '../../stores/QueryBuilderGroupOperationHelper.js'; import { QueryBuilderTDSState } from '../../stores/fetch-structure/tds/QueryBuilderTDSState.js'; import { @@ -100,6 +105,7 @@ import { } from '../../stores/fetch-structure/tds/window/QueryBuilderWindowState.js'; import type { QueryBuilderTDSColumnState } from '../../stores/fetch-structure/tds/QueryBuilderTDSColumnState.js'; import { QueryBuilderTelemetryHelper } from '../../__lib__/QueryBuilderTelemetryHelper.js'; +import { QueryBuilderPanelIssueCountBadge } from '../shared/QueryBuilderPanelIssueCountBadge.js'; const QueryBuilderPostFilterConditionContextMenu = observer( forwardRef< @@ -366,6 +372,9 @@ const QueryBuilderPostFilterConditionEditor = observer( reloadValues: debouncedTypeaheadSearch, cleanUpReloadValues, }; + const isPostFilterValueInValid = + node.condition.value instanceof InstanceValue && + !isValidInstanceValue(node.condition.value); const { showDroppableSuggestion } = useDragLayer((monitor) => ({ showDroppableSuggestion: @@ -454,6 +463,11 @@ const QueryBuilderPostFilterConditionEditor = observer( )} /> + {isPostFilterValueInValid && ( +
+ +
+ )} )} @@ -971,6 +985,11 @@ const QueryBuilderPostFilterPanelContent = observer(
post-filter
+ {postFilterState.allValidationIssues.length !== 0 && ( + + )}
({ showDroppableSuggestion: monitor.isDragging() && @@ -240,7 +244,9 @@ const QueryBuilderFilterConditionEditor = observer( : IS_DRAGGABLE_FILTER_DND_TYPES ).includes(monitor.getItemType()?.toString() ?? ''), })); - + const isFilterValueInValid = + node.condition.value instanceof InstanceValue && + !isValidInstanceValue(node.condition.value); return (
{showDroppableSuggestion && ( @@ -323,6 +329,11 @@ const QueryBuilderFilterConditionEditor = observer( )} /> + {isFilterValueInValid && ( +
+ +
+ )}
)}
@@ -906,6 +917,11 @@ export const QueryBuilderFilterPanel = observer(
filter
+ {filterState.allValidationIssues.length !== 0 && ( + + )}
diff --git a/packages/legend-query-builder/src/components/shared/BasicValueSpecificationEditor.tsx b/packages/legend-query-builder/src/components/shared/BasicValueSpecificationEditor.tsx index d3ba779f4c6..3730db80d46 100644 --- a/packages/legend-query-builder/src/components/shared/BasicValueSpecificationEditor.tsx +++ b/packages/legend-query-builder/src/components/shared/BasicValueSpecificationEditor.tsx @@ -33,6 +33,7 @@ import { BasePopover, PanelFormSection, CalculateIcon, + type SelectComponent, } from '@finos/legend-art'; import { type Enum, @@ -67,6 +68,7 @@ import { parseCSVString, guaranteeIsNumber, csvStringify, + guaranteeType, } from '@finos/legend-shared'; import { flowResult } from 'mobx'; import { observer } from 'mobx-react-lite'; @@ -227,6 +229,8 @@ const StringPrimitiveInstanceValueEditor = observer( selectorConfig, obseverContext, } = props; + const inputRef = useRef(null); + const selectorRef = useRef(null); const useSelector = Boolean(selectorConfig); const applicationStore = useApplicationStore(); const value = valueSpecification.values[0] as string; @@ -277,10 +281,19 @@ const StringPrimitiveInstanceValueEditor = observer( const noOptionsMessage = selectorConfig?.values === undefined ? (): null => null : undefined; + useEffect(() => { + if (useSelector) { + selectorRef.current?.focus(); + } else { + inputRef.current?.focus(); + } + }, [useSelector]); + return (
{useSelector ? ( ) : ( (null); - const numericValue = isInteger - ? Number.parseInt(Number(value).toString(), 10) - : Number(value); + const numericValue = value + ? isInteger + ? Number.parseInt(Number(value).toString(), 10) + : Number(value) + : undefined; const changeValue: React.ChangeEventHandler = (event) => { setValue(event.target.value); @@ -393,7 +411,7 @@ const NumberPrimitiveInstanceValueEditor = observer( // Support expression evaluation const calculateExpression = (): void => { - if (isNaN(numericValue)) { + if (value && numericValue && isNaN(numericValue)) { try { const calculatedValue = guaranteeIsNumber(evaluate(value)); setValue( @@ -405,7 +423,7 @@ const NumberPrimitiveInstanceValueEditor = observer( setValue((valueSpecification.values[0] as number).toString()); } } else { - setValue(numericValue.toString()); + setValue(numericValue ? numericValue.toString() : ''); } }; @@ -419,11 +437,16 @@ const NumberPrimitiveInstanceValueEditor = observer( }; useEffect(() => { - setValue((valueSpecification.values[0] as number).toString()); + setValue( + valueSpecification.values[0] + ? (valueSpecification.values[0] as number).toString() + : '', + ); }, [valueSpecification]); useEffect(() => { if ( + numericValue && !isNaN(numericValue) && numericValue !== valueSpecification.values[0] ) { @@ -434,6 +457,9 @@ const NumberPrimitiveInstanceValueEditor = observer( obseverContext, ); setValueSpecification(valueSpecification); + } else if (!numericValue) { + instanceValue_setValues(valueSpecification, [], obseverContext); + setValueSpecification(valueSpecification); } }, [ numericValue, @@ -442,6 +468,10 @@ const NumberPrimitiveInstanceValueEditor = observer( obseverContext, ]); + useEffect(() => { + inputRef.current?.focus(); + }, []); + return (
@@ -493,9 +523,13 @@ const EnumValueInstanceValueEditor = observer( setValueSpecification, obseverContext, } = props; - const enumValueRef = guaranteeNonNullable(valueSpecification.values[0]); - const enumValue = enumValueRef.value; - const options = enumValue._OWNER.values.map((value) => ({ + const selectorRef = useRef(null); + const enumValueRef = valueSpecification.values[0]; + const enumValue = enumValueRef?.value; + const options = guaranteeType( + valueSpecification.genericType?.ownerReference.value, + Enumeration, + ).values.map((value) => ({ label: value.name, value: value, })); @@ -509,13 +543,18 @@ const EnumValueInstanceValueEditor = observer( setValueSpecification(valueSpecification); }; + useEffect(() => { + selectorRef.current?.focus(); + }, []); + return (