Skip to content

Commit 3bbc48f

Browse files
improve UI and physical selection
1 parent 87cb6e1 commit 3bbc48f

File tree

9 files changed

+87
-23
lines changed

9 files changed

+87
-23
lines changed
1.11 MB
Loading

nebula/frontend/static/js/deployment/help-content.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const HelpContent = (function() {
44
const tooltipElements = {
55
'processHelpIcon': 'Process deployment allows you to deploy participants in the same machine using different processes.',
66
'dockerHelpIcon': 'Docker deployment allows you to deploy participants in different containers.',
7+
'physicalDevicesHelpIcon': 'Physical devices deployment allows you to deploy participants in physical devices.',
78
'architectureHelpIcon': architecture,
89
'topologyCustomIcon': topology.custom,
910
'topologyPredefinedIcon': topology.predefined,

nebula/frontend/static/js/deployment/main.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ const DeploymentManager = (function() {
3636
window.MobilityManager = MobilityManager;
3737
window.ReputationManager = ReputationManager;
3838
window.GraphSettings = GraphSettings;
39+
window.DeploymentManager = DeploymentManager;
40+
window.Utils = Utils;
3941
}
4042

4143
function getGraphWidth() {
@@ -71,7 +73,8 @@ const DeploymentManager = (function() {
7173
function setupDeploymentButtons() {
7274
const runBtn = document.getElementById("run-btn");
7375
if (runBtn) {
74-
runBtn.addEventListener("click", () => {
76+
runBtn.addEventListener("click", (event) => {
77+
event.stopPropagation();
7578
if (!validateScenario()) {
7679
return;
7780
}
@@ -81,6 +84,15 @@ const DeploymentManager = (function() {
8184
}
8285

8386
function validateScenario() {
87+
const physicalDevicesRadio = document.getElementById('physical-devices-radio');
88+
if (physicalDevicesRadio && physicalDevicesRadio.checked) {
89+
if (!window.lastPhysicalDevicesAlert || Date.now() - window.lastPhysicalDevicesAlert > 1000) {
90+
Utils.showAlert('danger', 'Physical devices deployment is not supported in this version');
91+
window.lastPhysicalDevicesAlert = Date.now();
92+
}
93+
return false;
94+
}
95+
8496
// Validate topology
8597
if (!TopologyManager.getData().nodes.length) {
8698
Utils.showAlert('error', 'Please create a topology with at least one node');
@@ -250,7 +262,8 @@ const DeploymentManager = (function() {
250262
}
251263

252264
return {
253-
initialize
265+
initialize,
266+
validateScenario
254267
};
255268
})();
256269

nebula/frontend/static/js/deployment/mobility.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const MobilityManager = {
5353
document.getElementById("mobility-btn").addEventListener("click", () => {
5454
mobilityOptionsDiv.style.display = "block";
5555
if (this.map) {
56-
this.addMapCircle();
56+
this.updateMapCircle();
5757
}
5858
});
5959

nebula/frontend/static/js/deployment/topology.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ const TopologyManager = (function() {
3838
generatePredefinedTopology();
3939
});
4040

41+
document.querySelectorAll('input[name="deploymentRadioOptions"]').forEach(radio => {
42+
radio.addEventListener('change', () => {
43+
if (Graph) {
44+
Graph.nodeThreeObject(node => createNodeObject(node));
45+
Graph.graphData(gData);
46+
}
47+
});
48+
});
49+
4150
// Add federation architecture change listener
4251
document.getElementById('federationArchitecture').addEventListener('change', function() {
4352
const federationType = this.value;
@@ -398,6 +407,15 @@ const TopologyManager = (function() {
398407
function createNodeObject(node) {
399408
let geometry;
400409
let main_color;
410+
const isPhysical = document.getElementById("physical-devices-radio").checked;
411+
412+
if (isPhysical) {
413+
const texture = new THREE.TextureLoader().load('/platform/static/images/physical-device.png');
414+
const spriteMaterial = new THREE.SpriteMaterial({ map: texture });
415+
const sprite = new THREE.Sprite(spriteMaterial);
416+
sprite.scale.set(20, 15, 0);
417+
return sprite;
418+
}
401419

402420
if (node.malicious) {
403421
geometry = new THREE.TorusGeometry(5, 2, 16, 100);

nebula/frontend/static/js/deployment/ui-controls.js

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,11 @@ const UIControls = (function() {
276276
}
277277

278278
async function handleDeployment() {
279+
// First check validation
280+
if (!window.DeploymentManager.validateScenario()) {
281+
return;
282+
}
283+
279284
const confirmModal = document.getElementById('confirm-modal');
280285
const confirmModalBody = document.getElementById('confirm-modal-body');
281286
const yesButton = document.getElementById("yes-button");
@@ -295,6 +300,11 @@ const UIControls = (function() {
295300
yesButton.disabled = false;
296301

297302
const modal = new bootstrap.Modal(confirmModal);
303+
304+
confirmModal.addEventListener('hidden.bs.modal', function () {
305+
cleanupModal(confirmModal);
306+
});
307+
298308
modal.show();
299309

300310
yesButton.onclick = async () => {
@@ -371,21 +381,25 @@ const UIControls = (function() {
371381

372382
// Add event listener for when modal is hidden
373383
infoModal.addEventListener('hidden.bs.modal', function () {
374-
document.querySelector(".overlay").style.display = "none";
375-
// Remove the modal backdrop
376-
const backdrop = document.querySelector('.modal-backdrop');
377-
if (backdrop) {
378-
backdrop.remove();
379-
}
380-
// Remove the modal-open class from body
381-
document.body.classList.remove('modal-open');
382-
document.body.style.overflow = '';
383-
document.body.style.paddingRight = '';
384+
cleanupModal(infoModal);
384385
});
385386

386387
modal.show();
387388
}
388389

390+
function cleanupModal(modal) {
391+
document.querySelector(".overlay").style.display = "none";
392+
// Remove the modal backdrop
393+
const backdrop = document.querySelector('.modal-backdrop');
394+
if (backdrop) {
395+
backdrop.remove();
396+
}
397+
// Remove the modal-open class from body
398+
document.body.classList.remove('modal-open');
399+
document.body.style.overflow = '';
400+
document.body.style.paddingRight = '';
401+
}
402+
389403
function hideLoadingIndicators() {
390404
document.querySelector(".overlay").style.display = "none";
391405
document.getElementById("spinner").style.display = "none";

nebula/frontend/static/js/deployment/utils.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
// Utility Functions Module
22
const Utils = (function() {
3-
function showAlert(type, message) {
4-
// Implementation of alert display
5-
console.log(`${type}: ${message}`);
6-
}
7-
83
function greaterThan0(input) {
94
const value = parseInt(input.value);
105
if(value < 1 && !isNaN(value)) {

nebula/frontend/templates/deployment.html

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,15 +206,18 @@ <h5 class="step-title">Deployment type</h5>
206206
<div class="form-check form-check-inline">
207207
<input class="form-check-input" type="radio" name="deploymentRadioOptions" id="docker-radio"
208208
value="docker" checked>
209-
<label class="form-check-label" for="docker-radio">Docker containers</label>
209+
<label class="form-check-label" for="docker-radio">Virtual devices</label>
210210
<small id="dockerHelp" class="form-text text-muted"></small>
211211
<i id="dockerHelpIcon" class="fa fa-info-circle" style="cursor: pointer;"></i>
212212
</small>
213213
</div>
214214
<div class="form-check form-check-inline">
215215
<input class="form-check-input" type="radio" name="deploymentRadioOptions" id="physical-devices-radio"
216-
value="physical" disabled>
216+
value="physical">
217217
<label class="form-check-label" for="physical-devices-radio">Physical devices</label>
218+
<small id="physicalDevicesHelp" class="form-text text-muted">
219+
<i id="physicalDevicesHelpIcon" class="fa fa-info-circle" style="cursor: pointer;"></i>
220+
</small>
218221
</div>
219222
</div>
220223
<div class="form-group row container-shadow tiny grey">
@@ -682,7 +685,7 @@ <h5 class="step-title">Scheme of mobility</h5>
682685
<div class="form-check form-check-inline">
683686
<select class="form-control" id="schemeMobilitySelect" name="schemeMobility"
684687
style="display: inline" disabled>
685-
<option value="random" selected>Random</option>
688+
<option value="random" selected>Realistic mobility</option>
686689
</select>
687690
</div>
688691
<h5 class="step-title">Each participant moves every (rounds)</h5>
@@ -696,6 +699,13 @@ <h5 class="step-title">% mobile participants</h5>
696699
placeholder="% of mobile participants" min="0" value="100"
697700
style="display: inline; width: 80%">
698701
</div>
702+
<h5 class="step-title">Mobility adaptation</h5>
703+
<div class="form-check form-check-inline">
704+
<select class="form-control" id="mobilityAdaptationSelect" name="mobilityAdaptation" style="display: inline">
705+
<option value="sa" selected>Situational Awareness</option>
706+
<option value="static">Static</option>
707+
</select>
708+
</div>
699709
<hr class="styled">
700710
<h5 class="step-title">Number of additional participants (deployed during
701711
federation)</h5>

nebula/scenarios.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -815,13 +815,17 @@ def load_configurations_and_start_nodes(self, additional_participants=None, sche
815815
dataset.initialize_dataset()
816816
logging.info(f"Splitting {dataset_name} dataset... Done")
817817

818-
if self.scenario.deployment in ["docker", "process"]:
818+
if self.scenario.deployment in ["docker", "process", "physical"]:
819819
if self.use_blockchain:
820820
self.start_blockchain()
821821
if self.scenario.deployment == "docker":
822822
self.start_nodes_docker()
823-
else:
823+
elif self.scenario.deployment == "physical":
824+
self.start_nodes_physical()
825+
elif self.scenario.deployment == "process":
824826
self.start_nodes_process()
827+
else:
828+
raise ValueError(f"Unknown deployment type: {self.scenario.deployment}")
825829
else:
826830
logging.info(
827831
f"Virtualization mode is disabled for scenario '{self.scenario_name}' with {self.n_nodes} nodes. Waiting for nodes to start manually..."
@@ -1097,6 +1101,15 @@ def start_nodes_process(self):
10971101

10981102
except Exception as e:
10991103
raise Exception(f"Error starting nodes as processes: {e}")
1104+
1105+
def start_nodes_physical(self):
1106+
logging.info("Starting nodes as physical devices...")
1107+
logging.info(f"env path: {self.env_path}")
1108+
1109+
for idx, node in enumerate(self.config.participants):
1110+
pass
1111+
1112+
logging.info("Physical devices deployment is not implemented publicly. Please use docker or process deployment.")
11001113

11011114
@classmethod
11021115
def remove_files_by_scenario(cls, scenario_name):

0 commit comments

Comments
 (0)