Merge pull request #185 from tiqi-group/feat/add_favicon

Feat: add favicon
This commit is contained in:
Mose Müller 2024-11-26 14:40:43 +01:00 committed by GitHub
commit 897387e39e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 55 additions and 2 deletions

View File

@ -219,7 +219,8 @@ For more information, see [Configuring pydase](https://pydase.readthedocs.io/en/
`pydase` allows you to enhance the user experience by customizing the web interface's appearance through
1. a custom CSS file, and
2. tailoring the frontend component layout and display style.
2. a custom favicon image, and
3. tailoring the frontend component layout and display style.
You can also provide a custom frontend source if you need even more flexibility.

View File

@ -21,7 +21,8 @@ The frontend uses a component-based approach, representing various data types an
`pydase` allows you to enhance the user experience by customizing the web interface's appearance through
1. a custom CSS file, and
2. tailoring the frontend component layout and display style.
2. a custom favicon image, and
3. tailoring the frontend component layout and display style.
For more advanced customization, you can provide a completely custom frontend source.
@ -51,6 +52,34 @@ This will apply the styles defined in `custom.css` to the web interface, allowin
Please ensure that the CSS file path is accessible from the server's running location. Relative or absolute paths can be used depending on your setup.
### Custom favicon image
You can customize the favicon displayed in the browser tab by providing your own favicon image file during the server initialization.
Here's how you can use this feature:
1. Prepare your custom favicon image (e.g. a `.png` file).
2. Pass the path to your favicon file as the `favicon_path` argument when initializing the `Server` class.
Heres an example:
```python
import pydase
class MyService(pydase.DataService):
# ... your service definition ...
if __name__ == "__main__":
service = MyService()
pydase.Server(service, favicon_path="./my/local/my-favicon.png").run()
```
This will serve the specified image instead of the default `pydase` logo.
### Tailoring Frontend Component Layout
You can customize the display names, visibility, and order of components via the `web_settings.json` file.

View File

@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site displaying a pydase UI." />

BIN
frontend/public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@ -3,6 +3,7 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site displaying a pydase UI." />

View File

@ -60,6 +60,8 @@ class WebServer:
css:
Path to a custom CSS file for styling the frontend. If None, no custom
styles are applied. Defaults to None.
favicon_path:
Path to a custom favicon.ico file. Defaults to None.
enable_cors:
Flag to enable or disable CORS policy. When True, CORS is enabled, allowing
cross-origin requests. Defaults to True.
@ -78,7 +80,9 @@ class WebServer:
data_service_observer: DataServiceObserver,
host: str,
port: int,
*,
css: str | Path | None = None,
favicon_path: str | Path | None = None,
enable_cors: bool = True,
config_dir: Path = ServiceConfig().config_dir,
generate_web_settings: bool = WebServerConfig().generate_web_settings,
@ -92,6 +96,11 @@ class WebServer:
self.css = css
self.enable_cors = enable_cors
self.frontend_src = frontend_src
self.favicon_path: Path | str = favicon_path # type: ignore
if self.favicon_path is None:
self.favicon_path = self.frontend_src / "favicon.ico"
self._service_config_dir = config_dir
self._generate_web_settings = generate_web_settings
self._loop: asyncio.AbstractEventLoop
@ -136,6 +145,11 @@ class WebServer:
f"{escaped_prefix}/assets/",
)
modified_html = modified_html.replace(
"/favicon.ico",
f"{escaped_prefix}/favicon.ico",
)
return aiohttp.web.Response(
text=modified_html, content_type="text/html"
)
@ -152,6 +166,7 @@ class WebServer:
# Define routes
self._sio.attach(app, socketio_path="/ws/socket.io")
app.router.add_static("/assets", self.frontend_src / "assets")
app.router.add_get("/favicon.ico", self._favicon_route)
app.router.add_get("/service-properties", self._service_properties_route)
app.router.add_get("/web-settings", self._web_settings_route)
app.router.add_get("/custom.css", self._styles_route)
@ -169,6 +184,12 @@ class WebServer:
shutdown_timeout=0.1,
)
async def _favicon_route(
self,
request: aiohttp.web.Request,
) -> aiohttp.web.FileResponse:
return aiohttp.web.FileResponse(self.favicon_path)
async def _service_properties_route(
self,
request: aiohttp.web.Request,