Skip to content

Commit 5b0ab93

Browse files
authored
refactor: ActionManagerComponent.tsx and fix rare render race condition (#203)
1 parent 70efd19 commit 5b0ab93

File tree

1 file changed

+61
-67
lines changed

1 file changed

+61
-67
lines changed
Lines changed: 61 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,85 +1,79 @@
1-
import React, { useState, useEffect } from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import { useLocation } from 'react-router-dom';
3-
import { useIntl } from 'react-intl';
43
import type { PanelComponent } from '@strapi/content-manager/strapi-admin';
5-
import { Box, Typography, Divider } from '@strapi/design-system';
6-
import Action from '../Action';
7-
import { getTrad } from '../../utils/getTrad';
8-
import { useSettings } from '../../hooks/useSettings';
94
import {
105
unstable_useDocument as useDocument,
116
unstable_useContentManagerContext as useContentManagerContext,
127
} from '@strapi/strapi/admin';
13-
import { Modules } from '@strapi/strapi';
8+
import { useSettings } from '../../hooks/useSettings';
9+
import Action from '../Action';
1410

15-
const actionModes = ['publish', 'unpublish'];
11+
const actionModes: Array<'publish' | 'unpublish'> = ['publish', 'unpublish'];
1612

17-
type Props = {
18-
document: Modules.Documents.AnyDocument,
19-
entity: ReturnType<typeof useContentManagerContext>,
20-
locale: string | null,
21-
}
13+
const ActionManager: PanelComponent = () => {
14+
const entity = useContentManagerContext();
15+
const location = useLocation();
16+
const params = new URLSearchParams(location.search);
17+
const currentLocale = params.get('plugins[i18n][locale]');
2218

23-
const ActionManagerComponent = ({ document, entity, locale }: Props) => {
24-
return (
25-
<>
26-
{actionModes.map((mode, index) => (
27-
<div className="actionButton" key={index}>
28-
<Action
29-
mode={mode}
30-
key={mode + index}
31-
documentId={document.documentId}
32-
entitySlug={entity.model}
33-
locale={locale}
34-
/>
35-
</div>
36-
))}
37-
<style>
38-
{`
39-
.actionButton {
40-
width: 100%;
41-
}
42-
`}
43-
</style>
44-
</>
45-
);
46-
};
19+
// Fetch the document (draft/published) with the selected locale
20+
const { document } = useDocument({
21+
documentId: entity?.id,
22+
model: entity?.model,
23+
collectionType: entity?.collectionType,
24+
params: { locale: currentLocale },
25+
});
4726

48-
const ActionManager: PanelComponent = () => {
49-
const entity = useContentManagerContext();
50-
const location = useLocation();
51-
const params = new URLSearchParams(location.search);
52-
const currentLocale = params.get('plugins[i18n][locale]');
27+
// Load plugin settings (whitelist of content types)
28+
const { getSettings } = useSettings();
29+
const { isLoading, data, isRefetching } = getSettings();
5330

54-
const { document } = useDocument({
55-
documentId: entity?.id,
56-
model: entity?.model,
57-
collectionType: entity?.collectionType,
58-
params: {
59-
locale: currentLocale,
60-
},
61-
});
31+
// Local state to determine whether to show the panel based on settings
32+
const [show, setShow] = useState<boolean>(true);
6233

63-
const { getSettings } = useSettings();
64-
const { isLoading, data, isRefetching } = getSettings();
34+
// When settings finish loading, update visibility based on whitelist
35+
useEffect(() => {
36+
if (!isLoading && !isRefetching) {
37+
const allowedList = data?.contentTypes || [];
38+
const isAllowed = allowedList.length === 0 || allowedList.includes(entity.slug);
39+
setShow(isAllowed);
40+
}
41+
}, [isLoading, isRefetching, data?.contentTypes, entity.slug]);
6542

66-
if (!entity.hasDraftAndPublish || entity.isCreatingEntry) return null;
67-
if (!document || !entity) return null;
43+
// Only proceed for content types with Draft & Publish enabled,
44+
// and not while creating a new entry
45+
if (!entity.hasDraftAndPublish || entity.isCreatingEntry) {
46+
return null;
47+
}
6848

69-
const isEnabled =
70-
!isLoading &&
71-
!isRefetching &&
72-
(
73-
!data.contentTypes?.length ||
74-
data.contentTypes?.includes(entity.slug)
75-
);
49+
// Wait until document and entity are loaded
50+
if (!document || !entity) {
51+
return null;
52+
}
7653

77-
if (!isEnabled) return null;
54+
// Only hide after settings have loaded and the type is not allowed
55+
if (!isLoading && !isRefetching && !show) {
56+
return null;
57+
}
7858

79-
return {
80-
title: "Publisher",
81-
content: <ActionManagerComponent document={document} entity={entity} locale={currentLocale} />,
82-
};
59+
// Render the panel with both action buttons
60+
return {
61+
title: 'Publisher',
62+
content: (
63+
<>
64+
{actionModes.map((mode) => (
65+
<div key={mode} style={{ width: '100%'}}>
66+
<Action
67+
mode={mode}
68+
documentId={document.documentId}
69+
entitySlug={entity.model}
70+
locale={currentLocale}
71+
/>
72+
</div>
73+
))}
74+
</>
75+
),
76+
};
8377
};
8478

85-
export default ActionManager;
79+
export default ActionManager;

0 commit comments

Comments
 (0)