mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 15:13:21 +00:00
feat!(content-manager): remove the ability to disable draft&publish (#18488)
* feat!: remove draft and publish triggering * chore: update snapshots and tests * test: adapt tests
This commit is contained in:
parent
df37b096ba
commit
5ae0dc40cd
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -21,7 +21,6 @@ describe('Admin Permissions - Conditions', () => {
|
||||
singularName: 'article',
|
||||
pluralName: 'articles',
|
||||
displayName: 'Article',
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -40,7 +39,6 @@ describe('Admin Permissions - Conditions', () => {
|
||||
singularName: 'category',
|
||||
pluralName: 'categories',
|
||||
displayName: 'Category',
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
|
||||
@ -19,7 +19,6 @@ const baseWorkflow = {
|
||||
|
||||
const productUID = 'api::product.product';
|
||||
const productModel = {
|
||||
draftAndPublish: true,
|
||||
pluginOptions: {},
|
||||
singularName: 'product',
|
||||
pluralName: 'products',
|
||||
@ -34,7 +33,6 @@ const productModel = {
|
||||
|
||||
const articleUID = 'api::article.article';
|
||||
const articleModel = {
|
||||
draftAndPublish: true,
|
||||
pluginOptions: {},
|
||||
singularName: 'article',
|
||||
pluralName: 'articles',
|
||||
|
||||
@ -18,7 +18,6 @@ const edition = process.env.STRAPI_DISABLE_EE === 'true' ? 'CE' : 'EE';
|
||||
|
||||
const productUID = 'api::product.product';
|
||||
const model = {
|
||||
draftAndPublish: true,
|
||||
pluginOptions: {},
|
||||
singularName: 'product',
|
||||
pluralName: 'products',
|
||||
|
||||
@ -19,7 +19,6 @@ const edition = process.env.STRAPI_DISABLE_EE === 'true' ? 'CE' : 'EE';
|
||||
|
||||
const productUID = 'api::product.product';
|
||||
const model = {
|
||||
draftAndPublish: false,
|
||||
pluginOptions: {},
|
||||
singularName: 'product',
|
||||
pluralName: 'products',
|
||||
@ -55,6 +54,12 @@ describeOnCondition(edition === 'EE')('Review workflows', () => {
|
||||
url: `/content-manager/collection-types/${uid}`,
|
||||
body: data,
|
||||
});
|
||||
|
||||
await requests.admin({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/${uid}/${body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
return body;
|
||||
};
|
||||
|
||||
|
||||
@ -80,7 +80,7 @@ describe('CM API - Basic + compo', () => {
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(product);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.productsWithCompo.push(res.body);
|
||||
});
|
||||
|
||||
@ -92,7 +92,7 @@ describe('CM API - Basic + compo', () => {
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(data.productsWithCompo[0]);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
});
|
||||
|
||||
test('Update product with compo', async () => {
|
||||
@ -115,7 +115,7 @@ describe('CM API - Basic + compo', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(product);
|
||||
expect(res.body.id).toEqual(data.productsWithCompo[0].id);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.productsWithCompo[0] = res.body;
|
||||
});
|
||||
|
||||
@ -128,7 +128,7 @@ describe('CM API - Basic + compo', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(data.productsWithCompo[0]);
|
||||
expect(res.body.id).toEqual(data.productsWithCompo[0].id);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.productsWithCompo.shift();
|
||||
});
|
||||
|
||||
@ -175,12 +175,18 @@ describe('CM API - Basic + compo', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
const res = await rq({
|
||||
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-compo.product-with-compo',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product-with-compo.product-with-compo/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
@ -248,24 +254,30 @@ describe('CM API - Basic + compo', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
const res = await rq({
|
||||
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-compo.product-with-compo',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product-with-compo.product-with-compo/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
error: {
|
||||
status: 400,
|
||||
name: 'ValidationError',
|
||||
message: 'compo[0].name must be defined.',
|
||||
message: 'compo[0].name must be a `string` type, but the final value was: `null`.',
|
||||
details: {
|
||||
errors: [
|
||||
{
|
||||
path: ['compo', '0', 'name'],
|
||||
message: 'compo[0].name must be defined.',
|
||||
message: 'compo[0].name must be a `string` type, but the final value was: `null`.',
|
||||
name: 'ValidationError',
|
||||
},
|
||||
],
|
||||
|
||||
@ -77,7 +77,7 @@ describe('CM API - Basic + compo', () => {
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(product);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.productsWithCompo.push(res.body);
|
||||
});
|
||||
|
||||
@ -89,7 +89,7 @@ describe('CM API - Basic + compo', () => {
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(data.productsWithCompo[0]);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
});
|
||||
|
||||
test('Update product with compo', async () => {
|
||||
@ -110,7 +110,7 @@ describe('CM API - Basic + compo', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(product);
|
||||
expect(res.body.id).toEqual(data.productsWithCompo[0].id);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.productsWithCompo[0] = res.body;
|
||||
});
|
||||
|
||||
@ -123,7 +123,7 @@ describe('CM API - Basic + compo', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(data.productsWithCompo[0]);
|
||||
expect(res.body.id).toEqual(data.productsWithCompo[0].id);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.productsWithCompo.shift();
|
||||
});
|
||||
|
||||
@ -152,28 +152,34 @@ describe('CM API - Basic + compo', () => {
|
||||
});
|
||||
|
||||
describe('validation', () => {
|
||||
test('Cannot create product with compo - compo required', async () => {
|
||||
test('Cannot publish product with compo - compo required', async () => {
|
||||
const product = {
|
||||
name: 'Product 1',
|
||||
description: 'Product description',
|
||||
};
|
||||
const res = await rq({
|
||||
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-compo.product-with-compo',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product-with-compo.product-with-compo/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
error: {
|
||||
message: 'compo must be defined.',
|
||||
message: 'compo must be a `object` type, but the final value was: `null`.',
|
||||
name: 'ValidationError',
|
||||
details: {
|
||||
errors: [
|
||||
{
|
||||
path: ['compo'],
|
||||
message: 'compo must be defined.',
|
||||
message: 'compo must be a `object` type, but the final value was: `null`.',
|
||||
name: 'ValidationError',
|
||||
},
|
||||
],
|
||||
@ -182,7 +188,7 @@ describe('CM API - Basic + compo', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Cannot create product with compo - minLength', async () => {
|
||||
test('Cannot publish product with compo - minLength', async () => {
|
||||
const product = {
|
||||
name: 'Product 1',
|
||||
description: 'Product description',
|
||||
@ -191,12 +197,18 @@ describe('CM API - Basic + compo', () => {
|
||||
description: '',
|
||||
},
|
||||
};
|
||||
const res = await rq({
|
||||
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-compo.product-with-compo',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product-with-compo.product-with-compo/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
@ -225,6 +237,7 @@ describe('CM API - Basic + compo', () => {
|
||||
description: 'A very long description that exceed the min length.',
|
||||
},
|
||||
};
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-compo.product-with-compo',
|
||||
@ -250,7 +263,7 @@ describe('CM API - Basic + compo', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Cannot create product with compo - required', async () => {
|
||||
test('Cannot publish product with compo - required', async () => {
|
||||
const product = {
|
||||
name: 'Product 1',
|
||||
description: 'Product description',
|
||||
@ -258,23 +271,29 @@ describe('CM API - Basic + compo', () => {
|
||||
description: 'short',
|
||||
},
|
||||
};
|
||||
const res = await rq({
|
||||
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-compo.product-with-compo',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product-with-compo.product-with-compo/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
error: {
|
||||
message: 'compo.name must be defined.',
|
||||
message: 'compo.name must be a `string` type, but the final value was: `null`.',
|
||||
name: 'ValidationError',
|
||||
details: {
|
||||
errors: [
|
||||
{
|
||||
path: ['compo', 'name'],
|
||||
message: 'compo.name must be defined.',
|
||||
message: 'compo.name must be a `string` type, but the final value was: `null`.',
|
||||
name: 'ValidationError',
|
||||
},
|
||||
],
|
||||
|
||||
@ -43,7 +43,6 @@ const productWithCompoAndDP = {
|
||||
repeatable: true,
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'product with compo and DP',
|
||||
singularName: 'product-with-compo-and-dp',
|
||||
pluralName: 'product-with-compo-and-dps',
|
||||
@ -51,7 +50,7 @@ const productWithCompoAndDP = {
|
||||
collectionName: '',
|
||||
};
|
||||
|
||||
describe('CM API - Basic + compo + draftAndPublish', () => {
|
||||
describe('CM API - Basic + compo', () => {
|
||||
beforeAll(async () => {
|
||||
await builder.addComponent(compo).addContentType(productWithCompoAndDP).build();
|
||||
|
||||
|
||||
@ -42,7 +42,6 @@ const productWithCompoAndDP = {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'product with compo and DP',
|
||||
singularName: 'product-with-compo-and-dp',
|
||||
pluralName: 'product-with-compo-and-dps',
|
||||
@ -50,7 +49,7 @@ const productWithCompoAndDP = {
|
||||
collectionName: '',
|
||||
};
|
||||
|
||||
describe('CM API - Basic + compo + draftAndPublish', () => {
|
||||
describe('CM API - Basic + compo', () => {
|
||||
beforeAll(async () => {
|
||||
await builder.addComponent(compo).addContentType(productWithCompoAndDP).build();
|
||||
|
||||
|
||||
@ -42,7 +42,6 @@ const productWithCompoAndDP = {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'product with dz and DP',
|
||||
singularName: 'product-with-dz-and-dp',
|
||||
pluralName: 'product-with-dz-and-dps',
|
||||
@ -50,7 +49,7 @@ const productWithCompoAndDP = {
|
||||
collectionName: '',
|
||||
};
|
||||
|
||||
describe('CM API - Basic + dz + draftAndPublish', () => {
|
||||
describe('CM API - Basic + dz', () => {
|
||||
beforeAll(async () => {
|
||||
await builder.addComponent(compo).addContentType(productWithCompoAndDP).build();
|
||||
|
||||
|
||||
@ -25,7 +25,6 @@ const productWithDP = {
|
||||
maxLength: 30,
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'product with DP',
|
||||
singularName: 'product-with-dp',
|
||||
pluralName: 'product-with-dps',
|
||||
@ -48,7 +47,7 @@ const compo = {
|
||||
},
|
||||
};
|
||||
|
||||
describe('CM API - Basic + draftAndPublish', () => {
|
||||
describe('CM API - Basic', () => {
|
||||
beforeAll(async () => {
|
||||
await builder.addComponent(compo).addContentType(productWithDP).build();
|
||||
|
||||
|
||||
@ -80,7 +80,7 @@ describe('CM API - Basic + dz', () => {
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(product);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBe(null);
|
||||
data.productsWithDz.push(res.body);
|
||||
});
|
||||
|
||||
@ -92,7 +92,7 @@ describe('CM API - Basic + dz', () => {
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(data.productsWithDz[0]);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBe(null);
|
||||
});
|
||||
|
||||
test('Update product with compo', async () => {
|
||||
@ -116,7 +116,7 @@ describe('CM API - Basic + dz', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(product);
|
||||
expect(res.body.id).toEqual(data.productsWithDz[0].id);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBe(null);
|
||||
data.productsWithDz[0] = res.body;
|
||||
});
|
||||
|
||||
@ -129,7 +129,7 @@ describe('CM API - Basic + dz', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(data.productsWithDz[0]);
|
||||
expect(res.body.id).toEqual(data.productsWithDz[0].id);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBe(null);
|
||||
data.productsWithDz.shift();
|
||||
});
|
||||
|
||||
@ -162,7 +162,7 @@ describe('CM API - Basic + dz', () => {
|
||||
});
|
||||
|
||||
describe('validation', () => {
|
||||
test('Cannot create product with compo - compo required', async () => {
|
||||
test('Cannot publish product with compo - compo required', async () => {
|
||||
const product = {
|
||||
name: 'Product 1',
|
||||
description: 'Product description',
|
||||
@ -205,12 +205,17 @@ describe('CM API - Basic + dz', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
const res = await rq({
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-dz.product-with-dz',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product-with-dz.product-with-dz/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
@ -280,24 +285,30 @@ describe('CM API - Basic + dz', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
const res = await rq({
|
||||
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-dz.product-with-dz',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product-with-dz.product-with-dz/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
error: {
|
||||
status: 400,
|
||||
name: 'ValidationError',
|
||||
message: 'dz[0].name must be defined.',
|
||||
message: 'dz[0].name must be a `string` type, but the final value was: `null`.',
|
||||
details: {
|
||||
errors: [
|
||||
{
|
||||
path: ['dz', '0', 'name'],
|
||||
message: 'dz[0].name must be defined.',
|
||||
message: 'dz[0].name must be a `string` type, but the final value was: `null`.',
|
||||
name: 'ValidationError',
|
||||
},
|
||||
],
|
||||
@ -317,6 +328,7 @@ describe('CM API - Basic + dz', () => {
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product-with-dz.product-with-dz',
|
||||
|
||||
@ -70,7 +70,7 @@ describe('CM API - Basic', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(omit('hiddenAttribute', product));
|
||||
expect(res.body).not.toHaveProperty('hiddenAttribute');
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.products.push(res.body);
|
||||
});
|
||||
|
||||
@ -91,7 +91,7 @@ describe('CM API - Basic', () => {
|
||||
}),
|
||||
])
|
||||
);
|
||||
res.body.results.forEach((p) => expect(p.publishedAt).toBeUndefined());
|
||||
res.body.results.forEach((p) => expect(p.publishedAt).toBeDefined());
|
||||
});
|
||||
|
||||
test('Update product', async () => {
|
||||
@ -109,7 +109,7 @@ describe('CM API - Basic', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(omit('hiddenAttribute', product));
|
||||
expect(res.body.id).toEqual(data.products[0].id);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.products[0] = res.body;
|
||||
});
|
||||
|
||||
@ -122,7 +122,7 @@ describe('CM API - Basic', () => {
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(data.products[0]);
|
||||
expect(res.body.id).toEqual(data.products[0].id);
|
||||
expect(res.body.publishedAt).toBeUndefined();
|
||||
expect(res.body.publishedAt).toBeDefined();
|
||||
data.products.shift();
|
||||
});
|
||||
|
||||
@ -176,17 +176,23 @@ describe('CM API - Basic', () => {
|
||||
});
|
||||
|
||||
describe('validators', () => {
|
||||
test('Cannot create a product - minLength', async () => {
|
||||
test('Cannot publish a product - minLength', async () => {
|
||||
const product = {
|
||||
name: 'Product 1',
|
||||
description: '',
|
||||
};
|
||||
const res = await rq({
|
||||
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product.product/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
@ -206,27 +212,33 @@ describe('CM API - Basic', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Cannot create a product - required', async () => {
|
||||
test('Cannot publish a product - required', async () => {
|
||||
const product = {
|
||||
description: 'Product description',
|
||||
};
|
||||
const res = await rq({
|
||||
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
body: product,
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::product.product/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
error: {
|
||||
message: 'name must be defined.',
|
||||
message: 'name must be a `string` type, but the final value was: `null`.',
|
||||
name: 'ValidationError',
|
||||
details: {
|
||||
errors: [
|
||||
{
|
||||
path: ['name'],
|
||||
message: 'name must be defined.',
|
||||
message: 'name must be a `string` type, but the final value was: `null`.',
|
||||
name: 'ValidationError',
|
||||
},
|
||||
],
|
||||
@ -240,6 +252,7 @@ describe('CM API - Basic', () => {
|
||||
name: 'Product 1',
|
||||
description: "I'm a product description that is very long. At least thirty characters.",
|
||||
};
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::product.product',
|
||||
|
||||
@ -64,7 +64,6 @@ const categoryDPModel = {
|
||||
displayName: 'Category Draft & Publish',
|
||||
singularName: 'categorydp',
|
||||
pluralName: 'categoriesdp',
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
@ -123,6 +122,12 @@ describe('CM API - Basic', () => {
|
||||
url: '/content-manager/collection-types/api::category.category',
|
||||
body: { name: 'Food' },
|
||||
});
|
||||
|
||||
await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::category.category/${category.id}/actions/publish`,
|
||||
});
|
||||
|
||||
data.categories.push(category);
|
||||
|
||||
const { body: categoryPublished } = await rq({
|
||||
@ -130,10 +135,12 @@ describe('CM API - Basic', () => {
|
||||
url: '/content-manager/collection-types/api::categorydp.categorydp',
|
||||
body: { name: 'Food' },
|
||||
});
|
||||
|
||||
await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::categorydp.categorydp/${categoryPublished.id}/actions/publish`,
|
||||
});
|
||||
|
||||
data.categoriesdp.published.push(categoryPublished);
|
||||
|
||||
const { body: categoryDraft1 } = await rq({
|
||||
@ -141,6 +148,7 @@ describe('CM API - Basic', () => {
|
||||
url: '/content-manager/collection-types/api::categorydp.categorydp',
|
||||
body: { name: 'Food' },
|
||||
});
|
||||
|
||||
data.categoriesdp.draft.push(categoryDraft1);
|
||||
|
||||
const { body: categoryDraft2 } = await rq({
|
||||
@ -148,6 +156,7 @@ describe('CM API - Basic', () => {
|
||||
url: '/content-manager/collection-types/api::categorydp.categorydp',
|
||||
body: { name: 'Food' },
|
||||
});
|
||||
|
||||
data.categoriesdp.draft.push(categoryDraft2);
|
||||
});
|
||||
|
||||
|
||||
@ -105,8 +105,8 @@ describe('Non repeatable and required component', () => {
|
||||
}
|
||||
);
|
||||
|
||||
test('Throws when sending a null value', async () => {
|
||||
const res = await rq.post('/', {
|
||||
test('Throws when publishing a null value', async () => {
|
||||
const creationRes = await rq.post('/', {
|
||||
body: {
|
||||
field: null,
|
||||
},
|
||||
@ -115,17 +115,21 @@ describe('Non repeatable and required component', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const res = await rq.post(`/${creationRes.body.id}/actions/publish`);
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
});
|
||||
|
||||
test('Throws when the component is not provided', async () => {
|
||||
const res = await rq.post('/', {
|
||||
const creationRes = await rq.post('/', {
|
||||
body: {},
|
||||
qs: {
|
||||
populate: ['field'],
|
||||
},
|
||||
});
|
||||
|
||||
const res = await rq.post(`/${creationRes.body.id}/actions/publish`);
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
});
|
||||
});
|
||||
@ -231,8 +235,8 @@ describe('Non repeatable and required component', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Throws if component is null', async () => {
|
||||
const res = await rq.post('/', {
|
||||
test('Throws when publishing if component is null', async () => {
|
||||
const creationRes = await rq.post('/', {
|
||||
body: {
|
||||
field: {
|
||||
name: 'someString',
|
||||
@ -243,7 +247,7 @@ describe('Non repeatable and required component', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const updateRes = await rq.put(`/${res.body.id}`, {
|
||||
const updateRes = await rq.put(`/${creationRes.body.id}`, {
|
||||
body: {
|
||||
field: null,
|
||||
},
|
||||
@ -252,16 +256,18 @@ describe('Non repeatable and required component', () => {
|
||||
},
|
||||
});
|
||||
|
||||
expect(updateRes.statusCode).toBe(400);
|
||||
const res = await rq.post(`/${updateRes.body.id}/actions/publish`);
|
||||
|
||||
const getRes = await rq.get(`/${res.body.id}`, {
|
||||
expect(res.statusCode).toBe(400);
|
||||
|
||||
const getRes = await rq.get(`/${creationRes.body.id}`, {
|
||||
qs: {
|
||||
populate: ['field'],
|
||||
},
|
||||
});
|
||||
|
||||
expect(getRes.statusCode).toBe(200);
|
||||
expect(getRes.body).toMatchObject(res.body);
|
||||
expect(getRes.body).toMatchObject(updateRes.body);
|
||||
});
|
||||
|
||||
test('Replaces the previous component if sent without id', async () => {
|
||||
|
||||
@ -155,7 +155,7 @@ describe('Test type UID', () => {
|
||||
});
|
||||
|
||||
test('Cannot set value to be null', async () => {
|
||||
const res = await rq.post(
|
||||
const createRes = await rq.post(
|
||||
'/content-manager/collection-types/api::withrequireduid.withrequireduid',
|
||||
{
|
||||
body: {
|
||||
@ -164,6 +164,10 @@ describe('Test type UID', () => {
|
||||
}
|
||||
);
|
||||
|
||||
const res = await rq.post(
|
||||
`/content-manager/collection-types/api::withrequireduid.withrequireduid/${createRes.body.id}/actions/publish`
|
||||
);
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
});
|
||||
});
|
||||
|
||||
@ -36,8 +36,7 @@ const compo = (withRelations = false) => ({
|
||||
},
|
||||
});
|
||||
|
||||
const productModel = (draftAndPublish = false) => ({
|
||||
draftAndPublish,
|
||||
const productModel = () => ({
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
@ -50,8 +49,7 @@ const productModel = (draftAndPublish = false) => ({
|
||||
collectionName: '',
|
||||
});
|
||||
|
||||
const shopModel = (draftAndPublish = false) => ({
|
||||
draftAndPublish,
|
||||
const shopModel = () => ({
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
@ -110,15 +108,14 @@ const createEntry = async (uid, data) => {
|
||||
return body;
|
||||
};
|
||||
|
||||
describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish) => {
|
||||
describe('Relations, with d&p: %p', () => {
|
||||
const builder = createTestBuilder();
|
||||
const addPublishedAtCheck = (value) => (withDraftAndPublish ? { publishedAt: value } : undefined);
|
||||
const addPublishedAtCheck = (value) => {
|
||||
publishedAt: value;
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await builder
|
||||
.addComponent(compo(false))
|
||||
.addContentTypes([productModel(withDraftAndPublish), shopModel(withDraftAndPublish)])
|
||||
.build();
|
||||
await builder.addComponent(compo(false)).addContentTypes([productModel(), shopModel()]).build();
|
||||
|
||||
await modelsUtils.modifyComponent(compo(true));
|
||||
|
||||
@ -128,12 +125,10 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish
|
||||
const createdProduct1 = await createEntry('api::product.product', { name: 'Skate' });
|
||||
const createdProduct2 = await createEntry('api::product.product', { name: 'Candle' });
|
||||
|
||||
if (withDraftAndPublish) {
|
||||
await rq({
|
||||
url: `/content-manager/collection-types/api::product.product/${createdProduct1.id}/actions/publish`,
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
await rq({
|
||||
url: `/content-manager/collection-types/api::product.product/${createdProduct1.id}/actions/publish`,
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
data.products.push(createdProduct1);
|
||||
data.products.push(createdProduct2);
|
||||
|
||||
@ -36,8 +36,7 @@ const compo = (withRelations = false) => ({
|
||||
},
|
||||
});
|
||||
|
||||
const productModel = (draftAndPublish = false) => ({
|
||||
draftAndPublish,
|
||||
const productModel = () => ({
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
@ -50,8 +49,7 @@ const productModel = (draftAndPublish = false) => ({
|
||||
collectionName: '',
|
||||
});
|
||||
|
||||
const shopModel = (draftAndPublish = false) => ({
|
||||
draftAndPublish,
|
||||
const shopModel = () => ({
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
@ -110,15 +108,14 @@ const createEntry = async (uid, data) => {
|
||||
return body;
|
||||
};
|
||||
|
||||
describe.each([false, true])('Relations, with d&p: %s', (withDraftAndPublish) => {
|
||||
describe('Relations', () => {
|
||||
const builder = createTestBuilder();
|
||||
const addPublishedAtCheck = (value) => (withDraftAndPublish ? { publishedAt: value } : undefined);
|
||||
const addPublishedAtCheck = (value) => {
|
||||
publishedAt: value;
|
||||
};
|
||||
|
||||
beforeAll(async () => {
|
||||
await builder
|
||||
.addComponent(compo(false))
|
||||
.addContentTypes([productModel(withDraftAndPublish), shopModel(withDraftAndPublish)])
|
||||
.build();
|
||||
await builder.addComponent(compo(false)).addContentTypes([productModel(), shopModel()]).build();
|
||||
|
||||
await modelsUtils.modifyComponent(compo(true));
|
||||
|
||||
@ -129,12 +126,10 @@ describe.each([false, true])('Relations, with d&p: %s', (withDraftAndPublish) =>
|
||||
const createdProduct2 = await createEntry('api::product.product', { name: 'Candle' });
|
||||
const createdProduct3 = await createEntry('api::product.product', { name: 'Tofu' });
|
||||
|
||||
if (withDraftAndPublish) {
|
||||
await rq({
|
||||
url: `/content-manager/collection-types/api::product.product/${createdProduct1.id}/actions/publish`,
|
||||
method: 'POST',
|
||||
});
|
||||
}
|
||||
await rq({
|
||||
url: `/content-manager/collection-types/api::product.product/${createdProduct1.id}/actions/publish`,
|
||||
method: 'POST',
|
||||
});
|
||||
|
||||
data.products.push(createdProduct1);
|
||||
data.products.push(createdProduct2);
|
||||
|
||||
@ -99,7 +99,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
});
|
||||
|
||||
test('Create tag2', async () => {
|
||||
@ -123,7 +123,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
});
|
||||
|
||||
test('Create tag3', async () => {
|
||||
@ -147,7 +147,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
});
|
||||
|
||||
test('Create article1 without relation', async () => {
|
||||
@ -176,7 +176,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
|
||||
const tags = (await getRelations('article', 'tags', body.id)).results;
|
||||
expect(tags.length).toBe(0);
|
||||
@ -208,7 +208,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
|
||||
const tags = (await getRelations('article', 'tags', body.id)).results;
|
||||
expect(tags.length).toBe(1);
|
||||
@ -239,7 +239,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
|
||||
const tags = (await getRelations('article', 'tags', body.id)).results;
|
||||
expect(tags.length).toBe(1);
|
||||
@ -266,7 +266,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
|
||||
const tags = (await getRelations('article', 'tags', body.id)).results;
|
||||
expect(tags.length).toBe(3);
|
||||
@ -292,7 +292,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
|
||||
const tags = (await getRelations('article', 'tags', body.id)).results;
|
||||
expect(tags.length).toBe(2);
|
||||
@ -322,7 +322,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
|
||||
const tags = (await getRelations('article', 'tags', body.id)).results;
|
||||
expect(tags.length).toBe(0);
|
||||
@ -484,7 +484,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
|
||||
const articles = (await getRelations('category', 'articles', body.id)).results;
|
||||
expect(articles.length).toBe(0);
|
||||
@ -511,7 +511,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
const articles = (await getRelations('category', 'articles', body.id)).results;
|
||||
expect(articles.length).toBe(0);
|
||||
});
|
||||
@ -542,7 +542,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
|
||||
const tags = (await getRelations('article', 'tags', body.id)).results;
|
||||
expect(tags.length).toBe(0);
|
||||
@ -816,7 +816,7 @@ describe('Relations', () => {
|
||||
id: 1,
|
||||
username: null,
|
||||
});
|
||||
expect(body.publishedAt).toBeUndefined();
|
||||
expect(body.publishedAt).toBeDefined();
|
||||
});
|
||||
|
||||
test('Update article1 with ref1', async () => {
|
||||
|
||||
@ -18,7 +18,6 @@ exports[`Content Type Builder - Content types Collection Types Get collection ty
|
||||
"collectionName": "test_collection_types",
|
||||
"description": "",
|
||||
"displayName": "Test Collection Type",
|
||||
"draftAndPublish": false,
|
||||
"kind": "collectionType",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
@ -35,7 +34,7 @@ exports[`Content Type Builder - Content types Collection Types Get collection ty
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Content Type Builder - Content types Collection Types Get collection type returns full schema and informations with draftAndPublish 1`] = `
|
||||
exports[`Content Type Builder - Content types Collection Types Get collection type returns full schema and informations 1`] = `
|
||||
{
|
||||
"data": {
|
||||
"apiID": "ct-with-dp",
|
||||
@ -48,7 +47,6 @@ exports[`Content Type Builder - Content types Collection Types Get collection ty
|
||||
"collectionName": "ct_with_dps",
|
||||
"description": "",
|
||||
"displayName": "CT with DP",
|
||||
"draftAndPublish": true,
|
||||
"kind": "collectionType",
|
||||
"pluralName": "ct-with-dps",
|
||||
"restrictRelationsTo": null,
|
||||
|
||||
@ -18,7 +18,6 @@ exports[`Content Type Builder - Content types Single Types Get single type retur
|
||||
"collectionName": "test_single_types",
|
||||
"description": "",
|
||||
"displayName": "Test Single Type",
|
||||
"draftAndPublish": false,
|
||||
"kind": "singleType",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
|
||||
@ -114,7 +114,7 @@ describe('Content Type Builder - Content types', () => {
|
||||
expect(res.body).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('Successful creation of a collection type with draftAndPublish enabled', async () => {
|
||||
test('Successful creation of a collection type', async () => {
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-type-builder/content-types',
|
||||
@ -123,7 +123,6 @@ describe('Content Type Builder - Content types', () => {
|
||||
displayName: 'CT with DP',
|
||||
singularName: 'ct-with-dp',
|
||||
pluralName: 'ct-with-dps',
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -141,7 +140,7 @@ describe('Content Type Builder - Content types', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('Get collection type returns full schema and informations with draftAndPublish', async () => {
|
||||
test('Get collection type returns full schema and informations', async () => {
|
||||
const res = await rq({
|
||||
method: 'GET',
|
||||
url: `/content-type-builder/content-types/${ctWithDpUID}`,
|
||||
@ -208,7 +207,6 @@ describe('Content Type Builder - Content types', () => {
|
||||
displayName: 'same string',
|
||||
singularName: 'same-string',
|
||||
pluralName: 'same-string',
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -242,7 +240,6 @@ describe('Content Type Builder - Content types', () => {
|
||||
url: '/content-type-builder/content-types',
|
||||
body: {
|
||||
contentType: {
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -295,7 +292,6 @@ describe('Content Type Builder - Content types', () => {
|
||||
displayName: 'new displayName',
|
||||
singularName: 'ct-with-dp-new',
|
||||
pluralName: 'ct-with-dps-new',
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -321,7 +317,6 @@ describe('Content Type Builder - Content types', () => {
|
||||
displayName: 'new displayName',
|
||||
singularName: 'ct-with-dp', // no change
|
||||
pluralName: 'ct-with-dps',
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -350,7 +345,6 @@ describe('Content Type Builder - Content types', () => {
|
||||
displayName: 'same string',
|
||||
singularName,
|
||||
pluralName,
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
|
||||
@ -91,7 +91,7 @@ describe('Core API - Basic + compo', () => {
|
||||
attributes: product,
|
||||
});
|
||||
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
data.productsWithCompo.push(body.data);
|
||||
});
|
||||
|
||||
@ -110,7 +110,7 @@ describe('Core API - Basic + compo', () => {
|
||||
expect(body.data[0]).toMatchObject(data.productsWithCompo[0]);
|
||||
|
||||
body.data.forEach((p) => {
|
||||
expect(p.attributes.publishedAt).toBeUndefined();
|
||||
expect(p.attributes.publishedAt).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -144,7 +144,7 @@ describe('Core API - Basic + compo', () => {
|
||||
attributes: product,
|
||||
});
|
||||
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
expect(body.data.publishedAt).toBeUndefined();
|
||||
|
||||
data.productsWithCompo[0] = body.data;
|
||||
@ -162,7 +162,7 @@ describe('Core API - Basic + compo', () => {
|
||||
expect(statusCode).toBe(200);
|
||||
expect(body.data).toMatchObject(data.productsWithCompo[0]);
|
||||
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
data.productsWithCompo.shift();
|
||||
});
|
||||
|
||||
|
||||
@ -92,7 +92,7 @@ describe('Core API - Basic + compo', () => {
|
||||
attributes: product,
|
||||
});
|
||||
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
data.productsWithCompo.push(body.data);
|
||||
});
|
||||
|
||||
@ -110,7 +110,7 @@ describe('Core API - Basic + compo', () => {
|
||||
expect(body.data).toHaveLength(1);
|
||||
expect(body.data[0]).toMatchObject(data.productsWithCompo[0]);
|
||||
body.data.forEach((p) => {
|
||||
expect(p.attributes.publishedAt).toBeUndefined();
|
||||
expect(p.attributes.publishedAt).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -141,7 +141,7 @@ describe('Core API - Basic + compo', () => {
|
||||
attributes: product,
|
||||
});
|
||||
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
data.productsWithCompo[0] = body.data;
|
||||
});
|
||||
|
||||
@ -157,7 +157,7 @@ describe('Core API - Basic + compo', () => {
|
||||
expect(statusCode).toBe(200);
|
||||
|
||||
expect(body.data).toMatchObject(data.productsWithCompo[0]);
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
data.productsWithCompo.shift();
|
||||
});
|
||||
|
||||
|
||||
@ -41,7 +41,6 @@ const productWithCompoAndDP = {
|
||||
repeatable: true,
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'product-with-compo-and-dp',
|
||||
singularName: 'product-with-compo-and-dp',
|
||||
pluralName: 'product-with-compo-and-dps',
|
||||
@ -49,7 +48,7 @@ const productWithCompoAndDP = {
|
||||
collectionName: '',
|
||||
};
|
||||
|
||||
describe('Core API - Basic + compo + draftAndPublish', () => {
|
||||
describe('Core API - Basic + compo ', () => {
|
||||
beforeAll(async () => {
|
||||
await builder.addComponent(compo).addContentType(productWithCompoAndDP).build();
|
||||
|
||||
|
||||
@ -40,7 +40,6 @@ const productWithCompoAndDP = {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'product-with-compo-and-dp',
|
||||
singularName: 'product-with-compo-and-dp',
|
||||
pluralName: 'product-with-compo-and-dps',
|
||||
@ -48,7 +47,7 @@ const productWithCompoAndDP = {
|
||||
collectionName: '',
|
||||
};
|
||||
|
||||
describe('Core API - Basic + compo + draftAndPublish', () => {
|
||||
describe('Core API - Basic + compo', () => {
|
||||
beforeAll(async () => {
|
||||
await builder.addComponent(compo).addContentType(productWithCompoAndDP).build();
|
||||
|
||||
|
||||
@ -40,7 +40,6 @@ const productWithDP = {
|
||||
maxLength: 30,
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'product-with-dp',
|
||||
singularName: 'product-with-dp',
|
||||
pluralName: 'product-with-dps',
|
||||
@ -48,7 +47,7 @@ const productWithDP = {
|
||||
collectionName: '',
|
||||
};
|
||||
|
||||
describe('Core API - Basic + draftAndPublish', () => {
|
||||
describe('Core API - Basic', () => {
|
||||
beforeAll(async () => {
|
||||
await builder.addComponent(compo).addContentType(productWithDP).build();
|
||||
|
||||
|
||||
@ -91,7 +91,7 @@ describe('Core API - Basic + dz', () => {
|
||||
attributes: product,
|
||||
});
|
||||
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
|
||||
data.productWithDz.push(body.data);
|
||||
});
|
||||
@ -109,7 +109,7 @@ describe('Core API - Basic + dz', () => {
|
||||
expect(body.data).toHaveLength(1);
|
||||
expect(body.data[0]).toMatchObject(data.productWithDz[0]);
|
||||
body.data.forEach((p) => {
|
||||
expect(p.attributes.publishedAt).toBeUndefined();
|
||||
expect(p.attributes.publishedAt).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -143,7 +143,7 @@ describe('Core API - Basic + dz', () => {
|
||||
attributes: product,
|
||||
});
|
||||
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
data.productWithDz[0] = body.data;
|
||||
});
|
||||
|
||||
@ -159,7 +159,7 @@ describe('Core API - Basic + dz', () => {
|
||||
expect(statusCode).toBe(200);
|
||||
|
||||
expect(body.data).toMatchObject(data.productWithDz[0]);
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
data.productWithDz.shift();
|
||||
});
|
||||
|
||||
|
||||
@ -77,7 +77,7 @@ describe('Core API - Basic', () => {
|
||||
attributes: product,
|
||||
},
|
||||
});
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
|
||||
data.product.push(body.data);
|
||||
});
|
||||
@ -106,7 +106,7 @@ describe('Core API - Basic', () => {
|
||||
);
|
||||
|
||||
body.data.forEach((p) => {
|
||||
expect(p.attributes.publishedAt).toBeUndefined();
|
||||
expect(p.attributes.publishedAt).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@ -131,7 +131,7 @@ describe('Core API - Basic', () => {
|
||||
});
|
||||
|
||||
expect(body.data.id).toEqual(data.product[0].id);
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
|
||||
data.product[0] = res.body.data;
|
||||
});
|
||||
@ -147,7 +147,7 @@ describe('Core API - Basic', () => {
|
||||
expect(statusCode).toBe(200);
|
||||
expect(body.data).toMatchObject(data.product[0]);
|
||||
expect(body.data.id).toEqual(data.product[0].id);
|
||||
expect(body.data.attributes.publishedAt).toBeUndefined();
|
||||
expect(body.data.attributes.publishedAt).toBeDefined();
|
||||
data.product.shift();
|
||||
});
|
||||
});
|
||||
|
||||
@ -742,7 +742,14 @@ describe('Core API - Validate', () => {
|
||||
*/
|
||||
|
||||
describe('Fields', () => {
|
||||
const allDocumentFields = ['name', 'name_non_searchable', 'misc', 'createdAt', 'updatedAt'];
|
||||
const allDocumentFields = [
|
||||
'name',
|
||||
'name_non_searchable',
|
||||
'misc',
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
'publishedAt',
|
||||
];
|
||||
|
||||
describe('No fields param', () => {
|
||||
it('Select all fields sort when no fields param is provided', async () => {
|
||||
|
||||
@ -1,183 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
|
||||
const { createTestBuilder } = require('api-tests/builder');
|
||||
const { createStrapiInstance } = require('api-tests/strapi');
|
||||
const { createAuthRequest } = require('api-tests/request');
|
||||
const modelsUtils = require('api-tests/models');
|
||||
|
||||
let builder;
|
||||
let strapi;
|
||||
let rq;
|
||||
const data = {
|
||||
dogs: [],
|
||||
};
|
||||
const dogModel = {
|
||||
draftAndPublish: false,
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
},
|
||||
code: {
|
||||
type: 'string',
|
||||
unique: true,
|
||||
},
|
||||
},
|
||||
singularName: 'dog',
|
||||
pluralName: 'dogs',
|
||||
displayName: 'Dog',
|
||||
description: '',
|
||||
collectionName: '',
|
||||
};
|
||||
|
||||
const dogs = [
|
||||
{
|
||||
name: 'Nelson',
|
||||
code: '1',
|
||||
},
|
||||
{
|
||||
name: 'Atos',
|
||||
code: '2',
|
||||
},
|
||||
];
|
||||
|
||||
const restart = async () => {
|
||||
await strapi.destroy();
|
||||
strapi = await createStrapiInstance();
|
||||
rq = await createAuthRequest({ strapi });
|
||||
};
|
||||
|
||||
const sortDogs = (dogs) => _.sortBy(dogs, 'name');
|
||||
|
||||
describe('Migration - draft and publish', () => {
|
||||
describe.each([
|
||||
['without table modifications', {}, {}],
|
||||
['with table modifications', { town: { type: 'string' } }, { color: { type: 'string' } }],
|
||||
])('%p', (testName, tableModification1, tableModification2) => {
|
||||
beforeAll(async () => {
|
||||
builder = createTestBuilder();
|
||||
|
||||
await builder.addContentType(dogModel).addFixtures(dogModel.singularName, dogs).build();
|
||||
|
||||
strapi = await createStrapiInstance();
|
||||
rq = await createAuthRequest({ strapi });
|
||||
|
||||
data.dogs = sortDogs(await builder.sanitizedFixturesFor(dogModel.singularName, strapi));
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await strapi.destroy();
|
||||
await builder.cleanup();
|
||||
});
|
||||
|
||||
describe('Enabling D&P on a content-type', () => {
|
||||
test('No publishedAt before enabling the feature', async () => {
|
||||
const { body } = await rq({
|
||||
url: '/content-manager/collection-types/api::dog.dog',
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
expect(body.results.length).toBe(2);
|
||||
|
||||
const sortedBody = sortDogs(body.results);
|
||||
|
||||
sortedBody.forEach((dog, index) => {
|
||||
expect(dog).toMatchObject(data.dogs[index]);
|
||||
expect(dog.publishedAt).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
test('Published_at is equal to created_at after enabling the feature', async () => {
|
||||
const schema = await modelsUtils.getContentTypeSchema(dogModel.singularName, { strapi });
|
||||
|
||||
await modelsUtils.modifyContentType(
|
||||
{
|
||||
...schema,
|
||||
attributes: _.merge(schema.attributes, tableModification1),
|
||||
draftAndPublish: true,
|
||||
},
|
||||
{ strapi }
|
||||
);
|
||||
|
||||
await restart();
|
||||
|
||||
const { body } = await rq({
|
||||
method: 'GET',
|
||||
url: '/content-manager/collection-types/api::dog.dog',
|
||||
});
|
||||
|
||||
expect(body.results.length).toBe(2);
|
||||
|
||||
const sortedBody = sortDogs(body.results);
|
||||
|
||||
sortedBody.forEach((dog, index) => {
|
||||
expect(dog).toMatchObject(data.dogs[index]);
|
||||
expect(dog.publishedAt).toBe(dog.createdAt || dog.created_at);
|
||||
expect(!Number.isNaN(new Date(dog.publishedAt).valueOf())).toBe(true);
|
||||
});
|
||||
|
||||
data.dogs = sortedBody;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Disabling D&P on a content-type', () => {
|
||||
test('No publishedAt after disabling the feature + draft removed', async () => {
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::dog.dog/${data.dogs[1].id}/actions/unpublish`,
|
||||
});
|
||||
|
||||
data.dogs[1] = res.body;
|
||||
|
||||
const schema = await modelsUtils.getContentTypeSchema(dogModel.singularName, { strapi });
|
||||
|
||||
await modelsUtils.modifyContentType(
|
||||
{
|
||||
...schema,
|
||||
draftAndPublish: false,
|
||||
attributes: _.merge(schema.attributes, tableModification2),
|
||||
},
|
||||
{ strapi }
|
||||
);
|
||||
|
||||
await restart();
|
||||
|
||||
// drafts should have been deleted with the migration, so we remove them
|
||||
data.dogs = data.dogs.filter((dog) => !_.isNil(dog.publishedAt));
|
||||
|
||||
const { body } = await rq({
|
||||
url: '/content-manager/collection-types/api::dog.dog',
|
||||
method: 'GET',
|
||||
});
|
||||
|
||||
expect(body.results.length).toBe(1);
|
||||
expect(body.results[0]).toMatchObject(_.pick(data.dogs[0], ['name']));
|
||||
expect(body.results[0].publishedAt).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Unique constraint is kept after disabling the feature', async () => {
|
||||
const dogToCreate = { code: 'sameCode' };
|
||||
|
||||
let res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::dog.dog/`,
|
||||
body: dogToCreate,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body).toMatchObject(dogToCreate);
|
||||
|
||||
data.dogs.push(res.body);
|
||||
|
||||
res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::dog.dog/`,
|
||||
body: dogToCreate,
|
||||
});
|
||||
|
||||
expect(res.statusCode).toBe(400);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -13,7 +13,6 @@ const data = {
|
||||
};
|
||||
|
||||
const dogModel = {
|
||||
draftAndPublish: false,
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
@ -69,7 +68,7 @@ describe('Migration - required attribute', () => {
|
||||
expect(dogWithNameNull).toBeTruthy();
|
||||
});
|
||||
|
||||
test('Cannot create an entry with null after migration', async () => {
|
||||
test('Cannot publish an entry with null after migration', async () => {
|
||||
// remove null values otherwise the migration would fail
|
||||
|
||||
const { body } = await rq({
|
||||
@ -87,12 +86,17 @@ describe('Migration - required attribute', () => {
|
||||
await restart();
|
||||
|
||||
// Try to create an entry with null
|
||||
const res = await rq({
|
||||
const creationRes = await rq({
|
||||
method: 'POST',
|
||||
url: '/content-manager/collection-types/api::dog.dog',
|
||||
body: { name: null },
|
||||
});
|
||||
|
||||
const res = await rq({
|
||||
method: 'POST',
|
||||
url: `/content-manager/collection-types/api::dog.dog/${creationRes.body.id}/actions/publish`,
|
||||
});
|
||||
|
||||
expect(res.body).toMatchObject({
|
||||
data: null,
|
||||
error: {
|
||||
|
||||
@ -13,7 +13,6 @@ const data = {
|
||||
};
|
||||
|
||||
const dogModel = {
|
||||
draftAndPublish: false,
|
||||
attributes: {
|
||||
name: {
|
||||
type: 'string',
|
||||
|
||||
@ -60,7 +60,6 @@ const contentTypes = {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'Product',
|
||||
singularName: 'product',
|
||||
pluralName: 'products',
|
||||
@ -73,7 +72,6 @@ const contentTypes = {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'Country',
|
||||
singularName: 'country',
|
||||
pluralName: 'countries',
|
||||
@ -86,7 +84,6 @@ const contentTypes = {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
displayName: 'Category',
|
||||
singularName: 'category',
|
||||
pluralName: 'categories',
|
||||
|
||||
@ -16,7 +16,6 @@ const model = {
|
||||
displayName: 'single-type',
|
||||
singularName: 'single-type',
|
||||
pluralName: 'single-types',
|
||||
draftAndPublish: true,
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
|
||||
@ -20,7 +20,6 @@ const documentModel = {
|
||||
type: 'richtext',
|
||||
},
|
||||
},
|
||||
draftAndPublish: true,
|
||||
singularName: 'document',
|
||||
pluralName: 'documents',
|
||||
displayName: 'Document',
|
||||
|
||||
@ -15,9 +15,7 @@ const categoryModel = {
|
||||
pluralName: 'categories',
|
||||
description: '',
|
||||
name: 'Category',
|
||||
options: {
|
||||
draftAndPublish: false,
|
||||
},
|
||||
options: {},
|
||||
pluginOptions: {
|
||||
i18n: {
|
||||
localized: true,
|
||||
@ -41,9 +39,7 @@ const homepageModel = {
|
||||
displayName: 'Homepage',
|
||||
singularName: 'homepage',
|
||||
pluralName: 'homepages',
|
||||
options: {
|
||||
draftAndPublish: false,
|
||||
},
|
||||
options: {},
|
||||
pluginOptions: {
|
||||
i18n: {
|
||||
localized: true,
|
||||
|
||||
@ -31,9 +31,7 @@ const categoryModel = {
|
||||
pluralName: 'categories',
|
||||
description: '',
|
||||
name: 'Category',
|
||||
options: {
|
||||
draftAndPublish: false,
|
||||
},
|
||||
options: {},
|
||||
pluginOptions: {
|
||||
i18n: {
|
||||
localized: true,
|
||||
@ -52,9 +50,7 @@ const dogSchema = {
|
||||
displayName: 'Dog',
|
||||
singularName: 'dog',
|
||||
pluralName: 'dogs',
|
||||
options: {
|
||||
draftAndPublish: false,
|
||||
},
|
||||
options: {},
|
||||
pluginOptions: {
|
||||
i18n: {
|
||||
localized: true,
|
||||
|
||||
@ -15,9 +15,7 @@ const categoryModel = {
|
||||
pluralName: 'categories',
|
||||
description: '',
|
||||
name: 'Category',
|
||||
options: {
|
||||
draftAndPublish: false,
|
||||
},
|
||||
options: {},
|
||||
pluginOptions: {
|
||||
i18n: {
|
||||
localized: true,
|
||||
|
||||
@ -114,7 +114,9 @@ describe('i18n - Find available relations', () => {
|
||||
});
|
||||
|
||||
expect(res.body.results).toHaveLength(1);
|
||||
expect(res.body.results[0]).toStrictEqual(pick(['id', 'name'], data.products[1]));
|
||||
expect(res.body.results[0]).toStrictEqual(
|
||||
pick(['id', 'name', 'publishedAt'], data.products[1])
|
||||
);
|
||||
});
|
||||
|
||||
test('Can filter on any locale', async () => {
|
||||
@ -125,6 +127,8 @@ describe('i18n - Find available relations', () => {
|
||||
});
|
||||
|
||||
expect(res.body.results).toHaveLength(1);
|
||||
expect(res.body.results[0]).toStrictEqual(pick(['id', 'name'], data.products[0]));
|
||||
expect(res.body.results[0]).toStrictEqual(
|
||||
pick(['id', 'name', 'publishedAt'], data.products[0])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -116,7 +116,9 @@ describe('i18n - Find existing relations', () => {
|
||||
});
|
||||
|
||||
expect(res.body.results).toHaveLength(1);
|
||||
expect(res.body.results[0]).toStrictEqual(pick(['id', 'name'], data.products[0]));
|
||||
expect(res.body.results[0]).toStrictEqual(
|
||||
pick(['id', 'name', 'publishedAt'], data.products[0])
|
||||
);
|
||||
});
|
||||
|
||||
test('Get english product for english shop', async () => {
|
||||
@ -126,6 +128,8 @@ describe('i18n - Find existing relations', () => {
|
||||
});
|
||||
|
||||
expect(res.body.results).toHaveLength(1);
|
||||
expect(res.body.results[0]).toStrictEqual(pick(['id', 'name'], data.products[1]));
|
||||
expect(res.body.results[0]).toStrictEqual(
|
||||
pick(['id', 'name', 'publishedAt'], data.products[1])
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -262,7 +262,6 @@ describe('Advanced Test GraphQL Users API End to End', () => {
|
||||
singularName: 'user',
|
||||
pluralName: 'users',
|
||||
description: '',
|
||||
draftAndPublish: false,
|
||||
kind: 'collectionType',
|
||||
collectionName: 'up_users',
|
||||
attributes: {
|
||||
|
||||
@ -95,8 +95,8 @@ telemetry.send('event_name', { key: 'value' });
|
||||
- `userProperties`: <Type>Object</Type> An object that defines the identity of the user who triggered the event.
|
||||
- `groupProperties`: <Type>Object</Type> An object that defines properties of the application or environment in which the event occurred.
|
||||
|
||||
Examples of event properties in Strapi include model, containsRelationalFields, displayedFields, kind, and hasDraftAndPublish. These properties are specific to the event and are used to provide additional context about what happened.
|
||||
Examples of event properties in Strapi include model, containsRelationalFields, displayedFields, kind. These properties are specific to the event and are used to provide additional context about what happened.
|
||||
|
||||
User properties can include information such as the user's operating system, node version, and hostname. These properties are typically used to group events by user or to filter events based on certain user characteristics.
|
||||
|
||||
Group properties can include information such as the language(s) used in the application, the database being used, and the number of locales. These properties are typically used to group events by application version, environment, or other characteristics.
|
||||
Group properties can include information such as the language(s) used in the application, the database being used, and the number of locales. These properties are typically used to group events by application version, environment, or other characteristics.
|
||||
|
||||
@ -6,9 +6,7 @@
|
||||
"pluralName": "testings",
|
||||
"displayName": "testing"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"options": {},
|
||||
"attributes": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
|
||||
@ -8,10 +8,7 @@
|
||||
"description": "",
|
||||
"name": "Address"
|
||||
},
|
||||
"options": {
|
||||
"reviewWorkflows": true,
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"options": {},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"postal_code": {
|
||||
|
||||
@ -9,8 +9,7 @@
|
||||
"name": "Category"
|
||||
},
|
||||
"options": {
|
||||
"reviewWorkflows": true,
|
||||
"draftAndPublish": true
|
||||
"reviewWorkflows": true
|
||||
},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
"name": "Country"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false,
|
||||
"comment": ""
|
||||
},
|
||||
"pluginOptions": {
|
||||
|
||||
@ -6,9 +6,7 @@
|
||||
"singularName": "homepage",
|
||||
"pluralName": "homepages"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"options": {},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
|
||||
@ -8,9 +8,7 @@
|
||||
"description": "",
|
||||
"name": "Kitchen Sink"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"options": {},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"short_text": {
|
||||
@ -60,33 +58,19 @@
|
||||
},
|
||||
"enumeration": {
|
||||
"type": "enumeration",
|
||||
"enum": [
|
||||
"A",
|
||||
"B",
|
||||
"C",
|
||||
"D",
|
||||
"E"
|
||||
]
|
||||
"enum": ["A", "B", "C", "D", "E"]
|
||||
},
|
||||
"single_media": {
|
||||
"type": "media",
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"allowedTypes": [
|
||||
"images",
|
||||
"files",
|
||||
"videos"
|
||||
]
|
||||
"allowedTypes": ["images", "files", "videos"]
|
||||
},
|
||||
"multiple_media": {
|
||||
"type": "media",
|
||||
"multiple": true,
|
||||
"required": false,
|
||||
"allowedTypes": [
|
||||
"images",
|
||||
"files",
|
||||
"videos"
|
||||
]
|
||||
"allowedTypes": ["images", "files", "videos"]
|
||||
},
|
||||
"json": {
|
||||
"type": "json"
|
||||
@ -103,10 +87,7 @@
|
||||
},
|
||||
"dynamiczone": {
|
||||
"type": "dynamiczone",
|
||||
"components": [
|
||||
"basic.simple",
|
||||
"blog.test-como"
|
||||
]
|
||||
"components": ["basic.simple", "blog.test-como"]
|
||||
},
|
||||
"one_way_tag": {
|
||||
"type": "relation",
|
||||
@ -162,10 +143,7 @@
|
||||
},
|
||||
"cats": {
|
||||
"type": "dynamiczone",
|
||||
"components": [
|
||||
"basic.relation",
|
||||
"basic.simple"
|
||||
]
|
||||
"components": ["basic.relation", "basic.simple"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false,
|
||||
"comment": ""
|
||||
},
|
||||
"attributes": {
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
"pluralName": "menus"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false,
|
||||
"comment": ""
|
||||
},
|
||||
"attributes": {
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false,
|
||||
"comment": ""
|
||||
},
|
||||
"attributes": {
|
||||
|
||||
@ -7,9 +7,7 @@
|
||||
"displayName": "Relations",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"options": {},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
@ -47,10 +45,7 @@
|
||||
}
|
||||
},
|
||||
"type": "dynamiczone",
|
||||
"components": [
|
||||
"basic.relation",
|
||||
"basic.simple"
|
||||
]
|
||||
"components": ["basic.relation", "basic.simple"]
|
||||
},
|
||||
"single_relation": {
|
||||
"type": "component",
|
||||
|
||||
@ -9,7 +9,6 @@
|
||||
"name": "Restaurant"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true,
|
||||
"populateCreatorFields": true,
|
||||
"comment": ""
|
||||
},
|
||||
@ -36,13 +35,7 @@
|
||||
"pluginOptions": {}
|
||||
},
|
||||
"priceRange": {
|
||||
"enum": [
|
||||
"very_cheap",
|
||||
"cheap",
|
||||
"average",
|
||||
"expensive",
|
||||
"very_expensive"
|
||||
],
|
||||
"enum": ["very_cheap", "cheap", "average", "expensive", "very_expensive"],
|
||||
"type": "enumeration",
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false,
|
||||
"comment": ""
|
||||
},
|
||||
"attributes": {
|
||||
|
||||
@ -7,9 +7,7 @@
|
||||
"pluralName": "tags",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"options": {},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"name": {
|
||||
|
||||
@ -8,9 +8,7 @@
|
||||
"name": "temp",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"options": {},
|
||||
"pluginOptions": {},
|
||||
"attributes": {
|
||||
"name": {
|
||||
|
||||
@ -6,9 +6,7 @@
|
||||
"pluralName": "tests",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"options": {},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
|
||||
@ -7,9 +7,7 @@
|
||||
"pluralName": "users",
|
||||
"displayName": "User"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"options": {},
|
||||
"attributes": {
|
||||
"username": {
|
||||
"type": "string",
|
||||
|
||||
@ -5,9 +5,7 @@
|
||||
"pluralName": "tests",
|
||||
"description": ""
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": false
|
||||
},
|
||||
"options": {},
|
||||
"pluginOptions": {
|
||||
"i18n": {
|
||||
"localized": true
|
||||
|
||||
@ -6,9 +6,7 @@
|
||||
"pluralName": "testings",
|
||||
"displayName": "testing"
|
||||
},
|
||||
"options": {
|
||||
"draftAndPublish": true
|
||||
},
|
||||
"options": {},
|
||||
"attributes": {
|
||||
"title": {
|
||||
"type": "string"
|
||||
|
||||
@ -342,7 +342,6 @@ const address = {
|
||||
kind: 'collectionType',
|
||||
info: { displayName: 'addresse', name: 'address', description: '', label: 'Addresses' },
|
||||
options: {
|
||||
draftAndPublish: true,
|
||||
increments: true,
|
||||
timestamps: ['createdAt', 'updatedAt'],
|
||||
comment: '',
|
||||
|
||||
@ -77,13 +77,9 @@ const EditViewDataManagerProvider = ({
|
||||
|
||||
const currentContentTypeLayout = get(allLayoutData, ['contentType'], {});
|
||||
|
||||
const hasDraftAndPublish = useMemo(() => {
|
||||
return get(currentContentTypeLayout, ['options', 'draftAndPublish'], false);
|
||||
}, [currentContentTypeLayout]);
|
||||
|
||||
const shouldNotRunValidations = useMemo(() => {
|
||||
return hasDraftAndPublish && !initialData.publishedAt;
|
||||
}, [hasDraftAndPublish, initialData.publishedAt]);
|
||||
return !initialData.publishedAt;
|
||||
}, [initialData.publishedAt]);
|
||||
|
||||
const { trackUsage } = useTracking();
|
||||
const { formatMessage } = useIntl();
|
||||
@ -358,12 +354,8 @@ const EditViewDataManagerProvider = ({
|
||||
);
|
||||
|
||||
const trackerProperty = useMemo(() => {
|
||||
if (!hasDraftAndPublish) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return shouldNotRunValidations ? { status: 'draft' } : {};
|
||||
}, [hasDraftAndPublish, shouldNotRunValidations]);
|
||||
}, [shouldNotRunValidations]);
|
||||
|
||||
const handlePublishPromptDismissal = useCallback(async (e) => {
|
||||
e.preventDefault();
|
||||
@ -619,7 +611,6 @@ const EditViewDataManagerProvider = ({
|
||||
checkFormErrors,
|
||||
createActionAllowedFields,
|
||||
formErrors,
|
||||
hasDraftAndPublish,
|
||||
initialData,
|
||||
isCreatingEntry,
|
||||
isSingleType,
|
||||
|
||||
@ -2,18 +2,15 @@ import { useCMEditViewDataManager } from '@strapi/helper-plugin';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
function useSelect() {
|
||||
const { hasDraftAndPublish, modifiedData } = useCMEditViewDataManager();
|
||||
const { modifiedData } = useCMEditViewDataManager();
|
||||
|
||||
let trackerProperty = {};
|
||||
|
||||
if (hasDraftAndPublish) {
|
||||
const isDraft = isEmpty(modifiedData.publishedAt);
|
||||
const isDraft = isEmpty(modifiedData.publishedAt);
|
||||
|
||||
trackerProperty = isDraft ? { status: 'draft' } : { status: 'published' };
|
||||
}
|
||||
trackerProperty = isDraft ? { status: 'draft' } : { status: 'published' };
|
||||
|
||||
return {
|
||||
hasDraftAndPublish,
|
||||
trackerProperty,
|
||||
};
|
||||
}
|
||||
|
||||
@ -19,13 +19,9 @@ const CustomBullet = styled(Dot)`
|
||||
}
|
||||
`;
|
||||
|
||||
const DraftAndPublishBadge = ({ hasDraftAndPublish, isPublished }) => {
|
||||
const DraftAndPublishBadge = ({ isPublished }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
if (!hasDraftAndPublish) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const colors = {
|
||||
draft: {
|
||||
textColor: 'secondary700',
|
||||
@ -85,7 +81,6 @@ const DraftAndPublishBadge = ({ hasDraftAndPublish, isPublished }) => {
|
||||
};
|
||||
|
||||
DraftAndPublishBadge.propTypes = {
|
||||
hasDraftAndPublish: PropTypes.bool.isRequired,
|
||||
isPublished: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ const makeApp = (props) => (
|
||||
|
||||
describe('<DraftAndPublishBadge />', () => {
|
||||
it('renders and matches the snapshot', () => {
|
||||
const App = makeApp({ hasDraftAndPublish: true, isPublished: true });
|
||||
const App = makeApp({ isPublished: true });
|
||||
|
||||
const {
|
||||
container: { firstChild },
|
||||
@ -124,7 +124,7 @@ describe('<DraftAndPublishBadge />', () => {
|
||||
});
|
||||
|
||||
it('should show the draft design when it is not published', () => {
|
||||
const App = makeApp({ hasDraftAndPublish: true, isPublished: false });
|
||||
const App = makeApp({ isPublished: false });
|
||||
|
||||
const {
|
||||
container: { firstChild },
|
||||
@ -222,12 +222,4 @@ describe('<DraftAndPublishBadge />', () => {
|
||||
</aside>
|
||||
`);
|
||||
});
|
||||
|
||||
it('should show return null when hasDraftAndPublish is falsy', () => {
|
||||
const App = makeApp({ hasDraftAndPublish: false, isPublished: false });
|
||||
|
||||
const { queryByText } = render(App);
|
||||
|
||||
expect(queryByText('Editing')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import { useCMEditViewDataManager } from '@strapi/helper-plugin';
|
||||
|
||||
function useSelect() {
|
||||
const { initialData, hasDraftAndPublish } = useCMEditViewDataManager();
|
||||
const { initialData } = useCMEditViewDataManager();
|
||||
|
||||
const isPublished = initialData.publishedAt !== undefined && initialData.publishedAt !== null;
|
||||
|
||||
return {
|
||||
hasDraftAndPublish,
|
||||
isPublished,
|
||||
};
|
||||
}
|
||||
|
||||
@ -35,7 +35,6 @@ const Header = ({
|
||||
initialData,
|
||||
isCreatingEntry,
|
||||
isSingleType,
|
||||
hasDraftAndPublish,
|
||||
layout,
|
||||
modifiedData,
|
||||
onPublish,
|
||||
@ -73,11 +72,9 @@ const Header = ({
|
||||
if (isCreatingEntry && canCreate) {
|
||||
primaryAction = (
|
||||
<Flex gap={2}>
|
||||
{hasDraftAndPublish && (
|
||||
<Button disabled startIcon={<Check />} variant="secondary">
|
||||
{formatMessage({ id: 'app.utils.publish', defaultMessage: 'Publish' })}
|
||||
</Button>
|
||||
)}
|
||||
<Button disabled startIcon={<Check />} variant="secondary">
|
||||
{formatMessage({ id: 'app.utils.publish', defaultMessage: 'Publish' })}
|
||||
</Button>
|
||||
<Button disabled={!didChangeData} loading={status === 'submit-pending'} type="submit">
|
||||
{formatMessage({
|
||||
id: getTrad('containers.Edit.submit'),
|
||||
@ -89,7 +86,7 @@ const Header = ({
|
||||
}
|
||||
|
||||
if (!isCreatingEntry && canUpdate) {
|
||||
const shouldShowPublishButton = hasDraftAndPublish && canPublish;
|
||||
const shouldShowPublishButton = canPublish;
|
||||
const isPublished = !isEmpty(initialData.publishedAt);
|
||||
const isPublishButtonLoading = isPublished
|
||||
? status === 'unpublish-pending'
|
||||
@ -286,7 +283,6 @@ Header.propTypes = {
|
||||
isSingleType: PropTypes.bool.isRequired,
|
||||
status: PropTypes.string.isRequired,
|
||||
layout: PropTypes.object.isRequired,
|
||||
hasDraftAndPublish: PropTypes.bool.isRequired,
|
||||
modifiedData: PropTypes.object.isRequired,
|
||||
onPublish: PropTypes.func.isRequired,
|
||||
onUnpublish: PropTypes.func.isRequired,
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
"isDisplayed": true,
|
||||
"info": { "name": "restaurant", "description": "" },
|
||||
"options": {
|
||||
"draftAndPublish": false,
|
||||
"increments": true,
|
||||
"timestamps": ["createdAt", "updatedAt"],
|
||||
"comment": ""
|
||||
|
||||
@ -22,7 +22,6 @@ const defaultProps = {
|
||||
initialData: {},
|
||||
isCreatingEntry: true,
|
||||
isSingleType: false,
|
||||
hasDraftAndPublish: false,
|
||||
layout: ct,
|
||||
modifiedData: {},
|
||||
onPublish: jest.fn(),
|
||||
@ -76,7 +75,7 @@ describe('CONTENT MANAGER | EditView | Header', () => {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.c14 {
|
||||
.c15 {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
color: #666687;
|
||||
@ -207,6 +206,8 @@ describe('CONTENT MANAGER | EditView | Header', () => {
|
||||
|
||||
.c12 {
|
||||
height: 2rem;
|
||||
border: 1px solid #d9d8ff;
|
||||
background: #f0f0ff;
|
||||
}
|
||||
|
||||
.c12 svg {
|
||||
@ -243,17 +244,81 @@ describe('CONTENT MANAGER | EditView | Header', () => {
|
||||
}
|
||||
|
||||
.c12:hover {
|
||||
border: 1px solid #7b79ff;
|
||||
background: #7b79ff;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.c12:active {
|
||||
background-color: #ffffff;
|
||||
border: 1px solid #4945ff;
|
||||
background: #4945ff;
|
||||
}
|
||||
|
||||
.c12:active .c3 {
|
||||
color: #4945ff;
|
||||
}
|
||||
|
||||
.c12:active svg > g,
|
||||
.c12:active svg path {
|
||||
fill: #4945ff;
|
||||
}
|
||||
|
||||
.c12 .c3 {
|
||||
color: #271fe0;
|
||||
}
|
||||
|
||||
.c12 svg > g,
|
||||
.c12 svg path {
|
||||
fill: #271fe0;
|
||||
}
|
||||
|
||||
.c14 {
|
||||
height: 2rem;
|
||||
}
|
||||
|
||||
.c14 svg {
|
||||
height: 0.75rem;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.c14[aria-disabled='true'] {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c14[aria-disabled='true'] .c3 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c14[aria-disabled='true'] svg > g,
|
||||
.c14[aria-disabled='true'] svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c14[aria-disabled='true']:active {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c14[aria-disabled='true']:active .c3 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c14[aria-disabled='true']:active svg > g,
|
||||
.c14[aria-disabled='true']:active svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c14:hover {
|
||||
border: 1px solid #7b79ff;
|
||||
background: #7b79ff;
|
||||
}
|
||||
|
||||
.c14:active {
|
||||
border: 1px solid #4945ff;
|
||||
background: #4945ff;
|
||||
}
|
||||
|
||||
.c14 svg > g,
|
||||
.c14 svg path {
|
||||
fill: #ffffff;
|
||||
}
|
||||
|
||||
@ -372,6 +437,35 @@ describe('CONTENT MANAGER | EditView | Header', () => {
|
||||
aria-disabled="true"
|
||||
class="c10 c9 c11 c12"
|
||||
disabled=""
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class=""
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="1rem"
|
||||
viewBox="0 0 24 24"
|
||||
width="1rem"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M20.727 2.97a.2.2 0 0 1 .286 0l2.85 2.89a.2.2 0 0 1 0 .28L9.554 20.854a.2.2 0 0 1-.285 0l-9.13-9.243a.2.2 0 0 1 0-.281l2.85-2.892a.2.2 0 0 1 .284 0l6.14 6.209L20.726 2.97Z"
|
||||
fill="#212134"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<span
|
||||
class="c3 c13"
|
||||
>
|
||||
Publish
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
aria-disabled="true"
|
||||
class="c10 c9 c11 c14"
|
||||
disabled=""
|
||||
type="submit"
|
||||
>
|
||||
<span
|
||||
@ -383,7 +477,7 @@ describe('CONTENT MANAGER | EditView | Header', () => {
|
||||
</div>
|
||||
</div>
|
||||
<p
|
||||
class="c3 c14"
|
||||
class="c3 c15"
|
||||
>
|
||||
API ID : restaurant
|
||||
</p>
|
||||
|
||||
@ -7,7 +7,6 @@ function useSelect() {
|
||||
isSingleType,
|
||||
status,
|
||||
layout,
|
||||
hasDraftAndPublish,
|
||||
modifiedData,
|
||||
onPublish,
|
||||
onUnpublish,
|
||||
@ -21,7 +20,6 @@ function useSelect() {
|
||||
isSingleType,
|
||||
status,
|
||||
layout,
|
||||
hasDraftAndPublish,
|
||||
modifiedData,
|
||||
onPublish,
|
||||
onUnpublish,
|
||||
|
||||
@ -34,7 +34,7 @@ export const TableRows = ({
|
||||
canCreate,
|
||||
canDelete,
|
||||
contentType,
|
||||
features: { hasDraftAndPublish, hasReviewWorkflows },
|
||||
features: { hasReviewWorkflows },
|
||||
headers,
|
||||
entriesToDelete,
|
||||
onClickDelete,
|
||||
@ -153,7 +153,7 @@ export const TableRows = ({
|
||||
)}
|
||||
|
||||
{headers.map(({ key, cellFormatter, name, ...rest }) => {
|
||||
if (hasDraftAndPublish && name === 'publishedAt') {
|
||||
if (name === 'publishedAt') {
|
||||
return (
|
||||
<Td key={key}>
|
||||
<Status
|
||||
@ -292,7 +292,6 @@ TableRows.propTypes = {
|
||||
}).isRequired,
|
||||
entriesToDelete: PropTypes.array,
|
||||
features: PropTypes.shape({
|
||||
hasDraftAndPublish: PropTypes.bool.isRequired,
|
||||
hasReviewWorkflows: PropTypes.bool.isRequired,
|
||||
}).isRequired,
|
||||
headers: PropTypes.array.isRequired,
|
||||
|
||||
@ -193,7 +193,6 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) {
|
||||
return filter;
|
||||
});
|
||||
|
||||
const hasDraftAndPublish = options?.draftAndPublish ?? false;
|
||||
const hasReviewWorkflows = options?.reviewWorkflows ?? false;
|
||||
|
||||
const reviewWorkflowColumns = useEnterprise(
|
||||
@ -507,23 +506,21 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) {
|
||||
};
|
||||
});
|
||||
|
||||
if (hasDraftAndPublish) {
|
||||
formattedHeaders.push({
|
||||
key: '__published_at_temp_key__',
|
||||
name: 'publishedAt',
|
||||
fieldSchema: {
|
||||
type: 'custom',
|
||||
},
|
||||
metadatas: {
|
||||
label: formatMessage({
|
||||
id: getTrad(`containers.ListPage.table-headers.publishedAt`),
|
||||
defaultMessage: 'publishedAt',
|
||||
}),
|
||||
searchable: false,
|
||||
sortable: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
formattedHeaders.push({
|
||||
key: '__published_at_temp_key__',
|
||||
name: 'publishedAt',
|
||||
fieldSchema: {
|
||||
type: 'custom',
|
||||
},
|
||||
metadatas: {
|
||||
label: formatMessage({
|
||||
id: getTrad(`containers.ListPage.table-headers.publishedAt`),
|
||||
defaultMessage: 'publishedAt',
|
||||
}),
|
||||
searchable: false,
|
||||
sortable: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (reviewWorkflowColumns) {
|
||||
// Make sure the column header label is translated
|
||||
@ -539,14 +536,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) {
|
||||
}
|
||||
|
||||
return formattedHeaders;
|
||||
}, [
|
||||
runHookWaterfall,
|
||||
displayedHeaders,
|
||||
layout,
|
||||
reviewWorkflowColumns,
|
||||
hasDraftAndPublish,
|
||||
formatMessage,
|
||||
]);
|
||||
}, [runHookWaterfall, displayedHeaders, layout, reviewWorkflowColumns, formatMessage]);
|
||||
|
||||
const subtitle = canRead
|
||||
? formatMessage(
|
||||
@ -564,7 +554,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) {
|
||||
{...props}
|
||||
forwardedAs={ReactRouterLink}
|
||||
onClick={() => {
|
||||
const trackerProperty = hasDraftAndPublish ? { status: 'draft' } : {};
|
||||
const trackerProperty = { status: 'draft' };
|
||||
|
||||
trackUsageRef.current('willCreateEntry', trackerProperty);
|
||||
}}
|
||||
@ -691,7 +681,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) {
|
||||
<Table.Root rows={data} isLoading={isLoading} colCount={colCount}>
|
||||
<Table.ActionBar>
|
||||
<BulkActionButtons
|
||||
showPublish={canPublish && hasDraftAndPublish}
|
||||
showPublish={canPublish}
|
||||
showDelete={canDelete}
|
||||
onConfirmDeleteAll={handleConfirmDeleteAllData}
|
||||
onConfirmUnpublishAll={handleConfirmUnpublishAllData}
|
||||
@ -738,7 +728,7 @@ function ListView({ canCreate, canDelete, canRead, canPublish, layout, slug }) {
|
||||
</Td>
|
||||
{/* Field data */}
|
||||
{tableHeaders.map(({ key, name, cellFormatter, ...rest }) => {
|
||||
if (hasDraftAndPublish && name === 'publishedAt') {
|
||||
if (name === 'publishedAt') {
|
||||
return (
|
||||
<Td key={key}>
|
||||
<Status
|
||||
|
||||
@ -62,44 +62,26 @@ const StyledTable = styled(Table)`
|
||||
}
|
||||
`;
|
||||
|
||||
const getCEHeaders = (isDraftAndPublish) => {
|
||||
const getCEHeaders = () => {
|
||||
const headers = [
|
||||
{ id: 'Settings.webhooks.events.create', defaultMessage: 'Create' },
|
||||
{ id: 'Settings.webhooks.events.update', defaultMessage: 'Update' },
|
||||
{ id: 'app.utils.delete', defaultMessage: 'Delete' },
|
||||
{ id: 'app.utils.publish', defaultMessage: 'Publish' },
|
||||
{ id: 'app.utils.unpublish', defaultMessage: 'Unpublish' },
|
||||
];
|
||||
|
||||
if (isDraftAndPublish) {
|
||||
headers.push({ id: 'app.utils.publish', defaultMessage: 'Publish' });
|
||||
headers.push({ id: 'app.utils.unpublish', defaultMessage: 'Unpublish' });
|
||||
}
|
||||
|
||||
return headers;
|
||||
};
|
||||
|
||||
const getCEEvents = (isDraftAndPublish) => {
|
||||
const entryEvents = ['entry.create', 'entry.update', 'entry.delete'];
|
||||
|
||||
if (isDraftAndPublish) {
|
||||
entryEvents.push('entry.publish', 'entry.unpublish');
|
||||
}
|
||||
|
||||
return {
|
||||
entry: entryEvents,
|
||||
media: ['media.create', 'media.update', 'media.delete'],
|
||||
};
|
||||
const CEEvents = {
|
||||
entry: ['entry.create', 'entry.update', 'entry.delete', 'entry.publish', 'entry.unpublish'],
|
||||
media: ['media.create', 'media.update', 'media.delete'],
|
||||
};
|
||||
|
||||
const WebhookEventContext = React.createContext();
|
||||
|
||||
const Root = ({ children }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const { collectionTypes, isLoading } = useContentTypes();
|
||||
|
||||
const isDraftAndPublish = React.useMemo(
|
||||
() => collectionTypes.some((ct) => ct.options.draftAndPublish === true),
|
||||
[collectionTypes]
|
||||
);
|
||||
const { isLoading } = useContentTypes();
|
||||
|
||||
const label = formatMessage({
|
||||
id: 'Settings.webhooks.form.events',
|
||||
@ -107,20 +89,18 @@ const Root = ({ children }) => {
|
||||
});
|
||||
|
||||
return (
|
||||
<WebhookEventContext.Provider value={{ isDraftAndPublish }}>
|
||||
<Flex direction="column" alignItems="stretch" gap={1}>
|
||||
<FieldLabel aria-hidden>{label}</FieldLabel>
|
||||
{isLoading && (
|
||||
<Loader>
|
||||
{formatMessage({
|
||||
id: 'Settings.webhooks.events.isLoading',
|
||||
defaultMessage: 'Events loading',
|
||||
})}
|
||||
</Loader>
|
||||
)}
|
||||
<StyledTable aria-label={label}>{children}</StyledTable>
|
||||
</Flex>
|
||||
</WebhookEventContext.Provider>
|
||||
<Flex direction="column" alignItems="stretch" gap={1}>
|
||||
<FieldLabel aria-hidden>{label}</FieldLabel>
|
||||
{isLoading && (
|
||||
<Loader>
|
||||
{formatMessage({
|
||||
id: 'Settings.webhooks.events.isLoading',
|
||||
defaultMessage: 'Events loading',
|
||||
})}
|
||||
</Loader>
|
||||
)}
|
||||
<StyledTable aria-label={label}>{children}</StyledTable>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
@ -129,10 +109,8 @@ Root.propTypes = {
|
||||
};
|
||||
|
||||
const Headers = ({ getHeaders = getCEHeaders }) => {
|
||||
const { isDraftAndPublish } = React.useContext(WebhookEventContext);
|
||||
|
||||
const { formatMessage } = useIntl();
|
||||
const headers = getHeaders(isDraftAndPublish);
|
||||
const headers = getHeaders();
|
||||
|
||||
return (
|
||||
<Thead>
|
||||
@ -184,9 +162,7 @@ Headers.propTypes = {
|
||||
};
|
||||
|
||||
const Body = ({ providedEvents }) => {
|
||||
const { isDraftAndPublish } = React.useContext(WebhookEventContext);
|
||||
|
||||
const events = providedEvents || getCEEvents(isDraftAndPublish);
|
||||
const events = providedEvents || CEEvents;
|
||||
const { values, handleChange: onChange } = useFormikContext();
|
||||
|
||||
const inputName = 'events';
|
||||
|
||||
@ -736,8 +736,6 @@ components:
|
||||
maxItems: 2
|
||||
items:
|
||||
type: string
|
||||
draftAndPublish:
|
||||
type: boolean
|
||||
attributes:
|
||||
type: object
|
||||
additionalProperties:
|
||||
|
||||
@ -106,7 +106,7 @@ describe('Relations', () => {
|
||||
'target',
|
||||
expect.objectContaining({
|
||||
sort: 'myField',
|
||||
fields: ['id', 'myField'],
|
||||
fields: ['id', 'myField', 'publishedAt'],
|
||||
filters: {
|
||||
$and: [
|
||||
{
|
||||
@ -146,7 +146,7 @@ describe('Relations', () => {
|
||||
'targetWithHidden',
|
||||
expect.objectContaining({
|
||||
sort: 'id',
|
||||
fields: ['id'],
|
||||
fields: ['id', 'publishedAt'],
|
||||
filters: {
|
||||
$and: [
|
||||
{
|
||||
@ -190,7 +190,7 @@ describe('Relations', () => {
|
||||
{ id: 1 },
|
||||
'relation',
|
||||
expect.objectContaining({
|
||||
fields: ['id', 'myField'],
|
||||
fields: ['id', 'myField', 'publishedAt'],
|
||||
})
|
||||
);
|
||||
});
|
||||
@ -220,7 +220,7 @@ describe('Relations', () => {
|
||||
{ id: 1 },
|
||||
'relationWithHidden',
|
||||
expect.objectContaining({
|
||||
fields: ['id'],
|
||||
fields: ['id', 'publishedAt'],
|
||||
})
|
||||
);
|
||||
});
|
||||
@ -266,7 +266,7 @@ describe('Relations', () => {
|
||||
{ id: 1 },
|
||||
'relationWithHidden',
|
||||
expect.objectContaining({
|
||||
fields: ['id'],
|
||||
fields: ['id', 'publishedAt'],
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
@ -131,9 +131,7 @@ describe('Single Types', () => {
|
||||
},
|
||||
getModel() {
|
||||
return {
|
||||
options: {
|
||||
draftAndPublish: true,
|
||||
},
|
||||
options: {},
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -248,9 +246,7 @@ describe('Single Types', () => {
|
||||
},
|
||||
getModel() {
|
||||
return {
|
||||
options: {
|
||||
draftAndPublish: true,
|
||||
},
|
||||
options: {},
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -346,9 +342,7 @@ describe('Single Types', () => {
|
||||
},
|
||||
getModel() {
|
||||
return {
|
||||
options: {
|
||||
draftAndPublish: true,
|
||||
},
|
||||
options: {},
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
@ -444,9 +438,7 @@ describe('Single Types', () => {
|
||||
},
|
||||
getModel() {
|
||||
return {
|
||||
options: {
|
||||
draftAndPublish: true,
|
||||
},
|
||||
options: {},
|
||||
attributes: {
|
||||
title: {
|
||||
type: 'string',
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const { prop, isEmpty, uniq, flow } = require('lodash/fp');
|
||||
const { hasDraftAndPublish } = require('@strapi/utils').contentTypes;
|
||||
const { isAnyToMany } = require('@strapi/utils').relations;
|
||||
const { PUBLISHED_AT_ATTRIBUTE } = require('@strapi/utils').contentTypes.constants;
|
||||
const { isOperatorOfType } = require('@strapi/utils');
|
||||
@ -122,10 +121,7 @@ module.exports = {
|
||||
(mainField) => sanitizeMainField(targetedModel, mainField, userAbility)
|
||||
)(modelConfig);
|
||||
|
||||
const fieldsToSelect = uniq(['id', mainField]);
|
||||
if (hasDraftAndPublish(targetedModel)) {
|
||||
fieldsToSelect.push(PUBLISHED_AT_ATTRIBUTE);
|
||||
}
|
||||
const fieldsToSelect = uniq(['id', mainField, PUBLISHED_AT_ATTRIBUTE]);
|
||||
|
||||
const queryParams = {
|
||||
sort: mainField,
|
||||
@ -233,10 +229,7 @@ module.exports = {
|
||||
(mainField) => sanitizeMainField(targetedModel, mainField, userAbility)
|
||||
)(modelConfig);
|
||||
|
||||
const fieldsToSelect = uniq(['id', mainField]);
|
||||
if (hasDraftAndPublish(targetedModel)) {
|
||||
fieldsToSelect.push(PUBLISHED_AT_ATTRIBUTE);
|
||||
}
|
||||
const fieldsToSelect = uniq(['id', mainField, PUBLISHED_AT_ATTRIBUTE]);
|
||||
|
||||
const queryParams = {
|
||||
fields: fieldsToSelect,
|
||||
|
||||
@ -1,57 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const hasDraftAndPublish = require('../has-draft-and-publish');
|
||||
|
||||
describe('hasDraftAndPublish policy', () => {
|
||||
beforeEach(() => {
|
||||
global.strapi = {
|
||||
errors: {
|
||||
forbidden: jest.fn(() => 'forbidden'),
|
||||
},
|
||||
contentTypes: {
|
||||
foo: {
|
||||
options: {
|
||||
draftAndPublish: true,
|
||||
},
|
||||
},
|
||||
bar: {
|
||||
options: {
|
||||
draftAndPublish: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
test('It should succeed when the model has draft & publish enabled', () => {
|
||||
const ctx = { params: { model: 'foo' } };
|
||||
const res = hasDraftAndPublish(ctx, {}, { strapi: global.strapi });
|
||||
|
||||
expect(res).toBe(true);
|
||||
});
|
||||
|
||||
test(`It should fail when the model has draft & publish disabled`, () => {
|
||||
const ctx = { params: { model: 'bar' } };
|
||||
|
||||
const res = hasDraftAndPublish(ctx, {}, { strapi: global.strapi });
|
||||
expect(res).toBe(false);
|
||||
});
|
||||
|
||||
test(`It should fail when the model doesn't exists`, () => {
|
||||
const ctx = { params: { model: 'foobar' } };
|
||||
|
||||
const res = hasDraftAndPublish(ctx, {}, { strapi: global.strapi });
|
||||
expect(res).toBe(false);
|
||||
});
|
||||
|
||||
test(`It should fail when params.model isn't provided`, () => {
|
||||
const ctx = { params: {} };
|
||||
|
||||
const res = hasDraftAndPublish(ctx, {}, { strapi: global.strapi });
|
||||
expect(res).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -1,13 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const {
|
||||
contentTypes: { hasDraftAndPublish },
|
||||
} = require('@strapi/utils');
|
||||
|
||||
module.exports = (ctx, config, { strapi }) => {
|
||||
const { model: modelUID } = ctx.params;
|
||||
|
||||
const model = strapi.contentTypes[modelUID];
|
||||
|
||||
return hasDraftAndPublish(model);
|
||||
};
|
||||
@ -1,9 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const hasDraftAndPublish = require('./has-draft-and-publish');
|
||||
const hasPermissions = require('./hasPermissions');
|
||||
|
||||
module.exports = {
|
||||
'has-draft-and-publish': hasDraftAndPublish,
|
||||
hasPermissions,
|
||||
};
|
||||
|
||||
@ -161,7 +161,6 @@ module.exports = {
|
||||
config: {
|
||||
middlewares: [routing],
|
||||
policies: [
|
||||
'plugin::content-manager.has-draft-and-publish',
|
||||
'admin::isAuthenticatedAdmin',
|
||||
{
|
||||
name: 'plugin::content-manager.hasPermissions',
|
||||
@ -177,7 +176,6 @@ module.exports = {
|
||||
config: {
|
||||
middlewares: [routing],
|
||||
policies: [
|
||||
'plugin::content-manager.has-draft-and-publish',
|
||||
'admin::isAuthenticatedAdmin',
|
||||
{
|
||||
name: 'plugin::content-manager.hasPermissions',
|
||||
@ -313,7 +311,6 @@ module.exports = {
|
||||
config: {
|
||||
middlewares: [routing],
|
||||
policies: [
|
||||
'plugin::content-manager.has-draft-and-publish',
|
||||
'admin::isAuthenticatedAdmin',
|
||||
{
|
||||
name: 'plugin::content-manager.hasPermissions',
|
||||
@ -329,7 +326,6 @@ module.exports = {
|
||||
config: {
|
||||
middlewares: [routing],
|
||||
policies: [
|
||||
'plugin::content-manager.has-draft-and-publish',
|
||||
'admin::isAuthenticatedAdmin',
|
||||
{
|
||||
name: 'plugin::content-manager.hasPermissions',
|
||||
@ -360,7 +356,6 @@ module.exports = {
|
||||
config: {
|
||||
middlewares: [routing],
|
||||
policies: [
|
||||
'plugin::content-manager.has-draft-and-publish',
|
||||
'admin::isAuthenticatedAdmin',
|
||||
{
|
||||
name: 'plugin::content-manager.hasPermissions',
|
||||
@ -376,7 +371,6 @@ module.exports = {
|
||||
config: {
|
||||
middlewares: [routing],
|
||||
policies: [
|
||||
'plugin::content-manager.has-draft-and-publish',
|
||||
'admin::isAuthenticatedAdmin',
|
||||
{
|
||||
name: 'plugin::content-manager.hasPermissions',
|
||||
|
||||
@ -13,7 +13,6 @@ const {
|
||||
ALLOWED_WEBHOOK_EVENTS: { ENTRY_PUBLISH, ENTRY_UNPUBLISH },
|
||||
} = require('../constants');
|
||||
|
||||
const { hasDraftAndPublish } = strapiUtils.contentTypes;
|
||||
const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
|
||||
|
||||
const omitPublishedAtField = omit(PUBLISHED_AT_ATTRIBUTE);
|
||||
@ -89,13 +88,10 @@ module.exports = ({ strapi }) => ({
|
||||
},
|
||||
|
||||
async create(body, uid) {
|
||||
const modelDef = strapi.getModel(uid);
|
||||
const publishData = { ...body };
|
||||
const populate = await buildDeepPopulate(uid);
|
||||
|
||||
if (hasDraftAndPublish(modelDef)) {
|
||||
publishData[PUBLISHED_AT_ATTRIBUTE] = null;
|
||||
}
|
||||
publishData[PUBLISHED_AT_ATTRIBUTE] = null;
|
||||
|
||||
const params = { data: publishData, populate };
|
||||
|
||||
@ -126,13 +122,10 @@ module.exports = ({ strapi }) => ({
|
||||
return updatedEntity;
|
||||
},
|
||||
async clone(entity, body, uid) {
|
||||
const modelDef = strapi.getModel(uid);
|
||||
const populate = await buildDeepPopulate(uid);
|
||||
const publishData = { ...body };
|
||||
|
||||
if (hasDraftAndPublish(modelDef)) {
|
||||
publishData[PUBLISHED_AT_ATTRIBUTE] = null;
|
||||
}
|
||||
publishData[PUBLISHED_AT_ATTRIBUTE] = null;
|
||||
|
||||
const params = {
|
||||
data: publishData,
|
||||
|
||||
@ -17,10 +17,6 @@ module.exports = ({ strapi }) => ({
|
||||
const displayedContentTypes = getService('content-types').findDisplayedContentTypes();
|
||||
const contentTypesUids = displayedContentTypes.map(prop('uid'));
|
||||
|
||||
const draftAndPublishContentTypesUids = displayedContentTypes
|
||||
.filter(contentTypesUtils.hasDraftAndPublish)
|
||||
.map(prop('uid'));
|
||||
|
||||
const actions = [
|
||||
{
|
||||
section: 'contentTypes',
|
||||
@ -64,7 +60,7 @@ module.exports = ({ strapi }) => ({
|
||||
displayName: 'Publish',
|
||||
uid: 'explorer.publish',
|
||||
pluginName: 'content-manager',
|
||||
subjects: draftAndPublishContentTypesUids,
|
||||
subjects: contentTypesUids,
|
||||
},
|
||||
{
|
||||
section: 'plugins',
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
const { castArray } = require('lodash/fp');
|
||||
const strapiUtils = require('@strapi/utils');
|
||||
|
||||
const { hasDraftAndPublish, isVisibleAttribute } = strapiUtils.contentTypes;
|
||||
const { isVisibleAttribute } = strapiUtils.contentTypes;
|
||||
/**
|
||||
* sumDraftCounts works recursively on the attributes of a model counting the
|
||||
* number of draft relations
|
||||
@ -24,8 +24,7 @@ const sumDraftCounts = (entity, uid) => {
|
||||
|
||||
switch (attribute.type) {
|
||||
case 'relation': {
|
||||
const childModel = strapi.getModel(attribute.target);
|
||||
if (hasDraftAndPublish(childModel) && isVisibleAttribute(model, attributeName)) {
|
||||
if (isVisibleAttribute(model, attributeName)) {
|
||||
return sum + value.count;
|
||||
}
|
||||
return sum;
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
const { merge, isEmpty, set, propEq } = require('lodash/fp');
|
||||
const strapiUtils = require('@strapi/utils');
|
||||
|
||||
const { hasDraftAndPublish, isVisibleAttribute } = strapiUtils.contentTypes;
|
||||
const { isVisibleAttribute } = strapiUtils.contentTypes;
|
||||
const { isAnyToMany } = strapiUtils.relations;
|
||||
const { PUBLISHED_AT_ATTRIBUTE } = strapiUtils.contentTypes.constants;
|
||||
|
||||
@ -168,8 +168,7 @@ const getDeepPopulateDraftCount = (uid) => {
|
||||
|
||||
switch (attribute.type) {
|
||||
case 'relation': {
|
||||
const childModel = strapi.getModel(attribute.target);
|
||||
if (hasDraftAndPublish(childModel) && isVisibleAttribute(model, attributeName)) {
|
||||
if (isVisibleAttribute(model, attributeName)) {
|
||||
populateAcc[attributeName] = {
|
||||
count: true,
|
||||
filters: { [PUBLISHED_AT_ATTRIBUTE]: { $null: true } },
|
||||
|
||||
@ -144,7 +144,6 @@ const createContentTypeSchema = ({
|
||||
},
|
||||
})
|
||||
.required(errorsTrads.required),
|
||||
draftAndPublish: yup.boolean(),
|
||||
kind: yup.string().oneOf(['singleType', 'collectionType']),
|
||||
reviewWorkflows: yup.boolean(),
|
||||
};
|
||||
|
||||
@ -15,22 +15,7 @@ const forms = {
|
||||
return {
|
||||
sections: [
|
||||
{
|
||||
items: [
|
||||
{
|
||||
intlLabel: {
|
||||
id: getTrad('contentType.draftAndPublish.label'),
|
||||
defaultMessage: 'Draft & publish',
|
||||
},
|
||||
description: {
|
||||
id: getTrad('contentType.draftAndPublish.description'),
|
||||
defaultMessage:
|
||||
'Allows writing a draft version of an entry, before it is published',
|
||||
},
|
||||
name: 'draftAndPublish',
|
||||
type: 'toggle-draft-publish',
|
||||
validations: {},
|
||||
},
|
||||
],
|
||||
items: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@ -184,35 +184,29 @@ const FormModal = () => {
|
||||
});
|
||||
}
|
||||
|
||||
// Create content type we need to add the default option draftAndPublish
|
||||
// Create content type
|
||||
if (modalType === 'contentType' && actionType === 'create') {
|
||||
dispatch({
|
||||
type: SET_DATA_TO_EDIT,
|
||||
modalType,
|
||||
actionType,
|
||||
data: {
|
||||
draftAndPublish: true,
|
||||
},
|
||||
data: {},
|
||||
pluginOptions: {},
|
||||
});
|
||||
}
|
||||
|
||||
// Edit content type
|
||||
if (modalType === 'contentType' && actionType === 'edit') {
|
||||
const {
|
||||
displayName,
|
||||
draftAndPublish,
|
||||
kind,
|
||||
pluginOptions,
|
||||
pluralName,
|
||||
reviewWorkflows,
|
||||
singularName,
|
||||
} = get(allDataSchema, [...pathToSchema, 'schema'], {
|
||||
displayName: null,
|
||||
pluginOptions: {},
|
||||
singularName: null,
|
||||
pluralName: null,
|
||||
});
|
||||
const { displayName, kind, pluginOptions, pluralName, reviewWorkflows, singularName } = get(
|
||||
allDataSchema,
|
||||
[...pathToSchema, 'schema'],
|
||||
{
|
||||
displayName: null,
|
||||
pluginOptions: {},
|
||||
singularName: null,
|
||||
pluralName: null,
|
||||
}
|
||||
);
|
||||
|
||||
dispatch({
|
||||
type: SET_DATA_TO_EDIT,
|
||||
@ -220,7 +214,6 @@ const FormModal = () => {
|
||||
modalType,
|
||||
data: {
|
||||
displayName,
|
||||
draftAndPublish,
|
||||
kind,
|
||||
pluginOptions,
|
||||
pluralName,
|
||||
|
||||
@ -5,7 +5,6 @@ export default {
|
||||
schema: {
|
||||
name: 'Address',
|
||||
description: '',
|
||||
draftAndPublish: false,
|
||||
pluginOptions: {
|
||||
i18n: {
|
||||
localized: true,
|
||||
|
||||
@ -50,8 +50,6 @@
|
||||
"contentType.collectionName.description": "Nützlich wenn sich der Name der Sammlung und der Tabellenname unterscheiden",
|
||||
"contentType.collectionName.label": "Name der Sammlung",
|
||||
"contentType.displayName.label": "Anzeigename",
|
||||
"contentType.draftAndPublish.description": "Lege einen Entwurf des Eintrags an bevor er veröffentlicht wird",
|
||||
"contentType.draftAndPublish.label": "Entwurf/Veröffentlichen-System",
|
||||
"contentType.kind.change.warning": "Du hast die Art eines Inhaltstyps geändert: API wird resettet (Routen, Controller und Services werden überschrieben).",
|
||||
"error.attributeName.reserved-name": "Dieser Name kann nicht für Attribute genutzt werden, da er andere Funktionalitäten beeinträchtigen würde",
|
||||
"error.contentType.pluralName-used": "Dieser Wert kann nicht gleich sein wie der Singular-Wert",
|
||||
|
||||
@ -50,8 +50,6 @@
|
||||
"contentType.collectionName.description": "Brugbar når navnet på din indholdstype og dit tabel navn er forskellige",
|
||||
"contentType.collectionName.label": "Dokument navn",
|
||||
"contentType.displayName.label": "Visningsnavn",
|
||||
"contentType.draftAndPublish.description": "Opret en version som udkast for hvert element inden det offentliggøres",
|
||||
"contentType.draftAndPublish.label": "Udkast/offentliggør system",
|
||||
"contentType.kind.change.warning": "Du har lige ændret typen af en indholdstype: API bliver nustillet (ruter, controllere, og services bliver overskrevet).",
|
||||
"error.attributeName.reserved-name": "Dette navn kan ikke bruges i din indholdstype, da det måske kan ødelægge andre funktioner",
|
||||
"error.contentType.pluralName-used": "Denne værdi kan ikke være den samme som ved ental",
|
||||
|
||||
@ -53,8 +53,6 @@
|
||||
"contentType.collectionName.description": "Useful when the name of your Content Type and your table name differ",
|
||||
"contentType.collectionName.label": "Collection name",
|
||||
"contentType.displayName.label": "Display name",
|
||||
"contentType.draftAndPublish.description": "Allows writing a draft version of an entry, before it is published",
|
||||
"contentType.draftAndPublish.label": "Draft & publish",
|
||||
"contentType.kind.change.warning": "You just changed the kind of a content type: API will be reset (routes, controllers, and services will be overwritten).",
|
||||
"error.attributeName.reserved-name": "This name cannot be used in your content type as it might break other functionalities",
|
||||
"error.contentType.pluralName-used": "This value cannot be the same as the singular one",
|
||||
|
||||
@ -50,8 +50,6 @@
|
||||
"contentType.collectionName.description": "Útil cuando el nombre de su Tipo de Contenido y el nombre de su tabla difieren",
|
||||
"contentType.collectionName.label": "Nombre de la colección",
|
||||
"contentType.displayName.label": "Nombre para mostrar",
|
||||
"contentType.draftAndPublish.description": "Escribe un borrador de cada entrada antes de publicarla.",
|
||||
"contentType.draftAndPublish.label": "Sistema de borrador/publicación",
|
||||
"contentType.kind.change.warning": "Acaba de cambiar el Tipo de Contenido: la API se restablecerá (las rutas, los controladores y los servicios se sobrescribirán).",
|
||||
"error.attributeName.reserved-name": "Este nombre no se puede utilizar en su Tipo de Contenido, ya que podría romper otras funcionalidades.",
|
||||
"error.contentType.pluralName-used": "Este valor no puede ser igual al valor singular",
|
||||
|
||||
@ -13,8 +13,6 @@
|
||||
"button.component.create": "Créer un composant",
|
||||
"button.model.create": "Créer un type de collection",
|
||||
"button.single-types.create": "Créer un single type",
|
||||
"contentType.draftAndPublish.description": "Rédigez une version brouillon de chaque entrée avant de la publier",
|
||||
"contentType.draftAndPublish.label": "Système brouillon/publier",
|
||||
"contentType.kind.change.warning": "Vous venez de changer le type de ce modèle: L'API va redémarrer (Les routes, controllers, et les services seront écrasés).",
|
||||
"form.attribute.item.customColumnName": "Nom de colonne personalisée",
|
||||
"form.attribute.item.customColumnName.description": "Pratique pour renommer la colonne de la db dans un format plus comprehensible pour les responses de l'API",
|
||||
|
||||
@ -45,8 +45,6 @@
|
||||
"contentType.collectionName.description": "Berguna jika nama Jenis Konten dan nama tabel Anda berbeda",
|
||||
"contentType.collectionName.label": "Nama koleksi",
|
||||
"contentType.displayName.label": "Nama tampilan",
|
||||
"contentType.draftAndPublish.description": "Tulis versi draf dari setiap entri sebelum menerbitkannya",
|
||||
"contentType.draftAndPublish.label": "Draf / sistem terbitkan",
|
||||
"contentType.kind.change.warning": "Anda baru saja mengubah jenis tipe konten: API akan disetel ulang (rute, pengontrol, dan layanan akan ditimpa).",
|
||||
"error.attributeName.reserved-name": "Nama ini tidak dapat digunakan dalam tipe konten Anda karena dapat merusak fungsi lainnya",
|
||||
"error.contentTypeName.reserved-name": "Nama ini tidak dapat digunakan dalam proyek Anda karena dapat merusak fungsi lainnya",
|
||||
|
||||
@ -45,8 +45,6 @@
|
||||
"contentType.collectionName.description": "Utile quando il nome della Collezione differisce dal nome della tabella del DB",
|
||||
"contentType.collectionName.label": "Nome della Collezione",
|
||||
"contentType.displayName.label": "Nome visualizzato",
|
||||
"contentType.draftAndPublish.description": "Scrivi una bozza dell'elemento prima di pubblicarlo",
|
||||
"contentType.draftAndPublish.label": "Sistema Bozza/pubblicato",
|
||||
"contentType.kind.change.warning": "Hai cambiato il genere di questo Tipo di Contenuto. Le API verranno ripristinate (route, controller e services verranno sovrascritti).",
|
||||
"error.attributeName.reserved-name": "Questo nome non può essere utilizzato nel tuo Tipo di Contenuto perché potrebbe danneggiare altre funzionalità",
|
||||
"error.contentTypeName.reserved-name": "Questo nome non può essere utilizzato nel tuo progetto perché potrebbe danneggiare altre funzionalità",
|
||||
|
||||
@ -50,8 +50,6 @@
|
||||
"contentType.collectionName.description": "콘텐츠 타입과 테이블 이름이 다를 때 유용합니다.",
|
||||
"contentType.collectionName.label": "콜렉션 이름",
|
||||
"contentType.displayName.label": "표시 이름",
|
||||
"contentType.draftAndPublish.description": "각 항목을 발행하기 전에 초안 버전을 작성합니다.",
|
||||
"contentType.draftAndPublish.label": "초안/발행 시스템",
|
||||
"contentType.kind.change.warning": "콘텐츠 타입을 수정했습니다. API가 리셋됩니다(라우트, 컨트롤러, 서비스가 덮어씌워집니다.)",
|
||||
"error.attributeName.reserved-name": "이 이름은 다른 기능을 손상시킬 수 있으므로 사용할 수 없습니다.",
|
||||
"error.contentType.pluralName-used": "이 값은 단수 이름과 같을 수 없습니다.",
|
||||
|
||||
@ -50,8 +50,6 @@
|
||||
"contentType.collectionName.description": "Przydatne, gdy nazwa typu zawartości i nazwa tabeli różnią się",
|
||||
"contentType.collectionName.label": "Nazwa kolekcji",
|
||||
"contentType.displayName.label": "Nazwa",
|
||||
"contentType.draftAndPublish.description": "Napisz szkic każdego wpisu przed publikacją",
|
||||
"contentType.draftAndPublish.label": "System szkicu/publikacji",
|
||||
"contentType.kind.change.warning": "Właśnie zmieniłeś rodzaj typu treści: API zostanie zresetowane (ścieżki, kontrolery i usługi zostaną nadpisane).",
|
||||
"error.attributeName.reserved-name": "Ta nazwa nie może być używana w tym typie treści, ponieważ może uszkodzić inne funkcje",
|
||||
"error.contentType.pluralName-used": "Ta wartość nie może być taka sama jak pojedyncza",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user