205 lines
7.5 KiB
JavaScript
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>
|
|
);
|
|
}
|