Initial commit: MicroNAS share manager (Phase 1)
This commit is contained in:
commit
f2aca2e3ea
8 files changed
+671
No files matched your search
+223
@@ -0,0 +1,223 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>SMB + NFS Manager</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/css/bootstrap.min.css">
|
||||
</head>
|
||||
<body class="bg-dark text-white p-4">
|
||||
|
||||
<div class="container">
|
||||
<h1 class="mb-4">📁 Share Manager (SMB + NFS)</h1>
|
||||
|
||||
<!-- Tabs -->
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-bs-toggle="tab" href="#smb">SMB Shares</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-bs-toggle="tab" href="#nfs">NFS Exports</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-bs-toggle="tab" href="#quotas">Quotas</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- SMB TAB -->
|
||||
<div id="smb" class="tab-pane fade show active mt-4">
|
||||
<h3>SMB Shares</h3>
|
||||
|
||||
<form class="row g-3 mb-4">
|
||||
<div class="col-md-3">
|
||||
<input type="text" id="smbName" class="form-control" placeholder="Share Name" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" id="smbPath" class="form-control" placeholder="/srv/samba/..." required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="text" id="smbUsers" class="form-control" placeholder="user1, user2">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="button" class="btn btn-success w-100" onclick="addSMBShare()">
|
||||
Add SMB
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="smbList" class="table-responsive">
|
||||
<table class="table table-dark table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Path</th>
|
||||
<th>Valid Users</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="smbTableBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- NFS TAB -->
|
||||
<div id="nfs" class="tab-pane fade mt-4">
|
||||
<h3>NFS Exports</h3>
|
||||
|
||||
<form class="row g-3 mb-4">
|
||||
<div class="col-md-4">
|
||||
<input type="text" id="nfsPath" class="form-control" placeholder="/srv/data" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<input type="text" id="nfsClients" class="form-control" placeholder="192.168.1.0/24 or *">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-check">
|
||||
<input type="checkbox" id="nfsReadOnly" class="form-check-input">
|
||||
Read Only
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<button type="button" class="btn btn-success w-100" onclick="addNFSShare()">
|
||||
Add NFS
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="nfsList" class="table-responsive">
|
||||
<table class="table table-dark table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Path</th>
|
||||
<th>Clients</th>
|
||||
<th>Options</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="nfsTableBody"></tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- QUOTAS TAB -->
|
||||
<div id="quotas" class="tab-pane fade mt-4">
|
||||
<h3>Set Quotas</h3>
|
||||
|
||||
<form class="row g-3 mb-4">
|
||||
<div class="col-md-2">
|
||||
<select id="quotaType" class="form-select">
|
||||
<option value="smb">SMB</option>
|
||||
<option value="nfs">NFS</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input type="text" id="quotaUser" class="form-control" placeholder="Username">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input type="text" id="quotaPath" class="form-control" placeholder="/srv/data (NFS only)">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<input type="number" id="quotaGB" class="form-control" placeholder="Quota (GB)">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<button type="button" class="btn btn-warning w-100" onclick="setQuota()">
|
||||
Set Quota
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
async function addSMBShare() {
|
||||
const data = {
|
||||
name: document.getElementById('smbName').value,
|
||||
path: document.getElementById('smbPath').value,
|
||||
validUsers: document.getElementById('smbUsers').value
|
||||
};
|
||||
|
||||
const res = await fetch('/api/share/smb', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
alert('SMB Share created!');
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
async function addNFSShare() {
|
||||
const data = {
|
||||
path: document.getElementById('nfsPath').value,
|
||||
clients: document.getElementById('nfsClients').value,
|
||||
readOnly: document.getElementById('nfsReadOnly').checked
|
||||
};
|
||||
|
||||
const res = await fetch('/api/share/nfs', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
alert('NFS Export created!');
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
async function setQuota() {
|
||||
const data = {
|
||||
type: document.getElementById('quotaType').value,
|
||||
user: document.getElementById('quotaUser').value,
|
||||
path: document.getElementById('quotaPath').value,
|
||||
quota: document.getElementById('quotaGB').value
|
||||
};
|
||||
|
||||
const res = await fetch('/api/quota', {
|
||||
method: 'POST',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify(data)
|
||||
});
|
||||
|
||||
alert(res.ok ? 'Quota set!' : 'Error');
|
||||
}
|
||||
|
||||
// Load shares on startup
|
||||
async function loadShares() {
|
||||
const res = await fetch('/api/shares');
|
||||
const shares = await res.json();
|
||||
|
||||
// Populate SMB table
|
||||
const smbBody = document.getElementById('smbTableBody');
|
||||
shares.smb.forEach(share => {
|
||||
smbBody.innerHTML += `
|
||||
<tr>
|
||||
<td>${share.name}</td>
|
||||
<td>${share.path}</td>
|
||||
<td>${share.valid_users}</td>
|
||||
<td><button class="btn btn-sm btn-danger">Delete</button></td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
|
||||
// Populate NFS table
|
||||
const nfsBody = document.getElementById('nfsTableBody');
|
||||
shares.nfs.forEach(share => {
|
||||
nfsBody.innerHTML += `
|
||||
<tr>
|
||||
<td>${share.path}</td>
|
||||
<td>${share.clients}</td>
|
||||
<td>-</td>
|
||||
<td><button class="btn btn-sm btn-danger">Delete</button></td>
|
||||
</tr>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
loadShares();
|
||||
</script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user