@strapi/admin 4.12.4 → 4.13.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumns.js +2 -0
- package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +8 -1
- package/admin/src/content-manager/components/Filter/CustomInputs/AdminUsersFilter.js +42 -0
- package/admin/src/content-manager/components/{AttributeFilter/Filters.js → Filter/Filter.js} +5 -7
- package/admin/src/content-manager/components/Filter/index.js +1 -0
- package/admin/src/content-manager/hooks/useAllowedAttributes.js +47 -0
- package/admin/src/content-manager/hooks/useSyncRbac/index.js +10 -2
- package/admin/src/content-manager/pages/EditView/Information/index.js +9 -8
- package/admin/src/content-manager/pages/EditViewLayoutManager/index.js +2 -2
- package/admin/src/content-manager/pages/ListSettingsView/components/Settings.js +40 -7
- package/admin/src/content-manager/pages/ListSettingsView/index.js +6 -2
- package/admin/src/content-manager/pages/ListView/components/FieldPicker/index.js +67 -69
- package/admin/src/content-manager/pages/ListView/components/ViewSettingsMenu/index.js +74 -0
- package/admin/src/content-manager/pages/ListView/index.js +254 -68
- package/admin/src/content-manager/pages/ListViewLayoutManager/index.js +2 -2
- package/admin/src/content-manager/utils/getDisplayName.js +33 -0
- package/admin/src/content-manager/utils/index.js +1 -0
- package/admin/src/translations/en.json +3 -1
- package/admin/src/translations/zh-Hans.json +918 -902
- package/build/1227.32fe57ce.chunk.js +1 -0
- package/build/4174.fa8f9954.chunk.js +1 -0
- package/build/4546.ff09eeda.chunk.js +1 -0
- package/build/4724.baf7c5b1.chunk.js +6 -0
- package/build/6158.c3c13c20.chunk.js +1 -0
- package/build/78.dcc6df5c.chunk.js +1 -0
- package/build/{9806.3392505e.chunk.js → 9806.5d5a0e8d.chunk.js} +16 -16
- package/build/{Admin-authenticatedApp.f5ece8ff.chunk.js → Admin-authenticatedApp.53a24d28.chunk.js} +2 -2
- package/build/audit-logs-settings-page.0f73ccf8.chunk.js +1 -0
- package/build/content-manager.7f96a2f1.chunk.js +1097 -0
- package/build/{content-type-builder.40534de5.chunk.js → content-type-builder.cd999f6e.chunk.js} +2 -2
- package/build/{en-json.08c05fcf.chunk.js → en-json.4f06fe03.chunk.js} +1 -1
- package/build/i18n-translation-ru-json.a3dbc125.chunk.js +1 -0
- package/build/index.html +1 -1
- package/build/main.40b94779.js +2859 -0
- package/build/{runtime~main.bb4efc54.js → runtime~main.b16af570.js} +2 -2
- package/build/users-permissions-translation-zh-Hans-json.8d82c809.chunk.js +1 -0
- package/build/{users-roles-settings-page.3f9f063e.chunk.js → users-roles-settings-page.9d9a1eff.chunk.js} +1 -1
- package/build/zh-Hans-json.97efd015.chunk.js +1 -0
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/AssigneeFilter.js +42 -0
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/StageFilter.js +70 -0
- package/ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants.js +71 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +9 -217
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/AssigneeSelect.js +149 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/AssigneeSelect/index.js +1 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/StageSelect.js +241 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/components/StageSelect/index.js +1 -0
- package/ee/admin/content-manager/pages/EditView/InformationBox/constants.js +2 -0
- package/ee/admin/content-manager/pages/ListSettingsView/constants.js +7 -0
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/ReviewWorkflowsAssigneeEE.js +51 -0
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/constants.js +44 -17
- package/ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn/index.js +1 -0
- package/ee/server/constants/workflows.js +1 -0
- package/ee/server/controllers/index.js +1 -0
- package/ee/server/controllers/workflows/assignees/index.js +44 -0
- package/ee/server/routes/review-workflows.js +17 -0
- package/ee/server/services/index.js +1 -0
- package/ee/server/services/review-workflows/assignees.js +54 -0
- package/ee/server/services/review-workflows/metrics/index.js +5 -0
- package/ee/server/services/review-workflows/review-workflows.js +20 -11
- package/ee/server/validation/review-workflows.js +8 -0
- package/package.json +10 -10
- package/server/services/permission/permissions-manager/sanitize.js +12 -0
- package/admin/src/content-manager/components/AttributeFilter/hooks/useAllowedAttributes.js +0 -42
- package/admin/src/content-manager/components/AttributeFilter/index.js +0 -40
- package/build/3984.dda474f7.chunk.js +0 -1
- package/build/4546.cfafae68.chunk.js +0 -1
- package/build/5483.6dd2e776.chunk.js +0 -6
- package/build/6158.c974fd83.chunk.js +0 -1
- package/build/audit-logs-settings-page.4b422831.chunk.js +0 -1
- package/build/content-manager.2af15f57.chunk.js +0 -1099
- package/build/i18n-translation-ru-json.401bc498.chunk.js +0 -1
- package/build/main.f13fc96c.js +0 -2856
- package/build/users-permissions-translation-zh-Hans-json.6ab714ee.chunk.js +0 -1
- package/build/zh-Hans-json.937b395b.chunk.js +0 -1
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
IconButton,
|
|
5
4
|
Main,
|
|
6
|
-
Box,
|
|
7
5
|
ActionLayout,
|
|
8
6
|
Button,
|
|
9
7
|
ContentLayout,
|
|
@@ -17,8 +15,8 @@ import {
|
|
|
17
15
|
lightTheme,
|
|
18
16
|
} from '@strapi/design-system';
|
|
19
17
|
import {
|
|
18
|
+
findMatchingPermissions,
|
|
20
19
|
NoPermissions,
|
|
21
|
-
CheckPermissions,
|
|
22
20
|
SearchURLQuery,
|
|
23
21
|
useFetchClient,
|
|
24
22
|
useFocusWhenNavigate,
|
|
@@ -28,12 +26,13 @@ import {
|
|
|
28
26
|
useTracking,
|
|
29
27
|
Link,
|
|
30
28
|
useAPIErrorHandler,
|
|
29
|
+
useCollator,
|
|
31
30
|
useStrapiApp,
|
|
32
31
|
Table,
|
|
33
32
|
PaginationURLQuery,
|
|
34
33
|
PageSizeURLQuery,
|
|
35
34
|
} from '@strapi/helper-plugin';
|
|
36
|
-
import { ArrowLeft,
|
|
35
|
+
import { ArrowLeft, Plus } from '@strapi/icons';
|
|
37
36
|
import axios, { AxiosError } from 'axios';
|
|
38
37
|
import isEqual from 'lodash/isEqual';
|
|
39
38
|
import PropTypes from 'prop-types';
|
|
@@ -43,33 +42,29 @@ import { useMutation } from 'react-query';
|
|
|
43
42
|
import { connect, useSelector } from 'react-redux';
|
|
44
43
|
import { useHistory, useLocation, Link as ReactRouterLink } from 'react-router-dom';
|
|
45
44
|
import { bindActionCreators, compose } from 'redux';
|
|
46
|
-
import styled from 'styled-components';
|
|
47
45
|
|
|
48
46
|
import { INJECT_COLUMN_IN_TABLE } from '../../../exposedHooks';
|
|
47
|
+
import { useAdminUsers } from '../../../hooks/useAdminUsers';
|
|
49
48
|
import { useEnterprise } from '../../../hooks/useEnterprise';
|
|
50
|
-
import { selectAdminPermissions } from '../../../pages/App/selectors';
|
|
51
49
|
import { InjectionZone } from '../../../shared/components';
|
|
52
|
-
import
|
|
53
|
-
import {
|
|
50
|
+
import { Filter } from '../../components/Filter';
|
|
51
|
+
import { AdminUsersFilter } from '../../components/Filter/CustomInputs/AdminUsersFilter';
|
|
52
|
+
import { useAllowedAttributes } from '../../hooks/useAllowedAttributes';
|
|
53
|
+
import { getTrad, getDisplayName } from '../../utils';
|
|
54
54
|
|
|
55
55
|
import { getData, getDataSucceeded, onChangeListHeaders, onResetListHeaders } from './actions';
|
|
56
56
|
import { Body } from './components/Body';
|
|
57
57
|
import BulkActionButtons from './components/BulkActionButtons';
|
|
58
58
|
import CellContent from './components/CellContent';
|
|
59
|
-
import {
|
|
59
|
+
import { ViewSettingsMenu } from './components/ViewSettingsMenu';
|
|
60
60
|
import makeSelectListView, { selectDisplayedHeaders } from './selectors';
|
|
61
61
|
import { buildValidGetParams } from './utils';
|
|
62
62
|
|
|
63
|
-
const ConfigureLayoutBox = styled(Box)`
|
|
64
|
-
svg {
|
|
65
|
-
path {
|
|
66
|
-
fill: ${({ theme }) => theme.colors.neutral900};
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
`;
|
|
70
|
-
|
|
71
63
|
const REVIEW_WORKFLOW_COLUMNS_CE = null;
|
|
72
64
|
const REVIEW_WORKFLOW_COLUMNS_CELL_CE = () => null;
|
|
65
|
+
const REVIEW_WORKFLOW_FILTER_CE = [];
|
|
66
|
+
const CREATOR_ATTRIBUTES = ['createdBy', 'updatedBy'];
|
|
67
|
+
const USER_FILTER_ATTRIBUTES = [...CREATOR_ATTRIBUTES, 'strapi_assignee'];
|
|
73
68
|
|
|
74
69
|
function ListView({
|
|
75
70
|
canCreate,
|
|
@@ -95,23 +90,106 @@ function ListView({
|
|
|
95
90
|
const [isConfirmDeleteRowOpen, setIsConfirmDeleteRowOpen] = React.useState(false);
|
|
96
91
|
const toggleNotification = useNotification();
|
|
97
92
|
const { trackUsage } = useTracking();
|
|
98
|
-
const { refetchPermissions } = useRBACProvider();
|
|
93
|
+
const { allPermissions, refetchPermissions } = useRBACProvider();
|
|
99
94
|
const trackUsageRef = React.useRef(trackUsage);
|
|
100
95
|
const fetchPermissionsRef = React.useRef(refetchPermissions);
|
|
101
96
|
const { notifyStatus } = useNotifyAT();
|
|
102
97
|
const { formatAPIError } = useAPIErrorHandler(getTrad);
|
|
103
|
-
const
|
|
98
|
+
const allowedAttributes = useAllowedAttributes(contentType, slug);
|
|
99
|
+
const [{ query }] = useQueryParams();
|
|
100
|
+
const { pathname } = useLocation();
|
|
101
|
+
const { push } = useHistory();
|
|
102
|
+
const { formatMessage, locale } = useIntl();
|
|
103
|
+
const fetchClient = useFetchClient();
|
|
104
|
+
const formatter = useCollator(locale, {
|
|
105
|
+
sensitivity: 'base',
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const selectedUserIds =
|
|
109
|
+
query?.filters?.$and?.reduce((acc, filter) => {
|
|
110
|
+
const [key, value] = Object.entries(filter)[0];
|
|
111
|
+
const id = value.id?.$eq || value.id?.$ne;
|
|
112
|
+
|
|
113
|
+
// TODO: strapi_assignee should not be in here and rather defined
|
|
114
|
+
// in the ee directory.
|
|
115
|
+
if (USER_FILTER_ATTRIBUTES.includes(key) && !acc.includes(id)) {
|
|
116
|
+
acc.push(id);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return acc;
|
|
120
|
+
}, []) ?? [];
|
|
121
|
+
|
|
122
|
+
const { users, isLoading: isLoadingAdminUsers } = useAdminUsers(
|
|
123
|
+
{ filter: { id: { in: selectedUserIds } } },
|
|
124
|
+
{
|
|
125
|
+
// fetch the list of admin users only if the filter contains users and the
|
|
126
|
+
// current user has permissions to display users
|
|
127
|
+
enabled:
|
|
128
|
+
selectedUserIds.length > 0 &&
|
|
129
|
+
findMatchingPermissions(allPermissions, [
|
|
130
|
+
{
|
|
131
|
+
action: 'admin::users.read',
|
|
132
|
+
subject: null,
|
|
133
|
+
},
|
|
134
|
+
]).length > 0,
|
|
135
|
+
}
|
|
136
|
+
);
|
|
104
137
|
|
|
105
138
|
useFocusWhenNavigate();
|
|
106
139
|
|
|
107
|
-
const [{ query }] = useQueryParams();
|
|
108
140
|
const params = React.useMemo(() => buildValidGetParams(query), [query]);
|
|
109
141
|
const pluginsQueryParams = stringify({ plugins: query.plugins }, { encode: false });
|
|
110
142
|
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
143
|
+
const displayedAttributeFilters = allowedAttributes.map((name) => {
|
|
144
|
+
const attribute = contentType.attributes[name];
|
|
145
|
+
const { type, enum: options } = attribute;
|
|
146
|
+
|
|
147
|
+
const trackedEvent = {
|
|
148
|
+
name: 'didFilterEntries',
|
|
149
|
+
properties: { useRelation: type === 'relation' },
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const { mainField, label } = metadatas[name].list;
|
|
153
|
+
|
|
154
|
+
const filter = {
|
|
155
|
+
name,
|
|
156
|
+
metadatas: { label: formatMessage({ id: label, defaultMessage: label }) },
|
|
157
|
+
fieldSchema: { type, options, mainField },
|
|
158
|
+
trackedEvent,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
if (attribute.type === 'relation' && attribute.target === 'admin::user') {
|
|
162
|
+
filter.metadatas = {
|
|
163
|
+
...filter.metadatas,
|
|
164
|
+
customOperators: [
|
|
165
|
+
{
|
|
166
|
+
intlLabel: {
|
|
167
|
+
id: 'components.FilterOptions.FILTER_TYPES.$eq',
|
|
168
|
+
defaultMessage: 'is',
|
|
169
|
+
},
|
|
170
|
+
value: '$eq',
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
intlLabel: {
|
|
174
|
+
id: 'components.FilterOptions.FILTER_TYPES.$ne',
|
|
175
|
+
defaultMessage: 'is not',
|
|
176
|
+
},
|
|
177
|
+
value: '$ne',
|
|
178
|
+
},
|
|
179
|
+
],
|
|
180
|
+
customInput: AdminUsersFilter,
|
|
181
|
+
options: users.map((user) => ({
|
|
182
|
+
label: getDisplayName(user, formatMessage),
|
|
183
|
+
customValue: user.id.toString(),
|
|
184
|
+
})),
|
|
185
|
+
};
|
|
186
|
+
filter.fieldSchema.mainField = {
|
|
187
|
+
name: 'id',
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
return filter;
|
|
192
|
+
});
|
|
115
193
|
|
|
116
194
|
const hasDraftAndPublish = options?.draftAndPublish ?? false;
|
|
117
195
|
const hasReviewWorkflows = options?.reviewWorkflows ?? false;
|
|
@@ -128,16 +206,82 @@ function ListView({
|
|
|
128
206
|
enabled: !!options?.reviewWorkflows,
|
|
129
207
|
}
|
|
130
208
|
);
|
|
131
|
-
const
|
|
209
|
+
const ReviewWorkflowsColumns = useEnterprise(
|
|
132
210
|
REVIEW_WORKFLOW_COLUMNS_CELL_CE,
|
|
133
|
-
async () =>
|
|
134
|
-
|
|
135
|
-
|
|
211
|
+
async () => {
|
|
212
|
+
const { ReviewWorkflowsStageEE, ReviewWorkflowsAssigneeEE } = await import(
|
|
213
|
+
'../../../../../ee/admin/content-manager/pages/ListView/ReviewWorkflowsColumn'
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
return { ReviewWorkflowsStageEE, ReviewWorkflowsAssigneeEE };
|
|
217
|
+
},
|
|
136
218
|
{
|
|
137
219
|
enabled: hasReviewWorkflows,
|
|
138
220
|
}
|
|
139
221
|
);
|
|
140
222
|
|
|
223
|
+
const reviewWorkflowFilter = useEnterprise(
|
|
224
|
+
REVIEW_WORKFLOW_FILTER_CE,
|
|
225
|
+
async () =>
|
|
226
|
+
(
|
|
227
|
+
await import(
|
|
228
|
+
'../../../../../ee/admin/content-manager/components/Filter/CustomInputs/ReviewWorkflows/constants'
|
|
229
|
+
)
|
|
230
|
+
).REVIEW_WORKFLOW_FILTERS,
|
|
231
|
+
{
|
|
232
|
+
combine(ceFilters, eeFilters) {
|
|
233
|
+
return [
|
|
234
|
+
...ceFilters,
|
|
235
|
+
...eeFilters
|
|
236
|
+
.filter((eeFilter) => {
|
|
237
|
+
// do not display the filter at all, if the current user does
|
|
238
|
+
// not have permissions to read admin users
|
|
239
|
+
if (eeFilter.name === 'strapi_assignee') {
|
|
240
|
+
return (
|
|
241
|
+
findMatchingPermissions(allPermissions, [
|
|
242
|
+
{
|
|
243
|
+
action: 'admin::users.read',
|
|
244
|
+
subject: null,
|
|
245
|
+
},
|
|
246
|
+
]).length > 0
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return true;
|
|
251
|
+
})
|
|
252
|
+
.map((eeFilter) => ({
|
|
253
|
+
...eeFilter,
|
|
254
|
+
metadatas: {
|
|
255
|
+
...eeFilter.metadatas,
|
|
256
|
+
// the stage filter needs the current content-type uid to fetch
|
|
257
|
+
// the list of stages that can be assigned to this content-type
|
|
258
|
+
...(eeFilter.name === 'strapi_stage' ? { uid: contentType.uid } : {}),
|
|
259
|
+
|
|
260
|
+
// translate the filter label
|
|
261
|
+
label: formatMessage(eeFilter.metadatas.label),
|
|
262
|
+
|
|
263
|
+
// `options` allows the filter-tag to render the displayname
|
|
264
|
+
// of a user over a plain id
|
|
265
|
+
options:
|
|
266
|
+
eeFilter.name === 'strapi_assignee' &&
|
|
267
|
+
users.map((user) => ({
|
|
268
|
+
label: getDisplayName(user, formatMessage),
|
|
269
|
+
customValue: user.id.toString(),
|
|
270
|
+
})),
|
|
271
|
+
},
|
|
272
|
+
})),
|
|
273
|
+
];
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
defaultValue: [],
|
|
277
|
+
|
|
278
|
+
// we have to wait for admin users to be fully loaded, because otherwise
|
|
279
|
+
// combine is called to early and does not contain the latest state of
|
|
280
|
+
// the users array
|
|
281
|
+
enabled: hasReviewWorkflows && !isLoadingAdminUsers,
|
|
282
|
+
}
|
|
283
|
+
);
|
|
284
|
+
|
|
141
285
|
const { post, del } = fetchClient;
|
|
142
286
|
|
|
143
287
|
const bulkUnpublishMutation = useMutation(
|
|
@@ -180,6 +324,22 @@ function ListView({
|
|
|
180
324
|
data: { results, pagination: paginationResult },
|
|
181
325
|
} = await fetchClient.get(endPoint, options);
|
|
182
326
|
|
|
327
|
+
// If user enters a page number that doesn't exist, redirect him to the last page
|
|
328
|
+
if (paginationResult.page > paginationResult.pageCount && paginationResult.pageCount > 0) {
|
|
329
|
+
const query = {
|
|
330
|
+
...params,
|
|
331
|
+
page: paginationResult.pageCount,
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
push({
|
|
335
|
+
pathname,
|
|
336
|
+
state: { from: pathname },
|
|
337
|
+
search: stringify(query),
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
|
|
183
343
|
notifyStatus(
|
|
184
344
|
formatMessage(
|
|
185
345
|
{
|
|
@@ -219,7 +379,17 @@ function ListView({
|
|
|
219
379
|
});
|
|
220
380
|
}
|
|
221
381
|
},
|
|
222
|
-
[
|
|
382
|
+
[
|
|
383
|
+
formatMessage,
|
|
384
|
+
getData,
|
|
385
|
+
getDataSucceeded,
|
|
386
|
+
notifyStatus,
|
|
387
|
+
push,
|
|
388
|
+
toggleNotification,
|
|
389
|
+
fetchClient,
|
|
390
|
+
params,
|
|
391
|
+
pathname,
|
|
392
|
+
]
|
|
223
393
|
);
|
|
224
394
|
|
|
225
395
|
const handleConfirmDeleteAllData = React.useCallback(
|
|
@@ -355,13 +525,15 @@ function ListView({
|
|
|
355
525
|
|
|
356
526
|
if (reviewWorkflowColumns) {
|
|
357
527
|
// Make sure the column header label is translated
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
528
|
+
reviewWorkflowColumns.map((column) => {
|
|
529
|
+
if (typeof column.metadatas.label !== 'string') {
|
|
530
|
+
column.metadatas.label = formatMessage(column.metadatas.label);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
return column;
|
|
534
|
+
});
|
|
363
535
|
|
|
364
|
-
formattedHeaders.push(reviewWorkflowColumns);
|
|
536
|
+
formattedHeaders.push(...reviewWorkflowColumns);
|
|
365
537
|
}
|
|
366
538
|
|
|
367
539
|
return formattedHeaders;
|
|
@@ -455,7 +627,7 @@ function ListView({
|
|
|
455
627
|
};
|
|
456
628
|
|
|
457
629
|
// Block rendering until the review stage component is fully loaded in EE
|
|
458
|
-
if (!
|
|
630
|
+
if (!ReviewWorkflowsColumns) {
|
|
459
631
|
return null;
|
|
460
632
|
}
|
|
461
633
|
|
|
@@ -482,25 +654,7 @@ function ListView({
|
|
|
482
654
|
endActions={
|
|
483
655
|
<>
|
|
484
656
|
<InjectionZone area="contentManager.listView.actions" />
|
|
485
|
-
<
|
|
486
|
-
<CheckPermissions
|
|
487
|
-
permissions={permissions.contentManager.collectionTypesConfigurations}
|
|
488
|
-
>
|
|
489
|
-
<ConfigureLayoutBox paddingTop={1} paddingBottom={1}>
|
|
490
|
-
<IconButton
|
|
491
|
-
onClick={() => {
|
|
492
|
-
trackUsage('willEditListLayout');
|
|
493
|
-
}}
|
|
494
|
-
forwardedAs={ReactRouterLink}
|
|
495
|
-
to={{ pathname: `${slug}/configurations/list`, search: pluginsQueryParams }}
|
|
496
|
-
icon={<Cog />}
|
|
497
|
-
label={formatMessage({
|
|
498
|
-
id: 'app.links.configure-view',
|
|
499
|
-
defaultMessage: 'Configure the view',
|
|
500
|
-
})}
|
|
501
|
-
/>
|
|
502
|
-
</ConfigureLayoutBox>
|
|
503
|
-
</CheckPermissions>
|
|
657
|
+
<ViewSettingsMenu slug={slug} layout={layout} />
|
|
504
658
|
</>
|
|
505
659
|
}
|
|
506
660
|
startActions={
|
|
@@ -518,8 +672,12 @@ function ListView({
|
|
|
518
672
|
trackedEvent="didSearch"
|
|
519
673
|
/>
|
|
520
674
|
)}
|
|
521
|
-
{isFilterable && (
|
|
522
|
-
<
|
|
675
|
+
{isFilterable && !isLoadingAdminUsers && (
|
|
676
|
+
<Filter
|
|
677
|
+
displayedFilters={[...displayedAttributeFilters, ...reviewWorkflowFilter].sort(
|
|
678
|
+
(a, b) => formatter.compare(a.metadatas.label, b.metadatas.label)
|
|
679
|
+
)}
|
|
680
|
+
/>
|
|
523
681
|
)}
|
|
524
682
|
</>
|
|
525
683
|
}
|
|
@@ -605,19 +763,47 @@ function ListView({
|
|
|
605
763
|
);
|
|
606
764
|
}
|
|
607
765
|
|
|
608
|
-
if (hasReviewWorkflows
|
|
766
|
+
if (hasReviewWorkflows) {
|
|
767
|
+
if (name === 'strapi_stage') {
|
|
768
|
+
return (
|
|
769
|
+
<Td key={key}>
|
|
770
|
+
{rowData.strapi_stage ? (
|
|
771
|
+
<ReviewWorkflowsColumns.ReviewWorkflowsStageEE
|
|
772
|
+
color={
|
|
773
|
+
rowData.strapi_stage.color ?? lightTheme.colors.primary600
|
|
774
|
+
}
|
|
775
|
+
name={rowData.strapi_stage.name}
|
|
776
|
+
/>
|
|
777
|
+
) : (
|
|
778
|
+
<Typography textColor="neutral800">-</Typography>
|
|
779
|
+
)}
|
|
780
|
+
</Td>
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
if (name === 'strapi_assignee') {
|
|
784
|
+
return (
|
|
785
|
+
<Td key={key}>
|
|
786
|
+
{rowData.strapi_assignee ? (
|
|
787
|
+
<ReviewWorkflowsColumns.ReviewWorkflowsAssigneeEE
|
|
788
|
+
firstname={rowData.strapi_assignee.firstname}
|
|
789
|
+
lastname={rowData?.strapi_assignee?.lastname}
|
|
790
|
+
displayname={rowData?.strapi_assignee?.username}
|
|
791
|
+
/>
|
|
792
|
+
) : (
|
|
793
|
+
<Typography textColor="neutral800">-</Typography>
|
|
794
|
+
)}
|
|
795
|
+
</Td>
|
|
796
|
+
);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
if (['createdBy', 'updatedBy'].includes(name.split('.')[0])) {
|
|
801
|
+
// Display the users full name
|
|
609
802
|
return (
|
|
610
803
|
<Td key={key}>
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
rowData.strapi_stage.color ?? lightTheme.colors.primary600
|
|
615
|
-
}
|
|
616
|
-
name={rowData.strapi_stage.name}
|
|
617
|
-
/>
|
|
618
|
-
) : (
|
|
619
|
-
<Typography textColor="neutral800">-</Typography>
|
|
620
|
-
)}
|
|
804
|
+
<Typography textColor="neutral800">
|
|
805
|
+
{getDisplayName(rowData[name.split('.')[0]], formatMessage)}
|
|
806
|
+
</Typography>
|
|
621
807
|
</Td>
|
|
622
808
|
);
|
|
623
809
|
}
|
|
@@ -14,7 +14,7 @@ const ListViewLayout = ({ layout, ...props }) => {
|
|
|
14
14
|
const dispatch = useDispatch();
|
|
15
15
|
const { replace } = useHistory();
|
|
16
16
|
const [{ query, rawQuery }] = useQueryParams();
|
|
17
|
-
const permissions = useSyncRbac(query, props.slug, 'listView');
|
|
17
|
+
const { permissions, isValid: isValidPermissions } = useSyncRbac(query, props.slug, 'listView');
|
|
18
18
|
const redirectionLink = useFindRedirectionLink(props.slug);
|
|
19
19
|
|
|
20
20
|
useEffect(() => {
|
|
@@ -33,7 +33,7 @@ const ListViewLayout = ({ layout, ...props }) => {
|
|
|
33
33
|
};
|
|
34
34
|
}, [dispatch]);
|
|
35
35
|
|
|
36
|
-
if (!
|
|
36
|
+
if (!isValidPermissions) {
|
|
37
37
|
return null;
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retrieves the display name of an admin panel user
|
|
3
|
+
* @typedef AdminUserNamesAttributes
|
|
4
|
+
* @property {string} firstname
|
|
5
|
+
* @property {string} lastname
|
|
6
|
+
* @property {string} username
|
|
7
|
+
* @property {string} email
|
|
8
|
+
*
|
|
9
|
+
* @type {(user: AdminUserNamesAttributes, formatMessage: import('react-intl').formatMessage) => string}
|
|
10
|
+
*/
|
|
11
|
+
const getDisplayName = ({ firstname, lastname, username, email }, formatMessage) => {
|
|
12
|
+
if (username) {
|
|
13
|
+
return username;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// firstname is not required if the user is created with a username
|
|
17
|
+
if (firstname) {
|
|
18
|
+
return formatMessage(
|
|
19
|
+
{
|
|
20
|
+
id: 'global.fullname',
|
|
21
|
+
defaultMessage: '{firstname} {lastname}',
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
firstname,
|
|
25
|
+
lastname,
|
|
26
|
+
}
|
|
27
|
+
).trim();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return email;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { getDisplayName };
|
|
@@ -12,3 +12,4 @@ export { default as mergeMetasWithSchema } from './mergeMetasWithSchema';
|
|
|
12
12
|
export { default as removeKeyInObject } from './removeKeyInObject';
|
|
13
13
|
export { default as removePasswordFieldsFromData } from './removePasswordFieldsFromData';
|
|
14
14
|
export { default as createYupSchema } from './schema';
|
|
15
|
+
export { getDisplayName } from './getDisplayName';
|
|
@@ -612,7 +612,7 @@
|
|
|
612
612
|
"components.PageFooter.select": "Entries per page",
|
|
613
613
|
"components.ProductionBlocker.description": "For safety purposes we have to disable this plugin in other environments.",
|
|
614
614
|
"components.ProductionBlocker.header": "This plugin is only available in development.",
|
|
615
|
-
"components.
|
|
615
|
+
"components.ViewSettings.tooltip": "View settings",
|
|
616
616
|
"components.TableHeader.sort": "Sort on {label}",
|
|
617
617
|
"components.Wysiwyg.ToggleMode.markdown-mode": "Markdown mode",
|
|
618
618
|
"components.Wysiwyg.ToggleMode.preview-mode": "Preview mode",
|
|
@@ -671,6 +671,7 @@
|
|
|
671
671
|
"content-manager.components.FiltersPickWrapper.PluginHeader.description": "Set the conditions to apply to filter the entries",
|
|
672
672
|
"content-manager.components.FiltersPickWrapper.PluginHeader.title.filter": "Filters",
|
|
673
673
|
"content-manager.components.FiltersPickWrapper.hide": "Hide",
|
|
674
|
+
"content-manager.components.Filters.usersSelect.label": "Search and select a user to filter by",
|
|
674
675
|
"content-manager.components.LeftMenu.Search.label": "Search for a content type",
|
|
675
676
|
"content-manager.components.LeftMenu.collection-types": "Collection Types",
|
|
676
677
|
"content-manager.components.LeftMenu.single-types": "Single Types",
|
|
@@ -914,6 +915,7 @@
|
|
|
914
915
|
"global.settings": "Settings",
|
|
915
916
|
"global.type": "Type",
|
|
916
917
|
"global.users": "Users",
|
|
918
|
+
"global.fullname": "{firstname} {lastname}",
|
|
917
919
|
"light": "Light",
|
|
918
920
|
"notification.contentType.relations.conflict": "Content type has conflicting relations",
|
|
919
921
|
"notification.default.title": "Information:",
|