diff --git a/views/mods/details.ejs b/views/mods/details.ejs new file mode 100644 index 0000000..dac5d12 --- /dev/null +++ b/views/mods/details.ejs @@ -0,0 +1,150 @@ +<% +const body = ` + + +
+
+
+

Mod Information

+
+
+
+
Name: ${mod.name}
+
Author: ${mod.author || 'Unknown'}
+
Files: ${mod.fileCount} files
+
Size: ${(mod.totalSize / 1024).toFixed(2)} KB
+
Created: ${new Date(mod.created).toLocaleString()}
+
Modified: ${new Date(mod.lastModified).toLocaleString()}
+ ${mod.min_minetest_version ? `
Min Version: ${mod.min_minetest_version}
` : ''} + ${mod.max_minetest_version ? `
Max Version: ${mod.max_minetest_version}
` : ''} +
+ + ${mod.depends.length > 0 ? ` +
+ Dependencies: +
+ ${mod.depends.map(dep => `${dep}`).join('')} +
+
+ ` : ''} + + ${mod.optional_depends.length > 0 ? ` +
+ Optional Dependencies: +
+ ${mod.optional_depends.map(dep => `${dep}`).join('')} +
+
+ ` : ''} +
+
+ + ${mod.installedWorlds.length > 0 ? ` +
+
+

Installed in Worlds (${mod.installedWorlds.length})

+
+
+
+ ${mod.installedWorlds.map(world => ` +
+
+ ${world.displayName} + (${world.name}) +
+
+
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} + +
+
+
+ `).join('')} +
+
+
+ ` : ''} + +
+
+

Actions

+
+
+
+ ← Back to Mods +
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} + +
+
+
+
+
+ + +`; +%> + +<%- include('../layout', { body: body, currentPage: 'mods', title: title }) %> \ No newline at end of file diff --git a/views/mods/index.ejs b/views/mods/index.ejs new file mode 100644 index 0000000..8ad5a41 --- /dev/null +++ b/views/mods/index.ejs @@ -0,0 +1,275 @@ +<% +const body = ` + + + ${typeof req !== 'undefined' && req.query && req.query.enabled ? ` +
+ Mod "${req.query.enabled}" enabled for ${selectedWorld}! +
+ ` : ''} + + ${typeof req !== 'undefined' && req.query && req.query.disabled ? ` +
+ Mod "${req.query.disabled}" disabled for ${selectedWorld}! +
+ ` : ''} + + ${typeof req !== 'undefined' && req.query && req.query.copied ? ` +
+ Mod "${req.query.copied}" copied to ${selectedWorld}! +
+ ` : ''} + + ${typeof req !== 'undefined' && req.query && req.query.removed ? ` +
+ Mod "${req.query.removed}" removed from ${selectedWorld}! +
+ ` : ''} + + ${typeof req !== 'undefined' && req.query && req.query.deleted ? ` +
+ Mod "${req.query.deleted}" deleted permanently! +
+ ` : ''} + +
+
+

Select World

+
+
+
+
+
+ + +
+ +
+
+
+
+ + ${selectedWorld ? ` +
+
+
+

World Mods (${worldMods.length})

+

Mods installed specifically for ${selectedWorld}

+
+
+ ${worldMods.length > 0 ? ` +
+ ${worldMods.map(mod => ` +
+
+

${mod.title}

+ ${mod.location === 'global-enabled' ? ` + Enabled + ` : mod.location === 'world-installed' ? ` + World Copy + ` : mod.location === 'global-missing' ? ` + Missing + ` : ` + Unknown + `} +
+ ${mod.description ? `

${mod.description}

` : ''} +
+ ${mod.author ? `Author: ${mod.author}` : ''} + ${mod.depends && mod.depends.length > 0 ? `Depends: ${mod.depends.join(', ')}` : ''} + Type: ${ + mod.location === 'global-enabled' ? 'Global mod (enabled via config)' : + mod.location === 'world-installed' ? 'World-specific installation' : + mod.location === 'global-missing' ? 'Missing global mod' : 'Unknown' + } +
+
+ ${mod.location === 'global-enabled' ? ` +
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} + +
+ ` : mod.location === 'world-installed' ? ` +
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} + +
+ ` : mod.location === 'global-missing' ? ` + Missing from global mods + ` : ''} +
+
+ `).join('')} +
+ ` : ` +

No mods enabled for this world.

+ `} +
+
+ +
+
+

Available Global Mods (${globalMods.length})

+

Install these mods to ${selectedWorld}

+
+
+ ${globalMods.length > 0 ? ` +
+ ${globalMods.map(mod => { + const isEnabled = worldMods.some(wm => wm.name === mod.name && wm.location === 'global-enabled'); + const isCopied = worldMods.some(wm => wm.name === mod.name && wm.location === 'world-installed'); + const isInUse = isEnabled || isCopied; + return ` +
+
+

${mod.title}

+ + ${isEnabled ? 'Enabled' : isCopied ? 'Copied' : 'Available'} + +
+ ${mod.description ? `

${mod.description}

` : ''} +
+ ${mod.author ? `Author: ${mod.author}` : ''} + ${mod.depends && mod.depends.length > 0 ? `Depends: ${mod.depends.join(', ')}` : ''} +
+
+ ${!isEnabled ? ` +
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} + +
+ ` : ''} + ${!isCopied ? ` +
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} + +
+ ` : ''} + Details +
+
+ `; + }).join('')} +
+ ` : ` +

No global mods found. Upload mods to the mods directory to see them here.

+ `} +
+
+
+ ` : ` +
+
+

Global Mods (${globalMods.length})

+
+
+ ${globalMods.length > 0 ? ` +
+ ${globalMods.map(mod => ` +
+
+

${mod.title}

+ Global +
+ ${mod.description ? `

${mod.description}

` : ''} +
+ ${mod.author ? `Author: ${mod.author}` : ''} + ${mod.depends.length > 0 ? `Depends: ${mod.depends.join(', ')}` : ''} +
+
+ Details +
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} + +
+
+
+ `).join('')} +
+ ` : ` +

No global mods found. Upload mods to the mods directory to see them here.

+ `} +
+
+ `} + + +`; +%> + +<%- include('../layout', { body: body, currentPage: 'mods', title: title }) %> \ No newline at end of file diff --git a/views/worlds/details.ejs b/views/worlds/details.ejs new file mode 100644 index 0000000..aa981bb --- /dev/null +++ b/views/worlds/details.ejs @@ -0,0 +1,131 @@ +<% +const body = ` + + + ${typeof req !== 'undefined' && req.query && req.query.updated ? ` +
+ World settings updated successfully! +
+ ` : ''} + +
+
+
+

World Settings

+
+
+
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} + +
+ + +
+ +
+ + +
+ +
+ +
+ + + + +
+
+ +
+ + Manage Mods +
+
+ +
+

World Information

+
+
Internal Name: ${world.name}
+
Game: ${world.gameid}
+
World Size: ${(world.worldSize / 1024 / 1024).toFixed(2)} MB
+
Created: ${new Date(world.created).toLocaleString()}
+
Last Modified: ${new Date(world.lastModified).toLocaleString()}
+
+
+
+
+ + ${world.enabledMods && world.enabledMods.length > 0 ? ` +
+
+

Enabled Mods (${world.enabledMods.length})

+
+
+
+ ${world.enabledMods.map(mod => ` +
+
+ ${mod.title} + ${mod.author ? `by ${mod.author}` : ''} +
+ ${mod.description ? `
${mod.description}
` : ''} +
+ ${mod.location === 'global-enabled' ? ` + Global (Enabled) + ` : mod.location === 'world-installed' ? ` + World Copy + ` : mod.location === 'global-missing' ? ` + Missing + ` : ` + ${mod.location} + `} +
+
+ `).join('')} +
+
+
+ ` : ''} +
+ +`; +%> + +<%- include('../layout', { body: body, currentPage: 'worlds', title: title }) %> \ No newline at end of file diff --git a/views/worlds/new.ejs b/views/worlds/new.ejs new file mode 100644 index 0000000..36f3ac8 --- /dev/null +++ b/views/worlds/new.ejs @@ -0,0 +1,70 @@ +<% +const body = ` + + + ${typeof error !== 'undefined' && error ? ` +
+ ${error} +
+ ` : ''} + +
+
+ ${typeof csrfToken !== 'undefined' && csrfToken ? `` : ''} +
+ + + Only letters, numbers, underscore and hyphen allowed +
+ +
+ + + Choose the base game for your world +
+ +
+ + Cancel +
+
+
+ +
+ World Creation Notes:
+ • World creation may take a few moments to complete
+ • You will be redirected to the worlds list when creation starts
+ • Additional world settings can be configured after creation
+ • Make sure the selected game is properly installed +
+`; +%> + +<%- include('../layout', { body: body, currentPage: 'worlds', title: title }) %> \ No newline at end of file