mirror of
				https://github.com/TeaOSLab/EdgeAdmin.git
				synced 2025-11-04 05:00:25 +08:00 
			
		
		
		
	实现一些阈值设置细节
This commit is contained in:
		@@ -5,6 +5,7 @@ import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/groups"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/monitor"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/cluster/node/thresholds"
 | 
			
		||||
	clusters "github.com/TeaOSLab/EdgeAdmin/internal/web/actions/default/clusters/clusterutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/helpers"
 | 
			
		||||
	"github.com/iwind/TeaGo"
 | 
			
		||||
@@ -45,6 +46,7 @@ func init() {
 | 
			
		||||
			Post("/node/monitor/trafficIn", new(monitor.TrafficInAction)).
 | 
			
		||||
			Post("/node/monitor/trafficOut", new(monitor.TrafficOutAction)).
 | 
			
		||||
			Post("/node/monitor/connections", new(monitor.ConnectionsAction)).
 | 
			
		||||
			Get("/node/thresholds", new(thresholds.IndexAction)).
 | 
			
		||||
 | 
			
		||||
			// 分组相关
 | 
			
		||||
			Get("/groups", new(groups.IndexAction)).
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,54 @@
 | 
			
		||||
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
 | 
			
		||||
 | 
			
		||||
package thresholds
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs"
 | 
			
		||||
	"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
 | 
			
		||||
	"github.com/iwind/TeaGo/maps"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type IndexAction struct {
 | 
			
		||||
	actionutils.ParentAction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) Init() {
 | 
			
		||||
	this.Nav("", "node", "threshold")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (this *IndexAction) RunGet(params struct {
 | 
			
		||||
	ClusterId int64
 | 
			
		||||
	NodeId    int64
 | 
			
		||||
}) {
 | 
			
		||||
	this.Data["nodeId"] = params.NodeId
 | 
			
		||||
 | 
			
		||||
	// 列出所有阈值
 | 
			
		||||
	thresholdsResp, err := this.RPC().NodeThresholdRPC().FindAllEnabledNodeThresholds(this.AdminContext(), &pb.FindAllEnabledNodeThresholdsRequest{
 | 
			
		||||
		Role:          "node",
 | 
			
		||||
		NodeClusterId: params.ClusterId,
 | 
			
		||||
		NodeId:        params.NodeId,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	thresholdMaps := []maps.Map{}
 | 
			
		||||
	for _, threshold := range thresholdsResp.NodeThresholds {
 | 
			
		||||
		thresholdMaps = append(thresholdMaps, maps.Map{
 | 
			
		||||
			"id":               threshold.Id,
 | 
			
		||||
			"itemName":         nodeconfigs.FindNodeValueItemName(threshold.Item),
 | 
			
		||||
			"paramName":        nodeconfigs.FindNodeValueItemParamName(threshold.Item, threshold.Param),
 | 
			
		||||
			"operatorName":     nodeconfigs.FindNodeValueOperatorName(threshold.Operator),
 | 
			
		||||
			"value":            nodeconfigs.UnmarshalNodeValue(threshold.ValueJSON),
 | 
			
		||||
			"sumMethodName":    nodeconfigs.FindNodeValueSumMethodName(threshold.SumMethod),
 | 
			
		||||
			"duration":         threshold.Duration,
 | 
			
		||||
			"durationUnitName": nodeconfigs.FindNodeValueDurationUnitName(threshold.DurationUnit),
 | 
			
		||||
			"isOn":             threshold.IsOn,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["thresholds"] = thresholdMaps
 | 
			
		||||
 | 
			
		||||
	this.Show()
 | 
			
		||||
}
 | 
			
		||||
@@ -20,8 +20,10 @@ func (this *CreatePopupAction) Init() {
 | 
			
		||||
 | 
			
		||||
func (this *CreatePopupAction) RunGet(params struct {
 | 
			
		||||
	ClusterId int64
 | 
			
		||||
	NodeId    int64
 | 
			
		||||
}) {
 | 
			
		||||
	this.Data["clusterId"] = params.ClusterId
 | 
			
		||||
	this.Data["nodeId"] = params.NodeId
 | 
			
		||||
	this.Data["items"] = nodeconfigs.FindAllNodeValueItemDefinitions()
 | 
			
		||||
	this.Data["operators"] = nodeconfigs.FindAllNodeValueOperatorDefinitions()
 | 
			
		||||
 | 
			
		||||
@@ -39,6 +41,7 @@ func (this *CreatePopupAction) RunPost(params struct {
 | 
			
		||||
	Duration       int32
 | 
			
		||||
	DurationUnit   string
 | 
			
		||||
	Message        string
 | 
			
		||||
	NotifyDuration int32
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
	CSRF *actionutils.CSRF
 | 
			
		||||
@@ -53,6 +56,7 @@ func (this *CreatePopupAction) RunPost(params struct {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resp, err := this.RPC().NodeThresholdRPC().CreateNodeThreshold(this.AdminContext(), &pb.CreateNodeThresholdRequest{
 | 
			
		||||
		Role:           "node",
 | 
			
		||||
		NodeClusterId:  params.ClusterId,
 | 
			
		||||
		NodeId:         params.NodeId,
 | 
			
		||||
		Item:           params.Item,
 | 
			
		||||
@@ -63,6 +67,7 @@ func (this *CreatePopupAction) RunPost(params struct {
 | 
			
		||||
		Duration:       params.Duration,
 | 
			
		||||
		DurationUnit:   params.DurationUnit,
 | 
			
		||||
		SumMethod:      params.SumMethod,
 | 
			
		||||
		NotifyDuration: params.NotifyDuration,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		this.ErrorPage(err)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ func (this *IndexAction) RunGet(params struct {
 | 
			
		||||
}) {
 | 
			
		||||
	// 列出所有阈值
 | 
			
		||||
	thresholdsResp, err := this.RPC().NodeThresholdRPC().FindAllEnabledNodeThresholds(this.AdminContext(), &pb.FindAllEnabledNodeThresholdsRequest{
 | 
			
		||||
		Role:          "node",
 | 
			
		||||
		NodeClusterId: params.ClusterId,
 | 
			
		||||
		NodeId:        0,
 | 
			
		||||
	})
 | 
			
		||||
@@ -33,16 +34,25 @@ func (this *IndexAction) RunGet(params struct {
 | 
			
		||||
 | 
			
		||||
	thresholdMaps := []maps.Map{}
 | 
			
		||||
	for _, threshold := range thresholdsResp.NodeThresholds {
 | 
			
		||||
		var nodeMap maps.Map = nil
 | 
			
		||||
		if threshold.Node != nil {
 | 
			
		||||
			nodeMap = maps.Map{
 | 
			
		||||
				"id":   threshold.Node.Id,
 | 
			
		||||
				"name": threshold.Node.Name,
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		thresholdMaps = append(thresholdMaps, maps.Map{
 | 
			
		||||
			"id":               threshold.Id,
 | 
			
		||||
			"itemName":         nodeconfigs.FindNodeValueItemName(threshold.Item),
 | 
			
		||||
			"paramName":        nodeconfigs.FindNodeValueItemParamName(threshold.Item, threshold.Param),
 | 
			
		||||
			"operatorName":     nodeconfigs.FindNodeValueOperatorName(threshold.Operator),
 | 
			
		||||
			"value":            string(threshold.ValueJSON),
 | 
			
		||||
			"value":            nodeconfigs.UnmarshalNodeValue(threshold.ValueJSON),
 | 
			
		||||
			"sumMethodName":    nodeconfigs.FindNodeValueSumMethodName(threshold.SumMethod),
 | 
			
		||||
			"duration":         threshold.Duration,
 | 
			
		||||
			"durationUnitName": nodeconfigs.FindNodeValueDurationUnitName(threshold.DurationUnit),
 | 
			
		||||
			"isOn":             threshold.IsOn,
 | 
			
		||||
			"node":             nodeMap,
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	this.Data["thresholds"] = thresholdMaps
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@ func (this *UpdatePopupAction) RunGet(params struct {
 | 
			
		||||
		"item":           threshold.Item,
 | 
			
		||||
		"param":          threshold.Param,
 | 
			
		||||
		"message":        threshold.Message,
 | 
			
		||||
		"notifyDuration": threshold.NotifyDuration,
 | 
			
		||||
		"value":          nodeconfigs.UnmarshalNodeValue(threshold.ValueJSON),
 | 
			
		||||
		"operator":       threshold.Operator,
 | 
			
		||||
		"duration":       threshold.Duration,
 | 
			
		||||
@@ -70,6 +71,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
 | 
			
		||||
	Duration       int32
 | 
			
		||||
	DurationUnit   string
 | 
			
		||||
	Message        string
 | 
			
		||||
	NotifyDuration int32
 | 
			
		||||
	IsOn           bool
 | 
			
		||||
 | 
			
		||||
	Must *actions.Must
 | 
			
		||||
@@ -89,6 +91,7 @@ func (this *UpdatePopupAction) RunPost(params struct {
 | 
			
		||||
		Operator:        params.Operator,
 | 
			
		||||
		ValueJSON:       valueJSON,
 | 
			
		||||
		Message:         params.Message,
 | 
			
		||||
		NotifyDuration:  params.NotifyDuration,
 | 
			
		||||
		Duration:        params.Duration,
 | 
			
		||||
		DurationUnit:    params.DurationUnit,
 | 
			
		||||
		SumMethod:       params.SumMethod,
 | 
			
		||||
 
 | 
			
		||||
@@ -197,6 +197,7 @@ func (this *ClusterHelper) checkThresholds(clusterId int64) (bool, error) {
 | 
			
		||||
		return false, err
 | 
			
		||||
	}
 | 
			
		||||
	resp, err := rpcClient.NodeThresholdRPC().CountAllEnabledNodeThresholds(rpcClient.Context(0), &pb.CountAllEnabledNodeThresholdsRequest{
 | 
			
		||||
		Role:          "node",
 | 
			
		||||
		NodeClusterId: clusterId,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
	<span class="item">|</span>
 | 
			
		||||
	<menu-item :href="'/clusters/cluster/node?clusterId=' + clusterId + '&nodeId=' + nodeId" code="node">节点详情</menu-item>
 | 
			
		||||
    <menu-item :href="'/clusters/cluster/node/monitor?clusterId=' + clusterId + '&nodeId=' + nodeId" code="monitor" v-if="teaIsPlus">监控图表</menu-item>
 | 
			
		||||
    <menu-item :href="'/clusters/cluster/node/thresholds?clusterId=' + clusterId + '&nodeId=' + nodeId" code="threshold" v-if="teaIsPlus">阈值设置</menu-item>
 | 
			
		||||
    <menu-item :href="'/clusters/cluster/node/logs?clusterId=' + clusterId + '&nodeId=' + nodeId" code="log">运行日志</menu-item>
 | 
			
		||||
	<menu-item :href="'/clusters/cluster/node/update?clusterId=' + clusterId + '&nodeId=' + nodeId" code="update">修改设置</menu-item>
 | 
			
		||||
	<menu-item :href="'/clusters/cluster/node/install?clusterId=' + clusterId + '&nodeId=' + nodeId" code="install">安装节点</menu-item>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,10 +6,10 @@
 | 
			
		||||
<script type="text/javascript" src="/js/echarts/echarts.min.js"></script>
 | 
			
		||||
{$end}
 | 
			
		||||
 | 
			
		||||
<h4>上行流量</h4>
 | 
			
		||||
<h4>上行流量(字节)</h4>
 | 
			
		||||
<div class="chart-box" id="traffic-in-chart"></div>
 | 
			
		||||
 | 
			
		||||
<h4>下行流量</h4>
 | 
			
		||||
<h4>下行流量(字节)</h4>
 | 
			
		||||
<div class="chart-box" id="traffic-out-chart"></div>
 | 
			
		||||
 | 
			
		||||
<h4>连接数</h4>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,37 @@
 | 
			
		||||
{$layout}
 | 
			
		||||
{$template "../node_menu"}
 | 
			
		||||
 | 
			
		||||
<div style="margin-top: -1em">
 | 
			
		||||
    <second-menu>
 | 
			
		||||
        <menu-item @click.prevent="createThreshold">添加阈值</menu-item>
 | 
			
		||||
    </second-menu>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
<p class="comment" v-if="thresholds.length == 0">暂时还没有设置阈值。</p>
 | 
			
		||||
<table class="ui table selectable celled" v-if="thresholds.length > 0">
 | 
			
		||||
    <thead>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <th>监控项</th>
 | 
			
		||||
            <th>参数</th>
 | 
			
		||||
            <th>操作符</th>
 | 
			
		||||
            <th>对比值</th>
 | 
			
		||||
            <th>统计时间段</th>
 | 
			
		||||
            <th class="two wide">状态</th>
 | 
			
		||||
            <th class="two op">操作</th>
 | 
			
		||||
        </tr>
 | 
			
		||||
    </thead>
 | 
			
		||||
    <tr v-for="threshold in thresholds">
 | 
			
		||||
        <td>{{threshold.itemName}}</td>
 | 
			
		||||
        <td>{{threshold.paramName}}</td>
 | 
			
		||||
        <td>{{threshold.operatorName}}</td>
 | 
			
		||||
        <td>{{threshold.value}}</td>
 | 
			
		||||
        <td>{{threshold.duration}}{{threshold.durationUnitName}}</td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <label-on :v-is-on="threshold.isOn"></label-on>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td>
 | 
			
		||||
            <a href="" @click.prevent="updateThreshold(threshold.id)">修改</a>  
 | 
			
		||||
            <a href="" @click.prevent="deleteThreshold(threshold.id)">删除</a>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
							
								
								
									
										41
									
								
								web/views/@default/clusters/cluster/node/thresholds/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								web/views/@default/clusters/cluster/node/thresholds/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
Tea.context(function () {
 | 
			
		||||
	this.createThreshold = function () {
 | 
			
		||||
		teaweb.popup(Tea.url("/clusters/cluster/settings/thresholds/createPopup", {
 | 
			
		||||
			clusterId: this.clusterId,
 | 
			
		||||
			nodeId: this.nodeId
 | 
			
		||||
		}), {
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					teaweb.reload()
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.updateThreshold = function (thresholdId) {
 | 
			
		||||
		teaweb.popup(Tea.url("/clusters/cluster/settings/thresholds/updatePopup", {
 | 
			
		||||
			thresholdId: thresholdId
 | 
			
		||||
		}), {
 | 
			
		||||
			callback: function () {
 | 
			
		||||
				teaweb.success("保存成功", function () {
 | 
			
		||||
					teaweb.reload()
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	this.deleteThreshold = function (thresholdId) {
 | 
			
		||||
		let that = this
 | 
			
		||||
		teaweb.confirm("确定要删除这个阈值吗?", function () {
 | 
			
		||||
			that.$post(".delete")
 | 
			
		||||
				.params({
 | 
			
		||||
					thresholdId: thresholdId
 | 
			
		||||
				})
 | 
			
		||||
				.success(function () {
 | 
			
		||||
					teaweb.success("删除成功", function () {
 | 
			
		||||
						teaweb.reload()
 | 
			
		||||
					})
 | 
			
		||||
				})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
})
 | 
			
		||||
@@ -4,6 +4,7 @@
 | 
			
		||||
<form class="ui form" data-tea-action="$" data-tea-success="success">
 | 
			
		||||
    <csrf-token></csrf-token>
 | 
			
		||||
    <input type="hidden" name="clusterId" :value="clusterId" />
 | 
			
		||||
    <input type="hidden" name="nodeId" :value="nodeId"/>
 | 
			
		||||
    <input type="hidden" name="sumMethod" value="avg"/>
 | 
			
		||||
 | 
			
		||||
    <table class="ui table definition selectable">
 | 
			
		||||
@@ -54,6 +55,10 @@
 | 
			
		||||
                </div>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td colspan="2"><more-options-indicator></more-options-indicator></td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tbody v-show="moreOptionsVisible">
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td>消息</td>
 | 
			
		||||
                <td>
 | 
			
		||||
@@ -61,6 +66,21 @@
 | 
			
		||||
                    <p class="comment">触发阈值时的消息提示。</p>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td>消息通知间隔</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <div class="ui fields inline">
 | 
			
		||||
                        <div class="ui field">
 | 
			
		||||
                            <input type="text" name="notifyDuration" value="10" style="width: 5em"/>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="ui field">
 | 
			
		||||
                            分钟
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <p class="comment">在此间隔内将不会重复发送跟此阈值相关的消息。</p>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <submit-btn></submit-btn>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@
 | 
			
		||||
    </first-menu>
 | 
			
		||||
 | 
			
		||||
    <p class="comment" v-if="thresholds.length == 0">暂时还没有设置阈值。</p>
 | 
			
		||||
    <table class="ui table selectable" v-if="thresholds.length > 0">
 | 
			
		||||
    <table class="ui table selectable celled" v-if="thresholds.length > 0">
 | 
			
		||||
        <thead>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <th>监控项</th>
 | 
			
		||||
@@ -20,10 +20,14 @@
 | 
			
		||||
            </tr>
 | 
			
		||||
        </thead>
 | 
			
		||||
        <tr v-for="threshold in thresholds">
 | 
			
		||||
            <td>{{threshold.itemName}}</td>
 | 
			
		||||
            <td>{{threshold.itemName}}
 | 
			
		||||
                <div v-if="threshold.node != null" style="margin-top: 0.3em">
 | 
			
		||||
                    <a :href="'/clusters/cluster/node/thresholds?clusterId=' + clusterId + '&nodeId=' + threshold.node.id" class="ui label basic tiny" title="节点专属阈值设置"><span class="small">节点:{{threshold.node.name}}</span></a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </td>
 | 
			
		||||
            <td>{{threshold.paramName}}</td>
 | 
			
		||||
            <td>{{threshold.operatorName}}</td>
 | 
			
		||||
            <td>{{threshold.itemName}}</td>
 | 
			
		||||
            <td>{{threshold.value}}</td>
 | 
			
		||||
            <td>{{threshold.duration}}{{threshold.durationUnitName}}</td>
 | 
			
		||||
            <td>
 | 
			
		||||
                <label-on :v-is-on="threshold.isOn"></label-on>
 | 
			
		||||
 
 | 
			
		||||
@@ -54,6 +54,10 @@
 | 
			
		||||
                </div>
 | 
			
		||||
            </td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tr>
 | 
			
		||||
            <td colspan="2"><more-options-indicator></more-options-indicator></td>
 | 
			
		||||
        </tr>
 | 
			
		||||
        <tbody v-show="moreOptionsVisible">
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td>消息</td>
 | 
			
		||||
                <td>
 | 
			
		||||
@@ -61,12 +65,27 @@
 | 
			
		||||
                    <p class="comment">触发阈值时的消息提示。</p>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td>消息通知间隔</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <div class="ui fields inline">
 | 
			
		||||
                        <div class="ui field">
 | 
			
		||||
                            <input type="text" name="notifyDuration" v-model="threshold.notifyDuration" value="10" style="width: 5em"/>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div class="ui field">
 | 
			
		||||
                            分钟
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <p class="comment">在此间隔内将不会重复发送跟此阈值相关的消息。</p>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr>
 | 
			
		||||
                <td>是否启用</td>
 | 
			
		||||
                <td>
 | 
			
		||||
                    <checkbox name="isOn" value="1" v-model="threshold.isOn"></checkbox>
 | 
			
		||||
                </td>
 | 
			
		||||
            </tr>
 | 
			
		||||
        </tbody>
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <submit-btn></submit-btn>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user