mirror of
https://bitbucket.org/bellord13/kit.git
synced 2026-11-13 19:06:11 +03:00
fix
This commit is contained in:
@@ -100,7 +100,7 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global)
|
||||
|
||||
this.__aminationTrapHide = new AnimationTrap(this.node, function (options) {
|
||||
if(options.onHideBefore !== false) {
|
||||
this.onHideBefore.eachCall(window, options);
|
||||
this.onHideBefore.eachCall(this.node, options);
|
||||
}
|
||||
removeAnimation.call(this, this.animShowClass);
|
||||
addAnimation.call(this, this.animHideClass);
|
||||
@@ -111,14 +111,14 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global)
|
||||
this.node.classList.add('hide');
|
||||
this.node.classList.remove('show');
|
||||
if(options.onHide !== false) {
|
||||
this.onHide.eachCall(window, options);
|
||||
this.onHide.eachCall(this.node, options);
|
||||
}
|
||||
this.node.style.display = 'none';
|
||||
}.bind(this));
|
||||
|
||||
this.__aminationTrapShow = new AnimationTrap(this.node, function (options = {}) {
|
||||
if(options.onShowBefore !== false) {
|
||||
this.onShowBefore.eachCall(window, options);
|
||||
this.onShowBefore.eachCall(this.node, options);
|
||||
}
|
||||
this.node.classList.remove('hide');
|
||||
this.node.classList.add('show');
|
||||
@@ -132,7 +132,7 @@ kit.PluginManager.register('Viewer', function(module, exports, require, global)
|
||||
removeAnimation.call(this, this.animHideClass);
|
||||
addAnimation.call(this, this.animShowClass);
|
||||
if(options.onShow !== false) {
|
||||
this.onShow.eachCall(window, options);
|
||||
this.onShow.eachCall(this.node, options);
|
||||
}
|
||||
}.bind(this), function (options = {}) {
|
||||
|
||||
|
||||
+49
-20
@@ -27,6 +27,10 @@ kit.PluginManager.register('align',function(module, exports, require) {
|
||||
}
|
||||
var metrics = {};
|
||||
if(this.node instanceof HTMLElement) {
|
||||
|
||||
var pr = getBoundingClientRect(this.node.offsetParent);
|
||||
var nr = getBoundingClientRect(this.node);
|
||||
|
||||
metrics = {
|
||||
offsetHeight: this.node.offsetHeight,
|
||||
offsetWidth: this.node.offsetWidth,
|
||||
@@ -36,39 +40,39 @@ kit.PluginManager.register('align',function(module, exports, require) {
|
||||
offsetTop: this.node.offsetTop,
|
||||
clientLeft: this.node.clientLeft,
|
||||
clientTop: this.node.clientTop,
|
||||
clientRight: this.node.offsetWidth - this.node.clientWidth,
|
||||
clientBottom: this.node.offsetHeight - this.node.clientHeight,
|
||||
clientRight: this.node.offsetWidth - this.node.clientWidth - this.node.clientLeft,
|
||||
clientBottom: this.node.offsetHeight - this.node.clientHeight - this.node.clientTop,
|
||||
|
||||
offsetRight: document.body.offsetWidth - this.node.offsetLeft - this.node.offsetWidth,
|
||||
offsetBottom: window.innerHeight - this.node.offsetTop - this.node.offsetHeight,
|
||||
offsetRight: pr.right - nr.right,
|
||||
offsetBottom: pr.bottom - nr.bottom,
|
||||
};
|
||||
metrics = Object.assign({}, getBoundingClientRect(this.node), metrics);
|
||||
metrics = Object.assign({}, nr, metrics);
|
||||
}
|
||||
if(this.node instanceof Window) {
|
||||
metrics = {
|
||||
offsetHeight: window.innerHeight,
|
||||
offsetWidth: document.body.offsetWidth,
|
||||
clientHeight: window.innerHeight,
|
||||
offsetWidth: window.innerWidth,
|
||||
clientHeight: document.body.offsetHeight,
|
||||
clientWidth: document.body.offsetWidth,
|
||||
offsetLeft: 0,
|
||||
offsetTop: 0,
|
||||
offsetLeft: window.pageXOffset,
|
||||
offsetTop: window.pageYOffset,
|
||||
clientLeft: 0,
|
||||
clientTop: 0,
|
||||
clientRight: 0,
|
||||
clientBottom: 0,
|
||||
clientRight: window.innerWidth - document.body.offsetWidth,
|
||||
clientBottom: window.innerHeight - document.body.offsetHeight,
|
||||
|
||||
offsetRight: 0,
|
||||
offsetBottom: 0,
|
||||
offsetRight: document.body.scrollWidth - document.body.offsetWidth - window.pageXOffset,
|
||||
offsetBottom: document.body.scrollHeight - document.body.offsetHeight - window.pageYOffset,
|
||||
};
|
||||
metrics = Object.assign({
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: document.body.offsetWidth,
|
||||
bottom: window.innerHeight,
|
||||
bottom: document.body.offsetHeight,
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: document.body.offsetWidth,
|
||||
height: window.innerHeight,
|
||||
height: document.body.offsetHeight,
|
||||
}, metrics)
|
||||
}
|
||||
Object.assign(this, metrics);
|
||||
@@ -173,7 +177,7 @@ kit.PluginManager.register('align',function(module, exports, require) {
|
||||
|
||||
this.style = {
|
||||
start: function (extra) {
|
||||
this.nodeMetricsLine.node.style[this.map.style.start()] = '' + ((!this.valid && extra)?this.shiftExtra:this.shift) + 'px';
|
||||
this.nodeMetricsLine.node.style[this.map.style.start()] = '' + (extra?this.shiftExtra:this.shift) + 'px';
|
||||
}.bind(this),
|
||||
end: function (extra) {
|
||||
this.nodeMetricsLine.node.style[this.map.style.end()] = 'unset';
|
||||
@@ -233,7 +237,7 @@ kit.PluginManager.register('align',function(module, exports, require) {
|
||||
};
|
||||
|
||||
var getShiftWhenHidingNodeUnderLimiterStart = function(shift) {
|
||||
var d = this.parentMetricsLine.start + shift - this.limiterMetricsLine.start;
|
||||
var d = this.parentMetricsLine.start + shift - Math.min(this.limiterMetricsLine.start, this.parentMetricsLine.end);
|
||||
if(d < 0) {
|
||||
shift = shift - d;
|
||||
}
|
||||
@@ -253,7 +257,13 @@ kit.PluginManager.register('align',function(module, exports, require) {
|
||||
return (this.parentMetricsLine.start + this.shift) >= this.limiterMetricsLine.start;
|
||||
}.bind(this),
|
||||
shiftExtra: function () {
|
||||
return getShiftWhenHidingNodeUnderLimiterStart(this.shift - this.applicability);
|
||||
var shift = getShiftWhenHidingNodeUnderLimiterStart(this.shift);
|
||||
var applicability = 0;
|
||||
if(!this.valid) {
|
||||
applicability = (this.parentMetricsLine.start + shift) - this.limiterMetricsLine.start;
|
||||
shift = getShiftWhenHidingNodeUnderLimiterStart(shift - applicability);
|
||||
}
|
||||
return shift;
|
||||
}.bind(this),
|
||||
},
|
||||
end: {
|
||||
@@ -267,7 +277,13 @@ kit.PluginManager.register('align',function(module, exports, require) {
|
||||
return this.limiterMetricsLine.end >= (this.parentMetricsLine.start + this.nodeMetricsLine.length + this.shift);
|
||||
}.bind(this),
|
||||
shiftExtra: function () {
|
||||
return getShiftWhenHidingNodeUnderLimiterStart(this.shift + this.applicability);
|
||||
var shift = getShiftWhenHidingNodeUnderLimiterStart(this.shift);
|
||||
var applicability = 0;
|
||||
if(!this.valid) {
|
||||
applicability = this.limiterMetricsLine.end - (this.parentMetricsLine.start + this.nodeMetricsLine.length + shift);
|
||||
shift = getShiftWhenHidingNodeUnderLimiterStart(shift + applicability);
|
||||
}
|
||||
return shift;
|
||||
}.bind(this),
|
||||
},
|
||||
/**
|
||||
@@ -284,7 +300,13 @@ kit.PluginManager.register('align',function(module, exports, require) {
|
||||
return this.limiterMetricsLine.end >= (this.parentMetricsLine.start + this.nodeMetricsLine.length + this.shift);
|
||||
}.bind(this),
|
||||
shiftExtra: function () {
|
||||
return getShiftWhenHidingNodeUnderLimiterStart(this.shift + this.applicability);
|
||||
var shift = getShiftWhenHidingNodeUnderLimiterStart(this.shift);
|
||||
var applicability = 0;
|
||||
if(!this.valid) {
|
||||
applicability = this.limiterMetricsLine.end - (this.parentMetricsLine.start + this.nodeMetricsLine.length + shift);
|
||||
shift = getShiftWhenHidingNodeUnderLimiterStart(shift + applicability);
|
||||
}
|
||||
return shift;
|
||||
}.bind(this),
|
||||
},
|
||||
},
|
||||
@@ -569,6 +591,13 @@ kit.PluginManager.register('align',function(module, exports, require) {
|
||||
if(!['absolute', 'relative'].includes(this.__nodeComputedStyle.position)) {
|
||||
this.node.style.position = 'absolute';
|
||||
}
|
||||
|
||||
if(!this.__parentNodeComputedStyle) {
|
||||
this.__parentNodeComputedStyle = getComputedStyle(this.parentNode);
|
||||
}
|
||||
if(!['absolute', 'relative', 'fixed'].includes(this.__parentNodeComputedStyle.position)) {
|
||||
this.parentNode.style.position = 'relative';
|
||||
}
|
||||
};
|
||||
|
||||
AlignClass.prototype.setEx = function(axis, align, direction){
|
||||
|
||||
@@ -42,4 +42,59 @@
|
||||
transform: scale(0.5);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.anim-fade-in {
|
||||
-webkit-animation: fade-in 0.15s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
|
||||
animation: fade-in 0.15s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
|
||||
}
|
||||
@-webkit-keyframes fade-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes fade-in {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.anim-fade-in-top {
|
||||
-webkit-animation: fade-in-top 0.15s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
|
||||
animation: fade-in-top 0.15s cubic-bezier(0.390, 0.575, 0.565, 1.000) both;
|
||||
}
|
||||
@-webkit-keyframes fade-in-top {
|
||||
0% {
|
||||
-webkit-transform: translateY(-50px);
|
||||
transform: translateY(-50px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes fade-in-top {
|
||||
0% {
|
||||
-webkit-transform: translateY(-50px);
|
||||
transform: translateY(-50px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.anim-fade-out {
|
||||
-webkit-animation: fade-out 0.15s ease-out both;
|
||||
animation: fade-out 0.15s ease-out both;
|
||||
}
|
||||
@-webkit-keyframes fade-out{0%{opacity:1}100%{opacity:0}}@keyframes fade-out{0%{opacity:1}100%{opacity:0}}
|
||||
.anim-fade-out-top{-webkit-animation:fade-out-top .15s cubic-bezier(.25,.46,.45,.94) both;animation:fade-out-top .15s cubic-bezier(.25,.46,.45,.94) both}
|
||||
@-webkit-keyframes fade-out-top{0%{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}100%{-webkit-transform:translateY(-50px);transform:translateY(-50px);opacity:0}}@keyframes fade-out-top{0%{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}100%{-webkit-transform:translateY(-50px);transform:translateY(-50px);opacity:0}}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* https://animista.net/
|
||||
* @link https://animista.net/
|
||||
* @module animations
|
||||
**/
|
||||
kit.PluginManager.register('animations',function(module, exports, require, global) {
|
||||
@@ -10,9 +10,13 @@ kit.PluginManager.register('animations',function(module, exports, require, globa
|
||||
var animations = {
|
||||
scaleIn: 'anim-scale-in',
|
||||
scaleOut: 'anim-scale-out',
|
||||
fadeIn: 'anim-fade-in',
|
||||
fadeInTop: 'anim-fade-in-top',
|
||||
fadeOut: 'anim-fade-out',
|
||||
fadeOutTop: 'anim-fade-out-top',
|
||||
};
|
||||
|
||||
Object.assign(animations, global.animations || {});
|
||||
//Object.assign(animations, global.animations || {});
|
||||
|
||||
return module.exports = animations;
|
||||
});
|
||||
|
||||
@@ -77,6 +77,16 @@ __PluginManager__.registerPlugins({
|
||||
},
|
||||
deps: ['popper', 'bsCore'],
|
||||
},
|
||||
Tooltip2: {
|
||||
path: __pmConfig__.assetsPath + '/tooltip2',
|
||||
module: '/tooltip2.js',
|
||||
type: 'loader',
|
||||
css: '/tooltip2.css',
|
||||
onInstall: function(){
|
||||
|
||||
},
|
||||
deps: ['Viewer', 'support', 'ActionCollection', 'Action', 'userAction', 'align'],
|
||||
},
|
||||
Popover: {
|
||||
path: __pmConfig__.assetsPath + '/popover',
|
||||
module: '/popover.js',
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* @property {kitToolkit} toolkit
|
||||
* @property {kitModal} Modal
|
||||
* @property {kitConfig} config
|
||||
* @property {kitTooltip} tooltip
|
||||
* @property {kitPopover} Popover
|
||||
* @property {kitPopper} popper
|
||||
*/
|
||||
|
||||
@@ -11,6 +11,7 @@ __PluginManager__.register('dataStructures', function(module, exports, require,
|
||||
this.timeout = 0;
|
||||
this.arguments = null;
|
||||
this.context = null;
|
||||
this.executeBeforeTimeout = false;
|
||||
this.setContext(context);
|
||||
this.setCallback(callback);
|
||||
this.setTimeout(timeout);
|
||||
@@ -29,22 +30,33 @@ __PluginManager__.register('dataStructures', function(module, exports, require,
|
||||
this.counter++;
|
||||
|
||||
if(this.timerId === 0) {
|
||||
this.__exec(this.counter);
|
||||
if(this.executeBeforeTimeout) {
|
||||
this.__execBeforeTimeout(this.counter);
|
||||
} else {
|
||||
this.__execAfterDelay();
|
||||
}
|
||||
}
|
||||
};
|
||||
stack.prototype.__exec = function (counter) {
|
||||
stack.prototype.__execBeforeTimeout = function (counter) {
|
||||
this.timerId = setTimeout((function(){
|
||||
if(this.counter > counter) {
|
||||
this.__exec(this.counter);
|
||||
this.__execBeforeTimeout(this.counter);
|
||||
return null;
|
||||
}
|
||||
this.timerId = 0;
|
||||
}).bind(this), this.timeout);
|
||||
this.callback.apply(this.context, this.arguments);
|
||||
};
|
||||
stack.prototype.__execAfterDelay = function () {
|
||||
this.timerId = setTimeout((function(){
|
||||
this.callback.apply(this.context, this.arguments);
|
||||
this.timerId = 0;
|
||||
}).bind(this), this.timeout);
|
||||
};
|
||||
stack.prototype.reset = function () {
|
||||
clearTimeout(this.timerId);
|
||||
this.timerId = 0;
|
||||
this.counter = 0;
|
||||
};
|
||||
return stack;
|
||||
})()
|
||||
|
||||
@@ -85,12 +85,16 @@ __PluginManager__.register('loggerService', function(module, exports, require, g
|
||||
|
||||
function setObjectValue(log, lvl, key, value, opClass, depth = 3, openDepth = 1, isRoot = true) {
|
||||
var rowChild, isObj = support.isObject(value), id = isObj?support.uniqueId():'',
|
||||
val = (isObj&&depth)?'<label for="'+id+'">'+value+'</label>':value, inp, j,
|
||||
valueString = ((isObj && typeof value.toString !== 'function') || typeof value === 'symbol')?(typeof value):value,
|
||||
val = (isObj&&depth)?'<label for="'+id+'">'+valueString+'</label>':valueString, inp, j,
|
||||
len = isObj?Object.keys(value).length:0;
|
||||
|
||||
if(!isRoot || (isRoot && !isObj)) {
|
||||
log.appendChild(getRowNode(lvl, key, '' + val + (isObj?(' ['+len+']'):''), opClass));
|
||||
}
|
||||
if(value === window || value === document) {
|
||||
return;
|
||||
}
|
||||
if(isObj&&depth) {
|
||||
!isRoot && ++lvl;
|
||||
depth = Math.max(0, depth - 1);
|
||||
|
||||
+5
-1
@@ -761,14 +761,18 @@ __PluginManager__.register('menu',function(module, exports, require, global) {
|
||||
);
|
||||
};
|
||||
|
||||
var reCalcAllMenuLimiter = new dataStructures.StackExecutionLimiter(this, reCalcAllMenu, 250);
|
||||
var reCalcAllMenuLimiter = new dataStructures.StackExecutionLimiter(this, reCalcAllMenu, 100);
|
||||
var globalHandlers = {
|
||||
resize: function(){
|
||||
reCalcAllMenuLimiter.exec();
|
||||
},
|
||||
scroll: function(){
|
||||
reCalcAllMenuLimiter.exec();
|
||||
},
|
||||
};
|
||||
|
||||
window.addEventListener('resize', globalHandlers.resize);
|
||||
window.addEventListener('scroll', globalHandlers.scroll);
|
||||
|
||||
/**
|
||||
* @memberOf kit
|
||||
|
||||
@@ -106,13 +106,17 @@
|
||||
margin-bottom: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.modal-body:empty {
|
||||
display: none;
|
||||
}
|
||||
.modal-body {
|
||||
position: relative;
|
||||
flex: 1 1 auto;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
.modal-footer:empty {
|
||||
display: none;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
@@ -131,9 +131,12 @@ __PluginManager__.register('support', function(module, exports, require, global)
|
||||
if(isNode(html)) {
|
||||
return html;
|
||||
}
|
||||
if(isString(html)) {
|
||||
html = html.trim();
|
||||
}
|
||||
var nodeWrap = document.createElement('div');
|
||||
nodeWrap.innerHTML = html;
|
||||
var r = nodeWrap.firstElementChild;
|
||||
var r = nodeWrap.firstChild;
|
||||
r.remove();
|
||||
return r;
|
||||
}
|
||||
@@ -141,8 +144,15 @@ __PluginManager__.register('support', function(module, exports, require, global)
|
||||
if(isNodeList(html)) {
|
||||
return html;
|
||||
}
|
||||
if(isString(html)) {
|
||||
html = html.trim();
|
||||
}
|
||||
var nodeWrap = document.createElement('div');
|
||||
nodeWrap.innerHTML = html;
|
||||
if(isNode(html)) {
|
||||
nodeWrap.append(html);
|
||||
} else {
|
||||
nodeWrap.innerHTML = html;
|
||||
}
|
||||
return nodeWrap.childNodes;
|
||||
}
|
||||
function setNodeData(node, key, value) {
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
}
|
||||
|
||||
.tooltip-inner {
|
||||
width: max-content;
|
||||
max-width: 200px;
|
||||
padding: 0.25rem 0.5rem;
|
||||
color: var(--popper-color);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
kit.PluginManager.register('tooltip',function(module, exports, require){
|
||||
/** @module Tooltip */
|
||||
kit.PluginManager.register('Tooltip',function(module, exports, require){
|
||||
|
||||
var Popper = require('popper');
|
||||
|
||||
@@ -115,7 +116,7 @@ kit.PluginManager.register('tooltip',function(module, exports, require){
|
||||
* ------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** @class kitTooltip */
|
||||
/** @memberOf kit */
|
||||
class Tooltip extends BaseComponent {
|
||||
constructor(element, config) {
|
||||
if (typeof Popper === 'undefined') {
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/** @module Tooltip2 */
|
||||
kit.PluginManager.register('Tooltip2',function(module, exports, require, global){
|
||||
|
||||
var Viewer = require('Viewer');
|
||||
var support = require('support');
|
||||
var ActionCollection = require('ActionCollection');
|
||||
var Action = require('Action');
|
||||
var userAction = require('userAction');
|
||||
var align = require('align');
|
||||
var animations = require('animations');
|
||||
|
||||
const PLUGIN_NAME = 'tooltip2';
|
||||
|
||||
const Default = {
|
||||
template: '<div class="tooltip" role="tooltip" style="display: none">' +
|
||||
//'<div class="tooltip-arrow" data-popper-arrow="true"></div>' +
|
||||
'<div class="tooltip-inner"></div>' +
|
||||
'</div>',
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @memberOf kit
|
||||
* @param masterNode
|
||||
* @param hintNode
|
||||
* @constructor
|
||||
*/
|
||||
var Tooltip2 = function(masterNode, hintNode) {
|
||||
var self = this;
|
||||
this.masterNode = support.getNode(masterNode);
|
||||
this.hintNode = support.getNode(hintNode);
|
||||
if(!this.hintNode) {
|
||||
this.hintNode = support.makeNode(Default.template);
|
||||
}
|
||||
this.hintNode.remove();
|
||||
this.masterNode.appendChild(this.hintNode);
|
||||
support.setNodeData(this.masterNode, PLUGIN_NAME, this);
|
||||
|
||||
this.align = new align.Class(this.hintNode, this.masterNode);
|
||||
this.align.offset = [0, 10];
|
||||
var hint = new userAction.Hint(this.masterNode, this.hintNode);
|
||||
this.viewer = hint.viewer;
|
||||
this.viewer.delayHide = 400;
|
||||
this.viewer.animShowClass = animations.fadeIn;
|
||||
this.viewer.animHideClass = animations.fadeOut;
|
||||
this.viewer.onShow.push(function () {
|
||||
self.render();
|
||||
});
|
||||
this.action = new ActionCollection([
|
||||
hint
|
||||
]);
|
||||
};
|
||||
|
||||
var __proto = Tooltip2.prototype;
|
||||
|
||||
__proto.setContent = function(html = ''){
|
||||
var titleNode = this.hintNode.querySelector('.tooltip-inner');
|
||||
support.innerHtml(titleNode, html);
|
||||
};
|
||||
|
||||
__proto.run = function(){
|
||||
this.action.run();
|
||||
};
|
||||
__proto.stop = function(){
|
||||
this.action.stop();
|
||||
};
|
||||
__proto.unset = function(){
|
||||
this.viewer.hide();
|
||||
this.stop();
|
||||
support.setNodeData(this.masterNode, PLUGIN_NAME, null);
|
||||
};
|
||||
__proto.render = function(){
|
||||
this.align.set('center', 'top', 'center', 'top');
|
||||
};
|
||||
|
||||
module.exports = Tooltip2;
|
||||
|
||||
return module.exports;
|
||||
});
|
||||
Reference in New Issue
Block a user