From 31f2830a42ae9c6ea5007e5655706f59a53adce4 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Thu, 25 May 2023 16:06:12 -0400 Subject: [PATCH 1/9] chore: rm url from service list --- src/components/ServiceList.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/components/ServiceList.js b/src/components/ServiceList.js index 49856b8a9..6bf01feab 100644 --- a/src/components/ServiceList.js +++ b/src/components/ServiceList.js @@ -80,13 +80,6 @@ const serviceColumns = (isAuthenticated) => [ : null; }, }, - { - title: "URL", - dataIndex: "url", - // url is undefined when service-registry does not receive replies from - // the container. - render: (url) => url ? {`${url}/service-info`} : "N/A", - }, { title: "Status", dataIndex: "status", From 9117b7bc63889c9d58ca17a2b4ca7624d9897a02 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Thu, 25 May 2023 16:06:27 -0400 Subject: [PATCH 2/9] style: no pagination on service table --- src/components/ServiceList.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/ServiceList.js b/src/components/ServiceList.js index 6bf01feab..af66a76fa 100644 --- a/src/components/ServiceList.js +++ b/src/components/ServiceList.js @@ -9,7 +9,6 @@ import { getIsAuthenticated } from "../lib/auth/utils"; import { withBasePath } from "../utils/url"; const SERVICE_KIND_STYLING = { fontFamily: "monospace" }; -const MAX_TABLE_PAGE_SIZE = 15; // noinspection JSUnresolvedFunction const getServiceTags = serviceInfo => [ @@ -126,11 +125,12 @@ const ServiceList = () => { return ( ); From 76acd1299d683c74c59dde80f00fe5a0892d3371 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Fri, 26 May 2023 11:43:23 -0400 Subject: [PATCH 3/9] feat: service request modal for making auth'd queries --- src/components/ServiceList.js | 116 +++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 9 deletions(-) diff --git a/src/components/ServiceList.js b/src/components/ServiceList.js index af66a76fa..535bce148 100644 --- a/src/components/ServiceList.js +++ b/src/components/ServiceList.js @@ -1,12 +1,13 @@ -import React from "react"; +import React, {useCallback, useEffect, useMemo, useState} from "react"; import { useSelector } from "react-redux"; import { Link } from "react-router-dom"; -import { Table, Typography, Tag, Icon} from "antd"; +import {Table, Typography, Tag, Icon, Button, Modal, Form, Input, Divider} from "antd"; -import { getIsAuthenticated } from "../lib/auth/utils"; +import {getIsAuthenticated, makeAuthorizationHeader} from "../lib/auth/utils"; import { withBasePath } from "../utils/url"; +import JsonDisplay from "./JsonDisplay"; const SERVICE_KIND_STYLING = { fontFamily: "monospace" }; @@ -49,7 +50,7 @@ const renderGitInfo = (tag, record, key) => {ta /* eslint-disable react/prop-types */ -const serviceColumns = (isAuthenticated) => [ +const serviceColumns = (isAuthenticated, setRequestModalService) => [ { title: "Kind", dataIndex: "service_kind", @@ -98,10 +99,100 @@ const serviceColumns = (isAuthenticated) => [ ] ), }, + { + title: "Actions", + render: (service) => { + const onClick = () => + setRequestModalService(service.serviceInfo?.bento?.serviceKind ?? service.key ?? null); + return ; + }, + }, ]; /* eslint-enable react/prop-types */ +const ServiceRequestModal = ({service, onCancel}) => { + const bentoServicesByKind = useSelector(state => state.chordServices.itemsByKind); + const serviceUrl = useMemo(() => bentoServicesByKind[service]?.url, [bentoServicesByKind, service]); + + const [requestPath, setRequestPath] = useState("service-info"); + const [requestData, setRequestData] = useState(null); + const [requestIsJSON, setRequestIsJSON] = useState(false); + + const [hasAttempted, setHasAttempted] = useState(false); + + const accessToken = useSelector((state) => state.auth.accessToken); + + const performRequestModalGet = useCallback(() => { + if (!serviceUrl) return; + (async () => { + const res = await fetch(`${serviceUrl}/${requestPath}`, { + headers: makeAuthorizationHeader(accessToken), + }); + + if ((res.headers.get("content-type") ?? "").includes("application/json")) { + const data = await res.json(); + setRequestIsJSON(true); + setRequestData(data); + } else { + const data = await res.text(); + setRequestIsJSON(false); + setRequestData(data); + } + })(); + }, [serviceUrl, requestPath, accessToken]); + + useEffect(() => { + if (!hasAttempted) { + performRequestModalGet(); + setHasAttempted(true); + } + }, [hasAttempted, performRequestModalGet]); + + useEffect(() => { + setRequestData(null); + setRequestIsJSON(false); + setRequestPath("service-info"); + setHasAttempted(false); + }, [service]); + + return +
+ + setRequestPath(e.target.value)} + /> + + + + + + + {requestIsJSON + ? + : ( +
+
+                        {((typeof requestData) === "string" || requestData === null)
+                            ? requestData
+                            : JSON.stringify(requestData)}
+                    
+
+ )} +
; +} + const ServiceList = () => { + const [requestModalService, setRequestModalService] = useState(null); + const dataSource = useSelector((state) => Object.entries(state.chordServices.itemsByKind).map(([kind, service]) => ({ ...service, @@ -115,14 +206,21 @@ const ServiceList = () => { })), ); - const columns = serviceColumns( - useSelector((state) => state.auth.hasAttempted && getIsAuthenticated(state.auth.idTokenContents)), - ); + const isAuthenticated = useSelector( + (state) => state.auth.hasAttempted && getIsAuthenticated(state.auth.idTokenContents)); + + const columns = useMemo( + () => serviceColumns(isAuthenticated, setRequestModalService), + [isAuthenticated]); /** @type boolean */ const isLoading = useSelector((state) => state.chordServices.isFetching || state.services.isFetching); - return ( + return <> + setRequestModalService(null)} />
{ pagination={false} loading={isLoading} /> - ); + ; }; export default ServiceList; From 30dcaa5ff2173c333443fa6c806edb195b51aa2e Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Fri, 26 May 2023 14:45:42 -0400 Subject: [PATCH 4/9] chore: show loading skeleton in service request modal --- src/components/ServiceList.js | 52 +++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/components/ServiceList.js b/src/components/ServiceList.js index 535bce148..001d6e6aa 100644 --- a/src/components/ServiceList.js +++ b/src/components/ServiceList.js @@ -3,7 +3,7 @@ import { useSelector } from "react-redux"; import { Link } from "react-router-dom"; -import {Table, Typography, Tag, Icon, Button, Modal, Form, Input, Divider} from "antd"; +import {Table, Typography, Tag, Icon, Button, Modal, Form, Input, Divider, Skeleton} from "antd"; import {getIsAuthenticated, makeAuthorizationHeader} from "../lib/auth/utils"; import { withBasePath } from "../utils/url"; @@ -115,6 +115,7 @@ const ServiceRequestModal = ({service, onCancel}) => { const serviceUrl = useMemo(() => bentoServicesByKind[service]?.url, [bentoServicesByKind, service]); const [requestPath, setRequestPath] = useState("service-info"); + const [requestLoading, setRequestLoading] = useState(false); const [requestData, setRequestData] = useState(null); const [requestIsJSON, setRequestIsJSON] = useState(false); @@ -123,20 +124,29 @@ const ServiceRequestModal = ({service, onCancel}) => { const accessToken = useSelector((state) => state.auth.accessToken); const performRequestModalGet = useCallback(() => { - if (!serviceUrl) return; + if (!serviceUrl) { + setRequestData(null); + return; + } (async () => { - const res = await fetch(`${serviceUrl}/${requestPath}`, { - headers: makeAuthorizationHeader(accessToken), - }); - - if ((res.headers.get("content-type") ?? "").includes("application/json")) { - const data = await res.json(); - setRequestIsJSON(true); - setRequestData(data); - } else { - const data = await res.text(); - setRequestIsJSON(false); - setRequestData(data); + setRequestLoading(true); + + try { + const res = await fetch(`${serviceUrl}/${requestPath}`, { + headers: makeAuthorizationHeader(accessToken), + }); + + if ((res.headers.get("content-type") ?? "").includes("application/json")) { + const data = await res.json(); + setRequestIsJSON(true); + setRequestData(data); + } else { + const data = await res.text(); + setRequestIsJSON(false); + setRequestData(data); + } + } finally { + setRequestLoading(false); } })(); }, [serviceUrl, requestPath, accessToken]); @@ -176,17 +186,19 @@ const ServiceRequestModal = ({service, onCancel}) => { - {requestIsJSON - ? - : ( -
+ {requestLoading ? : ( + requestIsJSON + ? + : ( +
                         {((typeof requestData) === "string" || requestData === null)
                             ? requestData
                             : JSON.stringify(requestData)}
                     
-
- )} +
+ ) + )} ; } From e18802ffcab7b81f045717d85a750f2ae77ec255 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Thu, 1 Jun 2023 12:10:17 -0400 Subject: [PATCH 5/9] refact: remove duplicate code for JsonDisplay --- src/components/JsonDisplay.js | 36 +++++++++++------------------------ 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/src/components/JsonDisplay.js b/src/components/JsonDisplay.js index 394a79e2c..79f3481b5 100644 --- a/src/components/JsonDisplay.js +++ b/src/components/JsonDisplay.js @@ -85,27 +85,6 @@ JsonArrayDisplay.defaultProps = { standalone: false, }; -const JsonPropertyDisplay = ({ value }) => { - console.debug("JsonPropertyDisplay", value); - - if (Array.isArray(value) && value.length > 100) { - // Display property as an array with custom nav - return ; - } - - if (typeof value === "object") { - // Display property as an object - return ; - } - - // Display primitive - return {JSON.stringify(value)}; -}; - -JsonPropertyDisplay.propTypes = { - value: PropTypes.any, -}; - const JsonObjectDisplay = ({ doc }) => { const entries = Object.entries(doc); return ( @@ -114,7 +93,7 @@ const JsonObjectDisplay = ({ doc }) => { {entries.map(([key, value]) => {key}} key={key}> - + , )} @@ -126,14 +105,21 @@ JsonObjectDisplay.propTypes = { doc: PropTypes.object, }; -const JsonDisplay = ({ jsonSrc }) => { +const JsonDisplay = ({ jsonSrc, showObjectWithReactJson }) => { if (Array.isArray(jsonSrc)) { // Special display for array nav return ; } - // Display for objects and primitives - return ; + if (typeof jsonSrc === "object") { + // Display for objects + return showObjectWithReactJson + ? + : ; + } + + // Display primitive + return {JSON.stringify(jsonSrc)}; }; JsonDisplay.propTypes = { From 7a718422d8742a89fd4e8444bb50f3480d560515 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Thu, 1 Jun 2023 12:10:37 -0400 Subject: [PATCH 6/9] fix: weird behaviour in fetch url box for service list fetch modal --- src/components/ServiceList.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/components/ServiceList.js b/src/components/ServiceList.js index 001d6e6aa..028d90ade 100644 --- a/src/components/ServiceList.js +++ b/src/components/ServiceList.js @@ -151,13 +151,6 @@ const ServiceRequestModal = ({service, onCancel}) => { })(); }, [serviceUrl, requestPath, accessToken]); - useEffect(() => { - if (!hasAttempted) { - performRequestModalGet(); - setHasAttempted(true); - } - }, [hasAttempted, performRequestModalGet]); - useEffect(() => { setRequestData(null); setRequestIsJSON(false); @@ -165,6 +158,13 @@ const ServiceRequestModal = ({service, onCancel}) => { setHasAttempted(false); }, [service]); + useEffect(() => { + if (!hasAttempted) { + performRequestModalGet(); + setHasAttempted(true); + } + }, [hasAttempted, performRequestModalGet]); + return { setRequestPath(e.target.value)} /> @@ -191,11 +192,11 @@ const ServiceRequestModal = ({service, onCancel}) => { ? : (
-
-                        {((typeof requestData) === "string" || requestData === null)
-                            ? requestData
-                            : JSON.stringify(requestData)}
-                    
+
+                            {((typeof requestData) === "string" || requestData === null)
+                                ? requestData
+                                : JSON.stringify(requestData)}
+                        
) )} From 2b02ad6bb6b581329109906c34017b4db29ade63 Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Thu, 1 Jun 2023 12:12:22 -0400 Subject: [PATCH 7/9] lint --- src/components/JsonDisplay.js | 4 ++++ src/components/ServiceList.js | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/JsonDisplay.js b/src/components/JsonDisplay.js index 79f3481b5..62832f735 100644 --- a/src/components/JsonDisplay.js +++ b/src/components/JsonDisplay.js @@ -126,7 +126,11 @@ JsonDisplay.propTypes = { jsonSrc: PropTypes.oneOfType([ PropTypes.object, PropTypes.array, + PropTypes.string, + PropTypes.bool, + PropTypes.number, ]), + showObjectWithReactJson: PropTypes.bool, }; export default JsonDisplay; diff --git a/src/components/ServiceList.js b/src/components/ServiceList.js index 028d90ade..81b156b5d 100644 --- a/src/components/ServiceList.js +++ b/src/components/ServiceList.js @@ -1,5 +1,6 @@ import React, {useCallback, useEffect, useMemo, useState} from "react"; import { useSelector } from "react-redux"; +import PropTypes from "prop-types"; import { Link } from "react-router-dom"; @@ -201,7 +202,11 @@ const ServiceRequestModal = ({service, onCancel}) => { ) )}
; -} +}; +ServiceRequestModal.propTypes = { + service: PropTypes.string, + onCancel: PropTypes.func, +}; const ServiceList = () => { const [requestModalService, setRequestModalService] = useState(null); From 3aa401d2af3d17296f898a6cda67d3c9035d1a4e Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Thu, 1 Jun 2023 12:14:59 -0400 Subject: [PATCH 8/9] fix: show nested displayed objects with react-json --- src/components/JsonDisplay.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/JsonDisplay.js b/src/components/JsonDisplay.js index 62832f735..de5c962de 100644 --- a/src/components/JsonDisplay.js +++ b/src/components/JsonDisplay.js @@ -93,7 +93,7 @@ const JsonObjectDisplay = ({ doc }) => { {entries.map(([key, value]) => {key}} key={key}> - + , )} From 12ccae904d30285ee93bfe5249b479068109353c Mon Sep 17 00:00:00 2001 From: David Lougheed Date: Thu, 1 Jun 2023 16:08:25 -0400 Subject: [PATCH 9/9] lint: reformat service list render --- src/components/ServiceList.js | 76 ++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/src/components/ServiceList.js b/src/components/ServiceList.js index 81b156b5d..1c122dfb4 100644 --- a/src/components/ServiceList.js +++ b/src/components/ServiceList.js @@ -166,42 +166,46 @@ const ServiceRequestModal = ({service, onCancel}) => { } }, [hasAttempted, performRequestModalGet]); - return -
- - setRequestPath(e.target.value)} - /> - - - - - - - {requestLoading ? : ( - requestIsJSON - ? - : ( -
-
-                            {((typeof requestData) === "string" || requestData === null)
-                                ? requestData
-                                : JSON.stringify(requestData)}
-                        
-
- ) - )} -
; + return ( + +
+ + setRequestPath(e.target.value)} + /> + + + + + + + {requestLoading ? : ( + requestIsJSON + ? + : ( +
+
+                                {((typeof requestData) === "string" || requestData === null)
+                                    ? requestData
+                                    : JSON.stringify(requestData)}
+                            
+
+ ) + )} +
+ ); }; ServiceRequestModal.propTypes = { service: PropTypes.string,