From a0ad98531eda81cb29eee918abfe02184fddc9a6 Mon Sep 17 00:00:00 2001 From: Jakob Pinterits Date: Tue, 9 Apr 2024 22:22:17 +0200 Subject: [PATCH] removed dashboard, snippet improvements --- dashboard/__init__.py | 20 ---- dashboard/components/__init__.py | 4 - dashboard/components/history.py | 58 --------- dashboard/components/sidebar.py | 34 ------ dashboard/components/stat_card.py | 66 ---------- dashboard/components/task_list.py | 58 --------- dashboard/pages/__init__.py | 1 - dashboard/pages/dashboard.py | 113 ------------------ ...tphone-sales-clean.csv => smartphones.csv} | 0 .../meta.json | 6 +- .../pages/interactive_plot.py | 45 ++++--- 11 files changed, 31 insertions(+), 374 deletions(-) delete mode 100644 dashboard/__init__.py delete mode 100644 dashboard/components/__init__.py delete mode 100644 dashboard/components/history.py delete mode 100644 dashboard/components/sidebar.py delete mode 100644 dashboard/components/stat_card.py delete mode 100644 dashboard/components/task_list.py delete mode 100644 dashboard/pages/__init__.py delete mode 100644 dashboard/pages/dashboard.py rename rio/snippets/snippet-files/project-template-Simple Dashboard/assets/{smartphone-sales-clean.csv => smartphones.csv} (100%) diff --git a/dashboard/__init__.py b/dashboard/__init__.py deleted file mode 100644 index 95f0a75b..00000000 --- a/dashboard/__init__.py +++ /dev/null @@ -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(), -) diff --git a/dashboard/components/__init__.py b/dashboard/components/__init__.py deleted file mode 100644 index c4290bf7..00000000 --- a/dashboard/components/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -from .history import History -from .sidebar import Sidebar -from .stat_card import StatCard -from .task_list import ProcessList diff --git a/dashboard/components/history.py b/dashboard/components/history.py deleted file mode 100644 index 40db415b..00000000 --- a/dashboard/components/history.py +++ /dev/null @@ -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, - ) diff --git a/dashboard/components/sidebar.py b/dashboard/components/sidebar.py deleted file mode 100644 index c95426fe..00000000 --- a/dashboard/components/sidebar.py +++ /dev/null @@ -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, - ) diff --git a/dashboard/components/stat_card.py b/dashboard/components/stat_card.py deleted file mode 100644 index d42376cc..00000000 --- a/dashboard/components/stat_card.py +++ /dev/null @@ -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, - ) diff --git a/dashboard/components/task_list.py b/dashboard/components/task_list.py deleted file mode 100644 index 0942cd96..00000000 --- a/dashboard/components/task_list.py +++ /dev/null @@ -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", - ) diff --git a/dashboard/pages/__init__.py b/dashboard/pages/__init__.py deleted file mode 100644 index 632302cb..00000000 --- a/dashboard/pages/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .dashboard import Dashboard diff --git a/dashboard/pages/dashboard.py b/dashboard/pages/dashboard.py deleted file mode 100644 index 3f8d7efc..00000000 --- a/dashboard/pages/dashboard.py +++ /dev/null @@ -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, - ) diff --git a/rio/snippets/snippet-files/project-template-Simple Dashboard/assets/smartphone-sales-clean.csv b/rio/snippets/snippet-files/project-template-Simple Dashboard/assets/smartphones.csv similarity index 100% rename from rio/snippets/snippet-files/project-template-Simple Dashboard/assets/smartphone-sales-clean.csv rename to rio/snippets/snippet-files/project-template-Simple Dashboard/assets/smartphones.csv diff --git a/rio/snippets/snippet-files/project-template-Simple Dashboard/meta.json b/rio/snippets/snippet-files/project-template-Simple Dashboard/meta.json index dbafd294..9a6b59d4 100644 --- a/rio/snippets/snippet-files/project-template-Simple Dashboard/meta.json +++ b/rio/snippets/snippet-files/project-template-Simple Dashboard/meta.json @@ -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" + } } \ No newline at end of file diff --git a/rio/snippets/snippet-files/project-template-Simple Dashboard/pages/interactive_plot.py b/rio/snippets/snippet-files/project-template-Simple Dashboard/pages/interactive_plot.py index 3e5b2b70..5934e9bb 100644 --- a/rio/snippets/snippet-files/project-template-Simple Dashboard/pages/interactive_plot.py +++ b/rio/snippets/snippet-files/project-template-Simple Dashboard/pages/interactive_plot.py @@ -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" +# +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) +# # 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(