From cf66702adc45dbedb0d3a0a1248da2de05dca1c8 Mon Sep 17 00:00:00 2001 From: jbpenrath Date: Tue, 12 Aug 2025 09:56:17 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(front)=20paginate=20maildomain=20and?= =?UTF-8?q?=20mailboxes=20views?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add pagination on maildomain and mailboxes data grid to allow navigation in large list of items --- src/backend/core/api/permissions.py | 16 ++- src/backend/core/api/viewsets/maildomain.py | 4 +- .../core/tests/api/test_mailbox_access.py | 97 +++++++++++++++---- .../src/features/i18n/translations.json | 4 + .../mailboxes-view/create-mailbox-action.tsx | 7 +- .../mailboxes-view/mailbox-data-grid.tsx | 39 +++++--- .../admin/mailboxes-view/page-content.tsx | 9 +- .../admin/modal-create-address/index.tsx | 4 +- .../admin/modal-manage-accesses/index.tsx | 2 +- .../features/providers/admin-maildomain.tsx | 30 +++--- .../src/pages/domain/[maildomainId]/index.tsx | 14 ++- src/frontend/src/pages/domain/index.tsx | 12 ++- src/frontend/src/styles/globals.scss | 5 + 13 files changed, 182 insertions(+), 61 deletions(-) diff --git a/src/backend/core/api/permissions.py b/src/backend/core/api/permissions.py index 7bd29adf..146b30df 100644 --- a/src/backend/core/api/permissions.py +++ b/src/backend/core/api/permissions.py @@ -376,7 +376,11 @@ class IsMailboxAdmin(permissions.BasePermission): except (models.Mailbox.DoesNotExist, ValueError): # ValueError for invalid UUID return False - # Check 1: Is user an admin of the specific mailbox? + # Check 1 : Is user a super user ? + if user.is_superuser: + return True + + # Check 2: Is user an admin of the specific mailbox? is_mailbox_admin = models.MailboxAccess.objects.filter( user=user, mailbox=target_mailbox, role=models.MailboxRoleChoices.ADMIN ).exists() @@ -384,7 +388,7 @@ class IsMailboxAdmin(permissions.BasePermission): if is_mailbox_admin: return True - # Check 2: Is user an admin of the mailbox's domain? + # Check 3: Is user an admin of the mailbox's domain? if target_mailbox.domain: is_domain_admin = models.MailDomainAccess.objects.filter( user=user, @@ -412,7 +416,11 @@ class IsMailboxAdmin(permissions.BasePermission): user = request.user target_mailbox = obj.mailbox # The mailbox related to the MailboxAccess object - # Check 1: Is user an admin of this specific mailbox? + # Check 1 : Is user a super user ? + if user.is_superuser: + return True + + # Check 2: Is user an admin of this specific mailbox? is_mailbox_admin = models.MailboxAccess.objects.filter( user=user, mailbox=target_mailbox, role=models.MailboxRoleChoices.ADMIN ).exists() @@ -420,7 +428,7 @@ class IsMailboxAdmin(permissions.BasePermission): if is_mailbox_admin: return True - # Check 2: Is user an admin of the mailbox's domain? + # Check 3: Is user an admin of the mailbox's domain? is_domain_admin = models.MailDomainAccess.objects.filter( user=user, maildomain=target_mailbox.domain, diff --git a/src/backend/core/api/viewsets/maildomain.py b/src/backend/core/api/viewsets/maildomain.py index f3290b68..f31364f9 100644 --- a/src/backend/core/api/viewsets/maildomain.py +++ b/src/backend/core/api/viewsets/maildomain.py @@ -147,9 +147,7 @@ class AdminMailDomainMailboxViewSet( def get_queryset(self): maildomain_pk = self.kwargs.get("maildomain_pk") - return models.Mailbox.objects.filter(domain_id=maildomain_pk).order_by( - "local_part" - ) + return models.Mailbox.objects.filter(domain_id=maildomain_pk) @extend_schema( description="Create new mailbox in a specific maildomain.", diff --git a/src/backend/core/tests/api/test_mailbox_access.py b/src/backend/core/tests/api/test_mailbox_access.py index a3035d62..989bb294 100644 --- a/src/backend/core/tests/api/test_mailbox_access.py +++ b/src/backend/core/tests/api/test_mailbox_access.py @@ -1,6 +1,7 @@ """Tests for the MailboxAccessViewSet API endpoint (nested under mailboxes).""" # pylint: disable=unused-argument +from django.contrib.auth.models import AnonymousUser from django.urls import reverse import pytest @@ -13,6 +14,13 @@ pytestmark = pytest.mark.django_db # --- Users --- +@pytest.fixture(name="super_user") +def fixture_super_user(): + """User with ADMIN access to mail_domain1.""" + user = factories.UserFactory(is_superuser=True, is_staff=False) + return user + + @pytest.fixture(name="domain_admin_user") def fixture_domain_admin_user(mail_domain1): """User with ADMIN access to mail_domain1.""" @@ -131,6 +139,29 @@ class TestMailboxAccessViewSet: ) # --- LIST Tests --- + def test_list_as_super_user_for_managed_mailbox( + self, + api_client, + super_user, + mailbox1_domain1, + access_m1d1_alpha, + access_m1d1_beta, + ): + """Super user should see accesses for the specified mailbox.""" + api_client.force_authenticate( + user=super_user + ) # Admin for domain1, which mailbox1_domain1 is in + response = api_client.get(self.list_create_url(mailbox_id=mailbox1_domain1.pk)) + + assert response.status_code == status.HTTP_200_OK + + # access_m2d1_alpha is for a different mailbox, so should not be listed here. + assert {item["id"] for item in response.data["results"]} == { + str(access_m1d1_alpha.pk), + str(access_m1d1_beta.pk), + } + assert response.data["count"] == 2 + def test_list_as_domain_admin_for_managed_mailbox( self, api_client, @@ -209,11 +240,14 @@ class TestMailboxAccessViewSet: assert response.status_code == status.HTTP_401_UNAUTHORIZED # --- CREATE Tests --- - @pytest.mark.parametrize("admin_type", ["domain_admin", "mailbox_admin"]) + @pytest.mark.parametrize( + "admin_type", ["domain_admin", "mailbox_admin", "super_user"] + ) def test_create_access_success( self, api_client, admin_type, + super_user, domain_admin_user, mailbox1_admin_user, mailbox1_domain1, @@ -221,9 +255,14 @@ class TestMailboxAccessViewSet: user_alpha, ): """Domain and mailbox admins should be able to create new accesses.""" - user_performing_action = ( - domain_admin_user if admin_type == "domain_admin" else mailbox1_admin_user - ) + user_performing_action = AnonymousUser() + if admin_type == "super_user": + user_performing_action = super_user + elif admin_type == "domain_admin": + user_performing_action = domain_admin_user + elif admin_type == "mailbox_admin": + user_performing_action = mailbox1_admin_user + api_client.force_authenticate(user=user_performing_action) data = { # No 'mailbox' field in data, it comes from URL @@ -288,20 +327,28 @@ class TestMailboxAccessViewSet: assert response.status_code == status.HTTP_403_FORBIDDEN # --- RETRIEVE Tests --- - @pytest.mark.parametrize("admin_type", ["domain_admin", "mailbox_admin"]) + @pytest.mark.parametrize( + "admin_type", ["domain_admin", "mailbox_admin", "super_user"] + ) def test_retrieve_access_success( self, api_client, admin_type, + super_user, domain_admin_user, mailbox1_admin_user, mailbox1_domain1, access_m1d1_alpha, ): - """Domain and mailbox admins should be able to retrieve mailbox access details.""" - user_performing_action = ( - domain_admin_user if admin_type == "domain_admin" else mailbox1_admin_user - ) + """Super user, Domain and mailbox admins should be able to retrieve mailbox access details.""" + user_performing_action = AnonymousUser() + if admin_type == "super_user": + user_performing_action = super_user + elif admin_type == "domain_admin": + user_performing_action = domain_admin_user + elif admin_type == "mailbox_admin": + user_performing_action = mailbox1_admin_user + api_client.force_authenticate(user=user_performing_action) response = api_client.get( self.detail_url(mailbox_id=mailbox1_domain1.pk, pk=access_m1d1_alpha.pk) @@ -326,11 +373,14 @@ class TestMailboxAccessViewSet: assert response.status_code == status.HTTP_404_NOT_FOUND # --- UPDATE Tests --- - @pytest.mark.parametrize("admin_type", ["domain_admin", "mailbox_admin"]) + @pytest.mark.parametrize( + "admin_type", ["domain_admin", "mailbox_admin", "super_user"] + ) def test_update_access_role_success( self, admin_type, api_client, + super_user, user_beta, domain_admin_user, mailbox1_admin_user, @@ -338,9 +388,14 @@ class TestMailboxAccessViewSet: access_m1d1_alpha, ): """Test that domain and mailbox admins can update mailbox access roles.""" - user_performing_action = ( - domain_admin_user if admin_type == "domain_admin" else mailbox1_admin_user - ) + user_performing_action = AnonymousUser() + if admin_type == "super_user": + user_performing_action = super_user + elif admin_type == "domain_admin": + user_performing_action = domain_admin_user + elif admin_type == "mailbox_admin": + user_performing_action = mailbox1_admin_user + api_client.force_authenticate(user=user_performing_action) data = {"role": "admin"} response = api_client.patch( @@ -366,20 +421,28 @@ class TestMailboxAccessViewSet: assert response.status_code == status.HTTP_400_BAD_REQUEST # --- DELETE Tests --- - @pytest.mark.parametrize("admin_type", ["domain_admin", "mailbox_admin"]) + @pytest.mark.parametrize( + "admin_type", ["domain_admin", "mailbox_admin", "super_user"] + ) def test_delete_access_success( self, api_client, admin_type, + super_user, domain_admin_user, mailbox1_admin_user, mailbox1_domain1, access_m1d1_alpha, ): """Test that domain and mailbox admins can delete mailbox accesses.""" - user_performing_action = ( - domain_admin_user if admin_type == "domain_admin" else mailbox1_admin_user - ) + user_performing_action = AnonymousUser() + if admin_type == "super_user": + user_performing_action = super_user + elif admin_type == "domain_admin": + user_performing_action = domain_admin_user + elif admin_type == "mailbox_admin": + user_performing_action = mailbox1_admin_user + api_client.force_authenticate(user=user_performing_action) response = api_client.delete( self.detail_url(mailbox_id=mailbox1_domain1.pk, pk=access_m1d1_alpha.pk) diff --git a/src/frontend/src/features/i18n/translations.json b/src/frontend/src/features/i18n/translations.json index 829cb738..8e337178 100644 --- a/src/frontend/src/features/i18n/translations.json +++ b/src/frontend/src/features/i18n/translations.json @@ -403,6 +403,8 @@ "datagrid_row_labels": { "no_accesses": "No accesses", "unknown_user": "Unknown user", + "other_user_one": "and 1 other user", + "other_user_other": "and {{count}} other users", "alias": "Redirection", "personal_mailbox": "Personal mailbox", "shared_mailbox": "Shared mailbox" @@ -844,6 +846,8 @@ "datagrid_row_labels": { "no_accesses": "Aucun accès", "unknown_user": "Utilisateur inconnu", + "other_user_one": "et 1 autre utilisateur", + "other_user_other": "et {{count}} autres utilisateurs", "alias": "Redirection", "personal_mailbox": "Boîte personnelle", "shared_mailbox": "Boîte partagée" diff --git a/src/frontend/src/features/layouts/components/admin/mailboxes-view/create-mailbox-action.tsx b/src/frontend/src/features/layouts/components/admin/mailboxes-view/create-mailbox-action.tsx index 8fd0cb2c..7bd54b50 100644 --- a/src/frontend/src/features/layouts/components/admin/mailboxes-view/create-mailbox-action.tsx +++ b/src/frontend/src/features/layouts/components/admin/mailboxes-view/create-mailbox-action.tsx @@ -4,11 +4,15 @@ import useAbility, { Abilities } from "@/hooks/use-ability"; import { Button, useModal } from "@openfun/cunningham-react"; import { useTranslation } from "react-i18next"; +type CreateMailboxActionProps = { + onCreate: () => void; +} + /** * Action button to create a new mailbox. * Only visible if the user has the ability to manage mailboxes. */ -export const CreateMailboxAction = () => { +export const CreateMailboxAction = ({ onCreate }: CreateMailboxActionProps) => { const modal = useModal(); const { t } = useTranslation(); const { selectedMailDomain } = useAdminMailDomain(); @@ -26,6 +30,7 @@ export const CreateMailboxAction = () => { ) diff --git a/src/frontend/src/features/layouts/components/admin/mailboxes-view/mailbox-data-grid.tsx b/src/frontend/src/features/layouts/components/admin/mailboxes-view/mailbox-data-grid.tsx index ca3286fe..295adc67 100644 --- a/src/frontend/src/features/layouts/components/admin/mailboxes-view/mailbox-data-grid.tsx +++ b/src/frontend/src/features/layouts/components/admin/mailboxes-view/mailbox-data-grid.tsx @@ -3,23 +3,23 @@ import { ModalMailboxManageAccesses } from "@/features/layouts/components/admin/ import { Banner } from "@/features/ui/components/banner"; import useAbility, { Abilities } from "@/hooks/use-ability"; import { Spinner } from "@gouvfr-lasuite/ui-kit"; -import { Button, DataGrid } from "@openfun/cunningham-react"; -import { useState } from "react"; +import { Button, DataGrid, usePagination } from "@openfun/cunningham-react"; +import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; type AdminUserDataGridProps = { domain: MailDomainAdmin; + pagination: ReturnType; } -export const AdminMailboxDataGrid = ({ domain }: AdminUserDataGridProps) => { +export const AdminMailboxDataGrid = ({ domain, pagination }: AdminUserDataGridProps) => { const { t } = useTranslation(); - const { data: mailboxesData, isLoading, error, refetch: refetchMailboxes } = useMaildomainsMailboxesList(domain.id); + const { data: mailboxesData, isLoading, error, refetch: refetchMailboxes } = useMaildomainsMailboxesList(domain.id, { page: pagination.page }); const mailboxes = mailboxesData?.data.results || []; - const [editedMailboxId, setEditedMailboxId] = useState(null); - const editedMailbox = mailboxes.find((mailbox) => mailbox.id === editedMailboxId); + const [editedMailbox, setEditedMailbox] = useState(null); const canManageMailboxes = useAbility(Abilities.CAN_MANAGE_MAILDOMAIN_MAILBOXES, domain); const handleCloseEditUserModal = (refetch: boolean = false) => { - setEditedMailboxId(null); + setEditedMailbox(null); if (refetch) { refetchMailboxes(); } @@ -58,7 +58,7 @@ export const AdminMailboxDataGrid = ({ domain }: AdminUserDataGridProps) => { renderCell: ({ row }: { row: MailboxAdmin }) => `${row.local_part}@${row.domain_name}`, }, { - id: "user_name", + id: "accesses", headerName: t("admin_maildomains_details.datagrid_headers.accesses"), renderCell: ({ row }: { row: MailboxAdmin }) => { if (row.accesses?.length === 0) { @@ -69,9 +69,10 @@ export const AdminMailboxDataGrid = ({ domain }: AdminUserDataGridProps) => { ); } - return row.accesses?.map((access) => { + const otherAccessesCount = row.accesses?.length - 2; + return row.accesses?.slice(0, 2).map((access) => { return access.user?.full_name || access.user?.email || t("admin_maildomains_details.datagrid_row_labels.unknown_user"); - }).join(", "); + }).join(", ") + (otherAccessesCount > 0 ? ` ${t("admin_maildomains_details.datagrid_row_labels.other_user", { count: otherAccessesCount })}` : ""); }, }, ...(canManageMailboxes ? [{ @@ -84,7 +85,7 @@ export const AdminMailboxDataGrid = ({ domain }: AdminUserDataGridProps) => { color="secondary" size="small" onClick={() => { - setEditedMailboxId(row.id); + setEditedMailbox(row); }} > {t('admin_maildomains_details.actions.manage_accesses')} @@ -94,6 +95,19 @@ export const AdminMailboxDataGrid = ({ domain }: AdminUserDataGridProps) => { }] : []), ]; + useEffect(() => { + if (!pagination.pagesCount && mailboxesData?.data.count) { + pagination.setPagesCount(Math.ceil(mailboxesData.data.count / pagination.pageSize)); + } + }, [mailboxesData?.data.count, pagination.pageSize]); + + useEffect(() => { + if (editedMailbox) { + const updatedMailbox = mailboxes.find((mailbox) => mailbox.id === editedMailbox.id); + if (updatedMailbox) setEditedMailbox(updatedMailbox); + } + }, [mailboxes, editedMailbox]); + if (isLoading) { return (
@@ -119,6 +133,9 @@ export const AdminMailboxDataGrid = ({ domain }: AdminUserDataGridProps) => { undefined} /> {canManageMailboxes && ( { +type AdminDomainPageContentProps = { + pagination: ReturnType; +} + +export const AdminDomainPageContent = ({ pagination }: AdminDomainPageContentProps) => { const { t } = useTranslation(); const { selectedMailDomain, isLoading } = useAdminMailDomain(); @@ -23,5 +28,5 @@ export const AdminDomainPageContent = () => { ); } - return ; + return ; } diff --git a/src/frontend/src/features/layouts/components/admin/modal-create-address/index.tsx b/src/frontend/src/features/layouts/components/admin/modal-create-address/index.tsx index 4f1149c9..3d4fc272 100644 --- a/src/frontend/src/features/layouts/components/admin/modal-create-address/index.tsx +++ b/src/frontend/src/features/layouts/components/admin/modal-create-address/index.tsx @@ -37,9 +37,10 @@ const slugify = (text: string): string => { type ModalCreateAddressProps = { isOpen: boolean; onClose: () => void; + onCreate: () => void; } -export const ModalCreateAddress = ({ isOpen, onClose }: ModalCreateAddressProps) => { +export const ModalCreateAddress = ({ isOpen, onClose, onCreate }: ModalCreateAddressProps) => { const { t } = useTranslation(); const router = useRouter(); const domainId = router.query.maildomainId as string; @@ -209,6 +210,7 @@ export const ModalCreateAddress = ({ isOpen, onClose }: ModalCreateAddressProps) const response = await createMailbox({ maildomainPk: domainId, data: payload }, ); refetchMailboxes(); setCreatedMailbox(response.data); + onCreate(); } catch (error: unknown) { if (error instanceof APIError && error.data.local_part) { setError("create_address_modal.api_errors.prefix_exists"); diff --git a/src/frontend/src/features/layouts/components/admin/modal-manage-accesses/index.tsx b/src/frontend/src/features/layouts/components/admin/modal-manage-accesses/index.tsx index 42d1bee5..796b1ed7 100644 --- a/src/frontend/src/features/layouts/components/admin/modal-manage-accesses/index.tsx +++ b/src/frontend/src/features/layouts/components/admin/modal-manage-accesses/index.tsx @@ -7,7 +7,7 @@ type ModalMailboxManageAccessesProps = { domainId: string; isOpen: boolean; onClose: () => void; - mailbox: MailboxAdmin | undefined; + mailbox: MailboxAdmin | null; onAccessChange: () => void; } diff --git a/src/frontend/src/features/providers/admin-maildomain.tsx b/src/frontend/src/features/providers/admin-maildomain.tsx index 6a955011..50586871 100644 --- a/src/frontend/src/features/providers/admin-maildomain.tsx +++ b/src/frontend/src/features/providers/admin-maildomain.tsx @@ -1,13 +1,15 @@ -import { createContext, PropsWithChildren, useContext, useEffect, useMemo, useState } from "react" +import { createContext, PropsWithChildren, useContext, useEffect, useMemo } from "react" import { MailDomainAdmin } from "../api/gen/models/mail_domain_admin"; -import { useMaildomainsList } from "../api/gen"; +import { useMaildomainsList, useMaildomainsRetrieve } from "../api/gen"; import { useRouter } from "next/router"; +import { usePagination } from "@openfun/cunningham-react"; type AdminMailDomainContextType = { selectedMailDomain: MailDomainAdmin | null; mailDomains: MailDomainAdmin[]; isLoading: boolean; error: unknown | null; + pagination: ReturnType; } const AdminMailDomainContext = createContext(undefined) @@ -17,24 +19,24 @@ const AdminMailDomainContext = createContext { - const { data: maildomainsData, isLoading, error } = useMaildomainsList(); const router = useRouter(); - const [selectedMailDomain, setSelectedMailDomain] = useState(null); + const pagination = usePagination({ pageSize: 20 }); + const { data: maildomainsData, isLoading: isLoadingList, error: listError } = useMaildomainsList({ page: pagination.page }); + const { data: selectedMaildomainData, isLoading: isLoadingItem, error: itemError } = useMaildomainsRetrieve( + router.query.maildomainId as string, { query: { enabled: !!router.query.maildomainId } }); const context = useMemo(() => ({ - selectedMailDomain, + selectedMailDomain: selectedMaildomainData?.data || null, mailDomains: maildomainsData?.data.results || [], - isLoading, - error, - }), [selectedMailDomain, maildomainsData, isLoading]); + isLoading: isLoadingList || isLoadingItem, + error: listError || itemError, + pagination + }), [selectedMaildomainData, maildomainsData, isLoadingList, isLoadingItem, listError, itemError, pagination.page]); useEffect(() => { - if (router.query.maildomainId) { - const maildomain = maildomainsData?.data.results?.find((maildomain) => maildomain.id === router.query.maildomainId); - if (maildomain) { - setSelectedMailDomain(maildomain); - } + if (maildomainsData?.data.count) { + pagination.setPagesCount(Math.ceil(maildomainsData.data.count / pagination.pageSize)); } - }, [router.query.maildomainId, maildomainsData]); + }, [maildomainsData?.data.count, pagination.pageSize, pagination.setPagesCount]); return ( {children} diff --git a/src/frontend/src/pages/domain/[maildomainId]/index.tsx b/src/frontend/src/pages/domain/[maildomainId]/index.tsx index ed714e20..1d3c7138 100644 --- a/src/frontend/src/pages/domain/[maildomainId]/index.tsx +++ b/src/frontend/src/pages/domain/[maildomainId]/index.tsx @@ -1,17 +1,25 @@ import { AdminLayout } from "@/features/layouts/components/admin/admin-layout"; import { CreateMailboxAction } from "@/features/layouts/components/admin/mailboxes-view/create-mailbox-action"; import { AdminDomainPageContent } from "@/features/layouts/components/admin/mailboxes-view/page-content"; +import { usePagination } from "@openfun/cunningham-react"; /** * Admin page which list all mailboxes for a given domain and allow to manage them. */ -export default function AdminDomainPage() { +export default function AdminDomainMailboxesPage() { + const pagination = usePagination({ pageSize: 20 }); + + const handleCreateMailbox = () => { + pagination.setPage(1); + pagination.setPagesCount(undefined) + } + return ( } + actions={} > - + ); } diff --git a/src/frontend/src/pages/domain/index.tsx b/src/frontend/src/pages/domain/index.tsx index dbed4ff1..3b50dd99 100644 --- a/src/frontend/src/pages/domain/index.tsx +++ b/src/frontend/src/pages/domain/index.tsx @@ -1,5 +1,5 @@ import { useEffect } from "react"; -import { DataGrid } from "@openfun/cunningham-react"; +import { DataGrid, usePagination } from "@openfun/cunningham-react"; import { useRouter } from "next/router"; import { useTranslation } from "react-i18next"; import { Spinner } from "@gouvfr-lasuite/ui-kit"; @@ -11,10 +11,11 @@ import useAbility, { Abilities } from "@/hooks/use-ability"; import { Banner } from "@/features/ui/components/banner"; type AdminDataGridProps = { + pagination: ReturnType; domains: MailDomainAdmin[]; } -function AdminDataGrid({ domains }: AdminDataGridProps) { +function AdminDataGrid({ domains, pagination }: AdminDataGridProps) { const router = useRouter(); const { t, i18n } = useTranslation(); @@ -48,6 +49,9 @@ function AdminDataGrid({ domains }: AdminDataGridProps) { undefined} />
); @@ -56,7 +60,7 @@ function AdminDataGrid({ domains }: AdminDataGridProps) { const AdminPageContent = () => { const router = useRouter(); const { t } = useTranslation(); - const { mailDomains, isLoading, error } = useAdminMailDomain(); + const { mailDomains, isLoading, error, pagination } = useAdminMailDomain(); const canCreateMaildomain = useAbility(Abilities.CAN_CREATE_MAILDOMAINS); const shouldRedirect = !canCreateMaildomain && !isLoading && mailDomains.length === 1; @@ -91,7 +95,7 @@ const AdminPageContent = () => {

{t("admin_maildomains_list.title")}

- + ) } diff --git a/src/frontend/src/styles/globals.scss b/src/frontend/src/styles/globals.scss index 7efe50c0..8f003898 100644 --- a/src/frontend/src/styles/globals.scss +++ b/src/frontend/src/styles/globals.scss @@ -49,6 +49,11 @@ body { font-size: var(--c--theme--font--sizes--ml); } +.c__datagrid .c__pagination .c__button--active { + background-color: var(--c--components--button--tertiary-text--background--color-hover); + color: var(--c--components--button--tertiary-text--color-hover); +} + // Related to @viselect/react .selection-area { background: rgba(46, 115, 252, 0.11);