Feature: add Google Drive backup and restore integration
This commit is contained in:
105
app.js
105
app.js
@@ -46,6 +46,10 @@ const backupBtn = document.getElementById("backupBtn");
|
||||
const restoreMergeBtn = document.getElementById("restoreMergeBtn");
|
||||
const restoreReplaceBtn = document.getElementById("restoreReplaceBtn");
|
||||
const restoreFileInput = document.getElementById("restoreFileInput");
|
||||
const googleDriveState = document.getElementById("googleDriveState");
|
||||
const googleConnectBtn = document.getElementById("googleConnectBtn");
|
||||
const googleBackupBtn = document.getElementById("googleBackupBtn");
|
||||
const googleRestoreBtn = document.getElementById("googleRestoreBtn");
|
||||
const quickSearchInput = document.getElementById("quickSearchInput");
|
||||
const quickSearchResults = document.getElementById("quickSearchResults");
|
||||
const gamesList = document.getElementById("gamesList");
|
||||
@@ -53,6 +57,7 @@ const gameCardTemplate = document.getElementById("gameCardTemplate");
|
||||
let editingGameId = null;
|
||||
let pendingRestoreMode = "merge";
|
||||
let quickSearchTerm = "";
|
||||
let googleStatus = { configured: false, connected: false, email: "" };
|
||||
|
||||
toolsToggleBtn.addEventListener("click", () => {
|
||||
toolsDrawer.classList.toggle("open");
|
||||
@@ -81,6 +86,48 @@ document.addEventListener("keydown", (event) => {
|
||||
}
|
||||
});
|
||||
|
||||
googleConnectBtn.addEventListener("click", async () => {
|
||||
try {
|
||||
const payload = await apiRequest("/api/google/connect-url");
|
||||
if (!payload.url) {
|
||||
throw new Error("Missing Google connect URL");
|
||||
}
|
||||
window.location.href = payload.url;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert("Connexion Google indisponible. Verifie la configuration OAuth.");
|
||||
}
|
||||
});
|
||||
|
||||
googleBackupBtn.addEventListener("click", async () => {
|
||||
try {
|
||||
const payload = await apiRequest("/api/google/backup/upload", { method: "POST" });
|
||||
await refreshGoogleStatus();
|
||||
alert(`Sauvegarde Drive OK: ${payload.fileName || "fichier cree"}.`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert("Echec sauvegarde Google Drive.");
|
||||
}
|
||||
});
|
||||
|
||||
googleRestoreBtn.addEventListener("click", async () => {
|
||||
const confirmed = window.confirm("Restaurer depuis le dernier backup Google Drive ?");
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const payload = await apiRequest("/api/google/backup/restore", {
|
||||
method: "POST",
|
||||
body: { mode: "merge" },
|
||||
});
|
||||
await refreshFromApi(state.selectedBrand, state.selectedConsole);
|
||||
alert(`Restauration Drive OK (${payload.mode})`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert("Echec restauration Google Drive.");
|
||||
}
|
||||
});
|
||||
|
||||
quickSearchInput.addEventListener("input", (event) => {
|
||||
quickSearchTerm = event.target.value.trim();
|
||||
renderSearchResults();
|
||||
@@ -435,6 +482,7 @@ restoreFileInput.addEventListener("change", async (event) => {
|
||||
|
||||
function render() {
|
||||
renderDataMode();
|
||||
renderGoogleStatus();
|
||||
renderBrandTabs();
|
||||
renderConsoleTabs();
|
||||
renderGames();
|
||||
@@ -491,6 +539,34 @@ function renderDataMode() {
|
||||
}
|
||||
}
|
||||
|
||||
function renderGoogleStatus() {
|
||||
if (!googleDriveState) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!googleStatus.configured) {
|
||||
googleDriveState.textContent = "Etat Google Drive: non configure (OAuth manquant).";
|
||||
googleConnectBtn.disabled = true;
|
||||
googleBackupBtn.disabled = true;
|
||||
googleRestoreBtn.disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!googleStatus.connected) {
|
||||
googleDriveState.textContent = "Etat Google Drive: non connecte.";
|
||||
googleConnectBtn.disabled = false;
|
||||
googleBackupBtn.disabled = true;
|
||||
googleRestoreBtn.disabled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
const email = googleStatus.email ? ` (${googleStatus.email})` : "";
|
||||
googleDriveState.textContent = `Etat Google Drive: connecte${email}.`;
|
||||
googleConnectBtn.disabled = false;
|
||||
googleBackupBtn.disabled = false;
|
||||
googleRestoreBtn.disabled = false;
|
||||
}
|
||||
|
||||
function findBrandByConsole(consoleName) {
|
||||
for (const [brand, consoles] of Object.entries(state.brands)) {
|
||||
if (Array.isArray(consoles) && consoles.includes(consoleName)) {
|
||||
@@ -829,6 +905,15 @@ async function refreshFromApi(preferredBrand, preferredConsole) {
|
||||
render();
|
||||
}
|
||||
|
||||
async function refreshGoogleStatus() {
|
||||
try {
|
||||
googleStatus = await apiRequest("/api/google/status");
|
||||
} catch {
|
||||
googleStatus = { configured: false, connected: false, email: "" };
|
||||
}
|
||||
renderGoogleStatus();
|
||||
}
|
||||
|
||||
async function hydrateFromApi() {
|
||||
try {
|
||||
await refreshFromApi(state.selectedBrand, state.selectedConsole);
|
||||
@@ -839,9 +924,29 @@ async function hydrateFromApi() {
|
||||
}
|
||||
|
||||
async function bootstrap() {
|
||||
await refreshGoogleStatus();
|
||||
await hydrateFromApi();
|
||||
normalizeState();
|
||||
render();
|
||||
handleGoogleCallbackResult();
|
||||
}
|
||||
|
||||
bootstrap();
|
||||
|
||||
function handleGoogleCallbackResult() {
|
||||
const url = new URL(window.location.href);
|
||||
const googleParam = url.searchParams.get("google");
|
||||
if (!googleParam) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (googleParam === "connected") {
|
||||
alert("Google Drive connecte avec succes.");
|
||||
refreshGoogleStatus();
|
||||
} else if (googleParam === "error") {
|
||||
alert("Connexion Google Drive echouee.");
|
||||
}
|
||||
|
||||
url.searchParams.delete("google");
|
||||
window.history.replaceState({}, "", url.toString());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user