funcion de descargar json eliminada
This commit is contained in:
@@ -13,9 +13,6 @@
|
|||||||
<span class="collapse-icon" :class="{ rotated: filtersCollapsed }">▼</span>
|
<span class="collapse-icon" :class="{ rotated: filtersCollapsed }">▼</span>
|
||||||
<span class="collapse-text">{{ filtersCollapsed ? 'Mostrar filtros' : 'Ocultar filtros' }}</span>
|
<span class="collapse-text">{{ filtersCollapsed ? 'Mostrar filtros' : 'Ocultar filtros' }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="btn" @click="downloadJSON" :disabled="loading" title="Descargar datos actuales como JSON">
|
|
||||||
📊 <span class="label">JSON</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-markers filters-indicators">
|
<div class="header-markers filters-indicators">
|
||||||
@@ -87,29 +84,6 @@
|
|||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Raw payload viewer for players-actions-stream -->
|
|
||||||
<div class="raw-viewer glass light" v-if="rawActionsPayload">
|
|
||||||
<div class="raw-header">
|
|
||||||
<div class="raw-title">Datos del stream (players-actions-stream)</div>
|
|
||||||
<div class="raw-actions">
|
|
||||||
<button class="btn" @click="showRaw = !showRaw">{{ showRaw ? 'Ocultar' : 'Mostrar' }}</button>
|
|
||||||
<button class="btn" @click="copyRaw" title="Copiar JSON">Copiar</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre v-show="showRaw" class="raw-pre">{{ prettyRaw }}</pre>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Datos filtrados (vista actual) -->
|
|
||||||
<div class="raw-viewer glass light">
|
|
||||||
<div class="raw-header">
|
|
||||||
<div class="raw-title">Datos filtrados (vista actual)</div>
|
|
||||||
<div class="raw-actions">
|
|
||||||
<button class="btn" @click="showFiltered = !showFiltered">{{ showFiltered ? 'Ocultar' : 'Mostrar' }}</button>
|
|
||||||
<button class="btn" @click="copyFiltered" title="Copiar JSON">Copiar</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<pre v-show="showFiltered" class="raw-pre">{{ prettyFiltered }}</pre>
|
|
||||||
</div>
|
|
||||||
<AppCredits position="bottom-right" />
|
<AppCredits position="bottom-right" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -426,7 +400,6 @@ watch(filterState, () => {
|
|||||||
}, { deep: true });
|
}, { deep: true });
|
||||||
|
|
||||||
const availableRooms = ref<{ roomId: string; name: string; playerCount?: number }[]>([]);
|
const availableRooms = ref<{ roomId: string; name: string; playerCount?: number }[]>([]);
|
||||||
const selectedRoomIds = ref<string[]>([]);
|
|
||||||
const playerLoading = ref(false);
|
const playerLoading = ref(false);
|
||||||
const playerEventCounts = ref<Record<string, number>>((Object.fromEntries(EVENTS.map(k => [k, 0])) as Record<string, number>));
|
const playerEventCounts = ref<Record<string, number>>((Object.fromEntries(EVENTS.map(k => [k, 0])) as Record<string, number>));
|
||||||
const playersActionsByUuid = ref<Record<string, Record<string, number>>>({});
|
const playersActionsByUuid = ref<Record<string, Record<string, number>>>({});
|
||||||
@@ -447,64 +420,6 @@ const playerBarGradient = computed(() => '#8b5cf6');
|
|||||||
const apiBase = (import.meta as any).env?.VITE_API_URL || `${window.location.protocol}//${window.location.host}/api`;
|
const apiBase = (import.meta as any).env?.VITE_API_URL || `${window.location.protocol}//${window.location.host}/api`;
|
||||||
const esActions = ref<EventSource|null>(null);
|
const esActions = ref<EventSource|null>(null);
|
||||||
const rawActionsPayload = ref<any>(null);
|
const rawActionsPayload = ref<any>(null);
|
||||||
const showRaw = ref(false);
|
|
||||||
const prettyRaw = computed(() => {
|
|
||||||
try {
|
|
||||||
return JSON.stringify(rawActionsPayload.value, null, 2);
|
|
||||||
} catch {
|
|
||||||
return String(rawActionsPayload.value || '');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
function copyRaw() {
|
|
||||||
try {
|
|
||||||
navigator.clipboard.writeText(prettyRaw.value);
|
|
||||||
} catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filtered snapshot (what the UI is showing after filters)
|
|
||||||
const showFiltered = ref(false);
|
|
||||||
const filteredSnapshot = computed(() => {
|
|
||||||
try {
|
|
||||||
return {
|
|
||||||
metadata: {
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
dataSource: filterState.value.timeMode === 'active' ? 'active-rooms' : 'aggregated',
|
|
||||||
filters: {
|
|
||||||
room: filterState.value.rooms,
|
|
||||||
round: filterState.value.rounds,
|
|
||||||
game: filterState.value.games,
|
|
||||||
selectedPlayers: filterState.value.playerUuids,
|
|
||||||
selectedRooms: selectedRoomIds.value,
|
|
||||||
timeMode: filterState.value.timeMode,
|
|
||||||
from: filterState.value.rangeFrom,
|
|
||||||
to: filterState.value.rangeTo,
|
|
||||||
liveEnd: filterState.value.liveEnd
|
|
||||||
}
|
|
||||||
},
|
|
||||||
chartTotals: {
|
|
||||||
offers: offersTotal.value,
|
|
||||||
responses: responsesTotal.value,
|
|
||||||
force: forceTotal.value,
|
|
||||||
shame: shameTotal.value,
|
|
||||||
report: reportTotal.value,
|
|
||||||
averageScore: averageScoreTotal.value,
|
|
||||||
totalPlayers: totalPlayersCount.value
|
|
||||||
},
|
|
||||||
globalEventCounts: eventFilters.globalEventCounts.value,
|
|
||||||
playerEventCounts: playerEventCounts.value,
|
|
||||||
combinedCounts: {
|
|
||||||
global: combinedGlobalCounts.value,
|
|
||||||
players: combinedPlayerCounts.value
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} catch (e) {
|
|
||||||
return { error: String(e) };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const prettyFiltered = computed(() => JSON.stringify(filteredSnapshot.value, null, 2));
|
|
||||||
function copyFiltered() {
|
|
||||||
try { navigator.clipboard.writeText(prettyFiltered.value); } catch {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Indicator labels
|
// Indicator labels
|
||||||
const periodLabel = computed(() => {
|
const periodLabel = computed(() => {
|
||||||
@@ -654,96 +569,6 @@ onUnmounted(() => {
|
|||||||
// const allPlayersActions = ref<{ uuid: string; name: string; total: number }[]>([]);
|
// const allPlayersActions = ref<{ uuid: string; name: string; total: number }[]>([]);
|
||||||
|
|
||||||
|
|
||||||
function downloadJSON() {
|
|
||||||
// Create a comprehensive snapshot of current interface data
|
|
||||||
const currentData = {
|
|
||||||
metadata: {
|
|
||||||
timestamp: new Date().toISOString(),
|
|
||||||
dataSource: filterState.value.timeMode === 'active' ? 'active-rooms' : 'aggregated',
|
|
||||||
filters: {
|
|
||||||
room: filterState.value.rooms,
|
|
||||||
round: filterState.value.rounds,
|
|
||||||
game: filterState.value.games,
|
|
||||||
hasActiveFilters: activeFilters.value.hasFilters,
|
|
||||||
selectedPlayers: filterState.value.playerUuids,
|
|
||||||
selectedRooms: selectedRoomIds.value,
|
|
||||||
timeMode: filterState.value.timeMode,
|
|
||||||
rangeFrom: filterState.value.rangeFrom,
|
|
||||||
rangeTo: filterState.value.rangeTo,
|
|
||||||
liveEnd: filterState.value.liveEnd
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Current chart totals being displayed
|
|
||||||
chartTotals: {
|
|
||||||
offers: offersTotal.value,
|
|
||||||
responses: responsesTotal.value,
|
|
||||||
force: forceTotal.value,
|
|
||||||
shame: shameTotal.value,
|
|
||||||
report: reportTotal.value,
|
|
||||||
averageScore: averageScoreTotal.value,
|
|
||||||
totalPlayers: totalPlayersCount.value
|
|
||||||
},
|
|
||||||
|
|
||||||
// Global event counts (filtered)
|
|
||||||
globalEventCounts: eventFilters.globalEventCounts.value,
|
|
||||||
|
|
||||||
// Selected player event counts (if applicable)
|
|
||||||
selectedPlayersEventCounts: filterState.value.playerUuids.length ? playerEventCounts.value : null,
|
|
||||||
|
|
||||||
// Additional metrics being displayed
|
|
||||||
additionalMetrics: additionalMetrics.value,
|
|
||||||
|
|
||||||
// Selected player metrics (if applicable)
|
|
||||||
selectedPlayersMetrics: filterState.value.playerUuids.length ? selectedPlayerMetrics.value : null,
|
|
||||||
|
|
||||||
// Combined counts used in charts
|
|
||||||
combinedGlobalCounts: combinedGlobalCounts.value,
|
|
||||||
combinedPlayerCounts: filterState.value.playerUuids.length ? combinedPlayerCounts.value : null,
|
|
||||||
|
|
||||||
// Players data
|
|
||||||
players: allPlayersWithScores.value,
|
|
||||||
availableRooms: availableRooms.value,
|
|
||||||
|
|
||||||
// Current filtered data if available
|
|
||||||
currentSourceEvents: eventFilters.currentSourceEvents.value,
|
|
||||||
|
|
||||||
// Per-player action counts
|
|
||||||
playersActionsByUuid: playersActionsByUuid.value,
|
|
||||||
|
|
||||||
// All players with scores data
|
|
||||||
allPlayersWithScores: allPlayersWithScores.value.map(player => ({
|
|
||||||
uuid: player.uuid,
|
|
||||||
name: player.name,
|
|
||||||
total: player.total,
|
|
||||||
shameTokens: player.shameTokens,
|
|
||||||
counts: player.counts,
|
|
||||||
roomScoreHistory: player.roomScoreHistory
|
|
||||||
}))
|
|
||||||
};
|
|
||||||
|
|
||||||
// Convert to formatted JSON string
|
|
||||||
const jsonString = JSON.stringify(currentData, null, 2);
|
|
||||||
|
|
||||||
// Create and download file
|
|
||||||
const blob = new Blob([jsonString], { type: 'application/json;charset=utf-8;' });
|
|
||||||
const link = document.createElement('a');
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
link.setAttribute('href', url);
|
|
||||||
|
|
||||||
// Generate filename with current filters and timestamp
|
|
||||||
const timestamp = new Date().toISOString().slice(0, 19).replace(/[T:]/g, '-');
|
|
||||||
const dataSourceLabel = filterState.value.timeMode === 'range' ? 'agregados' : 'activos';
|
|
||||||
const filterLabel = activeFilters.value.hasFilters ? '_filtrado' : '';
|
|
||||||
const filename = `leaderboard_${dataSourceLabel}${filterLabel}_${timestamp}.json`;
|
|
||||||
|
|
||||||
link.setAttribute('download', filename);
|
|
||||||
link.style.visibility = 'hidden';
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -939,12 +764,6 @@ function downloadJSON() {
|
|||||||
.marker-chip { display: inline-flex; align-items: center; gap: 6px; padding: 2px 4px; border-radius: 999px; border: none; background: transparent; color: #334155; font-size: 12px; font-weight: 700; }
|
.marker-chip { display: inline-flex; align-items: center; gap: 6px; padding: 2px 4px; border-radius: 999px; border: none; background: transparent; color: #334155; font-size: 12px; font-weight: 700; }
|
||||||
.marker-chip.clickable { cursor: pointer; }
|
.marker-chip.clickable { cursor: pointer; }
|
||||||
|
|
||||||
/* Raw payload styles */
|
|
||||||
.raw-viewer { margin-top: 14px; padding: 12px; border-radius: 14px; }
|
|
||||||
.raw-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
|
|
||||||
.raw-title { font-weight: 800; color: #334155; font-size: 14px; }
|
|
||||||
.raw-actions { display: flex; gap: 8px; }
|
|
||||||
.raw-pre { max-height: 420px; overflow: auto; background: #0b1020; color: #e5e7eb; padding: 12px; border-radius: 10px; font-size: 12px; line-height: 1.4; border: 1px solid #1f2937; }
|
|
||||||
|
|
||||||
/* Time indicator key */
|
/* Time indicator key */
|
||||||
.key.time { background: linear-gradient(90deg, #f59e0b, #d97706); box-shadow: 0 0 8px rgba(245,158,11,0.35); }
|
.key.time { background: linear-gradient(90deg, #f59e0b, #d97706); box-shadow: 0 0 8px rgba(245,158,11,0.35); }
|
||||||
|
|||||||
Reference in New Issue
Block a user