diff --git a/CHANGELOG.txt b/CHANGELOG.txt index c1d088e030..f280e317a1 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -20,6 +20,7 @@ Changelog * Fire `copy_for_translation_done` signal when copying translatable models as well as pages (Coen van der Kamp) * Add support for an image `description` field across all images, to better support accessible image descriptions (Chiemezuo Akujobi) * Prompt the user about unsaved changes when editing snippets (Sage Abdullah) + * Implement incremental dashboard design enhancements (Albina Starykova) * Fix: Prevent page type business rules from blocking reordering of pages (Andy Babic, Sage Abdullah) * Fix: Improve layout of object permissions table (Sage Abdullah) * Fix: Fix typo in aria-label attribute of page explorer navigation link (Sébastien Corbin) diff --git a/client/scss/components/_avatar.scss b/client/scss/components/_avatar.scss index 19b9fd022a..78c5fe8b1e 100644 --- a/client/scss/components/_avatar.scss +++ b/client/scss/components/_avatar.scss @@ -29,9 +29,12 @@ } &.large { + width: 60px; + height: 60px; + @include media-breakpoint-up(sm) { - width: 70px; - height: 70px; + width: 80px; + height: 80px; } } @@ -39,3 +42,33 @@ border-radius: 0; } } + +.avatar--edit { + overflow: visible; + flex-shrink: 0; + + img { + border-radius: 50%; + z-index: auto; + } +} + +.avatar__edit-link { + width: theme('spacing.5'); + height: theme('spacing.5'); + border-radius: 50%; + border: theme('spacing.px') solid theme('colors.border-furniture'); + display: flex; + align-items: center; + justify-content: center; + position: absolute; + top: 100%; + inset-inline-start: 50%; + transform: translate(calc(var(--w-direction-factor) * -50%), -50%); + background-color: theme('colors.surface-page'); + + .icon { + width: theme('spacing.[2.5]'); + height: theme('spacing.[2.5]'); + } +} diff --git a/client/scss/components/_header.scss b/client/scss/components/_header.scss index 4bbfbb7ab1..ad126efeb9 100644 --- a/client/scss/components/_header.scss +++ b/client/scss/components/_header.scss @@ -27,10 +27,6 @@ max-width: 1em; max-height: 1em; } - - &.avatar { - margin-inline-start: calc(0 - theme('spacing.2')); - } } .w-header__subtitle { @@ -38,11 +34,6 @@ font-weight: theme('fontWeight.normal'); } - .w-header__description { - font-size: theme('fontSize.18'); - font-weight: theme('fontWeight.normal'); - } - // Give padding to the rows inside of headers so that nested breadcrumbs aren't padded by their parent header el. // Use w-header--with-padding for headers that don't contain .row elements. &.w-header--with-padding, @@ -104,10 +95,6 @@ margin-inline-end: 2em; } - .avatar.small { - margin-inline-start: 0; - } - a { font-weight: theme('fontWeight.bold'); } @@ -126,12 +113,6 @@ padding-inline-start: 0; } - .w-header__glyph { - &.avatar { - margin-inline-start: calc(0 - theme('spacing.9')); - } - } - .left { float: inline-start; margin-inline-end: 0; diff --git a/client/scss/components/_indicator.scss b/client/scss/components/_indicator.scss index 96cae05992..456eadeff2 100644 --- a/client/scss/components/_indicator.scss +++ b/client/scss/components/_indicator.scss @@ -1,3 +1,17 @@ +.indicator { + margin-inline-end: 0; + opacity: theme('opacity.70'); + + .icon { + padding: 2px; + vertical-align: middle; // reset vertical-align set by icon.initial + } + + &--is-dimmed { + opacity: theme('opacity.50'); + } +} + .privacy-indicator { &.public { .label-private { @@ -11,31 +25,3 @@ } } } - -.indicator { - font-size: 1em; - margin-inline-end: 0; - opacity: theme('opacity.70'); - - .icon { - border: 1px solid transparent; - border-radius: 50%; - font-size: 1.25em; - padding: 2px; - vertical-align: middle; // reset vertical-align set by icon.initial - - @media (forced-colors: active) { - background-color: ButtonText; - } - } - - &.indicator--is-inverse { - .icon { - border-color: theme( - 'colors.surface-page' - ); // ensure border is available for high contrast mode - background-color: theme('colors.text-context'); - color: theme('colors.surface-page'); - } - } -} diff --git a/client/scss/components/_listing.scss b/client/scss/components/_listing.scss index 6d800aaba5..f5a8d44022 100644 --- a/client/scss/components/_listing.scss +++ b/client/scss/components/_listing.scss @@ -365,6 +365,79 @@ ul.listing { @include transition(border-color 0.2s ease); border: 3px solid theme('colors.surface-page'); } + + &--dashboard { + margin-bottom: 0; + + tbody { + border-bottom: 0; + } + + td:first-child { + padding-inline-start: theme('spacing.6'); + } + + td:last-child { + padding-inline-end: theme('spacing.6'); + } + + .title a { + font-weight: theme('fontWeight.medium'); + } + + .w-status--label { + float: inline-end; + font-size: inherit; + } + + .indicator .icon { + padding: 0; + } + + .privacy-indicator { + margin-inline-end: theme('spacing.2'); + + // Adjust icon size to closely match the appearance of the adjacent 'locked' icon + .icon-no-view { + width: 1.1em; + height: 1.1em; + } + } + + .tasks { + text-wrap: nowrap; + } + + .actions li { + float: inline-end; + } + + @include media-breakpoint-down(md) { + display: grid; + + tr { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: theme('spacing.2'); + padding: theme('spacing.5'); + } + + td, + td:first-child, + td:last-child { + padding: 0; + } + + .title { + width: 100%; + } + + .actions-container { + margin-inline-start: auto; + } + } + } } .image-choice { @@ -611,11 +684,12 @@ table.listing { // - no nice padding is applied, // - we're not in a report listing, // - we're not in the editor view, + // - we're not in the dashboard view, // and: // - no bulk actions are present, // - we're not in the "custom ordering" mode, // then apply the same 80px padding via the first column's left padding. - &:not(.nice-padding &, .report &, .editor-view &):not( + &:not(.nice-padding &, .report &, .editor-view &, .w-dashboard &):not( :has( td:first-child input[type='checkbox']:only-child, th:first-child input[type='checkbox']:only-child, diff --git a/client/scss/components/_panel.scss b/client/scss/components/_panel.scss index ffe0361c28..b33a56b571 100644 --- a/client/scss/components/_panel.scss +++ b/client/scss/components/_panel.scss @@ -160,3 +160,26 @@ $header-button-size: theme('spacing.6'); .w-panel__wrapper { @include max-form-width(); } + +.w-panel--dashboard { + background-color: theme('colors.surface-dashboard-panel'); + border: 1px solid theme('colors.border-furniture'); + border-radius: 5px; + margin-bottom: calc( + theme('spacing.4') + theme('spacing.4') * var(--w-density-factor) + ); + + .w-panel__header { + padding: theme('spacing.5'); + margin-inline-start: 0; + + @include media-breakpoint-up(sm) { + margin-inline-start: calc(-1 * theme('spacing.5')); + } + } + + .w-panel__heading { + margin-inline-start: theme('spacing.2'); + white-space: wrap; + } +} diff --git a/client/scss/components/_status-tag.scss b/client/scss/components/_status-tag.scss index 04668865da..6b0e606afb 100644 --- a/client/scss/components/_status-tag.scss +++ b/client/scss/components/_status-tag.scss @@ -19,7 +19,6 @@ &.w-status--primary { color: theme('colors.text-meta'); - border: 1px solid theme('colors.text-meta'); background: theme('colors.surface-page'); } diff --git a/client/scss/components/_summary.scss b/client/scss/components/_summary.scss index ee4b91df14..b14178eb9f 100644 --- a/client/scss/components/_summary.scss +++ b/client/scss/components/_summary.scss @@ -1,69 +1,32 @@ .w-summary { - // set up responsive font size for icon and number as local custom property - --w-summary-item-font-size: clamp( - theme('fontSize.30') * 1.5, - 6.5vw, - calc(theme('fontSize.30') * 3) - ); - color: theme('colors.text-link-default'); - margin-bottom: theme('spacing.8'); - padding-top: theme('spacing.8'); + margin-bottom: theme('spacing.3'); + padding-top: theme('spacing.1'); .w-summary__list { @include unlist(); display: flex; flex-wrap: wrap; - justify-content: space-evenly; - width: 100%; + column-gap: theme('spacing.8'); } /* Summary item */ li { display: flex; align-items: center; - flex: 1 1 auto; flex-wrap: nowrap; + gap: theme('spacing.[2.5]'); margin-bottom: theme('spacing.6'); } - /* Summary icon */ .icon { - font-size: var(--w-summary-item-font-size); - height: 1em; - margin-inline-end: 0.15em; - width: 1em; + @include svg-icon(1.375rem); + color: theme('colors.icon-primary'); } - /* Summary label (a link, use parent colours ) */ a { - color: inherit; - text-align: start; - display: inline-flex; - flex-direction: column; - gap: theme('spacing.[1.5]'); - - @include media-breakpoint-up(sm) { - font-size: theme('fontSize.18'); - } - - /* Summary big number */ - > span { - display: block; - font-size: calc(var(--w-summary-item-font-size) * 0.6); - font-weight: theme('fontWeight.bold'); - line-height: 0.9em; // label underneath to come in tight against the number - } - } -} - -// Media for Windows High Contrast Mode -@media (forced-colors: active) { - .w-summary { - .icon { - color: LinkText; - opacity: 1; - } + text-decoration: underline; + text-underline-offset: 3px; } } diff --git a/client/scss/core.scss b/client/scss/core.scss index fd3b6c837e..51c2750825 100644 --- a/client/scss/core.scss +++ b/client/scss/core.scss @@ -176,7 +176,6 @@ These are classes that provide overrides. @import 'layouts/404'; @import 'layouts/compare-revisions'; -@import 'layouts/home'; @import 'layouts/login'; @import 'layouts/account'; @import 'layouts/workflow-progress'; diff --git a/client/scss/layouts/_home.scss b/client/scss/layouts/_home.scss deleted file mode 100644 index 86f430e72e..0000000000 --- a/client/scss/layouts/_home.scss +++ /dev/null @@ -1,10 +0,0 @@ -.homepage { - .listing tbody { - border-bottom: 0; - } - - .task .icon { - // pull out the icon so it aligns with no-icon text - margin-inline-start: -1.75em; - } -} diff --git a/client/src/tokens/colorThemes.js b/client/src/tokens/colorThemes.js index fbae8dd249..58e65264df 100644 --- a/client/src/tokens/colorThemes.js +++ b/client/src/tokens/colorThemes.js @@ -106,6 +106,18 @@ const light = [ textUtility: 'w-text-surface-status-label', cssVariable: '--w-color-surface-status-label', }, + 'surface-info-panel': { + value: 'var(--w-color-info-50)', + bgUtility: 'w-bg-surface-info-panel', + textUtility: 'w-text-surface-info-panel', + cssVariable: '--w-color-surface-info-panel', + }, + 'surface-dashboard-panel': { + value: 'var(--w-color-white)', + bgUtility: 'w-bg-surface-dashboard-panel', + textUtility: 'w-text-surface-dashboard-panel', + cssVariable: '--w-color-surface-dashboard-panel', + }, }, }, { @@ -201,6 +213,12 @@ const light = [ textUtility: 'w-text-text-status-label', cssVariable: '--w-color-text-status-label', }, + 'text-link-info': { + value: 'var(--w-color-secondary-400)', + bgUtility: 'w-bg-text-link-info', + textUtility: 'w-text-text-link-info', + cssVariable: '--w-color-text-link-info', + }, }, }, { @@ -376,6 +394,18 @@ const dark = [ textUtility: 'w-text-surface-status-label', cssVariable: '--w-color-surface-status-label', }, + 'surface-info-panel': { + value: 'var(--w-color-info-100)', + bgUtility: 'w-bg-surface-info-panel', + textUtility: 'w-text-surface-info-panel', + cssVariable: '--w-color-surface-info-panel', + }, + 'surface-dashboard-panel': { + value: 'var(--w-color-grey-800)', + bgUtility: 'w-bg-surface-dashboard-panel', + textUtility: 'w-text-surface-dashboard-panel', + cssVariable: '--w-color-surface-dashboard-panel', + }, }, }, { @@ -471,6 +501,12 @@ const dark = [ textUtility: 'w-text-text-status-label', cssVariable: '--w-color-text-status-label', }, + 'text-link-info': { + value: 'var(--w-color-grey-50)', + bgUtility: 'w-bg-text-link-info', + textUtility: 'w-text-text-link-info', + cssVariable: '--w-color-text-link-info', + }, }, }, { diff --git a/client/src/tokens/colorVariables.test.js b/client/src/tokens/colorVariables.test.js index 1785ed457a..650dda0a89 100644 --- a/client/src/tokens/colorVariables.test.js +++ b/client/src/tokens/colorVariables.test.js @@ -211,9 +211,11 @@ describe('generateThemeColorVariables', () => { "--w-color-surface-button-hover": "var(--w-color-secondary-400)", "--w-color-surface-button-inactive": "var(--w-color-grey-400)", "--w-color-surface-button-outline-hover": "var(--w-color-secondary-50)", + "--w-color-surface-dashboard-panel": "var(--w-color-white)", "--w-color-surface-field": "var(--w-color-white)", "--w-color-surface-field-inactive": "var(--w-color-grey-50)", "--w-color-surface-header": "var(--w-color-grey-50)", + "--w-color-surface-info-panel": "var(--w-color-info-50)", "--w-color-surface-menu-item-active": "var(--w-color-primary-200)", "--w-color-surface-menus": "var(--w-color-primary)", "--w-color-surface-page": "var(--w-color-white)", @@ -231,6 +233,7 @@ describe('generateThemeColorVariables', () => { "--w-color-text-label-menus-default": "var(--w-color-white-80)", "--w-color-text-link-default": "var(--w-color-secondary)", "--w-color-text-link-hover": "var(--w-color-secondary-400)", + "--w-color-text-link-info": "var(--w-color-secondary-400)", "--w-color-text-meta": "var(--w-color-grey-400)", "--w-color-text-placeholder": "var(--w-color-grey-400)", "--w-color-text-status-label": "var(--w-color-info-100)", @@ -260,9 +263,11 @@ describe('generateThemeColorVariables', () => { "--w-color-surface-button-hover": "var(--w-color-secondary-400)", "--w-color-surface-button-inactive": "var(--w-color-grey-400)", "--w-color-surface-button-outline-hover": "var(--w-color-grey-700)", + "--w-color-surface-dashboard-panel": "var(--w-color-grey-800)", "--w-color-surface-field": "var(--w-color-grey-600)", "--w-color-surface-field-inactive": "var(--w-color-grey-500)", "--w-color-surface-header": "var(--w-color-grey-700)", + "--w-color-surface-info-panel": "var(--w-color-info-100)", "--w-color-surface-menu-item-active": "var(--w-color-grey-700)", "--w-color-surface-menus": "var(--w-color-grey-800)", "--w-color-surface-page": "var(--w-color-grey-600)", @@ -280,6 +285,7 @@ describe('generateThemeColorVariables', () => { "--w-color-text-label-menus-default": "var(--w-color-white-80)", "--w-color-text-link-default": "var(--w-color-secondary-100)", "--w-color-text-link-hover": "var(--w-color-secondary-75)", + "--w-color-text-link-info": "var(--w-color-grey-50)", "--w-color-text-meta": "var(--w-color-grey-150)", "--w-color-text-placeholder": "var(--w-color-grey-200)", "--w-color-text-status-label": "var(--w-color-info-75)", diff --git a/client/tests/integration/homepage.test.js b/client/tests/integration/homepage.test.js index 80d48d3a35..71e4e6c2b3 100644 --- a/client/tests/integration/homepage.test.js +++ b/client/tests/integration/homepage.test.js @@ -10,7 +10,7 @@ describe('Homepage', () => { it('has the right heading', async () => { const pageHeader = await page.$('h1'); const pageHeaderValue = await pageHeader.evaluate((el) => el.textContent); - expect(pageHeaderValue).toContain('Welcome to the Test Site Wagtail CMS'); + expect(pageHeaderValue).toContain('Test Site'); }); it('axe', async () => { diff --git a/docs/releases/6.3.md b/docs/releases/6.3.md index 6f279e838d..d5db48b72f 100644 --- a/docs/releases/6.3.md +++ b/docs/releases/6.3.md @@ -19,6 +19,13 @@ This release adds formal support for Python 3.13. This release adds formal support for Django 5.1. +### Incremental dashboard enhancements + +The Wagtail dashboard design evolves towards providing more information and navigation features. Mobile support is much improved. + +This feature was developed by Albina Starykova based on designs by Ben Enright. + + ### Other features * Formalize support for MariaDB (Sage Abdullah, Daniel Black) @@ -154,3 +161,11 @@ If access to JSON locales within JavaScript is needed, use `window.wagtailConfig The undocumented `js_translation_strings` template tag will be removed in a future release. If access to JSON translation strings within JavaScript is needed, use `window.wagtailConfig.STRINGS` instead. + +### `UpgradeNotificationPanel` is no longer removable with `construct_homepage_panels` hook + +The upgrade notification panel can still be removed with the [`WAGTAIL_ENABLE_UPDATE_CHECK = False`](update_notifications) setting. + +### `SiteSummaryPanel` is no longer removable with `construct_homepage_panels`hook + +The summary items can still be removed with the [`construct_homepage_summary_items`](construct_homepage_summary_items) hook. diff --git a/wagtail/admin/site_summary.py b/wagtail/admin/site_summary.py index 0230e47de4..b4671530b1 100644 --- a/wagtail/admin/site_summary.py +++ b/wagtail/admin/site_summary.py @@ -55,9 +55,7 @@ class PagesSummaryItem(SummaryItem): class SiteSummaryPanel(Component): - name = "site_summary" template_name = "wagtailadmin/home/site_summary.html" - order = 100 def __init__(self, request): self.request = request diff --git a/wagtail/admin/templates/wagtailadmin/home.html b/wagtail/admin/templates/wagtailadmin/home.html index 28a8a4f397..ae65ddd592 100644 --- a/wagtail/admin/templates/wagtailadmin/home.html +++ b/wagtail/admin/templates/wagtailadmin/home.html @@ -1,6 +1,5 @@ {% extends "wagtailadmin/generic/base.html" %} {% load wagtailadmin_tags i18n %} -{% block bodyclass %}homepage{% endblock %} {% block extra_css %} {{ block.super }} @@ -9,14 +8,32 @@ {% block content %} {% fragment as header_title %} - {% block branding_welcome %}{% blocktrans trimmed %}Welcome to the {{ site_name }} Wagtail CMS{% endblocktrans %}{% endblock %} + {% block branding_welcome %}{{ site_name|title }}{% endblock %} {% endfragment %} + {% component upgrade_notification %} + <div class="w-dashboard w-px-6 sm:w-px-[3.75rem] w-mt-16 sm:w-mt-10 lg:w-mt-[3.75rem]"> + <header class="w-flex w-flex-col lg:w-flex-row"> + <div class="lg:w-pr-20 lg:w-grow"> + <h1 class="w-h1 w-mt-0">{{ header_title }}</h1> + {% component site_summary %} - <div class="nice-padding w-mt-14"> - {% avatar_url user 70 as avatar %} - {% include "wagtailadmin/shared/header.html" with title=header_title description=user|user_display_name avatar=avatar merged=1 %} + <form + class="w-mb-12" + action="{% if root_page.pk %}{% url 'wagtailadmin_explore' root_page.pk %}{% else %}{% url 'wagtailadmin_explore_root' %}{% endif %}" + method="get" + novalidate + role="search" + > + {% for field in search_form %} + {% formattedfield field=field sr_only_label=True icon="search" %} + {% endfor %} + <div class="submit w-sr-only"><input type="submit" value="Search" class="button" /></div> + </form> + </div> + {% include "wagtailadmin/home/account_summary.html" %} + </header> {% if panels %} {% for panel in panels %} {% component panel fallback_render_method=True %} diff --git a/wagtail/admin/templates/wagtailadmin/home/account_summary.html b/wagtail/admin/templates/wagtailadmin/home/account_summary.html new file mode 100644 index 0000000000..a4d6cf1c71 --- /dev/null +++ b/wagtail/admin/templates/wagtailadmin/home/account_summary.html @@ -0,0 +1,26 @@ +{% load wagtailadmin_tags wagtailcore_tags i18n %} +<div class="w-hidden lg:w-flex w-gap-5 w-pt-4 w-mb-[3.5rem] w-px-[3.75rem] w-border-l w-border-border-furniture"> + {% avatar user size="large" edit_link=True %} + <div> + <h2 class="w-label-1 w-mt-0 w-mb-1">{{ user|user_display_name }}</h2> + <ul class="w-list-none w-p-0 w-m-0 w-flex w-flex-col w-gap-1"> + <li> + <a class="w-underline w-underline-offset-[3px]" + href="{% url 'wagtailadmin_account' %}">{% trans 'Account' %}</a> + </li> + {% wagtail_feature_release_editor_guide_link as editor_guide_link %} + {% wagtail_version as current_version %} + <li> + <a class="w-underline w-underline-offset-[3px] w-flex w-items-center w-gap-1" + href="{{ editor_guide_link }}" + target="_blank" + rel="noreferrer"> + {% blocktrans trimmed %} + Wagtail {{ current_version }} editor guide + {% endblocktrans %} + {% icon name="link-external" classname="initial" %} + </a> + </li> + </ul> + </div> +</div> diff --git a/wagtail/admin/templates/wagtailadmin/home/locked_pages.html b/wagtail/admin/templates/wagtailadmin/home/locked_pages.html index daa7791247..e6e8ff9fdb 100644 --- a/wagtail/admin/templates/wagtailadmin/home/locked_pages.html +++ b/wagtail/admin/templates/wagtailadmin/home/locked_pages.html @@ -1,34 +1,46 @@ {% load i18n wagtailadmin_tags %} {% load wagtailcore_tags %} {% if locked_pages %} - {% panel id="locked-pages" heading=_("Your locked pages") %} - <table class="listing listing-page"> + {% panel id="locked-pages" heading=_("Your locked pages") classname="w-panel--dashboard" %} + <table class="listing listing--dashboard listing-page"> <col /> - <col width="30%"/> - <col width="15%"/> - - <thead> + <col width="10%"/> + <col width="7%"/> + <col width="25%"/> + <col width="10%"/> + <col width="10%"/> + <thead class="w-sr-only"> <tr> <th class="title">{% trans "Title" %}</th> - <th aria-hidden="true">{% comment %} added for visual alignment only {% endcomment %}</th> + <th>{% trans "Language" %}</th> + <th>{% trans "Privacy and access" %}</th> + <th>{% trans "Status" %}</th> <th>{% trans "Locked at" %}</th> + <th aria-hidden="true">{% comment %} added for visual alignment only {% endcomment %}</th> </tr> </thead> <tbody> {% for page in locked_pages %} <tr> - <td class="title" valign="top"> + <td class="title"> <div class="title-wrapper"> <a href="{% url 'wagtailadmin_pages:edit' page.id %}" title="{% trans 'Edit this page' %}">{{ page.get_admin_display_title }}</a> - - {% i18n_enabled as show_locale_labels %} - {% if show_locale_labels and page.locale_id %} - {% locale_label_from_id page.locale_id as locale_label %} - {% status locale_label classname="w-status--label" %} - {% endif %} - {% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=page %} - {% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=page %} </div> + </td> + <td> + {% i18n_enabled as show_locale_labels %} + {% if show_locale_labels and page.locale_id %} + {% locale_label_from_id page.locale_id as locale_label %} + {% status locale_label classname="w-status--label" %} + {% endif %} + </td> + <td> + {% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=page %} + {% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=page %} + </td> + <td>{% include "wagtailadmin/shared/page_status_tag.html" with page=page %}</td> + <td>{% human_readable_date page.locked_at %}</td> + <td class="actions-container"> <ul class="actions"> <li> {% dropdown toggle_icon="dots-horizontal" toggle_aria_label=_("Actions") %} @@ -56,8 +68,6 @@ </li> </ul> </td> - <td>{# Deliberately empty #}</td> - <td valign="top">{% human_readable_date page.locked_at %}</td> </tr> {% endfor %} </tbody> diff --git a/wagtail/admin/templates/wagtailadmin/home/recent_edits.html b/wagtail/admin/templates/wagtailadmin/home/recent_edits.html index 577067a203..2ee281e02a 100644 --- a/wagtail/admin/templates/wagtailadmin/home/recent_edits.html +++ b/wagtail/admin/templates/wagtailadmin/home/recent_edits.html @@ -2,33 +2,48 @@ {% load wagtailcore_tags %} {% load i18n wagtailadmin_tags %} {% if last_edits %} - {% panel id="recent-edits" heading=_("Your most recent edits") %} - <table class="listing listing-page"> + {% panel id="recent-edits" heading=_("Your most recent edits") classname="w-panel--dashboard" %} + <table class="listing listing--dashboard listing-page"> <col /> - <col width="30%"/> - <col width="15%"/> + <col width="10%"/> + <col width="7%"/> + <col width="25%"/> + <col width="10%"/> + <col width="10%"/> <thead class="w-sr-only"> <tr> <th class="title">{% trans "Title" %}</th> + <th>{% trans "Language" %}</th> + <th>{% trans "Privacy and access" %}</th> <th>{% trans "Status" %}</th> <th>{% trans "Date" %}</th> + <th aria-hidden="true">{% comment %} added for visual alignment only {% endcomment %}</th> </tr> </thead> <tbody> {% for last_edited_at, page in last_edits %} <tr> - <td class="title" valign="top"> + <td class="title"> <div class="title-wrapper"> <a href="{% url 'wagtailadmin_pages:edit' page.id %}" title="{% trans 'Edit this page' %}">{{ page.get_admin_display_title }}</a> - - {% i18n_enabled as show_locale_labels %} - {% if show_locale_labels and page.locale_id %} - {% locale_label_from_id page.locale_id as locale_label %} - {% status locale_label classname="w-status--label" %} - {% endif %} - {% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=page %} - {% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=page %} </div> + </td> + <td> + {% i18n_enabled as show_locale_labels %} + {% if show_locale_labels and page.locale_id %} + {% locale_label_from_id page.locale_id as locale_label %} + {% status locale_label classname="w-status--label" %} + {% endif %} + </td> + <td> + {% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=page %} + {% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=page %} + </td> + <td> + {% include "wagtailadmin/shared/page_status_tag.html" with page=page %} + </td> + <td>{% human_readable_date last_edited_at %}</td> + <td class="actions-container"> <ul class="actions"> <li> {% dropdown toggle_icon="dots-horizontal" toggle_aria_label=_("Actions") %} @@ -46,10 +61,6 @@ </li> </ul> </td> - <td valign="top"> - {% include "wagtailadmin/shared/page_status_tag.html" with page=page %} - </td> - <td valign="top">{% human_readable_date last_edited_at %}</td> </tr> {% endfor %} </tbody> diff --git a/wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html b/wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html index f875701de7..106641baa8 100644 --- a/wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html +++ b/wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html @@ -4,9 +4,9 @@ {% icon name="doc-empty" %} <a href="{% url 'wagtailadmin_explore' root_page.pk %}"> {% blocktrans trimmed count counter=total_pages with total_pages|intcomma as total %} - <span>{{ total }}</span> Page <span class="w-sr-only">created in {{ site_name }}</span> + {{ total }} Page <span class="w-sr-only">created in {{ site_name }}</span> {% plural %} - <span>{{ total }}</span> Pages <span class="w-sr-only">created in {{ site_name }}</span> + {{ total }} Pages <span class="w-sr-only">created in {{ site_name }}</span> {% endblocktrans %} </a> </li> diff --git a/wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html b/wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html index 143f865fe1..eb0ca28c25 100644 --- a/wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html +++ b/wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html @@ -1,17 +1,20 @@ {% load i18n wagtailcore_tags wagtailadmin_tags %} {% wagtail_version as current_version %} -<div - class="w-panel-upgrade panel w-hidden" - data-controller="w-upgrade" - data-w-upgrade-current-version-value="{{ current_version }}" - {% if lts_only %}data-w-upgrade-lts-only-value="true"{% endif %} - data-w-upgrade-hidden-class="w-hidden" -> - <div class="help-block help-warning"> - {% icon name='warning' %} - {% blocktrans trimmed %} - Wagtail upgrade available. Your version: <strong>{{ current_version }}</strong>. New version: <strong data-w-upgrade-target="latestVersion"></strong>. - {% endblocktrans %} - <a href="" data-w-upgrade-target="link">{% trans "Read the release notes." %}</a> +<div class="w-panel-upgrade w-hidden w-flex w-mb-[-2rem] sm:w-mb-0 w-gap-5 w-items-center w-pl-slim-header w-pr-5 sm:w-px-[3.5rem] w-py-5 w-text-text-context w-bg-surface-info-panel w-border-b w-border-transparent" + data-controller="w-upgrade" + data-w-upgrade-current-version-value="{{ current_version }}" + {% if lts_only %}data-w-upgrade-lts-only-value="true"{% endif %} + data-w-upgrade-hidden-class="w-hidden"> + {% icon name='info-circle' classname='w-w-5 w-h-5 w-shrink-0 w-text-text-link-info w-ml-5 sm:w-ml-0' %} + <div> + <p class="w-mb-1"><strong>{% trans "Wagtail upgrade available" %}</strong></p> + <p class="w-mb-0"> + {% blocktrans trimmed %} + Your version: <strong>{{ current_version }}</strong>. New version: <strong data-w-upgrade-target="latestVersion"></strong>. + {% endblocktrans %} + <a href="" + data-w-upgrade-target="link" + class="w-text-text-link-info hover:w-text-text-link-info w-underline w-underline-offset-[3px]">{% trans "Read the release notes." %}</a> + </p> </div> </div> diff --git a/wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html b/wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html index 121a842b66..c6eb189571 100644 --- a/wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html +++ b/wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html @@ -2,16 +2,22 @@ {% load i18n wagtailadmin_tags %} {% if workflow_states %} - {% panel id="objects-in-workflow" heading=_("Your pages and snippets in a workflow") %} - <table class="listing"> + {% panel id="objects-in-workflow" heading=_("Your pages and snippets in a workflow") classname="w-panel--dashboard" %} + <table class="listing listing--dashboard"> <col /> - <col width="30%"/> - <col width="15%"/> + <col width="10%"/> + <col width="7%"/> + <col width="25%"/> + <col width="10%"/> + <col width="10%"/> <thead class="w-sr-only"> <tr> <th class="title">{% trans "Title" %}</th> + <th>{% trans "Language" %}</th> + <th>{% trans "Privacy and access" %}</th> <th>{% trans "Task" %}</th> <th>{% trans "Task started" %}</th> + <th aria-hidden="true">{% comment %} added for visual alignment only {% endcomment %}</th> </tr> </thead> <tbody> @@ -22,7 +28,7 @@ {% page_permissions obj as page_perms %} {% endif %} <tr> - <td class="title" valign="top"> + <td class="title"> <div class="title-wrapper"> {% admin_edit_url obj as edit_url %} {% if page_perms.can_edit or not is_page and edit_url %} @@ -30,28 +36,32 @@ {% else %} {% latest_str obj %} {% endif %} - - {% i18n_enabled as show_locale_labels %} - {% if show_locale_labels and obj.locale_id %} - {% locale_label_from_id obj.locale_id as locale_label %} - {% status locale_label classname="w-status--label" %} - {% endif %} - {% if is_page %} - {% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=obj %} - {% endif %} - {% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=obj %} </div> </td> - <td class="task" valign="top"> + <td> + {% i18n_enabled as show_locale_labels %} + {% if show_locale_labels and obj.locale_id %} + {% locale_label_from_id obj.locale_id as locale_label %} + {% status locale_label classname="w-status--label" %} + {% endif %} + </td> + <td> + {% if is_page %} + {% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=obj %} + {% endif %} + {% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=obj %} + </td> + <td class="task"> {% if workflow_state.current_task_state.status == 'rejected' %} - {% icon name="warning" classname="default" %} + {% icon name="warning" classname="w-h-4 w-w-4 w-align-text-top" %} {% trans "Changes requested at" %} {% elif workflow_state.current_task_state.status == 'in_progress' %} {% trans "Awaiting" %} {% endif %} {{ workflow_state.current_task_state.task.name }} </td> - <td valign="top">{% human_readable_date workflow_state.current_task_state.started_at %}</td> + <td>{% human_readable_date workflow_state.current_task_state.started_at %}</td> + <td>{# Deliberately empty #}</td> </tr> {% endwith %} {% endfor %} diff --git a/wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html b/wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html index 387f19e1ca..c3d55000f5 100644 --- a/wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html +++ b/wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html @@ -1,17 +1,23 @@ {% load i18n wagtailadmin_tags %} {% if states %} - {% panel id="awaiting-review" heading=_("Awaiting your review") %} - <table class="listing"> + {% panel id="awaiting-review" heading=_("Awaiting your review") classname="w-panel--dashboard" %} + <table class="listing listing--dashboard"> <col /> + <col width="10%"/> + <col width="7%"/> + <col width="10%"/> <col width="15%"/> - <col width="15%"/> - <col width="15%"/> + <col width="10%"/> + <col width="10%"/> <thead class="w-sr-only"> <tr> <th class="title">{% trans "Title" %}</th> + <th>{% trans "Language" %}</th> + <th>{% trans "Privacy and access" %}</th> <th>{% trans "Tasks" %}</th> <th>{% trans "Task submitted by" %}</th> <th>{% trans "Task started" %}</th> + <th aria-hidden="true">{% comment %} added for visual alignment only {% endcomment %}</th> </tr> </thead> <tbody> @@ -22,7 +28,7 @@ {% page_permissions obj as page_perms %} {% endif %} <tr> - <td class="title" valign="top"> + <td class="title"> <div class="title-wrapper"> {% admin_edit_url obj as edit_url %} {% if page_perms.can_edit or not is_page and edit_url %} @@ -30,17 +36,39 @@ {% else %} {% latest_str obj %} {% endif %} - - {% i18n_enabled as show_locale_labels %} - {% if show_locale_labels and obj.locale_id %} - {% locale_label_from_id obj.locale_id as locale_label %} - {% status locale_label classname="w-status--label" %} - {% endif %} - {% if is_page %} - {% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=obj %} - {% endif %} - {% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=obj %} </div> + </td> + <td> + {% i18n_enabled as show_locale_labels %} + {% if show_locale_labels and obj.locale_id %} + {% locale_label_from_id obj.locale_id as locale_label %} + {% status locale_label classname="w-status--label" %} + {% endif %} + </td> + <td> + {% if is_page %} + {% include "wagtailadmin/pages/listing/_privacy_indicator.html" with page=obj %} + {% endif %} + {% include "wagtailadmin/pages/listing/_locked_indicator.html" with page=obj %} + </td> + <td class="tasks"> + {% for task in workflow_tasks %} + <span data-controller="w-tooltip" data-w-tooltip-content-value="{{ task.name }}: {{ task.status_display }}"> + {% if task.status == 'approved' %} + {% icon "success" title=task.status_display classname="default" %} + {% elif task.status == 'rejected' %} + {% icon "error" title=task.status_display classname="default" %} + {% else %} + {% icon "radio-empty" title=status_display classname="default" %} + {% endif %} + </span> + {% endfor %} + </td> + <td> + {% if revision.user %}{{ revision.user|user_display_name }}{% endif %} + </td> + <td>{% human_readable_date task_state.started_at %}</td> + <td class="actions-container"> {% if actions %} <ul class="actions"> <li> @@ -65,23 +93,6 @@ </ul> {% endif %} </td> - <td class="tasks" valign="top"> - {% for task in workflow_tasks %} - <span data-controller="w-tooltip" data-w-tooltip-content-value="{{ task.name }}: {{ task.status_display }}"> - {% if task.status == 'approved' %} - {% icon "success" title=task.status_display classname="default" %} - {% elif task.status == 'rejected' %} - {% icon "error" title=task.status_display classname="default" %} - {% else %} - {% icon "radio-empty" title=status_display classname="default" %} - {% endif %} - </span> - {% endfor %} - </td> - <td valign="top"> - {% if revision.user %}{{ revision.user|user_display_name }}{% endif %} - </td> - <td valign="top">{% human_readable_date task_state.started_at %}</td> </tr> {% endwith %} {% endfor %} diff --git a/wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html b/wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html index 6964d6b60d..e1a062aadb 100644 --- a/wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html +++ b/wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html @@ -8,7 +8,7 @@ {% if page.locked %} <span - class="indicator locked-indicator {% if page.locked_by_id == request.user.pk %}indicator--is-inverse{% endif %}" + class="indicator {% if page.locked_by_id != request.user.pk %}indicator--is-dimmed{% endif %}" title="{% if page.locked_by_id == request.user.pk %}{% trans 'This page is locked, by you, to further editing' %}{% else %}{% trans 'This page is locked to further editing' %}{% endif %}" > {% icon name="lock" classname="initial" %} diff --git a/wagtail/admin/templates/wagtailadmin/shared/avatar.html b/wagtail/admin/templates/wagtailadmin/shared/avatar.html index 4279eb64c1..82d59528f5 100644 --- a/wagtail/admin/templates/wagtailadmin/shared/avatar.html +++ b/wagtail/admin/templates/wagtailadmin/shared/avatar.html @@ -1,4 +1,4 @@ -{% load wagtailadmin_tags %} +{% load i18n wagtailadmin_tags %} {% comment "text/markdown" %} Displays a user avatar using the avatar template Variables this template accepts: @@ -8,9 +8,10 @@ - `size` (string?) - small, large, square - `tooltip` (string?) - Modifier classes - `tooltip_html` (string?) - An HTML element to use for the tooltip content + - `edit_link` (boolean?) - Edit link to display underneath the avatar {% endcomment %} <span - class="{% classnames 'avatar' size classname %}" + class="{% classnames 'avatar' size classname edit_link|yesno:"avatar--edit," %}" {% if tooltip or tooltip_html %} data-controller="w-tooltip" {% endif %} {% if tooltip %} data-w-tooltip-content-value="{{ tooltip }}" {% endif %} > @@ -22,10 +23,19 @@ {% if size == 'small' %} <img src="{% avatar_url user size=25 %}" alt="" decoding="async" loading="lazy"/> {% elif size == 'large' %} - <img src="{% avatar_url user size=100 %}" alt="" decoding="async" loading="lazy"/> + <img src="{% avatar_url user size=80 %}" alt="" decoding="async" loading="lazy"/> {% elif size == 'square' %} <img src="{% avatar_url user %}" alt="" decoding="async" loading="lazy"/> {% else %} <img src="{% avatar_url user %}" alt="" decoding="async" loading="lazy"/> {% endif %} + {% if edit_link %} + <a + class="avatar__edit-link" + aria-label="{% trans 'Edit account avatar' %}" + href="{% url 'wagtailadmin_account' %}#avatar-section" + > + {% icon name="edit" %} + </a> + {% endif %} </span> diff --git a/wagtail/admin/templates/wagtailadmin/shared/header.html b/wagtail/admin/templates/wagtailadmin/shared/header.html index 74994273c7..8f24006568 100644 --- a/wagtail/admin/templates/wagtailadmin/shared/header.html +++ b/wagtail/admin/templates/wagtailadmin/shared/header.html @@ -6,7 +6,6 @@ - `classname` - if present, adds classname to the header class list - `title` - Displayed as `h1` - `subtitle` - Within the `h1` tag but smaller - - `description` - if present, displayed as a small text below the `h1` tag title - `search_url` - if present, display a search box. This is a URL route name (taking no parameters) to be used as the action for that search box - `search_form` - form object for the search form. Required if search_url is passed - `search_results_url` - URL to be used for async requests to search results, if not provided, the form's action URL will be used @@ -14,7 +13,6 @@ - `search_disable_async` - If True, the default header async search functionality will not be used - `query_parameters` - a query string (without the '?') to be placed after the search URL - `icon` - name of an icon to place against the title - - `avatar` - if present, display an 'avatar' in place of icon. This is the URL to be used as the img src for avatar - `merged` - if true, add the classname 'w-header--merged' - `action_url` - if present, display an 'action' button. This is the URL to be used as the link URL for the button - `action_text` - text for the 'action' button @@ -36,13 +34,10 @@ <h1 class="w-header__title" id="header-title"> {% if icon %} {% icon classname="w-header__glyph" name=icon %} - {% elif avatar %} - <div class="w-header__glyph avatar large"><img src="{{ avatar }}" alt="" /></div> {% endif %} {{ title }}{% if subtitle %} <span class="w-header__subtitle">{{ subtitle }}</span>{% endif %} </h1> {% endif %} - {% if description %}<div class="w-header__description">{{ description }}</div>{% endif %} </div> {% if search_url %} <form diff --git a/wagtail/admin/templatetags/wagtailadmin_tags.py b/wagtail/admin/templatetags/wagtailadmin_tags.py index 69320f93a5..fee4babce2 100644 --- a/wagtail/admin/templatetags/wagtailadmin_tags.py +++ b/wagtail/admin/templatetags/wagtailadmin_tags.py @@ -585,7 +585,14 @@ def bulk_action_choices(context, app_label, model_name): @register.inclusion_tag("wagtailadmin/shared/avatar.html") -def avatar(user=None, classname=None, size=None, tooltip=None, tooltip_html=None): +def avatar( + user=None, + classname=None, + size=None, + tooltip=None, + tooltip_html=None, + edit_link=False, +): """ Displays a user avatar using the avatar template Usage: @@ -596,6 +603,7 @@ def avatar(user=None, classname=None, size=None, tooltip=None, tooltip_html=None :param size: default None (None|'small'|'large'|'square') :param tooltip: Optional tooltip to display under the avatar (string) :param tooltip_html: Optional tooltip as an HTML element for rich content (string) + :param edit_link: Optional edit link to display underneath the avatar (boolean) :return: Rendered template snippet """ return { @@ -604,6 +612,7 @@ def avatar(user=None, classname=None, size=None, tooltip=None, tooltip_html=None "size": size, "tooltip": tooltip, "tooltip_html": tooltip_html, + "edit_link": edit_link, } diff --git a/wagtail/admin/tests/pages/test_explorer_view.py b/wagtail/admin/tests/pages/test_explorer_view.py index 55bebf9497..35d54686e6 100644 --- a/wagtail/admin/tests/pages/test_explorer_view.py +++ b/wagtail/admin/tests/pages/test_explorer_view.py @@ -1245,7 +1245,7 @@ class TestExplorablePageVisibility(WagtailTestUtils, TestCase): response = self.client.get(reverse("wagtailadmin_home")) self.assertEqual(response.status_code, 200) # Bob should only see the welcome for example.com, not testserver - self.assertContains(response, "Welcome to the example.com Wagtail CMS") + self.assertContains(response, "example.com") self.assertNotContains(response, "testserver") def test_breadcrumb_with_no_user_permissions(self): diff --git a/wagtail/admin/tests/test_dashboard.py b/wagtail/admin/tests/test_dashboard.py index e95d6a80a5..723182f322 100644 --- a/wagtail/admin/tests/test_dashboard.py +++ b/wagtail/admin/tests/test_dashboard.py @@ -229,7 +229,7 @@ class TestLockedPagesQueryCount(WagtailTestUtils, TestCase): # Warm up the cache html = panel.render_html(parent_context) - with self.assertNumQueries(1): + with self.assertNumQueries(7): html = panel.render_html(parent_context) soup = self.get_soup(html) # Should be sorted descending by locked_at diff --git a/wagtail/admin/tests/test_reports_views.py b/wagtail/admin/tests/test_reports_views.py index 820f4f8102..fdb0f9927e 100644 --- a/wagtail/admin/tests/test_reports_views.py +++ b/wagtail/admin/tests/test_reports_views.py @@ -194,7 +194,7 @@ class TestLockedPagesView(BaseReportViewTestCase): self.assertActiveFilterNotRendered(soup) # Locked by current user shown in indicator - self.assertContains(response, "locked-indicator indicator--is-inverse") + self.assertNotContains(response, "indicator--is-dimmed") self.assertContains( response, 'title="This page is locked, by you, to further editing"' ) diff --git a/wagtail/admin/tests/test_site_summary.py b/wagtail/admin/tests/test_site_summary.py index b77a2924ec..a6a7cb9fb2 100644 --- a/wagtail/admin/tests/test_site_summary.py +++ b/wagtail/admin/tests/test_site_summary.py @@ -57,11 +57,11 @@ class TestPagesSummary(WagtailTestUtils, TestCase): self.assertSummaryContainsLinkToPage(self.wagtail_root.pk) def test_summary_includes_page_count_without_wagtail_root(self): - self.assertSummaryContains(f"<span>{Page.objects.count() - 1}</span> Pages") + self.assertSummaryContains(f"{Page.objects.count() - 1} Pages") def test_summary_shows_zero_pages_if_none_exist_except_wagtail_root(self): Page.objects.exclude(pk=self.wagtail_root.pk).delete() - self.assertSummaryContains("<span>0</span> Pages") + self.assertSummaryContains("0 Pages") def test_user_with_no_page_permissions_is_not_shown_panel(self): self.user.is_superuser = False @@ -78,4 +78,4 @@ class TestPagesSummary(WagtailTestUtils, TestCase): self.user.is_superuser = False self.user.save() self.user.groups.add(self.test_page_group) - self.assertSummaryContains("<span>1</span> Page") + self.assertSummaryContains("1 Page") diff --git a/wagtail/admin/tests/tests.py b/wagtail/admin/tests/tests.py index 13674fe276..88eb0d4486 100644 --- a/wagtail/admin/tests/tests.py +++ b/wagtail/admin/tests/tests.py @@ -29,7 +29,7 @@ class TestHome(WagtailTestUtils, TestCase): def test_simple(self): response = self.client.get(reverse("wagtailadmin_home")) self.assertEqual(response.status_code, 200) - self.assertContains(response, "Welcome to the Test Site Wagtail CMS") + self.assertContains(response, "Test Site") def test_admin_menu(self): response = self.client.get(reverse("wagtailadmin_home")) diff --git a/wagtail/admin/views/home.py b/wagtail/admin/views/home.py index b88a6b0c75..05312501d1 100644 --- a/wagtail/admin/views/home.py +++ b/wagtail/admin/views/home.py @@ -8,10 +8,11 @@ from django.db.models import Exists, IntegerField, Max, OuterRef, Q from django.db.models.functions import Cast from django.forms import Media from django.http import Http404, HttpResponse -from django.utils.translation import gettext_lazy +from django.utils.translation import gettext_lazy as _ from django.views.generic.base import TemplateView from wagtail import hooks +from wagtail.admin.forms.search import SearchForm from wagtail.admin.icons import get_icons from wagtail.admin.navigation import get_site_for_user from wagtail.admin.site_summary import SiteSummaryPanel @@ -34,9 +35,7 @@ User = get_user_model() class UpgradeNotificationPanel(Component): - name = "upgrade_notification" template_name = "wagtailadmin/home/upgrade_notification.html" - order = 100 def get_upgrade_check_setting(self) -> Union[bool, str]: return getattr(settings, "WAGTAIL_ENABLE_UPDATE_CHECK", True) @@ -283,15 +282,20 @@ class RecentEditsPanel(Component): class HomeView(WagtailAdminTemplateMixin, TemplateView): template_name = "wagtailadmin/home.html" - page_title = gettext_lazy("Dashboard") + page_title = _("Dashboard") + permission_policy = page_permission_policy def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) panels = self.get_panels() + site_summary = SiteSummaryPanel(self.request) site_details = self.get_site_details() - context["media"] = self.get_media(panels) + context["media"] = self.get_media([*panels, site_summary]) context["panels"] = sorted(panels, key=lambda p: p.order) + context["site_summary"] = site_summary + context["upgrade_notification"] = UpgradeNotificationPanel() + context["search_form"] = SearchForm(placeholder=_("Search all pages…")) context["user"] = self.request.user return {**context, **site_details} @@ -307,10 +311,8 @@ class HomeView(WagtailAdminTemplateMixin, TemplateView): def get_panels(self): request = self.request panels = [ - SiteSummaryPanel(request), # Disabled until a release warrants the banner. # WhatsNewInWagtailVersionPanel(), - UpgradeNotificationPanel(), WorkflowObjectsToModeratePanel(), UserObjectsInWorkflowModerationPanel(), RecentEditsPanel(), diff --git a/wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html b/wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html index bfedb4f814..3a47052aae 100644 --- a/wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html +++ b/wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html @@ -4,9 +4,9 @@ {% icon name="doc-full" %} <a href="{% url 'wagtaildocs:index' %}"> {% blocktrans trimmed count counter=total_docs with total_docs|intcomma as total %} - <span>{{ total }}</span> Document <span class="w-sr-only">created in {{ site_name }}</span> + {{ total }} Document <span class="w-sr-only">created in {{ site_name }}</span> {% plural %} - <span>{{ total }}</span> Documents <span class="w-sr-only">created in {{ site_name }}</span> + {{ total }} Documents <span class="w-sr-only">created in {{ site_name }}</span> {% endblocktrans %} </a> </li> diff --git a/wagtail/documents/tests/test_site_summary.py b/wagtail/documents/tests/test_site_summary.py index 762e691ea1..8a87a95bcc 100644 --- a/wagtail/documents/tests/test_site_summary.py +++ b/wagtail/documents/tests/test_site_summary.py @@ -122,9 +122,9 @@ class TestDocumentsSummary(WagtailTestUtils, TestCase): def test_user_sees_proper_doc_count(self): cases = ( - (self.superuser, "<span>3</span> Documents"), - (self.report_adder, "<span>2</span> Documents"), - (self.report_chooser, "<span>2</span> Documents"), + (self.superuser, "3 Documents"), + (self.report_adder, "2 Documents"), + (self.report_chooser, "2 Documents"), ) for user, content in cases: with self.subTest(user=user): diff --git a/wagtail/images/templates/wagtailimages/homepage/site_summary_images.html b/wagtail/images/templates/wagtailimages/homepage/site_summary_images.html index 40b384bdfa..b3156ba7ae 100644 --- a/wagtail/images/templates/wagtailimages/homepage/site_summary_images.html +++ b/wagtail/images/templates/wagtailimages/homepage/site_summary_images.html @@ -4,9 +4,9 @@ {% icon name="image" %} <a href="{% url 'wagtailimages:index' %}"> {% blocktrans trimmed count counter=total_images with total_images|intcomma as total %} - <span>{{ total }}</span> Image <span class="w-sr-only">created in {{ site_name }}</span> + {{ total }} Image <span class="w-sr-only">created in {{ site_name }}</span> {% plural %} - <span>{{ total }}</span> Images <span class="w-sr-only">created in {{ site_name }}</span> + {{ total }} Images <span class="w-sr-only">created in {{ site_name }}</span> {% endblocktrans %} </a> </li> diff --git a/wagtail/images/tests/test_site_summary.py b/wagtail/images/tests/test_site_summary.py index b23c182590..06435f0db4 100644 --- a/wagtail/images/tests/test_site_summary.py +++ b/wagtail/images/tests/test_site_summary.py @@ -126,9 +126,9 @@ class TestImagesSummary(WagtailTestUtils, TestCase): def test_user_sees_proper_image_count(self): cases = ( - (self.superuser, "<span>3</span> Images"), - (self.bird_adder, "<span>2</span> Images"), - (self.bird_chooser, "<span>2</span> Images"), + (self.superuser, "3 Images"), + (self.bird_adder, "2 Images"), + (self.bird_chooser, "2 Images"), ) for user, content in cases: with self.subTest(user=user):