Skip to content

Commit

Permalink
Merge pull request #1070 from pascalbreuninger/feat/POD-652-download-…
Browse files Browse the repository at this point in the history
…action-logs

feat(desktop): add "Save Logs" button to actions view
  • Loading branch information
89luca89 committed May 17, 2024
2 parents 5e422b8 + c3e099b commit 55ef6d0
Show file tree
Hide file tree
Showing 16 changed files with 100 additions and 19 deletions.
2 changes: 1 addition & 1 deletion desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ tauri-build = { version = "1.2", features = [] }

[dependencies]
# Tauri
tauri = { version = "1.2.4", features = [
tauri = { version = "1.2.4", features = [ "dialog-save",
"process-relaunch",
"window-close",
"notification-all",
Expand Down
11 changes: 11 additions & 0 deletions desktop/src-tauri/src/action_logs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,17 @@ pub fn get_action_logs(
Ok(lines)
}

#[tauri::command]
pub fn get_action_log_file(
app_handle: AppHandle,
action_id: String,
) -> Result<String, ActionLogError> {
let mut path = get_actions_dir(&app_handle).map_err(|_| ActionLogError::NoDir)?;
path.push(format!("{}.log", &action_id));

Ok(path.to_string_lossy().into())
}

#[tauri::command]
pub fn sync_action_logs(app_handle: AppHandle, actions: Vec<String>) -> Result<(), ActionLogError> {
let now = SystemTime::now();
Expand Down
2 changes: 2 additions & 0 deletions desktop/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ fn main() -> anyhow::Result<()> {
ui_ready::ui_ready,
action_logs::write_action_log,
action_logs::get_action_logs,
action_logs::get_action_log_file,
action_logs::sync_action_logs,
install_cli::install_cli,
community_contributions::get_contributions,
Expand All @@ -157,6 +158,7 @@ fn main() -> anyhow::Result<()> {
ui_ready::ui_ready,
action_logs::write_action_log,
action_logs::get_action_logs,
action_logs::get_action_log_file,
action_logs::sync_action_logs,
install_cli::install_cli,
community_contributions::get_contributions,
Expand Down
3 changes: 2 additions & 1 deletion desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
"all": true
},
"dialog": {
"open": true
"open": true,
"save": true
},
"path": {
"all": true
Expand Down
6 changes: 5 additions & 1 deletion desktop/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ class Client {
return dialog.open({ directory: false, multiple: false })
}

public async copyFile(src: string, dest: string): Promise<void> {
return fs.copyFile(src, dest)
}

public async installCLI(force: boolean = false): Promise<Result<void>> {
try {
await invoke("install_cli", { force })
Expand Down Expand Up @@ -233,7 +237,7 @@ class Client {
}
}

public openLink(link: string): void {
public open(link: string): void {
shell.open(link)
}

Expand Down
17 changes: 16 additions & 1 deletion desktop/src/client/workspaces/client.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { invoke } from "@tauri-apps/api"
import { TActionID, TActionName, TActionObj } from "../../contexts"
import { Result, ResultError, Return, THandler, exists, noop } from "../../lib"
import { Result, ResultError, Return, THandler, exists, isError, noop } from "../../lib"
import {
TDevcontainerSetup,
TStreamID,
Expand Down Expand Up @@ -271,4 +271,19 @@ export class WorkspacesClient implements TDebuggable {
public syncActionLogs(actionIDs: readonly string[]) {
invoke("sync_action_logs", { actions: actionIDs })
}

public async getActionLogFile(actionID: TActionID): Promise<Result<string>> {
try {
const path = await invoke<string>("get_action_log_file", { actionId: actionID })

return Return.Value(path)
} catch (e) {
if (isError(e)) {
return Return.Failed(e.message)
}
console.error(e)

return Return.Failed(`Unable to retrieve log file for action ${actionID}`)
}
}
}
2 changes: 1 addition & 1 deletion desktop/src/components/Layout/Notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ export function Notifications() {
<Heading size="xs">{pendingUpdate.tag_name} is available</Heading>
<Text fontSize="xs">
See{" "}
<Link onClick={() => client.openLink(pendingUpdate.html_url)}>
<Link onClick={() => client.open(pendingUpdate.html_url)}>
release notes
</Link>
</Text>
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/components/Layout/Pro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function Pro() {

const backgroundColor = useColorModeValue("white", "gray.900")
const handleAnnouncementClicked = () => {
client.openLink("https://devpod.sh/pro")
client.open("https://devpod.sh/pro")
}
const { experimental_devPodPro } = useSettings()
const isProUnauthenticated = proInstances?.some(({ authenticated }) => !authenticated)
Expand Down Expand Up @@ -98,7 +98,7 @@ export function Pro() {
or create a new one. <br />
<Link
color="primary.600"
onClick={() => client.openLink("https://devpod.sh/pro")}>
onClick={() => client.open("https://devpod.sh/pro")}>
Learn more
</Link>
</Text>
Expand Down
6 changes: 3 additions & 3 deletions desktop/src/components/Layout/StatusBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export function StatusBar(boxProps: BoxProps) {
rounded="full"
icon={<StarIcon color={iconColor} />}
aria-label="Loving DevPod? Give us a star on Github"
onClick={() => client.openLink("https://github.com/loft-sh/devpod")}
onClick={() => client.open("https://github.com/loft-sh/devpod")}
/>
</Tooltip>

Expand All @@ -86,7 +86,7 @@ export function StatusBar(boxProps: BoxProps) {
rounded="full"
icon={<Icon as={HiDocumentMagnifyingGlass} color={iconColor} />}
aria-label="How to DevPod - Docs"
onClick={() => client.openLink("https://devpod.sh/docs")}
onClick={() => client.open("https://devpod.sh/docs")}
/>
</Tooltip>

Expand All @@ -96,7 +96,7 @@ export function StatusBar(boxProps: BoxProps) {
rounded="full"
icon={<Icon as={FaBug} color={iconColor} />}
aria-label="Report an Issue"
onClick={() => client.openLink("https://github.com/loft-sh/devpod/issues/new/choose")}
onClick={() => client.open("https://github.com/loft-sh/devpod/issues/new/choose")}
/>
</Tooltip>

Expand Down
2 changes: 1 addition & 1 deletion desktop/src/components/Layout/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function Toolbar({ ...boxProps }: BoxProps) {
<GridItem display="flex" alignItems="center">
{title}
</GridItem>
<GridItem display="flex" alignItems="center" justifyContent="center">
<GridItem display="flex" alignItems="center" justifyContent="start">
{actions}
</GridItem>
<GridItem display="flex" alignItems="center" justifyContent="center">
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/components/LoftOSSBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export function LoftOSSBadge() {
display="flex"
alignItems="center"
justifyContent="start"
onClick={() => client.openLink("https://loft.sh/")}>
onClick={() => client.open("https://loft.sh/")}>
<Text fontSize="sm" color={textColor} marginRight="2">
Open sourced by
</Text>
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/useChangelogModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function Changelog({ rawMarkdown }: TChangeLogProps) {
props: {
onClick: (e: TLinkClickEvent) => {
e.preventDefault()
client.openLink(e.target.href)
client.open(e.target.href)
},
},
},
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/useWelcomeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export function useWelcomeModal() {
For more information, head over to our{" "}
<Link
color="primary.600"
onClick={() => client.openLink("https://devpod.sh/docs")}>
onClick={() => client.open("https://devpod.sh/docs")}>
documentation.
</Link>
</Text>
Expand All @@ -120,7 +120,7 @@ export function useWelcomeModal() {
DevPod ships with a powerful CLI that allows you to create, manage and connect
to your workspaces and providers. You can either{" "}
<Link
onClick={() => client.openLink("https://github.com/loft-sh/devpod/releases")}>
onClick={() => client.open("https://github.com/loft-sh/devpod/releases")}>
download the standalone binary
</Link>{" "}
or directly add it to your <Code>$PATH</Code>.
Expand Down
52 changes: 50 additions & 2 deletions desktop/src/views/Actions/Action.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { Box, Button } from "@chakra-ui/react"
import { Box, Button, IconButton, Tooltip, useToast } from "@chakra-ui/react"
import { useEffect, useMemo } from "react"
import { HiStop } from "react-icons/hi2"
import { useNavigate } from "react-router"
import { useParams, useSearchParams } from "react-router-dom"
import { ToolbarActions, useStreamingTerminal } from "../../components"
import { useAction } from "../../contexts"
import { TActionID, useAction } from "../../contexts"
import { Routes } from "../../routes"
import { DownloadIcon } from "@chakra-ui/icons"
import { client } from "@/client"
import { useMutation } from "@tanstack/react-query"
import { dialog } from "@tauri-apps/api"

export function Action() {
const [searchParams] = useSearchParams()
Expand All @@ -32,6 +36,38 @@ export function Action() {
}
}, [searchParams, action, navigate])

const toast = useToast()
const { mutate: handleDownloadLogsClicked, isLoading: isDownloadingLogs } = useMutation({
mutationFn: async ({ actionID }: { actionID: TActionID }) => {
const actionLogFile = (await client.workspaces.getActionLogFile(actionID)).unwrap()

if (actionLogFile === undefined) {
throw new Error(`Unable to retrieve file for action ${actionID}`)
}

const targetFile = await dialog.save({
title: "Save Logs",
filters: [{ name: "format", extensions: ["log", "txt"] }],
})

// user cancelled "save file" dialog
if (targetFile === null) {
return
}

await client.copyFile(actionLogFile, targetFile)
client.open(targetFile)
},
onError(error) {
toast({
title: `Failed to save logs: ${error}`,
status: "error",
isClosable: true,
duration: 30_000, // 30 sec
})
},
})

return (
<>
<ToolbarActions>
Expand All @@ -44,6 +80,18 @@ export function Action() {
Cancel
</Button>
)}
{actionID !== undefined && (
<Tooltip label="Save Logs">
<IconButton
isLoading={isDownloadingLogs}
title="Save Logs"
variant="outline"
aria-label="Save Logs"
icon={<DownloadIcon />}
onClick={() => handleDownloadLogsClicked({ actionID })}
/>
</Tooltip>
)}
</ToolbarActions>
<Box height="calc(100% - 3rem)" width="full">
{terminal}
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/views/Settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ function UpdateSettings() {
{downloadLink && (
<Text fontSize="sm" width="full">
Visit{" "}
<Link onClick={() => client.openLink(downloadLink)} fontSize="sm">
<Link onClick={() => client.open(downloadLink)} fontSize="sm">
Github
</Link>{" "}
to download {selectedVersion}
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/views/Settings/useContextOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ export function useTelemetryOption() {
Telemetry plays an important role in improving DevPod for everyone.{" "}
<strong>We never collect any actual values, only anonymized metadata!</strong> For an
in-depth explanation, please refer to the{" "}
<Link onClick={() => client.openLink("https://devpod.sh/docs/other-topics/telemetry")}>
<Link onClick={() => client.open("https://devpod.sh/docs/other-topics/telemetry")}>
documentation
</Link>
</>
Expand Down

0 comments on commit 55ef6d0

Please sign in to comment.