diff --git a/app.go b/app.go index 07556d3..75e57f5 100644 --- a/app.go +++ b/app.go @@ -83,6 +83,41 @@ func (a *App) Invite(email string) string { return resp.Status } +func (a *App) getEnvZId(status string) (string,string) { + arr := strings.Split(status, " ") + return arr[len(arr)-4],arr[len(arr)-9] +} + + +func (a *App) UnShare(shrToken string) string { + status := []string{"status", "--secrets"} + output, _ := zrokCmd(status).Output() + + envZId, XToken := a.getEnvZId(string(output)) + + xurlsStrict := xurls.Strict() + find := xurlsStrict.FindAllString(string(output), -1) + apiEndpoint := find[0] + + requestBody := []byte(fmt.Sprintf(`{"envZId": "%s", "shrToken": "%s"}`, envZId,shrToken )) + log.Info("requestBody", string(requestBody)) + req, err := http.NewRequest("DELETE", apiEndpoint+"/api/v1/unshare", bytes.NewBuffer(requestBody)) + req.Header.Add("Content-Type", "application/zrok.v1+json") + req.Header.Add("X-Token", XToken) + + if err != nil { + log.Error("创建请求出错:", err) + } + + resp, err := http.DefaultClient.Do(req) + + if err != nil { + log.Error("发送请求时出错:", err) + } + defer resp.Body.Close() + return resp.Status +} + func (a *App) Version() string { version := []string{"version"} output, _ := zrokCmd(version).Output() @@ -120,3 +155,8 @@ func (a *App) Zrok(args []string) string { return stdout.String() } +// Open link in browser +func (a *App) OpenExternal(link string) { + runtime.BrowserOpenURL(a.ctx, link) +} + diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index a5484c9..70e809e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,10 +1,10 @@ import router from "./router"; -import { useEffect, useState } from "react"; import { isDark } from "./utils"; +import { Theme } from "@radix-ui/themes"; import { Toaster } from "react-hot-toast"; +import { useEffect, useState } from "react"; import { RouterProvider } from "react-router-dom"; import { useAutoDark } from "./hooks/useAutoDark"; -import { Theme, ThemePanel } from "@radix-ui/themes"; const App = () => { const [theme] = useAutoDark(); @@ -34,7 +34,6 @@ const App = () => { }, }} /> - ); }; diff --git a/frontend/src/assets/images/space3-1327x1536.png.webp b/frontend/src/assets/images/space3-1327x1536.png.webp new file mode 100644 index 0000000..f843a02 Binary files /dev/null and b/frontend/src/assets/images/space3-1327x1536.png.webp differ diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index cf5eda9..521643c 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -1,8 +1,9 @@ import React from "react"; -import { Link } from "react-router-dom"; -import { Card, Flex, Text } from "@radix-ui/themes"; +import { Link, useLocation } from "react-router-dom"; +import { Card, Flex, Text, ScrollArea } from "@radix-ui/themes"; const Sidebar = () => { + const { pathname } = useLocation(); const menus = [ { title: "Overview", @@ -28,27 +29,30 @@ const Sidebar = () => { return ( - - {menus.map((menu) => ( - - - - {menu.title} - - - - ))} - + + + {menus.map((menu) => ( + + + + {menu.title} + + + + ))} + + ); }; diff --git a/frontend/src/views/enable.tsx b/frontend/src/views/enable.tsx index 16f5070..e14287c 100644 --- a/frontend/src/views/enable.tsx +++ b/frontend/src/views/enable.tsx @@ -1,7 +1,8 @@ import { useState } from "react"; +import { Info } from "lucide-react"; import toast from "react-hot-toast"; -import { Zrok } from "../../wailsjs/go/main/App"; -import { Card, TextField, Button } from "@radix-ui/themes"; +import { Zrok, OpenExternal } from "../../wailsjs/go/main/App"; +import { Card, Tooltip, Flex, Text, TextField, Button } from "@radix-ui/themes"; const Page = () => { const [command, setCommand] = useState(""); @@ -22,22 +23,42 @@ const Page = () => { }; return ( - -

Enable your zrok account

-
+ + + Enable your zrok account + setCommand(e.target.value)} - /> + > + + + OpenExternal("https://api.zrok.io/")} + /> + + + -
+
); }; diff --git a/frontend/src/views/invite.tsx b/frontend/src/views/invite.tsx index 7ee38cc..28e911d 100644 --- a/frontend/src/views/invite.tsx +++ b/frontend/src/views/invite.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import toast from "react-hot-toast"; -import { Card, TextField, Button } from "@radix-ui/themes"; +import { Card, Flex, Text, TextField, Button } from "@radix-ui/themes"; import { Invite } from "../../wailsjs/go/main/App"; const Page = () => { @@ -23,21 +23,33 @@ const Page = () => { }; return ( - -
+ + + Please input email address setEmail(e.target.value)} /> + -
+
); }; diff --git a/frontend/src/views/overview.tsx b/frontend/src/views/overview.tsx index 3d33ff0..d3603e7 100644 --- a/frontend/src/views/overview.tsx +++ b/frontend/src/views/overview.tsx @@ -1,8 +1,20 @@ import dayjs from "dayjs"; +import { Delete, RefreshCw } from "lucide-react"; import { useEffect, useState } from "react"; -import { Card, Table } from "@radix-ui/themes"; import { Share, Environment } from "../../types/zrok"; -import { Overview } from "../../wailsjs/go/main/App"; +import { Overview, OpenExternal, UnShare } from "../../wailsjs/go/main/App"; +import { + Box, + Flex, + Text, + Link, + Table, + Button, + Skeleton, + ScrollArea, + Separator, +} from "@radix-ui/themes"; +import toast from "react-hot-toast"; type Environments = { environment: Environment[]; @@ -29,67 +41,120 @@ const Page = () => { useEffect(() => { if (!loading) { - setShares(environments[0]?.shares!); + setShares(environments[0]?.shares ?? []); } }, [loading]); - return ( - - - - - Property - Value - - - - {shares.map((share, index) => ( - - - backendMode - {share.backendMode} - - - shareMode - {share.shareMode} - - - frontendSelection - {share.frontendSelection} - - - - backendProxyEndpoint - - - {share.backendProxyEndpoint} - - - + const handleClickFrontendEndpoint = (url: string) => { + if (url == "private") { + return; + } + OpenExternal(url); + }; - - frontendEndpoint - - {share.frontendEndpoint} - - + const handleDelete = async (share: Share) => { + const result = await UnShare(share.token); + toast.success(result); + }; - - createdAt - - {dayjs(share.createdAt).format("YYYY/M/DD HH:mm:ss")} - - - - updatedAt - - {dayjs(share.updatedAt).format("YYYY/M/DD HH:mm:ss")} - - - - ))} - - + return ( + + + + + + + + + + + backendMode + + backendProxyEndpoint + + + frontendEndpoint + + shareMode + token + createdAt + updatedAt + zId + Actions + + + + {shares.map((share, index) => ( + + {share.backendMode} + + OpenExternal(share.backendProxyEndpoint)} + > + {share.backendProxyEndpoint} + + + + {share.frontendEndpoint == "private" ? ( + {share.frontendEndpoint} + ) : ( + + handleClickFrontendEndpoint(share.frontendEndpoint) + } + > + {share.frontendEndpoint} + + )} + + {share.shareMode} + {share.token} + + {dayjs(share.createdAt).format("YYYY/M/DD HH:mm:ss")} + + + {dayjs(share.updatedAt).format("YYYY/M/DD HH:mm:ss")} + + {share.zId} + + + + + ))} + + + + + ); }; diff --git a/frontend/src/views/sharing.tsx b/frontend/src/views/sharing.tsx index 9511179..05fe114 100644 --- a/frontend/src/views/sharing.tsx +++ b/frontend/src/views/sharing.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { Share, Environment } from "../../types/zrok"; import { Zrok, Overview } from "../../wailsjs/go/main/App"; -import { Tabs, Box, TextField, Button } from "@radix-ui/themes"; +import { Tabs, Flex, Card, Box, TextField, Button } from "@radix-ui/themes"; type Environments = { environment: Environment[]; @@ -40,46 +40,90 @@ const Sharing = () => { }; return ( - - - setType("public")} + + + - Public - - setType("private")} - > - Private - - - - - - setHostname(e.target.value)} - /> - setHostport(e.target.value)} - /> - - + + setType("public")} + > + Public + + setType("private")} + > + Private + + - - - + + + + setHostname(e.target.value)} + /> + setHostport(e.target.value)} + /> + + + + + + setHostname(e.target.value)} + /> + setHostport(e.target.value)} + /> + + + + + + + ); }; diff --git a/frontend/src/views/version.tsx b/frontend/src/views/version.tsx index c5efdee..52a1281 100644 --- a/frontend/src/views/version.tsx +++ b/frontend/src/views/version.tsx @@ -1,4 +1,4 @@ -import { Card } from "@radix-ui/themes"; +import { Card, Flex, Text } from "@radix-ui/themes"; import { useEffect, useState } from "react"; import { Version } from "../../wailsjs/go/main/App"; @@ -13,7 +13,24 @@ const Page = () => { getVersion(); }, []); return ( - Version: {version} + + + + Version: {version} + + + + ); }; diff --git a/frontend/wailsjs/go/main/App.d.ts b/frontend/wailsjs/go/main/App.d.ts index d9f884e..6e3b401 100644 --- a/frontend/wailsjs/go/main/App.d.ts +++ b/frontend/wailsjs/go/main/App.d.ts @@ -9,10 +9,14 @@ export function Maximize():Promise; export function Minimize():Promise; +export function OpenExternal(arg1:string):Promise; + export function Overview():Promise; export function Quit():Promise; +export function UnShare(arg1:string):Promise; + export function Version():Promise; export function Zrok(arg1:Array):Promise; diff --git a/frontend/wailsjs/go/main/App.js b/frontend/wailsjs/go/main/App.js index 37e4938..7fbe218 100644 --- a/frontend/wailsjs/go/main/App.js +++ b/frontend/wailsjs/go/main/App.js @@ -18,6 +18,10 @@ export function Minimize() { return window['go']['main']['App']['Minimize'](); } +export function OpenExternal(arg1) { + return window['go']['main']['App']['OpenExternal'](arg1); +} + export function Overview() { return window['go']['main']['App']['Overview'](); } @@ -26,6 +30,10 @@ export function Quit() { return window['go']['main']['App']['Quit'](); } +export function UnShare(arg1) { + return window['go']['main']['App']['UnShare'](arg1); +} + export function Version() { return window['go']['main']['App']['Version'](); } diff --git a/main.go b/main.go index 47b42b7..1e68cbd 100644 --- a/main.go +++ b/main.go @@ -17,9 +17,11 @@ func main() { // Create application with options err := wails.Run(&options.App{ - Title: "zroker", + Title: "Zroker", Width: 640, Height: 360, + MinWidth: 640, + MinHeight: 360, AssetServer: &assetserver.Options{ Assets: assets, },