Skip to content

Commit 769a1ad

Browse files
authored
Merge pull request #85 from UiPath/fix/ui-styling-tweaks
fix: revamp UI with status bar, favicon, and project metadata
2 parents 9fcbf1d + 7f2bab0 commit 769a1ad

File tree

19 files changed

+418
-338
lines changed

19 files changed

+418
-338
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath-dev"
3-
version = "0.0.58"
3+
version = "0.0.59"
44
description = "UiPath Developer Console"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"

src/uipath/dev/server/app.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from fastapi import FastAPI
1010
from fastapi.middleware.cors import CORSMiddleware
11-
from fastapi.responses import HTMLResponse, Response
11+
from fastapi.responses import HTMLResponse
1212

1313
from uipath.dev.server import UiPathDeveloperServer
1414

@@ -108,25 +108,6 @@ def create_app(server: UiPathDeveloperServer) -> FastAPI:
108108
allow_headers=["*"],
109109
)
110110

111-
# Favicon — UiPath orange branded icon
112-
_favicon_svg = (
113-
'<?xml version="1.0" encoding="UTF-8"?>'
114-
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">'
115-
'<rect width="32" height="32" rx="6" fill="#FA4616"/>'
116-
'<text x="16" y="24" font-size="22" text-anchor="middle" fill="#FFFFFF" '
117-
'font-family="system-ui, -apple-system, sans-serif" font-weight="700">U</text>'
118-
"</svg>"
119-
)
120-
_favicon_bytes = _favicon_svg.encode("utf-8")
121-
122-
@app.get("/favicon.ico", include_in_schema=False)
123-
async def _favicon_ico():
124-
return Response(content=_favicon_bytes, media_type="image/svg+xml")
125-
126-
@app.get("/favicon.svg", include_in_schema=False)
127-
async def _favicon_svg_route():
128-
return Response(content=_favicon_bytes, media_type="image/svg+xml")
129-
130111
# Store server reference on app state for route access
131112
app.state.server = server
132113

@@ -136,10 +117,36 @@ async def _favicon_svg_route():
136117
"no",
137118
)
138119

120+
# Read user's pyproject.toml from CWD (once at startup)
121+
_user_project: dict[str, str | None] = {
122+
"project_name": None,
123+
"project_version": None,
124+
"project_authors": None,
125+
}
126+
_pyproject_path = Path.cwd() / "pyproject.toml"
127+
if _pyproject_path.is_file():
128+
try:
129+
import tomllib
130+
131+
with open(_pyproject_path, "rb") as f:
132+
_pydata = tomllib.load(f)
133+
_proj = _pydata.get("project", {})
134+
_user_project["project_name"] = _proj.get("name")
135+
_user_project["project_version"] = _proj.get("version")
136+
_authors = _proj.get("authors")
137+
if _authors and isinstance(_authors, list) and len(_authors) > 0:
138+
_user_project["project_authors"] = (
139+
_authors[0].get("name")
140+
if isinstance(_authors[0], dict)
141+
else str(_authors[0])
142+
)
143+
except Exception:
144+
pass
145+
139146
# Config endpoint — tells the frontend which features are available
140147
@app.get("/api/config", include_in_schema=False)
141148
async def _config():
142-
return {"auth_enabled": auth_enabled}
149+
return {"auth_enabled": auth_enabled, **_user_project}
143150

144151
# Register routes
145152
from uipath.dev.server.routes.entrypoints import router as entrypoints_router

src/uipath/dev/server/frontend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
66
<title>UiPath Developer Console</title>
7-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7+
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
88
</head>
99
<body>
1010
<div id="root"></div>
16.1 KB
Binary file not shown.

src/uipath/dev/server/frontend/src/App.tsx

Lines changed: 51 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { useCallback, useEffect, useRef, useState } from "react";
22
import { useRunStore } from "./store/useRunStore";
33
import { useAuthStore } from "./store/useAuthStore";
4+
import { useConfigStore } from "./store/useConfigStore";
45
import { useWebSocket } from "./store/useWebSocket";
56
import { listRuns, listEntrypoints, getRun } from "./api/client";
67
import type { RunDetail } from "./types/run";
78
import { useHashRoute } from "./hooks/useHashRoute";
89
import { useIsMobile } from "./hooks/useIsMobile";
910
import Sidebar from "./components/layout/Sidebar";
11+
import StatusBar from "./components/layout/StatusBar";
1012
import NewRunPanel from "./components/runs/NewRunPanel";
1113
import SetupView from "./components/runs/SetupView";
1214
import RunDetailsPanel from "./components/runs/RunDetailsPanel";
@@ -40,15 +42,17 @@ export default function App() {
4042
}
4143
}, [view, routeRunId, selectedRunId, selectRun]);
4244

43-
// Load existing runs, entrypoints, and auth status on mount
45+
// Load existing runs, entrypoints, auth status, and config on mount
4446
const initAuth = useAuthStore((s) => s.init);
47+
const initConfig = useConfigStore((s) => s.init);
4548
useEffect(() => {
4649
listRuns().then(setRuns).catch(console.error);
4750
listEntrypoints()
4851
.then((eps) => setEntrypoints(eps.map((e) => e.name)))
4952
.catch(console.error);
5053
initAuth();
51-
}, [setRuns, setEntrypoints, initAuth]);
54+
initConfig();
55+
}, [setRuns, setEntrypoints, initAuth, initConfig]);
5256

5357
const selectedRun = selectedRunId ? runs[selectedRunId] : null;
5458

@@ -182,49 +186,52 @@ export default function App() {
182186
};
183187

184188
return (
185-
<div className="flex h-screen w-screen relative">
186-
{/* Mobile hamburger button */}
187-
{isMobile && !sidebarOpen && (
188-
<button
189-
onClick={() => setSidebarOpen(true)}
190-
className="fixed top-2 left-2 z-40 w-9 h-9 flex items-center justify-center rounded-lg cursor-pointer"
191-
style={{ background: "var(--bg-secondary)", border: "1px solid var(--border)" }}
192-
>
193-
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
194-
<line x1="3" y1="6" x2="21" y2="6" />
195-
<line x1="3" y1="12" x2="21" y2="12" />
196-
<line x1="3" y1="18" x2="21" y2="18" />
197-
</svg>
198-
</button>
199-
)}
200-
<Sidebar
201-
runs={Object.values(runs)}
202-
selectedRunId={selectedRunId}
203-
onSelectRun={handleSelectRun}
204-
onNewRun={handleNewRun}
205-
isMobile={isMobile}
206-
isOpen={sidebarOpen}
207-
onClose={() => setSidebarOpen(false)}
208-
/>
209-
<main className="flex-1 overflow-hidden bg-[var(--bg-primary)]">
210-
{view === "new" ? (
211-
<NewRunPanel />
212-
) : view === "setup" && setupEntrypoint && setupMode ? (
213-
<SetupView
214-
entrypoint={setupEntrypoint}
215-
mode={setupMode}
216-
ws={ws}
217-
onRunCreated={handleRunCreated}
218-
isMobile={isMobile}
219-
/>
220-
) : selectedRun ? (
221-
<RunDetailsPanel run={selectedRun} ws={ws} isMobile={isMobile} />
222-
) : (
223-
<div className="flex items-center justify-center h-full text-[var(--text-muted)]">
224-
Select a run or create a new one
225-
</div>
189+
<div className="flex flex-col h-screen w-screen">
190+
<div className="flex flex-1 overflow-hidden relative">
191+
{/* Mobile hamburger button */}
192+
{isMobile && !sidebarOpen && (
193+
<button
194+
onClick={() => setSidebarOpen(true)}
195+
className="fixed top-2 left-2 z-40 w-9 h-9 flex items-center justify-center rounded-lg cursor-pointer"
196+
style={{ background: "var(--bg-secondary)", border: "1px solid var(--border)" }}
197+
>
198+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round">
199+
<line x1="3" y1="6" x2="21" y2="6" />
200+
<line x1="3" y1="12" x2="21" y2="12" />
201+
<line x1="3" y1="18" x2="21" y2="18" />
202+
</svg>
203+
</button>
226204
)}
227-
</main>
205+
<Sidebar
206+
runs={Object.values(runs)}
207+
selectedRunId={selectedRunId}
208+
onSelectRun={handleSelectRun}
209+
onNewRun={handleNewRun}
210+
isMobile={isMobile}
211+
isOpen={sidebarOpen}
212+
onClose={() => setSidebarOpen(false)}
213+
/>
214+
<main className="flex-1 overflow-hidden bg-[var(--bg-primary)]">
215+
{view === "new" ? (
216+
<NewRunPanel />
217+
) : view === "setup" && setupEntrypoint && setupMode ? (
218+
<SetupView
219+
entrypoint={setupEntrypoint}
220+
mode={setupMode}
221+
ws={ws}
222+
onRunCreated={handleRunCreated}
223+
isMobile={isMobile}
224+
/>
225+
) : selectedRun ? (
226+
<RunDetailsPanel run={selectedRun} ws={ws} isMobile={isMobile} />
227+
) : (
228+
<div className="flex items-center justify-center h-full text-[var(--text-muted)]">
229+
Select a run or create a new one
230+
</div>
231+
)}
232+
</main>
233+
</div>
234+
<StatusBar />
228235
<ReloadToast />
229236
</div>
230237
);

0 commit comments

Comments
 (0)