Add file editing capability with CodeMirror 6 integration, loading indicator for searches, and clickable home logo
This commit is contained in:
parent
1213eb4781
commit
ae46e62902
@ -195,6 +195,39 @@ async def api_file_download(vault_name: str, path: str = Query(..., description=
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.put("/api/file/{vault_name}/save")
|
||||||
|
async def api_file_save(vault_name: str, path: str = Query(..., description="Relative path to file"), body: dict = {}):
|
||||||
|
"""Save file content."""
|
||||||
|
vault_data = get_vault_data(vault_name)
|
||||||
|
if not vault_data:
|
||||||
|
raise HTTPException(status_code=404, detail=f"Vault '{vault_name}' not found")
|
||||||
|
|
||||||
|
vault_root = Path(vault_data["path"])
|
||||||
|
file_path = vault_root / path
|
||||||
|
|
||||||
|
# Security: ensure path is within vault
|
||||||
|
try:
|
||||||
|
file_path.resolve().relative_to(vault_root.resolve())
|
||||||
|
except ValueError:
|
||||||
|
raise HTTPException(status_code=403, detail="Access denied: path outside vault")
|
||||||
|
|
||||||
|
if not file_path.exists():
|
||||||
|
raise HTTPException(status_code=404, detail=f"File not found: {path}")
|
||||||
|
|
||||||
|
# Get content from body
|
||||||
|
content = body.get('content', '')
|
||||||
|
|
||||||
|
try:
|
||||||
|
file_path.write_text(content, encoding="utf-8")
|
||||||
|
logger.info(f"File saved: {vault_name}/{path}")
|
||||||
|
return {"status": "ok", "vault": vault_name, "path": path, "size": len(content)}
|
||||||
|
except PermissionError:
|
||||||
|
raise HTTPException(status_code=403, detail="Permission denied: vault may be read-only")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error saving file {vault_name}/{path}: {e}")
|
||||||
|
raise HTTPException(status_code=500, detail=f"Error saving file: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
@app.get("/api/file/{vault_name}")
|
@app.get("/api/file/{vault_name}")
|
||||||
async def api_file(vault_name: str, path: str = Query(..., description="Relative path to file")):
|
async def api_file(vault_name: str, path: str = Query(..., description="Relative path to file")):
|
||||||
"""Return rendered HTML + metadata for a file."""
|
"""Return rendered HTML + metadata for a file."""
|
||||||
|
|||||||
193
frontend/app.js
193
frontend/app.js
@ -13,6 +13,9 @@
|
|||||||
let cachedRawSource = null;
|
let cachedRawSource = null;
|
||||||
let allVaults = [];
|
let allVaults = [];
|
||||||
let selectedContextVault = "all";
|
let selectedContextVault = "all";
|
||||||
|
let editorView = null;
|
||||||
|
let editorVault = null;
|
||||||
|
let editorPath = null;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// File extension → Lucide icon mapping
|
// File extension → Lucide icon mapping
|
||||||
@ -476,6 +479,14 @@
|
|||||||
document.body.removeChild(a);
|
document.body.removeChild(a);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const editBtn = el("button", { class: "btn-action", title: "Éditer" }, [
|
||||||
|
icon("edit", 14),
|
||||||
|
document.createTextNode("Éditer"),
|
||||||
|
]);
|
||||||
|
editBtn.addEventListener("click", () => {
|
||||||
|
openEditor(data.vault, data.path);
|
||||||
|
});
|
||||||
|
|
||||||
// Frontmatter
|
// Frontmatter
|
||||||
let fmSection = null;
|
let fmSection = null;
|
||||||
if (data.frontmatter && Object.keys(data.frontmatter).length > 0) {
|
if (data.frontmatter && Object.keys(data.frontmatter).length > 0) {
|
||||||
@ -529,7 +540,7 @@
|
|||||||
area.appendChild(el("div", { class: "file-header" }, [
|
area.appendChild(el("div", { class: "file-header" }, [
|
||||||
el("div", { class: "file-title" }, [document.createTextNode(data.title)]),
|
el("div", { class: "file-title" }, [document.createTextNode(data.title)]),
|
||||||
tagsDiv,
|
tagsDiv,
|
||||||
el("div", { class: "file-actions" }, [copyBtn, sourceBtn, downloadBtn]),
|
el("div", { class: "file-actions" }, [copyBtn, sourceBtn, downloadBtn, editBtn]),
|
||||||
]));
|
]));
|
||||||
if (fmSection) area.appendChild(fmSection);
|
if (fmSection) area.appendChild(fmSection);
|
||||||
area.appendChild(mdDiv);
|
area.appendChild(mdDiv);
|
||||||
@ -574,6 +585,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function performSearch(query, vaultFilter, tagFilter) {
|
async function performSearch(query, vaultFilter, tagFilter) {
|
||||||
|
showLoading();
|
||||||
|
|
||||||
let url = `/api/search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}`;
|
let url = `/api/search?q=${encodeURIComponent(query)}&vault=${encodeURIComponent(vaultFilter)}`;
|
||||||
if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`;
|
if (tagFilter) url += `&tag=${encodeURIComponent(tagFilter)}`;
|
||||||
|
|
||||||
@ -754,18 +767,196 @@
|
|||||||
safeCreateIcons();
|
safeCreateIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showLoading() {
|
||||||
|
const area = document.getElementById("content-area");
|
||||||
|
area.innerHTML = `
|
||||||
|
<div class="loading-indicator">
|
||||||
|
<div class="loading-spinner"></div>
|
||||||
|
<div>Recherche en cours...</div>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function goHome() {
|
||||||
|
const searchInput = document.getElementById("search-input");
|
||||||
|
if (searchInput) searchInput.value = "";
|
||||||
|
|
||||||
|
document.querySelectorAll(".tree-item.active").forEach((el) => el.classList.remove("active"));
|
||||||
|
|
||||||
|
currentVault = null;
|
||||||
|
currentPath = null;
|
||||||
|
showingSource = false;
|
||||||
|
cachedRawSource = null;
|
||||||
|
|
||||||
|
closeMobileSidebar();
|
||||||
|
showWelcome();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Editor (CodeMirror)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
async function openEditor(vaultName, filePath) {
|
||||||
|
editorVault = vaultName;
|
||||||
|
editorPath = filePath;
|
||||||
|
|
||||||
|
const modal = document.getElementById("editor-modal");
|
||||||
|
const titleEl = document.getElementById("editor-title");
|
||||||
|
const bodyEl = document.getElementById("editor-body");
|
||||||
|
|
||||||
|
titleEl.textContent = `Édition: ${filePath.split("/").pop()}`;
|
||||||
|
|
||||||
|
// Fetch raw content
|
||||||
|
const rawUrl = `/api/file/${encodeURIComponent(vaultName)}/raw?path=${encodeURIComponent(filePath)}`;
|
||||||
|
const rawData = await api(rawUrl);
|
||||||
|
|
||||||
|
// Clear previous editor
|
||||||
|
bodyEl.innerHTML = "";
|
||||||
|
if (editorView) {
|
||||||
|
editorView.destroy();
|
||||||
|
editorView = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for CodeMirror to be available
|
||||||
|
await waitForCodeMirror();
|
||||||
|
|
||||||
|
const { EditorView, EditorState, basicSetup, markdown, oneDark, keymap } = window.CodeMirror;
|
||||||
|
|
||||||
|
// Determine theme
|
||||||
|
const currentTheme = document.documentElement.getAttribute("data-theme");
|
||||||
|
const extensions = [
|
||||||
|
basicSetup,
|
||||||
|
markdown(),
|
||||||
|
keymap.of([{
|
||||||
|
key: "Mod-s",
|
||||||
|
run: () => {
|
||||||
|
saveFile();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}]),
|
||||||
|
EditorView.lineWrapping,
|
||||||
|
];
|
||||||
|
|
||||||
|
if (currentTheme === "dark") {
|
||||||
|
extensions.push(oneDark);
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = EditorState.create({
|
||||||
|
doc: rawData.raw,
|
||||||
|
extensions: extensions,
|
||||||
|
});
|
||||||
|
|
||||||
|
editorView = new EditorView({
|
||||||
|
state: state,
|
||||||
|
parent: bodyEl,
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.classList.add("active");
|
||||||
|
safeCreateIcons();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitForCodeMirror() {
|
||||||
|
let attempts = 0;
|
||||||
|
while (!window.CodeMirror && attempts < 50) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
attempts++;
|
||||||
|
}
|
||||||
|
if (!window.CodeMirror) {
|
||||||
|
throw new Error("CodeMirror failed to load");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeEditor() {
|
||||||
|
const modal = document.getElementById("editor-modal");
|
||||||
|
modal.classList.remove("active");
|
||||||
|
if (editorView) {
|
||||||
|
editorView.destroy();
|
||||||
|
editorView = null;
|
||||||
|
}
|
||||||
|
editorVault = null;
|
||||||
|
editorPath = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveFile() {
|
||||||
|
if (!editorView || !editorVault || !editorPath) return;
|
||||||
|
|
||||||
|
const content = editorView.state.doc.toString();
|
||||||
|
const saveBtn = document.getElementById("editor-save");
|
||||||
|
const originalText = saveBtn.textContent;
|
||||||
|
|
||||||
|
try {
|
||||||
|
saveBtn.disabled = true;
|
||||||
|
saveBtn.innerHTML = '<i data-lucide="loader" style="width:14px;height:14px"></i> Sauvegarde...';
|
||||||
|
safeCreateIcons();
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/file/${encodeURIComponent(editorVault)}/save?path=${encodeURIComponent(editorPath)}`,
|
||||||
|
{
|
||||||
|
method: "PUT",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({ content: content }),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const error = await response.json();
|
||||||
|
throw new Error(error.detail || "Erreur de sauvegarde");
|
||||||
|
}
|
||||||
|
|
||||||
|
saveBtn.innerHTML = '<i data-lucide="check" style="width:14px;height:14px"></i> Sauvegardé !';
|
||||||
|
safeCreateIcons();
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
closeEditor();
|
||||||
|
// Reload the file if it's currently open
|
||||||
|
if (currentVault === editorVault && currentPath === editorPath) {
|
||||||
|
openFile(currentVault, currentPath);
|
||||||
|
}
|
||||||
|
}, 800);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Save error:", err);
|
||||||
|
alert(`Erreur: ${err.message}`);
|
||||||
|
saveBtn.innerHTML = originalText;
|
||||||
|
saveBtn.disabled = false;
|
||||||
|
safeCreateIcons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initEditor() {
|
||||||
|
const cancelBtn = document.getElementById("editor-cancel");
|
||||||
|
const saveBtn = document.getElementById("editor-save");
|
||||||
|
const modal = document.getElementById("editor-modal");
|
||||||
|
|
||||||
|
cancelBtn.addEventListener("click", closeEditor);
|
||||||
|
saveBtn.addEventListener("click", saveFile);
|
||||||
|
|
||||||
|
// Close on overlay click
|
||||||
|
modal.addEventListener("click", (e) => {
|
||||||
|
if (e.target === modal) {
|
||||||
|
closeEditor();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// ESC to close
|
||||||
|
document.addEventListener("keydown", (e) => {
|
||||||
|
if (e.key === "Escape" && modal.classList.contains("active")) {
|
||||||
|
closeEditor();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Init
|
// Init
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
async function init() {
|
async function init() {
|
||||||
initTheme();
|
initTheme();
|
||||||
document.getElementById("theme-toggle").addEventListener("click", toggleTheme);
|
document.getElementById("theme-toggle").addEventListener("click", toggleTheme);
|
||||||
|
document.getElementById("header-logo").addEventListener("click", goHome);
|
||||||
initSearch();
|
initSearch();
|
||||||
initMobile();
|
initMobile();
|
||||||
initVaultContext();
|
initVaultContext();
|
||||||
initSidebarFilter();
|
initSidebarFilter();
|
||||||
initSidebarResize();
|
initSidebarResize();
|
||||||
initTagResize();
|
initTagResize();
|
||||||
|
initEditor();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all([loadVaults(), loadTags()]);
|
await Promise.all([loadVaults(), loadTags()]);
|
||||||
|
|||||||
@ -9,6 +9,16 @@
|
|||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css" id="hljs-theme-light" disabled>
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css" id="hljs-theme-light" disabled>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
||||||
<script src="https://unpkg.com/lucide@0.344.0/dist/umd/lucide.min.js"></script>
|
<script src="https://unpkg.com/lucide@0.344.0/dist/umd/lucide.min.js"></script>
|
||||||
|
|
||||||
|
<!-- CodeMirror 6 -->
|
||||||
|
<script type="module">
|
||||||
|
import { EditorView, basicSetup } from "https://esm.sh/@codemirror/basic-setup@0.20.0";
|
||||||
|
import { EditorState } from "https://esm.sh/@codemirror/state@6.2.0";
|
||||||
|
import { markdown } from "https://esm.sh/@codemirror/lang-markdown@6.1.0";
|
||||||
|
import { oneDark } from "https://esm.sh/@codemirror/theme-one-dark@6.1.0";
|
||||||
|
import { keymap } from "https://esm.sh/@codemirror/view@6.9.0";
|
||||||
|
window.CodeMirror = { EditorView, EditorState, basicSetup, markdown, oneDark, keymap };
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="app-container">
|
<div class="app-container">
|
||||||
@ -19,7 +29,7 @@
|
|||||||
<i data-lucide="menu" style="width:20px;height:20px"></i>
|
<i data-lucide="menu" style="width:20px;height:20px"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="header-logo">
|
<div class="header-logo" id="header-logo">
|
||||||
<i data-lucide="book-open" style="width:20px;height:20px"></i>
|
<i data-lucide="book-open" style="width:20px;height:20px"></i>
|
||||||
ObsiGate
|
ObsiGate
|
||||||
</div>
|
</div>
|
||||||
@ -81,6 +91,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Editor Modal -->
|
||||||
|
<div class="editor-modal" id="editor-modal">
|
||||||
|
<div class="editor-container">
|
||||||
|
<div class="editor-header">
|
||||||
|
<div class="editor-title" id="editor-title">Édition</div>
|
||||||
|
<div class="editor-actions">
|
||||||
|
<button class="editor-btn" id="editor-cancel">
|
||||||
|
<i data-lucide="x" style="width:14px;height:14px"></i>
|
||||||
|
Annuler
|
||||||
|
</button>
|
||||||
|
<button class="editor-btn primary" id="editor-save">
|
||||||
|
<i data-lucide="save" style="width:14px;height:14px"></i>
|
||||||
|
Sauvegarder
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="editor-body" id="editor-body"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="/static/app.js"></script>
|
<script src="/static/app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@ -118,6 +118,13 @@ a:hover {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 200ms ease;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.header-logo:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-wrapper {
|
.search-wrapper {
|
||||||
@ -741,6 +748,150 @@ a:hover {
|
|||||||
padding: 1px 6px;
|
padding: 1px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- Loading indicator --- */
|
||||||
|
.loading-indicator {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 40px 20px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.loading-spinner {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border: 3px solid var(--border);
|
||||||
|
border-top-color: var(--accent);
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 0.8s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --- Editor Modal --- */
|
||||||
|
.editor-modal {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
background: var(--overlay-bg);
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.editor-modal.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-container {
|
||||||
|
background: var(--bg-secondary);
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 12px;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 1200px;
|
||||||
|
max-height: 90vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 12px 16px;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
background: var(--bg-primary);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-title {
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-btn {
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
padding: 6px 12px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
border-radius: 6px;
|
||||||
|
background: transparent;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 150ms ease;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
|
.editor-btn:hover {
|
||||||
|
color: var(--accent);
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
.editor-btn.primary {
|
||||||
|
background: var(--accent);
|
||||||
|
color: #ffffff;
|
||||||
|
border-color: var(--accent);
|
||||||
|
}
|
||||||
|
.editor-btn.primary:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-body {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-editor {
|
||||||
|
height: 100%;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-scroller {
|
||||||
|
font-family: 'JetBrains Mono', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mobile editor */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.editor-modal {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-container {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 100vh;
|
||||||
|
border-radius: 0;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-header {
|
||||||
|
padding: 10px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-title {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.editor-btn {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --- No-select during resize --- */
|
/* --- No-select during resize --- */
|
||||||
body.resizing {
|
body.resizing {
|
||||||
user-select: none;
|
user-select: none;
|
||||||
@ -768,12 +919,13 @@ body.resizing-v {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
gap: 8px;
|
gap: 6px;
|
||||||
padding: 8px 12px;
|
padding: 8px 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-logo {
|
.header-logo {
|
||||||
font-size: 1rem;
|
font-size: 0.95rem;
|
||||||
|
gap: 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-wrapper {
|
.search-wrapper {
|
||||||
@ -781,9 +933,14 @@ body.resizing-v {
|
|||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-wrapper input {
|
||||||
|
padding: 6px 10px 6px 32px;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
.search-vault-filter {
|
.search-vault-filter {
|
||||||
font-size: 0.72rem;
|
font-size: 0.7rem;
|
||||||
padding: 5px 6px;
|
padding: 4px 6px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
@ -808,6 +965,16 @@ body.resizing-v {
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag-resize-handle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-cloud-section {
|
||||||
|
height: auto;
|
||||||
|
max-height: 200px;
|
||||||
|
min-height: 80px;
|
||||||
|
}
|
||||||
|
|
||||||
.content-area {
|
.content-area {
|
||||||
padding: 16px 12px 60px;
|
padding: 16px 12px 60px;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user