Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: article graph to use functional component #5498

Merged
266 changes: 119 additions & 147 deletions app/assets/javascripts/components/articles/article_graphs.jsx
Original file line number Diff line number Diff line change
@@ -1,170 +1,142 @@
import React from 'react';
import createReactClass from 'create-react-class';
import PropTypes from 'prop-types';
import React, { useEffect, useRef, useState } from 'react';
import Wp10Graph from './wp10_graph.jsx';
import EditSizeGraph from './edit_size_graph.jsx';
import Loading from '../common/loading.jsx';
import request from '../../utils/request';
import request from '../../utils/request.js';

const ArticleGraphs = ({ article }) => {
const { id: article_id } = article;

const ArticleGraphs = createReactClass({
displayName: 'ArticleGraphs',
const [showGraph, setShowGraph] = useState(false);
const [selectedRadio, setSelectedRadio] = useState('wp10_score');
const [articleData, setArticleData] = useState(null);

propTypes: {
article: PropTypes.object
},
const elementRef = useRef(null);

getInitialState() {
return {
showGraph: false,
selectedRadio: 'wp10_score',
articleData: null
useEffect(() => {
const handleClickOutside = (event) => {
const element = elementRef.current;
if (element && !element.contains(event.target)) {
handleHideGraph();
}
};
},

componentDidMount() {
this.ref = React.createRef();
},

componentDidUpdate(_, prevState) {
if (this.state.showGraph && !prevState.showGraph) {
// Add event listener when the component is visible
document.addEventListener('mousedown', this.handleClickOutside);
}
if (!this.state.showGraph && prevState.showGraph) {
// remove event listener when the component is hidden
document.removeEventListener('mousedown', this.handleClickOutside);
}
},
const handlePressEscapeKey = (event) => {
if (event.key === 'Escape') {
handleHideGraph();
}
};
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('keydown', handlePressEscapeKey);

getData() {
if (this.state.articleData) { return; }
return () => {
document.removeEventListener('mousedown', handleClickOutside);
document.removeEventListener('keydown', handlePressEscapeKey);
};
}, []);

const articleId = this.props.article.id;
const articledataUrl = `/articles/article_data.json?article_id=${articleId}`;
function getData() {
if (articleData) {
return;
}
const articledataUrl = `/articles/article_data.json?article_id=${article_id}`;
request(articledataUrl)
.then(resp => resp.json())
.then((data) => {
this.setState({ articleData: data });
setArticleData(data);
});
},
}

handleClickOutside(event) {
const element = this.ref.current;
if (element && !element.contains(event.target)) {
this.hideGraph();
}
},

showGraph() {
this.getData();
this.setState({ showGraph: true });
},

handleRadioChange(event) {
this.setState({
selectedRadio: event.currentTarget.value
});
},

hideGraph() {
this.state.articleData = null;
this.setState({ showGraph: false });
},

graphId() {
return `vega-graph-${this.props.article.id}`;
},

render() {
let style = 'hidden';
if (this.state.showGraph) {
style = '';
}
function handleShowGraph() {
getData();
setShowGraph(true);
}

let graph;
let editSize;
let radioInput;
const graphWidth = 500;
const graphHeight = 300;
const className = `vega-graph ${style}`;

if (this.state.articleData != null) {
// Only render the wp10 graph radio button if the data includes wp10 / article completeness scores
if (this.state.articleData[0].wp10) {
radioInput = (
<div>
<div className="input-row">
<input
type="radio"
name="wp10_score"
value="wp10_score"
checked={this.state.selectedRadio === 'wp10_score'}
onChange={this.handleRadioChange}
/>
<label htmlFor="wp10_score">{I18n.t('articles.wp10')}</label>
</div>
<div className="input-row">
<input
type="radio"
name="edit_size"
value="edit_size"
checked={this.state.selectedRadio === 'edit_size'}
onChange={this.handleRadioChange}
/>
<label htmlFor="edit_size">{I18n.t('articles.edit_size')}</label>
</div>
</div>
);
if (this.state.selectedRadio === 'wp10_score') {
graph = (
<Wp10Graph
graphid = {this.graphId()}
graphWidth = {graphWidth}
graphHeight = {graphHeight}
articleData = {this.state.articleData}
/>
);
} else {
graph = (
<EditSizeGraph
graphid ={this.graphId()}
graphWidth = {graphWidth}
graphHeight = {graphHeight}
articleData = {this.state.articleData}
/>
);
}
} else {
editSize = (
<p>{I18n.t('articles.edit_size')}</p>
);
graph = (
<EditSizeGraph
graphid ={this.graphId()}
graphWidth = {graphWidth}
graphHeight = {graphHeight}
articleData = {this.state.articleData}
/>
);
} // Display the loading element if articleData is not available
} else {
graph = <Loading />;
}
function handleHideGraph() {
setArticleData(null);
setShowGraph(false);
}

return (
<a onClick={this.showGraph} className="inline">
{I18n.t('articles.article_development')}
<div className={className} ref={this.ref}>
<div className="radio-row">
{radioInput}
{editSize}
</div>
{graph}
function handleRadioChange(event) {
setSelectedRadio(event.currentTarget.value);
}

const graphId = `vega-graph-${article_id}`;

const dataIncludesWp10 = articleData?.[0]?.wp10;

let graph;
if (!articleData) {
graph = <Loading />;
} else if (dataIncludesWp10 && selectedRadio === 'wp10_score') {
graph = (
<Wp10Graph
graphid={graphId}
graphWidth={500}
graphHeight={300}
articleData={articleData}
/>
);
} else {
graph = (
<EditSizeGraph
graphid={graphId}
graphWidth={500}
graphHeight={300}
articleData={articleData}
/>
);
}

let radioInput;
if (articleData?.[0].wp10) {
radioInput = (
<div>
<div className="input-row">
<input
type="radio"
name="wp10_score"
id="wp10_score"
value="wp10_score"
checked={selectedRadio === 'wp10_score'}
onChange={handleRadioChange}
/>
<label htmlFor="wp10_score">{I18n.t('articles.wp10')}</label>
</div>
</a>
<div className="input-row">
<input
type="radio"
name="edit_size"
id="edit_size"
value="edit_size"
checked={selectedRadio === 'edit_size'}
onChange={handleRadioChange}
/>
<label htmlFor="edit_size">{I18n.t('articles.edit_size')}</label>
</div>
</div>
);
} else {
radioInput = null;
}
});

const editSize = <p>{I18n.t('articles.edit_size')}</p>;


const className = `vega-graph ${showGraph ? '' : 'hidden'}`;

return (
<a onClick={handleShowGraph} className="inline">
{I18n.t('articles.article_development')}
<div className={className} ref={elementRef}>
<div className="radio-row">
{radioInput}
{editSize}
</div>
{graph}
</div>
</a>
);
};

export default ArticleGraphs;