Added code for handeling websocket data, And made the html code fariable in a js function
This commit is contained in:
115
web/index.html
115
web/index.html
@@ -1,5 +1,6 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<script src="https://cdn.plot.ly/plotly-latest.min.js" charset="utf-8"></script>
|
<script src="https://cdn.plot.ly/plotly-latest.min.js" charset="utf-8"></script>
|
||||||
@@ -23,8 +24,11 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
<div id="nodeDataLocation">
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Make a new flex container for the live data -->
|
<!-- Make a new flex container for the live data -->
|
||||||
<div class="nodeData">
|
<!-- <div class="nodeData">
|
||||||
|
|
||||||
<div class="flex-NodeData">
|
<div class="flex-NodeData">
|
||||||
<p>Node 1</p>
|
<p>Node 1</p>
|
||||||
@@ -51,120 +55,13 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Make a new flexcontainer for the graphs and API request time -->
|
|
||||||
<div class="flex-graph">
|
<div class="flex-graph">
|
||||||
<div>
|
<div>
|
||||||
<p>Live graph:</p>
|
<p>Live graph:</p>
|
||||||
<div id="liveGraph"></div>
|
<div id="liveGraph"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> -->
|
||||||
|
|
||||||
<div class="flex-NodeData">
|
|
||||||
<p>Node 2</p>
|
|
||||||
<div class="flex-LiveData">
|
|
||||||
<div>
|
|
||||||
<div>Temperatuur: <p id="temperature">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="tempStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div>Luchtvochtigheid: <p id="humidity">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="humidStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div>Lichtintensiteit: <p id="lightIntensity">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="lightIntensityStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Make a new flexcontainer for the graphs and API request time -->
|
|
||||||
<div class="flex-graph">
|
|
||||||
<div>
|
|
||||||
<p>Live graph:</p>
|
|
||||||
<div id="liveGraph2"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> <!-- class="nodeData" -->
|
|
||||||
<div class="nodeData">
|
|
||||||
<div class="flex-NodeData">
|
|
||||||
<p>Node 3</p>
|
|
||||||
<div class="flex-LiveData">
|
|
||||||
<div>
|
|
||||||
<div>Temperatuur: <p id="temperature">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="tempStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div>Luchtvochtigheid: <p id="humidity">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="humidStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div>Lichtintensiteit: <p id="lightIntensity">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="lightIntensityStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Make a new flexcontainer for the graphs and API request time -->
|
|
||||||
<div class="flex-graph">
|
|
||||||
<div>
|
|
||||||
<p>Live graph:</p>
|
|
||||||
<div id="liveGraph3"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> <div class="flex-NodeData">
|
|
||||||
<p>Node 4</p>
|
|
||||||
<div class="flex-LiveData">
|
|
||||||
<div>
|
|
||||||
<div>Temperatuur: <p id="temperature">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="tempStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div>Luchtvochtigheid: <p id="humidity">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="humidStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div>Lichtintensiteit: <p id="lightIntensity">Not connected</p>
|
|
||||||
</div>
|
|
||||||
<div class="statusElement">
|
|
||||||
<p class="statusText" id="lightIntensityStatus">Not connected</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Make a new flexcontainer for the graphs and API request time -->
|
|
||||||
<div class="flex-graph">
|
|
||||||
<div>
|
|
||||||
<p>Live graph:</p>
|
|
||||||
<div id="liveGraph4"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> <!-- class="nodeData" -->
|
|
||||||
|
|
||||||
<!-- Include the js file -->
|
<!-- Include the js file -->
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
|
282
web/main.js
282
web/main.js
@@ -6,25 +6,105 @@ let newArrayTemp = [];
|
|||||||
let newArrayHumid = [];
|
let newArrayHumid = [];
|
||||||
let newArrayLight = [];
|
let newArrayLight = [];
|
||||||
let timeArray = []; // Array to store time values`
|
let timeArray = []; // Array to store time values`
|
||||||
let dateArray = [1, 2, 3];
|
|
||||||
let valueArray = [1, 2, 3, 4, 5];
|
let valueArray = [1, 2, 3, 4, 5];
|
||||||
let valueArray2 = [1, 2, 3, 4, 5];
|
|
||||||
let valueArray3 = [1, 2, 3, 4, 5];
|
|
||||||
let valueArray4 = [1, 2, 3, 4, 5];
|
|
||||||
let newValueArray = [4, 5, 6];
|
let newValueArray = [4, 5, 6];
|
||||||
let myValue = 1;
|
let myValue = 1;
|
||||||
let intervalDelay = 50;
|
let intervalDelay = 50;
|
||||||
|
|
||||||
//const timeArray = [1,2,3,4];
|
// const socket = new WebSocket("ws://127.0.0.1:8001");
|
||||||
//const dateArray = [5,6,7,8];
|
|
||||||
//const valueArray = [1,1,1,3];
|
// Create WebSocket connection.
|
||||||
|
const socket = new WebSocket("ws://145.92.8.114/ws");
|
||||||
|
|
||||||
|
/*
|
||||||
|
function openConnection() {
|
||||||
|
// Connection opened
|
||||||
|
socket.addEventListener("open", (event) => {
|
||||||
|
console.log("Connected to the WebSocket server");
|
||||||
|
socket.send("Hello Server!");
|
||||||
|
});}
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
socket.addEventListener('error', (event) => {
|
||||||
|
console.error('WebSocket error:', event);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Message handling
|
||||||
|
socket.addEventListener("message", (event) => {
|
||||||
|
console.log('Message from server:', event.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
openConnection();
|
||||||
|
*//////////////////////
|
||||||
|
|
||||||
|
function openConnection() {
|
||||||
|
// Open connection
|
||||||
|
socket.addEventListener("open", (event) => {
|
||||||
|
console.log("Connected to the WebSocket server");
|
||||||
|
socket.send("Hello Server!");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Error handling
|
||||||
|
socket.addEventListener('error', (event) => {
|
||||||
|
console.error('WebSocket error:', event);
|
||||||
|
// Attempt to reconnect
|
||||||
|
setTimeout(openConnection, 1000); // Retry after 1 second
|
||||||
|
});
|
||||||
|
|
||||||
|
// Message handling
|
||||||
|
socket.addEventListener("message", (event) => {
|
||||||
|
console.log('Message from server:', event.data);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close handling
|
||||||
|
socket.addEventListener('close', (event) => {
|
||||||
|
console.log('Connection closed');
|
||||||
|
// Attempt to reconnect
|
||||||
|
setTimeout(openConnection, 1000); // Retry after 1 second
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open the connection
|
||||||
|
openConnection();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// socket.onopen = function(e) {
|
||||||
|
// alert("[open] Connection established");
|
||||||
|
// alert("Sending to server");
|
||||||
|
// socket.send("My name is John");
|
||||||
|
// };
|
||||||
|
|
||||||
|
// socket.onmessage = function(event) {
|
||||||
|
// // alert(`[message] Data received from server: ${event.data}`);
|
||||||
|
// console.log("Data received from server: ", event.data);
|
||||||
|
// };
|
||||||
|
|
||||||
|
// socket.addEventListener("message", (event) => {
|
||||||
|
// console.log(event.data);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// function openPort() {
|
||||||
|
// socket.addEventListener('open', function (event) {
|
||||||
|
// console.log('Connected to the WebSocket server');
|
||||||
|
// });
|
||||||
|
// console.log("Connected to the WebSocket server");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// socket.addEventListener('message', function (event) {
|
||||||
|
// console.log('Message from server:', event.data);
|
||||||
|
// // Here you can handle the received message and update your UI accordingly
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
function pushArray(array) {
|
function pushArray(array) {
|
||||||
for (let i = 0; i < 10; i++) {
|
for (let i = 0; i < 10; i++) {
|
||||||
array.push(Math.random() * 10);
|
array.push(Math.random() * 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Make lines in the graph of the live data
|
// Make lines in the graph of the live data
|
||||||
Plotly.plot("liveGraph", [
|
/*Plotly.plot("liveGraph", [
|
||||||
{
|
{
|
||||||
x: timeArray, // Use timeArray as x values
|
x: timeArray, // Use timeArray as x values
|
||||||
y: valueArray,
|
y: valueArray,
|
||||||
@@ -34,41 +114,6 @@ Plotly.plot("liveGraph", [
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Make lines in the graph of the live data
|
|
||||||
Plotly.plot("liveGraph2", [
|
|
||||||
{
|
|
||||||
x: timeArray, // Use timeArray as x values
|
|
||||||
y: valueArray2,
|
|
||||||
mode: "lines",
|
|
||||||
line: { color: "#80CAF6" },
|
|
||||||
name: "Temperature",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Make lines in the graph of the live data
|
|
||||||
Plotly.plot("liveGraph3", [
|
|
||||||
{
|
|
||||||
x: timeArray, // Use timeArray as x values
|
|
||||||
y: valueArray3,
|
|
||||||
mode: "lines",
|
|
||||||
line: { color: "#80CAF6" },
|
|
||||||
name: "Temperature",
|
|
||||||
},
|
|
||||||
]);// Make lines in the graph of the live data
|
|
||||||
Plotly.plot("liveGraph4", [
|
|
||||||
{
|
|
||||||
x: timeArray, // Use timeArray as x values
|
|
||||||
y: valueArray4,
|
|
||||||
mode: "lines",
|
|
||||||
line: { color: "#80CAF6" },
|
|
||||||
name: "Temperature",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
// Make lines in the graph of the live data
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let cnt = 0;
|
let cnt = 0;
|
||||||
|
|
||||||
// Update the graph every 1 ms
|
// Update the graph every 1 ms
|
||||||
@@ -97,80 +142,111 @@ let interval = setInterval(function () {
|
|||||||
if (cnt === 10) clearInterval(interval);
|
if (cnt === 10) clearInterval(interval);
|
||||||
}, intervalDelay);
|
}, intervalDelay);
|
||||||
|
|
||||||
// Update the graph every 1 ms
|
*/
|
||||||
let interval2 = setInterval(function () {
|
|
||||||
var time = new Date();
|
|
||||||
timeArray.push(new Date());
|
|
||||||
|
|
||||||
pushArray(valueArray2);
|
//function for making the html elements for the following html code
|
||||||
|
|
||||||
var update = {
|
function nodeData(data, node) {
|
||||||
x: [[time]],
|
let nodeData = document.createElement("div");
|
||||||
y: [[newValueArray]],
|
nodeData.innerHTML = data;
|
||||||
};
|
// nodeData.setAttribute("id", "node" + node);
|
||||||
|
document.body.appendChild(nodeData);
|
||||||
|
// console.log("Hello World");
|
||||||
|
}
|
||||||
|
|
||||||
var olderTime = time.setMinutes(time.getMinutes() - 1);
|
// nodeData("Temperature: ", 1);
|
||||||
var futureTime = time.setMinutes(time.getMinutes() + 1);
|
// nodeData("Humidity: ", 2);
|
||||||
|
|
||||||
var minuteView = {
|
|
||||||
xaxis: {
|
|
||||||
type: "date",
|
|
||||||
range: [olderTime, futureTime],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Plotly.relayout("liveGraph2", minuteView);
|
|
||||||
|
|
||||||
if (cnt === 1000) clearInterval(interval2);
|
function createNodeData(node) {
|
||||||
}, intervalDelay);
|
// Create main div
|
||||||
|
var nodeData = document.createElement("div");
|
||||||
|
nodeData.className = "nodeData";
|
||||||
|
|
||||||
// Update the graph every 1 ms
|
// Create flex-NodeData div
|
||||||
let interval3 = setInterval(function () {
|
var flexNodeData = document.createElement("div");
|
||||||
var time = new Date();
|
flexNodeData.className = "flex-NodeData";
|
||||||
timeArray.push(new Date());
|
|
||||||
|
|
||||||
pushArray(valueArray3);
|
// Create p element
|
||||||
|
var pNode = document.createElement("p");
|
||||||
|
pNode.textContent = "Node " + node;
|
||||||
|
|
||||||
var update = {
|
// Append p to flex-NodeData
|
||||||
x: [[time]],
|
flexNodeData.appendChild(pNode);
|
||||||
y: [[newValueArray]],
|
|
||||||
};
|
|
||||||
|
|
||||||
var olderTime = time.setMinutes(time.getMinutes() - 1);
|
// Create flex-LiveData div
|
||||||
var futureTime = time.setMinutes(time.getMinutes() + 1);
|
var flexLiveData = document.createElement("div");
|
||||||
|
flexLiveData.className = "flex-LiveData";
|
||||||
|
|
||||||
var minuteView = {
|
// Create data divs (Temperature, Humidity, Light Intensity)
|
||||||
xaxis: {
|
var dataTypes = ["Temperatuur", "Luchtvochtigheid", "Lichtintensiteit"];
|
||||||
type: "date",
|
var ids = ["temperature", "humidity", "lightIntensity"];
|
||||||
range: [olderTime, futureTime],
|
var statusIds = ["tempStatus", "humidStatus", "lightIntensityStatus"];
|
||||||
},
|
|
||||||
};
|
|
||||||
Plotly.relayout("liveGraph3", minuteView);
|
|
||||||
|
|
||||||
if (cnt === 1000) clearInterval(interval3);
|
for (var i = 0; i < dataTypes.length; i++) {
|
||||||
}, intervalDelay);
|
var dataDiv = document.createElement("div");
|
||||||
|
|
||||||
// Update the graph every 1 ms
|
var dataTypeDiv = document.createElement("div");
|
||||||
let interval4 = setInterval(function () {
|
dataTypeDiv.textContent = dataTypes[i] + ": ";
|
||||||
var time = new Date();
|
|
||||||
timeArray.push(new Date());
|
|
||||||
|
|
||||||
pushArray(valueArray4);
|
var pElement = document.createElement("p");
|
||||||
|
pElement.id = ids[i];
|
||||||
|
pElement.textContent = "Not connected";
|
||||||
|
|
||||||
var update = {
|
dataTypeDiv.appendChild(pElement);
|
||||||
x: [[time]],
|
dataDiv.appendChild(dataTypeDiv);
|
||||||
y: [[newValueArray]],
|
|
||||||
};
|
|
||||||
|
|
||||||
var olderTime = time.setMinutes(time.getMinutes() - 1);
|
var statusElement = document.createElement("div");
|
||||||
var futureTime = time.setMinutes(time.getMinutes() + 1);
|
statusElement.className = "statusElement";
|
||||||
|
|
||||||
var minuteView = {
|
var statusText = document.createElement("p");
|
||||||
xaxis: {
|
statusText.className = "statusText";
|
||||||
type: "date",
|
statusText.id = statusIds[i];
|
||||||
range: [olderTime, futureTime],
|
statusText.textContent = "Not connected";
|
||||||
},
|
|
||||||
};
|
|
||||||
Plotly.relayout("liveGraph4", minuteView);
|
|
||||||
|
|
||||||
if (cnt === 1000) clearInterval(interval4);
|
statusElement.appendChild(statusText);
|
||||||
}, intervalDelay);
|
dataDiv.appendChild(statusElement);
|
||||||
|
|
||||||
|
flexLiveData.appendChild(dataDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append flex-LiveData to flex-NodeData
|
||||||
|
flexNodeData.appendChild(flexLiveData);
|
||||||
|
|
||||||
|
// Create flex-graph div
|
||||||
|
var flexGraph = document.createElement("div");
|
||||||
|
flexGraph.className = "flex-graph";
|
||||||
|
|
||||||
|
var graphDiv = document.createElement("div");
|
||||||
|
|
||||||
|
var graphP = document.createElement("p");
|
||||||
|
graphP.textContent = "Live graph:";
|
||||||
|
|
||||||
|
var liveGraph = document.createElement("div");
|
||||||
|
liveGraph.id = "liveGraph";
|
||||||
|
|
||||||
|
graphDiv.appendChild(graphP);
|
||||||
|
graphDiv.appendChild(liveGraph);
|
||||||
|
flexGraph.appendChild(graphDiv);
|
||||||
|
|
||||||
|
// Append flex-graph to flex-NodeData
|
||||||
|
flexNodeData.appendChild(flexGraph);
|
||||||
|
|
||||||
|
// Append flex-NodeData to main div
|
||||||
|
nodeData.appendChild(flexNodeData);
|
||||||
|
|
||||||
|
// Check if nodeDataLocation element exists
|
||||||
|
var nodeDataLocation = document.getElementById("nodeDataLocation");
|
||||||
|
if (nodeDataLocation) {
|
||||||
|
// Append main div to nodeDataLocation
|
||||||
|
nodeDataLocation.appendChild(nodeData);
|
||||||
|
} else {
|
||||||
|
console.error("Element with ID 'nodeDataLocation' does not exist.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call the function to create the HTML structure
|
||||||
|
createNodeData(1);
|
||||||
|
createNodeData(2);
|
||||||
|
createNodeData(3);
|
||||||
|
createNodeData(4);
|
@@ -43,21 +43,56 @@ p1 {
|
|||||||
border: solid #1f82d3 2px;
|
border: solid #1f82d3 2px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
width: 90%;
|
width: 90%;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.statusText{
|
.statusText{
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* body{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-content: center;
|
||||||
|
} */
|
||||||
|
|
||||||
|
#randomShit{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
align-content: center;
|
||||||
|
border: 2px solid purple;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#nodeDataLocation{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
/* justify-content: center; */
|
||||||
|
/* align-content: center; */
|
||||||
|
border: 4px solid blue;
|
||||||
|
/* padding-bottom: 50%; */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.flex-NodeData {
|
.flex-NodeData {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-left: 1%;
|
margin-left: 1%;
|
||||||
margin-right: 1%;
|
margin-right: 1%;
|
||||||
width: 50%;
|
justify-content: space-evenly;
|
||||||
height: 40%;
|
/* height: 40%; */
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: 3px solid #1f82d3;
|
border: 3px solid #1f82d3;
|
||||||
border-radius: 20px;
|
/* border-radius: 20px; */
|
||||||
|
/* border: 2px solid red; */
|
||||||
|
/* margin-right: 90%; */
|
||||||
|
/* width: 150vh; */
|
||||||
|
/* padding-right: 40%; */
|
||||||
|
/* padding-left: 40%; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.nodeData {
|
.nodeData {
|
||||||
@@ -78,6 +113,8 @@ justify-content: left;
|
|||||||
justify-content: space-evenly;
|
justify-content: space-evenly;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -89,6 +126,8 @@ justify-content: left;
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
width: 30%;
|
width: 30%;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex-graph {
|
.flex-graph {
|
||||||
|
Reference in New Issue
Block a user