Files
LuHost/views/layout.ejs
Nathan Schneider 8aadab1b50 Implement configuration-based mod management and fix navigation spacing
## Major Features Added

### Configuration-Based Mod Management
- Implement proper Luanti mod system using load_mod_* entries in world.mt
- Add mod enable/disable via configuration instead of file copying
- Support both global mods (config-enabled) and world mods (physically installed)
- Clear UI distinction with badges: "Global (Enabled)", "World Copy", "Missing"
- Automatic registry verification to sync database with filesystem state

### Game ID Alias System
- Fix minetest_game/minetest technical debt with proper alias mapping
- Map minetest_game → minetest for world.mt files (matches Luanti internal behavior)
- Reference: c9d4c33174/src/content/subgames.cpp (L21)

### Navigation Improvements
- Fix navigation menu spacing and text overflow issues
- Change "Configuration" to "Config" for better fit
- Implement responsive font sizing with clamp() for better scaling
- Even distribution of nav buttons across full width

### Package Registry Enhancements
- Add verifyAndCleanRegistry() to automatically remove stale package entries
- Periodic verification (every 5 minutes) to keep registry in sync with filesystem
- Fix "already installed" errors for manually deleted packages
- Integration across dashboard, ContentDB, and installation workflows

## Technical Improvements

### Mod System Architecture
- Enhanced ConfigParser to handle load_mod_* entries in world.mt files
- Support for both configuration-based and file-based mod installations
- Proper mod type detection and management workflows
- Updated world details to show comprehensive mod information

### UI/UX Enhancements
- Responsive navigation with proper text scaling
- Improved mod management interface with clear action buttons
- Better visual hierarchy and status indicators
- Enhanced error handling and user feedback

### Code Quality
- Clean up gitignore to properly exclude runtime files
- Add package-lock.json for consistent dependency management
- Remove excess runtime database and log files
- Add .claude/ directory to gitignore

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-08 10:31:08 -06:00

118 lines
4.7 KiB
Plaintext

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %> | LuHost</title>
<% if (typeof csrfToken !== 'undefined' && csrfToken) { %>
<meta name="csrf-token" content="<%= csrfToken %>">
<% } %>
<link rel="stylesheet" href="/static/css/style.css">
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
</head>
<body>
<div class="container">
<!-- Header -->
<header class="header">
<div style="display: flex; justify-content: space-between; align-items: flex-start; flex-wrap: wrap; gap: 1rem;">
<div style="text-align: left;">
<h1>LuHost</h1>
<p>Hosting Luanti made easy</p>
</div>
<% if (typeof isAuthenticated !== 'undefined' && isAuthenticated && typeof user !== 'undefined') { %>
<div style="text-align: right;">
<div style="color: var(--text-secondary); font-size: 0.875rem; margin-bottom: 0.5rem;">
Welcome, <strong><%= user.username %></strong>
</div>
<div style="display: flex; gap: 0.5rem; align-items: center;">
<span id="connection-status" class="status status-running">Connected</span>
<a href="/logout" class="btn btn-sm btn-secondary">Logout</a>
</div>
</div>
<% } else { %>
<div style="margin-top: 1rem;">
<span id="connection-status" class="status status-running">Connected</span>
</div>
<% } %>
</div>
</header>
<!-- Navigation (only show when authenticated) -->
<% if (typeof isAuthenticated !== 'undefined' && isAuthenticated) { %>
<nav class="nav">
<div class="nav-item">
<a href="/" class="nav-link <%= currentPage === 'dashboard' ? 'active' : '' %>">
Dashboard
</a>
</div>
<div class="nav-item">
<a href="/worlds" class="nav-link <%= currentPage === 'worlds' ? 'active' : '' %>">
Worlds
</a>
</div>
<div class="nav-item">
<a href="/mods" class="nav-link <%= currentPage === 'mods' ? 'active' : '' %>">
Mods
</a>
</div>
<div class="nav-item">
<a href="/extensions" class="nav-link <%= currentPage === 'extensions' ? 'active' : '' %>">
Extensions
</a>
</div>
<div class="nav-item">
<a href="/server" class="nav-link <%= currentPage === 'server' ? 'active' : '' %>">
Server
</a>
</div>
<div class="nav-item">
<a href="/config" class="nav-link <%= currentPage === 'config' ? 'active' : '' %>">
Config
</a>
</div>
<div class="nav-item">
<a href="/users" class="nav-link <%= currentPage === 'users' ? 'active' : '' %>">
Users
</a>
</div>
</nav>
<% } %>
<!-- Main Content -->
<main>
<%- body %>
</main>
<!-- Footer -->
<footer style="margin-top: 2rem; padding: 2rem; text-align: center; color: var(--text-secondary); font-size: 0.875rem;">
<p><a href="https://git.medlab.host/Modpol/luhost" target="_blank" style="color: var(--primary-color);">LuHost</a> |
<a href="https://luanti.org" target="_blank" style="color: var(--primary-color);">Luanti</a> |
<a href="https://content.luanti.org" target="_blank" style="color: var(--primary-color);">ContentDB</a>
</p>
<p>A project of the <a href="https://www.colorado.edu/lab/medlab/" target="_blank" style="color: var(--primary-color);">Media Economies Design Lab</a></p>
</footer>
</div>
<!-- Socket.IO -->
<script src="/socket.io/socket.io.js"></script>
<!-- Main JavaScript -->
<script src="/static/js/main.js"></script>
<!-- Page-specific scripts -->
<% if (typeof scripts !== 'undefined') { %>
<% scripts.forEach(function(script) { %>
<script src="/static/js/<%= script %>"></script>
<% }); %>
<% } %>
<!-- Inline scripts -->
<% if (typeof inlineScript !== 'undefined') { %>
<script>
<%- inlineScript %>
</script>
<% } %>
</body>
</html>