UNPKG

@bigfishtv/cockpit

Version:

508 lines (443 loc) 18.5 kB
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } /** * Tree Utilities * @module Utilities/treeUtils */ import Immutable from 'immutable'; import cloneDeep from 'lodash/cloneDeep'; //// Immutable.js functions //// /** * Recursively iterates through tree looking for id * @param {Number} id * @param {Immutable.List} Branch * @param {String} [iteratorKey=children] * @return {Immutable.Map} */ export function getChildByIdImmutable(id, Branch) { var iteratorKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children'; if (typeof id !== 'number' || (typeof Branch === 'undefined' ? 'undefined' : _typeof(Branch)) !== 'object' || typeof iteratorKey !== 'string' || !Immutable.List.isList(Branch)) return false; var found = false; Branch.map(function (item) { if (!found) { if (item.get('id') === id) found = item;else if (item.get(iteratorKey)) found = getChildByIdImmutable(id, item.get(iteratorKey)); } }); return found; } /** * @deprecated This function is super-inefficient and should not be used. * * Recursively iterates through tree looking for parent of child's id * @param {Number} id * @param {Immutable.List} Branch * @param {String} [iteratorKey=children] * @return {Immutable.Map} */ export function getParentByChildIdImmutable(id, Branch) { var iteratorKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children'; if (typeof id !== 'number' || (typeof Branch === 'undefined' ? 'undefined' : _typeof(Branch)) !== 'object' || typeof iteratorKey !== 'string' || !Immutable.List.isList(Branch)) return false; var found = false; Branch.map(function (item) { if (!found) { if (item.get(iteratorKey)) item.get(iteratorKey).map(function (child) { if (!found) { if (child.get('id') === id) { found = item; } else found = getParentByChildIdImmutable(id, item.get(iteratorKey)); } }); } }); return found; } /** * Recursively iterates through tree using a checker function to determine whether or not to add a branch's key to an array of values * @param {Immutable.List} tree * @param {String} key * @param {Function} checker * @param {String} [iteratorKey=children] * @return {Array} - returns array of values */ export function collectValuesImmutable(tree, key, checker) { var iteratorKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; if ((typeof tree === 'undefined' ? 'undefined' : _typeof(tree)) !== 'object' || !Immutable.List.isList(tree) || typeof key !== 'string' || typeof checker !== 'function' || typeof iteratorKey !== 'string') return false; var values = []; tree.map(function (branch) { if (checker(branch) && branch.get(key)) values.push(branch.get(key)); if (branch.get(iteratorKey) && branch.get(iteratorKey).size > 0) values = values.concat(collectValuesImmutable(branch.get(iteratorKey), key, checker, iteratorKey)); }); return values; } /** * Prunes a tree's branches based on a key and an array of disallowed values * @param {Immutable.List} tree * @param {String} key * @param {Array} values - array of key values that determine if a branch is to be pruned * @param {String} [iteratorKey=children] * @return {Immutable.List} - returns pruned tree */ export function pruneTreeImmutable(tree, key, values) { var iteratorKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; if ((typeof tree === 'undefined' ? 'undefined' : _typeof(tree)) !== 'object' || !Immutable.List.isList(tree) || typeof iteratorKey !== 'string') return false; if (!(values instanceof Array)) values = [values]; tree = tree.filter(function (branch) { return values.indexOf(branch.get(key)) < 0; }); tree = tree.map(function (branch) { if (branch.get(iteratorKey) && branch.get(iteratorKey).size > 0) { return branch.set(iteratorKey, pruneTreeImmutable(branch.get(iteratorKey), key, values, iteratorKey)); } return branch; }); return tree; } //// Regular array/object functions //// /** * Recursively iterates through tree looking for id * @param {Number} id * @param {Object[]} Branch * @param {String} [iteratorKey=children] * @return {Object[]} */ export function getParentByChildId(id, Branch) { var iteratorKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children'; if (typeof id !== 'number' || (typeof Branch === 'undefined' ? 'undefined' : _typeof(Branch)) !== 'object' || typeof iteratorKey !== 'string' || !(Branch instanceof Array)) return false; var found = false; Branch.map(function (item) { if (!found) { if (iteratorKey in item) item[iteratorKey].map(function (child) { if (!found) { if ('id' in child && child['id'] === id) { found = item; } else { found = getParentByChildId(id, item[iteratorKey]); } } }); } }); return found; } // /** * Takes a flat array and makes it multidimensional * @param {Object[]} FlatTree - flat array to be inflated * @param {String} [idTag=id] * @param {String} [parentTag=parent_id] * @param {String} [childrenTag=children] * @param {Number} [parent_id=null] * @param {Number} [level=0] * @return {Object[]} */ export function inflate(FlatTree) { var idTag = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'id'; var parentTag = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'parent_id'; var childrenTag = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; var parent_id = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; var level = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0; if (!(FlatTree instanceof Array) || typeof idTag !== 'string' || typeof parentTag !== 'string' || typeof childrenTag !== 'string') return false; var branch = []; FlatTree.map(function (_item) { var item = cloneDeep(_item); if (idTag in item && parentTag in item && item[parentTag] === parent_id) { var children = inflate(FlatTree, idTag, parentTag, childrenTag, item[idTag], level + 1); item[childrenTag] = children && children instanceof Array ? children : []; // item.level = level; branch.push(item); } }); return branch; } /** * Takes a multidimensional array and flattens it * @param {Object[]} Tree * @param {String} [iteratorKey=children] * @param {Number} [level=0] * @return {Object[]} */ export function flatten(Tree) { var iteratorKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'children'; var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; if (!(Tree instanceof Array) || typeof iteratorKey !== 'string') return false; return Tree.reduce(function (list, branch) { var rest = {}; Object.keys(branch).map(function (key) { if (key !== iteratorKey) rest[key] = branch[key]; }); list.push(rest); if (iteratorKey in branch) { list = list.concat(flatten(branch[iteratorKey], iteratorKey, level + 1)); } return list; }, []); } /** * Takes a multidimensional array and flattens it, excluding certain ids * @param {Object[]} Tree * @param {Number[]} ignoreIds * @param {String} [iteratorKey=children] * @param {Number} [level=0] * @return {Object[]} */ export function flattenWithoutCollapsed(Tree) { var ignoreIds = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var iteratorKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'children'; var level = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0; if (!(Tree instanceof Array) || !(ignoreIds instanceof Array) || typeof iteratorKey !== 'string') return false; return Tree.reduce(function (list, branch) { var rest = {}; Object.keys(branch).map(function (key) { if (key !== iteratorKey) rest[key] = branch[key]; }); list.push(rest); if (iteratorKey in branch && ignoreIds.indexOf(branch.id) < 0) { list = list.concat(flattenWithoutCollapsed(branch[iteratorKey], ignoreIds, iteratorKey, level + 1)); } return list; }, []); } // takes a multidimensional array and flattens it /** * Takes a multidimensional array and flattens it with 'path' array * @param {Object[]} branches * @param {Array} path * @return {Object[]} */ export function flattenWithPath(branches) { var path = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var index = 0; return branches.reduce(function (list, branch) { var children = branch.children, rest = _objectWithoutProperties(branch, ['children']); var newPath = path.slice(); if (path.length) newPath.push('children'); newPath.push(index++); var item = { item: _extends({}, rest, { children: children }), path: newPath }; list.push(item); if (children && children.length) { list = list.concat(flattenWithPath(children, newPath)); } return list; }, []); } /** * @param {Object[]} branches * @param {Number} [parent_id=null] * @return {Object[]} */ export function flattenWithParentIds(branches) { var parent_id = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; return branches.reduce(function (list, branch) { var children = branch.children, rest = _objectWithoutProperties(branch, ['children']); var item = _extends({}, rest, { parent_id: parent_id }); list.push(item); if (children && children.length) { list = list.concat(flattenWithParentIds(children, item.id)); } return list; }, []); } /** * Prunes a tree's branches based on a key and an array of disallowed values * @param {Object[]} _tree * @param {String} key * @param {String[]} values * @param {String} [iteratorKey=children] * @return {Object[]} */ export function pruneTree(_tree, key, values) { var iteratorKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; if (!(_tree instanceof Array) || typeof key !== 'string' || typeof iteratorKey !== 'string') return false; if (!(values instanceof Array)) values = [values]; var tree = cloneDeep(_tree); tree = tree.filter(function (branch) { return values.indexOf(branch[key]) < 0; }); tree = tree.map(function (branch) { if (iteratorKey in branch && branch[iteratorKey] instanceof Array) branch[iteratorKey] = pruneTree(branch[iteratorKey], key, values, iteratorKey); return branch; }); return tree; } /** * Recursively iterates through tree using a checker function to determine whether or not to add a branch's key to an array of values * @param {Object[]} tree * @param {String} key * @param {Function} checker * @param {String} [iteratorKey=children] * @return {Array} - returns array of values */ export function collectValues(tree, key, checker) { var iteratorKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; if (!(tree instanceof Array) || typeof key !== 'string' || typeof checker !== 'function' || typeof iteratorKey !== 'string') return false; var values = []; tree.map(function (branch) { if (checker(branch) && key in branch) values.push(branch[key]); if (iteratorKey in branch && branch[iteratorKey] instanceof Array) values = values.concat(collectValues(branch[iteratorKey], key, checker, iteratorKey)); }); return values; } /** * Recursively iterates through tree to get a child by a key and a value * @param {Object[]} tree * @param {String} key * @param {*} value - Can be anything * @param {String} [iteratorKey=children] * @return {Object} */ export function getChildByKeyValue(tree, key, value) { var iteratorKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; if (!(tree instanceof Array) || typeof key !== 'string' || typeof iteratorKey !== 'string') return false; var found = false; tree.map(function (item) { if (!found) { if (item[key] === value) found = item;else if (item[iteratorKey]) found = getChildByKeyValue(item[iteratorKey], key, value, iteratorKey); } }); return found; } /** * Recursively iterates through tree and get all values of a set key * @param {Object[]} _tree * @param {Number} id * @param {String} key * @param {String} [iteratorKey=children] * @return {String[]} */ export function collectChildrenKeyValues(_tree, id, key) { var iteratorKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; if (!(_tree instanceof Array) || typeof key !== 'string' || typeof id !== 'number' || typeof iteratorKey !== 'string') return false; var branch = getChildByKeyValue(_tree, 'id', id, iteratorKey); if (!branch[iteratorKey]) return []; return collectValues(branch[iteratorKey], key, function (item) { return true; }, iteratorKey); } /** * Recursively iterates through tree looking for a child and sets a value by key, returns new tree * @param {Object[]} _tree * @param {Number} id * @param {String} setKey * @param {*} setValue - Can be anything * @param {Object[]} */ export function setKeyValueById(_tree, id, setKey, setValue) { var iteratorKey = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'children'; var tree = cloneDeep(_tree); return tree.map(function (item) { if (item.id === id) item[setKey] = setValue; if (item[iteratorKey]) item[iteratorKey] = setKeyValueById(item[iteratorKey], id, setKey, setValue, iteratorKey); return item; }); } /** * Recursively iterates through tree and sorts all branches by key, returns new tree * @param {Object[]} _tree * @param {String} key * @param {Boolean} desc - Descending * @param {String} [iteratorKey=children] * @return {Object[]} */ export function sortByKey(_tree, key) { var desc = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var iteratorKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; var tree = _tree.slice(); tree.sort(function (a, b) { if (typeof a[key] == 'string') { return a[key].localeCompare(b[key], undefined, { sensitivity: 'base' }); } else { return a[key] - b[key]; } }); if (desc) tree.reverse(); return tree.map(function (item) { var _extends2; if (!item[iteratorKey]) { return item; } return _extends({}, item, (_extends2 = {}, _extends2[iteratorKey] = sortByKey(item[iteratorKey], key, desc, iteratorKey), _extends2)); }); } /** * Recursively iterates through tree and appends child to parent by parentId, returns new tree * @param {Object[]} _tree * @param {Number} parentId * @param {Object} child * @param {Number} [currentParentId=null] * @param {String} [iteratorKey=children] * @return {Object[]} */ export function appendChildToParent(_tree, parentId, child) { var currentParentId = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; var iteratorKey = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'children'; if (!(_tree instanceof Array) || typeof iteratorKey !== 'string') return false; var tree = cloneDeep(_tree); if (parentId === currentParentId) tree.push(child);else tree = tree.map(function (item) { if (parentId === item.id && !item[iteratorKey]) item[iteratorKey] = []; if (item[iteratorKey]) item[iteratorKey] = appendChildToParent(item[iteratorKey], parentId, child, item.id, iteratorKey); return item; }); return tree; } /** * Recursively iterates through tree looking to replace a specific child by given key (children are preserved), returns new tree * @param {Object[]} _tree * @param {Object} child * @param {String} [key=id] * @param {String} [iteratorKey=children] * @return {Object[]} */ export function replaceChild(_tree, child) { var key = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'id'; var iteratorKey = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'children'; if (!(_tree instanceof Array) || typeof iteratorKey !== 'string') return false; var tree = cloneDeep(_tree); return tree.map(function (item) { if (item[key] === child[key]) { var _extends3; if (item[iteratorKey] && item[iteratorKey].length) return _extends({}, child, (_extends3 = {}, _extends3[iteratorKey] = item[iteratorKey], _extends3));else return child; } if (item[iteratorKey]) item[iteratorKey] = replaceChild(item[iteratorKey], child, key, iteratorKey); return item; }); } /** * Recursively iterates through tree and concats branch chilren where supplied values match branch value * @param {Object[]} _tree * @param {Object[]} values * @param {String} valueKey * @param {String} key * @param {String} iteratorKey * @return {Object[]} */ export function mergeChildren(_tree, values) { var valueKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'folder_id'; var key = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 'id'; var iteratorKey = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'children'; if (!(_tree instanceof Array) || !(values instanceof Array)) return false; var tree = cloneDeep(_tree); var orphanedValues = values.filter(function (value) { return value[valueKey] === null; }); if (orphanedValues.length > 0) tree = [].concat(tree, orphanedValues.map(function (value) { return _extends({}, value, { __injected: true }); })); return tree.map(function (item) { if (item.__injected) return item; var injectValues = values.filter(function (value) { return value[valueKey] == item[key]; }); if (item[iteratorKey] && item[iteratorKey].length > 0) { item[iteratorKey] = [].concat(mergeChildren(item[iteratorKey], values, valueKey, key, iteratorKey), injectValues); } else { item[iteratorKey] = injectValues; } return item; }); }