Skip to content

Commit

Permalink
Convert Wikimedia classes to components
Browse files Browse the repository at this point in the history
This turns the WikipediaExtract file (and the mostly deprecated
CommonsImage one) from classes to React components, and moves from
jQuery to useCallback/useEffect hooks.
  • Loading branch information
reosarevok committed Nov 27, 2024
1 parent 2277ced commit bc9ffbf
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 85 deletions.
87 changes: 48 additions & 39 deletions root/static/scripts/common/components/CommonsImage.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,48 +12,57 @@ import * as React from 'react';
import {minimalEntity} from '../../../../utility/hydrate.js';
import entityHref from '../utility/entityHref.js';

type Props = {
+cachedImage: ?CommonsImageT,
+entity: NonUrlRelatableEntityT,
};

type State = {
image: ?CommonsImageT,
};

class CommonsImage extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {image: props.cachedImage};
}

componentDidMount() {
if (!this.state.image) {
const $ = require('jquery');
$.get(entityHref(this.props.entity, '/commons-image'), data => {
this.setState({image: data.image});
});
type CommonsImageRequestCallbackT = (CommonsImageT | null) => void;

function loadCommonsImage(
entity: NonUrlRelatableEntityT,
callback: CommonsImageRequestCallbackT,
): void {
const url = entityHref(entity, '/commons-image');

fetch(url)
.then(resp => resp.json())
.then((reqData) => {
callback(reqData.image);
})
.catch((error) => {
console.error(error);
Sentry.captureException(error);
});
}

component CommonsImage(
cachedImage: ?CommonsImageT,
entity: NonUrlRelatableEntityT,
) {
const [commonsImage, setCommonsImage] = React.useState(cachedImage);

const loadCallback: CommonsImageRequestCallbackT =
React.useCallback((data) => {
setCommonsImage(data);
}, [setCommonsImage]);

React.useEffect(() => {
if (cachedImage == null) {
loadCommonsImage(entity, loadCallback);
}
}

render(): React.MixedElement | null {
const {image} = this.state;
return image ? (
<div className="picture">
<img src={image.thumb_url} />
<br />
<span className="picture-note">
<a href={image.page_url}>
{l('Image from Wikimedia Commons')}
</a>
</span>
</div>
) : null;
}
}, [entity, loadCallback]);

return commonsImage ? (
<div className="picture">
<img src={commonsImage.thumb_url} />
<br />
<span className="picture-note">
<a href={commonsImage.page_url}>
{l('Image from Wikimedia Commons')}
</a>
</span>
</div>
) : null;
}

export default (hydrate<Props>(
export default (hydrate<React.PropsOf<CommonsImage>>(
'div.commons-image',
CommonsImage,
minimalEntity,
): React.AbstractComponent<Props, void>);
): component(...React.PropsOf<CommonsImage>));
100 changes: 54 additions & 46 deletions root/static/scripts/common/components/WikipediaExtract.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,59 +31,67 @@ type MinimalEntityWithWikipediaExtractT = {
+gid: string,
};

type Props = {
+cachedWikipediaExtract: WikipediaExtractT | null,
+entity:
| EntityWithWikipediaExtractT
| MinimalEntityWithWikipediaExtractT,
};
type WikipediaExtractRequestCallbackT = (WikipediaExtractT | null) => void;

type State = {
wikipediaExtract: WikipediaExtractT | null,
};
function loadWikipediaExtract(
entity: EntityWithWikipediaExtractT | MinimalEntityWithWikipediaExtractT,
callback: WikipediaExtractRequestCallbackT,
): void {
const url = entityHref(entity, '/wikipedia-extract');

fetch(url)
.then(resp => resp.json())
.then((reqData) => {
callback(reqData.wikipediaExtract);
})
.catch((error) => {
console.error(error);
Sentry.captureException(error);
});
}

component WikipediaExtract(
cachedWikipediaExtract: WikipediaExtractT | null,
entity: EntityWithWikipediaExtractT | MinimalEntityWithWikipediaExtractT,
) {
const [wikipediaExtract, setWikipediaExtract] =
React.useState(cachedWikipediaExtract);

class WikipediaExtract extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {wikipediaExtract: props.cachedWikipediaExtract};
}
const loadCallback: WikipediaExtractRequestCallbackT =
React.useCallback((data) => {
setWikipediaExtract(data);
}, [setWikipediaExtract]);

componentDidMount() {
if (!this.state.wikipediaExtract) {
const $ = require('jquery');
$.get(entityHref(this.props.entity, '/wikipedia-extract'), data => {
this.setState(data);
});
React.useEffect(() => {
if (cachedWikipediaExtract == null) {
loadWikipediaExtract(entity, loadCallback);
}
}
}, [entity, loadCallback]);

render(): React.MixedElement | null {
const {wikipediaExtract} = this.state;
return wikipediaExtract ? (
<>
<h2 className="wikipedia">{l('Wikipedia')}</h2>
<Collapsible
className="wikipedia-extract"
html={wikipediaExtract.content}
/>
<a href={wikipediaExtract.url}>
{l('Continue reading at Wikipedia...')}
</a>
{' '}
<small>
{exp.l(
`Wikipedia content provided under the terms of the
{license_link|Creative Commons BY-SA license}`,
{license_link: 'https://creativecommons.org/licenses/by-sa/3.0/'},
)}
</small>
</>
) : null;
}
return wikipediaExtract ? (
<>
<h2 className="wikipedia">{l('Wikipedia')}</h2>
<Collapsible
className="wikipedia-extract"
html={wikipediaExtract.content}
/>
<a href={wikipediaExtract.url}>
{l('Continue reading at Wikipedia...')}
</a>
{' '}
<small>
{exp.l(
`Wikipedia content provided under the terms of the
{license_link|Creative Commons BY-SA license}`,
{license_link: 'https://creativecommons.org/licenses/by-sa/3.0/'},
)}
</small>
</>
) : null;
}

export default (hydrate<Props>(
export default (hydrate<React.PropsOf<WikipediaExtract>>(
'div.wikipedia-extract',
WikipediaExtract,
minimalEntity,
): React.AbstractComponent<Props, void>);
): component(...React.PropsOf<WikipediaExtract>));

0 comments on commit bc9ffbf

Please sign in to comment.