diff --git a/application/frontend/src/components/LoadingAndErrorIndicator/LoadingAndErrorIndicator.tsx b/application/frontend/src/components/LoadingAndErrorIndicator/LoadingAndErrorIndicator.tsx index 0e2303770..c59c1ac1a 100644 --- a/application/frontend/src/components/LoadingAndErrorIndicator/LoadingAndErrorIndicator.tsx +++ b/application/frontend/src/components/LoadingAndErrorIndicator/LoadingAndErrorIndicator.tsx @@ -10,6 +10,8 @@ export const LoadingAndErrorIndicator: FunctionComponent { + console.log(loading); + console.log(error); return ( <> {loading && } diff --git a/application/frontend/src/pages/BrowseRootCres/browseRootCres.tsx b/application/frontend/src/pages/BrowseRootCres/browseRootCres.tsx index c559e07c4..1466282f6 100644 --- a/application/frontend/src/pages/BrowseRootCres/browseRootCres.tsx +++ b/application/frontend/src/pages/BrowseRootCres/browseRootCres.tsx @@ -1,8 +1,7 @@ import './browseRootCres.scss'; +import axios from 'axios'; import React, { useContext, useEffect, useMemo, useState } from 'react'; -import { useQuery } from 'react-query'; -import { useParams } from 'react-router-dom'; import { DocumentNode } from '../../components/DocumentNode'; import { ClearFilterButton, FilterButton } from '../../components/FilterButton/FilterButton'; @@ -17,30 +16,29 @@ export const BrowseRootCres = () => { const { apiUrl } = useEnvironment(); const [loading, setLoading] = useState(false); const [display, setDisplay] = useState(); - const { error, data, refetch } = useQuery<{ data: Document }, string>( - 'cre', - () => - fetch(`${apiUrl}/root_cres`) - .then((res) => res.json()) - .then((resjson) => { - setDisplay(resjson.data); - return resjson; - }), - { - retry: false, - enabled: false, - onSettled: () => { - setLoading(false); - }, - } - ); + const [error, setError] = useState(null); useEffect(() => { - window.scrollTo(0, 0); setLoading(true); - refetch(); - }, []); + window.scrollTo(0, 0); + axios + .get(`${apiUrl}/root_cres`) + .then(function (response) { + setError(null); + setDisplay(response?.data?.data); + }) + .catch(function (axiosError) { + if (axiosError.response.status === 404) { + setError('Standard does not exist in the DB, please check your search parameters'); + } else { + setError(axiosError.response); + } + }) + .finally(() => { + setLoading(false); + }); + }, []); return (

Root CREs:

diff --git a/application/frontend/src/pages/CommonRequirementEnumeration/CommonRequirementEnumeration.tsx b/application/frontend/src/pages/CommonRequirementEnumeration/CommonRequirementEnumeration.tsx index 77cde05a2..4bd962daa 100644 --- a/application/frontend/src/pages/CommonRequirementEnumeration/CommonRequirementEnumeration.tsx +++ b/application/frontend/src/pages/CommonRequirementEnumeration/CommonRequirementEnumeration.tsx @@ -1,7 +1,7 @@ import './commonRequirementEnumeration.scss'; -import React, { useContext, useEffect, useMemo, useState } from 'react'; -import { useQuery } from 'react-query'; +import axios from 'axios'; +import React, { useEffect, useMemo, useState } from 'react'; import { useParams } from 'react-router-dom'; import { DocumentNode } from '../../components/DocumentNode'; @@ -17,27 +17,32 @@ export const CommonRequirementEnumeration = () => { const { id } = useParams(); const { apiUrl } = useEnvironment(); const [loading, setLoading] = useState(false); - const globalState = useContext(filterContext); - - const { error, data, refetch } = useQuery<{ data: Document }, string>( - 'cre', - () => fetch(`${apiUrl}/id/${id}`).then((res) => res.json()), - { - retry: false, - enabled: false, - onSettled: () => { - setLoading(false); - }, - } - ); + const [error, setError] = useState(null); + const [data, setData] = useState(); useEffect(() => { - window.scrollTo(0, 0); setLoading(true); - refetch(); + window.scrollTo(0, 0); + + axios + .get(`${apiUrl}/id/${id}`) + .then(function (response) { + setError(null); + setData(response?.data?.data); + }) + .catch(function (axiosError) { + if (axiosError.response.status === 404) { + setError('CRE does not exist in the DB, please check your search parameters'); + } else { + setError(axiosError.response); + } + }) + .finally(() => { + setLoading(false); + }); }, [id]); - const cre = data?.data; + const cre = data; let filteredCRE; if (cre != undefined) { filteredCRE = applyFilters(JSON.parse(JSON.stringify(cre))); // dirty deepcopy diff --git a/application/frontend/src/pages/Deeplink/Deeplink.tsx b/application/frontend/src/pages/Deeplink/Deeplink.tsx index 1f8a298df..b0d65da7f 100644 --- a/application/frontend/src/pages/Deeplink/Deeplink.tsx +++ b/application/frontend/src/pages/Deeplink/Deeplink.tsx @@ -1,5 +1,5 @@ +import axios from 'axios'; import React, { useEffect, useState } from 'react'; -import { useQuery } from 'react-query'; import { useLocation, useParams } from 'react-router-dom'; import { LoadingAndErrorIndicator } from '../../components/LoadingAndErrorIndicator'; @@ -10,6 +10,8 @@ export const Deeplink = () => { let { type, nodeName, section, subsection, tooltype, sectionID } = useParams(); const { apiUrl } = useEnvironment(); const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [data, setData] = useState(); const search = useLocation().search; section = section ? section : new URLSearchParams(search).get('section'); subsection = subsection ? subsection : new URLSearchParams(search).get('subsection'); @@ -27,25 +29,28 @@ export const Deeplink = () => { (tooltype != null ? `tooltype=${tooltype}&` : '') + (sectionID != null ? `sectionID=${sectionID}&` : ''); - const { error, data, refetch } = useQuery<{ standards: Document[] }, string>( - 'deeplink', - () => fetch(url).then((res) => res.json()), - { - retry: false, - enabled: false, - onSettled: () => { - setLoading(false); - }, - } - ); useEffect(() => { window.scrollTo(0, 0); setLoading(true); - refetch(); + axios + .get(url) + .then(function (response) { + setError(null); + setData(response.data?.standard); + }) + .catch(function (axiosError) { + if (axiosError.response.status === 404) { + setError('Standard does not exist, please check your search parameters'); + } else { + setError(axiosError.response); + } + }) + .finally(() => { + setLoading(false); + }); }, [type, nodeName]); - // const { error, data, } = useQuery<{ standards: Document[]; }, string>('deeplink', () => fetch(url).then((res) => res.json()), {}); - const documents = data?.standards || []; + const documents = data || []; return ( <>
diff --git a/application/frontend/src/pages/Graph/Graph.tsx b/application/frontend/src/pages/Graph/Graph.tsx index 1db5ceff4..7824fbd05 100644 --- a/application/frontend/src/pages/Graph/Graph.tsx +++ b/application/frontend/src/pages/Graph/Graph.tsx @@ -1,3 +1,4 @@ +import axios from 'axios'; import Elk, { ElkEdge, ElkNode, ElkPort, ElkPrimitiveEdge } from 'elkjs'; import React, { useEffect, useState } from 'react'; import ReactFlow, { @@ -14,7 +15,6 @@ import ReactFlow, { isNode, removeElements, } from 'react-flow-renderer'; -import { useQuery } from 'react-query'; import { useParams } from 'react-router-dom'; import { FlowNode } from 'typescript'; @@ -94,22 +94,29 @@ export const Graph = () => { const { id } = useParams(); const { apiUrl } = useEnvironment(); const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + const [data, setData] = useState(); - const { error, data, refetch } = useQuery<{ data: Document }, string>( - 'cre', - () => fetch(`${apiUrl}/id/${id}`).then((res) => res.json()), - { - retry: false, - enabled: false, - onSettled: () => { - setLoading(false); - }, - } - ); useEffect(() => { - window.scrollTo(0, 0); setLoading(true); - refetch(); + window.scrollTo(0, 0); + + axios + .get(`${apiUrl}/id/${id}`) + .then(function (response) { + setError(null); + setData(response?.data?.data); + }) + .catch(function (axiosError) { + if (axiosError.response.status === 404) { + setError('CRE does not exist in the DB, please check your search parameters'); + } else { + setError(axiosError.response); + } + }) + .finally(() => { + setLoading(false); + }); }, [id]); const [layout, setLayout] = useState<(Node | Edge)[]>(); @@ -119,7 +126,7 @@ export const Graph = () => { if (data) { console.log('flow running:', id); - let cre = data.data; + let cre = data; let graph = documentToReactFlowNode(cre); const els = await createGraphLayoutElk(graph.nodes, graph.edges); setLayout(els); diff --git a/application/frontend/src/pages/Search/SearchName.tsx b/application/frontend/src/pages/Search/SearchName.tsx index c3f5ef078..5699888b6 100644 --- a/application/frontend/src/pages/Search/SearchName.tsx +++ b/application/frontend/src/pages/Search/SearchName.tsx @@ -16,7 +16,7 @@ export const SearchName = () => { const { apiUrl } = useEnvironment(); const [loading, setLoading] = useState(false); const [documents, setDocuments] = useState([]); - const [error, setError] = useState(null); + const [error, setError] = useState(null); useEffect(() => { setLoading(true); @@ -27,9 +27,13 @@ export const SearchName = () => { setDocuments(response.data); }) .catch(function (axiosError) { - // TODO: backend errors if no matches, shoudl return + // TODO: backend errors if no matches, should return // proper error instead. - setError(axiosError); + if (axiosError.response.status === 404) { + setError('No results match your search term'); + } else { + setError(axiosError.response); + } }) .finally(() => { setLoading(false); diff --git a/application/frontend/src/pages/Search/components/SearchBar.tsx b/application/frontend/src/pages/Search/components/SearchBar.tsx index 42020f7c0..2989ed3be 100644 --- a/application/frontend/src/pages/Search/components/SearchBar.tsx +++ b/application/frontend/src/pages/Search/components/SearchBar.tsx @@ -45,7 +45,7 @@ export const SearchBar = () => { }); }} label={ - diff --git a/application/frontend/src/pages/Standard/Standard.tsx b/application/frontend/src/pages/Standard/Standard.tsx index 53bb7b316..7ccc1e008 100644 --- a/application/frontend/src/pages/Standard/Standard.tsx +++ b/application/frontend/src/pages/Standard/Standard.tsx @@ -1,14 +1,14 @@ import './standard.scss'; +import axios from 'axios'; import React, { useEffect, useState } from 'react'; -import { useQuery } from 'react-query'; import { useLocation, useParams } from 'react-router-dom'; import { Pagination } from 'semantic-ui-react'; import { DocumentNode } from '../../components/DocumentNode'; import { LoadingAndErrorIndicator } from '../../components/LoadingAndErrorIndicator'; import { useEnvironment } from '../../hooks'; -import { Document } from '../../types'; +import { Document, PaginatedResponse } from '../../types'; import { getDocumentDisplayName } from '../../utils/document'; export const Standard = () => { @@ -16,25 +16,33 @@ export const Standard = () => { const { apiUrl } = useEnvironment(); const [page, setPage] = useState(1); const [loading, setLoading] = useState(false); + const [err, setErr] = useState(null); + const [data, setData] = useState(); + if (!type) { type = 'standard'; } - const { error, data, refetch } = useQuery< - { standards: Document[]; total_pages: number; page: number }, - string - >('standard', () => fetch(`${apiUrl}/${type}/${id}?page=${page}`).then((res) => res.json()), { - retry: false, - enabled: false, - onSettled: () => { - setLoading(false); - }, - }); useEffect(() => { window.scrollTo(0, 0); setLoading(true); - refetch(); - }, [page, id]); + axios + .get(`${apiUrl}/${type}/${id}?page=${page}`) + .then(function (response) { + setErr(null); + setData(response.data); + }) + .catch(function (axiosError) { + if (axiosError.response.status === 404) { + setErr('Standard does not exist, please check your search parameters'); + } else { + setErr(axiosError.response); + } + }) + .finally(() => { + setLoading(false); + }); + }, [id, type, page]); const documents = data?.standards || []; @@ -42,9 +50,9 @@ export const Standard = () => { <>

{id}

- + {!loading && - !error && + !err && documents .sort((a, b) => getDocumentDisplayName(a).localeCompare(getDocumentDisplayName(b))) .map((standard, i) => ( diff --git a/application/frontend/src/pages/Standard/StandardSection.tsx b/application/frontend/src/pages/Standard/StandardSection.tsx index 303766a72..76c839458 100644 --- a/application/frontend/src/pages/Standard/StandardSection.tsx +++ b/application/frontend/src/pages/Standard/StandardSection.tsx @@ -1,7 +1,7 @@ import './standard.scss'; +import axios from 'axios'; import React, { useEffect, useMemo, useState } from 'react'; -import { useQuery } from 'react-query'; import { useParams } from 'react-router-dom'; import { Pagination } from 'semantic-ui-react'; @@ -9,7 +9,7 @@ import { DocumentNode } from '../../components/DocumentNode'; import { LoadingAndErrorIndicator } from '../../components/LoadingAndErrorIndicator'; import { DOCUMENT_TYPES, DOCUMENT_TYPE_NAMES, TOOL } from '../../const'; import { useEnvironment } from '../../hooks'; -import { Document } from '../../types'; +import { Document, PaginatedResponse } from '../../types'; import { getDocumentDisplayName, groupLinksByType } from '../../utils'; import { getDocumentTypeText } from '../../utils/document'; @@ -18,6 +18,8 @@ export const StandardSection = () => { const { apiUrl } = useEnvironment(); const [page, setPage] = useState(1); const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + const [data, setData] = useState(); const getSectionParameter = (): string => { return section ? `§ion=${encodeURIComponent(section)}` : ''; @@ -25,29 +27,27 @@ export const StandardSection = () => { const getSectionIDParameter = (): string => { return sectionID ? `§ionID=${encodeURIComponent(sectionID)}` : ''; }; - const { error, data, refetch } = useQuery< - { standards: Document[]; total_pages: number; page: number }, - string - >( - 'standard section', - () => - fetch(`${apiUrl}/standard/${id}?page=${page}${getSectionParameter()}${getSectionIDParameter()}`).then( - (res) => res.json() - ), - { - retry: false, - enabled: false, - onSettled: () => { - setLoading(false); - }, - } - ); useEffect(() => { window.scrollTo(0, 0); setLoading(true); - refetch(); - }, [page, id]); + axios + .get(`${apiUrl}/standard/${id}?page=${page}${getSectionParameter()}${getSectionIDParameter()}`) + .then(function (response) { + setError(null); + setData(response.data); + }) + .catch(function (axiosError) { + if (axiosError.response.status === 404) { + setError('Standard does not exist in the DB, please check your search parameters'); + } else { + setError(axiosError.response); + } + }) + .finally(() => { + setLoading(false); + }); + }, [id, section, sectionID, page]); const documents = data?.standards || []; const document = documents[0]; diff --git a/application/frontend/src/types.ts b/application/frontend/src/types.ts index c8b7cec72..5622cc405 100644 --- a/application/frontend/src/types.ts +++ b/application/frontend/src/types.ts @@ -19,3 +19,7 @@ export interface LinkedDocument { document: Document; ltype: string; } +export interface PaginatedResponse { + standards: Document[]; + total_pages: number; +} diff --git a/application/web/web_main.py b/application/web/web_main.py index 587f88e43..3ccd1f051 100644 --- a/application/web/web_main.py +++ b/application/web/web_main.py @@ -94,7 +94,7 @@ def find_cre(creid: str = None, crename: str = None) -> Any: # refer result = {"data": json.loads(oscal_utils.document_to_oscal(cre))} return jsonify(result) - abort(404) + abort(404, "CRE does not exist") @app.route("/rest/v1//", methods=["GET"]) @@ -171,7 +171,7 @@ def find_node_by_name(name: str, ntype: str = defs.Credoctypes.Standard.value) - return jsonify(result) else: - abort(404) + abort(404, "Node does not exist") # TODO: (spyros) paginate @@ -197,7 +197,7 @@ def find_document_by_tag() -> Any: return jsonify(result) logger.info("tags aborting 404") - abort(404) + abort(404, "Tag does not exist") @app.route("/rest/v1/gap_analysis", methods=["GET"]) @@ -239,7 +239,7 @@ def text_search() -> Any: res = [doc.todict() for doc in documents] return jsonify(res) else: - abort(404) + abort(404, "No object matches the given search terms") @app.route("/rest/v1/root_cres", methods=["GET"]) @@ -266,11 +266,13 @@ def find_root_cres() -> Any: return jsonify(json.loads(oscal_utils.list_to_oscal(documents))) return jsonify(result) - abort(404) + abort(404, "No root CREs") @app.errorhandler(404) def page_not_found(e) -> Any: + from pprint import pprint + return "Resource Not found", 404 @@ -336,7 +338,7 @@ def smartlink( return redirect(redirectors.redirect(name, section)) else: logger.info(f"not sure what happened, 404") - return abort(404) + return abort(404, "Document does not exist") @app.before_request