From 6bd74aae870120a560875fab1817e36ee11c26e2 Mon Sep 17 00:00:00 2001 From: swtmply Date: Sat, 1 Apr 2023 03:26:08 +0800 Subject: [PATCH 1/6] 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== From 6e7d1abd7093d52ce1a5b1e7a2af5e141f7f22b1 Mon Sep 17 00:00:00 2001 From: swtmply Date: Wed, 5 Apr 2023 02:35:07 +0800 Subject: [PATCH 2/6] fixed column resize --- client/package.json | 4 +- .../production-list-table.component.jsx | 68 ++++++++++++++++++- ...uction-list-table.resizeable.component.jsx | 5 ++ client/src/index.css | 15 ++++ client/yarn.lock | 16 +++-- 5 files changed, 100 insertions(+), 8 deletions(-) diff --git a/client/package.json b/client/package.json index 6f31ce130..7dd25f069 100644 --- a/client/package.json +++ b/client/package.json @@ -45,7 +45,7 @@ "react-color": "^2.19.3", "react-cookie": "^4.1.1", "react-dom": "^17.0.2", - "react-drag-listview": "^0.2.1", + "react-drag-listview": "^2.0.0", "react-grid-gallery": "^1.0.0", "react-grid-layout": "^1.3.4", "react-i18next": "^12.2.0", @@ -53,7 +53,7 @@ "react-image-lightbox": "^5.1.4", "react-number-format": "^5.1.3", "react-redux": "^8.0.5", - "react-resizable": "^3.0.4", + "react-resizable": "^3.0.5", "react-router-dom": "^5.3.0", "react-scripts": "^5.0.1", "react-sticky": "^6.0.3", diff --git a/client/src/components/production-list-table/production-list-table.component.jsx b/client/src/components/production-list-table/production-list-table.component.jsx index 6595476d5..808e0d56c 100644 --- a/client/src/components/production-list-table/production-list-table.component.jsx +++ b/client/src/components/production-list-table/production-list-table.component.jsx @@ -10,7 +10,7 @@ import { Statistic, Table, } from "antd"; -import React, { useMemo, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import ReactDragListView from "react-drag-listview"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -173,6 +173,12 @@ export function ProductionListTable({ // } // }; + useEffect( + () => calculateColumnsWidth(columns, dataSource), + // eslint-disable-next-line react-hooks/exhaustive-deps + [dataSource, state] + ); + if (!!!columns) return
No columns found.
; const totalHrs = data @@ -184,6 +190,7 @@ export function ProductionListTable({ 0 ) .toFixed(1); + return (
({ width: column.width, @@ -276,11 +284,67 @@ export function ProductionListTable({ rowKey="id" loading={loading} dataSource={dataSource} - // scroll={{ x: true }} + scroll={{ x: 1500 }} onChange={handleTableChange} />
); } + +const getTextWidth = (text, font = "14px -apple-system") => { + const canvas = document.createElement("canvas"); + const context = canvas.getContext("2d"); + context.font = font; + const metrics = context.measureText(text); + return Math.round(metrics.width + 80); +}; + +const calculateColumnsWidth = (columns, source, maxWidthPerCell = 500) => { + // First we calculate the width for each column + // The column width is based on its string length + + const columnsWithWidth = columns.map((column) => { + return Object.assign(column, { + width: column.width ?? getTextWidth(column.title), + }); + }); + + // Since we have a minimum width (column's width already calculated), + // now we are going to verify if the cell value is bigger + // than the column width which is already set + + source.forEach((entry) => { + columnsWithWidth.forEach((column, indexColumn) => { + const columnWidth = column.width; + const cellValue = Object.values(entry)[indexColumn]; + + // Get the string width based on chars length + let cellWidth = getTextWidth(cellValue); + + // Verify if the cell value is smaller than column's width + if (cellWidth < columnWidth) cellWidth = columnWidth; + + // Verify if the cell value width is bigger than our max width flag + if (cellWidth > maxWidthPerCell) cellWidth = maxWidthPerCell; + + // Update the column width + columnsWithWidth[indexColumn].width = cellWidth; + }); + }); + + // Sum of all columns width to determine the table max width + const tableWidth = columnsWithWidth + .map((column) => column.width) + .reduce((a, b) => { + return a + b; + }); + + return { + columns: columnsWithWidth, + source, + tableWidth, + }; +}; + export default connect(mapStateToProps, null)(ProductionListTable); diff --git a/client/src/components/production-list-table/production-list-table.resizeable.component.jsx b/client/src/components/production-list-table/production-list-table.resizeable.component.jsx index 2f1324999..e373f28b7 100644 --- a/client/src/components/production-list-table/production-list-table.resizeable.component.jsx +++ b/client/src/components/production-list-table/production-list-table.resizeable.component.jsx @@ -3,6 +3,11 @@ import { Resizable } from "react-resizable"; export default function ResizableComponent(props) { const { onResize, width, ...restProps } = props; + + if (!width) { + ; + } + return ( diff --git a/client/src/index.css b/client/src/index.css index c58b73347..68308ed42 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -12,3 +12,18 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } + +.react-resizable { + position: relative; + background-clip: padding-box; +} + +.react-resizable-handle { + position: absolute; + right: -5px; + bottom: 0; + z-index: 1; + width: 10px; + height: 100%; + cursor: col-resize; +} diff --git a/client/yarn.lock b/client/yarn.lock index 04749e444..5cd924deb 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -11105,10 +11105,10 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" -react-drag-listview@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/react-drag-listview/-/react-drag-listview-0.2.1.tgz#922fa3c37ed4d84f2a349a93b01a623ac565f7dc" - integrity sha512-LFR/14CpmiieITCywfe2rxAg1szAqsynpqgquSgirT9cansDwJdpqAVEjzIRSEql/DRIYTvBYLvMI/HJcVeU4w== +react-drag-listview@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/react-drag-listview/-/react-drag-listview-2.0.0.tgz#b8e7ec5f980ecbbf3abb85f50db0b03cd764edbf" + integrity sha512-7Apx/1Xt4qu+JHHP0rH6aLgZgS7c2MX8ocHVGCi03KfeIWEu0t14MhT3boQKM33l5eJrE/IWfExFTvoYq22fsg== dependencies: babel-runtime "^6.26.0" prop-types "^15.5.8" @@ -11256,6 +11256,14 @@ react-resizable@^3.0.4: prop-types "15.x" react-draggable "^4.0.3" +react-resizable@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-3.0.5.tgz#362721f2efbd094976f1780ae13f1ad7739786c1" + integrity sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w== + dependencies: + prop-types "15.x" + react-draggable "^4.0.3" + react-resize-detector@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-7.1.2.tgz#8ef975dd8c3d56f9a5160ac382ef7136dcd2d86c" From 8a6d94f193f7b11331f0fcfbcd177b7fa226336c Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 5 Apr 2023 14:02:34 -0700 Subject: [PATCH 3/6] Resolve time ticket posting issue. --- .../tech-job-clock-in-form.container.jsx | 15 ++++++++++++++- .../tech-job-clock-out-button.component.jsx | 1 + client/src/graphql/bodyshop.queries.js | 1 + 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.container.jsx b/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.container.jsx index 4144d06d3..7754c07f2 100644 --- a/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.container.jsx +++ b/client/src/components/tech-job-clock-in-form/tech-job-clock-in-form.container.jsx @@ -26,6 +26,10 @@ export function TechClockInContainer({ technician, bodyshop, }) { + console.log( + "🚀 ~ file: tech-job-clock-in-form.container.jsx:29 ~ technician:", + technician + ); const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [insertTimeTicket] = useMutation(INSERT_NEW_TIME_TICKET, { @@ -33,6 +37,10 @@ export function TechClockInContainer({ }); const { t } = useTranslation(); + const emps = bodyshop.employees.filter( + (e) => e.id === (technician && technician.id) + )[0]; + const handleFinish = async (values) => { setLoading(true); const theTime = (await axios.post("/utils/time")).data; @@ -87,7 +95,12 @@ export function TechClockInContainer({ onClick={() => { setTimeTicketContext({ actions: {}, - context: { timeticket: { employeeid: technician.id } }, + context: { + timeticket: { + employeeid: technician.id, + flat_rate: emps.flat_rate, + }, + }, }); }} > diff --git a/client/src/components/tech-job-clock-out-button/tech-job-clock-out-button.component.jsx b/client/src/components/tech-job-clock-out-button/tech-job-clock-out-button.component.jsx index 476742d60..7ea864ad5 100644 --- a/client/src/components/tech-job-clock-out-button/tech-job-clock-out-button.component.jsx +++ b/client/src/components/tech-job-clock-out-button/tech-job-clock-out-button.component.jsx @@ -59,6 +59,7 @@ export function TechClockOffButton({ emps && emps.rates.filter((r) => r.cost_center === values.cost_center)[0] ?.rate, + flat_rate: emps.flat_rate, ciecacode: bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? values.cost_center diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index bd52f4721..956bf9dd4 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -125,6 +125,7 @@ export const QUERY_BODYSHOP = gql` employee_number rates external_id + flat_rate } } } From 9b4247d6f6ce8069583b7695804f41354f801e67 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 5 Apr 2023 14:20:15 -0700 Subject: [PATCH 4/6] Revert "fixed column resize" This reverts commit 6e7d1abd7093d52ce1a5b1e7a2af5e141f7f22b1. --- client/package.json | 4 +- .../production-list-table.component.jsx | 68 +------------------ ...uction-list-table.resizeable.component.jsx | 5 -- client/src/index.css | 15 ---- client/yarn.lock | 16 ++--- 5 files changed, 8 insertions(+), 100 deletions(-) diff --git a/client/package.json b/client/package.json index 7dd25f069..6f31ce130 100644 --- a/client/package.json +++ b/client/package.json @@ -45,7 +45,7 @@ "react-color": "^2.19.3", "react-cookie": "^4.1.1", "react-dom": "^17.0.2", - "react-drag-listview": "^2.0.0", + "react-drag-listview": "^0.2.1", "react-grid-gallery": "^1.0.0", "react-grid-layout": "^1.3.4", "react-i18next": "^12.2.0", @@ -53,7 +53,7 @@ "react-image-lightbox": "^5.1.4", "react-number-format": "^5.1.3", "react-redux": "^8.0.5", - "react-resizable": "^3.0.5", + "react-resizable": "^3.0.4", "react-router-dom": "^5.3.0", "react-scripts": "^5.0.1", "react-sticky": "^6.0.3", diff --git a/client/src/components/production-list-table/production-list-table.component.jsx b/client/src/components/production-list-table/production-list-table.component.jsx index 808e0d56c..6595476d5 100644 --- a/client/src/components/production-list-table/production-list-table.component.jsx +++ b/client/src/components/production-list-table/production-list-table.component.jsx @@ -10,7 +10,7 @@ import { Statistic, Table, } from "antd"; -import React, { useEffect, useMemo, useState } from "react"; +import React, { useMemo, useState } from "react"; import ReactDragListView from "react-drag-listview"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -173,12 +173,6 @@ export function ProductionListTable({ // } // }; - useEffect( - () => calculateColumnsWidth(columns, dataSource), - // eslint-disable-next-line react-hooks/exhaustive-deps - [dataSource, state] - ); - if (!!!columns) return
No columns found.
; const totalHrs = data @@ -190,7 +184,6 @@ export function ProductionListTable({ 0 ) .toFixed(1); - return (
({ width: column.width, @@ -284,67 +276,11 @@ export function ProductionListTable({ rowKey="id" loading={loading} dataSource={dataSource} - scroll={{ x: 1500 }} + // scroll={{ x: true }} onChange={handleTableChange} />
); } - -const getTextWidth = (text, font = "14px -apple-system") => { - const canvas = document.createElement("canvas"); - const context = canvas.getContext("2d"); - context.font = font; - const metrics = context.measureText(text); - return Math.round(metrics.width + 80); -}; - -const calculateColumnsWidth = (columns, source, maxWidthPerCell = 500) => { - // First we calculate the width for each column - // The column width is based on its string length - - const columnsWithWidth = columns.map((column) => { - return Object.assign(column, { - width: column.width ?? getTextWidth(column.title), - }); - }); - - // Since we have a minimum width (column's width already calculated), - // now we are going to verify if the cell value is bigger - // than the column width which is already set - - source.forEach((entry) => { - columnsWithWidth.forEach((column, indexColumn) => { - const columnWidth = column.width; - const cellValue = Object.values(entry)[indexColumn]; - - // Get the string width based on chars length - let cellWidth = getTextWidth(cellValue); - - // Verify if the cell value is smaller than column's width - if (cellWidth < columnWidth) cellWidth = columnWidth; - - // Verify if the cell value width is bigger than our max width flag - if (cellWidth > maxWidthPerCell) cellWidth = maxWidthPerCell; - - // Update the column width - columnsWithWidth[indexColumn].width = cellWidth; - }); - }); - - // Sum of all columns width to determine the table max width - const tableWidth = columnsWithWidth - .map((column) => column.width) - .reduce((a, b) => { - return a + b; - }); - - return { - columns: columnsWithWidth, - source, - tableWidth, - }; -}; - export default connect(mapStateToProps, null)(ProductionListTable); diff --git a/client/src/components/production-list-table/production-list-table.resizeable.component.jsx b/client/src/components/production-list-table/production-list-table.resizeable.component.jsx index e373f28b7..2f1324999 100644 --- a/client/src/components/production-list-table/production-list-table.resizeable.component.jsx +++ b/client/src/components/production-list-table/production-list-table.resizeable.component.jsx @@ -3,11 +3,6 @@ import { Resizable } from "react-resizable"; export default function ResizableComponent(props) { const { onResize, width, ...restProps } = props; - - if (!width) { - ; - } - return ( diff --git a/client/src/index.css b/client/src/index.css index 68308ed42..c58b73347 100644 --- a/client/src/index.css +++ b/client/src/index.css @@ -12,18 +12,3 @@ code { font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace; } - -.react-resizable { - position: relative; - background-clip: padding-box; -} - -.react-resizable-handle { - position: absolute; - right: -5px; - bottom: 0; - z-index: 1; - width: 10px; - height: 100%; - cursor: col-resize; -} diff --git a/client/yarn.lock b/client/yarn.lock index 5cd924deb..04749e444 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -11105,10 +11105,10 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" -react-drag-listview@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/react-drag-listview/-/react-drag-listview-2.0.0.tgz#b8e7ec5f980ecbbf3abb85f50db0b03cd764edbf" - integrity sha512-7Apx/1Xt4qu+JHHP0rH6aLgZgS7c2MX8ocHVGCi03KfeIWEu0t14MhT3boQKM33l5eJrE/IWfExFTvoYq22fsg== +react-drag-listview@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/react-drag-listview/-/react-drag-listview-0.2.1.tgz#922fa3c37ed4d84f2a349a93b01a623ac565f7dc" + integrity sha512-LFR/14CpmiieITCywfe2rxAg1szAqsynpqgquSgirT9cansDwJdpqAVEjzIRSEql/DRIYTvBYLvMI/HJcVeU4w== dependencies: babel-runtime "^6.26.0" prop-types "^15.5.8" @@ -11256,14 +11256,6 @@ react-resizable@^3.0.4: prop-types "15.x" react-draggable "^4.0.3" -react-resizable@^3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-3.0.5.tgz#362721f2efbd094976f1780ae13f1ad7739786c1" - integrity sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w== - dependencies: - prop-types "15.x" - react-draggable "^4.0.3" - react-resize-detector@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-7.1.2.tgz#8ef975dd8c3d56f9a5160ac382ef7136dcd2d86c" From 58defad2ea2d12e9222d497719e66a4aee8119a7 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 5 Apr 2023 17:21:47 -0700 Subject: [PATCH 5/6] IO-2086 Resolve imports for additional classes with gallery. --- .../jobs-documents-gallery.external.component.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.external.component.jsx b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.external.component.jsx index fe23d8ceb..5465bbf5c 100644 --- a/client/src/components/jobs-documents-gallery/jobs-documents-gallery.external.component.jsx +++ b/client/src/components/jobs-documents-gallery/jobs-documents-gallery.external.component.jsx @@ -1,5 +1,5 @@ import React, { useEffect } from "react"; -import Gallery from "react-grid-gallery"; +import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; import { GenerateSrcUrl, GenerateThumbUrl } from "./job-documents.utility"; @@ -39,7 +39,7 @@ function JobsDocumentGalleryExternal({ { + onSelect={(index, image) => { setgalleryImages( galleryImages.map((g, idx) => index === idx ? { ...g, isSelected: !g.isSelected } : g From 146bf95e514ed42ade587e6ee925d924c8dd5b38 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Wed, 5 Apr 2023 17:22:18 -0700 Subject: [PATCH 6/6] IO-2086 Resolve additional gallery import issue & tech login issue. --- .../jobs-documents-local-gallery.external.component.jsx | 7 +++---- .../tech-job-clock-out-button.component.jsx | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.external.component.jsx b/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.external.component.jsx index 46625f419..49fef085e 100644 --- a/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.external.component.jsx +++ b/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.external.component.jsx @@ -1,5 +1,5 @@ import React, { useEffect } from "react"; -import Gallery from "react-grid-gallery"; +import { Gallery } from "react-grid-gallery"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; @@ -38,7 +38,7 @@ function JobDocumentsLocalGalleryExternal({ const { t } = useTranslation(); useEffect(() => { - if ( jobId) { + if (jobId) { getJobMedia(jobId); } }, [jobId, getJobMedia]); @@ -65,8 +65,7 @@ function JobDocumentsLocalGalleryExternal({
{ + onSelect={(index, image) => { setgalleryImages( galleryImages.map((g, idx) => index === idx ? { ...g, isSelected: !g.isSelected } : g diff --git a/client/src/components/tech-job-clock-out-button/tech-job-clock-out-button.component.jsx b/client/src/components/tech-job-clock-out-button/tech-job-clock-out-button.component.jsx index 7ea864ad5..85589b13d 100644 --- a/client/src/components/tech-job-clock-out-button/tech-job-clock-out-button.component.jsx +++ b/client/src/components/tech-job-clock-out-button/tech-job-clock-out-button.component.jsx @@ -59,7 +59,7 @@ export function TechClockOffButton({ emps && emps.rates.filter((r) => r.cost_center === values.cost_center)[0] ?.rate, - flat_rate: emps.flat_rate, + flat_rate: emps && emps.flat_rate, ciecacode: bodyshop.cdk_dealerid || bodyshop.pbs_serialnumber ? values.cost_center