diff --git a/client/scss/components/_dismissible.scss b/client/scss/components/_dismissible.scss new file mode 100644 index 0000000000..5aeda6e351 --- /dev/null +++ b/client/scss/components/_dismissible.scss @@ -0,0 +1,31 @@ +@keyframes pulse-warning { + 0% { + box-shadow: 0 0 0 0 + hsla( + var(--w-color-warning-100-hue), + var(--w-color-warning-100-saturation), + var(--w-color-warning-100-lightness), + 0.7 + ); + } + + 25% { + box-shadow: 0 0 0 10px + hsla( + var(--w-color-warning-100-hue), + var(--w-color-warning-100-saturation), + var(--w-color-warning-100-lightness), + 0 + ); + } + + 50% { + box-shadow: 0 0 0 0 + hsla( + var(--w-color-warning-100-hue), + var(--w-color-warning-100-saturation), + var(--w-color-warning-100-lightness), + 0 + ); + } +} diff --git a/client/scss/components/_whats-new.scss b/client/scss/components/_whats-new.scss new file mode 100644 index 0000000000..b4a34691b9 --- /dev/null +++ b/client/scss/components/_whats-new.scss @@ -0,0 +1,72 @@ +.w-whats-new { + @include nice-padding(); + margin-bottom: theme('spacing.16'); + + &.w-dismissible--dismissed { + display: none; + } + + &__banner { + position: relative; + display: flex; + align-items: center; + border-radius: theme('borderRadius.md'); + padding: theme('spacing.6'); + background-color: theme('colors.warning.50'); + border: 5px solid transparent; + } + + &__main-icon { + .icon { + color: theme('colors.warning.100'); + width: theme('spacing.10'); + height: theme('spacing.10'); + margin-inline-end: theme('spacing.4'); + border-radius: theme('borderRadius.full'); + + @media (prefers-reduced-motion: no-preference) { + animation: pulse-warning 5s 5; + } + } + } + + &__heading { + @apply w-h3; + color: theme('colors.grey.600'); + margin-top: 0; + margin-bottom: theme('spacing.2'); + } + + &__details { + @apply w-body-text-large; + margin-bottom: 0; + } + + &__link { + font-weight: theme('fontWeight.bold'); + color: theme('colors.secondary.400'); + text-decoration: underline; + text-decoration-thickness: 2px; + text-underline-offset: 3px; + } + + &__dismiss { + @apply -w-top-3 -w-right-3; + position: absolute; + padding: 0; + background-color: transparent; + + .icon { + border-radius: theme('borderRadius.full'); + width: theme('spacing.6'); + height: theme('spacing.6'); + background-color: theme('colors.white.DEFAULT'); + color: theme('colors.primary.DEFAULT'); + + @media (forced-colors: active) { + background-color: Canvas; + color: CanvasText; + } + } + } +} diff --git a/client/scss/core.scss b/client/scss/core.scss index 161355086e..b87b307c1e 100644 --- a/client/scss/core.scss +++ b/client/scss/core.scss @@ -129,6 +129,7 @@ These are classes for components. @import 'components/tabs'; @import 'components/panel'; @import 'components/dialog'; +@import 'components/dismissible'; @import 'components/dropdown'; @import 'components/dropdown.legacy'; @import 'components/help-block'; @@ -145,6 +146,7 @@ These are classes for components. @import 'components/search-bar'; @import 'components/progressbar'; @import 'components/summary'; +@import 'components/whats-new'; @import 'components/tooltips'; @import 'components/grid.legacy'; @import 'components/footer'; diff --git a/wagtail/admin/templates/wagtailadmin/home/whats_new_in_wagtail_version.html b/wagtail/admin/templates/wagtailadmin/home/whats_new_in_wagtail_version.html new file mode 100644 index 0000000000..78b16a0291 --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/home/whats_new_in_wagtail_version.html @@ -0,0 +1,28 @@ +{% load i18n wagtailadmin_tags wagtailcore_tags %} + +
+
+ +
+ {% icon name="help" %} +
+
+

+ {% blocktrans trimmed %} + Things in Wagtail {{ version }} have changed! + {% endblocktrans %} +

+

+ {% wagtail_feature_release_editor_guide_link as editor_guide_link %} + {% blocktrans trimmed %} + Don't worry, we've got your back. Check out the + Wagtail Editor Guide + to get the low down on what's changed and some exciting new features! + {% endblocktrans %} +

+
+
+
diff --git a/wagtail/admin/templates/wagtailadmin/icons/circle-xmark.svg b/wagtail/admin/templates/wagtailadmin/icons/circle-xmark.svg new file mode 100644 index 0000000000..e4decd74ac --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/icons/circle-xmark.svg @@ -0,0 +1 @@ + diff --git a/wagtail/admin/templates/wagtailadmin/icons/help.svg b/wagtail/admin/templates/wagtailadmin/icons/help.svg index 597b0afe43..7fca245d3b 100755 --- a/wagtail/admin/templates/wagtailadmin/icons/help.svg +++ b/wagtail/admin/templates/wagtailadmin/icons/help.svg @@ -1,3 +1 @@ - - - + diff --git a/wagtail/admin/views/home.py b/wagtail/admin/views/home.py index d02e6af35e..290f0ecbc0 100644 --- a/wagtail/admin/views/home.py +++ b/wagtail/admin/views/home.py @@ -59,6 +59,37 @@ class UpgradeNotificationPanel(Component): return "" +class WhatsNewInWagtailVersionPanel(Component): + name = "whats_new_in_wagtail_version" + template_name = "wagtailadmin/home/whats_new_in_wagtail_version.html" + order = 110 + _version = "4" + + def get_whats_new_banner_setting(self) -> Union[bool, str]: + return getattr(settings, "WAGTAIL_ENABLE_WHATS_NEW_BANNER", True) + + def get_dismissible_id(self) -> str: + return f"{self.name}_{self._version}" + + def get_context_data(self, parent_context: Mapping[str, Any]) -> Mapping[str, Any]: + return {"dismissible_id": self.get_dismissible_id(), "version": self._version} + + def is_shown(self, parent_context: Mapping[str, Any] = None) -> bool: + if not self.get_whats_new_banner_setting(): + return False + + profile = getattr(parent_context["request"].user, "wagtail_userprofile", None) + if profile and profile.dismissibles.get(self.get_dismissible_id()): + return False + + return True + + def render_html(self, parent_context: Mapping[str, Any] = None) -> str: + if not self.is_shown(parent_context): + return "" + return super().render_html(parent_context) + + class PagesForModerationPanel(Component): name = "pages_for_moderation" template_name = "wagtailadmin/home/pages_for_moderation.html" @@ -245,6 +276,7 @@ class HomeView(WagtailAdminTemplateMixin, TemplateView): request = self.request panels = [ SiteSummaryPanel(request), + WhatsNewInWagtailVersionPanel(), UpgradeNotificationPanel(), WorkflowPagesToModeratePanel(), PagesForModerationPanel(), diff --git a/wagtail/admin/wagtail_hooks.py b/wagtail/admin/wagtail_hooks.py index 0e2d658ad1..fcb7de8d2b 100644 --- a/wagtail/admin/wagtail_hooks.py +++ b/wagtail/admin/wagtail_hooks.py @@ -985,6 +985,7 @@ def register_icons(icons): "chevron-down.svg", "circle-check.svg", "circle-plus.svg", + "circle-xmark.svg", "clipboard-list.svg", "code.svg", "cog.svg", diff --git a/wagtail/templatetags/wagtailcore_tags.py b/wagtail/templatetags/wagtailcore_tags.py index 4d2276d98c..f938b467c9 100644 --- a/wagtail/templatetags/wagtailcore_tags.py +++ b/wagtail/templatetags/wagtailcore_tags.py @@ -93,6 +93,11 @@ def wagtail_release_notes_path(): return "%s.html" % get_main_version(VERSION) +@register.simple_tag +def wagtail_feature_release_editor_guide_link(): + return "https://wagtail.org/wagtail-4-1-editor-guide" + + @register.filter def richtext(value): if isinstance(value, RichText):