diff --git a/packages/strapi-generate-new/package.json b/packages/strapi-generate-new/package.json index 23f6d570cd..be8df579ef 100644 --- a/packages/strapi-generate-new/package.json +++ b/packages/strapi-generate-new/package.json @@ -13,7 +13,7 @@ "lib": "./lib" }, "dependencies": { - "@sentry/node": "^5.27.3", + "@sentry/node": "6.0.3", "chalk": "^2.4.2", "execa": "^1.0.0", "fs-extra": "^9.0.1", diff --git a/packages/strapi-plugin-content-manager/admin/src/components/Container/index.js b/packages/strapi-plugin-content-manager/admin/src/components/Container/index.js index 74a5fae189..b5c9ceee0a 100644 --- a/packages/strapi-plugin-content-manager/admin/src/components/Container/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/components/Container/index.js @@ -1,7 +1,7 @@ import styled from 'styled-components'; const Container = styled.div` - padding: 18px 30px 18px 30px; + padding: 18px 30px 66px 30px; `; export default Container; diff --git a/packages/strapi-plugin-content-manager/admin/src/components/InputUID/index.js b/packages/strapi-plugin-content-manager/admin/src/components/InputUID/index.js index a978c41f62..6d282f64cb 100644 --- a/packages/strapi-plugin-content-manager/admin/src/components/InputUID/index.js +++ b/packages/strapi-plugin-content-manager/admin/src/components/InputUID/index.js @@ -42,6 +42,7 @@ const InputUID = ({ contentTypeUID, description, error: inputError, + label: inputLabel, name, onChange, validations, @@ -217,7 +218,7 @@ const InputUID = ({ return ( - {name} + {inputLabel} {data.map(item => { const { id } = item; - const url = get(item, ['formats', 'small', 'url'], item.url); + const thumbnail = get(item, ['formats', 'small'], item); const isAllowed = allowedTypes.length > 0 ? allowedTypes.includes(getType(item.mime)) : true; const checked = selectedItems.findIndex(file => file.id === id) !== -1; - const fileUrl = prefixFileUrlWithBackendUrl(url); + const fileUrl = prefixFileUrlWithBackendUrl(thumbnail.url); return ( @@ -53,6 +53,7 @@ const List = ({ checked={checked} {...item} url={fileUrl} + mime={thumbnail.mime} onClick={onCardClick} small={smallCards} > diff --git a/packages/strapi-plugin-upload/admin/src/components/VideoPreview/index.js b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/index.js index deda4e2ea8..6f9bf3419c 100644 --- a/packages/strapi-plugin-upload/admin/src/components/VideoPreview/index.js +++ b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/index.js @@ -1,18 +1,36 @@ import React, { useEffect, useReducer, useRef } from 'react'; import PropTypes from 'prop-types'; - +import styled from 'styled-components'; +import { FormattedMessage, useIntl } from 'react-intl'; import Duration from '../Duration'; import LoadingIndicator from '../LoadingIndicator'; import PlayIcon from '../PlayIcon'; import Wrapper from './Wrapper'; import CanvasWrapper from './CanvasWrapper'; import Thumbnail from './Thumbnail'; - import reducer, { initialState } from './reducer'; +import getTrad from '../../utils/getTrad'; + +const EmptyPreview = styled.div` + display: flex; + align-items: center; + justify-content: center; + font-size: ${({ theme }) => theme.main.sizes.fonts.xs}; + color: ${({ theme }) => theme.main.colors.grey}; +`; const VideoPreview = ({ hasIcon, previewUrl, src }) => { + const { formatMessage } = useIntl(); const [reducerState, dispatch] = useReducer(reducer, initialState); - const { duration, dataLoaded, isHover, metadataLoaded, snapshot, seeked } = reducerState.toJS(); + const { + duration, + dataLoaded, + isHover, + metadataLoaded, + snapshot, + seeked, + isError, + } = reducerState.toJS(); // Adapted from https://github.com/brothatru/react-video-thumbnail/blob/master/src/components/VideoThumbnail.js // And from https://github.com/soupette/poc-video-preview @@ -51,6 +69,14 @@ const VideoPreview = ({ hasIcon, previewUrl, src }) => { } }, [dataLoaded, metadataLoaded, seeked, snapshot]); + if (isError) { + return ( + + + + ); + } + return ( { }); }} > - {!snapshot && } + {!snapshot && ( + + )} + {previewUrl ? ( - + ) : ( <> diff --git a/packages/strapi-plugin-upload/admin/src/components/VideoPreview/reducer.js b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/reducer.js index 3809dcf882..572d344abd 100644 --- a/packages/strapi-plugin-upload/admin/src/components/VideoPreview/reducer.js +++ b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/reducer.js @@ -7,6 +7,7 @@ const initialState = fromJS({ metadataLoaded: false, seeked: false, snapshot: false, + isError: false, }); const videoReducer = (state, action) => { @@ -21,6 +22,8 @@ const videoReducer = (state, action) => { return state.update('isHover', () => action.isHover); case 'SET_SNAPSHOT': return state.update('snapshot', () => action.snapshot); + case 'SET_ERROR': + return state.update('isError', () => action.isError); default: return state; } diff --git a/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/VideoPreview.test.js b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/VideoPreview.test.js new file mode 100644 index 0000000000..fbea94daa7 --- /dev/null +++ b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/VideoPreview.test.js @@ -0,0 +1,77 @@ +import React from 'react'; +import { screen, render, fireEvent } from '@testing-library/react'; +import { ThemeProvider } from 'styled-components'; +import VideoPreview from '..'; +import themes from '../../../../../../strapi-admin/admin/src/themes'; + +jest.mock('react-intl', () => ({ + // eslint-disable-next-line react/prop-types + FormattedMessage: ({ id }) =>
{id}
, + useIntl: () => ({ + formatMessage: ({ id }) => id, + }), +})); + +describe('VideoPreview', () => { + it('shows its initial state with no props', () => { + const { container } = render( + + + + ); + + expect(container).toMatchSnapshot(); + }); + + it('shows a loading state when resolving the asset', () => { + render( + + + + ); + + expect(screen.getByLabelText('upload.list.assets.loading-asset')).toBeVisible(); + }); + + it('shows the thumbnail but not the video when previewURL is passed', () => { + const { container } = render( + + + + ); + + expect(screen.getByAltText('upload.list.assets.preview-asset')).toBeVisible(); + + expect(container.querySelector('video')).toBeFalsy(); + }); + + it('shows the video when the previewURL is not passed', () => { + const { container } = render( + + + + ); + + expect(container.querySelector('video')).toBeVisible(); + }); + + it('shows a fallback message when the video is in error', () => { + const { container } = render( + + + + ); + + fireEvent(container.querySelector('video'), new Event('error')); + + expect(screen.getByText('upload.list.assets.not-supported-content')).toBeVisible(); + }); +}); diff --git a/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/__snapshots__/VideoPreview.test.js.snap b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/__snapshots__/VideoPreview.test.js.snap new file mode 100644 index 0000000000..03dae6bbc5 --- /dev/null +++ b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/__snapshots__/VideoPreview.test.js.snap @@ -0,0 +1,118 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`VideoPreview shows its initial state with no props 1`] = ` +.c3 { + margin: 0; + line-height: normal; + color: #ffffff; + font-size: 13px; + font-weight: 500; + text-transform: none; +} + +.c4 { + position: absolute; + bottom: 10px; + right: 10px; + padding: 3px 5px; + border-radius: 2px; + background-color: #333740; +} + +.c1 { + position: relative; + width: 44%; + height: 4px; + overflow: hidden; + background-color: #515764; + border-radius: 2px; +} + +.c1:before { + content: ''; + display: block; + position: absolute; + left: -100px; + width: 100px; + height: 4px; + background-color: #b3b5b9; + -webkit-animation: gPeyzP 2s linear infinite; + animation: gPeyzP 2s linear infinite; +} + +.c0 { + position: relative; + width: 100%; + height: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} + +.c0 video { + display: none; +} + +.c2 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-box-pack: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.c2 canvas { + display: block; + max-width: 100%; + max-height: 100%; + width: auto; + height: auto; + margin: auto; +} + +
+
+
+
+
+
+
+`; diff --git a/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/reducer.test.js b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/reducer.test.js index 86e79360c7..5d7c5ce591 100644 --- a/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/reducer.test.js +++ b/packages/strapi-plugin-upload/admin/src/components/VideoPreview/tests/reducer.test.js @@ -79,4 +79,17 @@ describe('Upload | components | VideoPreview | reducer', () => { expect(reducer(state, action)).toEqual(expectedState); }); + + it('should set isError to true when the payload is true', () => { + const state = initialState; + + const action = { + type: 'SET_ERROR', + isError: true, + }; + + const expectedState = state.set('isError', true); + + expect(reducer(state, action)).toEqual(expectedState); + }); }); diff --git a/packages/strapi-plugin-upload/admin/src/translations/en.json b/packages/strapi-plugin-upload/admin/src/translations/en.json index 9845cdab28..823a9ee394 100644 --- a/packages/strapi-plugin-upload/admin/src/translations/en.json +++ b/packages/strapi-plugin-upload/admin/src/translations/en.json @@ -35,6 +35,9 @@ "list.assets.selected.plural": "{number} assets selected", "list.assets.selected.singular": "{number} asset selected", "list.assets.type-not-allowed": "This type of file is not allowed.", + "list.assets.not-supported-content": "No preview available", + "list.assets.loading-asset": "Loading the preview for the media: {path}", + "list.assets.preview-asset": "Preview for the video at path {path}", "modal.file-details.date": "Date", "modal.file-details.dimensions": "Dimensions", "modal.file-details.extension": "Extension", diff --git a/packages/strapi-plugin-upload/admin/src/translations/fr.json b/packages/strapi-plugin-upload/admin/src/translations/fr.json index 5b51121d14..536256bd2c 100644 --- a/packages/strapi-plugin-upload/admin/src/translations/fr.json +++ b/packages/strapi-plugin-upload/admin/src/translations/fr.json @@ -35,6 +35,9 @@ "list.assets.selected.plural": "{number} médias sélectionnés", "list.assets.selected.singular": "{number} média sélectionné", "list.assets.type-not-allowed": "Ce type de fichier n'est pas autorisé.", + "list.assets.not-supported-content": "Preview non disponible", + "list.assets.loading-asset": "Chargement du contenu pour le media {path}", + "list.assets.preview-asset": "Preview de la vidéo {path}", "modal.file-details.date": "Date", "modal.file-details.dimensions": "Dimensions", "modal.file-details.extension": "Extension", diff --git a/packages/strapi-plugin-upload/admin/src/translations/index.js b/packages/strapi-plugin-upload/admin/src/translations/index.js index 45495ca45d..9b274b0c09 100644 --- a/packages/strapi-plugin-upload/admin/src/translations/index.js +++ b/packages/strapi-plugin-upload/admin/src/translations/index.js @@ -4,6 +4,7 @@ import en from './en.json'; import es from './es.json'; import fr from './fr.json'; import he from './he.json'; +import it from './it.json'; import ja from './ja.json'; import ms from './ms.json'; import ru from './ru.json'; @@ -20,6 +21,7 @@ const trads = { es, fr, he, + it, ja, ms, ru, diff --git a/packages/strapi-utils/lib/build-query.js b/packages/strapi-utils/lib/build-query.js index d366118804..1c7372240f 100644 --- a/packages/strapi-utils/lib/build-query.js +++ b/packages/strapi-utils/lib/build-query.js @@ -111,8 +111,16 @@ const hasDeepFilters = ({ where = [], sort = [] }, { minDepth = 1 } = {}) => { const normalizeWhereClauses = (whereClauses, { model }) => { return whereClauses - .filter(({ value }) => !_.isNil(value)) + .filter(({ value }) => !_.isNull(value)) .map(({ field, operator, value }) => { + if (_.isUndefined(value)) { + const err = new Error( + `The value of field: '${field}', in your where filter, is undefined.` + ); + err.status = 400; + throw err; + } + if (BOOLEAN_OPERATORS.includes(operator)) { return { field, diff --git a/test/config/front/strapi.js b/test/config/front/strapi.js index 182c0a6e71..1ea0728f8d 100644 --- a/test/config/front/strapi.js +++ b/test/config/front/strapi.js @@ -7,6 +7,8 @@ // Setup the strapi functioon global variable +import '@testing-library/jest-dom/extend-expect'; + const React = require('react'); const hoistNonReactStatics = require('hoist-non-react-statics'); diff --git a/yarn.lock b/yarn.lock index 0457ee6032..cef5f77230 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2694,17 +2694,6 @@ "@sendgrid/client" "^6.4.0" "@sendgrid/helpers" "^6.4.0" -"@sentry/core@5.27.3": - version "5.27.3" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.27.3.tgz#d7a175b71596b7eb4b2e8b4cd1858a60d95813bb" - integrity sha512-yqepQO88jSt5hy0awpk61AxI4oHB09LjVbUEk4nJDg+1YXuND23cuZvH+Sp2jCZX2vrsw2tefwflToYfA8/U2w== - dependencies: - "@sentry/hub" "5.27.3" - "@sentry/minimal" "5.27.3" - "@sentry/types" "5.27.3" - "@sentry/utils" "5.27.3" - tslib "^1.9.3" - "@sentry/core@6.0.3": version "6.0.3" resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.0.3.tgz#620cb32365a11eac75497bed281bd52b9f0bb359" @@ -2716,15 +2705,6 @@ "@sentry/utils" "6.0.3" tslib "^1.9.3" -"@sentry/hub@5.27.3": - version "5.27.3" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.27.3.tgz#f509c2fd38f500afef6030504e82510dbd0649d6" - integrity sha512-icEH3hr6NVQkpowXZcPOs9IgJZP5lMKtvud4mVioSpkd+NxtRdKrGEX4eF2TCviOJc9Md0mV4K+aL5Au7hxggQ== - dependencies: - "@sentry/types" "5.27.3" - "@sentry/utils" "5.27.3" - tslib "^1.9.3" - "@sentry/hub@6.0.3": version "6.0.3" resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.0.3.tgz#097f7b1e775a4c6c20c9bec60d7507d5ad2e8db0" @@ -2734,15 +2714,6 @@ "@sentry/utils" "6.0.3" tslib "^1.9.3" -"@sentry/minimal@5.27.3": - version "5.27.3" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.27.3.tgz#c9263bdd6270bfeae64137177448911dff568e53" - integrity sha512-ng01cM0rsE1RMjqVTpPLN0ZVkTo0I675usM1krkpQe8ddW6tfQ6EJWpt02/BrpQZRQzTtfWp6/RyB1KFXg6icg== - dependencies: - "@sentry/hub" "5.27.3" - "@sentry/types" "5.27.3" - tslib "^1.9.3" - "@sentry/minimal@6.0.3": version "6.0.3" resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.0.3.tgz#6eaaf78c479c49720df3e712d41518e7f4f0ffdf" @@ -2767,32 +2738,6 @@ lru_map "^0.3.3" tslib "^1.9.3" -"@sentry/node@^5.27.3": - version "5.27.3" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.27.3.tgz#174b81fbca8cadac12afe49910cbe9cc25b23f87" - integrity sha512-IZ/TkYRY+P/E5C+RF6Rcb6tpY59fyk0040Q3akzbDjb/hrw5TRKnK8fJ6/0gXCAOvlDPIlpRHFJgJ1p2QgWy+g== - dependencies: - "@sentry/core" "5.27.3" - "@sentry/hub" "5.27.3" - "@sentry/tracing" "5.27.3" - "@sentry/types" "5.27.3" - "@sentry/utils" "5.27.3" - cookie "^0.4.1" - https-proxy-agent "^5.0.0" - lru_map "^0.3.3" - tslib "^1.9.3" - -"@sentry/tracing@5.27.3": - version "5.27.3" - resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.27.3.tgz#787e57a2f7071e375f4fad0f3c3a5ff3381928e7" - integrity sha512-UWrHMdGxPfx1u558CWm1tptc2z0BuqCHVe2+BNN7POahq5BkpbGqaotyPQTBHbfmcs6QGfsMG57ou8HQFrBxyA== - dependencies: - "@sentry/hub" "5.27.3" - "@sentry/minimal" "5.27.3" - "@sentry/types" "5.27.3" - "@sentry/utils" "5.27.3" - tslib "^1.9.3" - "@sentry/tracing@6.0.3": version "6.0.3" resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.0.3.tgz#103f4942ddd546321e22ba20c011adf52b25b3f2" @@ -2804,24 +2749,11 @@ "@sentry/utils" "6.0.3" tslib "^1.9.3" -"@sentry/types@5.27.3": - version "5.27.3" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.27.3.tgz#d377508769bc658d672c287166c7f6c5db45660c" - integrity sha512-PkWhMArFMxBb1g3HtMEL8Ea9PYae2MU0z9CMIWiqzerFy2ZpKG98IU3pt8ic4JkmKQdwB8hDiZpRPMHhW0WYwQ== - "@sentry/types@6.0.3": version "6.0.3" resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.0.3.tgz#a1ef6d6b2ac2a9201e3e4a894db6ecf7ceb5b27c" integrity sha512-266aBQbk9AGedhG2dzXshWbn23LYLElXqlI74DLku48UrU2v7TGKdyik/8/nfOfquCoRSp0GFGYHbItwU124XQ== -"@sentry/utils@5.27.3": - version "5.27.3" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.27.3.tgz#1fc45dfad1f1e4398bee58684d8947666d8d3003" - integrity sha512-R9WvFrRBALZvCzu/9BsuXBCfkNxz4MwdBNSXaBsJo4afQw1ljkjIc9DpHzlL9S9goIwXo81Buwmr5gGDO6aH+Q== - dependencies: - "@sentry/types" "5.27.3" - tslib "^1.9.3" - "@sentry/utils@6.0.3": version "6.0.3" resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.0.3.tgz#114d9faa47f76416c3e140711465e76d2129dba8" @@ -9384,10 +9316,10 @@ graphql-upload@^8.0.2: http-errors "^1.7.3" object-path "^0.11.4" -graphql@15.4.0, graphql@^15.3.0: - version "15.4.0" - resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.4.0.tgz#e459dea1150da5a106486ba7276518b5295a4347" - integrity sha512-EB3zgGchcabbsU9cFe1j+yxdzKQKAbGUWRb13DsrsMN1yyfmmIq+2+L5MqVWcDCE4V89R5AyUOi7sMOGxdsYtA== +graphql@15.5.0, graphql@^15.3.0: + version "15.5.0" + resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5" + integrity sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA== growl@1.9.2: version "1.9.2" @@ -19304,21 +19236,16 @@ tslib@^1, tslib@^1.10.0, tslib@^1.11.2, tslib@^1.13.0, tslib@^1.9.0, tslib@^1.9. resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== -tslib@^2.0.0, tslib@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e" - integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ== - -tslib@^2.0.3, tslib@~2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" - integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== - -tslib@~2.1.0: +tslib@^2.0.0, tslib@^2.0.1, tslib@^2.0.3, tslib@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== +tslib@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.3.tgz#8e0741ac45fc0c226e58a17bfc3e64b9bc6ca61c" + integrity sha512-uZtkfKblCEQtZKBF6EBXVZeQNl82yqtDQdv+eck8u7tdPxjLu2/lp5/uPW+um2tpuxINHWy3GhiccY7QgEaVHQ== + tsscmp@1.0.6, tsscmp@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"