From 32b0ddc3d6d4e90e3ba7319d965a2a7f1af4706d Mon Sep 17 00:00:00 2001 From: Caden Buckhalt Date: Thu, 5 Dec 2024 12:11:12 -0800 Subject: [PATCH] refactor logic for showing warning. use across instances --- src/components/sections/Filter.js | 18 ++++----- .../SociogramPrompts/PromptFieldsEdges.js | 9 ++--- .../PromptFieldsTapBehaviour.js | 20 ++-------- .../sections/SociogramPrompts/selectors.js | 38 +++++++++++++++++++ 4 files changed, 54 insertions(+), 31 deletions(-) diff --git a/src/components/sections/Filter.js b/src/components/sections/Filter.js index 38c63dc92..5dc510886 100644 --- a/src/components/sections/Filter.js +++ b/src/components/sections/Filter.js @@ -8,6 +8,7 @@ import { Filter as FilterQuery, withFieldConnector, withStoreConnector, ruleValidator, } from '../Query'; import Tip from '../Tip'; +import { getEdgeFilteringWarning } from './SociogramPrompts/selectors'; const FilterField = withFieldConnector(withStoreConnector(FilterQuery)); @@ -49,15 +50,14 @@ const Filter = () => { (prompt) => prompt.edges.display, ); - const ruleEdgeTypes = currentValue?.rules.filter((rule) => rule.type === 'edge').map((rule) => rule.options.type); - // show warning if there are creation or display values that will not be shown based on filters - const shouldShowWarning = edgeCreationValues.some( - (edgeCreationValue) => !ruleEdgeTypes.includes(edgeCreationValue), - ) || edgeDisplayValues.some( - (edgeDisplayValue) => !edgeDisplayValue.some( - (edge) => ruleEdgeTypes.includes(edge), - ), - ); + let shouldShowWarning = false; + + if (edgeCreationValues.length > 0 || edgeDisplayValues.length > 0) { + shouldShowWarning = getEdgeFilteringWarning( + currentValue.rules, + [...edgeCreationValues, ...edgeDisplayValues], + ); + } const handleToggleChange = useCallback( async (newState) => { diff --git a/src/components/sections/SociogramPrompts/PromptFieldsEdges.js b/src/components/sections/SociogramPrompts/PromptFieldsEdges.js index 32cadf3a0..453ceb2b6 100644 --- a/src/components/sections/SociogramPrompts/PromptFieldsEdges.js +++ b/src/components/sections/SociogramPrompts/PromptFieldsEdges.js @@ -7,7 +7,7 @@ import { change, Field, formValueSelector } from 'redux-form'; import * as Fields from '@codaco/ui/lib/components/Fields'; import { Section, Row } from '@components/EditorLayout'; import Tip from '../../Tip'; -import { getEdgesForSubject } from './selectors'; +import { getEdgeFilteringWarning, getEdgesForSubject } from './selectors'; const DisplayEdges = ({ form, entity, type }) => { const dispatch = useDispatch(); @@ -35,10 +35,7 @@ const DisplayEdges = ({ form, entity, type }) => { const currentFilters = useSelector((state) => getStageValue(state, 'filter')); const edgeFilters = currentFilters.rules.filter((rule) => rule.type === 'edge'); - // TODO: look at this logic to see if it's correct for all cases - const selectedEdgesNotInFilters = displayEdges.filter( - (selectedEdge) => !edgeFilters.some((edgeFilter) => edgeFilter.options.type === selectedEdge), - ); + const shouldShowNetworkFilterWarning = getEdgeFilteringWarning(edgeFilters, displayEdges); return ( <> @@ -69,7 +66,7 @@ const DisplayEdges = ({ form, entity, type }) => { }} > - {selectedEdgesNotInFilters.length > 0 && ( + {shouldShowNetworkFilterWarning && (

One or more of the selected edge types are not currently included in the diff --git a/src/components/sections/SociogramPrompts/PromptFieldsTapBehaviour.js b/src/components/sections/SociogramPrompts/PromptFieldsTapBehaviour.js index 3ca100d1e..2d81a1b32 100644 --- a/src/components/sections/SociogramPrompts/PromptFieldsTapBehaviour.js +++ b/src/components/sections/SociogramPrompts/PromptFieldsTapBehaviour.js @@ -9,10 +9,9 @@ import Tip from '@components/Tip'; import EntitySelectField from '../fields/EntitySelectField/EntitySelectField'; import DetachedField from '../../DetachedField'; import VariablePicker from '../../Form/Fields/VariablePicker/VariablePicker'; -import { getHighlightVariablesForSubject } from './selectors'; +import { getHighlightVariablesForSubject, getEdgeFilteringWarning } from './selectors'; import { actionCreators as codebookActions } from '../../../ducks/modules/protocol/codebook'; -import { asOptions } from '../../../selectors/utils'; -import { getEdgeTypes } from '../../../selectors/codebook'; + // TODO: Move this somewhere else! // This was created as part of removing the HOC pattern used throughout the app. // It replaces withCreateVariableHandler. Other uses of this handler could be @@ -103,9 +102,6 @@ const TapBehaviour = ({ return true; }; - const edgeOptions = useSelector((state) => asOptions(getEdgeTypes(state))); - - // get selected value const selectedValue = useSelector((state) => getFormValue(state, 'edges.create')); // get the current edge filters from the stage @@ -113,15 +109,7 @@ const TapBehaviour = ({ const currentFilters = useSelector((state) => getStageValue(state, 'filter')); const edgeFilters = currentFilters.rules.filter((rule) => rule.type === 'edge'); - // get selected edges from options - const selectedEdges = edgeOptions.filter((option) => option.value === selectedValue); - - // TODO: look at this logic to see if it's correct for all cases - const selectedEdgesNotInFilters = selectedEdges.filter( - (selectedEdge) => !edgeFilters.some( - (edgeFilter) => edgeFilter.options.type === selectedEdge.value, - ), - ); + const showNetworkFilterWarning = getEdgeFilteringWarning(edgeFilters, [selectedValue]); return (

- {selectedEdgesNotInFilters.length > 0 && ( + {showNetworkFilterWarning && (

The selected edge type is not currently included in the stage-level network filtering. diff --git a/src/components/sections/SociogramPrompts/selectors.js b/src/components/sections/SociogramPrompts/selectors.js index e4f5fd626..3ab2b3b1a 100644 --- a/src/components/sections/SociogramPrompts/selectors.js +++ b/src/components/sections/SociogramPrompts/selectors.js @@ -32,3 +32,41 @@ export const getEdgesForSubject = (state) => { return codebookOptions; }; + +// compare selected edges to edge filters +// there are four cases to consider: +// 1. selected edge is in the filters with rule EXISTS -- no warning +// 2. selected edge is not in the filters with rule EXISTS -- show a warning +// 3. selected edge is in the filters with rule DOES_NOT_EXIST -- show a warning +// 4. selected edge is not in the filters with rule DOES_NOT_EXIST -- no warning + +export const getEdgeFilteringWarning = (filters, edges) => { + const existFilters = filters.filter((rule) => rule.options.operator === 'EXISTS'); + const doesNotExistFilters = filters.filter((rule) => rule.options.operator === 'NOT_EXISTS'); + + // if any edge should show a warning, return true + return edges.some((edge) => { + const isEdgeInExistFilters = existFilters.some((rule) => rule.options.type === edge); + const isEdgeInDoesNotExistFilters = doesNotExistFilters.some( + (rule) => rule.options.type === edge, + ); + + // case 1 + if (isEdgeInExistFilters) { + return false; + } + + // case 2 + if (!isEdgeInExistFilters && existFilters.length > 0) { + return true; + } + + // case 3 + if (isEdgeInDoesNotExistFilters) { + return true; + } + + // No warning in other cases + return false; + }); +};