mirror of
https://github.com/rio-labs/rio.git
synced 2026-02-09 07:09:00 -06:00
removed dashboard, snippet improvements
This commit is contained in:
@@ -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(),
|
||||
)
|
||||
@@ -1,4 +0,0 @@
|
||||
from .history import History
|
||||
from .sidebar import Sidebar
|
||||
from .stat_card import StatCard
|
||||
from .task_list import ProcessList
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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",
|
||||
)
|
||||
@@ -1 +0,0 @@
|
||||
from .dashboard import Dashboard
|
||||
@@ -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,
|
||||
)
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user