mirror of
https://github.com/strapi/strapi.git
synced 2025-06-27 00:41:25 +00:00
fix(content-manager): documentId missing from fields for the view and… (#23604)
* fix(content-manager): documentId missing from fields for the view and filters --------- Co-authored-by: Mark Kaylor <mark.kaylor@strapi.io>
This commit is contained in:
parent
3561ab6db9
commit
df5dd4b92e
@ -169,6 +169,7 @@ describe('useDocument', () => {
|
||||
},
|
||||
attributes: {
|
||||
id: { type: 'string' },
|
||||
documentId: { type: 'string' },
|
||||
slug: { type: 'uid' },
|
||||
name: { type: 'string' },
|
||||
city: {
|
||||
@ -293,6 +294,9 @@ describe('useDocument', () => {
|
||||
id: {
|
||||
type: 'string',
|
||||
},
|
||||
documentId: {
|
||||
type: 'string',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
default: 'toto',
|
||||
@ -338,6 +342,7 @@ describe('useDocument', () => {
|
||||
|
||||
expect(result.current.getInitialFormValues).toBeInstanceOf(Function);
|
||||
expect(result.current.getInitialFormValues()).toEqual({
|
||||
documentId: '12345',
|
||||
name: 'Entry 1',
|
||||
});
|
||||
});
|
||||
|
@ -39,7 +39,6 @@ describe('useDocumentActions', () => {
|
||||
documentId: '12345',
|
||||
},
|
||||
{
|
||||
documentId: '12345',
|
||||
title: 'test',
|
||||
content: 'the brown fox jumps over the lazy dog',
|
||||
}
|
||||
@ -51,7 +50,7 @@ describe('useDocumentActions', () => {
|
||||
expect(response).toEqual({
|
||||
data: {
|
||||
content: 'the brown fox jumps over the lazy dog',
|
||||
documentId: '12345',
|
||||
documentId: '67890',
|
||||
id: 2,
|
||||
title: 'test',
|
||||
},
|
||||
|
@ -681,7 +681,8 @@ const useDocumentActions: UseDocumentActions = () => {
|
||||
const clone: IUseDocumentActs['clone'] = React.useCallback(
|
||||
async ({ model, documentId, params }, body, trackerProperty) => {
|
||||
try {
|
||||
const { id: _id, ...restBody } = body;
|
||||
// Omit id and documentId so they are not copied to the clone
|
||||
const { id: _id, documentId: _documentId, ...restBody } = body;
|
||||
|
||||
/**
|
||||
* If we're cloning we want to post directly to this endpoint
|
||||
|
@ -1,6 +1,11 @@
|
||||
import { testData } from '../../../../tests/data';
|
||||
import { removeProhibitedFields } from '../data';
|
||||
|
||||
const defaultFieldsValues = {
|
||||
name: 'name',
|
||||
password: '',
|
||||
};
|
||||
|
||||
describe('data', () => {
|
||||
describe('removeProhibitedFields', () => {
|
||||
it('should return an empty object', () => {
|
||||
@ -13,9 +18,9 @@ describe('data', () => {
|
||||
const { components, contentType } = testData;
|
||||
|
||||
expect(
|
||||
removeProhibitedFields(['password'])(contentType, components)({ name: 'test' })
|
||||
removeProhibitedFields(['password'])(contentType, components)({ name: 'name' })
|
||||
).toEqual({
|
||||
name: 'test',
|
||||
name: 'name',
|
||||
});
|
||||
});
|
||||
|
||||
@ -24,10 +29,10 @@ describe('data', () => {
|
||||
|
||||
expect(
|
||||
removeProhibitedFields(['password'])(contentType, components)({
|
||||
name: 'test',
|
||||
name: 'name',
|
||||
password: 'password',
|
||||
})
|
||||
).toEqual({ name: 'test', password: '' });
|
||||
).toEqual(defaultFieldsValues);
|
||||
});
|
||||
|
||||
it('should remove all password fields', () => {
|
||||
@ -36,106 +41,70 @@ describe('data', () => {
|
||||
const result = removeProhibitedFields(['password'])(contentType, components)(modifiedData);
|
||||
|
||||
expect(result).toEqual({
|
||||
id: 1,
|
||||
name: 'name',
|
||||
createdAt: '2020-04-28T13:22:13.033Z',
|
||||
updatedAt: '2020-04-28T13:22:13.033Z',
|
||||
password: '',
|
||||
notrepeatable: {
|
||||
id: 1,
|
||||
name: 'name',
|
||||
password: '',
|
||||
subcomponotrepeatable: {
|
||||
id: 4,
|
||||
name: 'name',
|
||||
password: '',
|
||||
},
|
||||
subrepeatable: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'name',
|
||||
password: '',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'name',
|
||||
password: '',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'name',
|
||||
password: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
repeatable: [
|
||||
{
|
||||
id: 2,
|
||||
name: 'name',
|
||||
password: '',
|
||||
subcomponotrepeatable: {
|
||||
id: 6,
|
||||
name: 'name',
|
||||
password: '',
|
||||
},
|
||||
subrepeatable: [
|
||||
{
|
||||
id: 5,
|
||||
name: 'name',
|
||||
password: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'name',
|
||||
password: '',
|
||||
subcomponotrepeatable: null,
|
||||
subrepeatable: [],
|
||||
},
|
||||
],
|
||||
dz: [
|
||||
{
|
||||
__component: 'compos.sub-compo',
|
||||
id: 7,
|
||||
name: 'name',
|
||||
password: '',
|
||||
...defaultFieldsValues,
|
||||
},
|
||||
{
|
||||
__component: 'compos.test-compo',
|
||||
id: 4,
|
||||
name: 'name',
|
||||
password: '',
|
||||
documentId: '456789',
|
||||
...defaultFieldsValues,
|
||||
subcomponotrepeatable: null,
|
||||
subrepeatable: [],
|
||||
__component: 'compos.test-compo',
|
||||
},
|
||||
{
|
||||
__component: 'compos.test-compo',
|
||||
id: 5,
|
||||
name: 'name',
|
||||
password: '',
|
||||
subcomponotrepeatable: {
|
||||
id: 9,
|
||||
name: 'name',
|
||||
password: '',
|
||||
},
|
||||
subrepeatable: [
|
||||
{
|
||||
id: 8,
|
||||
name: 'name',
|
||||
password: '',
|
||||
},
|
||||
],
|
||||
documentId: '567890',
|
||||
...defaultFieldsValues,
|
||||
subcomponotrepeatable: { id: 9, name: 'name', password: '' },
|
||||
subrepeatable: [{ id: 8, name: 'name', password: '' }],
|
||||
__component: 'compos.test-compo',
|
||||
},
|
||||
{
|
||||
__component: 'compos.test-compo',
|
||||
id: 6,
|
||||
documentId: '678901',
|
||||
name: null,
|
||||
password: null,
|
||||
subcomponotrepeatable: null,
|
||||
subrepeatable: [],
|
||||
__component: 'compos.test-compo',
|
||||
},
|
||||
],
|
||||
id: 1,
|
||||
name: 'name',
|
||||
notrepeatable: {
|
||||
id: 1,
|
||||
documentId: '123456',
|
||||
...defaultFieldsValues,
|
||||
subcomponotrepeatable: { id: 4, name: 'name', password: '' },
|
||||
subrepeatable: [
|
||||
{ id: 1, name: 'name', password: '' },
|
||||
{ id: 2, name: 'name', password: '' },
|
||||
{ id: 3, name: 'name', password: '' },
|
||||
],
|
||||
},
|
||||
password: '',
|
||||
repeatable: [
|
||||
{
|
||||
id: 2,
|
||||
documentId: '234567',
|
||||
...defaultFieldsValues,
|
||||
subrepeatable: [{ id: 5, name: 'name', password: '' }],
|
||||
subcomponotrepeatable: { id: 6, name: 'name', password: '' },
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
documentId: '345678',
|
||||
...defaultFieldsValues,
|
||||
subrepeatable: [],
|
||||
subcomponotrepeatable: null,
|
||||
},
|
||||
],
|
||||
updatedAt: '2020-04-28T13:22:13.033Z',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -108,6 +108,7 @@ const FiltersImpl = ({ disabled, schema }: FiltersProps) => {
|
||||
return (
|
||||
[
|
||||
'id',
|
||||
'documentId',
|
||||
...allowedFields,
|
||||
...DEFAULT_ALLOWED_FILTERS,
|
||||
...(canReadAdminUsers ? CREATOR_FIELDS : []),
|
||||
|
@ -20,6 +20,7 @@ const testData = {
|
||||
createdAt: { type: 'timestamp' },
|
||||
dz: { type: 'dynamiczone', components: ['compos.test-compo', 'compos.sub-compo'] },
|
||||
id: { type: 'integer' },
|
||||
documentId: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
notrepeatable: {
|
||||
type: 'component',
|
||||
@ -45,6 +46,7 @@ const testData = {
|
||||
},
|
||||
attributes: {
|
||||
id: { type: 'integer' },
|
||||
documentId: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
password: { type: 'password' },
|
||||
},
|
||||
@ -62,6 +64,7 @@ const testData = {
|
||||
},
|
||||
attributes: {
|
||||
id: { type: 'integer' },
|
||||
documentId: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
password: { type: 'password' },
|
||||
subcomponotrepeatable: {
|
||||
@ -83,6 +86,7 @@ const testData = {
|
||||
{ __component: 'compos.sub-compo', id: 7, name: 'name', password: 'password' },
|
||||
{
|
||||
id: 4,
|
||||
documentId: '456789',
|
||||
name: 'name',
|
||||
password: 'password',
|
||||
subcomponotrepeatable: null,
|
||||
@ -91,6 +95,7 @@ const testData = {
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
documentId: '567890',
|
||||
name: 'name',
|
||||
password: 'password',
|
||||
subcomponotrepeatable: { id: 9, name: 'name', password: 'password' },
|
||||
@ -99,6 +104,7 @@ const testData = {
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
documentId: '678901',
|
||||
name: null,
|
||||
password: null,
|
||||
subcomponotrepeatable: null,
|
||||
@ -110,6 +116,7 @@ const testData = {
|
||||
name: 'name',
|
||||
notrepeatable: {
|
||||
id: 1,
|
||||
documentId: '123456',
|
||||
name: 'name',
|
||||
password: 'password',
|
||||
subcomponotrepeatable: { id: 4, name: 'name', password: 'password' },
|
||||
@ -123,6 +130,7 @@ const testData = {
|
||||
repeatable: [
|
||||
{
|
||||
id: 2,
|
||||
documentId: '234567',
|
||||
name: 'name',
|
||||
password: 'password',
|
||||
subrepeatable: [{ id: 5, name: 'name', password: 'password' }],
|
||||
@ -130,6 +138,7 @@ const testData = {
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
documentId: '345678',
|
||||
name: 'name',
|
||||
password: 'password',
|
||||
subrepeatable: [],
|
||||
|
@ -18,6 +18,9 @@ const CM_COMPONENTS_MOCK_DATA = [
|
||||
id: {
|
||||
type: 'string',
|
||||
},
|
||||
documentId: {
|
||||
type: 'string',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
default: 'toto',
|
||||
@ -371,6 +374,9 @@ const CM_CONTENT_TYPE_MOCK_DATA = [
|
||||
id: {
|
||||
type: 'string',
|
||||
},
|
||||
documentId: {
|
||||
type: 'string',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
@ -488,6 +494,9 @@ const CM_CONTENT_TYPE_MOCK_DATA = [
|
||||
id: {
|
||||
type: 'string',
|
||||
},
|
||||
documentId: {
|
||||
type: 'string',
|
||||
},
|
||||
Title: {
|
||||
type: 'string',
|
||||
default: 'New article',
|
||||
@ -695,6 +704,14 @@ const CM_COLLECTION_TYPE_LAYOUT_MOCK_DATA = {
|
||||
sortable: true,
|
||||
},
|
||||
},
|
||||
documentId: {
|
||||
edit: {},
|
||||
list: {
|
||||
label: 'documentId',
|
||||
searchable: true,
|
||||
sortable: true,
|
||||
},
|
||||
},
|
||||
name: {
|
||||
edit: {
|
||||
label: 'name',
|
||||
|
@ -56,7 +56,17 @@ export default {
|
||||
|
||||
const confWithUpdatedMetadata = {
|
||||
...configuration,
|
||||
metadatas: mapValues(assocMainField, configuration.metadatas),
|
||||
metadatas: {
|
||||
...mapValues(assocMainField, configuration.metadatas),
|
||||
documentId: {
|
||||
edit: {},
|
||||
list: {
|
||||
label: 'documentId',
|
||||
searchable: true,
|
||||
sortable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const components = await contentTypeService.findComponentsConfigurations(contentType);
|
||||
|
@ -27,6 +27,9 @@ export default () => ({
|
||||
type: 'integer',
|
||||
},
|
||||
...formatAttributes(contentType),
|
||||
documentId: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
|
@ -108,8 +108,10 @@ const documentManager = ({ strapi }: { strapi: Core.Strapi }) => {
|
||||
uid: UID.CollectionType
|
||||
) {
|
||||
const populate = await buildDeepPopulate(uid);
|
||||
|
||||
const params = {
|
||||
data: omitIdField(body),
|
||||
// Ensure id and documentId are not copied to the clone
|
||||
data: omit(['id', 'documentId'], body),
|
||||
populate,
|
||||
};
|
||||
|
||||
|
@ -17,6 +17,7 @@ export interface DocumentVersion {
|
||||
|
||||
const AVAILABLE_STATUS_FIELDS = [
|
||||
'id',
|
||||
'documentId',
|
||||
'locale',
|
||||
'updatedAt',
|
||||
'createdAt',
|
||||
@ -27,6 +28,7 @@ const AVAILABLE_STATUS_FIELDS = [
|
||||
];
|
||||
const AVAILABLE_LOCALES_FIELDS = [
|
||||
'id',
|
||||
'documentId',
|
||||
'locale',
|
||||
'updatedAt',
|
||||
'createdAt',
|
||||
|
@ -79,7 +79,7 @@ const isVisible = (schema: any, name: any) => {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isTimestamp(schema, name) || name === 'id') {
|
||||
if (isTimestamp(schema, name) || name === 'id' || name === 'documentId') {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ async function createDefaultLayouts(schema: any) {
|
||||
|
||||
function createDefaultListLayout(schema: any) {
|
||||
return Object.keys(schema.attributes)
|
||||
.filter((name) => isListable(schema, name))
|
||||
.filter((name) => isListable(schema, name) && name !== 'documentId')
|
||||
.slice(0, DEFAULT_LIST_LENGTH);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,14 @@ function createDefaultMetadatas(schema: any) {
|
||||
sortable: true,
|
||||
},
|
||||
},
|
||||
documentId: {
|
||||
edit: {},
|
||||
list: {
|
||||
label: 'documentId',
|
||||
searchable: true,
|
||||
sortable: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@ -95,6 +103,7 @@ async function syncMetadatas(configuration: any, schema: any) {
|
||||
const attr = schema.attributes[key];
|
||||
|
||||
const updatedMeta = { edit, list };
|
||||
|
||||
// update sortable attr
|
||||
if (list.sortable && !isSortable(schema, key)) {
|
||||
_.set(updatedMeta, ['list', 'sortable'], false);
|
||||
|
@ -9,11 +9,25 @@ test.describe('List View', () => {
|
||||
await login({ page });
|
||||
});
|
||||
|
||||
test('A user can filter entries', async ({ page }) => {
|
||||
await page.getByRole('link', { name: 'Content Manager' }).click();
|
||||
await page.getByRole('link', { name: 'Article' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Filters' }).click();
|
||||
await page.getByRole('combobox', { name: 'Select field' }).click();
|
||||
await page.getByRole('option', { name: 'documentId' }).click();
|
||||
// va0x2nt206hluydibmsoiquc => documentId for article "Why I prefer football over soccer"
|
||||
await page.getByRole('textbox', { name: 'documentId' }).fill('va0x2nt206hluydibmsoiquc');
|
||||
await page.getByRole('button', { name: 'Add filter' }).click();
|
||||
await expect(page.getByText('documentId is va0x2nt206hluydibmsoiquc')).toBeVisible();
|
||||
// There should be 2 rows, 1 for the header and 1 for the Article entry
|
||||
await expect(page.getByRole('row')).toHaveCount(2);
|
||||
});
|
||||
|
||||
test('A user should be able to navigate to the ListView of the content manager and see some entries', async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.getByRole('link', { name: 'Content Manager' }).click();
|
||||
|
||||
await expect(page).toHaveTitle('Article | Strapi');
|
||||
await expect(page.getByRole('heading', { name: 'Article' })).toBeVisible();
|
||||
await expect(page.getByRole('link', { name: /Create new entry/ }).first()).toBeVisible();
|
||||
|
Loading…
x
Reference in New Issue
Block a user