UNPKG

@mikezimm/npmfunctions

Version:
400 lines (326 loc) 19.8 kB
/*** * .d8b. d8888b. d8888b. .d8b. db db .d8888. * d8' `8b 88 `8D 88 `8D d8' `8b `8b d8' 88' YP * 88ooo88 88oobY' 88oobY' 88ooo88 `8bd8' `8bo. * 88~~~88 88`8b 88`8b 88~~~88 88 `Y8b. * 88 88 88 `88. 88 `88. 88 88 88 db 8D * YP YP 88 YD 88 YD YP YP YP `8888Y' * * //Checks import { doesObjectExistInArrayInt, doesObjectExistInArray, compareArrays, getMaxPropOfKeyInObjectArray, getNextElementInArray getKeySummary, getKeyChanges } from '@mikezimm/npmfunctions/dist/Services/Arrays/checks'; */ /** * export interface ICompareResult * export interface * export interface * * export function doesObjectExistInArrayInt * export function doesObjectExistInArray * export function compareArrays * export function getMaxPropOfKeyInObjectArray * export function getNextElementInArray * * export function getKeySummary * export function getKeyChanges */ import { stringifyKeyValue } from './services'; import { getHelpfullErrorV2 } from '../Logging/ErrorHandler'; /*** * d888888b d8b db d8888b. d88888b db db .d88b. d88888b .d8b. d8b db db db .o88b. .d8b. .d8888. d88888b * `88' 888o 88 88 `8D 88' `8b d8' .8P Y8. 88' d8' `8b 888o 88 `8b d8' d8P Y8 d8' `8b 88' YP 88' * 88 88V8o 88 88 88 88ooooo `8bd8' 88 88 88ooo 88ooo88 88V8o 88 `8bd8' 8P 88ooo88 `8bo. 88ooooo * 88 88 V8o88 88 88 88~~~~~ .dPYb. 88 88 88~~~ 88~~~88 88 V8o88 88 8b 88~~~88 `Y8b. 88~~~~~ * .88. 88 V888 88 .8D 88. .8P Y8. `8b d8' 88 88 88 88 V888 88 Y8b d8 88 88 db 8D 88. * Y888888P VP V8P Y8888D' Y88888P YP YP `Y88P' YP YP YP VP V8P YP `Y88P' YP YP `8888Y' Y88888P * * */ /** * Based on: https://bobbyhadz.com/blog/javascript-array-contains-string-case-insensitive * Any non-string checks will be considered 'not a match' * @param checkMe * @param inArray */ export function indexOfAnyCase( checkMe: string, inArray: string[], consoleLog: boolean, alertMe: boolean ) { let result = -1; //result = inArray.findIndex( element => { //NOTE: findIndex does not work in my code (typescript error) inArray.map( ( element: string, index ) => { try { if ( element.toLowerCase() === checkMe.toLowerCase() ) { result = index; } }catch(e){ //Sending false, false to getHelpfullErrorV2 because I'm handling that here let errMessage: string = getHelpfullErrorV2( e, alertMe, consoleLog, 'indexOfAnyCase ~ 65' ); } }); return result; } /*** * d8888b. .d88b. d88888b .d8888. .d88b. d8888b. d88b d88888b .o88b. d888888b d88888b db db d888888b .d8888. d888888b d888888b d8b db .d8b. d8888b. d8888b. .d8b. db db * 88 `8D .8P Y8. 88' 88' YP .8P Y8. 88 `8D `8P' 88' d8P Y8 `~~88~~' 88' `8b d8' `88' 88' YP `~~88~~' `88' 888o 88 d8' `8b 88 `8D 88 `8D d8' `8b `8b d8' * 88 88 88 88 88ooooo `8bo. 88 88 88oooY' 88 88ooooo 8P 88 88ooooo `8bd8' 88 `8bo. 88 88 88V8o 88 88ooo88 88oobY' 88oobY' 88ooo88 `8bd8' * 88 88 88 88 88~~~~~ `Y8b. 88 88 88~~~b. 88 88~~~~~ 8b 88 88~~~~~ .dPYb. 88 `Y8b. 88 88 88 V8o88 88~~~88 88`8b 88`8b 88~~~88 88 * 88 .8D `8b d8' 88. db 8D `8b d8' 88 8D db. 88 88. Y8b d8 88 88. .8P Y8. .88. db 8D 88 .88. 88 V888 88 88 88 `88. 88 `88. 88 88 88 * Y8888D' `Y88P' Y88888P `8888Y' `Y88P' Y8888P' Y8888P Y88888P `Y88P' YP Y88888P YP YP Y888888P `8888Y' YP Y888888P VP V8P YP YP 88 YD 88 YD YP YP YP * * */ /** * This function checks to see if an element of an array (object) contains a specific property/value pair. * * example call: if ( doesObjectExistInArray(currentFields, 'StaticName', checkField ) ) { * This takes an array of field objects (currentFields), and looks to see if any of the objects has a key of StaticName which has a value of checkField variable. * * @param sourceArray * @param objectProperty * @param propValue */ export function doesObjectExistInArrayInt(sourceArray: any[], objectProperty : string, propValue : any, exact : boolean = true ){ let result = doesObjectExistInArray(sourceArray, objectProperty, propValue, exact ); if ( result === false ) { return -1 } else { return parseInt( result ) ; } } export function doesObjectExistInArray(sourceArray: any[], objectProperty : string, propValue : any, exact : boolean = true ){ let result : boolean | string = false; for (let i in sourceArray){ let test = false; if ( exact === true ) { //2020-10-07: Added this to allow for Id string to number checks test = sourceArray[i][objectProperty] === propValue ? true : false; } else { test = sourceArray[i][objectProperty] == propValue ? true : false; } if ( test ) { result = i; break; } } return result; } export interface ICompareResult { checkForTheseItems: any []; inThisArray: any []; found: any []; notFound: any []; result: any []; message: string; } /*** * .o88b. .d88b. .88b d88. d8888b. .d8b. d8888b. d88888b .d8b. d8888b. d8888b. .d8b. db db .d8888. * d8P Y8 .8P Y8. 88'YbdP`88 88 `8D d8' `8b 88 `8D 88' d8' `8b 88 `8D 88 `8D d8' `8b `8b d8' 88' YP * 8P 88 88 88 88 88 88oodD' 88ooo88 88oobY' 88ooooo 88ooo88 88oobY' 88oobY' 88ooo88 `8bd8' `8bo. * 8b 88 88 88 88 88 88~~~ 88~~~88 88`8b 88~~~~~ 88~~~88 88`8b 88`8b 88~~~88 88 `Y8b. * Y8b d8 `8b d8' 88 88 88 88 88 88 88 `88. 88. 88 88 88 `88. 88 `88. 88 88 88 db 8D * `Y88P' `Y88P' YP YP YP 88 YP YP 88 YD Y88888P YP YP 88 YD 88 YD YP YP YP `8888Y' * * * The original goal of this function, would be to remove objects from one array if it were in another array. * As an example, I have an array of items I want to add to a list (addItemsArray) * Then I run a process which creates another 'result' array of what things were actually added - minus any errors * The function will remove the items in the 'result' array from the 'addItemsArray. * Only the items that were not added (ie the ones that errored out) will be left... or maybe it would add a key with the result. * * * @param checkForTheseItems - this is the array of items you want to check for in the sourceArray ('inThisArray') * @param inThisArray - this is the array where you are looking for items in * @param method - this tells what to do... either flage items in 'inThisArray' with found/not found, or remove the found ones * @param keyToCheck - checkForTheseItems must have a key which has this syntax: checkValue: "Title===Training" * keyToCheck would === 'checkValue' and the value for that key must have the syntax: PropertyKey===ValueOfProperty; * In the example above, it will split Title===Training into ['Title','Training'] * Then look for all items in 'inThisArray' which have the value 'Training' in the key 'Title', and apply the method you want to apply. */ export function compareArrays(checkForTheseItems: any [], inThisArray: any [], method: 'AddTag' | 'ReturnNOTFound' | 'ReturnFound', keyToCheck: string, checkDelimiter : string, messsages: 'Console'|'Alert'|'Both'|'None' ) { let compareKey : any = 'compareArrays'; let foundTag: any = 'Found'; let notFoundTag = 'Not' + foundTag; let result : ICompareResult = { checkForTheseItems: checkForTheseItems, inThisArray: inThisArray, found: [], notFound: [], result: [], message: '', }; let foundCount = 0; let notFoundCount = 0; let notFoundItems = ''; //Loop through all the objects you want to check for for (let c in checkForTheseItems){ let foundThisCheck : boolean = false; //Expecting syntax "Title===Email triage" let splitStr : string = checkForTheseItems[c][keyToCheck]; if ( splitStr ) { //Only check if this has a value for keyToCheck let splitArr: string[] = splitStr.split(checkDelimiter); let testKey: string = splitArr[0]; let testVal: string = splitArr[1]; if ( splitArr.length !== 2 ) { //There was a problem with the test value... needs to be syntax like this: "Title===Email triage" notFoundItems += '\n???: ' +splitStr; } else { //Loop through all the objects in the 'inThisArray' and process them for (let i in inThisArray){ let objectToUpdate: any = inThisArray[i]; if ( inThisArray[i][testKey] === testVal ) { //Value was found.... do whatever needs to be done. objectToUpdate[compareKey] = foundTag; /* if ( method === 'AddTag') { //Add item to result and then add keyTag to it objectToUpdate[compareKey] = foundTag; } else if ( method === 'ReturnNOTFound') { //Do not add this one to the result array } else if ( method === 'ReturnFound') { //Not sure about this loop yet } */ foundThisCheck = true; break; } } } } if ( foundThisCheck === false ) { notFoundItems += '\nNotFound: ' +splitStr; checkForTheseItems[c][compareKey] = notFoundTag; } } /** this is where we need to do some other things for other options * */ for (let i in inThisArray){ let objectToUpdate: any = inThisArray[i]; //Value was found.... do whatever needs to be done. if ( objectToUpdate[compareKey] ) { objectToUpdate[compareKey] = 'Found'; result.found.push(objectToUpdate); foundCount ++; } else { objectToUpdate[compareKey] = 'NOTFound'; result.notFound.push(objectToUpdate); notFoundCount ++; } } result.message = result.notFound.map( thisOne => { return 'NF: ' + stringifyKeyValue(thisOne, 0, '===') + '\n'; }).join(''); if (method === 'ReturnFound') { result.result = result.found; } else if (method === 'ReturnNOTFound') { result.result = result.notFound; } else if ( method === 'AddTag' ) { result.result = result.inThisArray; } if ( messsages !== 'None' ) { console.log('compareArrays - result: ' + method ,result); } if ( messsages === 'Alert' || messsages === 'Both') { //alert('compareArrays - completed! Check Console for results'); let alertMessage = `Found (${foundCount}) matches in both arrays`; if (notFoundCount > 0 ) { alertMessage += '\nCheck Console.log for details'; alertMessage += `\nDid NOT find these (${notFoundCount}) items!`; alertMessage += '\n' + result.message; } alert( alertMessage ); } return result; } /*** * d888b d88888b d888888b db dD d88888b db db .d8888. db db .88b d88. .88b d88. .d8b. d8888b. db db * 88' Y8b 88' `~~88~~' 88 ,8P' 88' `8b d8' 88' YP 88 88 88'YbdP`88 88'YbdP`88 d8' `8b 88 `8D `8b d8' * 88 88ooooo 88 88,8P 88ooooo `8bd8' `8bo. 88 88 88 88 88 88 88 88 88ooo88 88oobY' `8bd8' * 88 ooo 88~~~~~ 88 88`8b 88~~~~~ 88 `Y8b. 88 88 88 88 88 88 88 88 88~~~88 88`8b 88 * 88. ~8~ 88. 88 88 `88. 88. 88 db 8D 88b d88 88 88 88 88 88 88 88 88 88 `88. 88 * Y888P Y88888P YP YP YD Y88888P YP `8888Y' ~Y8888P' YP YP YP YP YP YP YP YP 88 YD YP * * * * Copied from FoamControl.tsx * @param thisDataObjec * @param compareTypes Tested values = ['string','number','boolean']; * @param ignoreKeys Tested values = ['element']; * @returns */ export function getKeySummary( baselineObject: any, compareTypes : string[], ignoreKeys : string[], parseMe: boolean ) { let keySummary: any = {}; Object.keys( baselineObject ).map( key => { let keyType = typeof baselineObject[key]; if ( compareTypes.indexOf( keyType ) > -1 && ignoreKeys.indexOf( key ) < 0 ) { keySummary[key] = baselineObject[key]; } }); if ( parseMe !== false ) { keySummary = JSON.parse( JSON.stringify( keySummary ) ) ; } return keySummary; } export const BaseFieldKeys = ['Title','StaticName','TypeAsString','FieldTypeKind','TypeDisplayName','Formula','InternalName','Required','Sealed','CanBeDeleted']; export const BaseViewKeys = ['Title','Id']; export const BaseTypeKeys = ['Title','Id']; export const DoesNotExistLabel = '- >> Does NOT Exist << -'; export const KeyChangeDelimiter = ' >>> '; /*** * d888b d88888b d888888b db dD d88888b db db .o88b. db db .d8b. d8b db d888b d88888b .d8888. * 88' Y8b 88' `~~88~~' 88 ,8P' 88' `8b d8' d8P Y8 88 88 d8' `8b 888o 88 88' Y8b 88' 88' YP * 88 88ooooo 88 88,8P 88ooooo `8bd8' 8P 88ooo88 88ooo88 88V8o 88 88 88ooooo `8bo. * 88 ooo 88~~~~~ 88 88`8b 88~~~~~ 88 8b 88~~~88 88~~~88 88 V8o88 88 ooo 88~~~~~ `Y8b. * 88. ~8~ 88. 88 88 `88. 88. 88 Y8b d8 88 88 88 88 88 V888 88. ~8~ 88. db 8D * Y888P Y88888P YP YP YD Y88888P YP `Y88P' YP YP YP YP VP V8P Y888P Y88888P `8888Y' * * */ /** * getKeyChanges function compares two objects which are similar... and returns the differences. * An example would be versions of a list item. * the keyChanges would compare both arrays to each other and only return the keys which have values that are not equal * This is more for converting changes into single label per key notation that is more easily readable * * baselineObject = { a: 1, b: 2} compareObject = { a: 1, b: 3} => result would be newObject = { b: '2 >>> 3' } * * * POSSIBLE BREAKING CHANGE VVVVV * * 2021-05-18: REVISED TO START USING 2nd Paramter (now called specificKeys ) * * TO AVOID ISSUES (this paramter was received but not used in the past) - pass in null or [] * * @param baselineObject * @param specificKeys ( was keySummary ) - Pass array of specific keys to check, empty or null to use keys in baselineObject * @param compareObject * @param parseMe */ export function getKeyChanges( baselineObject: any, specificKeys: string[], compareObject : any, parseMe: boolean ) { let keyChanges : any = {}; let TestTheseKeys =[]; if ( baselineObject === null || compareObject === null ) { TestTheseKeys = BaseFieldKeys; // TestTheseKeys = BaseFieldKeys; } else if ( specificKeys !== null && specificKeys !== undefined && specificKeys.length > 0 ) { TestTheseKeys = specificKeys; } else { TestTheseKeys = baselineObject ? Object.keys( baselineObject ) : Object.keys( compareObject ); } TestTheseKeys.map( key => { let baselineObjectVal: any = baselineObject ? baselineObject[key] : key === 'Title' ? DoesNotExistLabel : undefined; let compareObjectVal: any = compareObject ? compareObject[key] : key === 'Title' ? DoesNotExistLabel : undefined; //Can't directly compare arrays or objects so you have to stringify them first if ( typeof baselineObjectVal === 'object' ) { baselineObjectVal = JSON.stringify( baselineObject[key] ); } //Can't directly compare arrays or objects so you have to stringify them first if ( typeof compareObjectVal === 'object' ) { compareObjectVal = JSON.stringify( compareObject[key] ); } if ( baselineObjectVal !== compareObjectVal ) { let keyChange = baselineObjectVal + KeyChangeDelimiter + compareObjectVal; //Do not make comparisons for these... let ignoreCompares = [ `undefined${KeyChangeDelimiter}null`, `undefined${KeyChangeDelimiter}function(){}`, `undefined${KeyChangeDelimiter}[object HTMLDivElement]`, `undefined${KeyChangeDelimiter}[object Object]`, //May want to come back to this one though and add back `undefined${KeyChangeDelimiter}` ]; if ( ignoreCompares.indexOf( keyChange ) < 0 && keyChange.indexOf( `undefined${KeyChangeDelimiter}function` ) < 0 ) { keyChanges[key] = keyChange ; } if ( keyChange === `undefined${KeyChangeDelimiter}[object Object]` ) { console.log('OBJECT NOT COMPARED', baselineObjectVal, compareObjectVal ); } } }); if ( parseMe !== false ) { keyChanges = JSON.parse( JSON.stringify( keyChanges ) ) ; } return keyChanges; }