feat: Introduce initial web frontend and backend services, and generalize directory configuration in docker-compose.
This commit is contained in:
parent
6b03709b30
commit
d76ad89f09
@ -52,7 +52,7 @@ SUPPORTED_EXTENSIONS = {
|
||||
|
||||
|
||||
def load_vault_config() -> Dict[str, Dict[str, Any]]:
|
||||
"""Read VAULT_N_* env vars and return vault configuration.
|
||||
"""Read VAULT_N_* and DIR_N_* env vars and return vault configuration.
|
||||
|
||||
Scans environment variables ``VAULT_1_NAME``/``VAULT_1_PATH``,
|
||||
``VAULT_2_NAME``/``VAULT_2_PATH``, etc. in sequential order.
|
||||
@ -67,6 +67,7 @@ def load_vault_config() -> Dict[str, Dict[str, Any]]:
|
||||
- path: filesystem path (required)
|
||||
- attachmentsPath: relative attachments folder (optional)
|
||||
- scanAttachmentsOnStartup: boolean (default True)
|
||||
- type: "VAULT" or "DIR"
|
||||
"""
|
||||
vaults: Dict[str, Dict[str, Any]] = {}
|
||||
n = 1
|
||||
@ -84,8 +85,25 @@ def load_vault_config() -> Dict[str, Dict[str, Any]]:
|
||||
"path": path,
|
||||
"attachmentsPath": attachments_path,
|
||||
"scanAttachmentsOnStartup": scan_attachments,
|
||||
"type": "VAULT"
|
||||
}
|
||||
n += 1
|
||||
|
||||
n = 1
|
||||
while True:
|
||||
name = os.environ.get(f"DIR_{n}_NAME")
|
||||
path = os.environ.get(f"DIR_{n}_PATH")
|
||||
if not name or not path:
|
||||
break
|
||||
|
||||
vaults[name] = {
|
||||
"path": path,
|
||||
"attachmentsPath": None,
|
||||
"scanAttachmentsOnStartup": False,
|
||||
"type": "DIR"
|
||||
}
|
||||
n += 1
|
||||
|
||||
return vaults
|
||||
|
||||
|
||||
|
||||
@ -59,6 +59,7 @@ class VaultInfo(BaseModel):
|
||||
name: str = Field(description="Display name of the vault")
|
||||
file_count: int = Field(description="Number of indexed files")
|
||||
tag_count: int = Field(description="Number of unique tags")
|
||||
type: str = Field(default="VAULT", description="Type of the vault mapping (VAULT or DIR)")
|
||||
|
||||
|
||||
class BrowseItem(BaseModel):
|
||||
@ -603,10 +604,12 @@ async def api_vaults(current_user=Depends(require_auth)):
|
||||
result = []
|
||||
for name, data in index.items():
|
||||
if "*" in user_vaults or name in user_vaults:
|
||||
v_type = vault_config.get(name, {}).get("type", "VAULT")
|
||||
result.append({
|
||||
"name": name,
|
||||
"file_count": len(data["files"]),
|
||||
"tag_count": len(data["tags"]),
|
||||
"type": v_type,
|
||||
})
|
||||
return result
|
||||
|
||||
|
||||
@ -39,8 +39,8 @@ services:
|
||||
- VAULT_4_PATH=/vaults/Obsidian_WORKOUT
|
||||
- VAULT_5_NAME=Sessions
|
||||
- VAULT_5_PATH=/vaults/SessionsManager
|
||||
- VAULT_6_NAME=Bruno
|
||||
- VAULT_6_PATH=/vaults/bruno
|
||||
- DIR_1_NAME=Bruno
|
||||
- DIR_1_PATH=/vaults/bruno
|
||||
# Auth configuration (uncomment to enable)
|
||||
- OBSIGATE_AUTH_ENABLED=true
|
||||
- OBSIGATE_ADMIN_USER=admin
|
||||
|
||||
@ -1400,7 +1400,7 @@
|
||||
vaultsToShow.forEach((v) => {
|
||||
const vaultItem = el("div", { class: "tree-item vault-item", "data-vault": v.name }, [
|
||||
icon("chevron-right", 14),
|
||||
icon("database", 16),
|
||||
getVaultIcon(v.name, 16),
|
||||
document.createTextNode(` ${v.name} `),
|
||||
smallBadge(v.file_count),
|
||||
]);
|
||||
@ -1457,7 +1457,7 @@
|
||||
// Sidebar tree entry
|
||||
const vaultItem = el("div", { class: "tree-item vault-item", "data-vault": v.name }, [
|
||||
icon("chevron-right", 14),
|
||||
icon("database", 16),
|
||||
getVaultIcon(v.name, 16),
|
||||
document.createTextNode(` ${v.name} `),
|
||||
smallBadge(v.file_count),
|
||||
]);
|
||||
@ -1736,7 +1736,7 @@
|
||||
entries.sort((a, b) => a.path.localeCompare(b.path, undefined, { sensitivity: "base" }));
|
||||
|
||||
const vaultHeader = el("div", { class: "tree-item vault-item filter-results-header", "data-vault": vaultName }, [
|
||||
icon("database", 16),
|
||||
getVaultIcon(vaultName, 16),
|
||||
document.createTextNode(` ${vaultName} `),
|
||||
smallBadge(entries.length),
|
||||
]);
|
||||
@ -3296,6 +3296,46 @@
|
||||
return s;
|
||||
}
|
||||
|
||||
function getVaultIcon(vaultName, size = 16) {
|
||||
const v = allVaults.find((val) => val.name === vaultName);
|
||||
const type = v ? v.type : "VAULT";
|
||||
|
||||
if (type === "DIR") {
|
||||
const i = icon("folder", size);
|
||||
i.style.color = "#eab308"; // yellow tint
|
||||
return i;
|
||||
} else {
|
||||
const purple = "#8b5cf6";
|
||||
const svgNS = "http://www.w3.org/2000/svg";
|
||||
const svg = document.createElementNS(svgNS, "svg");
|
||||
svg.setAttribute("xmlns", svgNS);
|
||||
svg.setAttribute("width", size);
|
||||
svg.setAttribute("height", size);
|
||||
svg.setAttribute("viewBox", "0 0 24 24");
|
||||
svg.setAttribute("fill", "none");
|
||||
svg.setAttribute("stroke", purple);
|
||||
svg.setAttribute("stroke-width", "2");
|
||||
svg.setAttribute("stroke-linecap", "round");
|
||||
svg.setAttribute("stroke-linejoin", "round");
|
||||
svg.classList.add("icon");
|
||||
|
||||
const path1 = document.createElementNS(svgNS, "path");
|
||||
path1.setAttribute("d", "M6 3h12l4 6-10 12L2 9z");
|
||||
const path2 = document.createElementNS(svgNS, "path");
|
||||
path2.setAttribute("d", "M11 3 8 9l4 12");
|
||||
const path3 = document.createElementNS(svgNS, "path");
|
||||
path3.setAttribute("d", "M12 21l4-12-3-6");
|
||||
const path4 = document.createElementNS(svgNS, "path");
|
||||
path4.setAttribute("d", "M2 9h20");
|
||||
|
||||
svg.appendChild(path1);
|
||||
svg.appendChild(path2);
|
||||
svg.appendChild(path3);
|
||||
svg.appendChild(path4);
|
||||
return svg;
|
||||
}
|
||||
}
|
||||
|
||||
function makeBreadcrumbSpan(text, onClick) {
|
||||
const s = document.createElement("span");
|
||||
s.textContent = text;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user