Skip to content

Commit

Permalink
feat: add support for empty multiple fields
Browse files Browse the repository at this point in the history
  • Loading branch information
targos committed Jun 26, 2018
1 parent 75ecf57 commit 604d24b
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 14 deletions.
21 changes: 12 additions & 9 deletions src/__tests__/filterData.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,42 @@
import { Map } from 'immutable';

import filterData from '../filterData';
import { MULTIPLE_EMPTY } from '../constants/sentinels';

const data = [
{ A: ['Y'], B: 'Y', C: 1, D: { X: 'X' } },
{ A: ['Z'], B: 'Z', C: 3 },
{ A: ['Z', 'Y'], B: 'X', C: 2, D: { Y: 'Y' } },
{ A: ['X'], B: 'Y', C: -1, D: { X: 'OTHER' } },
{ B: true }
{ A: [], B: true },
{}
];
data.forEach((d, idx) => (d.idx = idx));

describe('Test filter', () => {
it('multiple', () => {
const filters = [
{ prop: 'A', value: [], expected: [0, 1, 2, 3, 4] },
{ prop: 'A', value: [], expected: [0, 1, 2, 3, 4, 5] },
{ prop: 'A', value: ['Y'], expected: [0, 2] },
{ prop: 'A', value: ['Y'], negated: true, expected: [1, 3, 4] },
{ prop: 'A', value: ['Y'], negated: true, expected: [1, 3, 4, 5] },
{ prop: 'A', value: ['Y', 'Z'], expected: [2] },
{ prop: 'A', value: ['Y', 'Z'], operator: 'OR', expected: [0, 1, 2] },
{
prop: 'A',
value: ['Y', 'Z'],
operator: 'AND',
negated: true,
expected: [3, 4]
expected: [3, 4, 5]
},
{
prop: 'A',
value: ['Z', 'Y'],
operator: 'OR',
negated: true,
expected: [0, 1, 3, 4]
expected: [0, 1, 3, 4, 5]
},
{ prop: 'A', value: ['W'], expected: [] }
{ prop: 'A', value: ['W'], expected: [] },
{ prop: 'A', value: [MULTIPLE_EMPTY], expected: [4] }
];
for (let filter of filters) {
const f = Map({
Expand All @@ -50,7 +53,7 @@ describe('Test filter', () => {
const filters = [
{ prop: 'B', value: ['Y'], expected: [0, 3] },
{ prop: 'B', value: ['W'], expected: [] },
{ prop: 'B', value: ['Y'], negated: true, expected: [1, 2, 4] },
{ prop: 'B', value: ['Y'], negated: true, expected: [1, 2, 4, 5] },
{ prop: 'B', value: ['X', 'Y'], operator: 'AND', expected: [] },
{ prop: 'B', value: ['X', 'Y'], operator: 'OR', expected: [0, 2, 3] },
{ prop: 'B', value: ['X'], expected: [2] },
Expand All @@ -59,14 +62,14 @@ describe('Test filter', () => {
value: ['X', 'Y'],
operator: 'AND',
negated: true,
expected: [1, 4]
expected: [1, 4, 5]
},
{
prop: 'B',
value: ['X', 'Y'],
operator: 'OR',
negated: true,
expected: [0, 1, 2, 3, 4]
expected: [0, 1, 2, 3, 4, 5]
},
{
prop: 'B',
Expand Down
1 change: 1 addition & 0 deletions src/constants/sentinels.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const MULTIPLE_EMPTY = 'MULTIPLE_EMPTY';
17 changes: 12 additions & 5 deletions src/filterData.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import lodashProperty from 'lodash-es/property';

import { AND, OR } from './constants/operators';
import { MULTIPLE_EMPTY } from './constants/sentinels';

export default function filterData(data, filters) {
filters = Array.from(filters);
Expand All @@ -21,20 +22,26 @@ export default function filterData(data, filters) {
// kind: multiple
operator = operator || AND;
if (operator === AND) {
for (const val of filterValue) {
if (!itemValue.includes(val)) {
if (!negated) {
for (const value of filterValue) {
if (
itemValue.includes(value) ||
(value === MULTIPLE_EMPTY && itemValue.length === 0)
) {
if (negated) {
return false;
}
} else {
if (negated) {
if (!negated) {
return false;
}
}
}
} else {
for (const value of filterValue) {
if (itemValue.includes(value)) {
if (
itemValue.includes(value) ||
(value === MULTIPLE_EMPTY && itemValue.length === 0)
) {
if (!negated) {
continue main;
}
Expand Down
8 changes: 8 additions & 0 deletions src/filterOneSelector.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import max from 'ml-array-max';

import filterData from './filterData';
import * as kinds from './constants/kinds';
import { MULTIPLE_EMPTY } from './constants/sentinels';

export default function filterOneSelector(data, name, propFunc, kind, filters) {
switch (kind) {
Expand Down Expand Up @@ -77,6 +78,13 @@ function countMultiple(data, propFunc) {
if (!value || !value[Symbol.iterator]) {
continue;
}
if (value.length === 0) {
if (!counts.has(MULTIPLE_EMPTY)) {
counts.set(MULTIPLE_EMPTY, 1);
} else {
counts.set(MULTIPLE_EMPTY, counts.get(MULTIPLE_EMPTY) + 1);
}
}
for (const el of value) {
if (!counts.has(el)) {
counts.set(el, 1);
Expand Down
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ export const setNegated = actions.setNegated;

// selectors
export { default as getFilteredData } from './getFilteredData';

// sentinels
export { MULTIPLE_EMPTY } from './constants/sentinels';

0 comments on commit 604d24b

Please sign in to comment.