浏览代码

Incremental dashboard enhancements. Fix #12089 (#12233)

Co-authored-by: Thibaud Colas <thibaudcolas@gmail.com>
Albina 5 月之前
父节点
当前提交
9a7427a589
共有 37 个文件被更改,包括 456 次插入248 次删除
  1. 1 0
      CHANGELOG.txt
  2. 35 2
      client/scss/components/_avatar.scss
  3. 0 19
      client/scss/components/_header.scss
  4. 13 27
      client/scss/components/_indicator.scss
  5. 75 1
      client/scss/components/_listing.scss
  6. 23 0
      client/scss/components/_panel.scss
  7. 0 1
      client/scss/components/_status-tag.scss
  8. 8 45
      client/scss/components/_summary.scss
  9. 0 1
      client/scss/core.scss
  10. 0 10
      client/scss/layouts/_home.scss
  11. 36 0
      client/src/tokens/colorThemes.js
  12. 6 0
      client/src/tokens/colorVariables.test.js
  13. 1 1
      client/tests/integration/homepage.test.js
  14. 15 0
      docs/releases/6.3.md
  15. 0 2
      wagtail/admin/site_summary.py
  16. 22 5
      wagtail/admin/templates/wagtailadmin/home.html
  17. 26 0
      wagtail/admin/templates/wagtailadmin/home/account_summary.html
  18. 28 18
      wagtail/admin/templates/wagtailadmin/home/locked_pages.html
  19. 28 17
      wagtail/admin/templates/wagtailadmin/home/recent_edits.html
  20. 2 2
      wagtail/admin/templates/wagtailadmin/home/site_summary_pages.html
  21. 16 13
      wagtail/admin/templates/wagtailadmin/home/upgrade_notification.html
  22. 28 18
      wagtail/admin/templates/wagtailadmin/home/user_objects_in_workflow_moderation.html
  23. 43 32
      wagtail/admin/templates/wagtailadmin/home/workflow_objects_to_moderate.html
  24. 1 1
      wagtail/admin/templates/wagtailadmin/pages/listing/_locked_indicator.html
  25. 13 3
      wagtail/admin/templates/wagtailadmin/shared/avatar.html
  26. 0 5
      wagtail/admin/templates/wagtailadmin/shared/header.html
  27. 10 1
      wagtail/admin/templatetags/wagtailadmin_tags.py
  28. 1 1
      wagtail/admin/tests/pages/test_explorer_view.py
  29. 1 1
      wagtail/admin/tests/test_dashboard.py
  30. 1 1
      wagtail/admin/tests/test_reports_views.py
  31. 3 3
      wagtail/admin/tests/test_site_summary.py
  32. 1 1
      wagtail/admin/tests/tests.py
  33. 9 7
      wagtail/admin/views/home.py
  34. 2 2
      wagtail/documents/templates/wagtaildocs/homepage/site_summary_documents.html
  35. 3 3
      wagtail/documents/tests/test_site_summary.py
  36. 2 2
      wagtail/images/templates/wagtailimages/homepage/site_summary_images.html
  37. 3 3
      wagtail/images/tests/test_site_summary.py

+ 1 - 0
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)

+ 35 - 2
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]');
+  }
+}

+ 0 - 19
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;

+ 13 - 27
client/scss/components/_indicator.scss

@@ -1,41 +1,27 @@
-.privacy-indicator {
-  &.public {
-    .label-private {
-      display: none;
-    }
-  }
-
-  &.private {
-    .label-public {
-      display: none;
-    }
-  }
-}
-
 .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
+  }
+
+  &--is-dimmed {
+    opacity: theme('opacity.50');
+  }
+}
 
-    @media (forced-colors: active) {
-      background-color: ButtonText;
+.privacy-indicator {
+  &.public {
+    .label-private {
+      display: none;
     }
   }
 
-  &.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');
+  &.private {
+    .label-public {
+      display: none;
     }
   }
 }

+ 75 - 1
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,

+ 23 - 0
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;
+  }
+}

+ 0 - 1
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');
   }
 

+ 8 - 45
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;
   }
 }

+ 0 - 1
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';

+ 0 - 10
client/scss/layouts/_home.scss

@@ -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;
-  }
-}

+ 36 - 0
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',
+      },
     },
   },
   {

+ 6 - 0
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)",

+ 1 - 1
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 () => {

+ 15 - 0
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.

+ 0 - 2
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

+ 22 - 5
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 %}

+ 26 - 0
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>

+ 28 - 18
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>

+ 28 - 17
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>

+ 2 - 2
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>

+ 16 - 13
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>

+ 28 - 18
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 %}

+ 43 - 32
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 %}

+ 1 - 1
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" %}

+ 13 - 3
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>

+ 0 - 5
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

+ 10 - 1
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,
     }
 
 

+ 1 - 1
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):

+ 1 - 1
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

+ 1 - 1
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"'
         )

+ 3 - 3
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")

+ 1 - 1
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"))

+ 9 - 7
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(),

+ 2 - 2
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>

+ 3 - 3
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):

+ 2 - 2
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>

+ 3 - 3
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):