1 import axios from 'axios';
2 import PropTypes from 'prop-types';
3 import React from 'react';
4 import { Helmet } from 'react-helmet';
5 import { withTranslation } from 'react-i18next';
7 import NotFound from './NotFound';
8 import ErrorBoundary from '../common/ErrorBoundary';
9 import ErrorMessage from '../common/ErrorMessage';
10 import Loading from '../common/Loading';
11 import Overview from '../techniques/Overview';
12 import { compareTranslation } from '../../helpers/Technique';
13 import i18n from '../../i18n';
15 const Techniques = ({ namespace, type }) => {
16 const [error, setError] = React.useState(null);
17 const [filter, setFilter] = React.useState({});
18 const [loading, setLoading] = React.useState(true);
19 const [techniques, setTechniques] = React.useState([]);
21 React.useEffect(() => {
22 const savedFilter = localStorage.getItem(`content.filter.${type}`);
24 setFilter(JSON.parse(savedFilter));
26 setFilter(filter => filter ? {} : filter);
30 const updateFilter = React.useCallback(newFilter => {
31 localStorage.setItem(`content.filter.${type}`, JSON.stringify(newFilter));
35 React.useEffect(() => {
36 const ctrl = new AbortController();
37 if (!techniques.length) {
41 .get(`/api/content`, {
51 setTechniques(response.data.sort(compareTranslation('title', i18n.language)));
54 if (!axios.isCancel(error)) {
63 }, [filter, namespace, type]);
65 React.useEffect(() => {
66 setTechniques(t => [...t].sort(compareTranslation('title', i18n.language)));
67 }, [namespace, i18n.language]);
74 return <ErrorMessage error={error} />;
77 if (!techniques || !techniques.length) {
81 return <ErrorBoundary>
83 <title>{i18n.t(`${namespace}.heading`)}</title>
84 <meta name="description" content={i18n.t(`${namespace}.description`)} />
89 setFilter={updateFilter}
90 techniques={techniques}
96 Techniques.propTypes = {
97 namespace: PropTypes.string,
98 type: PropTypes.string,
101 export default withTranslation()(Techniques);