Create & handle association between File upload and others models

This commit is contained in:
Aurelsicoko 2018-02-27 11:52:18 +01:00
parent 8d176dee31
commit ab108a6f93
8 changed files with 104 additions and 29 deletions

View File

@ -49,13 +49,11 @@ export function* submit() {
const isCreating = yield select(makeSelectIsCreating()); const isCreating = yield select(makeSelectIsCreating());
try { try {
const recordCleaned = Object.keys(recordJSON).reduce((acc, current) => { const recordCleaned = Object.keys(recordJSON).reduce((acc, current) => {
acc[current] = cleanData(recordJSON[current], 'value', 'id'); acc.append(current, cleanData(recordJSON[current], 'value', 'id'));
return acc; return acc;
}, {}); }, new FormData());
const id = isCreating ? '' : recordCleaned.id; const id = isCreating ? '' : recordCleaned.id;
const params = { source }; const params = { source };
@ -65,9 +63,12 @@ export function* submit() {
// Call our request helper (see 'utils/request') // Call our request helper (see 'utils/request')
yield call(request, requestUrl, { yield call(request, requestUrl, {
method: isCreating ? 'POST' : 'PUT', method: isCreating ? 'POST' : 'PUT',
headers: {
'X-Forwarded-Host': 'strapi',
},
body: recordCleaned, body: recordCleaned,
params, params,
}); }, false, false);
strapi.notification.success('content-manager.success.record.save'); strapi.notification.success('content-manager.success.record.save');
yield put(submitSuccess()); yield put(submitSuccess());

View File

@ -23,20 +23,40 @@ module.exports = {
}, },
create: async function (params) { create: async function (params) {
const entry = await this.create(Object.keys(params.values).reduce((acc, current) => { // Exclude relationships.
const values = Object.keys(params.values).reduce((acc, current) => {
if (this._attributes[current].type) { if (this._attributes[current].type) {
acc[current] = params.values[current]; acc[current] = params.values[current];
} }
return acc; return acc;
}, {})) }, {});
.catch((err) => {
const message = err.message.split('index:');
const field = _.words(_.last(message).split('_')[0]);
const error = { message: `This ${field} is already taken`, field };
throw error; this.associations
}); .filter(association => association.nature.toLowerCase().indexOf('morphto') !== -1)
.map(association => {
values[association.alias] = params.values[association.alias]
.map(obj => {
const globalId = obj.source && obj.source !== 'content-manager' ?
strapi.plugins[obj.source].models[obj.model].globalId:
strapi.models[obj.model].globalId;
return {
ref: obj.ref,
kind: globalId,
[association.filter]: obj.field
}
})
});
const entry = await this.create(values)
.catch((err) => {
const message = err.message.split('index:');
const field = _.words(_.last(message).split('_')[0]);
const error = { message: `This ${field} is already taken`, field };
throw error;
});
return module.exports.update.call(this, { return module.exports.update.call(this, {
[this.primaryKey]: entry[this.primaryKey], [this.primaryKey]: entry[this.primaryKey],

View File

@ -73,6 +73,7 @@ module.exports = {
// Create an entry using `queries` system // Create an entry using `queries` system
ctx.body = await strapi.plugins['content-manager'].services['contentmanager'].add(ctx.params, ctx.request.body, source); ctx.body = await strapi.plugins['content-manager'].services['contentmanager'].add(ctx.params, ctx.request.body, source);
} catch(error) { } catch(error) {
strapi.log.error(error);
ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: error.message, field: error.field }] }] : error.message); ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: error.message, field: error.field }] }] : error.message);
} }
}, },
@ -85,6 +86,7 @@ module.exports = {
ctx.body = await strapi.plugins['content-manager'].services['contentmanager'].edit(ctx.params, ctx.request.body, source); ctx.body = await strapi.plugins['content-manager'].services['contentmanager'].edit(ctx.params, ctx.request.body, source);
} catch(error) { } catch(error) {
// TODO handle error update // TODO handle error update
strapi.log.error(error);
ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: error.message, field: error.field }] }] : error.message); ctx.badRequest(null, ctx.request.admin ? [{ messages: [{ id: error.message, field: error.field }] }] : error.message);
} }
}, },

View File

@ -38,6 +38,49 @@ module.exports = {
}, },
edit: async (params, values, source) => { edit: async (params, values, source) => {
// Multipart/form-data.
if (values.hasOwnProperty('fields') && values.hasOwnProperty('files')) {
const fields = await strapi.query(params.model, source).update({
id: params.id,
values
});
// Request plugin upload.
if (strapi.plugins.upload) {
const config = await strapi.store({
environment: strapi.config.environment,
type: 'plugin',
name: 'upload'
}).get({ key: 'provider' });
const arrayOfPromise = await Promise.all(
Object.keys(values.files)
.map(async attribute => {
// Bufferize files per attribute.
const buffers = await strapi.plugins.upload.services.upload.bufferize(values.files[attribute]);
const files = buffers.map(file => {
// Add related information to be able to make
// the relationships later.
file.related = [{
ref: params.id,
model: params.model,
source,
field: attribute,
}];
return file;
});
// Make upload async.
return await strapi.plugins.upload.services.upload.upload(files, config);
})
);
}
return fields;
}
// Raw JSON.
return strapi.query(params.model, source).update({ return strapi.query(params.model, source).update({
id: params.id, id: params.id,
values values

View File

@ -32,24 +32,27 @@ module.exports = {
}, },
create: async function (params) { create: async function (params) {
return this.create(Object.keys(params).reduce((acc, current) => { // Exclude relationships.
const values = Object.keys(params).reduce((acc, current) => {
if (_.get(this._attributes, [current, 'type']) || _.get(this._attributes, [current, 'model'])) { if (_.get(this._attributes, [current, 'type']) || _.get(this._attributes, [current, 'model'])) {
acc[current] = params[current]; acc[current] = params[current];
} }
return acc; return acc;
}, {})) }, {});
.catch((err) => {
if (err.message.indexOf('index:') !== -1) {
const message = err.message.split('index:');
const field = _.words(_.last(message).split('_')[0]);
const error = { message: `This ${field} is already taken`, field };
throw error; return this.create(values)
} .catch((err) => {
if (err.message.indexOf('index:') !== -1) {
const message = err.message.split('index:');
const field = _.words(_.last(message).split('_')[0]);
const error = { message: `This ${field} is already taken`, field };
throw err; throw error;
}); }
throw err;
});
}, },
update: async function (search, params = {}) { update: async function (search, params = {}) {

View File

@ -30,7 +30,7 @@ module.exports = {
const Service = strapi.plugins['upload'].services.upload; const Service = strapi.plugins['upload'].services.upload;
// transform stream files to buffer // transform stream files to buffer
const files = await Service.bufferize(ctx.request.body.files); const files = await Service.bufferize(ctx.request.body.files.files);
for (var i = 0; i < files.length; i++) { for (var i = 0; i < files.length; i++) {
if (files[i].size > config.sizeLimit) { if (files[i].size > config.sizeLimit) {

View File

@ -13,13 +13,13 @@ const toArray = require('stream-to-array');
const uuid = require('uuid/v4'); const uuid = require('uuid/v4');
module.exports = { module.exports = {
bufferize: async values => { bufferize: async files => {
if (_.size(values.files) === 0) { if (_.isEmpty(files) === 0) {
throw 'Missing files.'; throw 'Missing files.';
} }
// files is always an array to map on // files is always an array to map on
const files = _.isArray(values.files) ? values.files : [values.files]; files = _.isArray(files) ? files : [files];
// transform all files in buffer // transform all files in buffer
return Promise.all( return Promise.all(

View File

@ -121,6 +121,10 @@ module.exports = {
} else if (association.hasOwnProperty('via') && association.hasOwnProperty('collection')) { } else if (association.hasOwnProperty('via') && association.hasOwnProperty('collection')) {
const relatedAttribute = models[association.collection].attributes[association.via]; const relatedAttribute = models[association.collection].attributes[association.via];
if (!relatedAttribute) {
throw new Error(`The attribute \`${association.via}\` is missing in the model ${_.upperFirst(association.collection)} ${association.plugin ? '(plugin - ' + association.plugin + ')' : '' }`);
}
types.current = 'collection'; types.current = 'collection';
if (relatedAttribute.hasOwnProperty('collection') && relatedAttribute.collection !== '*' && relatedAttribute.hasOwnProperty('via')) { if (relatedAttribute.hasOwnProperty('collection') && relatedAttribute.collection !== '*' && relatedAttribute.hasOwnProperty('via')) {
@ -329,7 +333,9 @@ module.exports = {
const infos = this.getNature(association, key, undefined, model.toLowerCase()); const infos = this.getNature(association, key, undefined, model.toLowerCase());
if (globalName !== '*') { if (globalName !== '*') {
details = _.get(strapi.models, `${globalName}.attributes.${association.via}`, {}); details = association.plugin ?
_.get(strapi.plugins, `${association.plugin}.models.${globalName}.attributes.${association.via}`, {}):
_.get(strapi.models, `${globalName}.attributes.${association.via}`, {});
} }
// Build associations object // Build associations object