Skip to content

Commit

Permalink
Merge pull request #122 from guardian/ts-jh/refactor-class-components
Browse files Browse the repository at this point in the history
refactor controls to a functional component
  • Loading branch information
tjsilver committed Aug 26, 2020
2 parents 82d5a03 + 5e95a52 commit 471512f
Showing 1 changed file with 65 additions and 81 deletions.
146 changes: 65 additions & 81 deletions src/ts/components/Controls.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Component } from "react";
import React, { useState, useEffect } from "react";
import { v4 } from "uuid";
import IconButton from "@material-ui/core/IconButton";
import { Close } from "@material-ui/icons";
Expand Down Expand Up @@ -26,47 +26,77 @@ interface IProps {
onToggleActiveState: () => void;
}

interface IState {
pluginState: IPluginState<IMatch> | undefined;
allCategories: ICategory[];
currentCategories: ICategory[];
isLoadingCategories: boolean;
}
const getErrorFeedbackLink = (pluginState: IPluginState<IMatch> | undefined, feedbackHref: string | undefined) => {
const errorLmit = 10;
const data = {
url: document.location.href,
errors: pluginState?.requestErrors?.slice(0, errorLmit)
};
const encodedData = encodeURIComponent(JSON.stringify(data, undefined, 2));
return feedbackHref + encodedData;
};

/**
* A sidebar to display current matches and allow users to apply suggestions.
* Controls to open and close Typerighter and check document.
*/
class Controls extends Component<IProps, IState> {
public state = {
allCategories: [],
currentCategories: [],
isLoadingCategories: false,
pluginState: undefined
} as IState;
public componentWillMount() {
this.props.store.on(STORE_EVENT_NEW_STATE, this.handleNotify);
this.setState({ pluginState: this.props.store.getState() });
this.initCategories();
}
const controls = ({
store,
requestMatchesForDocument,
fetchCategories,
getCurrentCategories,
feedbackHref,
onToggleActiveState,
addCategory
}: IProps) => {

const [pluginState, setPluginState] = useState<IPluginState<IMatch> | undefined>(undefined);
const [isLoadingCategories, setIsLoadingCategories] = useState<boolean>(false);

const fetchAllCategories = async () => {
setIsLoadingCategories(true);
try {
const allCategories = await fetchCategories();
allCategories.forEach(category => addCategory(category.id));
setIsLoadingCategories(false);
} catch (e) {
setIsLoadingCategories(false);
}
};

useEffect(() => {
store.on(STORE_EVENT_NEW_STATE, newState => {
setPluginState(newState);
});
setPluginState(store.getState());

fetchAllCategories();

return () =>
store.removeEventListener(STORE_EVENT_NEW_STATE, setPluginState);
}, []);

public render() {
const pluginIsActive =
this.state.pluginState && selectPluginIsActive(this.state.pluginState);
pluginState && selectPluginIsActive(pluginState);

const requestMatches = () => {
requestMatchesForDocument(
v4(),
getCurrentCategories().map(_ => _.id)
);
};

const handleCheckDocumentButtonClick = (): void => {
if (!pluginIsActive) {
this.props.onToggleActiveState();
onToggleActiveState();
}
this.requestMatchesForDocument();
requestMatches();
};

const headerContainerClasses = pluginIsActive
? "Sidebar__header-container"
: "Sidebar__header-container Sidebar__header-container--is-closed";

const renderErrorMessage = () => {
const pluginState = this.state.pluginState;

if (!pluginState) {
return;
}
Expand All @@ -86,10 +116,10 @@ class Controls extends Component<IProps, IState> {
return (
<div className="Controls__error-message">
{errorMessage}
{this.props.feedbackHref && (
{feedbackHref && (
<span>
If the error persists, please{" "}
<a href={this.getErrorFeedbackLink()} target="_blank">
<a href={getErrorFeedbackLink(pluginState, feedbackHref)} target="_blank">
contact us
</a>
.
Expand All @@ -108,8 +138,9 @@ class Controls extends Component<IProps, IState> {
className="Button"
onClick={handleCheckDocumentButtonClick}
disabled={
this.state.pluginState &&
selectRequestsInProgress(this.state.pluginState)
isLoadingCategories || (
pluginState &&
selectRequestsInProgress(pluginState))
}
>
Check document
Expand All @@ -118,10 +149,10 @@ class Controls extends Component<IProps, IState> {
<IconButton
size="small"
aria-label="close Typerighter"
onClick={this.props.onToggleActiveState}
onClick={onToggleActiveState}
disabled={
this.state.pluginState &&
selectRequestsInProgress(this.state.pluginState)
pluginState &&
selectRequestsInProgress(pluginState)
}
>
<Close />
Expand All @@ -133,53 +164,6 @@ class Controls extends Component<IProps, IState> {
</>
);
}
private handleNotify = (state: IPluginState<IMatch>) => {
this.setState({ pluginState: state });
};

private initCategories = async () => {
const allCategories = await this.fetchCategories();
if (!allCategories) {
return;
}
this.setState({
currentCategories: allCategories
});
allCategories.forEach(category => this.props.addCategory(category.id));
};

private fetchCategories = async () => {
this.setState({ isLoadingCategories: true });
try {
const allCategories = await this.props.fetchCategories();
this.setState({
allCategories,
isLoadingCategories: false
});
return allCategories;
} catch (e) {
this.setState({
isLoadingCategories: false
});
}
};

private requestMatchesForDocument = () => {
this.props.requestMatchesForDocument(
v4(),
this.props.getCurrentCategories().map(_ => _.id)
);
};

private getErrorFeedbackLink = () => {
const errorLmit = 10;
const data = {
url: document.location.href,
errors: this.state.pluginState?.requestErrors?.slice(0, errorLmit)
};
const encodedData = encodeURIComponent(JSON.stringify(data, undefined, 2));
return this.props.feedbackHref + encodedData;
};
}

export default Controls;
export default controls;

0 comments on commit 471512f

Please sign in to comment.