Base changes to job upload screen.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { UploadOutlined } from "@ant-design/icons";
|
||||
import { Result, Upload } from "antd";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import { handleUpload } from "./documents-local-upload.utility";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
export function DocumentsLocalUploadComponent({
|
||||
children,
|
||||
currentUser,
|
||||
bodyshop,
|
||||
job,
|
||||
callbackAfterUpload,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [fileList, setFileList] = useState([]);
|
||||
|
||||
const handleDone = (uid) => {
|
||||
setTimeout(() => {
|
||||
setFileList((fileList) => fileList.filter((x) => x.uid !== uid));
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
return (
|
||||
<Upload.Dragger
|
||||
multiple={true}
|
||||
fileList={fileList}
|
||||
onChange={(f) => {
|
||||
if (f.event && f.event.percent === 100) handleDone(f.file.uid);
|
||||
|
||||
setFileList(f.fileList);
|
||||
}}
|
||||
customRequest={(ev) =>
|
||||
handleUpload({
|
||||
ev,
|
||||
context: {
|
||||
jobid: job.id,
|
||||
callback: callbackAfterUpload,
|
||||
},
|
||||
})
|
||||
}
|
||||
accept="audio/*, video/*, image/*, .pdf, .doc, .docx, .xls, .xlsx"
|
||||
>
|
||||
{children || (
|
||||
<>
|
||||
<p className="ant-upload-drag-icon">
|
||||
<UploadOutlined />
|
||||
</p>
|
||||
<p className="ant-upload-text">
|
||||
Click or drag files to this area to upload.
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</Upload.Dragger>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(DocumentsLocalUploadComponent);
|
||||
@@ -0,0 +1,56 @@
|
||||
import cleanAxios from "../../utils/CleanAxios";
|
||||
import { store } from "../../redux/store";
|
||||
import { addMediaForJob } from "../../redux/media/media.actions";
|
||||
import normalizeUrl from "normalize-url";
|
||||
|
||||
export const handleUpload = async ({ ev, context }) => {
|
||||
const { onError, onSuccess, onProgress, file } = ev;
|
||||
const { jobid, callbackAfterUpload } = context;
|
||||
|
||||
var options = {
|
||||
headers: { "X-Requested-With": "XMLHttpRequest" },
|
||||
onUploadProgress: (e) => {
|
||||
if (!!onProgress) onProgress({ percent: (e.loaded / e.total) * 100 });
|
||||
},
|
||||
};
|
||||
|
||||
const formData = new FormData();
|
||||
|
||||
formData.append("jobid", jobid);
|
||||
formData.append("file", file);
|
||||
const bodyshop = store.getState().user.bodyshop;
|
||||
|
||||
const imexMediaServerResponse = await cleanAxios.post(
|
||||
normalizeUrl(`${bodyshop.localmediaserverhttp}/jobs/upload`),
|
||||
formData,
|
||||
{
|
||||
...options,
|
||||
}
|
||||
);
|
||||
|
||||
if (imexMediaServerResponse.status !== 200) {
|
||||
if (!!onError) {
|
||||
onError(imexMediaServerResponse.statusText);
|
||||
}
|
||||
} else {
|
||||
onSuccess(file);
|
||||
store.dispatch(
|
||||
addMediaForJob({
|
||||
jobid,
|
||||
media: imexMediaServerResponse.data.map((d) => {
|
||||
return {
|
||||
...d,
|
||||
src: normalizeUrl(`${bodyshop.localmediaserverhttp}/${d.src}`),
|
||||
thumbnail: normalizeUrl(
|
||||
`${bodyshop.localmediaserverhttp}/${d.thumbnail}`
|
||||
),
|
||||
};
|
||||
}),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (callbackAfterUpload) {
|
||||
callbackAfterUpload();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { SyncOutlined } from "@ant-design/icons";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { selectAllMedia } from "../../redux/media/media.selectors";
|
||||
import { getJobMedia } from "../../redux/media/media.actions";
|
||||
import { Button, Card, Space } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import Gallery from "react-grid-gallery";
|
||||
import DocumentsLocalUploadComponent from "../documents-local-upload/documents-local-upload.component";
|
||||
import { Link } from "react-router-dom";
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
allMedia: selectAllMedia,
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
getJobMedia: (id) => dispatch(getJobMedia(id)),
|
||||
});
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(JobsDocumentsLocalGallery);
|
||||
|
||||
export function JobsDocumentsLocalGallery({
|
||||
bodyshop,
|
||||
getJobMedia,
|
||||
allMedia,
|
||||
job,
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
if (job) {
|
||||
getJobMedia(job.id);
|
||||
}
|
||||
}, [job, getJobMedia]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Space wrap>
|
||||
<Button
|
||||
onClick={() => {
|
||||
getJobMedia(job.id);
|
||||
}}
|
||||
>
|
||||
<SyncOutlined />
|
||||
</Button>
|
||||
<a
|
||||
href={`imexmedia://${bodyshop.localmediaservernetwork}/Jobs/${job.id}`}
|
||||
>
|
||||
<Button>{t("documents.labels.openinexplorer")}</Button>
|
||||
</a>
|
||||
</Space>
|
||||
<Card>
|
||||
<DocumentsLocalUploadComponent job={job} />
|
||||
</Card>
|
||||
<Card title={t("jobs.labels.documents-images")}>
|
||||
<Gallery
|
||||
images={(allMedia && allMedia[job.id]) || []}
|
||||
enableImageSelection={false}
|
||||
backdropClosesModal={true}
|
||||
onClickImage={(props) => {
|
||||
window.open(
|
||||
props.target.src,
|
||||
"_blank",
|
||||
"toolbar=0,location=0,menubar=0"
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user