mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 18:33:55 +00:00
Refactor relation-list route
Signed-off-by: Alexandre Bodin <bodin.alex@gmail.com>
This commit is contained in:
parent
b37a92c60f
commit
7509a16152
@ -67,6 +67,24 @@
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/relations/:model/:targetField",
|
||||
"handler": "relations.find",
|
||||
"config": {
|
||||
"policies": [
|
||||
"admin::isAuthenticatedAdmin",
|
||||
[
|
||||
"plugins::content-manager.hasPermissions",
|
||||
[
|
||||
"plugins::content-manager.explorer.create",
|
||||
"plugins::content-manager.explorer.update"
|
||||
],
|
||||
{ "hasAtLeastOne": true }
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"method": "GET",
|
||||
@ -100,25 +118,7 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"method": "GET",
|
||||
"path": "/explorer/:model/relation-list/:targetField",
|
||||
"handler": "ContentManager.findRelationList",
|
||||
"config": {
|
||||
"policies": [
|
||||
"routing",
|
||||
"admin::isAuthenticatedAdmin",
|
||||
[
|
||||
"plugins::content-manager.hasPermissions",
|
||||
[
|
||||
"plugins::content-manager.explorer.create",
|
||||
"plugins::content-manager.explorer.update"
|
||||
],
|
||||
{ "hasAtLeastOne": true }
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"method": "POST",
|
||||
"path": "/explorer/:model",
|
||||
|
||||
@ -342,56 +342,4 @@ module.exports = {
|
||||
|
||||
ctx.body = pm.sanitize(unpublishedEntry, { action: ACTIONS.read });
|
||||
},
|
||||
|
||||
async findRelationList(ctx) {
|
||||
const { model, targetField } = ctx.params;
|
||||
const { _component, ...query } = ctx.request.query;
|
||||
|
||||
const contentManagerServices = strapi.plugins['content-manager'].services;
|
||||
|
||||
if (!targetField) {
|
||||
return ctx.badRequest();
|
||||
}
|
||||
|
||||
const modelDef = _component ? strapi.db.getModel(_component) : strapi.db.getModel(model);
|
||||
|
||||
if (!modelDef) {
|
||||
return ctx.notFound('model.notFound');
|
||||
}
|
||||
|
||||
const attr = modelDef.attributes[targetField];
|
||||
if (!attr) {
|
||||
return ctx.badRequest('targetField.invalid');
|
||||
}
|
||||
|
||||
const target = strapi.db.getModelByAssoc(attr);
|
||||
|
||||
if (!target) {
|
||||
return ctx.notFound('target.notFound');
|
||||
}
|
||||
|
||||
const contentManagerService = contentManagerServices.contentmanager;
|
||||
|
||||
let entities = [];
|
||||
|
||||
if (_.has(ctx.request.query, '_q')) {
|
||||
entities = await contentManagerService.search(target.uid, query);
|
||||
} else {
|
||||
entities = await contentManagerService.fetchAll(target.uid, query);
|
||||
}
|
||||
|
||||
if (!entities) {
|
||||
return ctx.notFound();
|
||||
}
|
||||
|
||||
const modelConfig = _component
|
||||
? await contentManagerServices.components.getConfiguration(modelDef.uid)
|
||||
: await contentManagerServices.contenttypes.getConfiguration(modelDef.uid);
|
||||
|
||||
const field = _.get(modelConfig, `metadatas.${targetField}.edit.mainField`, 'id');
|
||||
const pickFields = [field, 'id', target.primaryKey, PUBLISHED_AT_ATTRIBUTE];
|
||||
const sanitize = d => _.pick(d, pickFields);
|
||||
|
||||
ctx.body = _.isArray(entities) ? entities.map(sanitize) : sanitize(entities);
|
||||
},
|
||||
};
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const createContext = require('../../../../test/helpers/create-context');
|
||||
const ContentManager = require('../ContentManager');
|
||||
const relations = require('../relations');
|
||||
|
||||
describe('ContentManager', () => {
|
||||
describe('findRelationList', () => {
|
||||
describe('Relations', () => {
|
||||
describe('find', () => {
|
||||
test('Fails on model not found', async () => {
|
||||
const notFound = jest.fn();
|
||||
const ctx = createContext(
|
||||
@ -26,7 +26,7 @@ describe('ContentManager', () => {
|
||||
},
|
||||
};
|
||||
|
||||
await ContentManager.findRelationList(ctx);
|
||||
await relations.find(ctx);
|
||||
|
||||
expect(notFound).toHaveBeenCalledWith('model.notFound');
|
||||
});
|
||||
@ -55,7 +55,7 @@ describe('ContentManager', () => {
|
||||
},
|
||||
};
|
||||
|
||||
await ContentManager.findRelationList(ctx);
|
||||
await relations.find(ctx);
|
||||
|
||||
expect(badRequest).toHaveBeenCalledWith('targetField.invalid');
|
||||
});
|
||||
@ -84,7 +84,7 @@ describe('ContentManager', () => {
|
||||
},
|
||||
};
|
||||
|
||||
await ContentManager.findRelationList(ctx);
|
||||
await relations.find(ctx);
|
||||
|
||||
expect(notFound).toHaveBeenCalledWith('target.notFound');
|
||||
});
|
||||
@ -111,8 +111,8 @@ describe('ContentManager', () => {
|
||||
plugins: {
|
||||
'content-manager': {
|
||||
services: {
|
||||
contenttypes: {
|
||||
getConfiguration() {
|
||||
'content-types': {
|
||||
findConfiguration() {
|
||||
return {
|
||||
metadatas: {
|
||||
target: {
|
||||
@ -145,7 +145,7 @@ describe('ContentManager', () => {
|
||||
},
|
||||
};
|
||||
|
||||
await ContentManager.findRelationList(ctx);
|
||||
await relations.find(ctx);
|
||||
|
||||
expect(ctx.body).toEqual([
|
||||
{
|
||||
@ -0,0 +1,57 @@
|
||||
'use strict';
|
||||
|
||||
const { has, prop, pick } = require('lodash/fp');
|
||||
const { PUBLISHED_AT_ATTRIBUTE } = require('strapi-utils').contentTypes.constants;
|
||||
|
||||
const { getService } = require('../utils');
|
||||
|
||||
module.exports = {
|
||||
async find(ctx) {
|
||||
const { model, targetField } = ctx.params;
|
||||
const { _component, ...query } = ctx.request.query;
|
||||
|
||||
if (!targetField) {
|
||||
return ctx.badRequest();
|
||||
}
|
||||
|
||||
const modelDef = _component ? strapi.db.getModel(_component) : strapi.db.getModel(model);
|
||||
|
||||
if (!modelDef) {
|
||||
return ctx.notFound('model.notFound');
|
||||
}
|
||||
|
||||
const attr = modelDef.attributes[targetField];
|
||||
if (!attr) {
|
||||
return ctx.badRequest('targetField.invalid');
|
||||
}
|
||||
|
||||
const target = strapi.db.getModelByAssoc(attr);
|
||||
|
||||
if (!target) {
|
||||
return ctx.notFound('target.notFound');
|
||||
}
|
||||
|
||||
const contentManagerService = getService('contentmanager');
|
||||
|
||||
let entities = [];
|
||||
|
||||
if (has('_q', ctx.request.query)) {
|
||||
entities = await contentManagerService.search(target.uid, query);
|
||||
} else {
|
||||
entities = await contentManagerService.fetchAll(target.uid, query);
|
||||
}
|
||||
|
||||
if (!entities) {
|
||||
return ctx.notFound();
|
||||
}
|
||||
|
||||
const modelConfig = _component
|
||||
? await getService('components').findConfiguration(modelDef)
|
||||
: await getService('content-types').findConfiguration(modelDef);
|
||||
|
||||
const field = prop(`metadatas.${targetField}.edit.mainField`, modelConfig) || 'id';
|
||||
const pickFields = [field, 'id', target.primaryKey, PUBLISHED_AT_ATTRIBUTE];
|
||||
|
||||
ctx.body = entities.map(pick(pickFields));
|
||||
},
|
||||
};
|
||||
@ -276,14 +276,50 @@ paths:
|
||||
description: Suggestion if request value is not available
|
||||
|
||||
# Relationships
|
||||
/content-manager/relationships/{modelUid}/{targetField}:
|
||||
/content-manager/relations/{model}/{targetField}:
|
||||
get:
|
||||
tags:
|
||||
- Relational fields
|
||||
description: Fetch list of possible related content
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/model'
|
||||
- in: path
|
||||
name: targetField
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: name of the field in the model that holds the relation
|
||||
- in: query
|
||||
name: _component
|
||||
schema:
|
||||
type: string
|
||||
description: Component uid if the targetField is in a component
|
||||
responses:
|
||||
200:
|
||||
description: Returns a list of sanitized entries based of the relational attribute info
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: integer
|
||||
'[primaryKey]':
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: integer
|
||||
'[mainField]':
|
||||
type: string
|
||||
description: value of the mainField of the entry
|
||||
published_at:
|
||||
type: date
|
||||
|
||||
# Collection type
|
||||
/content-manager/collection-type/{modelUid}:
|
||||
/content-manager/collection-type/{model}:
|
||||
get:
|
||||
tags:
|
||||
- Collection Types content management
|
||||
@ -292,12 +328,12 @@ paths:
|
||||
tags:
|
||||
- Collection Types content management
|
||||
description: Create an entry
|
||||
/content-manager/collection-type/{modelUid}/actions/bulkDelete:
|
||||
/content-manager/collection-type/{model}/actions/bulkDelete:
|
||||
post:
|
||||
tags:
|
||||
- Collection Types content management
|
||||
description: Bulk delete entries
|
||||
/content-manager/collection-type/{modelUid}/{id}:
|
||||
/content-manager/collection-type/{model}/{id}:
|
||||
get:
|
||||
tags:
|
||||
- Collection Types content management
|
||||
@ -310,19 +346,19 @@ paths:
|
||||
tags:
|
||||
- Collection Types content management
|
||||
description: Delete one entry
|
||||
/content-manager/collection-type/{modelUid}/{id}/actions/publish:
|
||||
/content-manager/collection-type/{model}/{id}/actions/publish:
|
||||
post:
|
||||
tags:
|
||||
- Collection Types content management
|
||||
description: Publish one entry
|
||||
/content-manager/collection-type/{modelUid}/{id}/actions/unpublish:
|
||||
/content-manager/collection-type/{model}/{id}/actions/unpublish:
|
||||
post:
|
||||
tags:
|
||||
- Collection Types content management
|
||||
description: Unpublish one entry
|
||||
|
||||
# Single type
|
||||
/content-manager/single-type/{modelUid}:
|
||||
/content-manager/single-type/{model}:
|
||||
get:
|
||||
tags:
|
||||
- Single Types content management
|
||||
@ -332,11 +368,11 @@ paths:
|
||||
delete:
|
||||
tags:
|
||||
- Single Types content management
|
||||
/content-manager/single-type/{modelUid}/actions/publish:
|
||||
/content-manager/single-type/{model}/actions/publish:
|
||||
post:
|
||||
tags:
|
||||
- Single Types content management
|
||||
/content-manager/single-type/{modelUid}/actions/unpublish:
|
||||
/content-manager/single-type/{model}/actions/unpublish:
|
||||
post:
|
||||
tags:
|
||||
- Single Types content management
|
||||
@ -521,6 +557,14 @@ components:
|
||||
$ref: '#/components/schemas/kind'
|
||||
description: The number of items to skip before starting to collect the result set
|
||||
|
||||
model:
|
||||
in: path
|
||||
name: model
|
||||
schema:
|
||||
type: string
|
||||
required: true
|
||||
description: Model uid
|
||||
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
|
||||
@ -141,7 +141,7 @@ describe('Relation-list route', () => {
|
||||
test('Can get relation-list for products of a shop', async () => {
|
||||
const res = await rq({
|
||||
method: 'GET',
|
||||
url: '/content-manager/explorer/application::shop.shop/relation-list/products',
|
||||
url: '/content-manager/relations/application::shop.shop/products',
|
||||
});
|
||||
|
||||
expect(res.body).toHaveLength(data.products.length);
|
||||
@ -165,7 +165,7 @@ describe('Relation-list route', () => {
|
||||
test('Can get relation-list for products of a shop', async () => {
|
||||
const res = await rq({
|
||||
method: 'GET',
|
||||
url: '/content-manager/explorer/application::shop.shop/relation-list/products',
|
||||
url: '/content-manager/relations/application::shop.shop/products',
|
||||
});
|
||||
|
||||
expect(res.body).toHaveLength(data.products.length);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user