From 6bd74aae870120a560875fab1817e36ee11c26e2 Mon Sep 17 00:00:00 2001 From: swtmply Date: Sat, 1 Apr 2023 03:26:08 +0800 Subject: [PATCH] document galleries --- client/package.json | 3 +- .../jobs-documents-gallery.component.jsx | 115 +++++++++++------- ...jobs-documents-local-gallery.container.jsx | 76 +++++++++--- client/yarn.lock | 82 ++++--------- 4 files changed, 154 insertions(+), 122 deletions(-) diff --git a/client/package.json b/client/package.json index 638b799ac..6f31ce130 100644 --- a/client/package.json +++ b/client/package.json @@ -46,10 +46,11 @@ "react-cookie": "^4.1.1", "react-dom": "^17.0.2", "react-drag-listview": "^0.2.1", - "react-grid-gallery": "^0.5.5", + "react-grid-gallery": "^1.0.0", "react-grid-layout": "^1.3.4", "react-i18next": "^12.2.0", "react-icons": "^4.7.1", + "react-image-lightbox": "^5.1.4", "react-number-format": "^5.1.3", "react-redux": "^8.0.5", "react-resizable": "^3.0.4", diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx index dbd04dddc..2e343ea44 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.component.jsx @@ -1,7 +1,7 @@ import { EditFilled, FileExcelFilled, SyncOutlined } from "@ant-design/icons"; import { Button, Card, Col, Row, Space } from "antd"; import React, { useEffect, useState } from "react"; -import Gallery from "react-grid-gallery"; +import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; import DocumentsUploadComponent from "../documents-upload/documents-upload.component"; import { DetermineFileType } from "../documents-upload/documents-upload.utility"; @@ -11,6 +11,9 @@ import JobsDocumentsGalleryReassign from "./jobs-document-gallery.reassign.compo import JobsDocumentsDeleteButton from "./jobs-documents-gallery.delete.component"; import JobsDocumentsGallerySelectAllComponent from "./jobs-documents-gallery.selectall.component"; +import Lightbox from "react-image-lightbox"; +import "react-image-lightbox/style.css"; + function JobsDocumentsComponent({ data, jobId, @@ -23,11 +26,7 @@ function JobsDocumentsComponent({ }) { const [galleryImages, setgalleryImages] = useState({ images: [], other: [] }); const { t } = useTranslation(); - const [index, setIndex] = useState(0); - - const onCurrentImageChange = (index) => { - setIndex(index); - }; + const [modalState, setModalState] = useState({ open: false, index: 0 }); useEffect(() => { let documents = data.reduce( @@ -37,12 +36,14 @@ function JobsDocumentsComponent({ acc.images.push({ src: GenerateSrcUrl(value), thumbnail: GenerateThumbUrl(value), - thumbnailHeight: 225, - thumbnailWidth: 225, + // src: GenerateSrcUrl(value), + // thumbnail: GenerateThumbUrl(value), + fullsize: GenerateSrcUrl(value), + height: 225, + width: 225, isSelected: false, key: value.key, extension: value.extension, - id: value.id, type: value.type, size: value.size, @@ -62,7 +63,7 @@ function JobsDocumentsComponent({ const fileName = value.key.split("/").pop(); acc.other.push({ source: GenerateSrcUrl(value), - src: "", + src: thumb, thumbnail: thumb, tags: [ { @@ -85,10 +86,9 @@ function JobsDocumentsComponent({ ] : []), ], - thumbnailHeight: 225, - thumbnailWidth: 225, + height: 225, + width: 225, isSelected: false, - extension: value.extension, key: value.key, id: value.id, @@ -148,35 +148,15 @@ function JobsDocumentsComponent({ { - const newWindow = window.open( - `${window.location.protocol}//${window.location.host}/edit?documentId=${galleryImages.images[index].id}`, - "_blank", - "noopener,noreferrer" - ); - if (newWindow) newWindow.opener = null; - }} - > - - , - ]} - onClickImage={(props) => { - window.open( - props.target.src, - "_blank", - "toolbar=0,location=0,menubar=0" - ); + onClick={(index, item) => { + setModalState({ open: true, index: index }); + // window.open( + // item.fullsize, + // "_blank", + // "toolbar=0,location=0,menubar=0" + // ); }} - onSelectImage={(index, image) => { + onSelect={(index, image) => { setgalleryImages({ ...galleryImages, images: galleryImages.images.map((g, idx) => @@ -191,8 +171,6 @@ function JobsDocumentsComponent({ { return { backgroundImage: , @@ -201,14 +179,14 @@ function JobsDocumentsComponent({ cursor: "pointer", }; }} - onClickThumbnail={(index) => { + onClick={(index) => { window.open( galleryImages.other[index].source, "_blank", "toolbar=0,location=0,menubar=0" ); }} - onSelectImage={(index) => { + onSelect={(index) => { setgalleryImages({ ...galleryImages, other: galleryImages.other.map((g, idx) => @@ -219,6 +197,53 @@ function JobsDocumentsComponent({ /> + {modalState.open && ( + { + const newWindow = window.open( + `${window.location.protocol}//${ + window.location.host + }/edit?documentId=${ + galleryImages.images[modalState.index].id + }`, + "_blank", + "noopener,noreferrer" + ); + if (newWindow) newWindow.opener = null; + }} + />, + ]} + mainSrc={galleryImages.images[modalState.index].fullsize} + nextSrc={ + galleryImages.images[ + (modalState.index + 1) % galleryImages.images.length + ].fullsize + } + prevSrc={ + galleryImages.images[ + (modalState.index + galleryImages.images.length - 1) % + galleryImages.images.length + ].fullsize + } + onCloseRequest={() => setModalState({ open: false, index: 0 })} + onMovePrevRequest={() => + setModalState({ + ...modalState, + index: + (modalState.index + galleryImages.images.length - 1) % + galleryImages.images.length, + }) + } + onMoveNextRequest={() => + setModalState({ + ...modalState, + index: (modalState.index + 1) % galleryImages.images.length, + }) + } + /> + )} ); diff --git a/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx b/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx index 5370971d9..f9889f3a6 100644 --- a/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx +++ b/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx @@ -1,7 +1,7 @@ import { SyncOutlined, FileExcelFilled } from "@ant-design/icons"; import { Alert, Button, Card, Space } from "antd"; -import React, { useEffect } from "react"; -import Gallery from "react-grid-gallery"; +import React, { useEffect, useState } from "react"; +import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -19,6 +19,9 @@ import JobsLocalGalleryDownloadButton from "./jobs-documents-local-gallery.downl import JobsDocumentsLocalGalleryReassign from "./jobs-documents-local-gallery.reassign.component"; import JobsDocumentsLocalGallerySelectAllComponent from "./jobs-documents-local-gallery.selectall.component"; +import Lightbox from "react-image-lightbox"; +import "react-image-lightbox/style.css"; + const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, allMedia: selectAllMedia, @@ -49,6 +52,7 @@ export function JobsDocumentsLocalGallery({ vendorid, }) { const { t } = useTranslation(); + const [modalState, setModalState] = useState({ open: false, index: 0 }); useEffect(() => { if (job) { if (invoice_number) { @@ -70,12 +74,20 @@ export function JobsDocumentsLocalGallery({ ) { acc.images.push({ ...val, + fullsize: val.src, + src: val.thumbnail, + height: val.thumbnailHeight, + width: val.thumbnailWidth, ...(val.optimized && { src: val.optimized, fullsize: val.src }), }); if (val.optimized) optimized = true; } else { acc.other.push({ ...val, + fullsize: val.src, + src: val.thumbnail, + height: val.thumbnailHeight, + width: val.thumbnailWidth, tags: [{ value: val.filename, title: val.filename }], }); } @@ -120,8 +132,7 @@ export function JobsDocumentsLocalGallery({ { + onSelect={(index, image) => { toggleMediaSelected({ jobid: job.id, filename: image.filename }); }} {...(optimized && { @@ -133,24 +144,23 @@ export function JobsDocumentsLocalGallery({ />, ], })} - onClickImage={(props) => { - const media = allMedia[job.id].find( - (m) => m.optimized === props.target.src - ); + onClick={(index) => { + setModalState({ open: true, index: index }); + // const media = allMedia[job.id].find( + // (m) => m.optimized === item.src + // ); - window.open( - media ? media.src : props.target.src, - "_blank", - "toolbar=0,location=0,menubar=0" - ); + // window.open( + // media ? media.fullsize : item.fullsize, + // "_blank", + // "toolbar=0,location=0,menubar=0" + // ); }} /> { return { backgroundImage: , @@ -159,18 +169,48 @@ export function JobsDocumentsLocalGallery({ cursor: "pointer", }; }} - onClickThumbnail={(index) => { + onClick={(index) => { window.open( - jobMedia.other[index].src, + jobMedia.other[index].fullsize, "_blank", "toolbar=0,location=0,menubar=0" ); }} - onSelectImage={(index, image) => { + onSelect={(index, image) => { toggleMediaSelected({ jobid: job.id, filename: image.filename }); }} /> + {modalState.open && ( + setModalState({ open: false, index: 0 })} + onMovePrevRequest={() => + setModalState({ + ...modalState, + index: + (modalState.index + jobMedia.images.length - 1) % + jobMedia.images.length, + }) + } + onMoveNextRequest={() => + setModalState({ + ...modalState, + index: (modalState.index + 1) % jobMedia.images.length, + }) + } + /> + )} ); } diff --git a/client/yarn.lock b/client/yarn.lock index d8b9e9899..04749e444 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -3924,14 +3924,6 @@ anymatch@^3.0.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -aphrodite@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/aphrodite/-/aphrodite-0.5.0.tgz#a4b9a8902662395d2702e70ac7a2b4ca66f25703" - integrity sha512-bPcR/68OdLg+16XDYAaKnlGJufxrbOw86ucElS7qHm7Y6ZNvMT/D/VDEEfodjFgfyRyoTeKmSaikULG92kSYvQ== - dependencies: - asap "^2.0.3" - inline-style-prefixer "^2.0.0" - apollo-link-logger@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/apollo-link-logger/-/apollo-link-logger-2.0.1.tgz#63d86b4fe550c147c5a52108710075675694905c" @@ -4073,7 +4065,7 @@ array.prototype.tosorted@^1.1.1: es-shim-unscopables "^1.0.0" get-intrinsic "^1.1.3" -asap@^2.0.3, asap@~2.0.6: +asap@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== @@ -4484,11 +4476,6 @@ boolbase@^1.0.0, boolbase@~1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -bowser@^1.0.0: - version "1.9.4" - resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.9.4.tgz#890c58a2813a9d3243704334fa81b96a5c150c9a" - integrity sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ== - brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -6504,7 +6491,7 @@ executable@^4.1.1: dependencies: pify "^2.2.0" -exenv@^1.2.2: +exenv@^1.2.0: version "1.2.2" resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" integrity sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw== @@ -7404,11 +7391,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -hyphenate-style-name@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" - integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== - i18next-browser-languagedetector@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.0.1.tgz#ead34592edc96c6c3a618a51cb57ad027c5b5d87" @@ -7543,14 +7525,6 @@ ini@^1.3.5: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -inline-style-prefixer@^2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-2.0.5.tgz#c153c7e88fd84fef5c602e95a8168b2770671fe7" - integrity sha512-rlgoApaAAv66JeDFqGYaXwglnlxjyIr7RMaFZqJw4opT0WKnZVXhXMC9SAfuMpN7NELPaImUhJmOO3hAamSlfw== - dependencies: - bowser "^1.0.0" - hyphenate-style-name "^1.0.1" - internal-slot@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" @@ -11157,13 +11131,10 @@ react-error-overlay@6.0.9, react-error-overlay@^6.0.11: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== -react-grid-gallery@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/react-grid-gallery/-/react-grid-gallery-0.5.5.tgz#1b3f3c23a190834e587ab613c96d53ec3af4f0a2" - integrity sha512-DkKg2/Am+VZPDG39fazelTcsZSQrfM/YllnIcWToyUEfOZcrzHxUoqCziCkuTPmCuMbHnrjidBFuDbAFgvSnvQ== - dependencies: - prop-types "^15.5.8" - react-images "^0.5.16" +react-grid-gallery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/react-grid-gallery/-/react-grid-gallery-1.0.0.tgz#31604b9488dfa75a899aa39bc8884138f0409a12" + integrity sha512-S1gr6WXBlPFVrE0x2BHuu7jhyaB61mabcMQyx+8KCgAyKzGza0WF67AfAnS9Q00aurFEq4IP8eqb2Bk5F4RAmQ== react-grid-layout@^1.3.4: version "1.3.4" @@ -11189,15 +11160,13 @@ react-icons@^4.7.1: resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.7.1.tgz#0f4b25a5694e6972677cb189d2a72eabea7a8345" integrity sha512-yHd3oKGMgm7zxo3EA7H2n7vxSoiGmHk5t6Ou4bXsfcgWyhfDKMpyKfhHR6Bjnn63c+YXBLBPUql9H4wPJM6sXw== -react-images@^0.5.16: - version "0.5.19" - resolved "https://registry.yarnpkg.com/react-images/-/react-images-0.5.19.tgz#9339570029e065f9f28a19f03fdb5d9d5aa109d3" - integrity sha512-B3d4W1uFJj+m17K8S65iAyEJShKGBjPk7n7N1YsPiAydEm8mIq9a6CoeQFMY1d7N2QMs6FBCjT9vELyc5jP5JA== +react-image-lightbox@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/react-image-lightbox/-/react-image-lightbox-5.1.4.tgz#5b847dcb79e9efdf9d7cd5621a92e0f156d2cf30" + integrity sha512-kTiAODz091bgT7SlWNHab0LSMZAPJtlNWDGKv7pLlLY1krmf7FuG1zxE0wyPpeA8gPdwfr3cu6sPwZRqWsc3Eg== dependencies: - aphrodite "^0.5.0" - prop-types "^15.6.0" - react-scrolllock "^2.0.1" - react-transition-group "2" + prop-types "^15.7.2" + react-modal "^3.11.1" react-is@^16.10.2, react-is@^16.12.0, react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" @@ -11214,11 +11183,21 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== -react-lifecycles-compat@^3.0.4: +react-lifecycles-compat@^3.0.0, react-lifecycles-compat@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362" integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA== +react-modal@^3.11.1: + version "3.16.1" + resolved "https://registry.yarnpkg.com/react-modal/-/react-modal-3.16.1.tgz#34018528fc206561b1a5467fc3beeaddafb39b2b" + integrity sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg== + dependencies: + exenv "^1.2.0" + prop-types "^15.7.2" + react-lifecycles-compat "^3.0.0" + warning "^4.0.3" + react-number-format@^5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/react-number-format/-/react-number-format-5.1.3.tgz#5534f5141cea29e0fe889f76c73dfad11ddf2e17" @@ -11240,11 +11219,6 @@ react-overlays@^5.2.1: uncontrollable "^7.2.1" warning "^4.0.3" -react-prop-toggle@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/react-prop-toggle/-/react-prop-toggle-1.0.2.tgz#8b0b7e74653606b1427cfcf6c4eaa9198330568e" - integrity sha512-JmerjAXs7qJ959+d0Ygt7Cb2+4fG+n3I2VXO6JO0AcAY1vkRN/JpZKAN67CMXY889xEJcfylmMPhzvf6nWO68Q== - react-redux@^7.2.0: version "7.2.8" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.8.tgz#a894068315e65de5b1b68899f9c6ee0923dd28de" @@ -11373,14 +11347,6 @@ react-scripts@^5.0.1: optionalDependencies: fsevents "^2.3.2" -react-scrolllock@^2.0.1: - version "2.0.7" - resolved "https://registry.yarnpkg.com/react-scrolllock/-/react-scrolllock-2.0.7.tgz#3b879e1fe308fc900ab76e226e9be594c41226fd" - integrity sha512-Gzpu8+ulxdYcybAgJOFTXc70xs7SBZDQbZNpKzchZUgLCJKjz6lrgESx6LHHZgfELx1xYL4yHu3kYQGQPFas/g== - dependencies: - exenv "^1.2.2" - react-prop-toggle "^1.0.2" - react-smooth@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/react-smooth/-/react-smooth-2.0.1.tgz#74c7309916d6ccca182c4b30c8992f179e6c5a05" @@ -11405,7 +11371,7 @@ react-sublime-video@^0.2.5: prop-types "^15.5.10" rc-tween-one "^1.2.5" -react-transition-group@2, react-transition-group@2.9.0: +react-transition-group@2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==