Skip to content

Commit

Permalink
Merge pull request #5753 from om-chauhan1/RefactorReactClassComponent…
Browse files Browse the repository at this point in the history
…sStream16

Converted upload_viewer.jsx to functional component and used i18n for string literals
  • Loading branch information
ragesoss committed Apr 18, 2024
2 parents 09f6a53 + 7788004 commit da0a58c
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 158 deletions.
296 changes: 138 additions & 158 deletions app/assets/javascripts/components/uploads/upload_viewer.jsx
@@ -1,181 +1,161 @@
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 { get } from 'lodash-es';
import useOutsideClick from '../../hooks/useOutsideClick.js';

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());
};
},
}, [upload]);

componentDidMount() {
this.props.setUploadViewerMetadata(this.props.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 ref = useOutsideClick(handleClickOutside);

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}&nbsp;&nbsp;&nbsp;</td>
<td className="row-details"><a href={usage.url}>{usage.title}</a>&nbsp;&nbsp;&nbsp;</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}&nbsp;&nbsp;&nbsp;</td>
<td className="row-details"><a href={usage.url}>{usage.title}</a>&nbsp;&nbsp;&nbsp;</td>
<td className="text-right row-details">{this.props.pageViews[index]}</td>
let fileUsageTable;
if (globalUsage.length > 0) {
fileUsageTable = (
<div>
<h1>{'\n'}</h1>
<h4>{I18n.t('uploads.file_usage')}</h4>
<table border="1">
<thead>
<tr>
<th>{I18n.t('uploads.wiki_big')}</th>
<th>{I18n.t('uploads.article_name')}</th>
<th>{I18n.t('uploads.views_per_day')}</th>
</tr>
);
});
}
</thead>
<tbody>
{usageTableElements}
</tbody>
</table>
</div>
);
}
let categoriesList = [];
let categories;
(metadata?.categories ?? []).forEach((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>{I18n.t('uploads.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" ref={ref}>
<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">{I18n.t('uploads.original_file')}</a>{` (${width} X ${height} pixels, file size: ${size})`}</p>
<h4>{I18n.t('uploads.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">{I18n.t('uploads.date')}&nbsp;</td>
<td className="row-details">{formatDateWithoutTime(upload.uploaded_at)}</td>
</tr>
<tr>
<td className="row-details bg-grey">{I18n.t('uploads.author')}&nbsp;</td>
<td className="row-details">{author}</td>
</tr>
<tr>
<td className="row-details bg-grey">{I18n.t('uploads.source')}&nbsp;</td>
<td className="row-details" dangerouslySetInnerHTML={{ __html: source }} />
</tr>
<tr>
<td className="row-details bg-grey">{I18n.t('uploads.license')}&nbsp;</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:&nbsp;</td>
<td className="row-details">{formatDateWithoutTime(this.props.upload.uploaded_at)}</td>
</tr>
<tr>
<td className="row-details bg-grey">Author:&nbsp;</td>
<td className="row-details">{author}</td>
</tr>
<tr>
<td className="row-details bg-grey">Source:&nbsp;</td>
<td className="row-details" dangerouslySetInnerHTML={{ __html: source }} />
</tr>
<tr>
<td className="row-details bg-grey">License:&nbsp;</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">{I18n.t('uploads.view_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 UploadViewer;
12 changes: 12 additions & 0 deletions config/locales/en.yml
Expand Up @@ -1405,13 +1405,21 @@ en:
button: Update

uploads:
article_name: Article Name
author: "Author:"
categories: Categories
credit: Credit
date: "Date:"
description: Description
file_name: File Name
file_usage: File usage on other wikis
header: Files Uploaded to Wikimedia Commons
image: Image
label: Uploads
license: "License:"
loading: Loading uploads...
none: This class has not contributed any images or other media files to Wikimedia Commons.
original_file: Original File
select_label: Filter by uploader
time_doc: The time of each upload in your local time
uploaded_at: Upload Time
Expand All @@ -1424,7 +1432,11 @@ en:
usages: Usages
gallery_view: Gallery View
list_view: List View
source: "Source:"
tile_view: Tile View
views_per_day: Views per day
view_commons: View on Commons
wiki_big: Wiki

users:
already_enrolled: That user is already enrolled!
Expand Down

0 comments on commit da0a58c

Please sign in to comment.