Skip to content
This repository has been archived by the owner on Dec 30, 2022. It is now read-only.

Commit

Permalink
fix(hierarchicaMenu): allow sorting and using limit
Browse files Browse the repository at this point in the history
Make sure transformValue is applied before transformItems, so that the limit (or truncation) is applied when the items have been transformed.

fixes #92
  • Loading branch information
marielaures authored and vvo committed Oct 16, 2017
1 parent 3f218db commit fe178ed
Show file tree
Hide file tree
Showing 4 changed files with 264 additions and 27 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ addons:
before_install:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.1.0
- curl -o- -L https://yarnpkg.com/install.sh | bash -s -- --version 1.2.0
- export PATH=$HOME/.yarn/bin:$PATH
cache:
yarn: true
Expand Down
33 changes: 15 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,23 @@
"boot": "./scripts/boot.sh",
"upgrade-deps": "./scripts/upgrade-deps.sh",
"changelog": "conventional-changelog --preset angular --output-unreleased",
"start":
"NODE_ENV=development babel-node docgen/start.js & NODE_ENV=development yarn docs:storybook-start & wait",
"docs:build":
"babel-node docgen/build.js && yarn docs:storybook-build-production",
"docs:deploy-production":
"NODE_ENV=production yarn docs:build && babel-node scripts/gh-pages.js",
"start": "NODE_ENV=development babel-node docgen/start.js & NODE_ENV=development yarn docs:storybook-start & wait",
"docs:build": "babel-node docgen/build.js && yarn docs:storybook-build-production",
"docs:deploy-production": "NODE_ENV=production yarn docs:build && babel-node scripts/gh-pages.js",
"docs:build-preview": "./scripts/docs:build-preview.sh",
"docs:deploy-preview":
"NODE_ENV=production yarn docs:build-preview && rm -f preview.zip && zip -r -9 preview.zip docs-production/ && netlify deploy && rm preview.zip",
"docs:deploy-preview": "NODE_ENV=production yarn docs:build-preview && rm -f preview.zip && zip -r -9 preview.zip docs-production/ && netlify deploy && rm preview.zip",
"release": "NODE_ENV=production ./scripts/release.sh",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"docs:doctoc": "doctoc --maxlevel 1 README.md",
"test": "./scripts/test.sh",
"test:recipes": "./scripts/test:recipes.sh",
"test:build": "NODE_ENV=production ./scripts/test:build.sh",
"test:regressions":
"webpack --config test/regressions/webpack.config.js && rm -rf test/screenshots && happo run && babel-node ./test/regressions/normalize.js",
"test:regressions": "webpack --config test/regressions/webpack.config.js && rm -rf test/screenshots && happo run && babel-node ./test/regressions/normalize.js",
"argos": "argos upload test/screenshots --token $ARGOS_TOKEN || true",
"dev": "jest --watch --bail",
"docs:storybook-start":
"start-storybook -p 6006 -c ./storybook -s ./storybook/public",
"docs:storybook-build-production":
"build-storybook -s ./storybook/public -o docs-production/react-instantsearch/storybook -c ./storybook"
"docs:storybook-start": "start-storybook -p 6006 -c ./storybook -s ./storybook/public",
"docs:storybook-build-production": "build-storybook -s ./storybook/public -o docs-production/react-instantsearch/storybook -c ./storybook"
},
"devDependencies": {
"@storybook/addon-actions": "3.2.12",
Expand Down Expand Up @@ -129,12 +122,16 @@
},
"engines": {
"node": "8.6.0",
"yarn": "1.1.0"
"yarn": "1.2.0"
},
"jest": {
"notify": false,
"testPathIgnorePatterns": ["/packages/react-instantsearch/examples"],
"setupFiles": ["./shim.js"]
"testPathIgnorePatterns": [
"/packages/react-instantsearch/examples"
],
"setupFiles": [
"./shim.js"
]
},
"license": "MIT",
"author": {
Expand All @@ -145,4 +142,4 @@
"algolia-aerial": "^1.1.4",
"algolia-frontend-components": "^0.0.34"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,27 @@ function getValue(path, props, searchState, context) {
return nextRefinement;
}

function transformValue(value, limit, props, searchState, context) {
return value.slice(0, limit).map(v => ({
function transformValue(value, props, searchState, context) {
return value.map(v => ({
label: v.name,
value: getValue(v.path, props, searchState, context),
count: v.count,
isRefined: v.isRefined,
items: v.data && transformValue(v.data, limit, props, searchState, context),
items: v.data && transformValue(v.data, props, searchState, context),
}));
}

const truncate = (items = [], limit = 10) =>
items.slice(0, limit).map(
(item = {}) =>
Array.isArray(item.items)
? {
...item,
items: truncate(item.items, limit),
}
: item
);

function refine(props, searchState, nextRefinement, context) {
const id = getId(props);
const nextValue = { [id]: nextRefinement || '' };
Expand Down Expand Up @@ -166,8 +177,8 @@ export default createConnector({
getProvidedProps(props, searchState, searchResults) {
const { showMore, limitMin, limitMax } = props;
const id = getId(props);
const results = getResults(searchResults, this.context);

const results = getResults(searchResults, this.context);
const isFacetPresent =
Boolean(results) && Boolean(results.getFacetByName(id));

Expand All @@ -182,15 +193,16 @@ export default createConnector({
canRefine: false,
};
}

const limit = showMore ? limitMax : limitMin;
const value = results.getFacetValues(id, { sortBy });
const items = value.data
? transformValue(value.data, limit, props, searchState, this.context)
? transformValue(value.data, props, searchState, this.context)
: [];

const transformedItems = props.transformItems
? props.transformItems(items)
: items;
return {
items: props.transformItems ? props.transformItems(items) : items,
items: truncate(transformedItems, limit),
currentRefinement: getCurrentRefinement(props, searchState, this.context),
canRefine: items.length > 0,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe('connectHierarchicalMenu', () => {
{ hierarchicalMenu: { ok: 'wat' } },
{ results }
);

expect(props).toEqual({
canRefine: false,
currentRefinement: 'wat',
Expand Down Expand Up @@ -169,6 +170,233 @@ describe('connectHierarchicalMenu', () => {
expect(props.items).toEqual(['items']);
});

it('shows the effect of limitMax when there is no transformItems', () => {
const results = {
getFacetValues: jest.fn(),
getFacetByName: () => true,
hits: [],
};
results.getFacetValues.mockImplementation(() => ({
data: [
{
name: 'wat',
path: 'wat',
count: 20,
data: [
{
name: 'wot',
path: 'wat > wot',
count: 15,
},
{
name: 'wut',
path: 'wat > wut',
count: 3,
},
{
name: 'wit',
path: 'wat > wit',
count: 5,
},
],
},
{
name: 'oy',
path: 'oy',
count: 10,
},
{
name: 'ay',
path: 'ay',
count: 3,
},
],
}));

props = getProvidedProps(
{ attributes: ['ok'], showMore: true, limitMin: 0, limitMax: 2 },
{},
{ results }
);
expect(props.items).toEqual([
{
label: 'wat',
value: 'wat',
count: 20,
items: [
{
label: 'wot',
value: 'wat > wot',
count: 15,
},
{
label: 'wut',
value: 'wat > wut',
count: 3,
},
],
},
{
label: 'oy',
value: 'oy',
count: 10,
},
]);
});

it('applies limit after transforming items', () => {
const results = {
getFacetValues: jest.fn(),
getFacetByName: () => true,
hits: [],
};
results.getFacetValues.mockClear();
results.getFacetValues.mockImplementation(() => ({
data: [
{
name: 'wat',
path: 'wat',
count: 20,
data: [
{
name: 'wot',
path: 'wat > wot',
count: 15,
},
{
name: 'wut',
path: 'wat > wut',
count: 3,
},
{
name: 'wit',
path: 'wat > wit',
count: 5,
},
],
},
{
name: 'oy',
path: 'oy',
count: 10,
},
{
name: 'ay',
path: 'ay',
count: 3,
},
],
}));
props = getProvidedProps(
{ attributes: ['ok'], showMore: true, limitMin: 0, limitMax: 3 },
{},
{ results }
);
expect(props.items).toEqual([
{
label: 'wat',
value: 'wat',
count: 20,
items: [
{
label: 'wot',
value: 'wat > wot',
count: 15,
},
{
label: 'wut',
value: 'wat > wut',
count: 3,
},
{
label: 'wit',
value: 'wat > wit',
count: 5,
},
],
},
{
label: 'oy',
value: 'oy',
count: 10,
},
{
label: 'ay',
value: 'ay',
count: 3,
},
]);

function compareItem(a, b) {
if (a.label < b.label) return -1;
if (a.label > b.label) return 1;
return 0;
}
const transformItems = jest.fn(items => items.sort(compareItem));
props = getProvidedProps(
{ attributes: ['ok'], transformItems },
{},
{ results }
);
expect(transformItems.mock.calls[0][0]).toEqual([
{
label: 'ay',
value: 'ay',
count: 3,
},
{
label: 'oy',
value: 'oy',
count: 10,
},
{
label: 'wat',
value: 'wat',
count: 20,
items: [
{
label: 'wot',
value: 'wat > wot',
count: 15,
},
{
label: 'wut',
value: 'wat > wut',
count: 3,
},
{
label: 'wit',
value: 'wat > wit',
count: 5,
},
],
},
]);
props = getProvidedProps(
{
attributes: ['ok'],
transformItems,
showMore: true,
limitMin: 0,
limitMax: 2,
},
{},
{ results }
);
expect(props.items).toEqual([
{
label: 'ay',
value: 'ay',
count: 3,
},
{
label: 'oy',
value: 'oy',
count: 10,
},
]);
});

it("calling refine updates the widget's search state", () => {
const nextState = refine(
{ attributes: ['ok'] },
Expand Down

0 comments on commit fe178ed

Please sign in to comment.