diff --git a/docs/release-notes/version-4.0.md b/docs/release-notes/version-4.0.md index d85e2ec07..941a1239e 100644 --- a/docs/release-notes/version-4.0.md +++ b/docs/release-notes/version-4.0.md @@ -2,6 +2,20 @@ ## v4.0.10 (FUTURE) +### Enhancements + +* [#16857](https://github.com/netbox-community/netbox/issues/16857) - Scroll long rendered Markdown content within tables +* [#16949](https://github.com/netbox-community/netbox/issues/16949) - Add device count column to sites table +* [#17072](https://github.com/netbox-community/netbox/issues/17072) - Linkify email addresses & phone numbers in contact assignments list +* [#17177](https://github.com/netbox-community/netbox/issues/17177) - Add facility field to locations filter form + +### Bug Fixes + +* [#16640](https://github.com/netbox-community/netbox/issues/16640) - Fix potential corruption of JSON values in custom fields that are not UI-editable +* [#17070](https://github.com/netbox-community/netbox/issues/17070) - Image height & width values should not be required when creating an image attachment via the REST API +* [#17108](https://github.com/netbox-community/netbox/issues/17108) - Ensure template date & time filters always return localtime-aware values +* [#17117](https://github.com/netbox-community/netbox/issues/17117) - Work around Safari rendering bug + --- ## v4.0.9 (2024-08-14) diff --git a/netbox/extras/forms/reports.py b/netbox/extras/forms/reports.py index 358ee90e3..95692b3f6 100644 --- a/netbox/extras/forms/reports.py +++ b/netbox/extras/forms/reports.py @@ -31,7 +31,7 @@ class ReportForm(forms.Form): super().__init__(*args, **kwargs) # Annotate the current system time for reference - now = local_now().strftime('%Y-%m-%d %H:%M:%S') + now = local_now().strftime('%Y-%m-%d %H:%M:%S %Z') self.fields['schedule_at'].help_text += _(' (current time: {now})').format(now=now) # Remove scheduling fields if scheduling is disabled diff --git a/netbox/extras/forms/scripts.py b/netbox/extras/forms/scripts.py index ece96f5e4..331f7f01f 100644 --- a/netbox/extras/forms/scripts.py +++ b/netbox/extras/forms/scripts.py @@ -37,7 +37,7 @@ class ScriptForm(forms.Form): super().__init__(*args, **kwargs) # Annotate the current system time for reference - now = local_now().strftime('%Y-%m-%d %H:%M:%S') + now = local_now().strftime('%Y-%m-%d %H:%M:%S %Z') self.fields['_schedule_at'].help_text += _(' (current time: {now})').format(now=now) # Remove scheduling fields if scheduling is disabled diff --git a/netbox/project-static/dist/netbox.css b/netbox/project-static/dist/netbox.css index 8460154e6..7d95ac540 100644 Binary files a/netbox/project-static/dist/netbox.css and b/netbox/project-static/dist/netbox.css differ diff --git a/netbox/project-static/styles/overrides/_tabler.scss b/netbox/project-static/styles/overrides/_tabler.scss index 9ff87e4ef..38a600601 100644 --- a/netbox/project-static/styles/overrides/_tabler.scss +++ b/netbox/project-static/styles/overrides/_tabler.scss @@ -45,6 +45,19 @@ table a { background-color: rgba(var(--tblr-primary-rgb),.48) } +// Do not apply padding to elements inside a
 pre code {
   padding: unset;
 }
+
+// Use an icon instead of Tabler's native "caret" for dropdowns (avoids a Safari bug)
+.dropdown-toggle:after{
+  font-family: "Material Design Icons";
+  content: '\F0140';
+  padding-right: 9px;
+  border-bottom: none;
+  border-left: none;
+  transform: none;
+  vertical-align: .05em;
+  height: auto;
+}
diff --git a/netbox/utilities/permissions.py b/netbox/utilities/permissions.py
index 893cc619e..ba245dae1 100644
--- a/netbox/utilities/permissions.py
+++ b/netbox/utilities/permissions.py
@@ -1,7 +1,10 @@
 from django.conf import settings
+from django.apps import apps
 from django.db.models import Q
 from django.utils.translation import gettext_lazy as _
 
+from users.constants import CONSTRAINT_TOKEN_USER
+
 __all__ = (
     'get_permission_for_model',
     'permission_is_exempt',
@@ -90,6 +93,11 @@ def qs_filter_from_constraints(constraints, tokens=None):
     if tokens is None:
         tokens = {}
 
+    User = apps.get_model('users.User')
+    for token, value in tokens.items():
+        if token == CONSTRAINT_TOKEN_USER and isinstance(value, User):
+            tokens[token] = value.id
+
     def _replace_tokens(value, tokens):
         if type(value) is list:
             return list(map(lambda v: tokens.get(v, v), value))
diff --git a/netbox/utilities/templatetags/builtins/filters.py b/netbox/utilities/templatetags/builtins/filters.py
index 738b9a23e..b1c8c524b 100644
--- a/netbox/utilities/templatetags/builtins/filters.py
+++ b/netbox/utilities/templatetags/builtins/filters.py
@@ -8,6 +8,7 @@ from django.contrib.contenttypes.models import ContentType
 from django.contrib.humanize.templatetags.humanize import naturalday, naturaltime
 from django.utils.html import escape
 from django.utils.safestring import mark_safe
+from django.utils.timezone import localtime
 from markdown import markdown
 from markdown.extensions.tables import TableExtension
 
@@ -218,7 +219,8 @@ def isodate(value):
         text = value.isoformat()
         return mark_safe(f'{text}')
     elif type(value) is datetime.datetime:
-        text = value.date().isoformat()
+        local_value = localtime(value) if value.tzinfo else value
+        text = local_value.date().isoformat()
         return mark_safe(f'{text}')
     else:
         return ''
@@ -229,7 +231,8 @@ def isotime(value, spec='seconds'):
     if type(value) is datetime.time:
         return value.isoformat(timespec=spec)
     if type(value) is datetime.datetime:
-        return value.time().isoformat(timespec=spec)
+        local_value = localtime(value) if value.tzinfo else value
+        return local_value.time().isoformat(timespec=spec)
     return ''