Files
bodyshop/client/src/components/jobs-documents-local-gallery/jobs-documents-local-gallery.container.jsx

205 lines
7.5 KiB
JavaScript

import { EditFilled, SyncOutlined } from "@ant-design/icons";
import { Alert, Button, Card, Col, Row, Space } from "antd";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { getBillMedia, getJobMedia, toggleMediaSelected } from "../../redux/media/media.actions";
import { selectAllMedia } from "../../redux/media/media.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import { CreateExplorerLinkForJob } from "../../utils/localmedia";
import DocumentsLocalUploadComponent from "../documents-local-upload/documents-local-upload.component";
import JobsDocumentsLocalDeleteButton from "./jobs-documents-local-gallery.delete.component";
import JobsLocalGalleryDownloadButton from "./jobs-documents-local-gallery.download";
import JobsDocumentsLocalGalleryReassign from "./jobs-documents-local-gallery.reassign.component";
import JobsDocumentsLocalGallerySelectAllComponent from "./jobs-documents-local-gallery.selectall.component";
import LocalMediaGrid from "./local-media-grid.component";
import Lightbox from "react-image-lightbox";
import "react-image-lightbox/style.css";
import { HasFeatureAccess } from "../feature-wrapper/feature-wrapper.component";
import UpsellComponent, { upsellEnum } from "../upsell/upsell.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
allMedia: selectAllMedia
});
const mapDispatchToProps = (dispatch) => ({
getJobMedia: (id) => dispatch(getJobMedia(id)),
getBillMedia: ({ jobid, invoice_number }) => {
dispatch(getBillMedia({ jobid, invoice_number }));
},
toggleMediaSelected: ({ jobid, filename }) => dispatch(toggleMediaSelected({ jobid, filename }))
});
export default connect(mapStateToProps, mapDispatchToProps)(JobsDocumentsLocalGallery);
export function JobsDocumentsLocalGallery({
bodyshop,
toggleMediaSelected,
getJobMedia,
getBillMedia,
allMedia,
job,
invoice_number,
vendorid
}) {
const { t } = useTranslation();
const [modalState, setModalState] = useState({ open: false, index: 0 });
useEffect(() => {
if (job) {
if (invoice_number) {
getBillMedia({ jobid: job.id, invoice_number });
} else {
getJobMedia(job.id);
}
}
}, [job, invoice_number, getJobMedia, getBillMedia]);
let optimized;
const jobMedia = allMedia?.[job.id]
? allMedia[job.id].reduce(
(acc, val) => {
if (val.type?.mime && val.type.mime.startsWith("image")) {
acc.images.push({
...val,
fullsize: val.src,
src: val.thumbnail,
height: val.thumbnailHeight,
width: val.thumbnailWidth,
tags: [{ value: val.filename, title: val.filename }],
...(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 }]
});
}
return acc;
},
{ images: [], other: [] }
)
: { images: [], other: [] };
const hasMediaAccess = HasFeatureAccess({ bodyshop, featureName: "media" });
return (
<div>
<Row gutter={[16, 16]}>
<Col span={24}>
<Space wrap>
<Button
onClick={() => {
if (job) {
if (invoice_number) {
getBillMedia({ jobid: job.id, invoice_number });
} else {
getJobMedia(job.id);
}
}
}}
icon={<SyncOutlined />}
/>
<a href={CreateExplorerLinkForJob({ jobid: job.id })}>
<Button>{t("documents.labels.openinexplorer")}</Button>
</a>
<JobsDocumentsLocalGallerySelectAllComponent jobid={job.id} />
<JobsDocumentsLocalGalleryReassign jobid={job.id} />
<JobsLocalGalleryDownloadButton job={job} />
<JobsDocumentsLocalDeleteButton jobid={job.id} />
</Space>
</Col>
{!hasMediaAccess && (
<Col span={24}>
<Card>
<UpsellComponent disableMask upsell={upsellEnum().media.general} />
</Card>
</Col>
)}
<Col span={24}>
<Card>
<DocumentsLocalUploadComponent
job={job}
invoice_number={invoice_number}
vendorid={vendorid}
allowAllTypes
/>
</Card>
</Col>
<Col span={24}>
<Card title={t("jobs.labels.documents-images")}>
{optimized && (
<Alert style={{ margin: "4px" }} title={t("documents.labels.optimizedimage")} type="success" />
)}
<LocalMediaGrid
images={jobMedia.images}
onClick={(index) => {
setModalState({ open: true, index: index });
}}
onToggle={(index) => {
toggleMediaSelected({ jobid: job.id, filename: jobMedia.images[index].filename });
}}
minColumns={4}
expandHeight={true}
/>
</Card>
</Col>
<Col span={24}>
<Card title={t("jobs.labels.documents-other")}>
<LocalMediaGrid
images={jobMedia.other}
onClick={(index) => {
window.open(jobMedia.other[index].fullsize, "_blank", "toolbar=0,location=0,menubar=0");
}}
onToggle={(index) => {
toggleMediaSelected({ jobid: job.id, filename: jobMedia.other[index].filename });
}}
minColumns={4}
expandHeight={true}
/>
</Card>
</Col>
{modalState.open && (
<Lightbox
toolbarButtons={[
<EditFilled
key="edit"
onClick={() => {
const newWindow = window.open(
`${window.location.protocol}//${window.location.host}/edit?imageUrl=${
jobMedia.images[modalState.index].fullsize
}&filename=${jobMedia.images[modalState.index].filename}&jobid=${job.id}`,
"_blank",
"noopener,noreferrer"
);
if (newWindow) newWindow.opener = null;
}}
/>
]}
mainSrc={jobMedia.images[modalState.index].fullsize}
nextSrc={jobMedia.images[(modalState.index + 1) % jobMedia.images.length].fullsize}
prevSrc={jobMedia.images[(modalState.index + jobMedia.images.length - 1) % jobMedia.images.length].fullsize}
onCloseRequest={() => 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
})
}
/>
)}
</Row>
</div>
);
}