Merge branch 'master' into master

This commit is contained in:
Jim LAURIE 2020-04-27 11:29:14 +02:00 committed by GitHub
commit f65644ba64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 97 additions and 33 deletions

View File

@ -178,7 +178,7 @@ Load a middleware at the very first place
{ {
"timeout": 100, "timeout": 100,
"load": { "load": {
"before": ["time", "responseTime", "logger", "cors", "responses", "gzip"], "before": ["timer", "responseTime", "logger", "cors", "responses", "gzip"],
"order": [ "order": [
"Define the middlewares' load order by putting their name in this array is the right order" "Define the middlewares' load order by putting their name in this array is the right order"
], ],

View File

@ -328,9 +328,27 @@ To enable the provider, create or edit the file at `./extensions/upload/config/s
Make sure to read the provider's `README` to know what are the possible parameters. Make sure to read the provider's `README` to know what are the possible parameters.
::: tip ### Configuration per envrionment
Some providers may have additional settings such as the AWS S3 needs an API endpoint URL. You can find a list of these for AWS [here](https://docs.aws.amazon.com/general/latest/gr/ses.html)
::: When configuring your upload provider you might want to change the configuration based on the `NODE_ENV` environment variable or use environment specific credentials.
You can do so using a `settings.js` file:
```js
if (process.env.NODE_ENV === 'production') {
module.exports = {
provider: 'providerName',
providerOptions: {
cloud_name: process.env.PROVIDER_CLOUD_NAME,
api_key: process.env.PROVIDER_API_KEY,
api_secret: process.env.PROVIDER_API_SECRET,
},
};
} else {
// to use the default local provider you can return an empty configuration
module.exports = {};
}
```
## Create providers ## Create providers

View File

@ -24,7 +24,7 @@
"containers.Edit.clickToJump": "Klicke, um zu einem Eintrag zu springen", "containers.Edit.clickToJump": "Klicke, um zu einem Eintrag zu springen",
"containers.Edit.delete": "Löschen", "containers.Edit.delete": "Löschen",
"containers.Edit.editing": "Bearbeite...", "containers.Edit.editing": "Bearbeite...",
"containers.Edit.reset": "Abbrechen", "containers.Edit.reset": "Zurücksetzen",
"containers.Edit.returnList": "Zu Liste zurückkehren", "containers.Edit.returnList": "Zu Liste zurückkehren",
"containers.Edit.seeDetails": "Details", "containers.Edit.seeDetails": "Details",
"containers.Edit.submit": "Speichern", "containers.Edit.submit": "Speichern",

View File

@ -172,7 +172,7 @@ const EditForm = forwardRef(
try { try {
const file = await getCroppedResult(); const file = await getCroppedResult();
onSubmitEdit(e, shouldDuplicate, file); onSubmitEdit(e, shouldDuplicate, file, true);
} catch (err) { } catch (err) {
// Silent // Silent
} finally { } finally {

View File

@ -10,7 +10,7 @@ import stepper from './stepper';
import useModalContext from '../../hooks/useModalContext'; import useModalContext from '../../hooks/useModalContext';
const InputModalStepper = ({ isOpen, onToggle, noNavigation, onInputMediaChange }) => { const InputModalStepper = ({ isOpen, onToggle, noNavigation, onInputMediaChange }) => {
const { formatMessage } = useGlobalContext(); const { emitEvent, formatMessage } = useGlobalContext();
const [shouldDeleteFile, setShouldDeleteFile] = useState(false); const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
const [displayNextButton, setDisplayNextButton] = useState(false); const [displayNextButton, setDisplayNextButton] = useState(false);
const { const {
@ -62,6 +62,8 @@ const InputModalStepper = ({ isOpen, onToggle, noNavigation, onInputMediaChange
const editModalRef = useRef(); const editModalRef = useRef();
const handleReplaceMedia = () => { const handleReplaceMedia = () => {
emitEvent('didReplaceMedia', { location: 'upload' });
editModalRef.current.click(); editModalRef.current.click();
}; };
@ -199,12 +201,20 @@ const InputModalStepper = ({ isOpen, onToggle, noNavigation, onInputMediaChange
const handleSubmitEditExistingFile = async ( const handleSubmitEditExistingFile = async (
e, e,
shouldDuplicateMedia = false, shouldDuplicateMedia = false,
file = fileToEdit.file file = fileToEdit.file,
isSubmittingAfterCrop = false
) => { ) => {
e.preventDefault(); e.preventDefault();
submitEditExistingFile(); submitEditExistingFile();
if (isSubmittingAfterCrop) {
emitEvent('didCropFile', {
duplicatedFile: shouldDuplicateMedia,
location: 'content-manager',
});
}
const headers = {}; const headers = {};
const formData = new FormData(); const formData = new FormData();

View File

@ -34,7 +34,7 @@ const InputModalStepperProvider = ({
step, step,
}) => { }) => {
const [formErrors, setFormErrors] = useState(null); const [formErrors, setFormErrors] = useState(null);
const { plugins } = useGlobalContext(); const { emitEvent, plugins } = useGlobalContext();
const [, updated_at] = getFileModelTimestamps(plugins); const [, updated_at] = getFileModelTimestamps(plugins);
const [reducerState, dispatch] = useReducer(reducer, initialState, state => const [reducerState, dispatch] = useReducer(reducer, initialState, state =>
init({ init({
@ -69,6 +69,11 @@ const InputModalStepperProvider = ({
const downloadFiles = async () => { const downloadFiles = async () => {
const files = getFilesToDownload(filesToUpload); const files = getFilesToDownload(filesToUpload);
// Emit event when the users download files from url
if (files.length > 0) {
emitEvent('didSelectFile', { source: 'url', location: 'content-manager' });
}
try { try {
await Promise.all( await Promise.all(
files.map(file => { files.map(file => {
@ -263,6 +268,9 @@ const InputModalStepperProvider = ({
}; };
const handleSetCropResult = blob => { const handleSetCropResult = blob => {
// Emit event : the user cropped a file that is not uploaded
emitEvent('didCropFile', { duplicatedFile: null, location: 'content-manager' });
dispatch({ dispatch({
type: 'SET_CROP_RESULT', type: 'SET_CROP_RESULT',
blob, blob,
@ -352,6 +360,8 @@ const InputModalStepperProvider = ({
}; };
const addFilesToUpload = ({ target: { value } }) => { const addFilesToUpload = ({ target: { value } }) => {
emitEvent('didSelectFile', { source: 'computer', location: 'content-manager' });
dispatch({ dispatch({
type: 'ADD_FILES_TO_UPLOAD', type: 'ADD_FILES_TO_UPLOAD',
filesToUpload: value, filesToUpload: value,

View File

@ -26,7 +26,7 @@ const ModalStepper = ({
onDeleteMedia, onDeleteMedia,
onToggle, onToggle,
}) => { }) => {
const { formatMessage } = useGlobalContext(); const { emitEvent, formatMessage } = useGlobalContext();
const [isWarningDeleteOpen, setIsWarningDeleteOpen] = useState(false); const [isWarningDeleteOpen, setIsWarningDeleteOpen] = useState(false);
const [shouldDeleteFile, setShouldDeleteFile] = useState(false); const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
const [isFormDisabled, setIsFormDisabled] = useState(false); const [isFormDisabled, setIsFormDisabled] = useState(false);
@ -74,6 +74,8 @@ const ModalStepper = ({
}, [isOpen]); }, [isOpen]);
const addFilesToUpload = ({ target: { value } }) => { const addFilesToUpload = ({ target: { value } }) => {
emitEvent('didSelectFile', { source: 'computer', location: 'upload' });
dispatch({ dispatch({
type: 'ADD_FILES_TO_UPLOAD', type: 'ADD_FILES_TO_UPLOAD',
filesToUpload: value, filesToUpload: value,
@ -85,6 +87,11 @@ const ModalStepper = ({
downloadFilesRef.current = async () => { downloadFilesRef.current = async () => {
const files = getFilesToDownload(filesToUpload); const files = getFilesToDownload(filesToUpload);
// Emit event when the users download files from url
if (files.length > 0) {
emitEvent('didSelectFile', { source: 'url', location: 'upload' });
}
try { try {
await Promise.all( await Promise.all(
files.map(file => { files.map(file => {
@ -255,6 +262,9 @@ const ModalStepper = ({
}; };
const handleSetCropResult = blob => { const handleSetCropResult = blob => {
// Emit event : the user cropped a file that is not uploaded
emitEvent('didCropFile', { duplicatedFile: null, location: 'upload' });
dispatch({ dispatch({
type: 'SET_CROP_RESULT', type: 'SET_CROP_RESULT',
blob, blob,
@ -274,10 +284,15 @@ const ModalStepper = ({
const handleSubmitEditExistingFile = async ( const handleSubmitEditExistingFile = async (
e, e,
shouldDuplicateMedia = false, shouldDuplicateMedia = false,
file = fileToEdit.file file = fileToEdit.file,
isSubmittingAfterCrop = false
) => { ) => {
e.preventDefault(); e.preventDefault();
if (isSubmittingAfterCrop) {
emitEvent('didCropFile', { duplicatedFile: shouldDuplicateMedia, location: 'upload' });
}
dispatch({ dispatch({
type: 'ON_SUBMIT_EDIT_EXISTING_FILE', type: 'ON_SUBMIT_EDIT_EXISTING_FILE',
}); });
@ -331,6 +346,7 @@ const ModalStepper = ({
}; };
const handleReplaceMedia = () => { const handleReplaceMedia = () => {
emitEvent('didReplaceMedia', { location: 'upload' });
editModalRef.current.click(); editModalRef.current.click();
}; };

View File

@ -1,17 +1,40 @@
'use strict'; 'use strict';
const body = require('koa-body'); const body = require('koa-body');
const qs = require('koa-qs'); const qs = require('qs');
/** /**
* Body parser hook * Body parser hook
*/ */
const addQsParser = app => {
Object.defineProperty(app.request, 'query', {
configurable: false,
enumerable: true,
/*
* Get parsed query-string.
*/
get() {
const qstr = this.querystring;
const cache = (this._querycache = this._querycache || {});
return cache[qstr] || (cache[qstr] = qs.parse(qstr));
},
/*
* Set query-string as an object.
*/
set(obj) {
this.querystring = qs.stringify(obj);
},
});
return app;
};
module.exports = strapi => { module.exports = strapi => {
return { return {
/** /**
* Initialize the hook * Initialize the hook
*/ */
initialize() { initialize() {
strapi.app.use((ctx, next) => { strapi.app.use((ctx, next) => {
// disable for graphql // disable for graphql
@ -24,7 +47,7 @@ module.exports = strapi => {
})(ctx, next); })(ctx, next);
}); });
qs(strapi.app); addQsParser(strapi.app);
}, },
}; };
}; };

View File

@ -38,7 +38,6 @@
"koa-ip": "^2.0.0", "koa-ip": "^2.0.0",
"koa-locale": "~1.3.0", "koa-locale": "~1.3.0",
"koa-lusca": "~2.2.0", "koa-lusca": "~2.2.0",
"koa-qs": "^2.0.0",
"koa-router": "^7.4.0", "koa-router": "^7.4.0",
"koa-session": "^5.12.0", "koa-session": "^5.12.0",
"koa-static": "^5.0.0", "koa-static": "^5.0.0",
@ -49,6 +48,7 @@
"node-schedule": "1.3.2", "node-schedule": "1.3.2",
"opn": "^5.3.0", "opn": "^5.3.0",
"ora": "^3.0.0", "ora": "^3.0.0",
"qs": "^6.9.3",
"resolve-cwd": "^3.0.0", "resolve-cwd": "^3.0.0",
"rimraf": "^2.6.2", "rimraf": "^2.6.2",
"shelljs": "^0.8.3", "shelljs": "^0.8.3",

View File

@ -10821,14 +10821,6 @@ koa-lusca@~2.2.0:
dependencies: dependencies:
koa-compose "~2.3.0" koa-compose "~2.3.0"
koa-qs@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/koa-qs/-/koa-qs-2.0.0.tgz#18d16b43508a541f092e514351dc09563a48819f"
integrity sha1-GNFrQ1CKVB8JLlFDUdwJVjpIgZ8=
dependencies:
merge-descriptors "~0.0.2"
qs "~2.3.3"
koa-range@0.3.0: koa-range@0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/koa-range/-/koa-range-0.3.0.tgz#3588e3496473a839a1bd264d2a42b1d85bd7feac" resolved "https://registry.yarnpkg.com/koa-range/-/koa-range-0.3.0.tgz#3588e3496473a839a1bd264d2a42b1d85bd7feac"
@ -11778,16 +11770,11 @@ meow@^5.0.0:
trim-newlines "^2.0.0" trim-newlines "^2.0.0"
yargs-parser "^10.0.0" yargs-parser "^10.0.0"
merge-descriptors@1.0.1: merge-descriptors@1.0.1, merge-descriptors@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=
merge-descriptors@~0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-0.0.2.tgz#c36a52a781437513c57275f39dd9d317514ac8c7"
integrity sha1-w2pSp4FDdRPFcnXzndnTF1FKyMc=
merge-stream@^2.0.0: merge-stream@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
@ -14330,10 +14317,10 @@ qs@^6.4.0, qs@^6.5.1, qs@^6.5.2, qs@^6.9.1:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.1.tgz#20082c65cb78223635ab1a9eaca8875a29bf8ec9"
integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA== integrity sha512-Cxm7/SS/y/Z3MHWSxXb8lIFqgqBowP5JMlTUFyJN88y0SGQhVmZnqFK/PeuMX9LzUyWsqqhNxIyg0jlzq946yA==
qs@~2.3.3: qs@^6.9.3:
version "2.3.3" version "6.9.3"
resolved "https://registry.yarnpkg.com/qs/-/qs-2.3.3.tgz#e9e85adbe75da0bbe4c8e0476a086290f863b404" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.3.tgz#bfadcd296c2d549f1dffa560619132c977f5008e"
integrity sha1-6eha2+ddoLvkyOBHaghikPhjtAQ= integrity sha512-EbZYNarm6138UKKq46tdx08Yo/q9ZhFoAXAI1meAFd2GtbRDhbZY2WQSICskT0c5q99aFzLG1D4nvTk9tqfXIw==
qs@~6.5.1, qs@~6.5.2: qs@~6.5.1, qs@~6.5.2:
version "6.5.2" version "6.5.2"