Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import ToggleBar from "./ToggleBar";
import TripLogs from "./TripLogs";
import TaskLogs from "./TaskLogs";
import DatasetLoading from "./DatasetLoading";
import ExtraDataSource from "./ExtraDataSource";
import {
uploadFile,
getUploadedData,
Expand All @@ -25,7 +26,8 @@ import Utils, { log } from "./Utils";
import { toast, ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { ALL_TOGGLES, getVisibleToggles } from "./MapToggles";
import { HAS_EXTRA_DATA_SOURCE } from "./constants";

const HAS_EXTRA_DATA_SOURCE = ExtraDataSource.isAvailable();

const MARKER_COLORS = [
"#EA4335", // Red
Expand Down Expand Up @@ -807,6 +809,7 @@ class App extends React.Component {
onLogsReceived: handleCloudLogsReceived,
onExtraLogsReceived: handleExtraLogsReceived,
onFileUpload: handleFileUpload,
hasExtraDataSource: HAS_EXTRA_DATA_SOURCE,
});
dialogRoot.render(datasetLoadingComponent);
});
Expand Down
99 changes: 6 additions & 93 deletions src/DatasetLoading.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,13 @@ import ExtraDataSource from "./ExtraDataSource";
import { log } from "./Utils";
import { toast } from "react-toastify";
import { isTokenValid, fetchLogsWithToken, useCloudLoggingLogin, buildQueryFilter } from "./CloudLogging";
import { useSheetsLogin, isSheetsTokenValid, getSheetsToken, importFromGoogleSheet } from "./GoogleSheets";
import { HAS_EXTRA_DATA_SOURCE, GOOGLE_CLIENT_ID } from "./constants";
import DatasetSideLoading from "./DatasetSideLoading";
import { GOOGLE_CLIENT_ID } from "./constants";

const CloudLoggingFormComponent = ({ onLogsReceived, onFileUpload }) => {
const getStoredValue = (key, defaultValue = "") => localStorage.getItem(`datasetLoading_${key}`) || defaultValue;

const [fetching, setFetching] = useState(false);
const [sheetFormVisible, setSheetFormVisible] = useState(false);
const [sheetUrl, setSheetUrl] = useState(localStorage.getItem("datasetLoading_sheetUrl") || "");
const [sheetLoading, setSheetLoading] = useState(false);
const [queryParams, setQueryParams] = useState({
projectId: getStoredValue("projectId"),
vehicleId: getStoredValue("vehicleId"),
Expand Down Expand Up @@ -69,52 +66,6 @@ const CloudLoggingFormComponent = ({ onLogsReceived, onFileUpload }) => {
}
};

const handleSheetImport = (token) => {
setSheetLoading(true);
setLocalError(null);
localStorage.setItem("datasetLoading_sheetUrl", sheetUrl);

importFromGoogleSheet(sheetUrl, token)
.then((logs) => {
log(`Received ${logs.length} logs from Google Sheet`);
if (logs.length > 0) {
onLogsReceived(logs);
} else {
toast.warning("No logs found in the spreadsheet.");
}
})
.catch((err) => {
setLocalError(`Sheet import error: ${err.message}`);
toast.error(`Sheet import error: ${err.message}`);
})
.finally(() => setSheetLoading(false));
};

const sheetsLogin = useSheetsLogin(
(token) => {
log("Sheets login successful, importing...");
handleSheetImport(token);
},
(err) => {
log("Sheets login failed.", err);
setLocalError(`Auth Error: ${err.error || "Unknown"}`);
setSheetLoading(false);
}
);

const handleSheetLoadClick = () => {
if (!sheetUrl.trim()) {
setLocalError("Please enter a spreadsheet URL or ID.");
return;
}
setLocalError(null);
if (isSheetsTokenValid()) {
handleSheetImport(getSheetsToken());
} else {
sheetsLogin();
}
};

return (
<div className="cloud-logging-form">
<h3>Fleet Engine Logs Loading</h3>
Expand Down Expand Up @@ -211,56 +162,18 @@ const CloudLoggingFormComponent = ({ onLogsReceived, onFileUpload }) => {
<progress className="progress-bar" />
</div>
)}
<div className="cloud-logging-buttons">
<DatasetSideLoading onLogsReceived={onLogsReceived} onFileUpload={onFileUpload} setLocalError={setLocalError}>
<button type="button" onClick={handleFetch} disabled={fetching} className="fetch-logs-button">
{fetching ? "Fetching..." : isTokenValid() ? "Fetch Logs" : "Sign in and Fetch Logs"}
</button>
<button type="button" onClick={() => setSheetFormVisible(!sheetFormVisible)} className="sideload-logs-button">
Load Google Sheet
</button>
<label htmlFor="fileUploadInput" className="sideload-logs-button">
Load JSON or ZIP
</label>
<input type="file" id="fileUploadInput" accept=".json,.zip" onChange={onFileUpload} className="file-input" />
</div>
{sheetFormVisible && (
<div className="google-sheet-form">
<div className="form-field">
<label className="form-label">
Spreadsheet URL or ID:
<input
type="text"
value={sheetUrl}
onChange={(e) => setSheetUrl(e.target.value)}
placeholder="https://docs.google.com/spreadsheets/d/... or spreadsheet ID"
className="form-input"
/>
</label>
</div>
<button
type="button"
onClick={handleSheetLoadClick}
disabled={sheetLoading}
className="fetch-logs-button"
style={{ marginTop: "8px" }}
>
{sheetLoading ? "Loading..." : isSheetsTokenValid() ? "Load Sheet" : "Sign in and Load Sheet"}
</button>
{sheetLoading && (
<div className="progress-indicator">
<div>Loading from Google Sheet...</div>
<progress className="progress-bar" />
</div>
)}
</div>
)}
</DatasetSideLoading>
</div>
);
};

export default function DatasetLoading(props) {
const [activeDataSource, setActiveDataSource] = useState(
localStorage.getItem("lastUsedDataSource") || (HAS_EXTRA_DATA_SOURCE ? "extra" : "cloudLogging")
localStorage.getItem("lastUsedDataSource") || (props.hasExtraDataSource ? "extra" : "cloudLogging")
);

useEffect(() => {
Expand All @@ -271,7 +184,7 @@ export default function DatasetLoading(props) {
const ExtraFormComponent = isExtra ? ExtraDataSource.getFormComponent(props) : null;

const renderSourceSelection = () => {
if (!HAS_EXTRA_DATA_SOURCE) {
if (!props.hasExtraDataSource) {
return <button className="active static">Cloud Logging</button>;
}

Expand Down
115 changes: 115 additions & 0 deletions src/DatasetSideLoading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// src/DatasetSideLoading.js
import { useState } from "react";
import { toast } from "react-toastify";
import { useSheetsLogin, isSheetsTokenValid, getSheetsToken, importFromGoogleSheet } from "./GoogleSheets";
import { log } from "./Utils";

/**
* A shared section for sidebar/sideloading logs (Google Sheets and local files).
* This handles the "Load Google Sheet" and "Load JSON or ZIP" buttons and forms.
*
* @param {Object} props
* @param {Function} props.onLogsReceived Callback when logs are received (from Sheet).
* @param {Function} props.onFileUpload Callback for file uploads.
* @param {Function} props.setLocalError Callback to set error messages in the parent.
* @param {React.ReactNode} props.children The primary fetch button(s) to show alongside sideload buttons.
*/
export const DatasetSideLoading = ({ onLogsReceived, onFileUpload, setLocalError, children }) => {
const [sheetFormVisible, setSheetFormVisible] = useState(false);
const [sheetUrl, setSheetUrl] = useState(localStorage.getItem("datasetLoading_sheetUrl") || "");
const [sheetLoading, setSheetLoading] = useState(false);

const handleSheetImport = (token) => {
setSheetLoading(true);
if (setLocalError) setLocalError(null);
localStorage.setItem("datasetLoading_sheetUrl", sheetUrl);

importFromGoogleSheet(sheetUrl, token)
.then((logs) => {
log(`Received ${logs.length} logs from Google Sheet`);
if (logs.length > 0) {
onLogsReceived(logs);
} else {
toast.warning("No logs found in the spreadsheet.");
}
})
.catch((err) => {
if (setLocalError) setLocalError(`Sheet import error: ${err.message}`);
toast.error(`Sheet import error: ${err.message}`);
})
.finally(() => setSheetLoading(false));
};

const sheetsLogin = useSheetsLogin(
(token) => {
log("Sheets login successful, importing...");
handleSheetImport(token);
},
(err) => {
log("Sheets login failed.", err);
if (setLocalError) setLocalError(`Auth Error: ${err.error || "Unknown"}`);
setSheetLoading(false);
}
);

const handleSheetLoadClick = () => {
if (!sheetUrl.trim()) {
if (setLocalError) setLocalError("Please enter a spreadsheet URL or ID.");
return;
}
if (setLocalError) setLocalError(null);
if (isSheetsTokenValid()) {
handleSheetImport(getSheetsToken());
} else {
sheetsLogin();
}
};

return (
<>
<div className="cloud-logging-buttons">
{children}
<button type="button" onClick={() => setSheetFormVisible(!sheetFormVisible)} className="sideload-logs-button">
Load Google Sheet
</button>
<label htmlFor="fileUploadInput" className="sideload-logs-button">
Load JSON or ZIP
</label>
<input type="file" id="fileUploadInput" accept=".json,.zip" onChange={onFileUpload} className="file-input" />
</div>
{sheetFormVisible && (
<div className="google-sheet-form">
<div className="form-field">
<label className="form-label">
Spreadsheet URL or ID:
<input
type="text"
value={sheetUrl}
onChange={(e) => setSheetUrl(e.target.value)}
placeholder="https://docs.google.com/spreadsheets/d/... or spreadsheet ID"
className="form-input"
/>
</label>
</div>
<button
type="button"
onClick={handleSheetLoadClick}
disabled={sheetLoading}
className="fetch-logs-button"
style={{ marginTop: "8px" }}
>
{sheetLoading ? "Loading..." : isSheetsTokenValid() ? "Load Sheet" : "Sign in and Load Sheet"}
</button>
{sheetLoading && (
<div className="progress-indicator">
<div>Loading from Google Sheet...</div>
<progress className="progress-bar" />
</div>
)}
</div>
)}
</>
);
};

export default DatasetSideLoading;
2 changes: 0 additions & 2 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// constants.js
import ExtraDataSource from "./ExtraDataSource";

export const DEFAULT_API_KEY = "";
export const DEFAULT_MAP_ID = "e6ead35a6ace8599";
export const HAS_EXTRA_DATA_SOURCE = ExtraDataSource.isAvailable();
export const GOOGLE_CLIENT_ID = "829183678942-eq2c9cd7pjdm39l2um5thgbrvgva07e7.apps.googleusercontent.com";
Loading