filter groups
This commit is contained in:
		
							
								
								
									
										2
									
								
								Jenkinsfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								Jenkinsfile
									
									
									
									
										vendored
									
									
								
							@@ -5,7 +5,7 @@ pipeline {
 | 
				
			|||||||
        VERSION = VersionNumber([
 | 
					        VERSION = VersionNumber([
 | 
				
			||||||
            versionNumberString:
 | 
					            versionNumberString:
 | 
				
			||||||
                '${BUILDS_ALL_TIME}',
 | 
					                '${BUILDS_ALL_TIME}',
 | 
				
			||||||
            versionPrefix: '1.5.',
 | 
					            versionPrefix: '1.6.',
 | 
				
			||||||
            worstResultForIncrement: 'SUCCESS'
 | 
					            worstResultForIncrement: 'SUCCESS'
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								README.md
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
# @sapphirecode/utilities
 | 
					# @sapphirecode/utilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
version: 1.5.x
 | 
					version: 1.6.x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
small utility functions to make much needed features easier to work with
 | 
					small utility functions to make much needed features easier to work with
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -118,13 +118,34 @@ const result = util.recursive_filter(
 | 
				
			|||||||
  [
 | 
					  [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      filter: /foo bar/iu,
 | 
					      filter: /foo bar/iu,
 | 
				
			||||||
      fields: ['name', 'name_2'] // fields will be joined with a space in between
 | 
					      field: ['name', 'name_2'] // fields will be joined with a space in between
 | 
				
			||||||
      // {name: 'foo', name_2: 'bar'} will become 'foo bar'
 | 
					      // {name: 'foo', name_2: 'bar'} will become 'foo bar'
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					filter groups can be used to connect filters with OR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```js
 | 
				
			||||||
 | 
					const result = util.recursive_filter(
 | 
				
			||||||
 | 
					  [...],
 | 
				
			||||||
 | 
					  [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      filter: /foo bar/iu,
 | 
				
			||||||
 | 
					      field: 'name'
 | 
				
			||||||
 | 
					    }, 
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      or: [
 | 
				
			||||||
 | 
					        { filter: /foo/u, field: 'bar' },
 | 
				
			||||||
 | 
					        { filter: /bar/u, field: 'bar' }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## License
 | 
					## License
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MIT © Timo Hocker <timo@scode.ovh>
 | 
					MIT © Timo Hocker <timo@scode.ovh>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										47
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								index.js
									
									
									
									
									
								
							@@ -78,19 +78,45 @@ function is_nil (obj) {
 | 
				
			|||||||
      || (typeof obj === 'number' && isNaN (obj));
 | 
					      || (typeof obj === 'number' && isNaN (obj));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function to_search_string (element, field) {
 | 
					function check_filter (filter, e) {
 | 
				
			||||||
  return Array.isArray (field)
 | 
					  const search_str = Array.isArray (filter.field)
 | 
				
			||||||
    ? field.map ((f) => element[f])
 | 
					    ? filter.field.map ((f) => e[f])
 | 
				
			||||||
      .filter ((v) => typeof v !== 'undefined')
 | 
					      .filter ((v) => typeof v !== 'undefined')
 | 
				
			||||||
      .join (' ')
 | 
					      .join (' ')
 | 
				
			||||||
    : element[field];
 | 
					    : e[filter.field];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return filter.filter.test (search_str);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function check_filters (filters, e, or = false) {
 | 
				
			||||||
 | 
					  for (const filter of filters) {
 | 
				
			||||||
 | 
					    let res = false;
 | 
				
			||||||
 | 
					    if (Array.isArray (filter.or))
 | 
				
			||||||
 | 
					      res = check_filters (filter.or, e, true);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      res = check_filter (filter, e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (or && res)
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    if (!res && !or)
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return !or;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @typedef Filter
 | 
				
			||||||
 | 
					 * @type {object}
 | 
				
			||||||
 | 
					 * @property {string|string[]} field - fields to apply filter on
 | 
				
			||||||
 | 
					 * @property {RegExp} filter - filter
 | 
				
			||||||
 | 
					 * @property {Filter[]} or - create an OR group of filters
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * filter nested objects
 | 
					 * filter nested objects
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @param {Array<object>} input
 | 
					 * @param {Array<object>} input
 | 
				
			||||||
 * @param {Array<{field: string, filter: RegExp}>} filters
 | 
					 * @param {Filter[]} filters
 | 
				
			||||||
 * @returns {Array<object>} filtered data
 | 
					 * @returns {Array<object>} filtered data
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function recursive_filter (input, filters, children_key = 'children') {
 | 
					function recursive_filter (input, filters, children_key = 'children') {
 | 
				
			||||||
@@ -99,16 +125,7 @@ function recursive_filter (input, filters, children_key = 'children') {
 | 
				
			|||||||
  for (let i = 0; i < data.length; i++) {
 | 
					  for (let i = 0; i < data.length; i++) {
 | 
				
			||||||
    const e = { ...data[i] };
 | 
					    const e = { ...data[i] };
 | 
				
			||||||
    data[i] = e;
 | 
					    data[i] = e;
 | 
				
			||||||
    let match = true;
 | 
					    if (check_filters (filters, e)) {
 | 
				
			||||||
    for (const filter of filters) {
 | 
					 | 
				
			||||||
      const search_str = to_search_string (e, filter.field);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      if (!filter.filter.test (search_str)) {
 | 
					 | 
				
			||||||
        match = false;
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (match) {
 | 
					 | 
				
			||||||
      filtered.push (e);
 | 
					      filtered.push (e);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -204,3 +204,24 @@ test ('recursive filter undefined multifield', (t) => {
 | 
				
			|||||||
  );
 | 
					  );
 | 
				
			||||||
  t.deepEqual (res, []);
 | 
					  t.deepEqual (res, []);
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test ('recursive filter with or group', (t) => {
 | 
				
			||||||
 | 
					  const to_filter = [
 | 
				
			||||||
 | 
					    { name: 'foo' },
 | 
				
			||||||
 | 
					    { name: 'bar' },
 | 
				
			||||||
 | 
					    { name: 'baz' }
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const filter = [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      or: [
 | 
				
			||||||
 | 
					        { field: 'name', filter: /foo/u },
 | 
				
			||||||
 | 
					        { field: 'name', filter: /bar/u }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const res = util.recursive_filter (to_filter, filter);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  t.deepEqual (res, to_filter.slice (0, 2));
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user