Dashify 0.1.0__tar.gz

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.
dashify-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Icecreambobcat
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
dashify-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,251 @@
1
+ Metadata-Version: 2.4
2
+ Name: Dashify
3
+ Version: 0.1.0
4
+ Summary: A configurable terminal dashboard built with Textual.
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Keywords: dashboard,terminal,textual,tui
8
+ Author: Icecreambobcat
9
+ Author-email: icekingrex123@gmail.com
10
+ Requires-Python: >=3.14,<3.16
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Operating System :: OS Independent
14
+ Classifier: Topic :: Utilities
15
+ Requires-Dist: psutil (>=7.2.2,<8.0.0)
16
+ Requires-Dist: pydantic (>=2.13.4,<3.0.0)
17
+ Requires-Dist: textual (>=7.5.0,<8.0.0)
18
+ Requires-Dist: tomlkit (>=0.15.0,<0.16.0)
19
+ Project-URL: Issues, https://github.com/Icecreambobcat/dashify/issues
20
+ Project-URL: Repository, https://github.com/Icecreambobcat/dashify
21
+ Description-Content-Type: text/markdown
22
+
23
+ # Dashify
24
+
25
+ Dashify is a configurable terminal dashboard built with
26
+ [Textual](https://textual.textualize.io/). It arranges clocks, timers, todos,
27
+ weather, and system information into nested horizontal and vertical tiles.
28
+
29
+ ## Requirements
30
+
31
+ - Python 3.14 or 3.15
32
+ - A terminal with mouse support and Unicode glyphs
33
+ - Internet access for the Weather widget
34
+
35
+ ## Installation
36
+
37
+ Install [uv](https://docs.astral.sh/uv/getting-started/installation/), then
38
+ install Dashify as an isolated command-line tool. uv will obtain a compatible
39
+ Python interpreter when one is not already available:
40
+
41
+ ```console
42
+ uv tool install --python 3.14 dashify
43
+ dashify
44
+ ```
45
+
46
+ If `dashify` is not found after installation, add uv's executable directory to
47
+ your shell path and restart the shell:
48
+
49
+ ```console
50
+ uv tool update-shell
51
+ ```
52
+
53
+ To install directly from a source checkout instead:
54
+
55
+ ```console
56
+ git clone https://github.com/Icecreambobcat/dashify.git
57
+ cd dashify
58
+ uv tool install --python 3.14 .
59
+ ```
60
+
61
+ Upgrade or remove Dashify with:
62
+
63
+ ```console
64
+ uv tool upgrade dashify
65
+ uv tool uninstall dashify
66
+ ```
67
+
68
+ Dashify loads `~/.config/dashify/dashify.toml` when that file exists. Otherwise,
69
+ it uses its packaged default configuration. From a source checkout, copy the
70
+ documented default before customising your dashboard:
71
+
72
+ ```console
73
+ mkdir -p ~/.config/dashify
74
+ cp defaults/dashify.toml ~/.config/dashify/dashify.toml
75
+ ```
76
+
77
+ Users who installed from PyPI can download the same versioned default:
78
+
79
+ ```console
80
+ mkdir -p ~/.config/dashify
81
+ curl -L https://raw.githubusercontent.com/Icecreambobcat/dashify/v0.1.0/defaults/dashify.toml \
82
+ -o ~/.config/dashify/dashify.toml
83
+ ```
84
+
85
+ Press <kbd>Ctrl</kbd>+<kbd>Q</kbd> to quit.
86
+
87
+ ## Configuration
88
+
89
+ The dashboard is a tree rooted at the `[widgets]` table. Every widget table
90
+ requires a `kind`. `HBox` divides its space equally from left to right, while
91
+ `VBox` divides its space equally from top to bottom. Any other nested table name
92
+ is simply a readable identifier for a child.
93
+
94
+ ```toml
95
+ [widgets]
96
+ kind = "HBox"
97
+
98
+ [widgets.left]
99
+ kind = "VBox"
100
+
101
+ [widgets.left.clock]
102
+ kind = "Clock"
103
+ opts = { timezone = "Australia/Sydney" }
104
+
105
+ [widgets.left.timer]
106
+ kind = "Timer"
107
+
108
+ [widgets.right]
109
+ kind = "VBox"
110
+
111
+ [widgets.right.weather]
112
+ kind = "Weather"
113
+ opts = { location = "Melbourne", units = "metric", refresh_minutes = 15 }
114
+
115
+ [widgets.right.todos]
116
+ kind = "Todo"
117
+ ```
118
+
119
+ Only `HBox` and `VBox` treat named nested tables as children. Child tables on
120
+ ordinary widgets are ignored. The optional `opts` value must be a TOML table;
121
+ inline tables are preferred because they visually distinguish widget options
122
+ from layout children.
123
+
124
+ Malformed roots produce a centred warning screen. An invalid child or invalid
125
+ `opts` value produces a warning in that child's tile so that the rest of the
126
+ dashboard remains usable.
127
+
128
+ The widget snippets below are child tables intended to be added beneath an
129
+ `HBox` or `VBox` root such as the one in the complete example above.
130
+
131
+ ## Built-in widgets
132
+
133
+ ### Clock
134
+
135
+ `Clock` displays a 24-hour clock. It uses the local timezone by default.
136
+ `timezone` accepts `local`, `UTC`, a UTC offset, or an IANA timezone name.
137
+
138
+ ```toml
139
+ [widgets.clock]
140
+ kind = "Clock"
141
+ opts = { timezone = "Europe/London" }
142
+ ```
143
+
144
+ ### Timer
145
+
146
+ `Timer` is a countdown with one Start/Stop/Reset button. While stopped, click
147
+ the digits, enter up to six digits in `HHMMSS` order, and press Enter. Input is
148
+ right-aligned, so `130` becomes `00:01:30`. Invalid minutes and seconds are
149
+ rejected. The border flashes yellow when the countdown finishes.
150
+
151
+ ```toml
152
+ [widgets.timer]
153
+ kind = "Timer"
154
+ ```
155
+
156
+ ### Stopwatch
157
+
158
+ `Stopwatch` provides Start, Stop, and Reset controls. Reset remains visible but
159
+ is disabled while the stopwatch is running.
160
+
161
+ ```toml
162
+ [widgets.stopwatch]
163
+ kind = "Stopwatch"
164
+ ```
165
+
166
+ ### System monitor
167
+
168
+ `SystemMonitor` samples total CPU utilisation once per second. Its 38-sample
169
+ history graph uses green, yellow, and red threshold colours.
170
+
171
+ ```toml
172
+ [widgets.system_monitor]
173
+ kind = "SystemMonitor"
174
+ ```
175
+
176
+ ### Weather
177
+
178
+ `Weather` uses Open-Meteo to display current conditions. No API key is needed.
179
+ The default location is Sydney, units are metric, and the refresh interval is
180
+ 15 minutes. `units` accepts `metric` or `imperial`; the Refresh button requests
181
+ an immediate update.
182
+
183
+ ```toml
184
+ [widgets.weather]
185
+ kind = "Weather"
186
+ opts = { location = "Perth", units = "metric", refresh_minutes = 10 }
187
+ ```
188
+
189
+ The configured location is sent to Open-Meteo's geocoding and forecast APIs.
190
+ Network and response errors are shown inside the widget without stopping the
191
+ dashboard.
192
+
193
+ ### Todo
194
+
195
+ `Todo` stores a title, optional notes, and an optional ISO-format due date in a
196
+ local SQLite database at `~/.local/state/dashify/todo.db`. Todos remain in
197
+ insertion order.
198
+
199
+ Select **Manage todos** to enter the widget's interaction context. Menus support
200
+ the arrow keys and these Vim-inspired bindings:
201
+
202
+ - `j` / `k`: move down / up
203
+ - `g` / `G`: move to the first / last option
204
+ - `l` or `Enter`: select
205
+ - `Esc`: go back
206
+
207
+ Dashify asks before creating the database. Todo deletion and database deletion
208
+ are permanent; deleting the database requires a separate warning screen.
209
+
210
+ ```toml
211
+ [widgets.todos]
212
+ kind = "Todo"
213
+ ```
214
+
215
+ ### Custom
216
+
217
+ `Custom` is a single-layer vertical arrangement. Its Boolean switches enable
218
+ available elements in a fixed order; `text` adds a short heading and `timezone`
219
+ configures an enabled clock. Each enabled widget otherwise retains its built-in
220
+ defaults.
221
+
222
+ ```toml
223
+ [widgets.focus]
224
+ kind = "Custom"
225
+ opts = { text = "Focus", clock = true, timezone = "UTC", timer = true, weather = true }
226
+ ```
227
+
228
+ Available switches are `clock`, `timer`, `stopwatch`, `system_monitor`, `todo`,
229
+ and `weather`. Horizontal custom layouts are intentionally unsupported; use an
230
+ `HBox` in the main widget tree instead.
231
+
232
+ ## Development
233
+
234
+ Install the development dependencies and run all release checks with:
235
+
236
+ ```console
237
+ poetry install
238
+ poetry run black --check src tests
239
+ poetry run pyright
240
+ poetry run pytest
241
+ poetry check
242
+ poetry build
243
+ ```
244
+
245
+ Source files live in `src`, tests in `tests`, and the documented default layout
246
+ in `defaults/dashify.toml`.
247
+
248
+ ## Licence
249
+
250
+ Dashify is released under the MIT Licence. See `LICENSE`.
251
+
@@ -0,0 +1,228 @@
1
+ # Dashify
2
+
3
+ Dashify is a configurable terminal dashboard built with
4
+ [Textual](https://textual.textualize.io/). It arranges clocks, timers, todos,
5
+ weather, and system information into nested horizontal and vertical tiles.
6
+
7
+ ## Requirements
8
+
9
+ - Python 3.14 or 3.15
10
+ - A terminal with mouse support and Unicode glyphs
11
+ - Internet access for the Weather widget
12
+
13
+ ## Installation
14
+
15
+ Install [uv](https://docs.astral.sh/uv/getting-started/installation/), then
16
+ install Dashify as an isolated command-line tool. uv will obtain a compatible
17
+ Python interpreter when one is not already available:
18
+
19
+ ```console
20
+ uv tool install --python 3.14 dashify
21
+ dashify
22
+ ```
23
+
24
+ If `dashify` is not found after installation, add uv's executable directory to
25
+ your shell path and restart the shell:
26
+
27
+ ```console
28
+ uv tool update-shell
29
+ ```
30
+
31
+ To install directly from a source checkout instead:
32
+
33
+ ```console
34
+ git clone https://github.com/Icecreambobcat/dashify.git
35
+ cd dashify
36
+ uv tool install --python 3.14 .
37
+ ```
38
+
39
+ Upgrade or remove Dashify with:
40
+
41
+ ```console
42
+ uv tool upgrade dashify
43
+ uv tool uninstall dashify
44
+ ```
45
+
46
+ Dashify loads `~/.config/dashify/dashify.toml` when that file exists. Otherwise,
47
+ it uses its packaged default configuration. From a source checkout, copy the
48
+ documented default before customising your dashboard:
49
+
50
+ ```console
51
+ mkdir -p ~/.config/dashify
52
+ cp defaults/dashify.toml ~/.config/dashify/dashify.toml
53
+ ```
54
+
55
+ Users who installed from PyPI can download the same versioned default:
56
+
57
+ ```console
58
+ mkdir -p ~/.config/dashify
59
+ curl -L https://raw.githubusercontent.com/Icecreambobcat/dashify/v0.1.0/defaults/dashify.toml \
60
+ -o ~/.config/dashify/dashify.toml
61
+ ```
62
+
63
+ Press <kbd>Ctrl</kbd>+<kbd>Q</kbd> to quit.
64
+
65
+ ## Configuration
66
+
67
+ The dashboard is a tree rooted at the `[widgets]` table. Every widget table
68
+ requires a `kind`. `HBox` divides its space equally from left to right, while
69
+ `VBox` divides its space equally from top to bottom. Any other nested table name
70
+ is simply a readable identifier for a child.
71
+
72
+ ```toml
73
+ [widgets]
74
+ kind = "HBox"
75
+
76
+ [widgets.left]
77
+ kind = "VBox"
78
+
79
+ [widgets.left.clock]
80
+ kind = "Clock"
81
+ opts = { timezone = "Australia/Sydney" }
82
+
83
+ [widgets.left.timer]
84
+ kind = "Timer"
85
+
86
+ [widgets.right]
87
+ kind = "VBox"
88
+
89
+ [widgets.right.weather]
90
+ kind = "Weather"
91
+ opts = { location = "Melbourne", units = "metric", refresh_minutes = 15 }
92
+
93
+ [widgets.right.todos]
94
+ kind = "Todo"
95
+ ```
96
+
97
+ Only `HBox` and `VBox` treat named nested tables as children. Child tables on
98
+ ordinary widgets are ignored. The optional `opts` value must be a TOML table;
99
+ inline tables are preferred because they visually distinguish widget options
100
+ from layout children.
101
+
102
+ Malformed roots produce a centred warning screen. An invalid child or invalid
103
+ `opts` value produces a warning in that child's tile so that the rest of the
104
+ dashboard remains usable.
105
+
106
+ The widget snippets below are child tables intended to be added beneath an
107
+ `HBox` or `VBox` root such as the one in the complete example above.
108
+
109
+ ## Built-in widgets
110
+
111
+ ### Clock
112
+
113
+ `Clock` displays a 24-hour clock. It uses the local timezone by default.
114
+ `timezone` accepts `local`, `UTC`, a UTC offset, or an IANA timezone name.
115
+
116
+ ```toml
117
+ [widgets.clock]
118
+ kind = "Clock"
119
+ opts = { timezone = "Europe/London" }
120
+ ```
121
+
122
+ ### Timer
123
+
124
+ `Timer` is a countdown with one Start/Stop/Reset button. While stopped, click
125
+ the digits, enter up to six digits in `HHMMSS` order, and press Enter. Input is
126
+ right-aligned, so `130` becomes `00:01:30`. Invalid minutes and seconds are
127
+ rejected. The border flashes yellow when the countdown finishes.
128
+
129
+ ```toml
130
+ [widgets.timer]
131
+ kind = "Timer"
132
+ ```
133
+
134
+ ### Stopwatch
135
+
136
+ `Stopwatch` provides Start, Stop, and Reset controls. Reset remains visible but
137
+ is disabled while the stopwatch is running.
138
+
139
+ ```toml
140
+ [widgets.stopwatch]
141
+ kind = "Stopwatch"
142
+ ```
143
+
144
+ ### System monitor
145
+
146
+ `SystemMonitor` samples total CPU utilisation once per second. Its 38-sample
147
+ history graph uses green, yellow, and red threshold colours.
148
+
149
+ ```toml
150
+ [widgets.system_monitor]
151
+ kind = "SystemMonitor"
152
+ ```
153
+
154
+ ### Weather
155
+
156
+ `Weather` uses Open-Meteo to display current conditions. No API key is needed.
157
+ The default location is Sydney, units are metric, and the refresh interval is
158
+ 15 minutes. `units` accepts `metric` or `imperial`; the Refresh button requests
159
+ an immediate update.
160
+
161
+ ```toml
162
+ [widgets.weather]
163
+ kind = "Weather"
164
+ opts = { location = "Perth", units = "metric", refresh_minutes = 10 }
165
+ ```
166
+
167
+ The configured location is sent to Open-Meteo's geocoding and forecast APIs.
168
+ Network and response errors are shown inside the widget without stopping the
169
+ dashboard.
170
+
171
+ ### Todo
172
+
173
+ `Todo` stores a title, optional notes, and an optional ISO-format due date in a
174
+ local SQLite database at `~/.local/state/dashify/todo.db`. Todos remain in
175
+ insertion order.
176
+
177
+ Select **Manage todos** to enter the widget's interaction context. Menus support
178
+ the arrow keys and these Vim-inspired bindings:
179
+
180
+ - `j` / `k`: move down / up
181
+ - `g` / `G`: move to the first / last option
182
+ - `l` or `Enter`: select
183
+ - `Esc`: go back
184
+
185
+ Dashify asks before creating the database. Todo deletion and database deletion
186
+ are permanent; deleting the database requires a separate warning screen.
187
+
188
+ ```toml
189
+ [widgets.todos]
190
+ kind = "Todo"
191
+ ```
192
+
193
+ ### Custom
194
+
195
+ `Custom` is a single-layer vertical arrangement. Its Boolean switches enable
196
+ available elements in a fixed order; `text` adds a short heading and `timezone`
197
+ configures an enabled clock. Each enabled widget otherwise retains its built-in
198
+ defaults.
199
+
200
+ ```toml
201
+ [widgets.focus]
202
+ kind = "Custom"
203
+ opts = { text = "Focus", clock = true, timezone = "UTC", timer = true, weather = true }
204
+ ```
205
+
206
+ Available switches are `clock`, `timer`, `stopwatch`, `system_monitor`, `todo`,
207
+ and `weather`. Horizontal custom layouts are intentionally unsupported; use an
208
+ `HBox` in the main widget tree instead.
209
+
210
+ ## Development
211
+
212
+ Install the development dependencies and run all release checks with:
213
+
214
+ ```console
215
+ poetry install
216
+ poetry run black --check src tests
217
+ poetry run pyright
218
+ poetry run pytest
219
+ poetry check
220
+ poetry build
221
+ ```
222
+
223
+ Source files live in `src`, tests in `tests`, and the documented default layout
224
+ in `defaults/dashify.toml`.
225
+
226
+ ## Licence
227
+
228
+ Dashify is released under the MIT Licence. See `LICENSE`.
@@ -0,0 +1,55 @@
1
+ # The root layout has a timer and todos on the left. The right column nests a
2
+ # clock and system monitor beside a stopwatch, above the weather widget.
3
+ [widgets]
4
+ kind = "Hbox"
5
+
6
+ [widgets.left]
7
+ kind = "Vbox"
8
+
9
+ [widgets.right]
10
+ kind = "Vbox"
11
+
12
+ # A countdown timer. Click the digits while stopped, enter up to six digits in
13
+ # HHMMSS order, then press Enter to confirm the duration.
14
+ [widgets.left.timer]
15
+ kind = "Timer"
16
+
17
+ # Persistent local todos. Select Manage todos in the widget to create and use
18
+ # the SQLite database at ~/.local/state/dashify/todo.db.
19
+ [widgets.left.todo]
20
+ kind = "Todo"
21
+
22
+ # A vertical custom arrangement. Widget defaults remain in the app; uncomment
23
+ # switches and text below to enable them in this one-layer custom widget.
24
+ # [widgets.left.custom]
25
+ # kind = "Custom"
26
+ # opts = { text = "Focus time", clock = true, timezone = "Australia/Sydney", timer = true, stopwatch = true, system_monitor = true, todo = true, weather = true }
27
+
28
+ # The right column's top tile places the clock and system monitor in one
29
+ # vertical tile beside the stopwatch.
30
+ [widgets.right.top]
31
+ kind = "Hbox"
32
+
33
+ # Widget defaults are supplied by the app. Uncomment opts below to override the
34
+ # Clock's local timezone with "UTC", a UTC offset, or an IANA timezone name.
35
+ [widgets.right.top.status]
36
+ kind = "Vbox"
37
+
38
+ [widgets.right.top.status.clock]
39
+ kind = "Clock"
40
+ # opts = { timezone = "UTC+0" }
41
+
42
+ # A live CPU utilisation monitor. The graph retains the latest 38 samples,
43
+ # updates once per second, and marks low, medium, and high load in green,
44
+ # yellow, and red respectively.
45
+ [widgets.right.top.status.system_monitor]
46
+ kind = "SystemMonitor"
47
+
48
+ # A stopwatch with Start, Stop, and Reset controls. It has no options yet.
49
+ [widgets.right.top.stopwatch]
50
+ kind = "Stopwatch"
51
+
52
+ # Current weather for the app-supplied default location. Use inline opts to
53
+ # override location, units (metric or imperial), or refresh_minutes.
54
+ [widgets.right.weather]
55
+ kind = "Weather"
@@ -0,0 +1,54 @@
1
+ [project]
2
+ name = "Dashify"
3
+ description = "A configurable terminal dashboard built with Textual."
4
+ version = "0.1.0"
5
+ authors = [
6
+ {name = "Icecreambobcat",email = "icekingrex123@gmail.com"}
7
+ ]
8
+ license = "MIT"
9
+ readme = "README.md"
10
+ requires-python = ">=3.14,<3.16"
11
+ keywords = ["dashboard", "terminal", "textual", "tui"]
12
+ classifiers = [
13
+ "Development Status :: 3 - Alpha",
14
+ "Environment :: Console",
15
+ "Operating System :: OS Independent",
16
+ "Topic :: Utilities",
17
+ ]
18
+ dependencies = [
19
+ "textual (>=7.5.0,<8.0.0)",
20
+ "tomlkit (>=0.15.0,<0.16.0)",
21
+ "pydantic (>=2.13.4,<3.0.0)",
22
+ "psutil (>=7.2.2,<8.0.0)"
23
+ ]
24
+
25
+ [project.urls]
26
+ Repository = "https://github.com/Icecreambobcat/dashify"
27
+ Issues = "https://github.com/Icecreambobcat/dashify/issues"
28
+
29
+ [build-system]
30
+ requires = ["poetry-core>=2.0.0,<3.0.0"]
31
+ build-backend = "poetry.core.masonry.api"
32
+
33
+ [dependency-groups]
34
+ dev = [
35
+ "pytest (>=9.1.1,<10.0.0)",
36
+ "pyinstaller (>=6.22.2,<7.0.0)",
37
+ "pyright (>=1.1.411,<2.0.0)",
38
+ "black (>=26.5.1,<27.0.0)"
39
+ ]
40
+
41
+ [project.scripts]
42
+ dashify = "main:main"
43
+
44
+ [tool.poetry]
45
+ packages = [
46
+ { include = "main.py", from = "src" },
47
+ { include = "modules", from = "src" },
48
+ ]
49
+ include = [
50
+ { path = "defaults/dashify.toml", format = ["sdist", "wheel"] },
51
+ ]
52
+
53
+ [tool.black]
54
+ target-version = ["py314"]
@@ -0,0 +1,13 @@
1
+ import sys
2
+
3
+ from modules.app import Dashify
4
+
5
+
6
+ def main() -> int:
7
+ """Run Dashify and return a process-compatible exit code."""
8
+ exit_code = Dashify().run()
9
+ return int(exit_code) if exit_code is not None else 0
10
+
11
+
12
+ if __name__ == "__main__":
13
+ sys.exit(main())
File without changes
@@ -0,0 +1,47 @@
1
+ from textual.app import App, ComposeResult
2
+ from textual.binding import Binding
3
+ from textual.containers import Container
4
+ from textual.widgets import Footer, Header, Static
5
+
6
+ from modules.composer import compose_from_config
7
+ from modules.conf import make_config
8
+
9
+
10
+ class Dashify(App):
11
+ """Compose and run the configured terminal dashboard."""
12
+
13
+ TITLE = "Dashify"
14
+ BINDINGS = [Binding("ctrl+q", "quit", "Quit", key_display="^q")]
15
+
16
+ DEFAULT_CSS = """
17
+ #config-warning-screen {
18
+ width: 1fr;
19
+ height: 1fr;
20
+ align: center middle;
21
+ }
22
+
23
+ #config-warning {
24
+ width: 50;
25
+ height: 5;
26
+ border: round $warning;
27
+ padding: 1;
28
+ color: $warning;
29
+ content-align: center middle;
30
+ text-align: center;
31
+ }
32
+ """
33
+
34
+ def compose(self) -> ComposeResult:
35
+ """Compose the configured layout or a recoverable warning screen."""
36
+ yield Header()
37
+ config = make_config()
38
+ if config is not None and (layout := compose_from_config(config)) is not None:
39
+ yield layout
40
+ else:
41
+ with Container(id="config-warning-screen"):
42
+ yield Static(
43
+ "Configuration could not be loaded.\n"
44
+ "Check dashify.toml and restart.",
45
+ id="config-warning",
46
+ )
47
+ yield Footer()