ferp 0.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ferp/__init__.py +3 -0
- ferp/__main__.py +4 -0
- ferp/__version__.py +1 -0
- ferp/app.py +9 -0
- ferp/cli.py +160 -0
- ferp/core/__init__.py +0 -0
- ferp/core/app.py +1312 -0
- ferp/core/bundle_installer.py +245 -0
- ferp/core/command_provider.py +77 -0
- ferp/core/dependency_manager.py +59 -0
- ferp/core/fs_controller.py +70 -0
- ferp/core/fs_watcher.py +144 -0
- ferp/core/messages.py +49 -0
- ferp/core/path_actions.py +124 -0
- ferp/core/paths.py +3 -0
- ferp/core/protocols.py +8 -0
- ferp/core/script_controller.py +515 -0
- ferp/core/script_protocol.py +35 -0
- ferp/core/script_runner.py +421 -0
- ferp/core/settings.py +16 -0
- ferp/core/settings_store.py +69 -0
- ferp/core/state.py +156 -0
- ferp/core/task_store.py +164 -0
- ferp/core/transcript_logger.py +95 -0
- ferp/domain/__init__.py +0 -0
- ferp/domain/scripts.py +29 -0
- ferp/fscp/host/__init__.py +11 -0
- ferp/fscp/host/host.py +439 -0
- ferp/fscp/host/managed_process.py +113 -0
- ferp/fscp/host/process_registry.py +124 -0
- ferp/fscp/protocol/__init__.py +13 -0
- ferp/fscp/protocol/errors.py +2 -0
- ferp/fscp/protocol/messages.py +55 -0
- ferp/fscp/protocol/schemas/__init__.py +0 -0
- ferp/fscp/protocol/schemas/fscp/1.0/cancel.json +16 -0
- ferp/fscp/protocol/schemas/fscp/1.0/definitions.json +29 -0
- ferp/fscp/protocol/schemas/fscp/1.0/discriminator.json +14 -0
- ferp/fscp/protocol/schemas/fscp/1.0/envelope.json +13 -0
- ferp/fscp/protocol/schemas/fscp/1.0/exit.json +20 -0
- ferp/fscp/protocol/schemas/fscp/1.0/init.json +36 -0
- ferp/fscp/protocol/schemas/fscp/1.0/input_response.json +21 -0
- ferp/fscp/protocol/schemas/fscp/1.0/log.json +21 -0
- ferp/fscp/protocol/schemas/fscp/1.0/message.json +23 -0
- ferp/fscp/protocol/schemas/fscp/1.0/progress.json +23 -0
- ferp/fscp/protocol/schemas/fscp/1.0/request_input.json +47 -0
- ferp/fscp/protocol/schemas/fscp/1.0/result.json +16 -0
- ferp/fscp/protocol/schemas/fscp/__init__.py +0 -0
- ferp/fscp/protocol/state.py +16 -0
- ferp/fscp/protocol/validator.py +123 -0
- ferp/fscp/scripts/__init__.py +0 -0
- ferp/fscp/scripts/runtime/__init__.py +4 -0
- ferp/fscp/scripts/runtime/__main__.py +40 -0
- ferp/fscp/scripts/runtime/errors.py +14 -0
- ferp/fscp/scripts/runtime/io.py +64 -0
- ferp/fscp/scripts/runtime/script.py +149 -0
- ferp/fscp/scripts/runtime/state.py +17 -0
- ferp/fscp/scripts/runtime/worker.py +13 -0
- ferp/fscp/scripts/sdk.py +548 -0
- ferp/fscp/transcript/__init__.py +3 -0
- ferp/fscp/transcript/events.py +14 -0
- ferp/resources/__init__.py +0 -0
- ferp/services/__init__.py +3 -0
- ferp/services/file_listing.py +120 -0
- ferp/services/monday_sync.py +155 -0
- ferp/services/releases.py +214 -0
- ferp/services/scripts.py +90 -0
- ferp/services/update_check.py +130 -0
- ferp/styles/index.tcss +638 -0
- ferp/themes/themes.py +238 -0
- ferp/widgets/__init__.py +17 -0
- ferp/widgets/dialogs.py +167 -0
- ferp/widgets/file_tree.py +991 -0
- ferp/widgets/forms.py +146 -0
- ferp/widgets/output_panel.py +244 -0
- ferp/widgets/panels.py +13 -0
- ferp/widgets/process_list.py +158 -0
- ferp/widgets/readme_modal.py +59 -0
- ferp/widgets/scripts.py +192 -0
- ferp/widgets/task_capture.py +74 -0
- ferp/widgets/task_list.py +493 -0
- ferp/widgets/top_bar.py +110 -0
- ferp-0.7.1.dist-info/METADATA +128 -0
- ferp-0.7.1.dist-info/RECORD +87 -0
- ferp-0.7.1.dist-info/WHEEL +5 -0
- ferp-0.7.1.dist-info/entry_points.txt +2 -0
- ferp-0.7.1.dist-info/licenses/LICENSE +21 -0
- ferp-0.7.1.dist-info/top_level.txt +1 -0
ferp/themes/themes.py
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
from textual.theme import Theme
|
|
2
|
+
|
|
3
|
+
industrial_amber = Theme(
|
|
4
|
+
name="industrial-amber",
|
|
5
|
+
primary="#FFB000",
|
|
6
|
+
secondary="#E09F00",
|
|
7
|
+
accent="#FF6A00",
|
|
8
|
+
foreground="#FFE8B3",
|
|
9
|
+
background="#0E0E0E",
|
|
10
|
+
success="#9FD356",
|
|
11
|
+
warning="#FFB000",
|
|
12
|
+
error="#FF3B30",
|
|
13
|
+
surface="#161616",
|
|
14
|
+
panel="#1F1F1F",
|
|
15
|
+
dark=True,
|
|
16
|
+
variables={
|
|
17
|
+
"footer-key-foreground": "#ffb000",
|
|
18
|
+
"input-selection-background": "#ffb000 25%",
|
|
19
|
+
"block-cursor-text-style": "none",
|
|
20
|
+
},
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
blueprint = Theme(
|
|
24
|
+
name="blueprint",
|
|
25
|
+
primary="#4FC3F7",
|
|
26
|
+
secondary="#0288D1",
|
|
27
|
+
accent="#81D4FA",
|
|
28
|
+
foreground="#E1F5FE",
|
|
29
|
+
background="#0A192F",
|
|
30
|
+
success="#4CAF50",
|
|
31
|
+
warning="#FFC107",
|
|
32
|
+
error="#F44336",
|
|
33
|
+
surface="#102A43",
|
|
34
|
+
panel="#163A5F",
|
|
35
|
+
dark=True,
|
|
36
|
+
variables={
|
|
37
|
+
"footer-key-foreground": "#4fc3f7",
|
|
38
|
+
"input-selection-background": "#0288d1 35%",
|
|
39
|
+
"block-cursor-text-style": "none",
|
|
40
|
+
},
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
paper_ledger = Theme(
|
|
44
|
+
name="paper-ledger",
|
|
45
|
+
primary="#2C3E50",
|
|
46
|
+
secondary="#5D6D7E",
|
|
47
|
+
accent="#1F618D",
|
|
48
|
+
foreground="#1C1C1C",
|
|
49
|
+
background="#FAFAF7",
|
|
50
|
+
success="#2E7D32",
|
|
51
|
+
warning="#F9A825",
|
|
52
|
+
error="#C62828",
|
|
53
|
+
surface="#F0F0EB",
|
|
54
|
+
panel="#E6E6E0",
|
|
55
|
+
dark=False,
|
|
56
|
+
variables={
|
|
57
|
+
"footer-key-foreground": "#2c3e50",
|
|
58
|
+
"input-selection-background": "#1f618d 25%",
|
|
59
|
+
"block-cursor-text-style": "none",
|
|
60
|
+
},
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
neo_matrix = Theme(
|
|
64
|
+
name="neo-matrix",
|
|
65
|
+
primary="#37FF14DC",
|
|
66
|
+
secondary="#0F7B0F",
|
|
67
|
+
accent="#ABFCAB",
|
|
68
|
+
foreground="#B6FFB6",
|
|
69
|
+
background="#000B00",
|
|
70
|
+
success="#00FF66",
|
|
71
|
+
warning="#FFB000",
|
|
72
|
+
error="#FF3B30",
|
|
73
|
+
surface="#000B00",
|
|
74
|
+
panel="#000B00",
|
|
75
|
+
dark=True,
|
|
76
|
+
variables={
|
|
77
|
+
"footer-key-foreground": "#39ff14",
|
|
78
|
+
"input-selection-background": "#39ff14 25%",
|
|
79
|
+
"block-cursor-text-style": "none",
|
|
80
|
+
},
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
slate_copper = Theme(
|
|
84
|
+
name="slate-copper",
|
|
85
|
+
primary="#C97C5D",
|
|
86
|
+
secondary="#8C5A3C",
|
|
87
|
+
# accent="#E3A587",
|
|
88
|
+
accent="#DFB6A2",
|
|
89
|
+
foreground="#EDE7E3",
|
|
90
|
+
background="#2B2B2B",
|
|
91
|
+
success="#8BC34A",
|
|
92
|
+
warning="#FFB74D",
|
|
93
|
+
error="#E57373",
|
|
94
|
+
surface="#353535",
|
|
95
|
+
panel="#404040",
|
|
96
|
+
dark=True,
|
|
97
|
+
variables={
|
|
98
|
+
"footer-key-foreground": "#c97c5d",
|
|
99
|
+
"input-selection-background": "#c97c5d 30%",
|
|
100
|
+
"block-cursor-text-style": "none",
|
|
101
|
+
},
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
burgundy = Theme(
|
|
105
|
+
name="ron-burgundy",
|
|
106
|
+
primary="#7A1E2B", # deep burgundy
|
|
107
|
+
secondary="#A63A4A", # lighter wine
|
|
108
|
+
accent="#C94C5C", # rose accent
|
|
109
|
+
foreground="#E6DCDC", # warm off-white
|
|
110
|
+
background="#121012", # near-black, warm
|
|
111
|
+
success="#4FAF8F", # muted teal-green (contrasts burgundy well)
|
|
112
|
+
warning="#D4A017", # antique gold
|
|
113
|
+
error="#C83A3A", # restrained red
|
|
114
|
+
surface="#1C171A", # panels / cards
|
|
115
|
+
panel="#241C20", # raised panels
|
|
116
|
+
dark=True,
|
|
117
|
+
variables={
|
|
118
|
+
"footer-key-foreground": "#C94C5C",
|
|
119
|
+
"input-selection-background": "#7A1E2B 40%",
|
|
120
|
+
"block-cursor-text-style": "none",
|
|
121
|
+
},
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
zapp_brannigan = Theme(
|
|
125
|
+
name="zapp-brannigan",
|
|
126
|
+
primary="#b69003",
|
|
127
|
+
secondary="#1F6F78",
|
|
128
|
+
warning="#E5533D",
|
|
129
|
+
error="#B11226",
|
|
130
|
+
success="#4CAF73",
|
|
131
|
+
accent="#800e13",
|
|
132
|
+
foreground="#ECE8E1",
|
|
133
|
+
background="#0E1418",
|
|
134
|
+
surface="#172026",
|
|
135
|
+
panel="#1E2A32",
|
|
136
|
+
dark=True,
|
|
137
|
+
variables={
|
|
138
|
+
"block-cursor-text-style": "none",
|
|
139
|
+
"footer-key-foreground": "#C9A23F",
|
|
140
|
+
},
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
black_and_white = Theme(
|
|
145
|
+
name="black_and_white",
|
|
146
|
+
primary="#FFFFFF",
|
|
147
|
+
secondary="#C7C5C5",
|
|
148
|
+
warning="#E5533D",
|
|
149
|
+
error="#B11226",
|
|
150
|
+
success="#4CAF73",
|
|
151
|
+
accent="#AAAAAA",
|
|
152
|
+
foreground="#ECE8E1",
|
|
153
|
+
background="#000000",
|
|
154
|
+
surface="#292929",
|
|
155
|
+
panel="#000000",
|
|
156
|
+
dark=True,
|
|
157
|
+
variables={
|
|
158
|
+
"block-cursor-text-style": "none",
|
|
159
|
+
"footer-key-foreground": "#FFFFFF",
|
|
160
|
+
},
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
nashua_kyle = Theme(
|
|
165
|
+
name="nashua-kyle",
|
|
166
|
+
primary="#A3B18A",
|
|
167
|
+
secondary="#606c38",
|
|
168
|
+
warning="#ca6c00",
|
|
169
|
+
error="#c1121f",
|
|
170
|
+
success="#405824",
|
|
171
|
+
accent="#bc6c25",
|
|
172
|
+
foreground="#1e2211",
|
|
173
|
+
background="#EDE0D4",
|
|
174
|
+
surface="#a28c73",
|
|
175
|
+
panel="#c6ac8f",
|
|
176
|
+
dark=False,
|
|
177
|
+
variables={
|
|
178
|
+
"block-cursor-text-style": "none",
|
|
179
|
+
"footer-key-foreground": "#606c38",
|
|
180
|
+
"footer-description-foreground": "#EDE0D4",
|
|
181
|
+
},
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
hey_noodle = Theme(
|
|
186
|
+
name="hey-noodle",
|
|
187
|
+
primary="#748cab",
|
|
188
|
+
secondary="#1d2d44",
|
|
189
|
+
warning="#ca6c00",
|
|
190
|
+
error="#c1121f",
|
|
191
|
+
success="#679436",
|
|
192
|
+
accent="#959b9d",
|
|
193
|
+
foreground="#1d2d44",
|
|
194
|
+
background="#dbe9ee",
|
|
195
|
+
surface="#accbe1",
|
|
196
|
+
panel="#edede9",
|
|
197
|
+
dark=False,
|
|
198
|
+
variables={
|
|
199
|
+
"block-cursor-text-style": "none",
|
|
200
|
+
"footer-key-foreground": "#1d2d44",
|
|
201
|
+
"footer-description-foreground": "#1d2d44",
|
|
202
|
+
},
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
dusty_dawn = Theme(
|
|
207
|
+
name="dusty-dawn",
|
|
208
|
+
primary="#49111C",
|
|
209
|
+
secondary="#2C0B11",
|
|
210
|
+
warning="#b25f00",
|
|
211
|
+
error="#a8000b",
|
|
212
|
+
success="#53772C",
|
|
213
|
+
accent="#5E503F",
|
|
214
|
+
foreground="#F3E9EB",
|
|
215
|
+
background="#A9927D",
|
|
216
|
+
surface="#998163",
|
|
217
|
+
panel="#816D55",
|
|
218
|
+
dark=False,
|
|
219
|
+
variables={
|
|
220
|
+
"block-cursor-text-style": "none",
|
|
221
|
+
"footer-key-foreground": "#49111C",
|
|
222
|
+
},
|
|
223
|
+
)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
ALL_THEMES: list[Theme] = [
|
|
227
|
+
industrial_amber,
|
|
228
|
+
blueprint,
|
|
229
|
+
paper_ledger,
|
|
230
|
+
neo_matrix,
|
|
231
|
+
slate_copper,
|
|
232
|
+
burgundy,
|
|
233
|
+
black_and_white,
|
|
234
|
+
nashua_kyle,
|
|
235
|
+
zapp_brannigan,
|
|
236
|
+
hey_noodle,
|
|
237
|
+
dusty_dawn,
|
|
238
|
+
]
|
ferp/widgets/__init__.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from .dialogs import ConfirmDialog
|
|
2
|
+
from .file_tree import FileItem, FileListingEntry, FileTree, FileTreeFilterWidget
|
|
3
|
+
from .output_panel import ScriptOutputPanel
|
|
4
|
+
from .panels import ContentPanel
|
|
5
|
+
from .scripts import ScriptItem, ScriptManager
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"FileTree",
|
|
9
|
+
"FileListingEntry",
|
|
10
|
+
"FileItem",
|
|
11
|
+
"FileTreeFilterWidget",
|
|
12
|
+
"ScriptManager",
|
|
13
|
+
"ScriptItem",
|
|
14
|
+
"ContentPanel",
|
|
15
|
+
"ScriptOutputPanel",
|
|
16
|
+
"ConfirmDialog",
|
|
17
|
+
]
|
ferp/widgets/dialogs.py
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
from rich.style import Style
|
|
2
|
+
from rich.text import Text
|
|
3
|
+
from textual.containers import Container, Horizontal, Vertical
|
|
4
|
+
from textual.screen import ModalScreen
|
|
5
|
+
from textual.widgets import Button, DataTable, Input, Label, Select
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ConfirmDialog(ModalScreen[bool | None]):
|
|
9
|
+
def __init__(self, message: str, id="confirm_dialog"):
|
|
10
|
+
super().__init__(id=id)
|
|
11
|
+
self.message = message
|
|
12
|
+
|
|
13
|
+
def compose(self):
|
|
14
|
+
yield Container(
|
|
15
|
+
Label(self.message, id="dialog_message"),
|
|
16
|
+
Horizontal(
|
|
17
|
+
Button("Yes", id="yes", variant="primary", flat=True),
|
|
18
|
+
Button("No", id="cancel", flat=True),
|
|
19
|
+
classes="dialog_buttons",
|
|
20
|
+
),
|
|
21
|
+
id="dialog_container",
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
def on_button_pressed(self, event):
|
|
25
|
+
if event.button.id == "cancel":
|
|
26
|
+
self.dismiss(False)
|
|
27
|
+
return
|
|
28
|
+
self.dismiss(event.button.id == "yes")
|
|
29
|
+
|
|
30
|
+
def on_screen_resume(self) -> None:
|
|
31
|
+
if getattr(self, "_dismiss_on_resume", False):
|
|
32
|
+
self.dismiss(None)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class BulkRenameConfirmDialog(ModalScreen[bool | None]):
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
title: str,
|
|
39
|
+
rows: list[tuple[str, str]],
|
|
40
|
+
more_count: int = 0,
|
|
41
|
+
) -> None:
|
|
42
|
+
super().__init__(id="bulk_rename_confirm_dialog")
|
|
43
|
+
self.dialog_title: str = title or ""
|
|
44
|
+
self.rows: list[tuple[str, str]] = rows
|
|
45
|
+
self.more_count = more_count
|
|
46
|
+
|
|
47
|
+
def compose(self):
|
|
48
|
+
table = DataTable(
|
|
49
|
+
id="bulk_rename_preview_table", show_cursor=False, disabled=True
|
|
50
|
+
)
|
|
51
|
+
table.add_column("From", width=75)
|
|
52
|
+
table.add_column("To", width=75)
|
|
53
|
+
if self.rows:
|
|
54
|
+
success_color = self.app.theme_variables["success"]
|
|
55
|
+
error_color = self.app.theme_variables["error"]
|
|
56
|
+
styled_rows = [
|
|
57
|
+
(
|
|
58
|
+
Text(src, style=Style(color=error_color)),
|
|
59
|
+
Text(dest, style=Style(color=success_color)),
|
|
60
|
+
)
|
|
61
|
+
for src, dest in self.rows
|
|
62
|
+
]
|
|
63
|
+
table.add_rows(styled_rows)
|
|
64
|
+
yield Container(
|
|
65
|
+
Label(self.dialog_title, id="bulk_rename_dialog_title"),
|
|
66
|
+
table,
|
|
67
|
+
Label(
|
|
68
|
+
f"... and {self.more_count} more.",
|
|
69
|
+
id="bulk_rename_dialog_message",
|
|
70
|
+
classes="" if self.more_count else "hidden",
|
|
71
|
+
),
|
|
72
|
+
Horizontal(
|
|
73
|
+
Button("Yes", id="bulk_rename_yes", variant="primary", flat=True),
|
|
74
|
+
Button("No", id="bulk_rename_cancel", flat=True),
|
|
75
|
+
classes="dialog_buttons",
|
|
76
|
+
),
|
|
77
|
+
id="bulk_rename_dialog_container",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
def on_button_pressed(self, event):
|
|
81
|
+
if event.button.id == "bulk_rename_cancel":
|
|
82
|
+
self.dismiss(False)
|
|
83
|
+
return
|
|
84
|
+
self.dismiss(event.button.id == "bulk_rename_yes")
|
|
85
|
+
|
|
86
|
+
def on_screen_resume(self) -> None:
|
|
87
|
+
if getattr(self, "_dismiss_on_resume", False):
|
|
88
|
+
self.dismiss(None)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class InputDialog(ModalScreen[str | None]):
|
|
92
|
+
def __init__(
|
|
93
|
+
self, message: str, id: str = "input_dialog", default: str | None = None
|
|
94
|
+
) -> None:
|
|
95
|
+
super().__init__(id=id)
|
|
96
|
+
self._message = message
|
|
97
|
+
self._default = default
|
|
98
|
+
|
|
99
|
+
def compose(self):
|
|
100
|
+
yield Vertical(
|
|
101
|
+
Label(self._message, id="dialog_message"),
|
|
102
|
+
Container(
|
|
103
|
+
Input(value=self._default or "", id="input"),
|
|
104
|
+
id="input_container",
|
|
105
|
+
),
|
|
106
|
+
Horizontal(
|
|
107
|
+
Button("OK", id="ok", variant="primary", flat=True),
|
|
108
|
+
Button("Cancel", id="cancel", flat=True),
|
|
109
|
+
classes="dialog_buttons",
|
|
110
|
+
),
|
|
111
|
+
id="dialog_container",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
def on_mount(self) -> None:
|
|
115
|
+
self.query_one(Input).focus()
|
|
116
|
+
|
|
117
|
+
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
118
|
+
if event.button.id == "ok":
|
|
119
|
+
value = self.query_one(Input).value
|
|
120
|
+
self.dismiss(value)
|
|
121
|
+
else:
|
|
122
|
+
self.dismiss(None)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class SelectDialog(ModalScreen[str | None]):
|
|
126
|
+
def __init__(
|
|
127
|
+
self,
|
|
128
|
+
message: str,
|
|
129
|
+
options: list[str],
|
|
130
|
+
*,
|
|
131
|
+
id: str = "select_dialog",
|
|
132
|
+
) -> None:
|
|
133
|
+
super().__init__(id=id)
|
|
134
|
+
self._message = message
|
|
135
|
+
self._options = options
|
|
136
|
+
|
|
137
|
+
def compose(self):
|
|
138
|
+
select_options = [(option, option) for option in self._options]
|
|
139
|
+
default = self._options[0] if self._options else ""
|
|
140
|
+
yield Vertical(
|
|
141
|
+
Label(self._message, id="dialog_message"),
|
|
142
|
+
Container(
|
|
143
|
+
Select(
|
|
144
|
+
select_options,
|
|
145
|
+
value=default,
|
|
146
|
+
allow_blank=False,
|
|
147
|
+
id="select",
|
|
148
|
+
),
|
|
149
|
+
id="select_container",
|
|
150
|
+
),
|
|
151
|
+
Horizontal(
|
|
152
|
+
Button("OK", id="ok", variant="primary", flat=True),
|
|
153
|
+
Button("Cancel", id="cancel", flat=True),
|
|
154
|
+
classes="dialog_buttons",
|
|
155
|
+
),
|
|
156
|
+
id="dialog_container",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
def on_mount(self) -> None:
|
|
160
|
+
self.query_one(Select).focus()
|
|
161
|
+
|
|
162
|
+
def on_button_pressed(self, event: Button.Pressed) -> None:
|
|
163
|
+
if event.button.id == "ok":
|
|
164
|
+
value = self.query_one(Select).value
|
|
165
|
+
self.dismiss(str(value) if value is not None else None)
|
|
166
|
+
else:
|
|
167
|
+
self.dismiss(None)
|