From 88ebb4c60361d75306264f92efebbee1de902b6c Mon Sep 17 00:00:00 2001 From: Nathan Schneider Date: Mon, 8 Sep 2025 11:18:59 -0600 Subject: [PATCH] Add missing views/worlds/index.ejs and fix gitignore patterns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add views/worlds/index.ejs template file to repository - Update .gitignore to use /worlds/ instead of worlds/ to only exclude root-level worlds directory - This ensures application view templates are tracked while site-specific Luanti data remains ignored 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .gitignore | 2 +- views/worlds/index.ejs | 138 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 views/worlds/index.ejs diff --git a/.gitignore b/.gitignore index 1cb16d5..7db26a4 100644 --- a/.gitignore +++ b/.gitignore @@ -59,7 +59,7 @@ temp/ *.tmp # Luanti/Minetest specific files (if running locally) -worlds/ +/worlds/ mods/ games/ textures/ diff --git a/views/worlds/index.ejs b/views/worlds/index.ejs new file mode 100644 index 0000000..e651a92 --- /dev/null +++ b/views/worlds/index.ejs @@ -0,0 +1,138 @@ +<% +const body = ` + + + + + ${typeof worlds !== 'undefined' && worlds.length > 0 ? ` +
+ ${worlds.map(world => ` +
+
+

${world.displayName}

+ + ${world.creativeMode ? 'Creative' : 'Survival'} + +
+
+ ${world.description ? `

${world.description}

` : ''} +
+
+ Game: ${world.gameTitle || world.gameid} +
+
+ Players: ${world.playerCount || 0} +
+
+ PvP: ${world.enablePvp ? 'Enabled' : 'Disabled'} +
+
+ Damage: ${world.enableDamage ? 'Enabled' : 'Disabled'} +
+
+ Last Modified: ${new Date(world.lastModified).toLocaleDateString()} +
+
+
+ +
+ `).join('')} +
+ ` : ` +
+

No worlds created yet

+

Create your first world to get started with hosting Luanti servers.

+ Create First World +
+ `} + +`; +%> + +<%- include('../layout', { + body: body, + currentPage: 'worlds', + title: title, + inlineScript: ` + // Handle world creation progress + document.addEventListener('DOMContentLoaded', function() { + const urlParams = new URLSearchParams(window.location.search); + const creatingWorldName = urlParams.get('creating'); + + if (creatingWorldName) { + // Show creating alert + const creatingAlert = document.getElementById('creatingAlert'); + const creatingWorldNameSpan = document.getElementById('creatingWorldName'); + const progressBar = document.getElementById('progressBar'); + + if (creatingAlert && creatingWorldNameSpan) { + creatingWorldNameSpan.textContent = creatingWorldName; + creatingAlert.style.display = 'block'; + + // Quick progress animation (since creation is fast but not instant) + let progress = 0; + const progressInterval = setInterval(() => { + progress += 15; + if (progress > 85) progress = 85; // Don't complete until we get websocket confirmation + progressBar.style.width = progress + '%'; + }, 100); + + // Listen for websocket events + if (typeof socket !== 'undefined') { + socket.on('worldCreated', function(data) { + if (data.worldName === creatingWorldName) { + clearInterval(progressInterval); + + if (data.success) { + progressBar.style.width = '100%'; + setTimeout(() => { + // Remove the creating parameter and reload + const newUrl = new URL(window.location); + newUrl.searchParams.delete('creating'); + window.location.href = newUrl.toString(); + }, 500); + } else { + creatingAlert.className = 'alert alert-danger'; + creatingAlert.innerHTML = 'World creation failed:
' + + (data.error || 'Unknown error occurred'); + } + } + }); + } + + // Fallback: reload after 5 seconds if no websocket response + setTimeout(() => { + clearInterval(progressInterval); + const newUrl = new URL(window.location); + newUrl.searchParams.delete('creating'); + window.location.href = newUrl.toString(); + }, 5000); + } + } + }); + ` +}) %> \ No newline at end of file