Enhance note-taking features by adding label support, improving modal styles, and refining CSS for better responsiveness. Update login page title and adjust password management UI for better usability.

This commit is contained in:
root
2026-03-27 20:04:52 +07:00
parent 937033ea07
commit 99f948ba5d
5 changed files with 188 additions and 48 deletions

View File

@@ -217,11 +217,10 @@ $active_folder = $_GET['vault_folder'] ?? 'all';
<input type="hidden" name="delete_password" value="1">
<input type="hidden" name="password_id" id="delete-pw-id">
</form>
<div style="display:flex; justify-content:flex-end; gap:0.5rem; flex-wrap:wrap; margin-bottom:1rem;">
<button class="btn btn-secondary" onclick="showAddFolderPrompt()"><i class="fa fa-folder-plus"></i> New Folder</button>
<button class="btn" onclick="openAddPassword()"><i class="fa fa-plus"></i> Add Entry</button>
</div>
<form method="POST" id="remove-share-form" style="display:none;">
<input type="hidden" name="remove_password_share" value="1">
<input type="hidden" name="share_id" id="remove-share-id">
</form>
<!-- Add folder form (hidden) -->
<form method="POST" id="add-folder-form" style="display:none;">
@@ -234,7 +233,7 @@ $active_folder = $_GET['vault_folder'] ?? 'all';
</form>
<div style="background:var(--surface); border-radius:1rem; box-shadow:0 4px 6px -1px rgba(0,0,0,0.07); border:1px solid var(--border); overflow:hidden;">
<div class="vault-layout" style="min-height:calc(100vh - 200px);">
<div class="vault-layout" style="min-height:calc(100vh - 130px);">
<!-- Vault Sidebar (Folders) -->
<div class="vault-sidebar">
<div style="font-size:0.7rem; text-transform:uppercase; letter-spacing:0.06em; color:var(--text-light); font-weight:700; padding:0.25rem 0.65rem; margin-bottom:0.25rem;">Folders</div>
@@ -265,6 +264,10 @@ $active_folder = $_GET['vault_folder'] ?? 'all';
<!-- Vault Main -->
<div class="vault-main">
<div style="display:flex; justify-content:flex-end; gap:0.5rem; flex-wrap:wrap; margin-bottom:1rem;">
<button class="btn btn-secondary" onclick="showAddFolderPrompt()"><i class="fa fa-folder-plus"></i> New Folder</button>
<button class="btn" onclick="openAddPassword()"><i class="fa fa-plus"></i> Add Entry</button>
</div>
<!-- Search + Bulk Actions -->
<div class="vault-search">
<div style="position:relative; flex:1;">
@@ -347,11 +350,20 @@ $active_folder = $_GET['vault_folder'] ?? 'all';
$domain = preg_replace('/^www\./', '', $domain);
}
$favicon = $domain ? "https://www.google.com/s2/favicons?domain={$domain}&sz=32" : '';
$pw_shares = [];
if($p['is_mine']) {
$pw_shares = query("SELECT ps.id, ps.share_type, ps.share_id, u.username, g.name as gname FROM password_shares ps LEFT JOIN users u ON (ps.share_type='user' AND ps.share_id=u.id) LEFT JOIN groups g ON (ps.share_type='group' AND ps.share_id=g.id) WHERE ps.password_id=?", [$p['id']])->fetchAll();
}
$shares_json = htmlspecialchars(json_encode($pw_shares), ENT_QUOTES, 'UTF-8');
?>
<div class="vault-entry pw-row"
data-pw="<?= htmlspecialchars(addslashes($p['password'])) ?>"
data-usr="<?= htmlspecialchars((string)$p['username']) ?>"
data-id="<?= $p['id'] ?>"
data-url="<?= htmlspecialchars((string)($p['url'] ?? '')) ?>"
data-notes="<?= htmlspecialchars(addslashes((string)($p['notes'] ?? ''))) ?>"
data-folder-id="<?= htmlspecialchars((string)($p['folder_id'] ?? '')) ?>"
data-shares="<?= $shares_json ?>"
onclick="openViewEntry(this)">
<!-- Checkbox (only for owned items) -->
<?php if($p['is_mine']): ?>
@@ -463,8 +475,8 @@ function openViewEntry(row) {
document.getElementById('pw-view-toggle').innerHTML = '<i class="fa fa-eye"></i>';
const urlEl = document.getElementById('pw-view-url');
urlEl.textContent = '';
// try to show url from data attribute if we add it - just show username for now
document.getElementById('pw-view-notes').textContent = '';
urlEl.textContent = row.dataset.url || '';
document.getElementById('pw-view-notes').textContent = row.dataset.notes || '';
document.getElementById('password-view-modal').classList.add('active');
}
@@ -492,6 +504,8 @@ function openAddPassword() {
document.getElementById('pw-edit-url').value = '';
document.getElementById('pw-edit-notes').value = '';
document.getElementById('pw-edit-folder').value = '';
document.getElementById('pw-shares-section').style.display = 'none';
document.getElementById('pw-shares-list').innerHTML = '';
document.getElementById('pw-edit-delete-wrap').style.display = 'none';
document.getElementById('pw-edit-pw').dispatchEvent(new Event('input'));
document.getElementById('password-edit-modal').classList.add('active');
@@ -517,13 +531,48 @@ function openEditEntry(row) {
document.getElementById('pw-edit-uname').value = row.dataset.usr;
document.getElementById('pw-edit-pw').value = row.dataset.pw;
document.getElementById('pw-edit-pw').type = 'password';
document.getElementById('pw-edit-url').value = '';
document.getElementById('pw-edit-notes').value = '';
document.getElementById('pw-edit-folder').value = '';
document.getElementById('pw-edit-url').value = row.dataset.url || '';
document.getElementById('pw-edit-notes').value = row.dataset.notes || '';
document.getElementById('pw-edit-folder').value = row.dataset.folderId || '';
document.getElementById('pw-edit-delete-wrap').style.display = 'block';
renderPasswordShares(row.dataset.shares || '[]');
document.getElementById('password-edit-modal').classList.add('active');
}
function renderPasswordShares(jsonShares) {
const sec = document.getElementById('pw-shares-section');
const list = document.getElementById('pw-shares-list');
list.innerHTML = '';
let shares = [];
try { shares = JSON.parse(jsonShares || '[]'); } catch(e) { shares = []; }
if(!shares || shares.length === 0) {
sec.style.display = 'none';
return;
}
shares.forEach(sh => {
const label = sh.share_type === 'user' ? ('👤 ' + (sh.username || 'User')) : ('👥 ' + (sh.gname || 'Group'));
const chip = document.createElement('div');
chip.style.display = 'inline-flex';
chip.style.alignItems = 'center';
chip.style.gap = '0.35rem';
chip.style.fontSize = '0.72rem';
chip.style.padding = '3px 7px';
chip.style.borderRadius = '999px';
chip.style.background = 'rgba(var(--primary-rgb),0.12)';
chip.style.color = 'var(--primary)';
chip.innerHTML = `<span>${label}</span><button type="button" style="border:none;background:transparent;color:inherit;cursor:pointer;line-height:1;" title="Unshare" onclick="removePasswordShare(${Number(sh.id)})">×</button>`;
list.appendChild(chip);
});
sec.style.display = 'block';
}
function removePasswordShare(shareId) {
if(!shareId) return;
if(!confirm('Unshare this password access?')) return;
document.getElementById('remove-share-id').value = String(shareId);
document.getElementById('remove-share-form').submit();
}
function deletePassword() {
if(!confirm('Delete this entry permanently?')) return;
document.getElementById('delete-pw-id').value = document.getElementById('pw-edit-id').value;