From 640bb98bcc40dd493109dbb5887b6322d085e357 Mon Sep 17 00:00:00 2001 From: Max Chopart Date: Thu, 26 May 2022 11:43:05 +0200 Subject: [PATCH] [Upd #149] Images keep proportions and can be zoomed in --- package-lock.json | 176 ++++++++++++++++++++++++++++++-- package.json | 5 +- src/components/MediaContent.tsx | 92 ++++++++--------- src/styles/s-forms.css | 26 ++--- 4 files changed, 231 insertions(+), 68 deletions(-) diff --git a/package-lock.json b/package-lock.json index ff695f1e..c51cd4d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "prop-types": "^15.7.2", "react-bootstrap": "1.0.1", "react-datepicker": "^4.2.1", + "react-image-zooom": "^1.0.4", "react-intl": "^5.24.6", "react-loader-spinner": "^5.1.0", "react-select": "^3.1.0", @@ -7442,6 +7443,22 @@ "react-docgen": "^5.0.0" } }, + "node_modules/babel-plugin-styled-components": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz", + "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==", + "peer": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11", + "picomatch": "^2.3.0" + }, + "peerDependencies": { + "styled-components": ">= 2" + } + }, "node_modules/babel-plugin-syntax-jsx": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", @@ -8392,6 +8409,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg==", + "peer": true + }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -10237,6 +10260,15 @@ "source-map-resolve": "^0.6.0" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/css-loader": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", @@ -10327,6 +10359,17 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/css-to-react-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", + "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", + "peer": true, + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/css-tree": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", @@ -21391,6 +21434,16 @@ "react-dom": "^16.6.0 || ^17.0.0" } }, + "node_modules/react-image-zooom": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-image-zooom/-/react-image-zooom-1.0.4.tgz", + "integrity": "sha512-Mqi++XgazQ1aG9P2rDprKTUQr/h/VNMrbNGIWtxfgi2dCI2oqI/Gx/9MP5nLyrWityzbGccxWZpuCj1DxAUo/Q==", + "peerDependencies": { + "react": "^17.0.1", + "react-dom": "^17.0.1", + "styled-components": "^5.2.1" + } + }, "node_modules/react-input-autosize": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz", @@ -21445,8 +21498,7 @@ "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", @@ -23319,8 +23371,7 @@ "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "dev": true + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, "node_modules/shasum": { "version": "1.0.2", @@ -24512,6 +24563,46 @@ "tslib": "^2.1.0" } }, + "node_modules/styled-components": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.5.tgz", + "integrity": "sha512-ndETJ9RKaaL6q41B69WudeqLzOpY1A/ET/glXkNZ2T7dPjPqpPCXXQjDFYZWwNnE5co0wX+gTCqx9mfxTmSIPg==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/@emotion/is-prop-valid": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz", + "integrity": "sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==", + "peer": true, + "dependencies": { + "@emotion/memoize": "^0.7.4" + } + }, "node_modules/subarg": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", @@ -33025,6 +33116,19 @@ "react-docgen": "^5.0.0" } }, + "babel-plugin-styled-components": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz", + "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==", + "peer": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.16.0", + "@babel/helper-module-imports": "^7.16.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11", + "picomatch": "^2.3.0" + } + }, "babel-plugin-syntax-jsx": { "version": "6.18.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", @@ -33801,6 +33905,12 @@ "quick-lru": "^4.0.1" } }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg==", + "peer": true + }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -35314,6 +35424,12 @@ } } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=", + "peer": true + }, "css-loader": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", @@ -35380,6 +35496,17 @@ "nth-check": "^2.0.1" } }, + "css-to-react-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", + "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", + "peer": true, + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "css-tree": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", @@ -43835,6 +43962,12 @@ "shallowequal": "^1.1.0" } }, + "react-image-zooom": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/react-image-zooom/-/react-image-zooom-1.0.4.tgz", + "integrity": "sha512-Mqi++XgazQ1aG9P2rDprKTUQr/h/VNMrbNGIWtxfgi2dCI2oqI/Gx/9MP5nLyrWityzbGccxWZpuCj1DxAUo/Q==", + "requires": {} + }, "react-input-autosize": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-3.0.0.tgz", @@ -43874,8 +44007,7 @@ "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", - "dev": true + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, "react-lifecycles-compat": { "version": "3.0.4", @@ -45359,8 +45491,7 @@ "shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", - "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", - "dev": true + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, "shasum": { "version": "1.0.2", @@ -46335,6 +46466,35 @@ "tslib": "^2.1.0" } }, + "styled-components": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.5.tgz", + "integrity": "sha512-ndETJ9RKaaL6q41B69WudeqLzOpY1A/ET/glXkNZ2T7dPjPqpPCXXQjDFYZWwNnE5co0wX+gTCqx9mfxTmSIPg==", + "peer": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^1.1.0", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "dependencies": { + "@emotion/is-prop-valid": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.2.tgz", + "integrity": "sha512-3QnhqeL+WW88YjYbQL5gUIkthuMw7a0NGbZ7wfFVk2kg/CK5w8w5FFa0RzWjyY1+sujN0NWbtSHH6OJmWHtJpQ==", + "peer": true, + "requires": { + "@emotion/memoize": "^0.7.4" + } + } + } + }, "subarg": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", diff --git a/package.json b/package.json index 9dcabd9a..bea8938c 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "prop-types": "^15.7.2", "react-bootstrap": "1.0.1", "react-datepicker": "^4.2.1", + "react-image-zooom": "^1.0.4", "react-intl": "^5.24.6", "react-loader-spinner": "^5.1.0", "react-select": "^3.1.0", @@ -89,6 +90,7 @@ "chromatic": "^6.5.3", "css-loader": "^3.5.3", "enzyme": "^3.11.0", + "husky": "^7.0.0", "jest": "^26.0.1", "prettier": "^2.5.1", "query-string": "^6.13.5", @@ -97,8 +99,7 @@ "standard-version": "^9.3.2", "style-loader": "^1.2.1", "typescript": "^4.5.5", - "watchify": "^3.11.1", - "husky": "^7.0.0" + "watchify": "^3.11.1" }, "scripts": { "test": "jest", diff --git a/src/components/MediaContent.tsx b/src/components/MediaContent.tsx index 441498fa..74433c47 100644 --- a/src/components/MediaContent.tsx +++ b/src/components/MediaContent.tsx @@ -1,60 +1,81 @@ import React from "react"; import Constants from "../constants/Constants"; import LinkIcon from "./LinkIcon"; +// @ts-ignore +import ImageZoom from "react-image-zooom"; interface Props { question: object; - - // Added only for example in story - hardcodedLink?: string; - iFrame?: boolean; + isIframe?: boolean; } const YOUTUBE_URL = "https://www.youtube.com/"; +const YOUTUBE_WATCH_URL_PARAMETER = "watch?v="; const GOOGLE_DRIVE_URL = "https://drive.google.com/"; +const EMBED_URL_PARAMETER = "embed/"; +const GOOGLE_DRIVE_FILE_PATH = "/file/d/"; +const GOOGLE_DRIVE = "uc?export=view&id="; -const MediaContent = ({ question, hardcodedLink, iFrame }: Props) => { +const MediaContent = ({ question, isIframe = true }: Props) => { const isGoogleDriveImage = (mediaContentUrl: string) => { return ( - mediaContentUrl.includes("/file/d/") && + mediaContentUrl.includes(GOOGLE_DRIVE_FILE_PATH) && mediaContentUrl.includes(GOOGLE_DRIVE_URL) ); }; const isYoutubeVideo = (mediaContentUrl: string) => { return ( - mediaContentUrl.includes("watch?v=") && - mediaContentUrl.includes(YOUTUBE_URL) + mediaContentUrl.includes(YOUTUBE_URL) && + (mediaContentUrl.includes(YOUTUBE_WATCH_URL_PARAMETER) || + mediaContentUrl.includes(EMBED_URL_PARAMETER)) ); }; const getMediaId = (mediaContentUrl: string) => { if (isGoogleDriveImage(mediaContentUrl)) { return mediaContentUrl.substring( - mediaContentUrl.indexOf("/file/d/") + 8, + mediaContentUrl.indexOf(GOOGLE_DRIVE_FILE_PATH) + + GOOGLE_DRIVE_FILE_PATH.length, mediaContentUrl.lastIndexOf("/") ); } if (isYoutubeVideo(mediaContentUrl)) { - return mediaContentUrl.substring(mediaContentUrl.indexOf("watch?v=") + 8); + return mediaContentUrl.substring( + mediaContentUrl.indexOf(YOUTUBE_WATCH_URL_PARAMETER) + + YOUTUBE_WATCH_URL_PARAMETER.length + ); } }; const getEmbedLink = (mediaContentUrl: string) => { if (isGoogleDriveImage(mediaContentUrl)) { - return ( - GOOGLE_DRIVE_URL + "uc?export=view&id=" + getMediaId(mediaContentUrl) - ); + return GOOGLE_DRIVE_URL + GOOGLE_DRIVE + getMediaId(mediaContentUrl); } - if (isYoutubeVideo(mediaContentUrl)) { - return YOUTUBE_URL + "embed/" + getMediaId(mediaContentUrl); + if ( + isYoutubeVideo(mediaContentUrl) && + !mediaContentUrl.includes(EMBED_URL_PARAMETER) + ) { + return YOUTUBE_URL + EMBED_URL_PARAMETER + getMediaId(mediaContentUrl); } return mediaContentUrl; }; const getMediaType = (mediaContentUrl: string) => { - if (mediaContentUrl.includes(YOUTUBE_URL)) { - return