removed dashboard, snippet improvements

This commit is contained in:
Jakob Pinterits
2024-04-09 22:22:17 +02:00
parent 456c42e70c
commit a0ad98531e
11 changed files with 31 additions and 374 deletions

View File

@@ -1,20 +0,0 @@
from __future__ import annotations
from typing import * # type: ignore
import rio
from . import components as comps
from . import pages
app = rio.App(
name="Rio",
icon=rio.common.RIO_LOGO_ASSET_PATH,
pages=[
rio.Page(
page_url="",
build=pages.Dashboard,
),
],
theme=rio.Theme.from_color(),
)

View File

@@ -1,4 +0,0 @@
from .history import History
from .sidebar import Sidebar
from .stat_card import StatCard
from .task_list import ProcessList

View File

@@ -1,58 +0,0 @@
from __future__ import annotations
import time
from dataclasses import KW_ONLY, field
from typing import * # type: ignore
import plotly.graph_objects as go
import psutil
import rio
from .. import components as comps
class History(rio.Component):
timestamps: List[float] = field(default_factory=list)
values: List[float] = field(default_factory=list)
@rio.event.periodic(0.5)
async def on_populate(self) -> None:
# Add the current time and CPU usage to the lists
now = time.time()
self.timestamps.append(now)
self.values.append(psutil.cpu_percent())
# Remove any old ones
while self.timestamps[0] < now - 60:
del self.timestamps[0]
del self.values[0]
await self.force_refresh()
def build(self) -> rio.Component:
figure = go.Figure(
go.Scatter(
x=self.timestamps,
y=self.values,
line={
"color": self.session.theme.secondary_color.as_plotly,
"width": 4,
},
fill="tozeroy",
fillcolor=self.session.theme.secondary_color.replace(
opacity=0.2
).as_plotly,
),
)
figure.update_layout(
yaxis_range=[0, 100],
xaxis_showticklabels=False,
# margin={"t": 0, "r": 0, "b": 0, "l": 0},
)
return rio.Plot(
figure,
corner_radius=self.session.theme.corner_radius_medium,
)

View File

@@ -1,34 +0,0 @@
from __future__ import annotations
from typing import * # type: ignore
import rio
from .. import components as comps
class Sidebar(rio.Component):
def build(self) -> rio.Component:
return rio.Card(
rio.SwitcherBar(
icons=[
"material/castle",
"material/archive",
"material/settings",
],
names=[
"Dash",
"Project",
"Settings",
],
values=[
"dashboard",
"projects",
"settings",
],
orientation="vertical",
align_y=0,
margin=0.4,
),
corner_radius=0,
)

View File

@@ -1,66 +0,0 @@
from __future__ import annotations
from typing import * # type: ignore
import rio
from .. import components as comps
class StatCard(rio.Component):
icon: str
color: rio.Color
title: str
current: str
maximum: str | None = None
on_press: rio.EventHandler[[]] = None
@rio.event.periodic(1)
async def on_populate(self) -> None:
await self.force_refresh()
def _on_press(self) -> None:
pass
def build(self) -> rio.Component:
return rio.Card(
rio.Column(
rio.Row(
rio.Icon(
self.icon,
width=3,
height=3,
align_y=0,
),
rio.Column(
rio.Text(
self.title,
style="heading3",
align_x=1,
margin_bottom=1,
),
rio.Spacer(),
rio.Text(
self.current,
align_x=1,
),
(
rio.Spacer(height=0)
if self.maximum is None
else rio.Text(
f"of {self.maximum}",
style="dim",
align_x=1,
)
),
width="grow",
),
height="grow",
),
margin=1.5,
),
color=self.color,
on_press=self._on_press,
)

View File

@@ -1,58 +0,0 @@
from __future__ import annotations
from typing import * # type: ignore
import psutil
import rio
from .. import components as comps
class ProcessList(rio.Component):
example_state: str = "For demonstration purposes"
def build(self) -> rio.Component:
entries = []
# entries.append(
# rio.SimpleListItem(
# text="Task 1",
# secondary_text="This is a description of task 1",
# key="task1",
# ),
# )
# entries.append(
# rio.SimpleListItem(
# text="Task 2",
# secondary_text="This is a description of task 2",
# key="task2",
# ),
# )
processes = list(psutil.process_iter())
processes.sort(key=lambda proc: proc.name())
processes = processes[:10]
for proc in processes:
entries.append(
rio.SimpleListItem(
text=proc.name(),
secondary_text=f"PID: {proc.pid}",
key=str(proc.pid),
),
)
return rio.Card(
rio.Column(
rio.Text(
"Tasks",
style="heading2",
margin=1,
),
rio.ListView(
*entries,
),
),
# color="primary",
)

View File

@@ -1 +0,0 @@
from .dashboard import Dashboard

View File

@@ -1,113 +0,0 @@
from __future__ import annotations
from typing import * # type: ignore
import psutil
import rio
from .. import components as comps
class Dashboard(rio.Component):
banner_message: str | None = None
def build(self) -> rio.Component:
# Grids need more information about their children than most components.
# It's often easier to create them first, then add children afterwards.
grid = rio.Grid(
width="grow",
height="grow",
row_spacing=2,
column_spacing=2,
margin=2,
)
# The banner will display a message at the top of the page.
grid.add(
rio.Banner(
self.banner_message,
style="info",
),
row=0,
column=0,
width=4,
)
# CPU
grid.add(
comps.StatCard(
icon="material/memory",
# color=rio.Color.RED,
color=self.session.theme.primary_color,
title="Processor",
current=f"{psutil.cpu_percent()}%",
),
row=1,
column=0,
)
# Memory
mem = psutil.virtual_memory()
grid.add(
comps.StatCard(
icon="material/apps",
# color=rio.Color.GREEN,
color=self.session.theme.primary_color,
title="Memory",
current=f"{mem.used / 2**30:.0f}GiB",
maximum=f"{mem.total / 2 ** 30:.0f}GiB",
),
row=1,
column=1,
)
# Network
net = psutil.net_io_counters()
grid.add(
comps.StatCard(
icon="material/wifi",
# color=rio.Color.BLUE,
color=self.session.theme.primary_color,
title="Network",
current=f"{net.bytes_sent / 2**30:.0f}GiB",
),
row=1,
column=2,
)
# Storage
disk = psutil.disk_usage("/")
grid.add(
comps.StatCard(
icon="material/storage",
# color=rio.Color.ORANGE,
color=self.session.theme.primary_color,
title="Storage",
current=f"{disk.used / 2**30:.0f}GiB",
maximum=f"{disk.total / 2**30:.0f}GiB",
),
row=1,
column=3,
)
grid.add(
comps.History(
height="grow",
),
row=2,
column=0,
width=3,
)
grid.add(
comps.ProcessList(
align_y=0,
),
row=2,
column=3,
)
return rio.Row(
comps.Sidebar(),
grid,
)

View File

@@ -1,4 +1,8 @@
{
"level": "beginner",
"summary": "A simple dashboard, featuring an interactive graph, controls and CSV download"
"summary": "A simple dashboard, featuring an interactive graph, controls and CSV download",
"dependencies": {
"plotly": ">=5.20.0",
"pandas": ">=2.2.1"
}
}

View File

@@ -1,33 +1,40 @@
import urllib.request
from pathlib import Path
import pandas as pd
import plotly.graph_objs as go
from dataclasses import field
import rio
# Load the dataset
CSV_PATH = Path(__file__).parent / "smartphone-sales.csv"
CSV_URL = "https://TODO-real-url.com"
# <additional-imports>
import pandas as pd
import plotly.graph_objs as go
if not CSV_PATH.exists():
with urllib.request.urlopen(CSV_URL) as response:
CSV_PATH.write_bytes(response.read())
raw_df = pd.read_csv(CSV_PATH)
raw_df = raw_df.head(1000)
# </additional-imports>
# <component>
class InteractivePlot(rio.Component):
x_axis: str = raw_df.columns[0]
y_axis: str = raw_df.columns[1]
# The full dataset, containing all smartphone data. This will be loaded when
# the component is initialized. See the `load_data` method for details.
dataset: pd.DataFrame = field(default_factory=pd.DataFrame)
# The currently selected columns to display in the scatterplot. These values
# will be initializes when the dataset is loaded.
x_axis: str = ""
y_axis: str = ""
# If this is `True`, we'll take care to remove unlikely data by keeping only
# the tenth to ninetieth percentile of the dataset.
remove_outliers: bool = False
@rio.event.on_populate
def load_data(self) -> None:
self.dataset = pd.read_csv(
self.session.assets / "smartphones.csv",
)
self.x_axis = self.dataset.columns[0]
self.y_axis = self.dataset.columns[1]
async def on_download_csv(self) -> None:
# Build a CSV file from the selected columns
selected_df = raw_df[[self.x_axis, self.y_axis]]
selected_df = self.dataset[[self.x_axis, self.y_axis]]
csv = selected_df.to_csv(index=False)
# Save the file
@@ -41,7 +48,7 @@ class InteractivePlot(rio.Component):
Remove outliers from the dataset, by keeping only the tenth to ninetieth
percentile.
"""
result = raw_df
result = self.dataset
# Remove outliers in the x-axis
series = result[self.x_axis]
@@ -68,7 +75,7 @@ class InteractivePlot(rio.Component):
if self.remove_outliers:
df = self.filter_data()
else:
df = raw_df
df = self.dataset
# Build the plot
return rio.Row(