From 4532367088fdf2a9fe516a425fe2bf10cfc3bf82 Mon Sep 17 00:00:00 2001 From: anish-work Date: Tue, 10 Dec 2024 02:14:23 +0530 Subject: [PATCH 1/3] show last saved time --- daras_ai_v2/base.py | 29 +++++++++++++++++++++++------ daras_ai_v2/utils.py | 22 ++++++++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 daras_ai_v2/utils.py diff --git a/daras_ai_v2/base.py b/daras_ai_v2/base.py index 399592b8d..34e9deada 100644 --- a/daras_ai_v2/base.py +++ b/daras_ai_v2/base.py @@ -69,6 +69,7 @@ from routers.root import RecipeTabs from workspaces.models import Workspace, WorkspaceMembership from workspaces.widgets import get_current_workspace, set_current_workspace +from daras_ai_v2.utils import get_relative_time DEFAULT_META_IMG = ( # Small @@ -345,12 +346,24 @@ def render(self): header_placeholder = gui.div() gui.newline() - - with gui.nav_tabs(): - for tab in self.get_tabs(): - url = self.current_app_url(tab) - with gui.nav_item(url, active=tab == self.tab): - gui.html(tab.title) + with gui.div(className="position-relative"): + with gui.nav_tabs(): + for tab in self.get_tabs(): + url = self.current_app_url(tab) + with gui.nav_item(url, active=tab == self.tab): + gui.html(tab.title) + + if self.current_pr and not self.current_pr.is_root(): + with gui.div( + className="container-margin-reset d-none d-md-block", + style=dict( + position="absolute", + top="50%", + right="0", + transform="translateY(-50%)", + ), + ): + self._render_saved_timestamp(self.current_pr) with gui.nav_tab_content(): self.render_selected_tab() @@ -467,6 +480,10 @@ def _render_unpublished_changes_indicator(self): ): gui.html("Unpublished changes") + def _render_saved_timestamp(self, pr: PublishedRun): + with gui.tag("span", className="text-muted"): + gui.write(f"{get_relative_time(pr.updated_at)}") + def _render_options_button_with_dialog(self): ref = gui.use_alert_dialog(key="options-modal") if gui.button(label=icons.more_options, className="mb-0", type="tertiary"): diff --git a/daras_ai_v2/utils.py b/daras_ai_v2/utils.py new file mode 100644 index 000000000..2ebc8e553 --- /dev/null +++ b/daras_ai_v2/utils.py @@ -0,0 +1,22 @@ +from datetime import datetime + + +def get_relative_time(timestamp): + now = datetime.now(timestamp.tzinfo) + diff = now - timestamp + + seconds = diff.total_seconds() + if seconds < 2: + return "just now" + if seconds < 60: + return f"{int(seconds)}s ago" + elif seconds < 3600: + return f"{int(seconds/60)}m ago" + elif seconds < 86400: + return f"{int(seconds/3600)}h ago" + elif seconds < 2592000: + return f"{int(seconds/86400)}d ago" + elif seconds < 31536000: + return f"{int(seconds/2592000)}mo ago" + else: + return f"{int(seconds/31536000)}y ago" From 8a9c4cf59567fd30a3f5d931286bd6c8548a7273 Mon Sep 17 00:00:00 2001 From: anish-work Date: Thu, 12 Dec 2024 22:15:13 +0530 Subject: [PATCH 2/3] use timedelta --- daras_ai_v2/utils.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/daras_ai_v2/utils.py b/daras_ai_v2/utils.py index 2ebc8e553..e728b4d76 100644 --- a/daras_ai_v2/utils.py +++ b/daras_ai_v2/utils.py @@ -1,22 +1,22 @@ -from datetime import datetime +from django.utils import timezone +from datetime import timedelta def get_relative_time(timestamp): - now = datetime.now(timestamp.tzinfo) - diff = now - timestamp - + diff = timezone.now() - timestamp seconds = diff.total_seconds() + if seconds < 2: - return "just now" - if seconds < 60: + return "Just now" + if seconds < timedelta(minutes=1).total_seconds(): return f"{int(seconds)}s ago" - elif seconds < 3600: - return f"{int(seconds/60)}m ago" - elif seconds < 86400: - return f"{int(seconds/3600)}h ago" - elif seconds < 2592000: - return f"{int(seconds/86400)}d ago" - elif seconds < 31536000: - return f"{int(seconds/2592000)}mo ago" + elif seconds < timedelta(hours=1).total_seconds(): + return f"{int(seconds/timedelta(minutes=1).total_seconds())}m ago" + elif seconds < timedelta(days=1).total_seconds(): + return f"{int(seconds/timedelta(hours=1).total_seconds())}h ago" + elif seconds < timedelta(days=30).total_seconds(): + return f"{int(seconds/timedelta(days=1).total_seconds())}d ago" + elif seconds < timedelta(days=365).total_seconds(): + return f"{int(seconds/timedelta(days=30).total_seconds())}mo ago" else: - return f"{int(seconds/31536000)}y ago" + return f"{int(seconds/timedelta(days=365).total_seconds())}y ago" From 3bce2f377568d644c365f6401b919b7714c3bf6d Mon Sep 17 00:00:00 2001 From: anish-work Date: Fri, 27 Dec 2024 04:29:12 +0530 Subject: [PATCH 3/3] use timedelta thresholds --- daras_ai_v2/utils.py | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/daras_ai_v2/utils.py b/daras_ai_v2/utils.py index e728b4d76..5ba6a875c 100644 --- a/daras_ai_v2/utils.py +++ b/daras_ai_v2/utils.py @@ -1,22 +1,19 @@ from django.utils import timezone -from datetime import timedelta +from datetime import timedelta, datetime +THRESHOLDS = [ + (timedelta(days=365), "y"), + (timedelta(days=30), "mo"), + (timedelta(days=1), "d"), + (timedelta(hours=1), "h"), + (timedelta(minutes=1), "m"), + (timedelta(seconds=3), "s"), +] -def get_relative_time(timestamp): - diff = timezone.now() - timestamp - seconds = diff.total_seconds() - if seconds < 2: - return "Just now" - if seconds < timedelta(minutes=1).total_seconds(): - return f"{int(seconds)}s ago" - elif seconds < timedelta(hours=1).total_seconds(): - return f"{int(seconds/timedelta(minutes=1).total_seconds())}m ago" - elif seconds < timedelta(days=1).total_seconds(): - return f"{int(seconds/timedelta(hours=1).total_seconds())}h ago" - elif seconds < timedelta(days=30).total_seconds(): - return f"{int(seconds/timedelta(days=1).total_seconds())}d ago" - elif seconds < timedelta(days=365).total_seconds(): - return f"{int(seconds/timedelta(days=30).total_seconds())}mo ago" - else: - return f"{int(seconds/timedelta(days=365).total_seconds())}y ago" +def get_relative_time(timestamp: datetime) -> str: + diff = timezone.now() - timestamp + for threshold, unit in THRESHOLDS: + if diff >= threshold: + return f"{round(diff / threshold)}{unit} ago" + return "Just now"