mirror of
https://github.com/strapi/strapi.git
synced 2025-11-11 07:39:16 +00:00
[Bugfix] Bulk publish/unpublish for non-default locale entities (#17941)
* pass the locale to the publish and draft relations calls * fix the problem for entities without internationalization and add unit tests
This commit is contained in:
parent
c03a0a4a28
commit
e3a5416487
@ -6,6 +6,7 @@ import {
|
|||||||
useFetchClient,
|
useFetchClient,
|
||||||
useNotification,
|
useNotification,
|
||||||
useAPIErrorHandler,
|
useAPIErrorHandler,
|
||||||
|
useQueryParams,
|
||||||
} from '@strapi/helper-plugin';
|
} from '@strapi/helper-plugin';
|
||||||
import { Check, ExclamationMarkCircle } from '@strapi/icons';
|
import { Check, ExclamationMarkCircle } from '@strapi/icons';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
@ -82,6 +83,7 @@ const ConfirmDialogPublishAll = ({ isOpen, onToggleDialog, isConfirmButtonLoadin
|
|||||||
const {
|
const {
|
||||||
contentType: { uid: slug },
|
contentType: { uid: slug },
|
||||||
} = useSelector(listViewDomain());
|
} = useSelector(listViewDomain());
|
||||||
|
const [{ query }] = useQueryParams();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: countDraftRelations,
|
data: countDraftRelations,
|
||||||
@ -97,6 +99,7 @@ const ConfirmDialogPublishAll = ({ isOpen, onToggleDialog, isConfirmButtonLoadin
|
|||||||
{
|
{
|
||||||
params: {
|
params: {
|
||||||
ids: selectedEntries,
|
ids: selectedEntries,
|
||||||
|
locale: query?.plugins?.i18n?.locale,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { lightTheme, ThemeProvider } from '@strapi/design-system';
|
import { lightTheme, ThemeProvider } from '@strapi/design-system';
|
||||||
import { Table } from '@strapi/helper-plugin';
|
import { Table, useQueryParams } from '@strapi/helper-plugin';
|
||||||
import { render as renderRTL, screen, waitFor, within } from '@testing-library/react';
|
import { render as renderRTL, screen, waitFor, within } from '@testing-library/react';
|
||||||
import { rest } from 'msw';
|
import { rest } from 'msw';
|
||||||
import { setupServer } from 'msw/node';
|
import { setupServer } from 'msw/node';
|
||||||
@ -34,6 +34,17 @@ jest.mock('@strapi/helper-plugin', () => ({
|
|||||||
useNotification: jest.fn(() => {
|
useNotification: jest.fn(() => {
|
||||||
return toggleNotification;
|
return toggleNotification;
|
||||||
}),
|
}),
|
||||||
|
useQueryParams: jest.fn(() => [
|
||||||
|
{
|
||||||
|
query: {
|
||||||
|
plugins: {
|
||||||
|
i18n: {
|
||||||
|
locale: 'en',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const handlers = [
|
const handlers = [
|
||||||
@ -215,4 +226,35 @@ describe('ConfirmDialogPublishAll', () => {
|
|||||||
);
|
);
|
||||||
expect(await screen.getByRole('alert')).toBeInTheDocument();
|
expect(await screen.getByRole('alert')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should show the warning message with 2 draft relations and 2 entries even if the locale param is not passed', async () => {
|
||||||
|
useQueryParams.mockImplementation(() => [
|
||||||
|
{
|
||||||
|
query: {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
sort: 'name:ASC',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
server.use(
|
||||||
|
rest.get('*/countManyEntriesDraftRelations', (req, res, ctx) => {
|
||||||
|
return res.once(
|
||||||
|
ctx.status(200),
|
||||||
|
ctx.json({
|
||||||
|
data: 2,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
render();
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
const publishDialog = screen.getByRole('dialog');
|
||||||
|
expect(publishDialog).toBeInTheDocument();
|
||||||
|
within(publishDialog).getByText(/2 relations out of 2 entries are/i);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -445,7 +445,7 @@ const SelectedEntriesModal = ({ onToggle }) => {
|
|||||||
// We want to keep the selected entries order same as the list view
|
// We want to keep the selected entries order same as the list view
|
||||||
const [
|
const [
|
||||||
{
|
{
|
||||||
query: { sort },
|
query: { sort, plugins },
|
||||||
},
|
},
|
||||||
] = useQueryParams();
|
] = useQueryParams();
|
||||||
|
|
||||||
@ -458,6 +458,7 @@ const SelectedEntriesModal = ({ onToggle }) => {
|
|||||||
$in: entriesToFetch,
|
$in: entriesToFetch,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
locale: plugins?.i18n?.locale,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { get } = useFetchClient();
|
const { get } = useFetchClient();
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { lightTheme, ThemeProvider } from '@strapi/design-system';
|
import { lightTheme, ThemeProvider } from '@strapi/design-system';
|
||||||
import { Table } from '@strapi/helper-plugin';
|
import { Table, useQueryParams } from '@strapi/helper-plugin';
|
||||||
import {
|
import {
|
||||||
render as renderRTL,
|
render as renderRTL,
|
||||||
screen,
|
screen,
|
||||||
@ -31,6 +31,11 @@ jest.mock('@strapi/helper-plugin', () => ({
|
|||||||
{
|
{
|
||||||
query: {
|
query: {
|
||||||
sort: 'name:DESC',
|
sort: 'name:DESC',
|
||||||
|
plugins: {
|
||||||
|
i18n: {
|
||||||
|
locale: 'en',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]),
|
]),
|
||||||
@ -159,6 +164,32 @@ describe('Bulk publish selected entries modal', () => {
|
|||||||
expect(screen.queryByText('Entry 4')).not.toBeInTheDocument();
|
expect(screen.queryByText('Entry 4')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders the selected items in the modal even if the locale param is not passed', async () => {
|
||||||
|
useQueryParams.mockImplementation(() => [
|
||||||
|
{
|
||||||
|
query: {
|
||||||
|
page: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
sort: 'name:DESC',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const { queryByText } = render(
|
||||||
|
<Table.Root defaultSelectedEntries={[1, 2, 3]} colCount={4}>
|
||||||
|
<SelectedEntriesModal onToggle={jest.fn()} />
|
||||||
|
</Table.Root>
|
||||||
|
);
|
||||||
|
|
||||||
|
await waitForElementToBeRemoved(() => queryByText('Loading content'));
|
||||||
|
|
||||||
|
expect(screen.getByText(/publish entries/i)).toBeInTheDocument();
|
||||||
|
|
||||||
|
// Nested table should render the selected items from the parent table
|
||||||
|
expect(screen.queryByText('Entry 1')).toBeInTheDocument();
|
||||||
|
expect(screen.queryByText('Entry 4')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('reacts to selection updates', async () => {
|
it('reacts to selection updates', async () => {
|
||||||
const { queryByText } = render(
|
const { queryByText } = render(
|
||||||
<Table.Root defaultSelectedEntries={[1, 2, 3]} colCount={4}>
|
<Table.Root defaultSelectedEntries={[1, 2, 3]} colCount={4}>
|
||||||
|
|||||||
@ -445,6 +445,7 @@ module.exports = {
|
|||||||
async countManyEntriesDraftRelations(ctx) {
|
async countManyEntriesDraftRelations(ctx) {
|
||||||
const { userAbility } = ctx.state;
|
const { userAbility } = ctx.state;
|
||||||
const ids = ctx.request.query.ids;
|
const ids = ctx.request.query.ids;
|
||||||
|
const locale = ctx.request.query.locale;
|
||||||
const { model } = ctx.params;
|
const { model } = ctx.params;
|
||||||
|
|
||||||
const entityManager = getService('entity-manager');
|
const entityManager = getService('entity-manager');
|
||||||
@ -454,13 +455,13 @@ module.exports = {
|
|||||||
return ctx.forbidden();
|
return ctx.forbidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
const entities = await entityManager.find(ids, model);
|
const entities = await entityManager.find({ ids, locale }, model);
|
||||||
|
|
||||||
if (!entities) {
|
if (!entities) {
|
||||||
return ctx.notFound();
|
return ctx.notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
const number = await entityManager.countManyEntriesDraftRelations(ids, model);
|
const number = await entityManager.countManyEntriesDraftRelations(ids, model, locale);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: number,
|
data: number,
|
||||||
|
|||||||
@ -11,7 +11,7 @@ interface EntityManager {
|
|||||||
publish(): any;
|
publish(): any;
|
||||||
unpublish(): any;
|
unpublish(): any;
|
||||||
countDraftRelations(id: string, uid: string): number;
|
countDraftRelations(id: string, uid: string): number;
|
||||||
countManyEntriesDraftRelations(ids: number[], uid: string): number;
|
countManyEntriesDraftRelations(ids: number[], uid: string, locale?: string): number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (opts: { strapi: Strapi }): EntityManager;
|
export default function (opts: { strapi: Strapi }): EntityManager;
|
||||||
|
|||||||
@ -301,7 +301,7 @@ module.exports = ({ strapi }) => ({
|
|||||||
return sumDraftCounts(entity, uid);
|
return sumDraftCounts(entity, uid);
|
||||||
},
|
},
|
||||||
|
|
||||||
async countManyEntriesDraftRelations(ids, uid) {
|
async countManyEntriesDraftRelations(ids, uid, locale = 'en') {
|
||||||
const { populate, hasRelations } = getDeepPopulateDraftCount(uid);
|
const { populate, hasRelations } = getDeepPopulateDraftCount(uid);
|
||||||
|
|
||||||
if (!hasRelations) {
|
if (!hasRelations) {
|
||||||
@ -311,6 +311,7 @@ module.exports = ({ strapi }) => ({
|
|||||||
const entities = await strapi.entityService.findMany(uid, {
|
const entities = await strapi.entityService.findMany(uid, {
|
||||||
populate,
|
populate,
|
||||||
filters: { id: { $in: ids } },
|
filters: { id: { $in: ids } },
|
||||||
|
locale,
|
||||||
});
|
});
|
||||||
|
|
||||||
const totalNumberDraftRelations = entities.reduce(
|
const totalNumberDraftRelations = entities.reduce(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user