feat(gui): Display logs of specific swap on press of button on history page

This commit is contained in:
binarybaron 2024-09-09 21:00:27 +02:00
parent 063f9dbf9b
commit c486ca5de9
No known key found for this signature in database
GPG key ID: 99B75D3E1476A26E
5 changed files with 66 additions and 13 deletions

View file

@ -18,3 +18,26 @@ export interface CliLog {
[index: string]: unknown; [index: string]: unknown;
}[]; }[];
} }
function isCliLog(log: unknown): log is CliLog {
return (
typeof log === "object" &&
log !== null &&
"timestamp" in log &&
"level" in log &&
"fields" in log
);
}
export function parseCliLogString(log: string): CliLog | string {
try {
const parsed = JSON.parse(log);
if (isCliLog(parsed)) {
return parsed;
} else {
return log;
}
} catch (err) {
return log;
}
}

View file

@ -6,29 +6,38 @@ import {
DialogTitle, DialogTitle,
} from "@material-ui/core"; } from "@material-ui/core";
import { ButtonProps } from "@material-ui/core/Button/Button"; import { ButtonProps } from "@material-ui/core/Button/Button";
import { CliLog } from "models/cliModel"; import { CliLog, parseCliLogString } from "models/cliModel";
import { GetLogsResponse } from "models/tauriModel";
import { useState } from "react"; import { useState } from "react";
import PromiseInvokeButton from "renderer/components/PromiseInvokeButton"; import PromiseInvokeButton from "renderer/components/PromiseInvokeButton";
import { getLogsOfSwap } from "renderer/rpc";
import CliLogsBox from "../../../other/RenderedCliLog"; import CliLogsBox from "../../../other/RenderedCliLog";
export default function SwapLogFileOpenButton({ export default function SwapLogFileOpenButton({
swapId, swapId,
...props ...props
}: { swapId: string } & ButtonProps) { }: { swapId: string } & ButtonProps) {
const [logs, setLogs] = useState<CliLog[] | null>(null); const [logs, setLogs] = useState<(CliLog | string)[] | null>(null);
function onLogsReceived(response: GetLogsResponse) {
setLogs(response.logs.map(parseCliLogString));
}
return ( return (
<> <>
<PromiseInvokeButton <PromiseInvokeButton
onSuccess={(data) => { onSuccess={onLogsReceived}
setLogs(data as CliLog[]); onInvoke={() => getLogsOfSwap(swapId, false)}
}}
onInvoke={async () => {
throw new Error("Not implemented");
}}
{...props} {...props}
> >
View log View full logs
</PromiseInvokeButton>
<PromiseInvokeButton
onSuccess={onLogsReceived}
onInvoke={() => getLogsOfSwap(swapId, true)}
{...props}
>
View redacted logs
</PromiseInvokeButton> </PromiseInvokeButton>
{logs && ( {logs && (
<Dialog open onClose={() => setLogs(null)} fullWidth maxWidth="lg"> <Dialog open onClose={() => setLogs(null)} fullWidth maxWidth="lg">
@ -37,7 +46,13 @@ export default function SwapLogFileOpenButton({
<CliLogsBox logs={logs} label="Logs relevant to the swap" /> <CliLogsBox logs={logs} label="Logs relevant to the swap" />
</DialogContent> </DialogContent>
<DialogActions> <DialogActions>
<Button onClick={() => setLogs(null)}>Close</Button> <Button
onClick={() => setLogs(null)}
variant="contained"
color="primary"
>
Close
</Button>
</DialogActions> </DialogActions>
</Dialog> </Dialog>
)} )}

View file

@ -5,6 +5,8 @@ import {
BalanceResponse, BalanceResponse,
BuyXmrArgs, BuyXmrArgs,
BuyXmrResponse, BuyXmrResponse,
GetLogsArgs,
GetLogsResponse,
GetSwapInfoResponse, GetSwapInfoResponse,
MoneroRecoveryArgs, MoneroRecoveryArgs,
ResumeSwapArgs, ResumeSwapArgs,
@ -132,3 +134,13 @@ export async function checkContextAvailability(): Promise<boolean> {
const available = await invokeNoArgs<boolean>("is_context_available"); const available = await invokeNoArgs<boolean>("is_context_available");
return available; return available;
} }
export async function getLogsOfSwap(
swapId: string,
redact: boolean,
): Promise<GetLogsResponse> {
return await invoke<GetLogsArgs, GetLogsResponse>("get_logs", {
swap_id: swapId,
redact,
});
}

View file

@ -3,8 +3,8 @@ use std::sync::Arc;
use swap::cli::{ use swap::cli::{
api::{ api::{
request::{ request::{
BalanceArgs, BuyXmrArgs, GetHistoryArgs, GetSwapInfosAllArgs, MoneroRecoveryArgs, BalanceArgs, BuyXmrArgs, GetHistoryArgs, GetLogsArgs, GetSwapInfosAllArgs,
ResumeSwapArgs, SuspendCurrentSwapArgs, WithdrawBtcArgs, MoneroRecoveryArgs, ResumeSwapArgs, SuspendCurrentSwapArgs, WithdrawBtcArgs,
}, },
tauri_bindings::{TauriContextStatusEvent, TauriEmitter, TauriHandle}, tauri_bindings::{TauriContextStatusEvent, TauriEmitter, TauriHandle},
Context, ContextBuilder, Context, ContextBuilder,
@ -168,6 +168,7 @@ pub fn run() {
resume_swap, resume_swap,
get_history, get_history,
monero_recovery, monero_recovery,
get_logs,
suspend_current_swap, suspend_current_swap,
is_context_available, is_context_available,
]) ])
@ -206,6 +207,7 @@ tauri_command!(buy_xmr, BuyXmrArgs);
tauri_command!(resume_swap, ResumeSwapArgs); tauri_command!(resume_swap, ResumeSwapArgs);
tauri_command!(withdraw_btc, WithdrawBtcArgs); tauri_command!(withdraw_btc, WithdrawBtcArgs);
tauri_command!(monero_recovery, MoneroRecoveryArgs); tauri_command!(monero_recovery, MoneroRecoveryArgs);
tauri_command!(get_logs, GetLogsArgs);
// These commands require no arguments // These commands require no arguments
tauri_command!(suspend_current_swap, SuspendCurrentSwapArgs, no_args); tauri_command!(suspend_current_swap, SuspendCurrentSwapArgs, no_args);

View file

@ -359,9 +359,10 @@ impl Request for GetSwapInfosAllArgs {
#[typeshare] #[typeshare]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct GetLogsArgs { pub struct GetLogsArgs {
#[typeshare(serialized_as = "Option<string>")]
pub swap_id: Option<Uuid>, pub swap_id: Option<Uuid>,
pub redact: bool, pub redact: bool,
#[typeshare(serialized_as = "string")] #[typeshare(serialized_as = "Option<string>")]
pub logs_dir: Option<PathBuf>, pub logs_dir: Option<PathBuf>,
} }