-
Notifications
You must be signed in to change notification settings - Fork 598
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Converted upload_viewer.jsx to functional component
- Loading branch information
1 parent
05f1173
commit 01b1052
Showing
1 changed file
with
137 additions
and
158 deletions.
There are no files selected for viewing
295 changes: 137 additions & 158 deletions
295
app/assets/javascripts/components/uploads/upload_viewer.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,181 +1,160 @@ | ||
import React from 'react'; | ||
import React, { useEffect, useState } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import createReactClass from 'create-react-class'; | ||
import { forEach, get } from 'lodash-es'; | ||
import OnClickOutside from 'react-onclickoutside'; | ||
import { connect } from 'react-redux'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { setUploadViewerMetadata, setUploadPageViews, resetUploadsViews } from '../../actions/uploads_actions.js'; | ||
import { formatDateWithoutTime } from '../../utils/date_utils.js'; | ||
import { forEach, get } from 'lodash-es'; | ||
import OnClickOutside from 'react-onclickoutside'; | ||
|
||
const UploadViewer = createReactClass({ | ||
displayName: 'UploadViewer', | ||
const UploadViewer = ({ closeUploadViewer, upload, imageFile }) => { | ||
const dispatch = useDispatch(); | ||
const uploadMetadata = useSelector(state => state.uploads.uploadMetadata); | ||
const pageViews = useSelector(state => state.uploads.averageViews); | ||
|
||
propTypes: { | ||
upload: PropTypes.object, | ||
closeUploadViewer: PropTypes.func, | ||
}, | ||
const [loadingViews, setLoadingViews] = useState(true); | ||
|
||
getInitialState() { | ||
return { | ||
loadingViews: true | ||
useEffect(() => { | ||
dispatch(setUploadViewerMetadata(upload)); | ||
return () => { | ||
dispatch(resetUploadsViews()); | ||
}; | ||
}, | ||
|
||
componentDidMount() { | ||
this.props.setUploadViewerMetadata(this.props.upload); | ||
}, | ||
}, [upload]); | ||
|
||
componentDidUpdate() { | ||
const metadata = get(this.props.uploadMetadata, `query.pages[${this.props.upload.id}]`); | ||
useEffect(() => { | ||
const metadata = get(uploadMetadata, `query.pages[${upload.id}]`); | ||
const fileUsage = get(metadata, 'globalusage', []); | ||
if (fileUsage) { | ||
if (this.state.loadingViews) { | ||
this.handleGetFileViews(fileUsage); | ||
} | ||
if (fileUsage && loadingViews) { | ||
handleGetFileViews(fileUsage); | ||
} | ||
}, | ||
|
||
componentWillUnmount() { | ||
this.props.resetUploadsViews(); | ||
}, | ||
|
||
handleGetFileViews(files) { | ||
this.props.setUploadPageViews(files); | ||
this.setState({ | ||
loadingViews: false | ||
}, [uploadMetadata, upload.id, loadingViews]); | ||
|
||
const handleGetFileViews = files => { | ||
dispatch(setUploadPageViews(files)); | ||
setLoadingViews(false); | ||
}; | ||
|
||
const handleClickOutside = () => { | ||
closeUploadViewer(); | ||
}; | ||
|
||
const metadata = get(uploadMetadata, `query.pages[${upload.id}]`); | ||
const imageDescription = get(metadata, 'imageinfo[0].extmetadata.ImageDescription.value'); | ||
const width = get(metadata, 'imageinfo[0].width'); | ||
const height = get(metadata, 'imageinfo[0].height'); | ||
|
||
let size = get(metadata, 'imageinfo[0].size'); | ||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; | ||
const i = Math.floor(Math.log(size) / Math.log(1024)); | ||
size = `${parseFloat((size / (1024 ** i)).toFixed(2))} ${sizes[i]}`; | ||
|
||
const imageUrl = get(metadata, 'imageinfo[0].url'); | ||
|
||
const profileLink = `/users/${encodeURIComponent(upload.uploader)}`; | ||
const author = <a href={profileLink} target="_blank">{upload.uploader}</a>; | ||
const source = get(metadata, 'imageinfo[0].extmetadata.Credit.value'); | ||
const license = get(metadata, 'imageinfo[0].extmetadata.LicenseShortName.value'); | ||
const globalUsage = get(metadata, 'globalusage', []); | ||
let usageTableElements; | ||
if (globalUsage && pageViews !== undefined) { | ||
usageTableElements = globalUsage.map((usage, index) => { | ||
return ( | ||
<tr className="view-file-details" key={usage.url}> | ||
<td className="row-details">{usage.wiki} </td> | ||
<td className="row-details"><a href={usage.url}>{usage.title}</a> </td> | ||
<td className="text-right row-details">{pageViews[index]}</td> | ||
</tr> | ||
); | ||
}); | ||
}, | ||
|
||
handleClickOutside() { | ||
this.props.closeUploadViewer(); | ||
}, | ||
|
||
|
||
render() { | ||
const metadata = get(this.props.uploadMetadata, `query.pages[${this.props.upload.id}]`); | ||
const imageDescription = get(metadata, 'imageinfo[0].extmetadata.ImageDescription.value'); | ||
const width = get(metadata, 'imageinfo[0].width'); | ||
const height = get(metadata, 'imageinfo[0].height'); | ||
|
||
let size = get(metadata, 'imageinfo[0].size'); | ||
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; | ||
const i = Math.floor(Math.log(size) / Math.log(1024)); | ||
size = `${parseFloat((size / (1024 ** i)).toFixed(2))} ${sizes[i]}`; | ||
|
||
const imageUrl = get(metadata, 'imageinfo[0].url'); | ||
} | ||
|
||
const profileLink = `/users/${encodeURIComponent(this.props.upload.uploader)}`; | ||
const author = <a href={profileLink} target="_blank">{this.props.upload.uploader}</a>; | ||
const source = get(metadata, 'imageinfo[0].extmetadata.Credit.value'); | ||
const license = get(metadata, 'imageinfo[0].extmetadata.LicenseShortName.value'); | ||
const globalUsage = get(metadata, 'globalusage', []); | ||
let usageTableElements; | ||
if (globalUsage && (this.props.pageViews !== undefined)) { | ||
usageTableElements = globalUsage.map((usage, index) => { | ||
return ( | ||
<tr className="view-file-details" key={usage.url}> | ||
<td className="row-details">{usage.wiki} </td> | ||
<td className="row-details"><a href={usage.url}>{usage.title}</a> </td> | ||
<td className="text-right row-details">{this.props.pageViews[index]}</td> | ||
let fileUsageTable; | ||
if (globalUsage.length > 0) { | ||
fileUsageTable = ( | ||
<div> | ||
<h1>{'\n'}</h1> | ||
<h4>File usage on other wikis</h4> | ||
<table border="1"> | ||
<thead> | ||
<tr> | ||
<th>Wiki</th> | ||
<th>Article Name</th> | ||
<th>Views per day</th> | ||
</tr> | ||
); | ||
}); | ||
} | ||
</thead> | ||
<tbody> | ||
{usageTableElements} | ||
</tbody> | ||
</table> | ||
</div> | ||
); | ||
} | ||
let categoriesList = []; | ||
let categories; | ||
forEach(get(metadata, 'categories', []), (category) => { | ||
categoriesList.push(<span key={`span-${category.title}`}> | </span>); | ||
categoriesList.push(<a href={`https://commons.wikimedia.org/wiki/${category.title}`} target="_blank" key={`link-${category.title}`}>{category.title.slice('Category:'.length)}</a>); | ||
}); | ||
if (categoriesList.length > 0) { | ||
categoriesList = categoriesList.splice(1); | ||
categories = ( | ||
<div> | ||
<h1>{'\n'}</h1> | ||
<h4>Categories</h4> | ||
{categoriesList} | ||
</div> | ||
); | ||
} | ||
|
||
let fileUsageTable; | ||
if (globalUsage.length > 0) { | ||
fileUsageTable = ( | ||
<div> | ||
<h1>{'\n'}</h1> | ||
<h4>File usage on other wikis</h4> | ||
<table border="1"> | ||
<thead> | ||
return ( | ||
<div className="module upload-viewer"> | ||
<div className="modal-header"> | ||
<button className="pull-right icon-close" onClick={handleClickOutside} /> | ||
<h3>{upload.file_name}</h3> | ||
</div> | ||
<div className="modal-body"> | ||
<div className="left"> | ||
<a href={upload.url} target="_blank"><img alt={upload.file_name} src={imageFile} /></a> | ||
<p><a href={imageUrl} target="_blank">Original File</a>{` (${width} X ${height} pixels, file size: ${size})`}</p> | ||
<h4>Description</h4> | ||
<p dangerouslySetInnerHTML={{ __html: imageDescription }} /> | ||
</div> | ||
<div className="right"> | ||
<table className="view-file-details"> | ||
<tbody> | ||
<tr> | ||
<th>Wiki</th> | ||
<th>Article Name</th> | ||
<th>Views per day</th> | ||
<td className="row-details bg-grey">Date: </td> | ||
<td className="row-details">{formatDateWithoutTime(upload.uploaded_at)}</td> | ||
</tr> | ||
<tr> | ||
<td className="row-details bg-grey">Author: </td> | ||
<td className="row-details">{author}</td> | ||
</tr> | ||
<tr> | ||
<td className="row-details bg-grey">Source: </td> | ||
<td className="row-details" dangerouslySetInnerHTML={{ __html: source }} /> | ||
</tr> | ||
<tr> | ||
<td className="row-details bg-grey">License: </td> | ||
<td className="row-details">{license}</td> | ||
<td>{'\n'}</td> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{usageTableElements} | ||
</tbody> | ||
</table> | ||
</div> | ||
); | ||
} | ||
let categoriesList = []; | ||
let categories; | ||
forEach(get(metadata, 'categories', []), (category) => { | ||
categoriesList.push(<span key={`span-${category.title}`}> | </span>); | ||
categoriesList.push(<a href={`https://commons.wikimedia.org/wiki/${category.title}`} target="_blank" key={`link-${category.title}`}>{category.title.slice('Category:'.length)}</a>); | ||
}); | ||
if (categoriesList.length > 0) { | ||
categoriesList = categoriesList.splice(1); | ||
categories = ( | ||
<div> | ||
<h1>{'\n'}</h1> | ||
<h4>Categories</h4> | ||
{categoriesList} | ||
</div> | ||
); | ||
} | ||
|
||
return ( | ||
<div className="module upload-viewer"> | ||
<div className="modal-header"> | ||
<button className="pull-right icon-close" onClick={this.props.closeUploadViewer} /> | ||
<h3>{this.props.upload.file_name}</h3> | ||
</div> | ||
<div className="modal-body"> | ||
<div className="left"> | ||
<a href={this.props.upload.url} target="_blank"><img alt={this.props.upload.file_name} src={this.props.imageFile} /></a> | ||
<p><a href={imageUrl} target="_blank">Original File</a>{` (${width} X ${height} pixels, file size: ${size})`}</p> | ||
<h4>Description</h4> | ||
<p dangerouslySetInnerHTML={{ __html: imageDescription }} /> | ||
</div> | ||
<div className="right"> | ||
<table className="view-file-details"> | ||
<tbody> | ||
<tr> | ||
<td className="row-details bg-grey">Date: </td> | ||
<td className="row-details">{formatDateWithoutTime(this.props.upload.uploaded_at)}</td> | ||
</tr> | ||
<tr> | ||
<td className="row-details bg-grey">Author: </td> | ||
<td className="row-details">{author}</td> | ||
</tr> | ||
<tr> | ||
<td className="row-details bg-grey">Source: </td> | ||
<td className="row-details" dangerouslySetInnerHTML={{ __html: source }} /> | ||
</tr> | ||
<tr> | ||
<td className="row-details bg-grey">License: </td> | ||
<td className="row-details">{license}</td> | ||
<td>{'\n'}</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
{categories} | ||
{fileUsageTable} | ||
</div> | ||
</div> | ||
<div className="modal-footer"> | ||
<a className="button dark small pull-right upload-viewer-button" href={this.props.upload.url} target="_blank">View on Commons</a> | ||
{categories} | ||
{fileUsageTable} | ||
</div> | ||
</div> | ||
); | ||
} | ||
}); | ||
|
||
const mapStateToProps = state => ({ | ||
uploadMetadata: state.uploads.uploadMetadata, | ||
pageViews: state.uploads.averageViews | ||
}); | ||
<div className="modal-footer"> | ||
<a className="button dark small pull-right upload-viewer-button" href={upload.url} target="_blank">View on Commons</a> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
const mapDispatchToProps = { | ||
setUploadViewerMetadata, | ||
setUploadPageViews, | ||
resetUploadsViews | ||
UploadViewer.propTypes = { | ||
upload: PropTypes.object, | ||
closeUploadViewer: PropTypes.func, | ||
imageFile: PropTypes.string | ||
}; | ||
|
||
export default connect(mapStateToProps, mapDispatchToProps)(OnClickOutside(UploadViewer)); | ||
export default OnClickOutside(UploadViewer); |