Add Factorio World Management feature to GSM
- Add gsm-frontend to repository (React + Vite + TailwindCSS) - New "Worlds" tab for Factorio server with: - List saved worlds with Start/Delete actions - Create new world with full map generation parameters - Preset selection (Default, Rich Resources, Rail World, etc.) - Save custom configurations as templates - Show which save will be loaded in Overview tab - Lock world management while server is running - Backend changes deployed to server separately 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
181
gsm-frontend/src/api.js
Normal file
181
gsm-frontend/src/api.js
Normal file
@@ -0,0 +1,181 @@
|
||||
const API_URL = import.meta.env.VITE_API_URL || 'https://monitor.dimension47.de/api'
|
||||
|
||||
async function fetchAPI(endpoint, options = {}) {
|
||||
const response = await fetch(`${API_URL}${endpoint}`, {
|
||||
...options,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers,
|
||||
},
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => ({ message: 'Request failed' }))
|
||||
throw new Error(error.message || `HTTP ${response.status}`)
|
||||
}
|
||||
|
||||
return response.json()
|
||||
}
|
||||
|
||||
// Auth
|
||||
export async function login(username, password) {
|
||||
return fetchAPI('/auth/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ username, password }),
|
||||
})
|
||||
}
|
||||
|
||||
export async function getMe(token) {
|
||||
return fetchAPI('/auth/me', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function changePassword(currentPassword, newPassword) {
|
||||
const token = localStorage.getItem('gsm_token')
|
||||
return fetchAPI('/auth/change-password', {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify({ currentPassword, newPassword }),
|
||||
})
|
||||
}
|
||||
|
||||
// Servers
|
||||
export async function getServers(token) {
|
||||
return fetchAPI('/servers', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function serverAction(token, serverId, action, body = null) {
|
||||
return fetchAPI(`/servers/${serverId}/${action}`, {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
...(body && { body: JSON.stringify(body) }),
|
||||
})
|
||||
}
|
||||
|
||||
export async function getWhitelist(token, serverId) {
|
||||
const headers = token ? { Authorization: `Bearer ${token}` } : {}
|
||||
return fetchAPI(`/servers/${serverId}/whitelist`, { headers })
|
||||
}
|
||||
|
||||
export async function sendRcon(token, serverId, command) {
|
||||
return fetchAPI(`/servers/${serverId}/rcon`, {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify({ command }),
|
||||
})
|
||||
}
|
||||
|
||||
export async function getServerLogs(token, serverId, lines = 50) {
|
||||
return fetchAPI(`/servers/${serverId}/logs?lines=${lines}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
// Metrics
|
||||
export async function getMetricsHistory(token, serverId, range = '1h') {
|
||||
return fetchAPI(`/servers/${serverId}/metrics/history?range=${range}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
// Users (admin only)
|
||||
export async function getUsers(token) {
|
||||
return fetchAPI('/auth/users', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function createUser(token, userData) {
|
||||
return fetchAPI('/auth/users', {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify(userData),
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateUserRole(token, userId, role) {
|
||||
return fetchAPI(`/auth/users/${userId}/role`, {
|
||||
method: 'PATCH',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify({ role }),
|
||||
})
|
||||
}
|
||||
|
||||
export async function updateUserPassword(token, userId, password) {
|
||||
return fetchAPI(`/auth/users/${userId}/password`, {
|
||||
method: 'PATCH',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify({ password }),
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteUser(token, userId) {
|
||||
return fetchAPI(`/auth/users/${userId}`, {
|
||||
method: 'DELETE',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
// Factorio World Management
|
||||
export async function getFactorioSaves(token) {
|
||||
return fetchAPI('/servers/factorio/saves', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function getFactorioPresets(token) {
|
||||
return fetchAPI('/servers/factorio/presets', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function getFactorioPreset(token, name) {
|
||||
return fetchAPI(`/servers/factorio/presets/${name}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function getFactorioTemplates(token) {
|
||||
return fetchAPI('/servers/factorio/templates', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function createFactorioTemplate(token, name, settings) {
|
||||
return fetchAPI('/servers/factorio/templates', {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify({ name, settings }),
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteFactorioTemplate(token, id) {
|
||||
return fetchAPI(`/servers/factorio/templates/${id}`, {
|
||||
method: 'DELETE',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function createFactorioWorld(token, saveName, settings) {
|
||||
return fetchAPI('/servers/factorio/create-world', {
|
||||
method: 'POST',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
body: JSON.stringify({ saveName, settings }),
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteFactorioSave(token, saveName) {
|
||||
return fetchAPI(`/servers/factorio/saves/${encodeURIComponent(saveName)}`, {
|
||||
method: 'DELETE',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
|
||||
export async function getFactorioCurrentSave(token) {
|
||||
return fetchAPI('/servers/factorio/current-save', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user