Skip to content

Commit

Permalink
Fix default filter form and code/data tests
Browse files Browse the repository at this point in the history
  • Loading branch information
marcopagliarulo committed Apr 30, 2023
1 parent 370a0fb commit ceebdfc
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 115 deletions.
8 changes: 4 additions & 4 deletions packages/bodiless-core/__tests__/withEditButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ describe('withEditButton', () => {
});
});

it.skip('does not re-render a menu option when data changes', () => {
it('does not re-render a menu option when data changes', () => {
const MockMenu = observer(() => {
const { contextMenuOptions } = useEditContext();
const op = contextMenuOptions[0] || false;
Expand Down Expand Up @@ -102,16 +102,16 @@ describe('withEditButton', () => {
const wrapper = mount(<Test componentData={{ foo: 'foo' }} />);
expect(itemRendered).toBeCalledTimes(1);
wrapper.find('div[aria-label="Foo"]').simulate('click');
expect(wrapper.find('input[name="foo"]').prop('value')).toEqual('foo');
expect(wrapper.find('input[name$="foo"]').prop('value')).toEqual('foo');
expect(itemRendered).toBeCalledTimes(2);
wrapper.find('button[aria-label="Cancel"]').simulate('click');
expect(itemRendered).toBeCalledTimes(3);
expect(wrapper.find('input[name="foo"]')).toHaveLength(0);
expect(wrapper.find('input[name$="foo"]')).toHaveLength(0);
wrapper.setProps({ componentData: { foo: 'bar' } });
// @TODO: investigate why it is triggering extra render.
// expect(itemRendered).toBeCalledTimes(3);
wrapper.find('div[aria-label="Foo"]').simulate('click');
expect(wrapper.find('input[name="foo"]').prop('value')).toEqual('bar');
expect(wrapper.find('input[name$="foo"]').prop('value')).toEqual('bar');
// @TODO: investigate why it is triggering extra render.
// expect(itemRendered).toBeCalledTimes(4);
});
Expand Down
4 changes: 2 additions & 2 deletions packages/bodiless-data/__tests__/withDefaultContent.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ describe('withDefaultContent', () => {
const wrapper = mount(<Foo />);
expect(wrapper.find('Foo').html()).toBe('root$foo');
});
it.skip('allows getting sibling node data', () => {
it('allows getting sibling node data', () => {
const Foo = flow(
withNode,
withNodeKey('foo'),
Expand All @@ -165,7 +165,7 @@ describe('withDefaultContent', () => {
bar: 'defaultBarValue',
})(BazBase);
const wrapper = mount(<Baz />);
expect(wrapper.find('Foo').html()).toBe('');
expect(wrapper.find('Foo').text()).toBe('');
});
it('allows merging default content with node data', () => {
const FooConsumer = createNodeConsumer('Foo');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ describe('Filter item interactions', () => {
input.simulate('change', { target: { value: [] } });
});

// Skip because the feature actually works and this test doesn't cover anymore the scenario.
it.skip('context form should not save content when cancel is clicked', () => {
let input = menuForm.find('input[name$="tags"][type="hidden"]');
input.simulate('change', { target: { value: [testTag] } });
Expand Down
238 changes: 130 additions & 108 deletions packages/bodiless-filtering/src/FilterByGroup/withFilterSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
* limitations under the License.
*/

import React, { useCallback, useEffect, useState } from 'react';
import { useFormState } from 'informed';
import React, { useEffect } from 'react';
import { useFormApi, Multistep, useMultistepApi} from 'informed';
import {
withEditButton,
EditButtonOptions,
Expand All @@ -23,6 +23,7 @@ import {
ContextMenuFormProps,
getUI,
useEditContext,
ContextMenuUI,
} from '@bodiless/core';
import {
withNodeDataHandlers,
Expand Down Expand Up @@ -58,152 +59,173 @@ const MSG_RESET_CLEAR = 'The Saved State is filtering this Page for the End User
const MSG_RESET_SUCCESS = 'UI Filter reset to Saved State.';
const MSG_CLEAR_SUCCESS = 'The Saved State has been cleared.';

/**
* Renders default filter form in different use cases:
* - No existing default filter set yet.
* submit form to save the selected tags.
* - Has saved default filter.
* - Clear/remove saved default filter
* - Reset current selection to default filter selection.
*
* @private
* @params props Default filter form properties.
* @returns void
*/
const getRenderForm = (node: ContentNode<DefaultFilterData>) => (props: ContextMenuFormProps) => {
const { getSelectedTags, updateSelectedTags } = useFilterByGroupContext();
const { ui } = props;
const SaveForm = ({node, ui} : {node: ContentNode<DefaultFilterData>, ui?: ContextMenuUI}) => {
const {
ComponentFormText,
ComponentFormDescription,
ComponentFormSubmitButton,
} = getUI(ui);
const { getFormState } = useFormApi();
const { setCurrent } = useMultistepApi();
const { getSelectedTags, updateSelectedTags } = useFilterByGroupContext();
const { tags: defaultTags = [] } = node.data;

useEffect(() => {
if (defaultTags.length) {
setCurrent('clear');
}
}, []);

// eslint-disable-next-line consistent-return
const handleSubmit = (e: React.SyntheticEvent) => {
e.preventDefault();
const { values } = getFormState();
// @ts-ignore
const v = values[Object.keys(values)[0]] as any;
// eslint-disable-next-line default-case
switch (v.save.filterSelectionAction) {
case FilterSelectionAction.save: {
const currentTags = getSelectedTags();
updateSelectedTags(currentTags);
node.setData({ tags: currentTags });
setCurrent('saveSuccess');
return currentTags;
}
}
};

return (
<>
<ComponentFormDescription>
{MSG_SAVE}
</ComponentFormDescription>
<ComponentFormText
type="hidden"
name="filterSelectionAction"
keepState
initialValue={FilterSelectionAction.save}
/>
<ComponentFormSubmitButton
aria-label="Submit"
onClick={handleSubmit}
/>
</>
);
};

const RestClearForm = ({node, ui} : {node: ContentNode<DefaultFilterData>, ui?: ContextMenuUI}) => {
const {
ComponentFormDescription,
ComponentFormLabel,
ComponentFormRadioGroup,
ComponentFormRadio,
ComponentFormSubmitButton,
} = getUI(ui);

const { getFormState } = useFormApi();
const { setCurrent } = useMultistepApi();
const { updateSelectedTags } = useFilterByGroupContext();
const { tags: defaultTags = [] } = node.data;
const [step, setStep] = useState(1);
const { values } = useFormState();

// eslint-dis
useEffect(() => {
if (!defaultTags.length) {
setStep(FilterSelectionAction.save);
} else {
setStep(FilterSelectionAction.reset);
setCurrent('save');
}
}, []);

// eslint-disable-next-line consistent-return
const handleSubmit = useCallback((e: React.SyntheticEvent) => {
const handleSubmit = (e: React.SyntheticEvent) => {
e.preventDefault();
const { values } = getFormState();
// @ts-ignore
const v = values[Object.keys(values)[0]] as any;
// eslint-disable-next-line default-case
switch (v.filterSelectionAction) {
switch (v.clear.filterSelectionAction) {
case FilterSelectionAction.clear: {
const submitValues = { tags: [] };
updateSelectedTags(submitValues.tags);
node.setData(submitValues);
setStep(FilterSelectionAction.clear_success);
setCurrent('clearSuccess');
return submitValues;
}
case FilterSelectionAction.reset: {
updateSelectedTags(defaultTags);
setStep(FilterSelectionAction.reset_success);
setCurrent('resetSuccess');
return { tags: defaultTags };
}
case FilterSelectionAction.save: {
const currentTags = getSelectedTags();
updateSelectedTags(currentTags);
node.setData({ tags: currentTags });
setStep(FilterSelectionAction.save_success);
return currentTags;
}
}
}, [values]);
};

const SaveForm = useCallback(() => {
if (step === FilterSelectionAction.save_success) {
return (
<ComponentFormDescription>
{MSG_SAVE_SUCCESS}
</ComponentFormDescription>
);
}
return (
<>
<ComponentFormDescription>
{MSG_RESET_CLEAR}
</ComponentFormDescription>
<ComponentFormRadioGroup
name="filterSelectionAction"
keepState
initialValue={FilterSelectionAction.reset}
>
<ComponentFormLabel key={FilterSelectionAction.reset}>
<ComponentFormRadio value={FilterSelectionAction.reset.toString()} />
Reset Local Filter UI to Saved State
</ComponentFormLabel>
<ComponentFormLabel key={FilterSelectionAction.clear}>
<ComponentFormRadio value={FilterSelectionAction.clear.toString()} />
Clear Saved State from Page
</ComponentFormLabel>
</ComponentFormRadioGroup>
<ComponentFormSubmitButton
aria-label="Submit"
onClick={handleSubmit}
/>
</>
);
};

return (
<>
/**
* Renders default filter form in different use cases:
* - No existing default filter set yet.
* submit form to save the selected tags.
* - Has saved default filter.
* - Clear/remove saved default filter
* - Reset current selection to default filter selection.
*
* @private
* @params props Default filter form properties.
* @returns void
*/
const getRenderForm = (node: ContentNode<DefaultFilterData>) => (props: ContextMenuFormProps) => {
const { ui } = props;
const {
ComponentFormDescription,
} = getUI(ui);

return (
<Multistep>
<Multistep.Step step="save">
<SaveForm ui={ui} node={node} />
</Multistep.Step>
<Multistep.Step step="saveSuccess">
<ComponentFormDescription>
{MSG_SAVE}
{MSG_SAVE_SUCCESS}
</ComponentFormDescription>
<ComponentFormText
type="hidden"
name="filterSelectionAction"
keepState
initialValue={FilterSelectionAction.save}
/>
<ComponentFormSubmitButton
aria-label="Submit"
onClick={handleSubmit}
/>
</>
);
}, [step]);

const RestClearForm = useCallback(() => {
if (step === FilterSelectionAction.clear_success) {
return (
</Multistep.Step>
<Multistep.Step step="clear">
<RestClearForm ui={ui} node={node} />
</Multistep.Step>
<Multistep.Step step="clearSuccess">
<ComponentFormDescription>
{MSG_CLEAR_SUCCESS}
</ComponentFormDescription>
);
}

if (step === FilterSelectionAction.reset_success) {
return (
</Multistep.Step>
<Multistep.Step step="resetSuccess">
<ComponentFormDescription>
{MSG_RESET_SUCCESS}
</ComponentFormDescription>
);
}

return (
<>
<ComponentFormDescription>
{MSG_RESET_CLEAR}
</ComponentFormDescription>
<ComponentFormRadioGroup
name="filterSelectionAction"
keepState
initialValue={FilterSelectionAction.reset}
>
<ComponentFormLabel key={FilterSelectionAction.reset}>
<ComponentFormRadio value={FilterSelectionAction.reset.toString()} />
Reset Local Filter UI to Saved State
</ComponentFormLabel>
<ComponentFormLabel key={FilterSelectionAction.clear}>
<ComponentFormRadio value={FilterSelectionAction.clear.toString()} />
Clear Saved State from Page
</ComponentFormLabel>
</ComponentFormRadioGroup>
<ComponentFormSubmitButton
aria-label="Submit"
onClick={handleSubmit}
/>
</>
);
}, [step, values]);

return (
<>
{(step === FilterSelectionAction.save
|| step === FilterSelectionAction.save_success)
&& <SaveForm />}
{(step === FilterSelectionAction.reset
|| step === FilterSelectionAction.reset_success
|| step === FilterSelectionAction.clear
|| step === FilterSelectionAction.clear_success)
&& <RestClearForm />}
</>
</Multistep.Step>
</Multistep>
);
};

Expand Down
4 changes: 4 additions & 0 deletions packages/bodiless-filtering/src/TagButton/withTagButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ export const tagButtonOptions: TagButtonType = {
} = componentProps;

const suggestions = getSuggestions();
const suggestionsTransform = (value: string, suggestions: TagType[]) => (
suggestions.filter((tag: TagType) => value && tag.label.search(value) >= 0)
);

const context = useEditContext();
const displayListOfTags = () => context.showPageOverlay({
Expand Down Expand Up @@ -89,6 +92,7 @@ export const tagButtonOptions: TagButtonType = {
allowMultipleTags={allowMultipleTags}
selected={[]}
renderInput={Input}
suggestionsTransform={suggestionsTransform}
/>
<ComponentFormUnwrapButton type="button" onClick={displayListOfTags}>
{seeAllText}
Expand Down
2 changes: 1 addition & 1 deletion sites/test-site/src/data/pages/filter-page/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const Switcher = () => {
<>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label className="py-4 block">
<input className="mr-2" type="checkbox" checked={multiple} onClick={() => setMultiple(v => !v)} />
<input className="mr-2" type="checkbox" checked={multiple} onChange={() => {}} onClick={() => setMultiple(v => !v)} />
Allow selecting multiple terms in each category
</label>
<Filter>
Expand Down

0 comments on commit ceebdfc

Please sign in to comment.