Splitting out helpers into separate files

This commit is contained in:
James Barnsley
2020-03-03 16:39:37 +13:00
parent 57dd18e870
commit 5a1f08fdf0
105 changed files with 5456 additions and 5574 deletions

254
src/js/util/arrays.js Normal file
View File

@ -0,0 +1,254 @@
/**
* Digest an array of objects and pull into simple array of one property
*
* @param property = string
* @param items = Array
* @return Array
* */
const arrayOf = function (property, items) {
const array = [];
for (const item of items) {
// Make sure the property is defined
if (item[property] !== undefined && item[property] != null) {
array.push(item[property]);
}
}
return array;
};
/**
* Merge duplicated items in an array
*
* @param list Array the unclean array
* @param key string = the unique key (id, uri, tlid, etc)
* */
const mergeDuplicates = function (list, key) {
const clean_list = [];
const keyed_list = {};
for (var i in list) {
let item = list[i];
if (item[key] in keyed_list) {
item = { ...keyed_list[item[key]], ...item };
}
keyed_list[item[key]] = item;
}
for (i in keyed_list) {
clean_list.push(keyed_list[i]);
}
return clean_list;
};
/**
* Remove duplicate items in a simple array
*
* @param list Array the unclean array
* */
const removeDuplicates = function (array) {
const unique = [];
for (const i in array) {
if (unique.indexOf(array[i]) <= -1) {
unique.push(array[i]);
}
}
return unique;
};
/**
* Apply a partial text search on an array of objects
*
* @param field = string (the field we're to search)
* @param value = string (the value to find)
* @param array = array of objects to search
* @param singular = boolean (just return the first result)
* @return array
* */
const applyFilter = function (field, value, array, singular = false) {
const results = [];
for (let i = 0; i < array.length; i++) {
if (array[i][field] && String(array[i][field]).toLowerCase().includes(String(value).toLowerCase())) {
if (singular) {
return array[i];
}
results.push(array[i]);
}
}
return results;
};
/**
* Convert a list of indexes to a useable range
* We ignore stragglers, and only attend to the first 'bunch' of consecutive indexes
*
* @param indexes array of int
* */
const createRange = function (indexes) {
// sort our indexes smallest to largest
function sortAsc(a, b) {
return a - b;
}
indexes.sort(sortAsc);
// iterate indexes to build the first 'bunch'
const first_bunch = [];
let previous_index = false;
for (let i = 0; i < indexes.length; i++) {
if (!previous_index || previous_index == indexes[i] - 1) {
first_bunch.push(indexes[i]);
previous_index = indexes[i];
}
// TODO: break when we find an integer step for better performance
}
return {
start: first_bunch[0],
length: first_bunch.length,
};
};
/**
* Sort an array of objects
* @param array = array to sort
* @param property = string to sort by
* @param reverse = boolean
* @param sort_map = array of value ordering (rather than alphabetical, numerical, etc)
* @return array
* */
const sortItems = function (array, property, reverse = false, sort_map = null) {
if (!array || array.length <= 0) {
return [];
}
function get_value(value) {
const split = property.split('.');
for (const property_element of split) {
// Apply sort on a property of the first item of an array
if (property_element == 'first') {
if (Array.isArray(value) && value.length > 0) {
value = value[0];
continue;
} else {
return null;
}
// Just need the length of an array
} else if (property_element == 'length') {
if (Array.isArray(value)) {
return value.length;
}
return 0;
// No value here
} else if (typeof (value[property_element]) === 'undefined') {
return null;
}
// Otherwise continue looping to the end of the split property
value = value[property_element];
}
return value;
}
function compare(a, b) {
let a_value = get_value(a);
let b_value = get_value(b);
// Sorting by URI as a reference for sorting by uri source (first component of URI)
if (property == 'uri') {
a_value = uriSource(a_value);
b_value = uriSource(b_value);
}
// Map sorting
// Use the index of the string as a sorting mechanism
if (sort_map) {
const a_index = sort_map.indexOf(`${a_value}:`);
const b_index = sort_map.indexOf(`${b_value}:`);
if (a_index < b_index) return 1;
if (a_index > b_index) return -1;
// Boolean sorting
} else if (typeof a_value === 'boolean' && typeof b_value === 'boolean') {
if (a_value && !b_value) return -1;
if (!a_value && b_value) return 1;
return 0;
// Numeric sorting
} else if (typeof a_value === 'number' && typeof b_value === 'number') {
if (a_value == null && b_value == null) return 0;
if (a_value == null) return -1;
if (b_value == null) return 1;
if (parseInt(a_value) > parseInt(b_value)) return 1;
if (parseInt(a_value) < parseInt(b_value)) return -1;
return 0;
// Alphabetic sorting
} else {
if (a_value && !b_value) return -1;
if (!a_value && b_value) return 1;
if (!a_value && !b_value) return 0;
if (a_value.toLowerCase() > b_value.toLowerCase()) return 1;
if (a_value.toLowerCase() < b_value.toLowerCase()) return -1;
return 0;
}
}
const sorted = Object.assign([], array.sort(compare));
if (reverse) {
sorted.reverse();
}
return sorted;
};
/**
* Shuffle items in place
*
* @param Array items
* @return Array
* */
const shuffle = function (array) {
let j; let x; let
i;
for (i = array.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
x = array[i];
array[i] = array[j];
array[j] = x;
}
return array;
};
export {
arrayOf,
mergeDuplicates,
removeDuplicates,
applyFilter,
createRange,
sortItems,
shuffle,
};
export default {
arrayOf,
mergeDuplicates,
removeDuplicates,
applyFilter,
createRange,
sortItems,
shuffle,
};