1156 lines
64 KiB
HTML
1156 lines
64 KiB
HTML
{% extends "dashboard/layout.html" %}
|
|
|
|
{% block title %}Mycelium Dashboard - Resource Provider{% endblock %}
|
|
|
|
{% block dashboard_content %}
|
|
<div class="my-4">
|
|
<h1>Resource Provider Dashboard</h1>
|
|
<p class="lead">Manage your nodes, configure slices, and monitor earnings</p>
|
|
|
|
<!-- Status Summary -->
|
|
<div class="row mt-4">
|
|
<div class="col-md-4">
|
|
<div class="stats-card success">
|
|
<h5 class="card-title">Active Nodes</h5>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h2 class="mb-0" id="active-nodes-count">{{ resource_provider_stats.online_nodes }}</h2>
|
|
<small class="text-muted">of {{ resource_provider_stats.total_nodes }} total</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="stats-card primary">
|
|
<h5 class="card-title">Allocated Slices</h5>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h2 class="mb-0" id="active-slices-count">{{ resource_provider_stats.allocated_base_slices }}</h2>
|
|
<small class="text-muted">of {{ resource_provider_stats.total_base_slices }} total</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="stats-card warning">
|
|
<h5 class="card-title">Monthly Earnings</h5>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h2 class="mb-0" id="monthly-earnings">{{ resource_provider_stats.monthly_earnings }}</h2>
|
|
<small class="text-muted">$/month</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wallet & Staking Summary -->
|
|
<div class="row mt-4">
|
|
<div class="col-md-4">
|
|
<div class="stats-card secondary">
|
|
<h5 class="card-title">
|
|
<i class="bi bi-wallet2 me-2"></i>Wallet Balance
|
|
</h5>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h2 class="mb-0" id="wallet-balance">0</h2>
|
|
<small class="text-muted">Credits</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="stats-card success">
|
|
<h5 class="card-title">
|
|
<i class="bi bi-shield-check me-2"></i>Total Staked
|
|
</h5>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h2 class="mb-0" id="total-staked">0</h2>
|
|
<small class="text-muted">Credits</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4">
|
|
<div class="stats-card info">
|
|
<h5 class="card-title">
|
|
<i class="bi bi-nodes me-2"></i>Staked Nodes
|
|
</h5>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h2 class="mb-0" id="staked-nodes-count">0</h2>
|
|
<small class="text-muted">With Staking</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Node Button -->
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="d-flex justify-content-end">
|
|
<a href="#" class="btn btn-success" data-bs-toggle="modal" data-bs-target="#addNodeModal">
|
|
<i class="bi bi-plus-circle me-2"></i> Add Nodes
|
|
</a>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- My Nodes Section -->
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="dashboard-section">
|
|
<h3>My Nodes</h3>
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-hover align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Grid Node ID</th>
|
|
<th>Farm & Location</th>
|
|
<th>Specifications</th>
|
|
<th>SLA & Pricing</th>
|
|
<th>Certification</th>
|
|
<th>Status</th>
|
|
<th>Group</th>
|
|
<th>Staked</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="nodes-table-tbody">
|
|
<!-- Nodes will be populated by JavaScript -->
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Node Groups Section -->
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="dashboard-section">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h3>Node Groups</h3>
|
|
<button class="btn btn-outline-success" data-bs-toggle="modal" data-bs-target="#createCustomNodeGroupModal">
|
|
<i class="bi bi-plus-circle me-2"></i> Create Custom Group
|
|
</button>
|
|
</div>
|
|
|
|
<div class="alert alert-info">
|
|
<h5><i class="bi bi-info-circle me-2"></i>Node Groups</h5>
|
|
<p class="mb-0">Organize your nodes into groups for easier management. Default groups (Compute, Storage, AI/GPU) are provided, or create custom groups for specific use cases.</p>
|
|
</div>
|
|
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-hover align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Group Name</th>
|
|
<th>Type</th>
|
|
<th>Nodes</th>
|
|
<th>Total Resources</th>
|
|
<th>Status</th>
|
|
<th>Average Uptime</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="node-groups-table">
|
|
<tr>
|
|
<td colspan="7" class="text-center text-muted">
|
|
<div class="spinner-border spinner-border-sm me-2" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
Loading node groups...
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Automatic Slice Management Section -->
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="dashboard-section">
|
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
|
<h3>Slice Management</h3>
|
|
<div class="d-flex gap-2">
|
|
<button class="btn btn-outline-info" data-action="slice.refresh">
|
|
<i class="bi bi-arrow-clockwise me-2"></i> Refresh Calculations
|
|
</button>
|
|
<button class="btn btn-outline-success" data-action="grid.sync">
|
|
<i class="bi bi-cloud-download me-2"></i> Sync with Grid
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="alert alert-info">
|
|
<h5><i class="bi bi-info-circle me-2"></i>Automatic Slice System</h5>
|
|
<p class="mb-0">Your nodes are automatically divided into <strong>base slices</strong> (1 vCPU + 4GB RAM + 200GB storage). Users can rent individual slices or combinations (2x, 4x, 8x). Slice availability updates in real-time based on node capacity.</p>
|
|
</div>
|
|
|
|
<!-- Slice Overview Cards -->
|
|
<div class="row mb-4">
|
|
<div class="col-md-3">
|
|
<div class="stats-card primary">
|
|
<h6 class="card-title">Total Base Slices</h6>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h3 class="mb-0" id="total-base-slices">{{ resource_provider_stats.total_base_slices }}</h3>
|
|
<small class="text-muted">Available</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="stats-card success">
|
|
<h6 class="card-title">Allocated Slices</h6>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h3 class="mb-0" id="allocated-base-slices">{{ resource_provider_stats.allocated_base_slices }}</h3>
|
|
<small class="text-muted">Rented</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="stats-card info">
|
|
<h6 class="card-title">Available Slices</h6>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h3 class="mb-0" id="available-base-slices">{{ resource_provider_stats.available_base_slices }}</h3>
|
|
<small class="text-muted">For Rent</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="stats-card warning">
|
|
<h6 class="card-title">Utilization</h6>
|
|
<div class="d-flex justify-content-between align-items-end">
|
|
<h3 class="mb-0" id="slice-utilization">{{ resource_provider_stats.slice_utilization_percentage }}%</h3>
|
|
<small class="text-muted">Capacity</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Node Slice Breakdown Table -->
|
|
<div class="table-responsive">
|
|
<table class="table table-striped table-hover align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Node</th>
|
|
<th>Location</th>
|
|
<th>Total Slices</th>
|
|
<th>Allocated</th>
|
|
<th>Available</th>
|
|
<th>Slice Combinations</th>
|
|
<th>Pricing</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="node-slices-table">
|
|
{% if resource_provider_nodes %}
|
|
{% for node in resource_provider_nodes %}
|
|
<tr>
|
|
<td>
|
|
<div class="d-flex align-items-center">
|
|
<div class="node-status-indicator
|
|
{% if node.status == 'Online' %}bg-success{% else %}bg-danger{% endif %}
|
|
me-2"></div>
|
|
<div>
|
|
<strong>{{ node.name }}</strong>
|
|
{% if node.grid_node_id %}
|
|
<br><small class="text-muted">Grid ID: {{ node.grid_node_id }}</small>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<span class="node-location" data-city="{{ node.grid_data.city | default(value='Unknown') }}" data-country="{{ node.grid_data.country | default(value='Unknown') }}">
|
|
{{ node.location }}
|
|
</span>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-primary">{{ node.total_base_slices }}</span>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-success">{{ node.allocated_base_slices }}</span>
|
|
</td>
|
|
<td>
|
|
<span class="badge bg-info">{{ node.total_base_slices - node.allocated_base_slices }}</span>
|
|
</td>
|
|
<td>
|
|
<div class="slice-combinations">
|
|
{% if node.available_combinations %}
|
|
{% for combo in node.available_combinations %}
|
|
{% if combo.quantity_available > 0 %}
|
|
<span class="badge bg-light text-dark me-1">
|
|
{{ combo.multiplier }}x ({{ combo.quantity_available }})
|
|
</span>
|
|
{% endif %}
|
|
{% endfor %}
|
|
{% else %}
|
|
<small class="text-muted">Calculating...</small>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
<td>
|
|
<div class="pricing-info">
|
|
{% if node.marketplace_sla %}
|
|
<strong>${{ node.marketplace_sla.base_slice_price }}/hr</strong>
|
|
<br><small class="text-muted">{{ node.marketplace_sla.uptime_guarantee_percentage | format_decimal(precision=1) }}% uptime</small>
|
|
{% else %}
|
|
<strong>${{ node.slice_pricing.base_price_per_hour }}/hr</strong>
|
|
<br><small class="text-muted">{{ node.uptime_percentage | format_decimal(precision=1) }}% uptime</small>
|
|
{% endif %}
|
|
</div>
|
|
</td>
|
|
<td>
|
|
{% if node.status == 'Online' %}
|
|
<span class="badge bg-success">Online</span>
|
|
{% else %}
|
|
<span class="badge bg-danger">{{ node.status }}</span>
|
|
{% endif %}
|
|
</td>
|
|
<td>
|
|
<div class="btn-group btn-group-sm">
|
|
<button class="btn btn-outline-primary" onclick="viewNodeDetails('{{ node.id }}')" title="View Details">
|
|
<i class="bi bi-eye"></i>
|
|
</button>
|
|
<button class="btn btn-outline-danger" onclick="deleteNodeConfiguration('{{ node.id }}')" title="Delete">
|
|
<i class="bi bi-trash"></i>
|
|
</button>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
{% else %}
|
|
<tr>
|
|
<td colspan="9" class="text-center text-muted py-4">
|
|
<i class="bi bi-nodes display-4 d-block mb-3"></i>
|
|
<h5>No Nodes Added Yet</h5>
|
|
<p>Add your first node from the Mycelium Grid to start offering slices on the marketplace.</p>
|
|
<button class="btn btn-success" data-bs-toggle="modal" data-bs-target="#addNodeModal">
|
|
<i class="bi bi-plus-circle me-2"></i> Add Your First Node
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
{% endif %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Capacity and Node Analytics Section -->
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="dashboard-section">
|
|
<h3>Capacity Analytics</h3>
|
|
<div class="row">
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5>Capacity Utilization</h5>
|
|
</div>
|
|
<div class="card-body d-flex justify-content-center align-items-center">
|
|
<canvas id="capacityUtilizationChart" width="400" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6 mb-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5>Node Status Overview</h5>
|
|
</div>
|
|
<div class="card-body d-flex justify-content-center align-items-center">
|
|
<canvas id="nodeStatusChart" width="400" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Earnings Monitoring Section -->
|
|
<div class="row mt-4">
|
|
<div class="col-12">
|
|
<div class="dashboard-section">
|
|
<h3>Earnings Monitoring</h3>
|
|
<div class="row">
|
|
<div class="col-md-8 mb-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5>Monthly Earnings Trend</h5>
|
|
</div>
|
|
<div class="card-body d-flex justify-content-center align-items-center">
|
|
<canvas id="earningsChart" width="400" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-4 mb-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h5>Earnings Breakdown</h5>
|
|
</div>
|
|
<div class="card-body d-flex justify-content-center align-items-center">
|
|
<canvas id="earningsBreakdownChart" width="400" height="300"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% block scripts %}
|
|
{{ super() }}
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@3.7.1/dist/chart.min.js"></script>
|
|
|
|
<!-- Load resource provider dashboard JavaScript -->
|
|
<script src="/static/js/dashboard-resource_provider.js"></script>
|
|
|
|
<style>
|
|
/* Ensure charts have consistent sizes */
|
|
.card-body {
|
|
min-height: 340px;
|
|
}
|
|
|
|
/* Slice Format Selection Styles */
|
|
.slice-format-card {
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
border: 2px solid #e9ecef;
|
|
}
|
|
|
|
.slice-format-card:hover {
|
|
border-color: #007bff;
|
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 123, 255, 0.075);
|
|
}
|
|
|
|
.slice-format-card.selected {
|
|
border-color: #007bff;
|
|
background-color: #f8f9ff;
|
|
box-shadow: 0 0.125rem 0.25rem rgba(0, 123, 255, 0.15);
|
|
}
|
|
|
|
.slice-format-checkbox {
|
|
transform: scale(1.2);
|
|
}
|
|
|
|
/* Node Management Modal Styles */
|
|
.node-management-tabs .nav-link {
|
|
border-radius: 0.375rem 0.375rem 0 0;
|
|
}
|
|
|
|
.node-management-tabs .nav-link.active {
|
|
background-color: #007bff;
|
|
border-color: #007bff;
|
|
color: white;
|
|
}
|
|
|
|
.slice-allocation-matrix {
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.allocation-status {
|
|
padding: 0.5rem;
|
|
border-radius: 0.375rem;
|
|
text-align: center;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.allocation-status.allocated {
|
|
background-color: #d1ecf1;
|
|
color: #0c5460;
|
|
border: 1px solid #bee5eb;
|
|
}
|
|
|
|
.allocation-status.available {
|
|
background-color: #f8f9fa;
|
|
border: 1px solid #dee2e6;
|
|
}
|
|
|
|
/* Enhanced pricing display styles */
|
|
.pricing-breakdown {
|
|
line-height: 1.3;
|
|
}
|
|
|
|
.pricing-breakdown small {
|
|
display: block;
|
|
margin-top: 2px;
|
|
}
|
|
|
|
/* Enhanced progress bar colors for utilization */
|
|
.progress-bar.bg-success {
|
|
background-color: #28a745 !important;
|
|
}
|
|
|
|
.progress-bar.bg-info {
|
|
background-color: #17a2b8 !important;
|
|
}
|
|
|
|
.progress-bar.bg-warning {
|
|
background-color: #ffc107 !important;
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
<!-- Delete Slice Confirmation Modal -->
|
|
<div class="modal fade" id="deleteSliceModal" tabindex="-1" aria-labelledby="deleteSliceModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="deleteSliceModalLabel">
|
|
<i class="bi bi-exclamation-triangle text-warning me-2"></i>
|
|
Confirm Deletion
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="alert alert-warning">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
<strong>Warning:</strong> This action cannot be undone.
|
|
</div>
|
|
<p>Are you sure you want to delete the slice configuration <strong id="deleteSliceName">""</strong>?</p>
|
|
<p class="text-muted small">This will remove the slice template and stop offering it on the marketplace. Any active rentals will continue until their expiration.</p>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-danger" id="confirmDeleteSliceBtn">
|
|
<i class="bi bi-trash me-2"></i>Delete Slice Configuration
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Add Nodes Modal -->
|
|
<div class="modal fade" id="addNodeModal" tabindex="-1" aria-labelledby="addNodeModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="addNodeModalLabel">Add Nodes from Mycelium Grid</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
<strong>Mycelium Grid Integration:</strong> Enter the Grid Node IDs of your physical Mycelium Nodes. Node specifications and location will be automatically fetched from the Mycelium Grid.
|
|
</div>
|
|
|
|
<!-- Node Input Mode Selection -->
|
|
<div class="mb-4">
|
|
<label class="form-label">How many nodes do you want to add?</label>
|
|
<div class="btn-group w-100" role="group" aria-label="Node input mode">
|
|
<input type="radio" class="btn-check" name="nodeInputMode" id="singleNodeMode" value="single" checked>
|
|
<label class="btn btn-outline-primary" for="singleNodeMode">Single Node</label>
|
|
|
|
<input type="radio" class="btn-check" name="nodeInputMode" id="multipleNodeMode" value="multiple">
|
|
<label class="btn btn-outline-primary" for="multipleNodeMode">Multiple Nodes</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Single Node Input -->
|
|
<div id="singleNodeInput" class="mb-4">
|
|
<label for="gridNodeId" class="form-label">Mycelium Grid Node ID</label>
|
|
<input type="number" class="form-control" id="gridNodeId" placeholder="e.g., 8, 42, 1337" min="1">
|
|
<small class="text-muted">Enter the ID of your node on the Mycelium Grid</small>
|
|
</div>
|
|
|
|
<!-- Multiple Nodes Input -->
|
|
<div id="multipleNodeInput" class="mb-4" style="display: none;">
|
|
<label for="gridNodeIds" class="form-label">Mycelium Grid Node IDs</label>
|
|
<textarea class="form-control" id="gridNodeIds" rows="3" placeholder="Enter node IDs separated by commas or new lines e.g., 8, 42, 1337 or one per line"></textarea>
|
|
<small class="text-muted">Enter multiple node IDs separated by commas or new lines</small>
|
|
</div>
|
|
|
|
<!-- Node Preview Section -->
|
|
<div id="nodePreview" class="mb-4" style="display: none;">
|
|
<h6>Node Preview</h6>
|
|
<div id="nodePreviewContent" class="border rounded p-3 bg-light">
|
|
<!-- Node preview will be populated here -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Node Group Assignment -->
|
|
<div class="mb-4">
|
|
<label for="nodeGroup" class="form-label">Node Group</label>
|
|
<select class="form-select node-group-select" id="nodeGroup" name="node_group">
|
|
<option value="">Single (No Group)</option>
|
|
<!-- Groups will be populated dynamically -->
|
|
</select>
|
|
<small class="text-muted">Assign this node to a group for easier management. Default groups are provided, or you can create custom groups.</small>
|
|
</div>
|
|
|
|
<!-- Group Configuration (Legacy - Hidden) -->
|
|
<div class="mb-4" style="display: none;">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="createGroupToggle">
|
|
<label class="form-check-label" for="createGroupToggle">
|
|
<strong>Organize nodes into a group</strong>
|
|
</label>
|
|
</div>
|
|
<small class="text-muted">Group nodes together for easier management and shared slice pricing</small>
|
|
</div>
|
|
|
|
<!-- Automatic Slice Management Section -->
|
|
<div class="mb-4">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="mb-0"><i class="bi bi-layers me-2"></i>Automatic Slice Management</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-success">
|
|
<i class="bi bi-check-circle me-2"></i>
|
|
<strong>Automatic Slice Calculation:</strong> Slices will be automatically calculated from your node's capacity using the standard base slice unit (1 vCPU + 4GB RAM + 200GB storage). All possible slice combinations (1x, 2x, 4x, 8x, 16x, etc.) will be available based on your node's total capacity.
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Base Slice Pricing</label>
|
|
<div class="input-group">
|
|
<input type="number" class="form-control" id="baseSlicePrice" placeholder="0.50" min="0.10" max="2.00" step="0.01" value="0.50">
|
|
<span class="input-group-text">$/hour</span>
|
|
</div>
|
|
<small class="text-muted">Price per base slice (1 vCPU + 4GB RAM + 200GB storage). Range: $0.10 - $2.00/hour. Larger combinations will be priced proportionally.</small>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
<strong>How it works:</strong>
|
|
<ul class="mb-0 mt-2">
|
|
<li>Your node capacity will be automatically analyzed</li>
|
|
<li>Maximum number of base slices will be calculated</li>
|
|
<li>All possible slice combinations (2x, 4x, 8x, 16x, etc.) will be generated automatically based on capacity</li>
|
|
<li>All slices inherit your node's location, uptime, and bandwidth characteristics</li>
|
|
<li>Slices appear in marketplace immediately after node registration</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label class="form-label">Node SLA Configuration</label>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<label for="nodeUptimeSLA" class="form-label">Minimum Uptime SLA</label>
|
|
<select class="form-select" id="nodeUptimeSLA">
|
|
<option value="99.0">99.0%</option>
|
|
<option value="99.5">99.5%</option>
|
|
<option value="99.8" selected>99.8%</option>
|
|
<option value="99.9">99.9%</option>
|
|
<option value="99.95">99.95%</option>
|
|
</select>
|
|
<small class="text-muted">All slices inherit this uptime guarantee</small>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label for="nodeBandwidthSLA" class="form-label">Minimum Bandwidth</label>
|
|
<div class="input-group">
|
|
<input type="number" class="form-control" id="nodeBandwidthSLA" placeholder="100" min="10" value="100">
|
|
<span class="input-group-text">Mbps</span>
|
|
</div>
|
|
<small class="text-muted">Shared bandwidth across all slices</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="enableStaking">
|
|
<label class="form-check-label" for="enableStaking">
|
|
<strong>Enable Staking</strong>
|
|
</label>
|
|
</div>
|
|
<small class="text-muted">Stake Credits on this node for slashing protection and network security</small>
|
|
</div>
|
|
|
|
<!-- Staking Configuration Section -->
|
|
<div id="stakingConfigSection" style="display: none;">
|
|
<div class="card mt-3 mb-3">
|
|
<div class="card-header">
|
|
<h6 class="mb-0"><i class="bi bi-shield-check me-2"></i>Node Staking Configuration</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
<strong>Staking Purpose:</strong> Stake Credits for slashing protection and network security. Staked amounts can be slashed if SLA requirements are not met.
|
|
</div>
|
|
|
|
<!-- Staking Amount -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<label for="stakingAmount" class="form-label">Staking Amount ($)</label>
|
|
<input type="number" class="form-control" id="stakingAmount" placeholder="e.g., 100" min="1" step="1">
|
|
<small class="text-muted">Available Balance: $<span id="availableBalance">0</span></small>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<label for="stakingPeriod" class="form-label">Staking Period</label>
|
|
<select class="form-select" id="stakingPeriod">
|
|
<option value="3">3 Months</option>
|
|
<option value="6">6 Months</option>
|
|
<option value="12" selected>12 Months</option>
|
|
<option value="24">24 Months</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Staking Options -->
|
|
<div class="row mb-3">
|
|
<div class="col-md-6">
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="checkbox" id="earlyWithdrawalAllowed" checked>
|
|
<label class="form-check-label" for="earlyWithdrawalAllowed">
|
|
Allow early withdrawal (25% penalty)
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Multi-node staking configuration -->
|
|
<div id="multiNodeStakingOptions" style="display: none;">
|
|
<hr class="my-4">
|
|
<h6><i class="bi bi-layers me-2"></i>Multi-Node Staking Configuration</h6>
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
<strong>Multiple Nodes Detected:</strong> Choose how to apply staking across your nodes.
|
|
</div>
|
|
<div class="form-check mb-2">
|
|
<input class="form-check-input" type="radio" name="multiNodeStaking" id="sameStakingForAllNodes" value="same" checked>
|
|
<label class="form-check-label" for="sameStakingForAllNodes">
|
|
<strong>Apply same staking to all nodes</strong>
|
|
<small class="text-muted d-block">All nodes will use the staking configuration above</small>
|
|
</label>
|
|
</div>
|
|
<div class="form-check">
|
|
<input class="form-check-input" type="radio" name="multiNodeStaking" id="individualStaking" value="individual">
|
|
<label class="form-check-label" for="individualStaking">
|
|
<strong>Set individual staking per node</strong>
|
|
<small class="text-muted d-block">Configure different staking amounts for each node</small>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Group Configuration Section -->
|
|
<div id="groupConfigSection" class="mb-4" style="display: none;">
|
|
<div class="card">
|
|
<div class="card-header">
|
|
<h6 class="mb-0">Node Group Configuration</h6>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="mb-3">
|
|
<label for="groupName" class="form-label">Group Name</label>
|
|
<input type="text" class="form-control" id="groupName" placeholder="e.g., High Performance Cluster">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="groupDescription" class="form-label">Description (Optional)</label>
|
|
<textarea class="form-control" id="groupDescription" rows="2" placeholder="Describe the purpose of this node group"></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Existing Group Selection -->
|
|
<div id="existingGroupSection" class="mb-4" style="display: none;">
|
|
<label for="existingGroup" class="form-label">Add to Existing Group</label>
|
|
<select class="form-select node-group-select" id="existingGroup">
|
|
<option value="">Select an existing group...</option>
|
|
<!-- Existing groups will be populated here -->
|
|
</select>
|
|
</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" id="validateNodesBtn">Fetch Nodes</button>
|
|
<button type="button" class="btn btn-success" id="addNodesBtn" style="display: none;">Add Nodes</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Node Slice Preview Modal -->
|
|
<div class="modal fade" id="nodeSlicePreviewModal" tabindex="-1" aria-labelledby="nodeSlicePreviewModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="nodeSlicePreviewModalLabel">Node Slice Breakdown</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
<strong>Automatic Slice Calculation:</strong> Based on your node's capacity, the following slice combinations will be automatically available in the marketplace.
|
|
</div>
|
|
|
|
<div id="sliceBreakdownContent">
|
|
<!-- Slice breakdown will be populated here -->
|
|
<div class="text-center">
|
|
<div class="spinner-border" role="status">
|
|
<span class="visually-hidden">Calculating slices...</span>
|
|
</div>
|
|
<p class="mt-2">Calculating available slice combinations...</p>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
<button type="button" class="btn btn-primary" data-action="slice.refresh">
|
|
<i class="bi bi-arrow-clockwise me-2"></i>Recalculate Slices
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create Custom Node Group Modal -->
|
|
<div class="modal fade" id="createCustomNodeGroupModal" tabindex="-1" aria-labelledby="createCustomNodeGroupModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="createCustomNodeGroupModalLabel">Create Custom Node Group</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="alert alert-info">
|
|
<h6><i class="bi bi-info-circle me-2"></i>Custom Node Groups</h6>
|
|
<p class="mb-0">Create custom groups for specific use cases beyond the default Compute, Storage, and AI/GPU groups. You can assign nodes to this group later.</p>
|
|
</div>
|
|
|
|
<form id="createCustomGroupForm">
|
|
<div class="mb-3">
|
|
<label for="customGroupName" class="form-label">Group Name <span class="text-danger">*</span></label>
|
|
<input type="text" class="form-control" id="customGroupName" placeholder="e.g., High Performance Cluster" required>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="customGroupDescription" class="form-label">Description</label>
|
|
<textarea class="form-control" id="customGroupDescription" rows="3" placeholder="Describe the purpose and characteristics of this group"></textarea>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="resourceOptimization" class="form-label">Resource Optimization</label>
|
|
<select class="form-select" id="resourceOptimization">
|
|
<option value="balanced">Balanced - General purpose optimization</option>
|
|
<option value="performance">Performance - Optimized for high performance</option>
|
|
<option value="efficiency">Efficiency - Optimized for resource efficiency</option>
|
|
<option value="custom">Custom - Manual optimization settings</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<label for="groupSlicePricing" class="form-label">Group Slice Pricing Strategy</label>
|
|
<select class="form-select" id="groupSlicePricing">
|
|
<option value="individual">Individual Node Pricing - Each node sets its own slice pricing</option>
|
|
<option value="unified">Unified Group Pricing - All nodes in group use same slice pricing</option>
|
|
<option value="tiered">Tiered Pricing - Different pricing based on node performance tier</option>
|
|
</select>
|
|
<small class="text-muted">Determines how slice pricing is managed across nodes in this group</small>
|
|
</div>
|
|
|
|
<div class="mb-3">
|
|
<div class="form-check form-switch">
|
|
<input class="form-check-input" type="checkbox" id="autoScaling">
|
|
<label class="form-check-label" for="autoScaling">
|
|
Enable Auto-scaling
|
|
</label>
|
|
</div>
|
|
<small class="text-muted">Automatically adjust resources based on demand</small>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
<button type="button" class="btn btn-success" id="createCustomGroupBtn">Create Custom Group</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Node Management Modal -->
|
|
<div class="modal fade" id="manageNodeModal" tabindex="-1" aria-labelledby="manageNodeModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-xl">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="manageNodeModalLabel">Manage Node: <span id="nodeNameTitle"></span></h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<!-- Tabbed Interface -->
|
|
<ul class="nav nav-tabs node-management-tabs" role="tablist">
|
|
<li class="nav-item">
|
|
<button class="nav-link active" id="overview-tab" data-bs-toggle="tab" data-bs-target="#node-overview" type="button" role="tab">
|
|
<i class="bi bi-speedometer2 me-1"></i>Overview
|
|
</button>
|
|
</li>
|
|
<li class="nav-item">
|
|
<button class="nav-link" id="configuration-tab" data-bs-toggle="tab" data-bs-target="#node-configuration" type="button" role="tab">
|
|
<i class="bi bi-gear me-1"></i>Configuration
|
|
</button>
|
|
</li>
|
|
<li class="nav-item">
|
|
<button class="nav-link" id="slices-tab" data-bs-toggle="tab" data-bs-target="#node-slices" type="button" role="tab">
|
|
<i class="bi bi-grid-3x3-gap me-1"></i>Slice Allocation
|
|
</button>
|
|
</li>
|
|
<li class="nav-item">
|
|
<button class="nav-link" id="performance-tab" data-bs-toggle="tab" data-bs-target="#node-performance" type="button" role="tab">
|
|
<i class="bi bi-graph-up me-1"></i>Performance
|
|
</button>
|
|
</li>
|
|
</ul>
|
|
|
|
<div class="tab-content mt-3">
|
|
<!-- Overview Tab -->
|
|
<div class="tab-pane fade show active" id="node-overview" role="tabpanel">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>Node Status</h6>
|
|
<div class="mb-3">
|
|
<label for="nodeStatus" class="form-label">Current Status</label>
|
|
<select class="form-select" id="nodeStatus">
|
|
<option value="Online">Online</option>
|
|
<option value="Offline">Offline</option>
|
|
<option value="Maintenance">Maintenance</option>
|
|
<option value="Error">Error</option>
|
|
<option value="Standby">Standby</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Quick Actions</label>
|
|
<div class="d-grid gap-2">
|
|
<button class="btn btn-outline-warning" data-action="node.maintenance">
|
|
<i class="bi bi-tools me-1"></i>Enter Maintenance Mode
|
|
</button>
|
|
<button class="btn btn-outline-success" data-action="node.restart">
|
|
<i class="bi bi-arrow-clockwise me-1"></i>Restart Node
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>Node Information</h6>
|
|
<table class="table table-sm">
|
|
<tr><td><strong>Node ID:</strong></td><td id="nodeIdDisplay"></td></tr>
|
|
<tr><td><strong>Location:</strong></td><td id="nodeLocationDisplay"></td></tr>
|
|
<tr><td><strong>Uptime:</strong></td><td id="nodeUptimeDisplay"></td></tr>
|
|
<tr><td><strong>Health Score:</strong></td><td id="nodeHealthDisplay"></td></tr>
|
|
<tr><td><strong>Last Seen:</strong></td><td id="nodeLastSeenDisplay"></td></tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Configuration Tab -->
|
|
<div class="tab-pane fade" id="node-configuration" role="tabpanel">
|
|
<form id="nodeConfigForm">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>Basic Configuration</h6>
|
|
<div class="mb-3">
|
|
<label for="editNodeName" class="form-label">Node Name</label>
|
|
<input type="text" class="form-control" id="editNodeName">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="editNodeLocation" class="form-label">Location</label>
|
|
<input type="text" class="form-control" id="editNodeLocation">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="editNodeRegion" class="form-label">Region</label>
|
|
<select class="form-select" id="editNodeRegion">
|
|
<option value="US-East">US-East</option>
|
|
<option value="US-West">US-West</option>
|
|
<option value="EU-Central">EU-Central</option>
|
|
<option value="Asia-Pacific">Asia-Pacific</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>Hardware Specifications</h6>
|
|
<div class="mb-3">
|
|
<label for="editCpuCores" class="form-label">CPU Cores</label>
|
|
<input type="number" class="form-control" id="editCpuCores">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="editMemoryGb" class="form-label">Memory (GB)</label>
|
|
<input type="number" class="form-control" id="editMemoryGb">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="editStorageGb" class="form-label">Storage (GB)</label>
|
|
<input type="number" class="form-control" id="editStorageGb">
|
|
</div>
|
|
<div class="mb-3">
|
|
<label for="editBandwidthMbps" class="form-label">Bandwidth (Mbps)</label>
|
|
<input type="number" class="form-control" id="editBandwidthMbps">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<!-- Slice Allocation Tab -->
|
|
<div class="tab-pane fade" id="node-slices" role="tabpanel">
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<h6>Current Slice Allocation</h6>
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
You can modify slice allocation when no slices are currently rented.
|
|
</div>
|
|
|
|
<div class="slice-allocation-matrix">
|
|
<h6>Available Slice Formats</h6>
|
|
<div class="row" id="nodeSliceFormats">
|
|
<!-- Slice formats will be loaded here -->
|
|
</div>
|
|
|
|
<div class="mt-4">
|
|
<h6>Capacity Utilization</h6>
|
|
<div class="row">
|
|
<div class="col-md-3">
|
|
<div class="text-center">
|
|
<div class="progress mb-2" style="height: 20px;">
|
|
<div class="progress-bar" id="cpuUtilBar" role="progressbar"></div>
|
|
</div>
|
|
<small>CPU Utilization</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-center">
|
|
<div class="progress mb-2" style="height: 20px;">
|
|
<div class="progress-bar bg-info" id="memoryUtilBar" role="progressbar"></div>
|
|
</div>
|
|
<small>Memory Utilization</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-center">
|
|
<div class="progress mb-2" style="height: 20px;">
|
|
<div class="progress-bar bg-warning" id="storageUtilBar" role="progressbar"></div>
|
|
</div>
|
|
<small>Storage Utilization</small>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-3">
|
|
<div class="text-center">
|
|
<div class="progress mb-2" style="height: 20px;">
|
|
<div class="progress-bar bg-success" id="bandwidthUtilBar" role="progressbar"></div>
|
|
</div>
|
|
<small>Bandwidth Utilization</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Performance Tab -->
|
|
<div class="tab-pane fade" id="node-performance" role="tabpanel">
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<h6>Performance Metrics</h6>
|
|
<div class="card">
|
|
<div class="card-body">
|
|
<canvas id="nodePerformanceChart" width="400" height="200"></canvas>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<h6>Earnings & Statistics</h6>
|
|
<table class="table table-sm">
|
|
<tr><td><strong>Today's Earnings:</strong></td><td id="nodeTodayEarnings">$0</td></tr>
|
|
<tr><td><strong>Monthly Earnings:</strong></td><td id="nodeMonthlyEarnings">$0</td></tr>
|
|
<tr><td><strong>Total Deployments:</strong></td><td id="nodeTotalDeployments">0</td></tr>
|
|
<tr><td><strong>Active Slices:</strong></td><td id="nodeActiveSlices">0</td></tr>
|
|
<tr><td><strong>Average Load:</strong></td><td id="nodeAverageLoad">0%</td></tr>
|
|
</table>
|
|
|
|
<div class="mt-3">
|
|
<h6>Health Alerts</h6>
|
|
<div id="nodeHealthAlerts">
|
|
<div class="alert alert-success alert-sm">
|
|
<i class="bi bi-check-circle me-1"></i>All systems operational
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
<button type="button" class="btn btn-primary" id="saveNodeManagementBtn"><i class="bi bi-check me-1"></i>Save Configuration</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Node Details Modal -->
|
|
<div class="modal fade" id="nodeDetailsModal" tabindex="-1" aria-labelledby="nodeDetailsModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog modal-lg">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="nodeDetailsModalLabel">
|
|
<i class="bi bi-server me-2"></i>Node Details
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div id="nodeDetailsContent">
|
|
<!-- Node details will be populated here -->
|
|
<div class="text-center">
|
|
<div class="spinner-border" role="status">
|
|
<span class="visually-hidden">Loading...</span>
|
|
</div>
|
|
<p class="mt-2">Loading node details...</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<!-- Node Delete Confirmation Modal -->
|
|
<div class="modal fade" id="deleteNodeModal" tabindex="-1" aria-labelledby="deleteNodeModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title" id="deleteNodeModalLabel">
|
|
<i class="bi bi-exclamation-triangle text-warning me-2"></i>
|
|
Confirm Node Removal
|
|
</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="alert alert-danger">
|
|
<i class="bi bi-exclamation-triangle me-2"></i>
|
|
<strong>Warning:</strong> This action cannot be undone.
|
|
</div>
|
|
<p>Are you sure you want to remove the node <strong id="deleteNodeName">""</strong> from your farm?</p>
|
|
<p class="text-muted small">This will:</p>
|
|
<ul class="text-muted small">
|
|
<li>Remove the node from your dashboard</li>
|
|
<li>Stop offering it on the marketplace</li>
|
|
<li>Cancel any pending slice offerings</li>
|
|
<li>Preserve any active rentals until their expiration</li>
|
|
</ul>
|
|
<div class="alert alert-info">
|
|
<i class="bi bi-info-circle me-2"></i>
|
|
<strong>Note:</strong> For grid nodes, this only removes the node from your dashboard. The physical node remains on the Mycelium Grid.
|
|
</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-danger" id="confirmDeleteNodeBtn">
|
|
<i class="bi bi-trash me-2"></i>Remove Node
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %} |