guardado y restaurado del estado del nameManager

This commit is contained in:
2025-08-28 01:51:06 -06:00
parent fd3338cf2d
commit 220248b588
3 changed files with 231 additions and 2 deletions

View File

@@ -6,12 +6,23 @@
<div class="buttons">
<button class="btn btn-export" @click="downloadCsvByRoom">Descargar por sala (CSV)</button>
<button class="btn btn-export alt" @click="downloadCsvByUuid">Descargar por UUID (CSV)</button>
<button class="btn btn-save" @click="downloadNameManagerState">💾 Descargar Estado (.snatchSave)</button>
<div class="upload-container">
<input
ref="fileInput"
type="file"
accept=".snatchSave"
@change="handleFileUpload"
style="display: none"
/>
<button class="btn btn-load" @click="triggerFileUpload">📂 Cargar Estado (.snatchSave)</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import { computed, ref } from 'vue';
interface PlayerRow {
sessionId: string;
@@ -35,6 +46,7 @@ interface RoomDetail {
const props = defineProps<{ rooms: any[]; roomDetails: { [key: string]: RoomDetail } }>();
const fileInput = ref<HTMLInputElement>();
const gameRooms = computed(() => props.rooms.filter(r => r.name === 'game'));
function csvEscape(v: any): string {
@@ -169,6 +181,83 @@ function triggerDownload(csv: string, suffix: string) {
function downloadCsvByRoom() { triggerDownload(buildCsvByRoom(), 'by-room'); }
async function downloadCsvByUuid() { const csv = await buildCsvByUuid(); triggerDownload(csv, 'by-uuid'); }
// NameManager save/load functions
async function downloadNameManagerState() {
try {
const apiBase = (import.meta as any).env?.VITE_API_URL || `${window.location.protocol}//${window.location.host}/api`;
const response = await fetch(`${apiBase}/admin/namemanager/export`);
if (!response.ok) {
throw new Error(`Failed to fetch nameManager state: ${response.status}`);
}
const data = await response.json();
const jsonString = JSON.stringify(data, null, 2);
const blob = new Blob([jsonString], { type: 'application/json;charset=utf-8;' });
const url = URL.createObjectURL(blob);
const now = new Date();
const pad = (n: number) => String(n).padStart(2, '0');
const fileName = `namemanager-${now.getFullYear()}${pad(now.getMonth()+1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}.snatchSave`;
const a = document.createElement('a');
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
} catch (error) {
console.error('Error downloading nameManager state:', error);
alert('Error al descargar el estado del nameManager');
}
}
function triggerFileUpload() {
fileInput.value?.click();
}
async function handleFileUpload(event: Event) {
const target = event.target as HTMLInputElement;
const file = target.files?.[0];
if (!file) return;
if (!file.name.endsWith('.snatchSave')) {
alert('Por favor selecciona un archivo .snatchSave válido');
return;
}
try {
const text = await file.text();
const data = JSON.parse(text);
const apiBase = (import.meta as any).env?.VITE_API_URL || `${window.location.protocol}//${window.location.host}/api`;
const response = await fetch(`${apiBase}/admin/namemanager/import`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
});
if (!response.ok) {
throw new Error(`Failed to upload nameManager state: ${response.status}`);
}
const result = await response.json();
alert(`Estado cargado exitosamente. ${result.message || 'NameManager actualizado.'}`);
} catch (error) {
console.error('Error uploading nameManager state:', error);
alert('Error al cargar el estado del nameManager. Verifica que el archivo sea válido.');
} finally {
// Reset file input
target.value = '';
}
}
</script>
<style scoped>
@@ -183,8 +272,13 @@ async function downloadCsvByUuid() { const csv = await buildCsvByUuid(); trigger
}
.section-header h2 { margin:0; font-size: 1.3rem; }
.buttons { display:flex; gap: 10px; flex-wrap: wrap; }
.btn { padding: 10px 14px; border:none; border-radius: 10px; font-weight:700; cursor:pointer; }
.btn { padding: 10px 14px; border:none; border-radius: 10px; font-weight:700; cursor:pointer; transition: all 0.3s ease; }
.btn-export { background: linear-gradient(135deg, #10b981 0%, #059669 100%); color:white; }
.btn-export.alt { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); }
.btn-export:hover { filter: brightness(1.05); }
.btn-save { background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); color:white; }
.btn-save:hover { filter: brightness(1.05); transform: translateY(-1px); }
.btn-load { background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); color:white; }
.btn-load:hover { filter: brightness(1.05); transform: translateY(-1px); }
.upload-container { position: relative; }
</style>