Merge branch 'master' into lev-dist
This commit is contained in:
31
README.md
31
README.md
@ -157,6 +157,7 @@ average(1, 2, 3);
|
||||
* [`sortedIndexBy`](#sortedindexby)
|
||||
* [`sortedLastIndex`](#sortedlastindex)
|
||||
* [`sortedLastIndexBy`](#sortedlastindexby)
|
||||
* [`stableSort`](#stablesort-)
|
||||
* [`symmetricDifference`](#symmetricdifference)
|
||||
* [`symmetricDifferenceBy`](#symmetricdifferenceby)
|
||||
* [`symmetricDifferenceWith`](#symmetricdifferencewith)
|
||||
@ -2328,6 +2329,36 @@ sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, o => o.x); // 1
|
||||
<br>[⬆ Back to top](#table-of-contents)
|
||||
|
||||
|
||||
### stableSort 
|
||||
|
||||
Performs stable sorting of an array, preserving the initial indexes of items when their values are the same.
|
||||
Does not mutate the original array, but returns a new array instead.
|
||||
|
||||
Use `Array.map()` to pair each element of the input array with its corresponding index.
|
||||
Use `Array.sort()` and a `compare` function to sort the list, preserving their initial order if the items compared are equal.
|
||||
Use `Array.map()` to convert back to the initial array items.
|
||||
|
||||
```js
|
||||
const stableSort = (arr, compare) =>
|
||||
arr
|
||||
.map((item, index) => ({ item, index }))
|
||||
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
|
||||
.map(({ item }) => item);
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Examples</summary>
|
||||
|
||||
```js
|
||||
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
const stable = stableSort(arr, () => 0); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
<br>[⬆ Back to top](#table-of-contents)
|
||||
|
||||
|
||||
### symmetricDifference
|
||||
|
||||
Returns the symmetric difference between two arrays.
|
||||
|
||||
13
dist/_30s.es5.js
vendored
13
dist/_30s.es5.js
vendored
File diff suppressed because one or more lines are too long
2
dist/_30s.es5.min.js
vendored
2
dist/_30s.es5.min.js
vendored
File diff suppressed because one or more lines are too long
8
dist/_30s.esm.js
vendored
8
dist/_30s.esm.js
vendored
@ -1160,6 +1160,12 @@ const splitLines = str => str.split(/\r?\n/);
|
||||
|
||||
const spreadOver = fn => argsArr => fn(...argsArr);
|
||||
|
||||
const stableSort = (arr, compare) =>
|
||||
arr
|
||||
.map((item, index) => ({ item, index }))
|
||||
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
|
||||
.map(({ item }) => item);
|
||||
|
||||
const standardDeviation = (arr, usePopulation = false) => {
|
||||
const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
|
||||
return Math.sqrt(
|
||||
@ -1417,6 +1423,6 @@ const zipWith = (...arrays) => {
|
||||
return fn ? result.map(arr => fn(...arr)) : result;
|
||||
};
|
||||
|
||||
var imports = {JSONToFile,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,anagrams,any,approximatelyEqual,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,createElement,createEventHub,currentURL,curry,debounce,decapitalize,deepClone,deepFlatten,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,inRange,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isArrayLike,isBoolean,isDivisible,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isSorted,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapValues,mask,matches,matchesWith,maxBy,maxN,median,memoize,merge,minBy,minN,mostPerformant,negate,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,palindrome,parseCookie,partial,partialRight,partition,percentile,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,redirect,reduceSuccessive,reduceWhich,reducedFilter,remove,removeNonASCII,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,show,shuffle,similarity,size,sleep,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,standardDeviation,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,untildify,unzip,unzipWith,validateNumber,without,words,xProd,yesNo,zip,zipObject,zipWith,}
|
||||
var imports = {JSONToFile,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,anagrams,any,approximatelyEqual,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,createElement,createEventHub,currentURL,curry,debounce,decapitalize,deepClone,deepFlatten,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,inRange,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isArrayLike,isBoolean,isDivisible,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isSorted,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapValues,mask,matches,matchesWith,maxBy,maxN,median,memoize,merge,minBy,minN,mostPerformant,negate,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,palindrome,parseCookie,partial,partialRight,partition,percentile,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,redirect,reduceSuccessive,reduceWhich,reducedFilter,remove,removeNonASCII,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,show,shuffle,similarity,size,sleep,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,untildify,unzip,unzipWith,validateNumber,without,words,xProd,yesNo,zip,zipObject,zipWith,}
|
||||
|
||||
export default imports;
|
||||
|
||||
8
dist/_30s.js
vendored
8
dist/_30s.js
vendored
@ -1166,6 +1166,12 @@ const splitLines = str => str.split(/\r?\n/);
|
||||
|
||||
const spreadOver = fn => argsArr => fn(...argsArr);
|
||||
|
||||
const stableSort = (arr, compare) =>
|
||||
arr
|
||||
.map((item, index) => ({ item, index }))
|
||||
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
|
||||
.map(({ item }) => item);
|
||||
|
||||
const standardDeviation = (arr, usePopulation = false) => {
|
||||
const mean = arr.reduce((acc, val) => acc + val, 0) / arr.length;
|
||||
return Math.sqrt(
|
||||
@ -1423,7 +1429,7 @@ const zipWith = (...arrays) => {
|
||||
return fn ? result.map(arr => fn(...arr)) : result;
|
||||
};
|
||||
|
||||
var imports = {JSONToFile,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,anagrams,any,approximatelyEqual,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,createElement,createEventHub,currentURL,curry,debounce,decapitalize,deepClone,deepFlatten,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,inRange,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isArrayLike,isBoolean,isDivisible,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isSorted,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapValues,mask,matches,matchesWith,maxBy,maxN,median,memoize,merge,minBy,minN,mostPerformant,negate,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,palindrome,parseCookie,partial,partialRight,partition,percentile,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,redirect,reduceSuccessive,reduceWhich,reducedFilter,remove,removeNonASCII,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,show,shuffle,similarity,size,sleep,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,standardDeviation,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,untildify,unzip,unzipWith,validateNumber,without,words,xProd,yesNo,zip,zipObject,zipWith,}
|
||||
var imports = {JSONToFile,RGBToHex,URLJoin,UUIDGeneratorBrowser,UUIDGeneratorNode,all,anagrams,any,approximatelyEqual,arrayToHtmlList,ary,atob,attempt,average,averageBy,bifurcate,bifurcateBy,bind,bindAll,bindKey,binomialCoefficient,bottomVisible,btoa,byteSize,call,capitalize,capitalizeEveryWord,castArray,chainAsync,chunk,clampNumber,cloneRegExp,coalesce,coalesceFactory,collectInto,colorize,compact,compose,composeRight,converge,copyToClipboard,countBy,countOccurrences,createElement,createEventHub,currentURL,curry,debounce,decapitalize,deepClone,deepFlatten,defaults,defer,degreesToRads,delay,detectDeviceType,difference,differenceBy,differenceWith,digitize,distance,drop,dropRight,dropRightWhile,dropWhile,elementIsVisibleInViewport,elo,equals,escapeHTML,escapeRegExp,everyNth,extendHex,factorial,fibonacci,filterNonUnique,findKey,findLast,findLastIndex,findLastKey,flatten,flattenObject,flip,forEachRight,forOwn,forOwnRight,formatDuration,fromCamelCase,functionName,functions,gcd,geometricProgression,get,getColonTimeFromDate,getDaysDiffBetweenDates,getMeridiemSuffixOfInteger,getScrollPosition,getStyle,getType,getURLParameters,groupBy,hammingDistance,hasClass,hasFlags,hashBrowser,hashNode,head,hexToRGB,hide,httpGet,httpPost,httpsRedirect,inRange,indexOfAll,initial,initialize2DArray,initializeArrayWithRange,initializeArrayWithRangeRight,initializeArrayWithValues,intersection,intersectionBy,intersectionWith,invertKeyValues,is,isAbsoluteURL,isArrayLike,isBoolean,isDivisible,isEmpty,isEven,isFunction,isLowerCase,isNil,isNull,isNumber,isObject,isObjectLike,isPlainObject,isPrime,isPrimitive,isPromiseLike,isSorted,isString,isSymbol,isTravisCI,isUndefined,isUpperCase,isValidJSON,join,last,lcm,longestItem,lowercaseKeys,luhnCheck,mapKeys,mapObject,mapValues,mask,matches,matchesWith,maxBy,maxN,median,memoize,merge,minBy,minN,mostPerformant,negate,none,nthArg,nthElement,objectFromPairs,objectToPairs,observeMutations,off,omit,omitBy,on,onUserInputChange,once,orderBy,over,overArgs,palindrome,parseCookie,partial,partialRight,partition,percentile,pick,pickBy,pipeAsyncFunctions,pipeFunctions,pluralize,powerset,prettyBytes,primes,promisify,pull,pullAtIndex,pullAtValue,pullBy,radsToDegrees,randomHexColorCode,randomIntArrayInRange,randomIntegerInRange,randomNumberInRange,readFileLines,rearg,redirect,reduceSuccessive,reduceWhich,reducedFilter,remove,removeNonASCII,reverseString,round,runAsync,runPromisesInSeries,sample,sampleSize,scrollToTop,sdbm,serializeCookie,setStyle,shallowClone,show,shuffle,similarity,size,sleep,sortCharactersInString,sortedIndex,sortedIndexBy,sortedLastIndex,sortedLastIndexBy,splitLines,spreadOver,stableSort,standardDeviation,stripHTMLTags,sum,sumBy,sumPower,symmetricDifference,symmetricDifferenceBy,symmetricDifferenceWith,tail,take,takeRight,takeRightWhile,takeWhile,throttle,timeTaken,times,toCamelCase,toCurrency,toDecimalMark,toKebabCase,toOrdinalSuffix,toSafeInteger,toSnakeCase,toggleClass,tomorrow,transform,truncateString,truthCheckCollection,unary,uncurry,unescapeHTML,unflattenObject,unfold,union,unionBy,unionWith,uniqueElements,untildify,unzip,unzipWith,validateNumber,without,words,xProd,yesNo,zip,zipObject,zipWith,}
|
||||
|
||||
return imports;
|
||||
|
||||
|
||||
2
dist/_30s.min.js
vendored
2
dist/_30s.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
21
snippets/stableSort.md
Normal file
21
snippets/stableSort.md
Normal file
@ -0,0 +1,21 @@
|
||||
### stableSort
|
||||
|
||||
Performs stable sorting of an array, preserving the initial indexes of items when their values are the same.
|
||||
Does not mutate the original array, but returns a new array instead.
|
||||
|
||||
Use `Array.map()` to pair each element of the input array with its corresponding index.
|
||||
Use `Array.sort()` and a `compare` function to sort the list, preserving their initial order if the items compared are equal.
|
||||
Use `Array.map()` to convert back to the initial array items.
|
||||
|
||||
```js
|
||||
const stableSort = (arr, compare) =>
|
||||
arr
|
||||
.map((item, index) => ({ item, index }))
|
||||
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
|
||||
.map(({ item }) => item);
|
||||
```
|
||||
|
||||
```js
|
||||
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
const stable = stableSort(arr, () => 0); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
||||
```
|
||||
@ -234,6 +234,7 @@ sortedLastIndex:array,math
|
||||
sortedLastIndexBy:array,math,function
|
||||
splitLines:string
|
||||
spreadOver:adapter
|
||||
stableSort:array,sort,advanced
|
||||
standardDeviation:math,array
|
||||
stripHTMLTags:string,utility,regexp
|
||||
sum:math,array
|
||||
|
||||
6
test/stableSort/stableSort.js
Normal file
6
test/stableSort/stableSort.js
Normal file
@ -0,0 +1,6 @@
|
||||
const stableSort = (arr, compare) =>
|
||||
arr
|
||||
.map((item, index) => ({ item, index }))
|
||||
.sort((a, b) => compare(a.item, b.item) || a.index - b.index)
|
||||
.map(({ item }) => item);
|
||||
module.exports = stableSort;
|
||||
17
test/stableSort/stableSort.test.js
Normal file
17
test/stableSort/stableSort.test.js
Normal file
@ -0,0 +1,17 @@
|
||||
const test = require('tape');
|
||||
const stableSort = require('./stableSort.js');
|
||||
|
||||
test('Testing stableSort', (t) => {
|
||||
//For more information on all the methods supported by tape
|
||||
//Please go to https://github.com/substack/tape
|
||||
t.true(typeof stableSort === 'function', 'stableSort is a Function');
|
||||
//t.deepEqual(stableSort(args..), 'Expected');
|
||||
//t.equal(stableSort(args..), 'Expected');
|
||||
//t.false(stableSort(args..), 'Expected');
|
||||
//t.throws(stableSort(args..), 'Expected');
|
||||
|
||||
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
const compare = () => 0;
|
||||
t.deepEqual(stableSort(arr, compare), arr, 'Array is properly sorted');
|
||||
t.end();
|
||||
});
|
||||
@ -1,4 +1,4 @@
|
||||
Test log for: Sun Feb 18 2018 19:56:04 GMT+0530 (India Standard Time)
|
||||
Test log for: Sun Feb 18 2018 20:24:43 GMT+0000 (UTC)
|
||||
|
||||
> 30-seconds-of-code@0.0.2 test R:\github\30-seconds-of-code
|
||||
> tape test/**/*.test.js | tap-spec
|
||||
@ -1527,6 +1527,11 @@ Test log for: Sun Feb 18 2018 19:56:04 GMT+0530 (India Standard Time)
|
||||
√ spreadOver is a Function
|
||||
√ Takes a variadic function and returns a closure that accepts an array of arguments to map to the inputs of the function.
|
||||
|
||||
Testing stableSort
|
||||
|
||||
✔ stableSort is a Function
|
||||
✔ Array is properly sorted
|
||||
|
||||
Testing standardDeviation
|
||||
|
||||
√ standardDeviation is a Function
|
||||
@ -1915,6 +1920,7 @@ Test log for: Sun Feb 18 2018 19:56:04 GMT+0530 (India Standard Time)
|
||||
√ Works with multiple promises
|
||||
|
||||
|
||||
|
||||
total: 974
|
||||
passing: 974
|
||||
duration: 2.9s
|
||||
|
||||
Reference in New Issue
Block a user