#37 Working Joining and Leaving
This commit is contained in:
@@ -1,98 +1,13 @@
|
||||
// Modules
|
||||
const { SlashCommandBuilder } = require('discord.js');
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder");
|
||||
const { getMembersInRole, getAllClientIds, filterAutocompleteValues, getKeyByArrayValue } = require("../utilities/utils");
|
||||
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
|
||||
const { getOnlineNodes, updateNodeInfo, addNodeConnection, getConnectionByNodeId, getAllConnections } = require("../utilities/mysqlHandler");
|
||||
const { filterAutocompleteValues } = require("../utilities/utils");
|
||||
const { getOnlineNodes, getAllConnections } = require("../utilities/mysqlHandler");
|
||||
const { joinServerWrapper } = require("../controllers/adminController");
|
||||
|
||||
// Global Vars
|
||||
const log = new DebugBuilder("server", "join");
|
||||
|
||||
/**
|
||||
* * This wrapper will check if there is an available node with the requested preset and if so checks for an available client ID to join with
|
||||
*
|
||||
* @param {*} presetName The preset name to listen to on the client
|
||||
* @param {*} channelId The channel ID to join the bot to
|
||||
* @param {*} connections EITHER A collection of clients that are currently connected OR a single discord client ID (NOT dev portal ID) that should be used to join the server with
|
||||
* @param {number} nodeId [OPTIONAL] The node ID to join with (will join with another node if given node is not available)
|
||||
* @returns
|
||||
*/
|
||||
async function joinServerWrapper(presetName, channelId, connections, nodeId = 0) {
|
||||
// Get nodes online
|
||||
var onlineNodes = await new Promise((recordResolve, recordReject) => {
|
||||
getOnlineNodes((nodeRows) => {
|
||||
recordResolve(nodeRows);
|
||||
});
|
||||
});
|
||||
|
||||
// Check which nodes have the selected preset
|
||||
onlineNodes = onlineNodes.filter(node => node.presets.includes(presetName));
|
||||
log.DEBUG("Filtered Online Nodes: ", onlineNodes);
|
||||
|
||||
// Check if any nodes with this preset are available
|
||||
var nodesCurrentlyAvailable = [];
|
||||
for (const node of onlineNodes) {
|
||||
const currentConnection = await getConnectionByNodeId(node.id);
|
||||
log.DEBUG("Checking to see if there is a connection for Node: ", node, currentConnection);
|
||||
if(!currentConnection) nodesCurrentlyAvailable.push(node);
|
||||
}
|
||||
log.DEBUG("Nodes Currently Available: ", nodesCurrentlyAvailable);
|
||||
|
||||
// If not, let the user know
|
||||
if (!nodesCurrentlyAvailable.length > 0) return Error("All nodes with this channel are unavailable, consider swapping one of the currently joined bots.");
|
||||
|
||||
// If so, join with the first node
|
||||
var availableClientIds = await getAllClientIds();
|
||||
log.DEBUG("All clients: ", Object.keys(availableClientIds));
|
||||
|
||||
var selectedClientId;
|
||||
if (typeof connections === 'string') {
|
||||
for (const availableClientId of availableClientIds) {
|
||||
if (availableClientId.discordId != connections ) selectedClientId = availableClientId;
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.DEBUG("Open connections: ", connections);
|
||||
for (const connection of connections) {
|
||||
log.DEBUG("Used Client ID: ", connection);
|
||||
availableClientIds = availableClientIds.filter(cid => cid.discordId != connection.clientObject.discordId);
|
||||
}
|
||||
|
||||
log.DEBUG("Available Client IDs: ", availableClientIds);
|
||||
|
||||
if (!Object.keys(availableClientIds).length > 0) return log.ERROR("All client ID have been used, consider swapping one of the curretly joined bots or adding more Client IDs to the pool.")
|
||||
selectedClientId = availableClientIds[0];
|
||||
}
|
||||
|
||||
let selectedNode;
|
||||
if (nodeId > 0) selectedNode = getKeyByArrayValue(nodesCurrentlyAvailable, nodeId);
|
||||
|
||||
if (!selectedNode) selectedNode = nodesCurrentlyAvailable[0];
|
||||
|
||||
const reqOptions = new requestOptions("/bot/join", "POST", selectedNode.ip, selectedNode.port);
|
||||
const postObject = {
|
||||
"channelId": channelId,
|
||||
"clientId": selectedClientId.clientId,
|
||||
"presetName": presetName
|
||||
};
|
||||
log.INFO("Post Object: ", postObject);
|
||||
sendHttpRequest(reqOptions, JSON.stringify(postObject), async (responseObj) => {
|
||||
log.VERBOSE("Response Object from node ", selectedNode, responseObj);
|
||||
if (!responseObj || !responseObj.statusCode == 200) return false;
|
||||
// Node has connected to discord
|
||||
// Updating node Object in DB
|
||||
const updatedNode = await updateNodeInfo(selectedNode);
|
||||
log.DEBUG("Updated Node: ", updatedNode);
|
||||
|
||||
// Adding a new node connection
|
||||
const nodeConnection = await addNodeConnection(selectedNode, selectedClientId);
|
||||
log.DEBUG("Node Connection: ", nodeConnection);
|
||||
});
|
||||
|
||||
return selectedClientId;
|
||||
}
|
||||
exports.joinServerWrapper = joinServerWrapper;
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('join')
|
||||
|
||||
@@ -2,41 +2,12 @@
|
||||
const { SlashCommandBuilder } = require('discord.js');
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder");
|
||||
const { getAllClientIds, getKeyByArrayValue, filterAutocompleteValues } = require("../utilities/utils");
|
||||
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
|
||||
const { checkNodeConnectionByClientId, removeNodeConnectionByNodeId, getAllConnections } = require('../utilities/mysqlHandler');
|
||||
const { getAllConnections } = require('../utilities/mysqlHandler');
|
||||
const { leaveServerWrapper } = require('../controllers/adminController');
|
||||
|
||||
// Global Vars
|
||||
const log = new DebugBuilder("server", "leave");
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} clientIdObject The client ID object for the node to leave the server. Either 'clientId'||'name' can be set.
|
||||
* @returns
|
||||
*/
|
||||
async function leaveServerWrapper(clientIdObject) {
|
||||
if (!clientIdObject.clientId || !clientIdObject.name) return log.ERROR("Tried to leave server without client ID and/or Name");
|
||||
|
||||
const node = await checkNodeConnectionByClientId(clientIdObject);
|
||||
|
||||
reqOptions = new requestOptions("/bot/leave", "POST", node.ip, node.port);
|
||||
|
||||
const responseObj = await new Promise((recordResolve, recordReject) => {
|
||||
sendHttpRequest(reqOptions, JSON.stringify({}), async (responseObj) => {
|
||||
recordResolve(responseObj);
|
||||
});
|
||||
});
|
||||
|
||||
log.VERBOSE("Response Object from node ", node, responseObj);
|
||||
if (!responseObj || !responseObj.statusCode == 202) return false;
|
||||
// Node has disconnected from discor
|
||||
// Removing the node connection from the DB
|
||||
const removedConnection = removeNodeConnectionByNodeId(node.id);
|
||||
log.DEBUG("Removed Node Connection: ", removedConnection);
|
||||
|
||||
return;
|
||||
}
|
||||
exports.leaveServerWrapper = leaveServerWrapper;
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('leave')
|
||||
@@ -64,7 +35,6 @@ module.exports = {
|
||||
log.DEBUG("Client names: ", clinetIds);
|
||||
const clientDiscordId = getKeyByArrayValue(clinetIds, {'name': botName});
|
||||
log.DEBUG("Selected bot: ", clinetIds[clientDiscordId]);
|
||||
// Need to create a table in DB to keep track of what bots have what IDs or an endpoint on the clients to return what ID they are running with
|
||||
await leaveServerWrapper(clinetIds[clientDiscordId]);
|
||||
|
||||
await interaction.editReply(`**${clinetIds[clientDiscordId].name}** has been disconnected`); // This will reply to the initial interaction
|
||||
|
||||
@@ -4,12 +4,9 @@ require('dotenv').config();
|
||||
const { DebugBuilder } = require("../utilities/debugBuilder.js");
|
||||
const log = new DebugBuilder("server", "adminController");
|
||||
// Utilities
|
||||
const mysqlHandler = require("../utilities/mysqlHandler");
|
||||
const utils = require("../utilities/utils");
|
||||
const requests = require("../utilities/httpRequests");
|
||||
const { leaveServerWrapper } = require("../commands/leave");
|
||||
const { joinServerWrapper } = require("../commands/join");
|
||||
|
||||
const { getAllClientIds } = require("../utilities/utils");
|
||||
const { getOnlineNodes, updateNodeInfo, addNodeConnection, getConnectionByNodeId, getNodeInfoFromId, checkNodeConnectionByClientId, removeNodeConnectionByNodeId } = require("../utilities/mysqlHandler");
|
||||
const { requestOptions, sendHttpRequest } = require("../utilities/httpRequests");
|
||||
|
||||
/** Get the presets of all online nodes, can be used for functions
|
||||
*
|
||||
@@ -17,15 +14,15 @@ const { joinServerWrapper } = require("../commands/join");
|
||||
* @returns {*} A list of the systems online
|
||||
*/
|
||||
async function getPresetsOfOnlineNodes(callback) {
|
||||
mysqlHandler.getOnlineNodes((onlineNodes) => {
|
||||
getOnlineNodes((onlineNodes) => {
|
||||
return callback(onlineNodes);
|
||||
});
|
||||
}
|
||||
|
||||
async function getNodeBotStatus(nodeId, callback) {
|
||||
mysqlHandler.getNodeInfoFromId(nodeId, (nodeObject) =>{
|
||||
reqOptions = new requests.requestOptions("/bot/status", "GET", nodeObject.ip, nodeObject.port, undefined, 5);
|
||||
requests.sendHttpRequest(reqOptions, JSON.stringify({}), (responseObject) => {
|
||||
getNodeInfoFromId(nodeId, (nodeObject) =>{
|
||||
reqOptions = new requestOptions("/bot/status", "GET", nodeObject.ip, nodeObject.port, undefined, 5);
|
||||
sendHttpRequest(reqOptions, JSON.stringify({}), (responseObject) => {
|
||||
if (responseObject === false) {
|
||||
// Bot is joined
|
||||
}
|
||||
@@ -73,21 +70,141 @@ exports.joinPreset = async (req, res) => {
|
||||
|
||||
const joinedClient = await joinServerWrapper(preset, channelId, clientId, nodeId);
|
||||
if (!joinedClient) return res.send(400).json("No joined client");
|
||||
return res.send(200).json(joinedClient);
|
||||
return res.status(200).json(joinedClient);
|
||||
}
|
||||
|
||||
/** Request a node to join the server listening to a specific preset
|
||||
*
|
||||
* @param {*} req Express request parameter
|
||||
* @param {*} res Express response parameter
|
||||
* @var {*} req.body.clientId The ID of the client to disconnect
|
||||
* @var {*} req.body.nodeId The ID of the node to disconnect
|
||||
*/
|
||||
exports.leaveServer = async (req, res) => {
|
||||
if (!req.body.clientId) return res.status(400).json("No clientID specified");
|
||||
if (!req.body.nodeId) return res.status(400).json("No node ID specified");
|
||||
|
||||
const clientId = req.body.clientId;
|
||||
const nodeId = req.body.nodeId;
|
||||
const currentConnection = await getConnectionByNodeId(nodeId);
|
||||
log.DEBUG("Current Connection for node: ", currentConnection);
|
||||
|
||||
await leaveServerWrapper(clientId)
|
||||
await leaveServerWrapper(currentConnection.clientObject)
|
||||
|
||||
return res.send(200);
|
||||
}
|
||||
return res.status(200).json(currentConnection.clientObject.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* * This wrapper will check if there is an available node with the requested preset and if so checks for an available client ID to join with
|
||||
*
|
||||
* @param {*} presetName The preset name to listen to on the client
|
||||
* @param {*} channelId The channel ID to join the bot to
|
||||
* @param {*} connections EITHER A collection of clients that are currently connected OR a single discord client ID (NOT dev portal ID) that should be used to join the server with
|
||||
* @param {number} nodeId [OPTIONAL] The node ID to join with (will join with another node if given node is not available)
|
||||
* @returns
|
||||
*/
|
||||
async function joinServerWrapper(presetName, channelId, connections, nodeId = 0) {
|
||||
// Get nodes online
|
||||
var onlineNodes = await new Promise((recordResolve, recordReject) => {
|
||||
getOnlineNodes((nodeRows) => {
|
||||
recordResolve(nodeRows);
|
||||
});
|
||||
});
|
||||
|
||||
// Check which nodes have the selected preset
|
||||
onlineNodes = onlineNodes.filter(node => node.presets.includes(presetName));
|
||||
log.DEBUG("Filtered Online Nodes: ", onlineNodes);
|
||||
|
||||
// Check if any nodes with this preset are available
|
||||
var nodesCurrentlyAvailable = [];
|
||||
for (const node of onlineNodes) {
|
||||
const currentConnection = await getConnectionByNodeId(node.id);
|
||||
log.DEBUG("Checking to see if there is a connection for Node: ", node, currentConnection);
|
||||
if(!currentConnection) nodesCurrentlyAvailable.push(node);
|
||||
}
|
||||
log.DEBUG("Nodes Currently Available: ", nodesCurrentlyAvailable);
|
||||
|
||||
// If not, let the user know
|
||||
if (!nodesCurrentlyAvailable.length > 0) return Error("All nodes with this channel are unavailable, consider swapping one of the currently joined bots.");
|
||||
|
||||
// If so, join with the first node
|
||||
var availableClientIds = await getAllClientIds();
|
||||
log.DEBUG("All clients: ", Object.keys(availableClientIds));
|
||||
|
||||
var selectedClientId;
|
||||
if (typeof connections === 'string') {
|
||||
for (const availableClientId of availableClientIds) {
|
||||
if (availableClientId.discordId != connections ) selectedClientId = availableClientId;
|
||||
}
|
||||
}
|
||||
else {
|
||||
log.DEBUG("Open connections: ", connections);
|
||||
for (const connection of connections) {
|
||||
log.DEBUG("Used Client ID: ", connection);
|
||||
availableClientIds = availableClientIds.filter(cid => cid.discordId != connection.clientObject.discordId);
|
||||
}
|
||||
|
||||
log.DEBUG("Available Client IDs: ", availableClientIds);
|
||||
|
||||
if (!Object.keys(availableClientIds).length > 0) return log.ERROR("All client ID have been used, consider swapping one of the curretly joined bots or adding more Client IDs to the pool.")
|
||||
selectedClientId = availableClientIds[0];
|
||||
}
|
||||
|
||||
let selectedNode;
|
||||
if (nodeId > 0) {
|
||||
for(const availableNode of nodesCurrentlyAvailable){
|
||||
if (availableNode.id == nodeId) selectedNode = availableNode;
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedNode) selectedNode = nodesCurrentlyAvailable[0];
|
||||
|
||||
const reqOptions = new requestOptions("/bot/join", "POST", selectedNode.ip, selectedNode.port);
|
||||
const postObject = {
|
||||
"channelId": channelId,
|
||||
"clientId": selectedClientId.clientId,
|
||||
"presetName": presetName
|
||||
};
|
||||
log.INFO("Post Object: ", postObject);
|
||||
sendHttpRequest(reqOptions, JSON.stringify(postObject), async (responseObj) => {
|
||||
log.VERBOSE("Response Object from node ", selectedNode, responseObj);
|
||||
if (!responseObj || !responseObj.statusCode == 200) return false;
|
||||
// Node has connected to discord
|
||||
// Updating node Object in DB
|
||||
const updatedNode = await updateNodeInfo(selectedNode);
|
||||
log.DEBUG("Updated Node: ", updatedNode);
|
||||
|
||||
// Adding a new node connection
|
||||
const nodeConnection = await addNodeConnection(selectedNode, selectedClientId);
|
||||
log.DEBUG("Node Connection: ", nodeConnection);
|
||||
});
|
||||
|
||||
return selectedClientId;
|
||||
}
|
||||
exports.joinServerWrapper = joinServerWrapper;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} clientIdObject The client ID object for the node to leave the server. Either 'clientId'||'name' can be set.
|
||||
* @returns
|
||||
*/
|
||||
async function leaveServerWrapper(clientIdObject) {
|
||||
if (!clientIdObject.clientId || !clientIdObject.name) return log.ERROR("Tried to leave server without client ID and/or Name");
|
||||
|
||||
const node = await checkNodeConnectionByClientId(clientIdObject);
|
||||
|
||||
reqOptions = new requestOptions("/bot/leave", "POST", node.ip, node.port);
|
||||
|
||||
const responseObj = await new Promise((recordResolve, recordReject) => {
|
||||
sendHttpRequest(reqOptions, JSON.stringify({}), async (responseObj) => {
|
||||
recordResolve(responseObj);
|
||||
});
|
||||
});
|
||||
|
||||
log.VERBOSE("Response Object from node ", node, responseObj);
|
||||
if (!responseObj || !responseObj.statusCode == 202) return false;
|
||||
// Node has disconnected from discor
|
||||
// Removing the node connection from the DB
|
||||
const removedConnection = removeNodeConnectionByNodeId(node.id);
|
||||
log.DEBUG("Removed Node Connection: ", removedConnection);
|
||||
|
||||
return;
|
||||
}
|
||||
exports.leaveServerWrapper = leaveServerWrapper;
|
||||
@@ -192,7 +192,8 @@ exports.requestNodeCheckIn = async (req, res) => {
|
||||
if (!req.params.nodeId) return res.status(400).json("No Node ID supplied in request");
|
||||
const node = await getNodeInfoFromId(req.params.nodeId);
|
||||
if (!node) return res.status(400).json("No Node with the ID given");
|
||||
checkInWithNode(node);
|
||||
await checkInWithNode(node);
|
||||
res.sendStatus(200);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -38,6 +38,48 @@ function addFrequencyInput(system){
|
||||
document.getElementById(`frequencyRow_${system.replaceAll(" ", "_")}`).appendChild(colParent);
|
||||
}
|
||||
|
||||
function createToast(notificationMessage){
|
||||
const toastTitle = document.createElement('strong');
|
||||
toastTitle.classList.add('me-auto');
|
||||
toastTitle.appendChild(document.createTextNode("Server Notification"));
|
||||
|
||||
const toastTime = document.createElement('small');
|
||||
toastTime.appendChild(document.createTextNode(Date.now().toLocaleString()));
|
||||
|
||||
const toastClose = document.createElement('button');
|
||||
toastClose.type = 'button';
|
||||
toastClose.classList.add('btn-close');
|
||||
toastClose.ariaLabel = 'Close';
|
||||
toastClose.setAttribute('data-bs-dismiss', 'toast');
|
||||
|
||||
const toastHeader = document.createElement('div');
|
||||
toastHeader.classList.add('toast-header');
|
||||
toastHeader.appendChild(toastTitle);
|
||||
toastHeader.appendChild(toastTime);
|
||||
toastHeader.appendChild(toastClose);
|
||||
|
||||
|
||||
const toastMessage = document.createElement('p');
|
||||
toastMessage.classList.add("px-2");
|
||||
toastMessage.appendChild(document.createTextNode(notificationMessage));
|
||||
|
||||
const toastBody = document.createElement('div');
|
||||
toastBody.classList.add('toast-body');
|
||||
toastBody.appendChild(toastMessage);
|
||||
|
||||
const wrapperDiv = document.createElement('div');
|
||||
wrapperDiv.classList.add('toast');
|
||||
wrapperDiv.role ='alert';
|
||||
wrapperDiv.ariaLive = 'assertive';
|
||||
wrapperDiv.ariaAtomic = true;
|
||||
wrapperDiv.appendChild(toastHeader);
|
||||
wrapperDiv.appendChild(toastMessage);
|
||||
|
||||
document.getElementById("toastZone").appendChild(wrapperDiv);
|
||||
|
||||
$('.toast').toast('show');
|
||||
}
|
||||
|
||||
function checkInByNodeId(nodeId){
|
||||
const Http = new XMLHttpRequest();
|
||||
const url='/nodes/'+nodeId;
|
||||
@@ -46,5 +88,56 @@ function checkInByNodeId(nodeId){
|
||||
|
||||
Http.onreadystatechange = (e) => {
|
||||
console.log(Http.responseText)
|
||||
createToast(Http.responseText);
|
||||
}
|
||||
}
|
||||
|
||||
function joinServer(){
|
||||
const preset = document.getElementById("selectRadioPreset").value;
|
||||
const nodeId = document.getElementById("nodeId").value;
|
||||
const clientId = document.getElementById("inputDiscordClientId").value;
|
||||
const channelId = document.getElementById("inputDiscordChannelId").value;
|
||||
|
||||
const reqBody = {
|
||||
'preset': preset,
|
||||
'nodeId': nodeId,
|
||||
'clientId': clientId,
|
||||
'channelId': channelId
|
||||
};
|
||||
|
||||
console.log(reqBody);
|
||||
|
||||
const Http = new XMLHttpRequest();
|
||||
const url='/admin/join';
|
||||
Http.open("POST", url);
|
||||
Http.setRequestHeader("Content-Type", "application/json");
|
||||
Http.send(JSON.stringify(reqBody));
|
||||
|
||||
Http.onloadend = (e) => {
|
||||
const responseObject = JSON.parse(Http.responseText)
|
||||
console.log(Http.status);
|
||||
console.log(responseObject);
|
||||
createToast(`${responseObject.name} will join shortly`);
|
||||
$("#joinModal").modal('toggle');
|
||||
}
|
||||
}
|
||||
|
||||
function leaveServer(){
|
||||
const nodeId = document.getElementById("nodeId").value;
|
||||
const reqBody = {
|
||||
'nodeId': nodeId
|
||||
};
|
||||
|
||||
const Http = new XMLHttpRequest();
|
||||
const url='/admin/leave';
|
||||
Http.open("POST", url);
|
||||
Http.setRequestHeader("Content-Type", "application/json");
|
||||
Http.send(JSON.stringify(reqBody));
|
||||
|
||||
Http.onloadend = (e) => {
|
||||
const responseObject = JSON.parse(Http.responseText)
|
||||
console.log(Http.status);
|
||||
console.log(responseObject);
|
||||
createToast(`${responseObject} is leaving`);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +118,8 @@ class nodeObject {
|
||||
this.ip = _ip;
|
||||
this.port = _port;
|
||||
this.location = _location;
|
||||
this.nearbySystems = _nearbySystems;
|
||||
this.nearbySystems = _nearbySystems;
|
||||
if (this.nearbySystems) this.presets = Object.keys(_nearbySystems);
|
||||
this.online = _online;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<form>
|
||||
<div class="row gx-3 mb-3">
|
||||
<div class="">
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
<% } %>
|
||||
<hr>
|
||||
<!-- Join Server button-->
|
||||
<a type="button" class="btn btn-info <% if(!node.online) { %>disabled<% } %>" href="/join/<%=node.id%>">Join Server</a>
|
||||
<a type="button" class="btn btn-info <% if(!node.online) { %>disabled<% } %>" data-bs-toggle="modal" data-bs-target="#joinModal" href="#">Join Server</a>
|
||||
<!-- Leave Server button -->
|
||||
<a type="button" class="btn btn-danger <% if(!node.online) { %>disabled<% } %>" href="/leave/<%=node.id%>">Leave Server</a>
|
||||
<a type="button" class="btn btn-danger <% if(!node.online) { %>disabled<% } %>" href="#" onclick="leaveServer()">Leave Server</a>
|
||||
<!-- Checkin with client button -->
|
||||
<a type="button" class="btn btn-secondary" href="#" onclick="checkInByNodeId('<%=node.id%>')">Check-in with Node</a>
|
||||
</div>
|
||||
@@ -149,6 +149,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%- include('partials/joinModal.ejs', {'nearbySystems': node.nearbySystems}) %>
|
||||
<%- include('partials/bodyEnd.ejs') %>
|
||||
<script src="/res/js/node.js"></script>
|
||||
<%- include('partials/htmlFooter.ejs') %>
|
||||
@@ -2,5 +2,6 @@
|
||||
<html lang="en" data-bs-theme="auto">
|
||||
<%- include('head.ejs') %>
|
||||
<body>
|
||||
<div class="toast-container mx-2" id="toastZone"></div>
|
||||
<%- include('navbar.ejs') %>
|
||||
<%- include('sidebar.ejs') %>
|
||||
44
Server/views/partials/joinModal.ejs
Normal file
44
Server/views/partials/joinModal.ejs
Normal file
@@ -0,0 +1,44 @@
|
||||
<div class="modal fade" id="joinModal" tabindex="-1" aria-labelledby="joinModal" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="joinModal">Join Node <%=node.id%> to a Discord Server</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container">
|
||||
<div class="card mb-4">
|
||||
<div class="card-body">
|
||||
<form>
|
||||
<div class="row gx-3 mb-3">
|
||||
<div class="col-md-12">
|
||||
<label class="small mb-1" for="inputDiscordClientId">Discord Client ID:</label>
|
||||
<input class="form-control" id="inputDiscordClientId" type="text" value="" required></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row gx-3 mb-3">
|
||||
<div class="col-md-6">
|
||||
<label class="small mb-1" for="inputDiscordChannelId">Discord Channel ID:</label>
|
||||
<input class="form-control" id="inputDiscordChannelId" type="text" value="" required></input>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="small mb-1" for="selectRadioPreset">Selected Preset:</label>
|
||||
<select class="custom-select" id="selectRadioPreset">
|
||||
<% for(const system in nearbySystems) { %>
|
||||
<option value="<%=system%>"><%=system%></option>
|
||||
<% } %>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" onclick="joinServer()">Join</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user