Skip to content

Commit a7cb2d0

Browse files
committed
fixup
1 parent 7eb0f98 commit a7cb2d0

3 files changed

Lines changed: 163 additions & 51 deletions

File tree

src/uipath/_cli/_dev/_terminal/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@ def compose(self) -> ComposeResult:
7474
yield NewRunPanel(
7575
id="new-run-panel",
7676
classes="new-run-panel",
77-
initial_entrypoint=self.initial_entrypoint,
78-
initial_input=self.initial_input,
7977
)
8078

8179
# Run details panel (initially hidden)
Lines changed: 99 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,77 @@
1-
from typing import Tuple
1+
import json
2+
import os
3+
from typing import Dict, Tuple
24

35
from textual.app import ComposeResult
46
from textual.containers import Container, Horizontal, Vertical
5-
from textual.widgets import Button, Static, TextArea
7+
from textual.reactive import reactive
8+
from textual.widgets import Button, Select, TextArea
9+
10+
11+
def mock_json_from_schema(schema: Dict) -> Dict:
12+
props = schema.get("properties", {})
13+
required = schema.get("required", [])
14+
mock = {}
15+
for key, info in props.items():
16+
if "default" in info:
17+
mock[key] = info["default"]
18+
continue
19+
t = info.get("type")
20+
if t == "string":
21+
mock[key] = f"example_{key}" if key in required else ""
22+
elif t == "integer":
23+
mock[key] = 0 if key in required else None
24+
elif t == "boolean":
25+
mock[key] = True if key in required else False
26+
elif t == "array":
27+
item_schema = info.get("items", {"type": "string"})
28+
mock[key] = [mock_json_from_schema(item_schema)]
29+
elif t == "object":
30+
mock[key] = mock_json_from_schema(info)
31+
else:
32+
mock[key] = None
33+
return mock
634

735

836
class NewRunPanel(Container):
9-
"""Panel for creating new runs."""
10-
11-
def __init__(
12-
self,
13-
initial_entrypoint: str = "main.py",
14-
initial_input: str = '{\n "message": "Hello World"\n}',
15-
**kwargs,
16-
):
37+
"""Panel for creating new runs with a Select entrypoint selector."""
38+
39+
selected_entrypoint = reactive("")
40+
41+
def __init__(self, **kwargs):
1742
super().__init__(**kwargs)
18-
self.initial_entrypoint = initial_entrypoint
19-
self.initial_input = initial_input
43+
json_path = os.path.join(os.getcwd(), "uipath.json")
44+
with open(json_path, "r") as f:
45+
data = json.load(f)
46+
47+
self.entrypoints = data.get("entryPoints", [])
48+
self.entrypoint_paths = [ep["filePath"] for ep in self.entrypoints]
49+
50+
self.selected_entrypoint = (
51+
self.entrypoint_paths[0] if self.entrypoint_paths else ""
52+
)
53+
ep = next(
54+
(
55+
ep
56+
for ep in self.entrypoints
57+
if ep["filePath"] == self.selected_entrypoint
58+
),
59+
{},
60+
)
61+
self.initial_input = json.dumps(
62+
mock_json_from_schema(ep.get("input", {})), indent=2
63+
)
2064

2165
def compose(self) -> ComposeResult:
2266
with Vertical():
23-
yield Static("Entrypoint", classes="field-label")
24-
yield TextArea(
25-
text=self.initial_entrypoint,
26-
id="script-input",
27-
classes="input-field script-input",
67+
options = [(path, path) for path in self.entrypoint_paths]
68+
yield Select(
69+
options,
70+
id="entrypoint-select",
71+
value=self.selected_entrypoint,
72+
allow_blank=False,
2873
)
2974

30-
yield Static("Input JSON", classes="field-label")
3175
yield TextArea(
3276
text=self.initial_input,
3377
language="json",
@@ -37,10 +81,7 @@ def compose(self) -> ComposeResult:
3781

3882
with Horizontal(classes="run-actions"):
3983
yield Button(
40-
"▶ Run",
41-
id="execute-btn",
42-
variant="primary",
43-
classes="action-btn",
84+
"▶ Run", id="execute-btn", variant="primary", classes="action-btn"
4485
)
4586
yield Button(
4687
"Cancel",
@@ -49,17 +90,44 @@ def compose(self) -> ComposeResult:
4990
classes="action-btn cancel-btn",
5091
)
5192

52-
def get_input_values(self) -> Tuple[str, str]:
53-
"""Get the current input values from the form."""
54-
script_input = self.query_one("#script-input", TextArea)
93+
async def on_select_changed(self, event: Select.Changed) -> None:
94+
"""Update JSON input when user selects an entrypoint."""
95+
self.selected_entrypoint = event.value
96+
97+
ep = next(
98+
(
99+
ep
100+
for ep in self.entrypoints
101+
if ep["filePath"] == self.selected_entrypoint
102+
),
103+
{},
104+
)
55105
json_input = self.query_one("#json-input", TextArea)
106+
json_input.text = json.dumps(
107+
mock_json_from_schema(ep.get("input", {})), indent=2
108+
)
56109

57-
return script_input.text.strip(), json_input.text.strip()
110+
def get_input_values(self) -> Tuple[str, str]:
111+
json_input = self.query_one("#json-input", TextArea)
112+
return self.selected_entrypoint, json_input.text.strip()
58113

59114
def reset_form(self):
60-
"""Reset form to initial values."""
61-
script_input = self.query_one("#script-input", TextArea)
62-
json_input = self.query_one("#json-input", TextArea)
115+
"""Reset selection and JSON input to defaults."""
116+
self.selected_entrypoint = (
117+
self.entrypoint_paths[0] if self.entrypoint_paths else ""
118+
)
119+
select = self.query_one("#entrypoint-select", Select)
120+
select.value = self.selected_entrypoint
63121

64-
script_input.text = self.initial_entrypoint
65-
json_input.text = self.initial_input
122+
ep = next(
123+
(
124+
ep
125+
for ep in self.entrypoints
126+
if ep["filePath"] == self.selected_entrypoint
127+
),
128+
{},
129+
)
130+
json_input = self.query_one("#json-input", TextArea)
131+
json_input.text = json.dumps(
132+
mock_json_from_schema(ep.get("input", {})), indent=2
133+
)

src/uipath/_cli/_dev/_terminal/_styles/terminal.tcss

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ Screen {
7171
padding: 0 1;
7272
height: 1;
7373
border: solid #404040;
74-
border-bottom: none;
7574
margin-bottom: 0;
7675
}
7776

@@ -87,21 +86,6 @@ Screen {
8786
background: #252525;
8887
}
8988

90-
.input-field {
91-
border: solid #404040;
92-
margin-bottom: 1;
93-
background: #1a1a1a;
94-
color: #e0e0e0;
95-
}
96-
97-
.script-input {
98-
height: 3;
99-
}
100-
101-
.json-input {
102-
height: 8;
103-
}
104-
10589
.run-actions {
10690
height: 2;
10791
align: left middle;
@@ -212,7 +196,6 @@ RichLog {
212196
Header {
213197
background: #000000;
214198
color: #00d4ff;
215-
border-bottom: solid #404040;
216199
}
217200

218201
Footer {
@@ -312,4 +295,67 @@ SpanDetailsDisplay {
312295

313296
#span-details {
314297
height: 100%;
315-
}
298+
}
299+
300+
/* Panels */
301+
.new-run-panel {
302+
height: 100%;
303+
background: #252525;
304+
padding: 1;
305+
}
306+
307+
/* Section Titles */
308+
.new-run-title {
309+
color: #00d4ff;
310+
text-style: bold;
311+
background: #1f1f1f;
312+
padding: 0 1;
313+
height: 2;
314+
content-align: left middle;
315+
}
316+
317+
/* Labels */
318+
.field-label {
319+
color: #00d4ff;
320+
text-style: bold;
321+
margin: 1 0;
322+
}
323+
324+
.input-field {
325+
background: #1a1a1a;
326+
color: #e0e0e0;
327+
}
328+
329+
.script-input {
330+
height: 3;
331+
}
332+
333+
.json-input {
334+
margin-top: 1;
335+
height: 12;
336+
}
337+
338+
.run-actions {
339+
height: auto;
340+
padding: 1;
341+
}
342+
343+
.action-btn {
344+
min-width: 10;
345+
padding: 0 2;
346+
text-style: bold;
347+
border: none;
348+
}
349+
350+
.action-btn:hover {
351+
background: #00cc66;
352+
}
353+
354+
.cancel-btn {
355+
background: #404040;
356+
color: #e0e0e0;
357+
}
358+
359+
.cancel-btn:hover {
360+
background: #555555;
361+
}

0 commit comments

Comments
 (0)